Skip to content

Commit e1160c2

Browse files
dupondjeglinton
authored andcommitted
Add ip restriction for the prometheus_client output (#4431)
1 parent 199841a commit e1160c2

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

etc/telegraf.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@
747747
# #basic_username = "Foo"
748748
# #basic_password = "Bar"
749749
#
750+
# ## IP Ranges which are allowed to access metrics
751+
# #ip_range = ["192.168.0.0/24", "192.168.1.0/30"]
752+
#
750753
# ## Interval to expire metrics and not deliver to prometheus, 0 == no expiration
751754
# # expiration_interval = "60s"
752755
#

plugins/outputs/prometheus_client/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ This plugin starts a [Prometheus](https://prometheus.io/) Client, it exposes all
1818
basic_username = "Foo"
1919
basic_password = "Bar"
2020
21+
# IP Ranges which are allowed to access metrics
22+
ip_range = ["192.168.0.0/24", "192.168.1.0/30"]
23+
2124
# Path to publish the metrics on, defaults to /metrics
2225
path = "/metrics"
2326

plugins/outputs/prometheus_client/prometheus_client.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"crypto/subtle"
66
"fmt"
77
"log"
8+
"net"
89
"net/http"
910
"os"
1011
"regexp"
@@ -58,6 +59,7 @@ type PrometheusClient struct {
5859
TLSKey string `toml:"tls_key"`
5960
BasicUsername string `toml:"basic_username"`
6061
BasicPassword string `toml:"basic_password"`
62+
IPRange []string `toml:"ip_range"`
6163
ExpirationInterval internal.Duration `toml:"expiration_interval"`
6264
Path string `toml:"path"`
6365
CollectorsExclude []string `toml:"collectors_exclude"`
@@ -84,6 +86,9 @@ var sampleConfig = `
8486
#basic_username = "Foo"
8587
#basic_password = "Bar"
8688
89+
## IP Ranges which are allowed to access metrics
90+
#ip_range = ["192.168.0.0/24", "192.168.1.0/30"]
91+
8792
## Interval to expire metrics and not deliver to prometheus, 0 == no expiration
8893
# expiration_interval = "60s"
8994
@@ -96,7 +101,7 @@ var sampleConfig = `
96101
string_as_label = true
97102
`
98103

99-
func (p *PrometheusClient) basicAuth(h http.Handler) http.Handler {
104+
func (p *PrometheusClient) auth(h http.Handler) http.Handler {
100105
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
101106
if p.BasicUsername != "" && p.BasicPassword != "" {
102107
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
@@ -110,6 +115,27 @@ func (p *PrometheusClient) basicAuth(h http.Handler) http.Handler {
110115
}
111116
}
112117

118+
if len(p.IPRange) > 0 {
119+
matched := false
120+
remoteIPs, _, _ := net.SplitHostPort(r.RemoteAddr)
121+
remoteIP := net.ParseIP(remoteIPs)
122+
for _, iprange := range p.IPRange {
123+
_, ipNet, err := net.ParseCIDR(iprange)
124+
if err != nil {
125+
http.Error(w, "Config Error in ip_range setting", 500)
126+
return
127+
}
128+
if ipNet.Contains(remoteIP) {
129+
matched = true
130+
break
131+
}
132+
}
133+
if !matched {
134+
http.Error(w, "Not authorized", 401)
135+
return
136+
}
137+
}
138+
113139
h.ServeHTTP(w, r)
114140
})
115141
}
@@ -146,7 +172,7 @@ func (p *PrometheusClient) Start() error {
146172
}
147173

148174
mux := http.NewServeMux()
149-
mux.Handle(p.Path, p.basicAuth(promhttp.HandlerFor(
175+
mux.Handle(p.Path, p.auth(promhttp.HandlerFor(
150176
registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError})))
151177

152178
p.server = &http.Server{

0 commit comments

Comments
 (0)