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

logcli: add support for bearer token authentication #3749

Merged
merged 1 commit into from
Jun 9, 2021
Merged
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
2 changes: 2 additions & 0 deletions cmd/logcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ func newQueryClient(app *kingpin.Application) client.Client {
app.Flag("cert", "Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var.").Default("").Envar("LOKI_CLIENT_CERT_PATH").StringVar(&client.TLSConfig.CertFile)
app.Flag("key", "Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var.").Default("").Envar("LOKI_CLIENT_KEY_PATH").StringVar(&client.TLSConfig.KeyFile)
app.Flag("org-id", "adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway.").Default("").Envar("LOKI_ORG_ID").StringVar(&client.OrgID)
app.Flag("bearer-token", "adds the Authorization header to API requests for authentication purposes. Can also be set using LOKI_BEARER_TOKEN env var.").Default("").Envar("LOKI_BEARER_TOKEN").StringVar(&client.BearerToken)
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)

return client
}
Expand Down
2 changes: 1 addition & 1 deletion docs/sources/getting-started/logcli.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ $ export LOKI_ADDR=http://localhost:3100

> Note: If you are running Loki behind a proxy server and you have
> authentication configured, you will also have to pass in LOKI_USERNAME
> and LOKI_PASSWORD accordingly.
> and LOKI_PASSWORD, LOKI_BEARER_TOKEN or LOKI_BEARER_TOKEN_FILE accordingly.

```bash
$ logcli labels job
Expand Down
56 changes: 50 additions & 6 deletions pkg/logcli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ type Tripperware func(http.RoundTripper) http.RoundTripper

// Client contains fields necessary to query a Loki instance
type DefaultClient struct {
TLSConfig config.TLSConfig
Username string
Password string
Address string
OrgID string
Tripperware Tripperware
TLSConfig config.TLSConfig
Username string
Password string
Address string
OrgID string
Tripperware Tripperware
BearerToken string
BearerTokenFile string
}

// Query uses the /api/v1/query endpoint to execute an instant query
Expand Down Expand Up @@ -181,6 +183,27 @@ func (c *DefaultClient) doRequest(path, query string, quiet bool, out interface{
req.Header.Set("X-Scope-OrgID", c.OrgID)
}

if (c.Username != "" || c.Password != "") && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
return fmt.Errorf("at most one of HTTP basic auth (username/password), bearer-token & bearer-token-file is allowed to be configured")
}

if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
return fmt.Errorf("at most one of the options bearer-token & bearer-token-file is allowed to be configured")
}

if c.BearerToken != "" {
req.Header.Set("Authorization", "Bearer "+c.BearerToken)
}

if c.BearerTokenFile != "" {
b, err := ioutil.ReadFile(c.BearerTokenFile)
if err != nil {
return fmt.Errorf("unable to read authorization credentials file %s: %s", c.BearerTokenFile, err)
}
bearerToken := strings.TrimSpace(string(b))
req.Header.Set("Authorization", "Bearer "+bearerToken)
}

// Parse the URL to extract the host
clientConfig := config.HTTPClientConfig{
TLSConfig: c.TLSConfig,
Expand Down Expand Up @@ -237,6 +260,27 @@ func (c *DefaultClient) wsConnect(path, query string, quiet bool) (*websocket.Co
h.Set("X-Scope-OrgID", c.OrgID)
}

if (c.Username != "" || c.Password != "") && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
dbluxo marked this conversation as resolved.
Show resolved Hide resolved
return nil, fmt.Errorf("at most one of HTTP basic auth (username/password), bearer-token & bearer-token-file is allowed to be configured")
}

if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
return nil, fmt.Errorf("at most one of the options bearer-token & bearer-token-file is allowed to be configured")
}

if c.BearerToken != "" {
h.Set("Authorization", "Bearer "+c.BearerToken)
}

if c.BearerTokenFile != "" {
b, err := ioutil.ReadFile(c.BearerTokenFile)
if err != nil {
return nil, fmt.Errorf("unable to read authorization credentials file %s: %s", c.BearerTokenFile, err)
}
bearerToken := strings.TrimSpace(string(b))
h.Set("Authorization", "Bearer "+bearerToken)
}

ws := websocket.Dialer{
TLSClientConfig: tlsConfig,
}
Expand Down