diff --git a/.changelog/20518.txt b/.changelog/20518.txt new file mode 100644 index 000000000..3bf6deff3 --- /dev/null +++ b/.changelog/20518.txt @@ -0,0 +1,3 @@ +```release-note:improvement +cli: Add `-jwks-ca-file` argument to `setup consul/vault` commands +``` diff --git a/command/setup_consul.go b/command/setup_consul.go index 28876f3a8..7b162e6b7 100644 --- a/command/setup_consul.go +++ b/command/setup_consul.go @@ -42,7 +42,8 @@ type SetupConsulCommand struct { client *api.Client clientCfg *api.Config - jwksURL string + jwksURL string + jwksCACertPath string consulEnt bool destroy bool @@ -71,6 +72,10 @@ Setup Consul options: URL of Nomad's JWKS endpoint contacted by Consul to verify JWT signatures. Defaults to http://localhost:4646/.well-known/jwks.json. + -jwks-ca-file + Path to a CA certificate file that will be used to validate the + JWKS URL if it uses TLS + -destroy Removes all configuration components this command created from the Consul cluster. @@ -86,9 +91,10 @@ Setup Consul options: func (s *SetupConsulCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ - "-jwks-url": complete.PredictAnything, - "-destroy": complete.PredictSet("true", "false"), - "-y": complete.PredictSet("true", "false"), + "-jwks-url": complete.PredictAnything, + "-jwks-ca-file": complete.PredictAnything, + "-destroy": complete.PredictSet("true", "false"), + "-y": complete.PredictSet("true", "false"), }) } @@ -110,6 +116,7 @@ func (s *SetupConsulCommand) Run(args []string) int { flags.BoolVar(&s.destroy, "destroy", false, "") flags.BoolVar(&s.autoYes, "y", false, "") flags.StringVar(&s.jwksURL, "jwks-url", "http://localhost:4646/.well-known/jwks.json", "") + flags.StringVar(&s.jwksCACertPath, "jwks-ca-file", "", "") if err := flags.Parse(args); err != nil { return 1 } @@ -430,6 +437,14 @@ func (s *SetupConsulCommand) renderAuthMethod(name string, desc string) (*api.AC authConfig["BoundAudiences"] = []string{consulAud} authConfig["JWTSupportedAlgs"] = []string{"RS256"} + if s.jwksCACertPath != "" { + caCert, err := os.ReadFile(s.jwksCACertPath) + if err != nil { + return nil, fmt.Errorf("could not read -jwks-certfile: %v", err) + } + authConfig["JWKSCACert"] = string(caCert) + } + method := &api.ACLAuthMethod{ Name: name, Type: "jwt", diff --git a/command/setup_vault.go b/command/setup_vault.go index a0557063b..ffa5e21c3 100644 --- a/command/setup_vault.go +++ b/command/setup_vault.go @@ -45,7 +45,8 @@ type SetupVaultCommand struct { vLogical *api.Logical ns string - jwksURL string + jwksURL string + jwksCACertPath string destroy bool autoYes bool @@ -82,6 +83,10 @@ Setup Vault options: URL of Nomad's JWKS endpoint contacted by Vault to verify JWT signatures. Defaults to http://localhost:4646/.well-known/jwks.json. + -jwks-ca-file + Path to a CA certificate file that will be used to validate the + JWKS URL if it uses TLS + -destroy Removes all configuration components this command created from the Vault cluster. @@ -112,9 +117,10 @@ Setup Vault options when using -check: func (s *SetupVaultCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ - "-jwks-url": complete.PredictAnything, - "-destroy": complete.PredictSet("true", "false"), - "-y": complete.PredictSet("true", "false"), + "-jwks-url": complete.PredictAnything, + "-jwks-ca-file": complete.PredictAnything, + "-destroy": complete.PredictSet("true", "false"), + "-y": complete.PredictSet("true", "false"), // Options for -check. "-check": complete.PredictSet("true", "false"), @@ -142,6 +148,7 @@ func (s *SetupVaultCommand) Run(args []string) int { flags.BoolVar(&s.destroy, "destroy", false, "") flags.BoolVar(&s.autoYes, "y", false, "") flags.StringVar(&s.jwksURL, "jwks-url", "http://localhost:4646/.well-known/jwks.json", "") + flags.StringVar(&s.jwksCACertPath, "jwks-ca-file", "", "") // Options for -check. flags.BoolVar(&s.check, "check", false, "") @@ -485,6 +492,14 @@ func (s *SetupVaultCommand) renderAuthMethod() (map[string]any, error) { authConfig["jwks_url"] = s.jwksURL authConfig["default_role"] = vaultRole + if s.jwksCACertPath != "" { + caCert, err := os.ReadFile(s.jwksCACertPath) + if err != nil { + return nil, fmt.Errorf("could not read -jwks-certfile: %v", err) + } + authConfig["jwks_ca_pem"] = string(caCert) + } + return authConfig, nil } diff --git a/website/content/docs/commands/setup/consul.mdx b/website/content/docs/commands/setup/consul.mdx index 49109f111..1fdd82839 100644 --- a/website/content/docs/commands/setup/consul.mdx +++ b/website/content/docs/commands/setup/consul.mdx @@ -32,6 +32,9 @@ nomad setup consul [options] - `-jwks-url`: URL of Nomad's JWKS endpoint contacted by Consul to verify JWT signatures. Defaults to `http://localhost:4646/.well-known/jwks.json`. +- `-jwks-ca-file`: Path to a CA certificate file that will be used to validate + the JWKS URL if it uses TLS. + - `-destroy`: Removes all configuration components this command created from the Consul cluster. diff --git a/website/content/docs/commands/setup/vault.mdx b/website/content/docs/commands/setup/vault.mdx index a016ea036..835a85dd4 100644 --- a/website/content/docs/commands/setup/vault.mdx +++ b/website/content/docs/commands/setup/vault.mdx @@ -39,6 +39,9 @@ nomad setup vault [options] - `-jwks-url`: URL of Nomad's JWKS endpoint contacted by Consul to verify JWT signatures. Defaults to `http://localhost:4646/.well-known/jwks.json`. +- `-jwks-ca-file`: Path to a CA certificate file that will be used to validate + the JWKS URL if it uses TLS. + - `-destroy`: Removes all configuration components this command created from the Consul cluster.