Skip to content

Commit

Permalink
logcli: add --proxy-url flag for http/https proxy support (#6484)
Browse files Browse the repository at this point in the history
Add `--proxy-url` flag to `logcli` to support connecting to Loki
instances running behind either HTTP or HTTPS CONNECT-style proxies.

Examples:

http proxy:

```
logcli \
  --addr="http://loki-distributed-querier.loki.svc.cluster.local.:3100/" \
  --proxy-url "http://envoy.dom.tld" \
  query '{app"foo"}'
```

https proxy with mTLS auth:
```
logcli \
  --addr="https://loki-distributed-querier.loki.svc.cluster.local.:3100/" \
  --proxy-url "https://envoy.dom.tld" \
  --cert tls.crt \
  --key tls.key \
  --ca-cert ca.crt \
  query '{app"foo"}'
```

Note that tail (`-f`) support and https proxies only works with a fork of the
`gorilla/websocket` lib. There are open PRs that promise to add support
for https proxies such as: gorilla/websocket#740

Add the following to `go.mod` to use the fork with https support:

```
replace github.com/gorilla/websocket v1.4.2 => github.com/philipatl/websocket v1.4.3-0.20211206152948-d16969baa130
```
  • Loading branch information
joemiller committed Jun 24, 2022
1 parent b8c9672 commit 6d11a15
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
8 changes: 8 additions & 0 deletions cmd/logcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ func newQueryClient(app *kingpin.Application) client.Client {

// extract host
addressAction := func(c *kingpin.ParseContext) error {
// If a proxy is to be used do not set TLS ServerName. In the case of HTTPS proxy this ensures
// the http client validates both the proxy's cert and the cert used by loki behind the proxy
// using the ServerName's from the provided --addr and --proxy-url flags.
if client.ProxyURL != "" {
return nil
}

u, err := url.Parse(client.Address)
if err != nil {
return err
Expand All @@ -245,6 +252,7 @@ func newQueryClient(app *kingpin.Application) client.Client {
app.Flag("bearer-token-file", "adds the Authorization header to API requests for authentication purposes. Can also be set using LOKI_BEARER_TOKEN_FILE env var.").Default("").Envar("LOKI_BEARER_TOKEN_FILE").StringVar(&client.BearerTokenFile)
app.Flag("retries", "How many times to retry each query when getting an error response from Loki. Can also be set using LOKI_CLIENT_RETRIES").Default("0").Envar("LOKI_CLIENT_RETRIES").IntVar(&client.Retries)
app.Flag("auth-header", "The authorization header used. Can also be set using LOKI_AUTH_HEADER").Default("Authorization").Envar("LOKI_AUTH_HEADER").StringVar(&client.AuthHeader)
app.Flag("proxy-url", "The http or https proxy to use when making requests. Can also be set using LOKI_HTTP_PROXY_URL env var.").Default("").Envar("LOKI_HTTP_PROXY_URL").StringVar(&client.ProxyURL)

return client
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/logcli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type DefaultClient struct {
Retries int
QueryTags string
AuthHeader string
ProxyURL string
}

// Query uses the /api/v1/query endpoint to execute an instant query
Expand Down Expand Up @@ -191,6 +192,14 @@ func (c *DefaultClient) doRequest(path, query string, quiet bool, out interface{
TLSConfig: c.TLSConfig,
}

if c.ProxyURL != "" {
prox, err := url.Parse(c.ProxyURL)
if err != nil {
return err
}
clientConfig.ProxyURL = config.URL{URL: prox}
}

client, err := config.NewClientFromConfig(clientConfig, "promtail", config.WithHTTP2Disabled())
if err != nil {
return err
Expand Down Expand Up @@ -315,6 +324,12 @@ func (c *DefaultClient) wsConnect(path, query string, quiet bool) (*websocket.Co
TLSClientConfig: tlsConfig,
}

if c.ProxyURL != "" {
ws.Proxy = func(req *http.Request) (*url.URL, error) {
return url.Parse(c.ProxyURL)
}
}

conn, resp, err := ws.Dial(us, h)
if err != nil {
if resp == nil {
Expand Down

0 comments on commit 6d11a15

Please sign in to comment.