Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow override of metrics URL in client for security #41

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ There is no authentication or authorisation included, a reverse proxy can be
put in front though to add these.

Running the client allows those with access to the proxy or the client to access
all network services on the machine hosting the client.
all network services on the machine hosting the client, unless you specify the
`--override-url` setting.
```
./client --proxy-url=http://proxy:8080/ --override-url=http://client:9100/metrics
```
11 changes: 11 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
tlsCert = kingpin.Flag("tls.cert", "<cert> Client certificate file").String()
tlsKey = kingpin.Flag("tls.key", "<key> Private key file").String()
metricsAddr = kingpin.Flag("metrics-addr", "Serve Prometheus metrics at this address").Default(":9369").String()
overrideURL = kingpin.Flag("override-url", "<URL> Force the URL to scrape").String()
)

var (
Expand Down Expand Up @@ -74,6 +75,16 @@ func (c *Coordinator) doScrape(request *http.Request, client *http.Client) {
// We cannot handle https requests at the proxy, as we would only
// see a CONNECT, so use a URL parameter to trigger it.
params := request.URL.Query()

// Force GET verb
request.Method = "GET"

// Override
if err := util.OverrideURLIfDesired(overrideURL, request); err != nil {
level.Error(logger).Log("msg", "Failed to parse overrideURL:", "err", err)
return
}

if params.Get("_scheme") == "https" {
request.URL.Scheme = "https"
params.Del("_scheme")
Expand Down
18 changes: 18 additions & 0 deletions util/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package util

import (
"net/http"
"net/url"
)

func OverrideURLIfDesired(overrideURL *string, request *http.Request) error {
if *overrideURL != "" {
parsedURL, err := url.Parse(*overrideURL)
if err != nil {
return err
}
request.URL = parsedURL
}

return nil
}
32 changes: 32 additions & 0 deletions util/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package util

import (
"net/http"
"net/url"
"testing"
)

func TestOverrideURLIfDesired(t *testing.T) {
// With override
request := &http.Request{URL: &url.URL{Scheme: "http", Host: "wrong-service:9090", Path: "/v1/user/1"}}
overrideURL := "http://localhost:8080/metrics"
err := OverrideURLIfDesired(&overrideURL, request)
if err != nil {
t.Errorf("Expected no error, got one: %v", err)
}
if request.URL.String() != overrideURL {
t.Errorf("Expected %s, got %s", overrideURL, request.URL.String())
}

// Without override
request = &http.Request{URL: &url.URL{Scheme: "http", Host: "localhost:9090", Path: "/metrics"}}
overrideURL = ""
err = OverrideURLIfDesired(&overrideURL, request)
if err != nil {
t.Errorf("Expected no error, got one: %v", err)
}
nonOverride := "http://localhost:9090/metrics"
if request.URL.String() != nonOverride {
t.Errorf("Expected %s, got %s", nonOverride, request.URL.String())
}
}