From 005809ddce3ea1d3cb072c7d89b08d7e8425ae0a Mon Sep 17 00:00:00 2001 From: Sergey Trasko Date: Thu, 18 Apr 2019 10:59:19 +0300 Subject: [PATCH 1/5] Support OIDC auth backends --- vault/resource_auth_backend.go | 2 +- vault/resource_jwt_auth_backend.go | 71 +++++++++++++++++--- vault/resource_jwt_auth_backend_role.go | 18 +++++ website/docs/r/jwt_auth_backend.html.md | 49 +++++++++++++- website/docs/r/jwt_auth_backend_role.html.md | 30 ++++++++- 5 files changed, 158 insertions(+), 12 deletions(-) diff --git a/vault/resource_auth_backend.go b/vault/resource_auth_backend.go index f8d3e536b..c69e28746 100644 --- a/vault/resource_auth_backend.go +++ b/vault/resource_auth_backend.go @@ -77,7 +77,7 @@ func authBackendResource() *schema.Resource { Type: schema.TypeString, ForceNew: true, Optional: true, - Description: "Speficies whether to show this mount in the UI-specific listing endpoint", + Description: "Specifies whether to show this mount in the UI-specific listing endpoint", }, "local": { diff --git a/vault/resource_jwt_auth_backend.go b/vault/resource_jwt_auth_backend.go index 26f40daf4..cff4dbffb 100644 --- a/vault/resource_jwt_auth_backend.go +++ b/vault/resource_jwt_auth_backend.go @@ -7,11 +7,10 @@ import ( "strings" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/vault/api" ) -var jwtAuthType = "jwt" - func jwtAuthBackendResource() *schema.Resource { return &schema.Resource{ Create: jwtAuthBackendWrite, @@ -26,7 +25,7 @@ func jwtAuthBackendResource() *schema.Resource { Optional: true, ForceNew: true, Description: "path to mount the backend", - Default: jwtAuthType, + Default: "jwt", ValidateFunc: func(v interface{}, k string) (ws []string, errs []error) { value := v.(string) if strings.HasSuffix(value, "/") { @@ -36,6 +35,15 @@ func jwtAuthBackendResource() *schema.Resource { }, }, + "type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Type of backend. Can be either 'jwt' or 'oidc'", + Default: "jwt", + ValidateFunc: validation.StringInSlice([]string{"jwt", "oidc"}, false), + }, + "description": { Type: schema.TypeString, Required: false, @@ -50,6 +58,19 @@ func jwtAuthBackendResource() *schema.Resource { Description: "The OIDC Discovery URL, without any .well-known component (base path)", }, + "oidc_client_id": { + Type: schema.TypeString, + Optional: true, + Description: "Client ID uses for OIDC", + }, + + "oidc_client_secret": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Description: "Client Secret uses for OIDC", + }, + "oidc_discovery_ca_pem": { Type: schema.TypeString, Optional: true, @@ -76,11 +97,18 @@ func jwtAuthBackendResource() *schema.Resource { Description: "A list of supported signing algorithms. Defaults to [RS256]", }, + "default_role": { + Type: schema.TypeString, + Optional: true, + Description: "The default role to use if none is provided during login", + }, + "accessor": { Type: schema.TypeString, Computed: true, Description: "The accessor of the JWT auth backend", }, + "tune": authMountTuneSchema(), }, } } @@ -88,7 +116,7 @@ func jwtAuthBackendResource() *schema.Resource { func jwtAuthBackendWrite(d *schema.ResourceData, meta interface{}) error { client := meta.(*api.Client) - authType := jwtAuthType + authType := d.Get("type").(string) desc := d.Get("description").(string) path := getJwtPath(d) @@ -153,7 +181,10 @@ func jwtAuthBackendRead(d *schema.ResourceData, meta interface{}) error { d.Set("accessor", backend.Accessor) d.Set("oidc_discovery_ca_pem", config.Data["oidc_discovery_ca_pem"]) + d.Set("oidc_client_id", config.Data["oidc_client_id"]) + d.Set("oidc_client_secret", config.Data["oidc_client_secret"]) d.Set("bound_issuer", config.Data["bound_issuer"]) + d.Set("default_role", config.Data["default_role"]) d.Set("oidc_discovery_url", config.Data["oidc_discovery_url"]) d.Set("jwt_validation_pubkeys", config.Data["jwt_validation_pubkeys"]) d.Set("jwt_supported_algs", config.Data["jwt_supported_algs"]) @@ -175,7 +206,6 @@ func jwtAuthBackendUpdate(d *schema.ResourceData, meta interface{}) error { oidcDiscoveryUrl, oidcDiscoveryUrlExists := d.GetOk("oidc_discovery_url") jwtValidationPubKeys, jwtValidationPubKeysExists := d.GetOk("jwt_validation_pubkeys") - jwtSupportedAlgs, jwtSupportedAlgsExists := d.GetOk("jwt_supported_algs") if oidcDiscoveryUrlExists == jwtValidationPubKeysExists { return errors.New("exactly one of oidc_discovery_url and jwt_validation_pubkeys should be provided") @@ -189,8 +219,17 @@ func jwtAuthBackendUpdate(d *schema.ResourceData, meta interface{}) error { configuration["jwt_validation_pubkeys"] = jwtValidationPubKeys } - if jwtSupportedAlgsExists { - configuration["jwt_supported_algs"] = jwtSupportedAlgs + if v, ok := d.GetOkExists("jwt_supported_algs"); ok { + configuration["jwt_supported_algs"] = v + } + if v, ok := d.GetOkExists("oidc_client_id"); ok { + configuration["oidc_client_id"] = v.(string) + } + if v, ok := d.GetOkExists("oidc_client_secret"); ok { + configuration["oidc_client_secret"] = v.(string) + } + if v, ok := d.GetOkExists("default_role"); ok { + configuration["default_role"] = v.(string) } _, err := client.Logical().Write(jwtConfigEndpoint(path), configuration) @@ -198,6 +237,22 @@ func jwtAuthBackendUpdate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error updating configuration to Vault for path %s: %s", path, err) } + if d.HasChange("tune") { + log.Printf("[INFO] JWT/OIDC Auth '%q' tune configuration changed", d.Id()) + if raw, ok := d.GetOk("tune"); ok { + backendType := d.Get("type") + log.Printf("[DEBUG] Writing %s auth tune to '%q'", backendType, path) + + err := authMountTune(client, "auth/"+path, raw) + if err != nil { + return nil + } + + log.Printf("[INFO] Written %s auth tune to '%q'", backendType, path) + d.SetPartial("tune") + } + } + return jwtAuthBackendRead(d, meta) } @@ -215,7 +270,7 @@ func getJwtAuthBackendIfPresent(client *api.Client, path string) (*api.AuthMount for authBackendPath, auth := range auths { - if auth.Type == jwtAuthType && authBackendPath == configuredPath { + if authBackendPath == configuredPath { return auth, nil } } diff --git a/vault/resource_jwt_auth_backend_role.go b/vault/resource_jwt_auth_backend_role.go index 51e7ed7cf..e0e756858 100644 --- a/vault/resource_jwt_auth_backend_role.go +++ b/vault/resource_jwt_auth_backend_role.go @@ -63,6 +63,14 @@ func jwtAuthBackendRoleResource() *schema.Resource { }, Description: "Policies to be set on tokens issued using this role.", }, + "allowed_redirect_uris": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "The list of allowed values for redirect_uri during OIDC logins.", + }, "ttl": { Type: schema.TypeInt, Optional: true, @@ -193,6 +201,13 @@ func jwtAuthBackendRoleRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf("error setting policies in state: %s", err) } + if resp.Data["allowed_redirect_uris"] != nil { + allowedRedirectUris := util.JsonStringArrayToStringArray(resp.Data["allowed_redirect_uris"].([]interface{})) + err = d.Set("allowed_redirect_uris", allowedRedirectUris) + if err != nil { + return fmt.Errorf("error setting allowed_redirect_uris in state: %s", err) + } + } tokenTTL, err := resp.Data["ttl"].(json.Number).Int64() if err != nil { @@ -340,6 +355,9 @@ func jwtAuthBackendRoleDataToWrite(d *schema.ResourceData) map[string]interface{ if dataList := util.TerraformSetToStringArray(d.Get("policies")); len(dataList) > 0 { data["policies"] = dataList } + if dataList := util.TerraformSetToStringArray(d.Get("allowed_redirect_uris")); len(dataList) > 0 { + data["allowed_redirect_uris"] = dataList + } if v, ok := d.GetOk("role_type"); ok { data["role_type"] = v.(string) diff --git a/website/docs/r/jwt_auth_backend.html.md b/website/docs/r/jwt_auth_backend.html.md index dd3ca07c5..88b37ff05 100644 --- a/website/docs/r/jwt_auth_backend.html.md +++ b/website/docs/r/jwt_auth_backend.html.md @@ -13,6 +13,8 @@ Provides a resource for managing an ## Example Usage +Manage JWT auth backend: + ```hcl resource "vault_jwt_auth_backend" "example" { description = "Demonstration of the Terraform JWT auth backend" @@ -22,16 +24,39 @@ resource "vault_jwt_auth_backend" "example" { } ``` +Manage OIDC auth backend: + +```hcl +resource "vault_jwt_auth_backend" "example" { + description = "Demonstration of the Terraform JWT auth backend" + path = "oidc" + type = "oidc" + oidc_discovery_url = "https://myco.auth0.com/" + oidc_client_id = "1234567890" + oidc_client_secret = "secret123456" + bound_issuer = "https://myco.auth0.com/" + tune = { + listing_visibility = "unauth" + } +} +``` + ## Argument Reference The following arguments are supported: -* `path` - (Required) Path to mount the JWT auth backend +* `path` - (Required) Path to mount the JWT/OIDC auth backend + +* `type` - (Optional) Type of auth backend. Should be one of `jwt` or `oidc`. Default - `jwt` * `description` - (Optional) The description of the auth backend * `oidc_discovery_url` - (Optional) The OIDC Discovery URL, without any .well-known component (base path). Cannot be used in combination with `jwt_validation_pubkeys` +* `oidc_client_id` - (Optional) Client ID used for OIDC backends + +* `oidc_client_secret` - (Optional) Client Secret used for OIDC backends + * `bound_issuer` - (Optional) The value against which to match the iss claim in a JWT * `oidc_discovery_ca_pem` - (Optional) The CA certificate or chain of certificates, in PEM format, to use to validate connections to the OIDC Discovery URL. If not set, system certificates are used @@ -40,6 +65,28 @@ The following arguments are supported: * `jwt_supported_algs` - (Optional) A list of supported signing algorithms. Vault 1.1.0 defaults to [RS256] but future or past versions of Vault may differ +The `tune` block is used to tune the auth backend: + +* `default_lease_ttl` - (Optional) Specifies the default time-to-live. + If set, this overrides the global default. + Must be a valid [duration string](https://golang.org/pkg/time/#ParseDuration) + +* `max_lease_ttl` - (Optional) Specifies the maximum time-to-live. + If set, this overrides the global default. + Must be a valid [duration string](https://golang.org/pkg/time/#ParseDuration) + +* `audit_non_hmac_response_keys` - (Optional) Specifies the list of keys that will + not be HMAC'd by audit devices in the response data object. + +* `audit_non_hmac_request_keys` - (Optional) Specifies the list of keys that will + not be HMAC'd by audit devices in the request data object. + +* `listing_visibility` - (Optional) Specifies whether to show this mount in + the UI-specific listing endpoint. Valid values are "unauth" or "hidden". + +* `passthrough_request_headers` - (Optional) List of headers to whitelist and + pass from the request to the backend. + ## Attributes Reference No additional attributes are exposed by this resource. diff --git a/website/docs/r/jwt_auth_backend_role.html.md b/website/docs/r/jwt_auth_backend_role.html.md index e28c1291a..937e91ed7 100644 --- a/website/docs/r/jwt_auth_backend_role.html.md +++ b/website/docs/r/jwt_auth_backend_role.html.md @@ -3,17 +3,19 @@ layout: "vault" page_title: "Vault: vault_jwt_auth_backend_role resource" sidebar_current: "docs-vault-resource-jwt-auth-backend-role" description: |- - Manages JWT auth backend roles in Vault. + Manages JWT/OIDC auth backend roles in Vault. --- # vault\_jwt\_auth\_backend\_role -Manages an JWT auth backend role in a Vault server. See the [Vault +Manages an JWT/OIDC auth backend role in a Vault server. See the [Vault documentation](https://www.vaultproject.io/docs/auth/jwt.html) for more information. ## Example Usage +Role for JWT backend: + ```hcl resource "vault_jwt_auth_backend" "jwt" { path = "jwt" @@ -26,6 +28,27 @@ resource "vault_jwt_auth_backend_role" "example" { bound_audiences = ["https://myco.test"] user_claim = "https://vault/user" + role_type = "jwt" +} +``` + +Role for OIDC backend: + +```hcl +resource "vault_jwt_auth_backend" "oidc" { + path = "oidc" + default_role = "test-role" +} + +resource "vault_jwt_auth_backend_role" "example" { + backend = "${vault_jwt_auth_backend.oidc.path}" + role_name = "test-role" + policies = ["default", "dev", "prod"] + + bound_audiences = ["https://myco.test"] + user_claim = "https://vault/user" + allowed_redirect_uris = ["http://localhost:8200/ui/vault/auth/oidc/oidc/callback"] + role_type = "oidc" } ``` @@ -84,6 +107,9 @@ The following arguments are supported: * `backend` - (Optional) The unique name of the auth backend to configure. Defaults to `jwt`. +* `allowed_redirect_uris` - (Optional) The list of allowed values for redirect_uri during OIDC logins. + Required for OIDC roles + ## Attributes Reference No additional attributes are exported by this resource. From fc996171223d7e20433c310705fd889838906f65 Mon Sep 17 00:00:00 2001 From: Sergey Trasko Date: Thu, 25 Apr 2019 11:30:27 +0300 Subject: [PATCH 2/5] Code review fixes (typos) --- vault/resource_jwt_auth_backend.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vault/resource_jwt_auth_backend.go b/vault/resource_jwt_auth_backend.go index cff4dbffb..8185556ee 100644 --- a/vault/resource_jwt_auth_backend.go +++ b/vault/resource_jwt_auth_backend.go @@ -61,14 +61,14 @@ func jwtAuthBackendResource() *schema.Resource { "oidc_client_id": { Type: schema.TypeString, Optional: true, - Description: "Client ID uses for OIDC", + Description: "Client ID used for OIDC", }, "oidc_client_secret": { Type: schema.TypeString, Optional: true, Sensitive: true, - Description: "Client Secret uses for OIDC", + Description: "Client Secret used for OIDC", }, "oidc_discovery_ca_pem": { From afc5d1cff3365441a90a93c690a0808822d4857b Mon Sep 17 00:00:00 2001 From: Sergey Trasko Date: Mon, 29 Apr 2019 16:35:21 +0300 Subject: [PATCH 3/5] Added support for bound_claims, claim_mappings and oidc_scopes --- vault/resource_jwt_auth_backend_role.go | 48 ++++++++ vault/resource_jwt_auth_backend_role_test.go | 116 ++++++++++++++++++- vault/resource_jwt_auth_backend_test.go | 44 +++++++ website/docs/r/jwt_auth_backend_role.html.md | 9 ++ 4 files changed, 215 insertions(+), 2 deletions(-) diff --git a/vault/resource_jwt_auth_backend_role.go b/vault/resource_jwt_auth_backend_role.go index e0e756858..71f807f08 100644 --- a/vault/resource_jwt_auth_backend_role.go +++ b/vault/resource_jwt_auth_backend_role.go @@ -106,6 +106,24 @@ func jwtAuthBackendRoleResource() *schema.Resource { Type: schema.TypeString, }, }, + "oidc_scopes": { + Type: schema.TypeSet, + Optional: true, + Description: "List of OIDC scopes to be used with an OIDC role. The standard scope \"openid\" is automatically included and need not be specified", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "bound_claims": { + Type: schema.TypeMap, + Optional: true, + Description: "Map of claims/values to match against. The expected value may be a single string or a list of strings.", + }, + "claim_mappings": { + Type: schema.TypeMap, + Optional: true, + Description: "Map of claims (keys) to be copied to specified metadata fields (values).", + }, "groups_claim": { Type: schema.TypeString, Optional: true, @@ -246,6 +264,24 @@ func jwtAuthBackendRoleRead(d *schema.ResourceData, meta interface{}) error { d.Set("bound_cidrs", make([]string, 0)) } + if resp.Data["oidc_scopes"] != nil { + cidrs := util.JsonStringArrayToStringArray(resp.Data["oidc_scopes"].([]interface{})) + err = d.Set("oidc_scopes", cidrs) + if err != nil { + return fmt.Errorf("error setting oidc_scopes in state: %s", err) + } + } else { + d.Set("oidc_scopes", make([]string, 0)) + } + + if resp.Data["bound_claims"] != nil { + d.Set("bound_claims", resp.Data["bound_claims"]) + } + + if resp.Data["claim_mappings"] != nil { + d.Set("claim_mappings", resp.Data["claim_mappings"]) + } + d.Set("groups_claim", resp.Data["groups_claim"].(string)) if resp.Data["groups_claim_delimiter_pattern"] != nil { d.Set("groups_claim_delimiter_pattern", resp.Data["groups_claim_delimiter_pattern"].(string)) @@ -383,6 +419,18 @@ func jwtAuthBackendRoleDataToWrite(d *schema.ResourceData) map[string]interface{ data["bound_cidrs"] = dataList } + if dataList := util.TerraformSetToStringArray(d.Get("oidc_scopes")); len(dataList) > 0 { + data["oidc_scopes"] = dataList + } + + if v, ok := d.GetOk("bound_claims"); ok { + data["bound_claims"] = v + } + + if v, ok := d.GetOk("claim_mappings"); ok { + data["claim_mappings"] = v + } + if v, ok := d.GetOkExists("groups_claim"); ok { data["groups_claim"] = v.(string) } diff --git a/vault/resource_jwt_auth_backend_role_test.go b/vault/resource_jwt_auth_backend_role_test.go index 20d8ebea9..7f68bf833 100644 --- a/vault/resource_jwt_auth_backend_role_test.go +++ b/vault/resource_jwt_auth_backend_role_test.go @@ -243,6 +243,76 @@ func TestAccJWTAuthBackendRole_full(t *testing.T) { }) } +func TestAccJWTAuthBackendRoleOIDC_full(t *testing.T) { + backend := acctest.RandomWithPrefix("oidc") + role := acctest.RandomWithPrefix("test-role") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testProviders, + CheckDestroy: testAccCheckJWTAuthBackendRoleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccJWTAuthBackendRoleConfigOIDC_full(backend, role), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "backend", backend), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "role_name", role), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "policies.#", "3"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "policies.1971754988", "default"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "policies.232240223", "prod"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "policies.326271447", "dev"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "ttl", "3600"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "max_ttl", "7200"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "num_uses", "12"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "period", "0"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_cidrs.#", "2"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_cidrs.1709552943", "10.148.0.0/20"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_cidrs.838827017", "10.150.0.0/20"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_subject", "sl29dlldsfj3uECzsU3Sbmh0F29Fios1@client"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_audiences.#", "1"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_audiences.2478800941", "https://myco.test"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "user_claim", "https://vault/user"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "groups_claim", "https://vault/groups"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "allowed_redirect_uris.#", "1"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "allowed_redirect_uris.4240710842", "http://localhost:8080"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_claims.%", "2"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_claims.department", "engineering"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "bound_claims.sector", "7g"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "claim_mappings.%", "2"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "claim_mappings.group", "group"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend_role.role", + "claim_mappings.preferred_language", "language"), + ), + }, + }, + }) +} + func TestAccJWTAuthBackendRole_fullUpdate(t *testing.T) { backend := acctest.RandomWithPrefix("jwt") role := acctest.RandomWithPrefix("test-role") @@ -399,8 +469,42 @@ resource "vault_auth_backend" "jwt" { resource "vault_jwt_auth_backend_role" "role" { backend = "${vault_auth_backend.jwt.path}" - role_name = "%s" - role_type = "jwt" + role_name = "%s" + role_type = "jwt" + + bound_subject = "sl29dlldsfj3uECzsU3Sbmh0F29Fios1@client" + bound_cidrs = ["10.148.0.0/20", "10.150.0.0/20"] + bound_audiences = ["https://myco.test"] + user_claim = "https://vault/user" + groups_claim = "https://vault/groups" + policies = ["default", "dev", "prod"] + ttl = 3600 + num_uses = 12 + max_ttl = 7200 +}`, backend, role) +} + +func testAccJWTAuthBackendRoleConfigOIDC_full(backend, role string) string { + return fmt.Sprintf(` +resource "vault_jwt_auth_backend" "jwt" { + type = "oidc" + path = "%s" + oidc_discovery_url = "https://myco.auth0.com/" + oidc_client_id = "client" + oidc_client_secret = "secret" + lifecycle = { + ignore_changes = [ + # Ignore changes to odic_clie_secret inside the tests + "oidc_client_secret" + ] + } +} + +resource "vault_jwt_auth_backend_role" "role" { + backend = "${vault_jwt_auth_backend.jwt.path}" + role_name = "%s" + role_type = "oidc" + allowed_redirect_uris = ["http://localhost:8080"] bound_subject = "sl29dlldsfj3uECzsU3Sbmh0F29Fios1@client" bound_cidrs = ["10.148.0.0/20", "10.150.0.0/20"] @@ -411,6 +515,14 @@ resource "vault_jwt_auth_backend_role" "role" { ttl = 3600 num_uses = 12 max_ttl = 7200 + bound_claims = { + department = "engineering", + sector = "7g" + } + claim_mappings = { + preferred_language = "language", + group = "group" + } }`, backend, role) } diff --git a/vault/resource_jwt_auth_backend_test.go b/vault/resource_jwt_auth_backend_test.go index db2481533..fd043a919 100644 --- a/vault/resource_jwt_auth_backend_test.go +++ b/vault/resource_jwt_auth_backend_test.go @@ -25,6 +25,7 @@ func TestAccJWTAuthBackend(t *testing.T) { resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "path", path), resource.TestCheckResourceAttrSet("vault_jwt_auth_backend.jwt", "accessor"), resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "bound_issuer", ""), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "type", "jwt"), ), }, { @@ -33,6 +34,7 @@ func TestAccJWTAuthBackend(t *testing.T) { resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "oidc_discovery_url", "https://myco.auth0.com/"), resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "bound_issuer", "api://default"), resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "jwt_supported_algs.#", "1"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "type", "jwt"), ), }, { @@ -41,6 +43,27 @@ func TestAccJWTAuthBackend(t *testing.T) { resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "oidc_discovery_url", "https://myco.auth0.com/"), resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "bound_issuer", "api://default"), resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "jwt_supported_algs.#", "2"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.jwt", "type", "jwt"), + ), + }, + }, + }) +} +func TestAccJWTAuthBackend_OIDC(t *testing.T) { + path := acctest.RandomWithPrefix("oidc") + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testProviders, + CheckDestroy: testJWTAuthBackend_Destroyed(path), + Steps: []resource.TestStep{ + { + Config: testAccJWTAuthBackendConfigOIDC(path), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_jwt_auth_backend.oidc", "oidc_discovery_url", "https://myco.auth0.com/"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.oidc", "bound_issuer", "api://default"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.oidc", "oidc_client_id", "client"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.oidc", "type", "oidc"), + resource.TestCheckResourceAttr("vault_jwt_auth_backend.oidc", "default_role", "api"), ), }, }, @@ -90,6 +113,27 @@ resource "vault_jwt_auth_backend" "jwt" { `, oidcDiscoveryUrl, validationPublicKeys, boundIssuer, supportedAlgs, path) } +func testAccJWTAuthBackendConfigOIDC(path string) string { + return fmt.Sprintf(` +resource "vault_jwt_auth_backend" "oidc" { + description = "OIDC backend" + oidc_discovery_url = "https://myco.auth0.com/" + oidc_client_id = "client" + oidc_client_secret = "secret" + bound_issuer = "api://default" + path = "%s" + type = "oidc" + default_role = "api" + lifecycle = { + ignore_changes = [ + # Ignore changes to odic_clie_secret inside the tests + "oidc_client_secret" + ] + } +} +`, path) +} + func testJWTAuthBackend_Destroyed(path string) resource.TestCheckFunc { return func(s *terraform.State) error { diff --git a/website/docs/r/jwt_auth_backend_role.html.md b/website/docs/r/jwt_auth_backend_role.html.md index 937e91ed7..bde5551d6 100644 --- a/website/docs/r/jwt_auth_backend_role.html.md +++ b/website/docs/r/jwt_auth_backend_role.html.md @@ -89,6 +89,15 @@ The following arguments are supported: address for login requests. This value is also encoded into any resulting token. +* `bound_claims` - (Optional) If set, a map of claims/values to match against. + The expected value may be a single string or a list of strings. + +* `claim_mappings` - (Optional) If set, a map of claims (keys) to be copied + to specified metadata fields (values). + +* `oidc_scopes` - (Optional) If set, a list of OIDC scopes to be used with an OIDC role. + The standard scope "openid" is automatically included and need not be specified. + * `groups_claim` - (Optional) The claim to use to uniquely identify the set of groups to which the user belongs; this will be used as the names for the Identity group aliases created due to a successful login. The claim From fc58866fdff92f77e0bd7291296fcb2f08d11a06 Mon Sep 17 00:00:00 2001 From: Becca Petrin Date: Wed, 1 May 2019 17:07:05 +0300 Subject: [PATCH 4/5] Update vault/resource_jwt_auth_backend_role.go Co-Authored-By: sergeytrasko --- vault/resource_jwt_auth_backend_role.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vault/resource_jwt_auth_backend_role.go b/vault/resource_jwt_auth_backend_role.go index decd2d463..5794e92ca 100644 --- a/vault/resource_jwt_auth_backend_role.go +++ b/vault/resource_jwt_auth_backend_role.go @@ -109,7 +109,7 @@ func jwtAuthBackendRoleResource() *schema.Resource { "oidc_scopes": { Type: schema.TypeSet, Optional: true, - Description: "List of OIDC scopes to be used with an OIDC role. The standard scope \"openid\" is automatically included and need not be specified", + Description: "List of OIDC scopes to be used with an OIDC role. The standard scope \"openid\" is automatically included and need not be specified.", Elem: &schema.Schema{ Type: schema.TypeString, }, From 44cbc86a1dac49f97fc040fd96ccc2ed8e62bf3f Mon Sep 17 00:00:00 2001 From: Sergey Trasko Date: Wed, 1 May 2019 17:11:55 +0300 Subject: [PATCH 5/5] Fix compilation errors (after merge from master) --- vault/resource_jwt_auth_backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vault/resource_jwt_auth_backend.go b/vault/resource_jwt_auth_backend.go index 83b2dcc1b..39ee766f5 100644 --- a/vault/resource_jwt_auth_backend.go +++ b/vault/resource_jwt_auth_backend.go @@ -24,7 +24,7 @@ func jwtAuthBackendResource() *schema.Resource { Optional: true, ForceNew: true, Description: "path to mount the backend", - Default: jwtAuthType, + Default: "jwt", ValidateFunc: validateNoTrailingSlash, },