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

Add support for authenticating by bearer or JWT token to mimirtool #2146

Merged
merged 8 commits into from Jun 21, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -79,6 +79,7 @@

### Mimirtool

* [FEATURE] Added bearer token support for when Mimir is behind a gateway authenticating by bearer token. #2146
* [BUGFIX] mimirtool analyze: Fix dashboard JSON unmarshalling errors (#1840). #1973

### Mimir Continuous Test
Expand Down
1 change: 1 addition & 0 deletions operations/mimir-rules-action/README.md
Expand Up @@ -11,6 +11,7 @@ This action is configured using environment variables defined in the workflow. T
| `MIMIR_ADDRESS` | URL address for the target Mimir cluster | `false` | N/A |
| `MIMIR_TENANT_ID` | ID for the desired tenant in the target Mimir cluster. Used as the username under HTTP Basic authentication. | `false` | N/A |
| `MIMIR_API_KEY` | Optional password that is required for password-protected Mimir clusters. An encrypted [github secret](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) is recommended. Used as the password under HTTP Basic authentication. | `false` | N/A |
| `MIMIR_AUTH_TOKEN` | Optional bearer or JWT token that is required for Mimir clusters authenticating by bearer or JWT token. An encrypted [github secret](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) is recommended. | `false` | N/A |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `MIMIR_AUTH_TOKEN` | Optional bearer or JWT token that is required for Mimir clusters authenticating by bearer or JWT token. An encrypted [github secret](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) is recommended. | `false` | N/A |
| `MIMIR_AUTH_TOKEN` | Optional bearer or JWT token that is required for Mimir clusters authenticating by bearer or JWT token. | `false` | N/A |

I would remove mention of "An encrypted github secret is recommended." because mimirtool user cannot control what the Mimir installation (or gateway in front of it) is using.

But I see this is copied from MIMIR_API_KEY description, so we can address both later.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why the GitHub secret is mentioned here is different. This is the mimir-rules-action and it's suggesting to use a GitHub secret to hold this env variable value.

| `ACTION` | Which action to take. One of `lint`, `prepare`, `check`, `diff` or `sync` | `true` | N/A |
| `RULES_DIR` | Comma-separated list of directories to walk in order to source rules files | `false` | `./` |
| `LABEL_EXCLUDED_RULE_GROUPS` | Comma separated list of rule group names to exclude when including the configured label to aggregations. This option is supported only by the `prepare` action. | `false` | N/A |
Expand Down
47 changes: 32 additions & 15 deletions pkg/mimirtool/client/client.go
Expand Up @@ -38,17 +38,19 @@ type Config struct {
Address string `yaml:"address"`
ID string `yaml:"id"`
TLS tls.ClientConfig
UseLegacyRoutes bool `yaml:"use_legacy_routes"`
UseLegacyRoutes bool `yaml:"use_legacy_routes"`
AuthToken string `yaml:"auth_token"`
}

// MimirClient is used to get and load rules into a Mimir ruler.
type MimirClient struct {
user string
key string
id string
endpoint *url.URL
Client http.Client
apiPath string
user string
key string
id string
endpoint *url.URL
Client http.Client
apiPath string
authToken string
}

// New returns a new MimirClient.
Expand Down Expand Up @@ -90,12 +92,13 @@ func New(cfg Config) (*MimirClient, error) {
}

return &MimirClient{
user: cfg.User,
key: cfg.Key,
id: cfg.ID,
endpoint: endpoint,
Client: client,
apiPath: path,
user: cfg.User,
key: cfg.Key,
id: cfg.ID,
endpoint: endpoint,
Client: client,
apiPath: path,
authToken: cfg.AuthToken,
}, nil
}

Expand All @@ -119,10 +122,24 @@ func (r *MimirClient) doRequest(path, method string, payload []byte) (*http.Resp
return nil, err
}

