Skip to content

Commit

Permalink
Merge pull request #448 from jorgemarey/f-auth-jwt
Browse files Browse the repository at this point in the history
Add JWT options for acl_auth_method
  • Loading branch information
lgfa29 committed Apr 8, 2024
2 parents d4a0b03 + 6d1896e commit 16a99fb
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 2.2.1 (Unreleased)

IMPROVEMENTS:
* resource/acl_auth_method: add support for configuring a JWT auth-method ([#448](https://github.com/hashicorp/terraform-provider-nomad/pull/448))

## 2.2.0 (March 12, 2024)

IMPROVEMENTS:
Expand Down
129 changes: 112 additions & 17 deletions nomad/resource_acl_auth_method.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func resourceACLAuthMethod() *schema.Resource {
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
api.ACLAuthMethodTypeOIDC,
api.ACLAuthMethodTypeJWT,
}, false),
},
"token_locality": {
Expand Down Expand Up @@ -80,20 +81,38 @@ func resourceACLAuthMethod() *schema.Resource {
func resourceACLAuthMethodConfig() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"oidc_discovery_url": {
Description: "The OIDC Discovery URL, without any .well-known component (base path).",
"jwt_validation_pub_keys": {
Description: "List of PEM-encoded public keys to use to authenticate signatures locally.",
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
ExactlyOneOf: []string{"config.0.jwks_url", "config.0.oidc_discovery_url"},
},
"jwks_url": {
Description: "JSON Web Key Sets url for authenticating signatures.",
Type: schema.TypeString,
Required: true,
Optional: true,
},
"jwks_ca_cert": {
Description: "PEM encoded CA cert for use by the TLS client used to talk with the JWKS server.",
Type: schema.TypeString,
Optional: true,
},
"oidc_discovery_url": {
Description: "The OIDC Discovery URL, without any .well-known component (base path).",
Type: schema.TypeString,
Optional: true,
RequiredWith: []string{"config.0.oidc_client_id", "config.0.oidc_client_secret"},
},
"oidc_client_id": {
Description: "The OAuth Client ID configured with the OIDC provider.",
Type: schema.TypeString,
Required: true,
Optional: true,
},
"oidc_client_secret": {
Description: "The OAuth Client Secret configured with the OIDC provider.",
Type: schema.TypeString,
Required: true,
Optional: true,
Sensitive: true,
},
"oidc_disable_userinfo": {
Expand All @@ -114,11 +133,17 @@ func resourceACLAuthMethodConfig() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},
"bound_issuer": {
Description: "The value against which to match the iss claim in a JWT.",
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},
"allowed_redirect_uris": {
Description: "A list of allowed values that can be used for the redirect URI.",
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Required: true,
Optional: true,
},
"discovery_ca_pem": {
Description: "PEM encoded CA certs for use by the TLS client used to talk with the OIDC Discovery URL.",
Expand All @@ -132,6 +157,24 @@ func resourceACLAuthMethodConfig() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},
"expiration_leeway": {
Description: `Duration of leeway when validating expiration of a JWT in the form of a time duration such as "5m" or "1h".`,
Type: schema.TypeString,
Default: "0s",
Optional: true,
},
"not_before_leeway": {
Description: `Duration of leeway when validating not before values of a token in the form of a time duration such as "5m" or "1h".`,
Type: schema.TypeString,
Default: "0s",
Optional: true,
},
"clock_skew_leeway": {
Description: `Duration of leeway when validating all claims in the form of a time duration such as "5m" or "1h".`,
Type: schema.TypeString,
Default: "0s",
Optional: true,
},
"claim_mappings": {
Description: "Mappings of claims (key) that will be copied to a metadata field (value).",
Type: schema.TypeMap,
Expand Down Expand Up @@ -302,6 +345,16 @@ func generateNomadACLAuthMethodConfig(intf interface{}) (*api.ACLAuthMethodConfi

for k, v := range configMap {
switch k {
case "jwt_validation_pub_keys":
unpacked, err := unpackStringArray(v, "jwt_validation_pub_keys")
if err != nil {
return nil, err
}
authMethodConfig.JWTValidationPubKeys = unpacked
case "jwks_url":
authMethodConfig.JWKSURL = v.(string)
case "jwks_ca_cert":
authMethodConfig.JWKSCACert = v.(string)
case "oidc_discovery_url":
authMethodConfig.OIDCDiscoveryURL = v.(string)
case "oidc_client_id":
Expand All @@ -322,6 +375,12 @@ func generateNomadACLAuthMethodConfig(intf interface{}) (*api.ACLAuthMethodConfi
return nil, err
}
authMethodConfig.BoundAudiences = unpacked
case "bound_issuer":
unpacked, err := unpackStringArray(v, "bound_issuer")
if err != nil {
return nil, err
}
authMethodConfig.BoundIssuer = unpacked
case "allowed_redirect_uris":
unpacked, err := unpackStringArray(v, "allowed_redirect_uris")
if err != nil {
Expand All @@ -340,6 +399,24 @@ func generateNomadACLAuthMethodConfig(intf interface{}) (*api.ACLAuthMethodConfi
return nil, err
}
authMethodConfig.SigningAlgs = unpacked
case "expiration_leeway":
dur, err := parseDuration(v.(string), "expiration_leeway")
if err != nil {
return nil, err
}
authMethodConfig.ExpirationLeeway = dur
case "not_before_leeway":
dur, err := parseDuration(v.(string), "not_before_leeway")
if err != nil {
return nil, err
}
authMethodConfig.NotBeforeLeeway = dur
case "clock_skew_leeway":
dur, err := parseDuration(v.(string), "clock_skew_leeway")
if err != nil {
return nil, err
}
authMethodConfig.ClockSkewLeeway = dur
case "claim_mappings":
unpacked, err := unpackStringMap(v, "claim_mappings")
if err != nil {
Expand All @@ -363,17 +440,24 @@ func flattenACLAuthMethodConfig(cfg *api.ACLAuthMethodConfig) []any {
return nil
}
result := map[string]interface{}{
"oidc_discovery_url": cfg.OIDCDiscoveryURL,
"oidc_client_id": cfg.OIDCClientID,
"oidc_client_secret": cfg.OIDCClientSecret,
"oidc_scopes": packStringArray(cfg.OIDCScopes),
"oidc_disable_userinfo": cfg.OIDCDisableUserInfo,
"bound_audiences": packStringArray(cfg.BoundAudiences),
"allowed_redirect_uris": packStringArray(cfg.AllowedRedirectURIs),
"discovery_ca_pem": packStringArray(cfg.DiscoveryCaPem),
"signing_algs": packStringArray(cfg.SigningAlgs),
"claim_mappings": packStringMap(cfg.ClaimMappings),
"list_claim_mappings": packStringMap(cfg.ListClaimMappings),
"jwt_validation_pub_keys": packStringArray(cfg.JWTValidationPubKeys),
"jwks_url": cfg.JWKSURL,
"jwks_ca_cert": cfg.JWKSCACert,
"oidc_discovery_url": cfg.OIDCDiscoveryURL,
"oidc_client_id": cfg.OIDCClientID,
"oidc_client_secret": cfg.OIDCClientSecret,
"oidc_scopes": packStringArray(cfg.OIDCScopes),
"oidc_disable_userinfo": cfg.OIDCDisableUserInfo,
"bound_audiences": packStringArray(cfg.BoundAudiences),
"bound_issuer": packStringArray(cfg.BoundIssuer),
"allowed_redirect_uris": packStringArray(cfg.AllowedRedirectURIs),
"discovery_ca_pem": packStringArray(cfg.DiscoveryCaPem),
"signing_algs": packStringArray(cfg.SigningAlgs),
"expiration_leeway": cfg.ExpirationLeeway.String(),
"not_before_leeway": cfg.NotBeforeLeeway.String(),
"clock_skew_leeway": cfg.ClockSkewLeeway.String(),
"claim_mappings": packStringMap(cfg.ClaimMappings),
"list_claim_mappings": packStringMap(cfg.ListClaimMappings),
}
return []any{result}
}
Expand Down Expand Up @@ -421,3 +505,14 @@ func packStringMap(stringMap map[string]string) map[string]interface{} {
}
return packed
}

func parseDuration(durStr, name string) (time.Duration, error) {
if durStr == "" {
return 0, nil
}
dur, err := time.ParseDuration(durStr)
if err != nil {
return dur, fmt.Errorf("failed to parse %s duration: %v", name, err)
}
return dur, nil
}
31 changes: 26 additions & 5 deletions website/docs/r/acl_auth_method.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ The following arguments are supported:

- `name` `(string: <required>)` - The identifier of the ACL Auth Method.

- `type` `(string: <required>)` - ACL Auth Method SSO workflow type. Currently,
the only supported type is `OIDC`.
- `type` `(string: <required>)` - ACL Auth Method SSO workflow type. Valid values,
are `OIDC` and `JWT`.

- `token_locality` `(string: <required>)` - Defines whether the ACL Auth Method
creates a local or global token when performing SSO login. This field must be
Expand All @@ -65,13 +65,22 @@ The following arguments are supported:
- `config`: `(block: <required>)` - Configuration specific to the auth method
provider.

- `oidc_discovery_url`: `(string: <required>)` - The OIDC Discovery URL,
- `jwt_validation_pub_keys`: `([]string: <optional>)` - List of PEM-encoded
public keys to use to authenticate signatures locally.

- `jwks_url`: `(string: <optional>)` - JSON Web Key Sets url for authenticating
signatures.

- `jwks_ca_cert`: `(string: <optional>)` - PEM encoded CA cert for use by the
TLS client used to talk with the JWKS server.

- `oidc_discovery_url`: `(string: <optional>)` - The OIDC Discovery URL,
without any .well-known component (base path).

- `oidc_client_id`: `(string: <required>)` - The OAuth Client ID configured
- `oidc_client_id`: `(string: <optional>)` - The OAuth Client ID configured
with the OIDC provider.

- `oidc_client_secret`: `(string: <required>)` - The OAuth Client Secret
- `oidc_client_secret`: `(string: <optional>)` - The OAuth Client Secret
configured with the OIDC provider.

- `oidc_scopes`: `([]string: <optional>)` - List of OIDC scopes.
Expand All @@ -84,6 +93,9 @@ The following arguments are supported:
- `bound_audiences`: `([]string: <optional>)` - List of auth claims that are
valid for login.

- `bound_issuer`: `([]string: <optional>)` - The value against which to match
the iss claim in a JWT.

- `allowed_redirect_uris`: `([]string: <optional>)` - A list of allowed values
that can be used for the redirect URI.

Expand All @@ -93,6 +105,15 @@ The following arguments are supported:
- `signing_algs`: `([]string: <optional>)` - A list of supported signing
algorithms.

- `expiration_leeway`: `(string: <optional>)` - Duration of leeway when validating
expiration of a JWT in the form of a time duration such as "5m" or "1h".

- `not_before_leeway`: `(string: <optional>)` - Duration of leeway when validating
not before values of a token in the form of a time duration such as "5m" or "1h".

- `clock_skew_leeway`: `(string: <optional>)` - Duration of leeway when validating
all claims in the form of a time duration such as "5m" or "1h".

- `claim_mappings`: `(map[string]string: <optional>)` - Mappings of claims (key)
that will be copied to a metadata field (value).

Expand Down

0 comments on commit 16a99fb

Please sign in to comment.