if r.user != "" {
switch {
case (r.user != "" || r.key != "") && r.authToken != "":
err := errors.New("at most one of basic auth or auth token should be configured")
log.WithFields(log.Fields{
"url": req.URL.String(),
"method": req.Method,
"error": err,
}).Errorln("error during setting up request to mimir api")
return nil, err

case r.user != "":
req.SetBasicAuth(r.user, r.key)
} else if r.key != "" {

case r.key != "":
req.SetBasicAuth(r.id, r.key)

case r.authToken != "":
req.Header.Add("Authorization", "Bearer "+r.authToken)
}

req.Header.Add("X-Scope-OrgID", r.id)
Expand Down
3 changes: 2 additions & 1 deletion pkg/mimirtool/commands/alerts.go
Expand Up @@ -72,7 +72,7 @@ func (a *AlertmanagerCommand) Register(app *kingpin.Application, envVars EnvVarN
alertCmd.Flag("tls-ca-path", "TLS CA certificate to verify Grafana Mimir API as part of mTLS; alternatively, set "+envVars.TLSCAPath+".").Default("").Envar(envVars.TLSCAPath).StringVar(&a.ClientConfig.TLS.CAPath)
alertCmd.Flag("tls-cert-path", "TLS client certificate to authenticate with the Grafana Mimir API as part of mTLS; alternatively, set "+envVars.TLSCertPath+".").Default("").Envar(envVars.TLSCertPath).StringVar(&a.ClientConfig.TLS.CertPath)
alertCmd.Flag("tls-key-path", "TLS client certificate private key to authenticate with the Grafana Mimir API as part of mTLS; alternatively, set "+envVars.TLSKeyPath+".").Default("").Envar(envVars.TLSKeyPath).StringVar(&a.ClientConfig.TLS.KeyPath)

alertCmd.Flag("auth-token", "Authentication token bearer authentication; alternatively, set "+envVars.AuthToken+".").Default("").Envar(envVars.AuthToken).StringVar(&a.ClientConfig.AuthToken)
// Get Alertmanager Configs Command
getAlertsCmd := alertCmd.Command("get", "Get the Alertmanager configuration that is currently in the Grafana Mimir Alertmanager.").Action(a.getConfig)
getAlertsCmd.Flag("disable-color", "disable colored output").BoolVar(&a.DisableColor)
Expand Down Expand Up @@ -147,6 +147,7 @@ func (a *AlertCommand) Register(app *kingpin.Application, envVars EnvVarNames) {
alertCmd.Flag("id", "Mimir tenant id, alternatively set "+envVars.TenantID+".").Envar(envVars.TenantID).Required().StringVar(&a.ClientConfig.ID)
alertCmd.Flag("user", fmt.Sprintf("API user to use when contacting Grafana Mimir, alternatively set %s. If empty, %s will be used instead.", envVars.APIUser, envVars.TenantID)).Default("").Envar(envVars.APIUser).StringVar(&a.ClientConfig.User)
alertCmd.Flag("key", "API key to use when contacting Grafana Mimir; alternatively, set "+envVars.APIKey+".").Default("").Envar(envVars.APIKey).StringVar(&a.ClientConfig.Key)
alertCmd.Flag("auth-token", "Authentication token for bearer token or JWT auth, alternatively set "+envVars.AuthToken+".").Default("").Envar(envVars.AuthToken).StringVar(&a.ClientConfig.AuthToken)

verifyAlertsCmd := alertCmd.Command("verify", "Verifies whether or not alerts in an Alertmanager cluster are deduplicated; useful for verifying correct configuration when transferring from Prometheus to Grafana Mimir alert evaluation.").Action(a.verifyConfig)
verifyAlertsCmd.Flag("ignore-alerts", "A comma separated list of Alert names to ignore in deduplication checks.").StringVar(&a.IgnoreString)
Expand Down
3 changes: 3 additions & 0 deletions pkg/mimirtool/commands/env_var.go
Expand Up @@ -11,6 +11,7 @@ type EnvVarNames struct {
TLSKeyPath string
TenantID string
UseLegacyRoutes string
AuthToken string
}

func NewEnvVarsWithPrefix(prefix string) EnvVarNames {
Expand All @@ -23,6 +24,7 @@ func NewEnvVarsWithPrefix(prefix string) EnvVarNames {
tlsCertPath = "TLS_CERT_PATH"
tlsKeyPath = "TLS_KEY_PATH"
useLegacyRoutes = "USE_LEGACY_ROUTES"
authToken = "AUTH_TOKEN"
)

if len(prefix) > 0 && prefix[len(prefix)-1] != '_' {
Expand All @@ -38,5 +40,6 @@ func NewEnvVarsWithPrefix(prefix string) EnvVarNames {
TLSKeyPath: prefix + tlsKeyPath,
TenantID: prefix + tenantID,
UseLegacyRoutes: prefix + useLegacyRoutes,
AuthToken: prefix + authToken,
}
}
1 change: 1 addition & 0 deletions pkg/mimirtool/commands/rules.go
Expand Up @@ -97,6 +97,7 @@ func (r *RuleCommand) Register(app *kingpin.Application, envVars EnvVarNames) {
rulesCmd.Flag("user", fmt.Sprintf("API user to use when contacting Grafana Mimir; alternatively, set %s. If empty, %s is used instead.", envVars.APIUser, envVars.TenantID)).Default("").Envar(envVars.APIUser).StringVar(&r.ClientConfig.User)
rulesCmd.Flag("key", "API key to use when contacting Grafana Mimir; alternatively, set "+envVars.APIKey+".").Default("").Envar(envVars.APIKey).StringVar(&r.ClientConfig.Key)
rulesCmd.Flag("backend", "Backend type to interact with (deprecated)").Default(rules.MimirBackend).EnumVar(&r.Backend, backends...)
rulesCmd.Flag("auth-token", "Authentication token for bearer token or JWT auth, alternatively set "+envVars.AuthToken+".").Default("").Envar(envVars.AuthToken).StringVar(&r.ClientConfig.AuthToken)

// Register rule commands
listCmd := rulesCmd.
Expand Down