From db95128768ccaebb4b2f9d505002ff770a58237b Mon Sep 17 00:00:00 2001 From: Ben Ash <32777270+benashz@users.noreply.github.com> Date: Wed, 13 Sep 2023 13:23:50 -0400 Subject: [PATCH] Update k8s-auth config to support unsetting the K8s CA Cert (#2005) Prior to vault-1.9.3, the k8s-auth engine would store the K8S CA cert in its configuration if Vault was running in K8s. Post vault-1.9.3, this behaviour was changed to longer store the K8s CA cert in config. That change confuses TFVP since the kubernetes_ca_cert field can no longer be computed. This fix detects and remedies by adding the ability to "unset" the CA cert in the case where we are provisioning vault-1.9.3+. It should also clean up any K8s CA cert that was left behind after upgrading from any Vault prior to 1.9.3. * Factor out some more K8s field constants * CI: skip in k8s cluster tests * Update imports --- .github/workflows/build.yml | 2 +- internal/consts/consts.go | 7 +- internal/provider/meta.go | 1 - ...a_source_kubernetes_auth_backend_config.go | 27 +- ...rce_kubernetes_auth_backend_config_test.go | 35 +- ...data_source_kubernetes_credentials_test.go | 7 +- ...resource_kubernetes_auth_backend_config.go | 222 +++++++----- ...rce_kubernetes_auth_backend_config_test.go | 331 +++++++++++++++--- vault/resource_kubernetes_secret_backend.go | 29 +- ...rce_kubernetes_secret_backend_role_test.go | 3 +- ...resource_kubernetes_secret_backend_test.go | 20 +- vault/resource_quota_rate_limit.go | 2 +- 12 files changed, 482 insertions(+), 204 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc4f3c10d..81f08febd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -192,7 +192,7 @@ jobs: LDAP_BINDPASS: "adminpassword" LDAP_URL: "ldap://openldap:1389" run: | - make testacc-ent TESTARGS='-test.v' SKIP_MSSQL_MULTI_CI=true SKIP_RAFT_TESTS=true SKIP_VAULT_NEXT_TESTS=true + make testacc-ent TESTARGS='-test.v' SKIP_MSSQL_MULTI_CI=true SKIP_RAFT_TESTS=true SKIP_VAULT_NEXT_TESTS=true TF_ACC_K8S_SKIP_IN_CLUSTER=true - name: "Generate Vault API Path Coverage Report" run: | go run cmd/coverage/main.go -openapi-doc=./testdata/openapi.json diff --git a/internal/consts/consts.go b/internal/consts/consts.go index 88d6f43e5..e7d9ddd36 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -352,6 +352,12 @@ const ( FieldCredentialType = "credential_type" FieldFilename = "filename" FieldDefault = "default" + FieldKubernetesCACert = "kubernetes_ca_cert" + FieldDisableLocalCAJWT = "disable_local_ca_jwt" + FieldKubernetesHost = "kubernetes_host" + FieldServiceAccountJWT = "service_account_jwt" + FieldDisableISSValidation = "disable_iss_validation" + FieldPEMKeys = "pem_keys" /* common environment variables */ @@ -385,7 +391,6 @@ const ( EnvVarRadiusPassword = "RADIUS_PASSWORD" // EnvVarTokenFilename for the TokenFile auth login. EnvVarTokenFilename = "TERRAFORM_VAULT_TOKEN_FILENAME" - /* common mount types */ diff --git a/internal/provider/meta.go b/internal/provider/meta.go index 9842e5f79..d80e9459b 100644 --- a/internal/provider/meta.go +++ b/internal/provider/meta.go @@ -35,7 +35,6 @@ const ( var ( MaxHTTPRetriesCCC int - VaultVersion190 = version.Must(version.NewSemver(consts.VaultVersion190)) VaultVersion110 = version.Must(version.NewSemver(consts.VaultVersion110)) VaultVersion111 = version.Must(version.NewSemver(consts.VaultVersion111)) VaultVersion112 = version.Must(version.NewSemver(consts.VaultVersion112)) diff --git a/vault/data_source_kubernetes_auth_backend_config.go b/vault/data_source_kubernetes_auth_backend_config.go index d6b7de310..9f67f34db 100644 --- a/vault/data_source_kubernetes_auth_backend_config.go +++ b/vault/data_source_kubernetes_auth_backend_config.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/internal/provider" ) @@ -28,38 +29,38 @@ func kubernetesAuthBackendConfigDataSource() *schema.Resource { return strings.Trim(v.(string), "/") }, }, - "kubernetes_host": { + consts.FieldKubernetesHost: { Type: schema.TypeString, Computed: true, Optional: true, Description: "Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.", }, - "kubernetes_ca_cert": { + consts.FieldKubernetesCACert: { Type: schema.TypeString, Description: "PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API.", Computed: true, Optional: true, }, - "pem_keys": { + consts.FieldPEMKeys: { Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, Description: "Optional list of PEM-formatted public keys or certificates used to verify the signatures of Kubernetes service account JWTs. If a certificate is given, its public key will be extracted. Not every installation of Kubernetes exposes these keys.", Optional: true, }, - "issuer": { + consts.FieldIssuer: { Type: schema.TypeString, Computed: true, Optional: true, Description: "Optional JWT issuer. If no issuer is specified, kubernetes.io/serviceaccount will be used as the default issuer.", }, - "disable_iss_validation": { + consts.FieldDisableISSValidation: { Type: schema.TypeBool, Computed: true, Optional: true, Description: "Optional disable JWT issuer validation. Allows to skip ISS validation.", }, - "disable_local_ca_jwt": { + consts.FieldDisableLocalCAJWT: { Type: schema.TypeBool, Computed: true, Optional: true, @@ -89,20 +90,20 @@ func kubernetesAuthBackendConfigDataSourceRead(d *schema.ResourceData, meta inte return nil } d.SetId(path) - d.Set("kubernetes_ca_cert", resp.Data["kubernetes_ca_cert"]) - d.Set("kubernetes_host", resp.Data["kubernetes_host"]) + d.Set(consts.FieldKubernetesCACert, resp.Data[consts.FieldKubernetesCACert]) + d.Set(consts.FieldKubernetesHost, resp.Data[consts.FieldKubernetesHost]) - iPemKeys := resp.Data["pem_keys"].([]interface{}) + iPemKeys := resp.Data[consts.FieldPEMKeys].([]interface{}) pemKeys := make([]string, 0, len(iPemKeys)) for _, iPemKey := range iPemKeys { pemKeys = append(pemKeys, iPemKey.(string)) } - d.Set("pem_keys", pemKeys) - d.Set("issuer", resp.Data["issuer"]) - d.Set("disable_iss_validation", resp.Data["disable_iss_validation"]) - d.Set("disable_local_ca_jwt", resp.Data["disable_local_ca_jwt"]) + d.Set(consts.FieldPEMKeys, pemKeys) + d.Set(consts.FieldIssuer, resp.Data[consts.FieldIssuer]) + d.Set(consts.FieldDisableISSValidation, resp.Data[consts.FieldDisableISSValidation]) + d.Set(consts.FieldDisableLocalCAJWT, resp.Data[consts.FieldDisableLocalCAJWT]) return nil } diff --git a/vault/data_source_kubernetes_auth_backend_config_test.go b/vault/data_source_kubernetes_auth_backend_config_test.go index bbc5bef68..f3f0ef06f 100644 --- a/vault/data_source_kubernetes_auth_backend_config_test.go +++ b/vault/data_source_kubernetes_auth_backend_config_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/testutil" ) @@ -29,9 +30,9 @@ func TestAccKubernetesAuthBackendConfigDataSource_basic(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), ), @@ -44,9 +45,9 @@ func TestAccKubernetesAuthBackendConfigDataSource_basic(t *testing.T) { resource.TestCheckNoResourceAttr("data.vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt"), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", "pem_keys.#", "0"), ), @@ -68,14 +69,15 @@ func TestAccKubernetesAuthBackendConfigDataSource_full(t *testing.T) { CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, Steps: []resource.TestStep{ { - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, jwt, issuer, disableIssValidation, disableLocalCaJwt), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, jwt, issuer, + disableIssValidation, disableLocalCaJwt, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -83,11 +85,11 @@ func TestAccKubernetesAuthBackendConfigDataSource_full(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", issuer), + consts.FieldIssuer, issuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(disableIssValidation)), + consts.FieldDisableISSValidation, strconv.FormatBool(disableIssValidation)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(disableLocalCaJwt)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(disableLocalCaJwt)), ), }, { @@ -98,19 +100,19 @@ func TestAccKubernetesAuthBackendConfigDataSource_full(t *testing.T) { resource.TestCheckNoResourceAttr("data.vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt"), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", "pem_keys.#", "1"), resource.TestCheckResourceAttr("data.vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", issuer), + consts.FieldIssuer, issuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(disableIssValidation)), + consts.FieldDisableISSValidation, strconv.FormatBool(disableIssValidation)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(disableLocalCaJwt)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(disableLocalCaJwt)), ), }, }, @@ -132,5 +134,6 @@ func testAccKubernetesAuthBackendConfigDataSourceConfig_full(backend, jwt string data "vault_kubernetes_auth_backend_config" "config" { backend = "%s" -}`, testAccKubernetesAuthBackendConfigConfig_full(backend, jwt, issuer, disableIssValidation, disableLocalCaJwt), backend) +}`, testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, jwt, issuer, + disableIssValidation, disableLocalCaJwt, false), backend) } diff --git a/vault/data_source_kubernetes_credentials_test.go b/vault/data_source_kubernetes_credentials_test.go index dd6e86960..c486723cc 100644 --- a/vault/data_source_kubernetes_credentials_test.go +++ b/vault/data_source_kubernetes_credentials_test.go @@ -9,12 +9,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/testutil" ) func TestAccKubernetesSecretCredentialsDataSource(t *testing.T) { - testutil.SkipTestEnvSet(t, testutil.EnvVarSkipVaultNext) + t.Skip("Requires a Kubernetes cluster and manual setup. Should be automated.") dataSourceName := "data.vault_kubernetes_service_account_token.token" backend := acctest.RandomWithPrefix("tf-test-kubernetes") @@ -22,7 +23,9 @@ func TestAccKubernetesSecretCredentialsDataSource(t *testing.T) { resource.Test(t, resource.TestCase{ Providers: testProviders, - PreCheck: func() { testutil.TestAccPreCheck(t) }, + PreCheck: func() { + testutil.TestAccPreCheck(t) + }, Steps: []resource.TestStep{ { Config: testDataSourceKubernetesServiceAccountTokenConfig(backend, name), diff --git a/vault/resource_kubernetes_auth_backend_config.go b/vault/resource_kubernetes_auth_backend_config.go index 7c0765805..524f7cd95 100644 --- a/vault/resource_kubernetes_auth_backend_config.go +++ b/vault/resource_kubernetes_auth_backend_config.go @@ -4,19 +4,85 @@ package vault import ( + "context" "fmt" "log" "regexp" "strings" + "sync" + "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/internal/provider" ) -var kubernetesAuthBackendConfigFromPathRegex = regexp.MustCompile("^auth/(.+)/config$") +var ( + kubernetesAuthBackendConfigFromPathRegex = regexp.MustCompile("^auth/(.+)/config$") + // overrideKubernetesFieldsMap maps resource IDs to a slice of strings containing + // field names that should be unset/overridden on resource update. Typically only + // computed fields might need to be unset. map[resource.ID+"."+fieldName] = + // overrideValue + overrideKubernetesFieldsMap = sync.Map{} + vaultVersion193 = version.Must(version.NewSemver("1.9.3")) +) func kubernetesAuthBackendConfigResource() *schema.Resource { + s := map[string]*schema.Schema{ + consts.FieldKubernetesHost: { + Type: schema.TypeString, + Required: true, + Description: "Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.", + }, + consts.FieldKubernetesCACert: { + Type: schema.TypeString, + Description: "PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API.", + Optional: true, + Computed: true, + }, + "token_reviewer_jwt": { + Type: schema.TypeString, + Description: "A service account JWT used to access the TokenReview API to validate other JWTs during login. If not set the JWT used for login will be used to access the API.", + Default: "", + Optional: true, + Sensitive: true, + }, + consts.FieldPEMKeys: { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Optional list of PEM-formatted public keys or certificates used to verify the signatures of Kubernetes service account JWTs. If a certificate is given, its public key will be extracted. Not every installation of Kubernetes exposes these keys.", + Optional: true, + }, + consts.FieldBackend: { + Type: schema.TypeString, + Optional: true, + Description: "Unique name of the kubernetes backend to configure.", + ForceNew: true, + Default: "kubernetes", + // standardise on no beginning or trailing slashes + StateFunc: func(v interface{}) string { + return strings.Trim(v.(string), "/") + }, + }, + consts.FieldIssuer: { + Type: schema.TypeString, + Optional: true, + Description: "Optional JWT issuer. If no issuer is specified, kubernetes.io/serviceaccount will be used as the default issuer.", + }, + consts.FieldDisableISSValidation: { + Type: schema.TypeBool, + Computed: true, + Optional: true, + Description: "Optional disable JWT issuer validation. Allows to skip ISS validation.", + }, + consts.FieldDisableLocalCAJWT: { + Type: schema.TypeBool, + Computed: true, + Optional: true, + Description: "Optional disable defaulting to the local CA cert and service account JWT when running in a Kubernetes pod.", + }, + } return &schema.Resource{ Create: kubernetesAuthBackendConfigCreate, Read: provider.ReadWrapper(kubernetesAuthBackendConfigRead), @@ -26,61 +92,43 @@ func kubernetesAuthBackendConfigResource() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - - Schema: map[string]*schema.Schema{ - "kubernetes_host": { - Type: schema.TypeString, - Required: true, - Description: "Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.", - }, - "kubernetes_ca_cert": { - Type: schema.TypeString, - Description: "PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API.", - Optional: true, - Computed: true, - }, - "token_reviewer_jwt": { - Type: schema.TypeString, - Description: "A service account JWT used to access the TokenReview API to validate other JWTs during login. If not set the JWT used for login will be used to access the API.", - Default: "", - Optional: true, - Sensitive: true, - }, - "pem_keys": { - Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Optional list of PEM-formatted public keys or certificates used to verify the signatures of Kubernetes service account JWTs. If a certificate is given, its public key will be extracted. Not every installation of Kubernetes exposes these keys.", - Optional: true, - }, - "backend": { - Type: schema.TypeString, - Optional: true, - Description: "Unique name of the kubernetes backend to configure.", - ForceNew: true, - Default: "kubernetes", - // standardise on no beginning or trailing slashes - StateFunc: func(v interface{}) string { - return strings.Trim(v.(string), "/") - }, - }, - "issuer": { - Type: schema.TypeString, - Optional: true, - Description: "Optional JWT issuer. If no issuer is specified, kubernetes.io/serviceaccount will be used as the default issuer.", - }, - "disable_iss_validation": { - Type: schema.TypeBool, - Computed: true, - Optional: true, - Description: "Optional disable JWT issuer validation. Allows to skip ISS validation.", - }, - "disable_local_ca_jwt": { - Type: schema.TypeBool, - Computed: true, - Optional: true, - Description: "Optional disable defaulting to the local CA cert and service account JWT when running in a Kubernetes pod.", - }, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, m interface{}) error { + if !diff.Get(consts.FieldDisableLocalCAJWT).(bool) && diff.Id() != "" { + // on Vault 1.9.3+ the K8S CA certificate is no longer stored in the Vault + // configuration when Vault is running in K8s and FieldDisableLocalCAJWT is + // false. Unfortunately, the change did not consider the Vault schema upgrade + // path and would leave a stale CA certificate in Vault config. See + // https://github.com/hashicorp/vault-plugin-auth-kubernetes/pull/122 for more + // details + // + // This bit if code will ensure the following cases are handled: + // - CA certificate in Vault config but unset in TF + // - CA certificate in Vault config and set to "" in TF + // + // If any of the above cases are detected the CA certificate configured in Vault + // will be unset upon TF apply. + meta, ok := m.(*provider.ProviderMeta) + if !ok { + return fmt.Errorf("invalid type %T", m) + } + + if s[consts.FieldKubernetesCACert].Computed && meta.GetVaultVersion().GreaterThanOrEqual(vaultVersion193) { + val, valExists := diff.GetRawConfig().AsValueMap()[consts.FieldKubernetesCACert] + o, n := diff.GetChange(consts.FieldKubernetesCACert) + if (valExists && val.IsNull() && n.(string) != "") || (o.(string) != "" && n.(string) == "") { + // trigger a diff, since we want to unset the previously computed value. + if err := diff.SetNew(consts.FieldKubernetesCACert, ""); err != nil { + return err + } + overrideKubernetesFieldsMap.Store(diff.Id()+"."+consts.FieldKubernetesCACert, "") + } + } + } + + return nil }, + + Schema: s, } } @@ -101,33 +149,33 @@ func kubernetesAuthBackendConfigCreate(d *schema.ResourceData, meta interface{}) data := map[string]interface{}{} - if v, ok := d.GetOk("kubernetes_ca_cert"); ok { - data["kubernetes_ca_cert"] = v.(string) + if v, ok := d.GetOk(consts.FieldKubernetesCACert); ok { + data[consts.FieldKubernetesCACert] = v } if v, ok := d.GetOk("token_reviewer_jwt"); ok { data["token_reviewer_jwt"] = v.(string) } - if v, ok := d.GetOkExists("pem_keys"); ok { + if v, ok := d.GetOkExists(consts.FieldPEMKeys); ok { var pemKeys []string for _, pemKey := range v.([]interface{}) { pemKeys = append(pemKeys, pemKey.(string)) } - data["pem_keys"] = strings.Join(pemKeys, ",") + data[consts.FieldPEMKeys] = strings.Join(pemKeys, ",") } - data["kubernetes_host"] = d.Get("kubernetes_host").(string) + data[consts.FieldKubernetesHost] = d.Get(consts.FieldKubernetesHost).(string) - if v, ok := d.GetOk("issuer"); ok { - data["issuer"] = v.(string) + if v, ok := d.GetOk(consts.FieldIssuer); ok { + data[consts.FieldIssuer] = v.(string) } - if v := d.Get("disable_iss_validation"); v != nil { - data["disable_iss_validation"] = v + if v := d.Get(consts.FieldDisableISSValidation); v != nil { + data[consts.FieldDisableISSValidation] = v } - if v, ok := d.GetOk("disable_local_ca_jwt"); ok { - data["disable_local_ca_jwt"] = v + if v, ok := d.GetOk(consts.FieldDisableLocalCAJWT); ok { + data[consts.FieldDisableLocalCAJWT] = v } _, err := client.Logical().Write(path, data) if err != nil { @@ -189,12 +237,12 @@ func kubernetesAuthBackendConfigRead(d *schema.ResourceData, meta interface{}) e } params := []string{ - "kubernetes_host", - "kubernetes_ca_cert", - "issuer", - "disable_iss_validation", - "disable_local_ca_jwt", - "pem_keys", + consts.FieldKubernetesCACert, + consts.FieldKubernetesHost, + consts.FieldIssuer, + consts.FieldDisableISSValidation, + consts.FieldDisableLocalCAJWT, + consts.FieldPEMKeys, } for _, k := range params { @@ -218,34 +266,40 @@ func kubernetesAuthBackendConfigUpdate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Updating Kubernetes auth backend config %q", path) data := map[string]interface{}{} + setData := func(param string, val interface{}) { + if override, ok := overrideKubernetesFieldsMap.LoadAndDelete(d.Id() + "." + param); ok { + val = override + } + data[param] = val + } - if v, ok := d.GetOk("kubernetes_ca_cert"); ok { - data["kubernetes_ca_cert"] = v.(string) + if v, ok := d.GetOk(consts.FieldKubernetesCACert); ok { + setData(consts.FieldKubernetesCACert, v) } if v, ok := d.GetOk("token_reviewer_jwt"); ok { - data["token_reviewer_jwt"] = v.(string) + setData("token_reviewer_jwt", v.(string)) } - if v, ok := d.GetOkExists("pem_keys"); ok { + if v, ok := d.GetOkExists(consts.FieldPEMKeys); ok { var pemKeys []string for _, pemKey := range v.([]interface{}) { pemKeys = append(pemKeys, pemKey.(string)) } - data["pem_keys"] = strings.Join(pemKeys, ",") + setData(consts.FieldPEMKeys, strings.Join(pemKeys, ",")) } - data["kubernetes_host"] = d.Get("kubernetes_host").(string) + setData(consts.FieldKubernetesHost, d.Get(consts.FieldKubernetesHost).(string)) - if v, ok := d.GetOk("issuer"); ok { - data["issuer"] = v.(string) + if v, ok := d.GetOk(consts.FieldIssuer); ok { + setData(consts.FieldIssuer, v.(string)) } - if v, ok := d.GetOkExists("disable_iss_validation"); ok { - data["disable_iss_validation"] = v + if v, ok := d.GetOkExists(consts.FieldDisableISSValidation); ok { + setData(consts.FieldDisableISSValidation, v) } - if v, ok := d.GetOk("disable_local_ca_jwt"); ok { - data["disable_local_ca_jwt"] = v + if v, ok := d.GetOk(consts.FieldDisableLocalCAJWT); ok { + setData(consts.FieldDisableLocalCAJWT, v) } _, err := client.Logical().Write(path, data) diff --git a/vault/resource_kubernetes_auth_backend_config_test.go b/vault/resource_kubernetes_auth_backend_config_test.go index 67e947245..b1e193dc2 100644 --- a/vault/resource_kubernetes_auth_backend_config_test.go +++ b/vault/resource_kubernetes_auth_backend_config_test.go @@ -12,13 +12,15 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/internal/provider" "github.com/hashicorp/terraform-provider-vault/testutil" ) const ( - kubernetesJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWF1dGgtdmF1bHQtb3BlcmF0b3IiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoia3ViZXJuZXRlcy1hdXRoLXZhdWx0LW9wZXJhdG9yLXRva2VuLWZycmc3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Imt1YmVybmV0ZXMtYXV0aC12YXVsdC1vcGVyYXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjMwYzRiZjdkLTMwZmYtMTFlOC04ODdkLTA4MDAyNzZhYmI4OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWF1dGgtdmF1bHQtb3BlcmF0b3I6a3ViZXJuZXRlcy1hdXRoLXZhdWx0LW9wZXJhdG9yIn0.V6lWrH6rgNfghn5Qc9IdPwxrAV0E8cdVNvGh3KmVCZpZVwOnL4eCQ3R6V37pO7ssTs-0aYYWc2NYcGnLiXvUPah89uK2wkE_Eod3NgWDqlutcM-LJuIK6xubuH0y2Bpb7ZddZmtc5MOa8e88iwiZmQ_zKhifwESdwFWaA5Nn1QNzwIPu2kOZU0Wz9sVN4i_NETUGqaEQYVU6DF--gErCLeloUDERW-QyrCRZ-ymTFt7UWRiPi3zAZ0-BG8j4TsjNYLiifGiMiaD6Ss-pd0brVMzQylpVlnZ7Of6ywIv-BWVa278ki3cd1RMqQj8tzHNg2tlbBSLMn92Gxh16jBW90w" - kubernetesAnotherJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tNzhsNXAiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjUzZjZhY2Y5LTMwZmEtMTFlOC04ODdkLTA4MDAyNzZhYmI4OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.pM5ugxaTX22vBsb4IOUz-pgwKM_ZfhgFhS1PKfpcSJYs4h-C4OujjKpF8j-Lw5oxaHOIxbROUxurlh-9eqvYqKREQOVxZvhoqxiflWCuAtu4RxHI-x4COSqV0H7pc_JNnDbgEqBhbFW1UiKfoye3QiqiqwYBaxvdpyH3uarv5yi26FT2lNvy6rHWMaMg3VZLzbZPOPY-v1C0RUbiyCz100A2UvaU5QbdHfwFab18vqgB_FN4aFXP9TKrcDUPyFyAhoC6h4Tb_ounuQ1u8UWtLL_KwDK7KEAgwg-FfayzHtw41PneS9nNtNm7bZJsLtzsvSzuMJpwehnN1GtUCMvDzA" + kubernetesJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWF1dGgtdmF1bHQtb3BlcmF0b3IiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoia3ViZXJuZXRlcy1hdXRoLXZhdWx0LW9wZXJhdG9yLXRva2VuLWZycmc3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Imt1YmVybmV0ZXMtYXV0aC12YXVsdC1vcGVyYXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjMwYzRiZjdkLTMwZmYtMTFlOC04ODdkLTA4MDAyNzZhYmI4OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlcm5ldGVzLWF1dGgtdmF1bHQtb3BlcmF0b3I6a3ViZXJuZXRlcy1hdXRoLXZhdWx0LW9wZXJhdG9yIn0.V6lWrH6rgNfghn5Qc9IdPwxrAV0E8cdVNvGh3KmVCZpZVwOnL4eCQ3R6V37pO7ssTs-0aYYWc2NYcGnLiXvUPah89uK2wkE_Eod3NgWDqlutcM-LJuIK6xubuH0y2Bpb7ZddZmtc5MOa8e88iwiZmQ_zKhifwESdwFWaA5Nn1QNzwIPu2kOZU0Wz9sVN4i_NETUGqaEQYVU6DF--gErCLeloUDERW-QyrCRZ-ymTFt7UWRiPi3zAZ0-BG8j4TsjNYLiifGiMiaD6Ss-pd0brVMzQylpVlnZ7Of6ywIv-BWVa278ki3cd1RMqQj8tzHNg2tlbBSLMn92Gxh16jBW90w" + kubernetesAnotherJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tNzhsNXAiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjUzZjZhY2Y5LTMwZmEtMTFlOC04ODdkLTA4MDAyNzZhYmI4OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.pM5ugxaTX22vBsb4IOUz-pgwKM_ZfhgFhS1PKfpcSJYs4h-C4OujjKpF8j-Lw5oxaHOIxbROUxurlh-9eqvYqKREQOVxZvhoqxiflWCuAtu4RxHI-x4COSqV0H7pc_JNnDbgEqBhbFW1UiKfoye3QiqiqwYBaxvdpyH3uarv5yi26FT2lNvy6rHWMaMg3VZLzbZPOPY-v1C0RUbiyCz100A2UvaU5QbdHfwFab18vqgB_FN4aFXP9TKrcDUPyFyAhoC6h4Tb_ounuQ1u8UWtLL_KwDK7KEAgwg-FfayzHtw41PneS9nNtNm7bZJsLtzsvSzuMJpwehnN1GtUCMvDzA" + envVarTFAccK8sSkipInCluster = "TF_ACC_K8S_SKIP_IN_CLUSTER" ) const kubernetesCAcert = `-----BEGIN CERTIFICATE----- @@ -72,8 +74,6 @@ func TestAccKubernetesAuthBackendConfig_import(t *testing.T) { backend := acctest.RandomWithPrefix("kubernetes") jwt := kubernetesJWT issuer := "kubernetes/serviceaccount" - disableIssValidation := false - disableLocalCaJwt := false resource.Test(t, resource.TestCase{ PreCheck: func() { testutil.TestAccPreCheck(t) }, @@ -81,14 +81,15 @@ func TestAccKubernetesAuthBackendConfig_import(t *testing.T) { CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, Steps: []resource.TestStep{ { - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, jwt, issuer, disableIssValidation, disableLocalCaJwt), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, jwt, issuer, + false, false, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -96,11 +97,11 @@ func TestAccKubernetesAuthBackendConfig_import(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.#", "1"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", issuer), + consts.FieldIssuer, issuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(disableIssValidation)), + consts.FieldDisableISSValidation, strconv.FormatBool(false)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(disableLocalCaJwt)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), ), }, { @@ -116,9 +117,9 @@ func TestAccKubernetesAuthBackendConfig_import(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), ), @@ -149,9 +150,9 @@ func TestAccKubernetesAuthBackendConfig_basic(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), ), @@ -198,9 +199,9 @@ func TestAccKubernetesAuthBackendConfig_update(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", oldJWT), ), @@ -211,9 +212,9 @@ func TestAccKubernetesAuthBackendConfig_update(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", newJWT), ), @@ -226,8 +227,6 @@ func TestAccKubernetesAuthBackendConfig_full(t *testing.T) { backend := acctest.RandomWithPrefix("kubernetes") jwt := kubernetesJWT issuer := "api" - disableIssValidation := true - disableLocalCaJwt := true resource.Test(t, resource.TestCase{ PreCheck: func() { testutil.TestAccPreCheck(t) }, @@ -235,14 +234,15 @@ func TestAccKubernetesAuthBackendConfig_full(t *testing.T) { CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, Steps: []resource.TestStep{ { - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, jwt, issuer, disableIssValidation, disableLocalCaJwt), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, jwt, issuer, + true, true, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -250,11 +250,11 @@ func TestAccKubernetesAuthBackendConfig_full(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", "api"), + consts.FieldIssuer, "api"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(disableIssValidation)), + consts.FieldDisableISSValidation, strconv.FormatBool(true)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(disableLocalCaJwt)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(true)), ), }, }, @@ -274,14 +274,15 @@ func TestAccKubernetesAuthBackendConfig_fullUpdate(t *testing.T) { CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, Steps: []resource.TestStep{ { - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, oldJWT, oldIssuer, false, false), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, oldJWT, oldIssuer, + false, false, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", oldJWT), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -289,24 +290,25 @@ func TestAccKubernetesAuthBackendConfig_fullUpdate(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", oldIssuer), + consts.FieldIssuer, oldIssuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", oldIssuer), + consts.FieldIssuer, oldIssuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(false)), + consts.FieldDisableISSValidation, strconv.FormatBool(false)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(false)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), ), }, { - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, newJWT, newIssuer, true, true), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, newJWT, newIssuer, + true, true, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", newJWT), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -314,23 +316,24 @@ func TestAccKubernetesAuthBackendConfig_fullUpdate(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", newIssuer), + consts.FieldIssuer, newIssuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(true)), + consts.FieldDisableISSValidation, strconv.FormatBool(true)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(true)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(true)), ), }, { // ensure we can set disable_iss_validation to false - Config: testAccKubernetesAuthBackendConfigConfig_full(backend, newJWT, newIssuer, false, true), + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, newJWT, newIssuer, + false, true, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", newJWT), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", @@ -338,11 +341,11 @@ func TestAccKubernetesAuthBackendConfig_fullUpdate(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "pem_keys.0", kubernetesPEMfile), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "issuer", newIssuer), + consts.FieldIssuer, newIssuer), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_iss_validation", strconv.FormatBool(false)), + consts.FieldDisableISSValidation, strconv.FormatBool(false)), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "disable_local_ca_jwt", strconv.FormatBool(true)), + consts.FieldDisableLocalCAJWT, strconv.FormatBool(true)), ), }, }, @@ -356,7 +359,7 @@ func TestAccKubernetesAuthBackendConfig_localCA(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testutil.TestAccPreCheck(t) - SkipIfAPIVersionGTE(t, testProvider.Meta(), provider.VaultVersion111) + SkipIfAPIVersionGTE(t, testProvider.Meta(), vaultVersion193) }, Providers: testProviders, CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, @@ -367,9 +370,9 @@ func TestAccKubernetesAuthBackendConfig_localCA(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", ""), + consts.FieldKubernetesCACert, ""), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), ), @@ -380,9 +383,9 @@ func TestAccKubernetesAuthBackendConfig_localCA(t *testing.T) { path := kubernetesAuthBackendConfigPath(backend) if _, err := client.Logical().Write(path, map[string]interface{}{ - "kubernetes_ca_cert": kubernetesCAcert, - "kubernetes_host": "http://example.com:443", - "token_reviewer_jwt": jwt, + consts.FieldKubernetesCACert: kubernetesCAcert, + consts.FieldKubernetesHost: "http://example.com:443", + "token_reviewer_jwt": jwt, }); err != nil { t.Fatal(err) } @@ -392,9 +395,9 @@ func TestAccKubernetesAuthBackendConfig_localCA(t *testing.T) { resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "backend", backend), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_host", "http://example.com:443"), + consts.FieldKubernetesHost, "http://example.com:443"), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", - "kubernetes_ca_cert", kubernetesCAcert), + consts.FieldKubernetesCACert, kubernetesCAcert), resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", "token_reviewer_jwt", jwt), ), @@ -425,7 +428,14 @@ resource "vault_kubernetes_auth_backend_config" "config" { return config + "}" } -func testAccKubernetesAuthBackendConfigConfig_full(backend, jwt string, issuer string, disableIssValidation bool, disableLocalCaJwt bool) string { +func testAccKubernetesAuthBackendConfigConfig_full(backend, caCert, jwt, issuer string, + disableIssValidation, disableLocalCaJwt, omitCA bool, +) string { + var caConfig string + if !omitCA { + caConfig = fmt.Sprintf(`kubernetes_ca_cert = %q`, caCert) + } + config := fmt.Sprintf(` resource "vault_auth_backend" "kubernetes" { type = "kubernetes" @@ -435,13 +445,222 @@ resource "vault_auth_backend" "kubernetes" { resource "vault_kubernetes_auth_backend_config" "config" { backend = vault_auth_backend.kubernetes.path kubernetes_host = "http://example.com:443" - kubernetes_ca_cert = %q + %s token_reviewer_jwt = %q pem_keys = [%q] issuer = %q disable_iss_validation = %t disable_local_ca_jwt = %t -}`, backend, kubernetesCAcert, jwt, kubernetesPEMfile, issuer, disableIssValidation, disableLocalCaJwt) +}`, backend, caConfig, jwt, kubernetesPEMfile, issuer, disableIssValidation, disableLocalCaJwt) return config } + +func testAccKubernetesAuthBackendConfigConfig_fullUnsetCA(backend, jwt, issuer string, disableIssValidation, disableLocalCaJwt bool) string { + config := fmt.Sprintf(` +resource "vault_auth_backend" "kubernetes" { + type = "kubernetes" + path = "%s" +} + +resource "vault_kubernetes_auth_backend_config" "config" { + backend = vault_auth_backend.kubernetes.path + kubernetes_host = "http://example.com:443" + token_reviewer_jwt = %q + pem_keys = [%q] + issuer = %q + disable_iss_validation = %t + disable_local_ca_jwt = %t +}`, backend, jwt, kubernetesPEMfile, issuer, disableIssValidation, disableLocalCaJwt) + + return config +} + +func TestAccKubernetesAuthBackendConfig_fullInK8sCluster(t *testing.T) { + backend := acctest.RandomWithPrefix("kubernetes") + oldJWT := kubernetesJWT + // newJWT := kubernetesAnotherJWT + oldIssuer := "kubernetes/serviceaccount" + // newIssuer := "api" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testutil.TestAccPreCheck(t) + testutil.SkipTestEnvSet(t, envVarTFAccK8sSkipInCluster) + SkipIfAPIVersionLT(t, testProvider.Meta(), vaultVersion193) + }, + Providers: testProviders, + CheckDestroy: testAccCheckKubernetesAuthBackendConfigDestroy, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, "", oldJWT, oldIssuer, + false, false, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + { + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, oldJWT, oldIssuer, + false, false, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, kubernetesCAcert), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + { + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, "", oldJWT, oldIssuer, + false, false, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + { + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, "", oldJWT, oldIssuer, + false, false, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + { + PreConfig: func() { + client := testProvider.Meta().(*provider.ProviderMeta).GetClient() + + path := kubernetesAuthBackendConfigPath(backend) + // mimic pre vault-1.9.3 behaviour, whereby the in-cluster K8s CA was stored in + // Vault config. + if _, err := client.Logical().Write(path, map[string]interface{}{ + consts.FieldKubernetesCACert: kubernetesCAcert, + consts.FieldKubernetesHost: "http://example.com:443", + }); err != nil { + t.Fatal(err) + } + }, + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, "", oldJWT, oldIssuer, + false, false, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + { + Config: testAccKubernetesAuthBackendConfigConfig_full(backend, kubernetesCAcert, oldJWT, oldIssuer, + false, false, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "backend", backend), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesHost, "http://example.com:443"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldKubernetesCACert, kubernetesCAcert), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "token_reviewer_jwt", oldJWT), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.#", "1"), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + "pem_keys.0", kubernetesPEMfile), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldIssuer, oldIssuer), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableISSValidation, strconv.FormatBool(false)), + resource.TestCheckResourceAttr("vault_kubernetes_auth_backend_config.config", + consts.FieldDisableLocalCAJWT, strconv.FormatBool(false)), + ), + }, + }, + }) +} diff --git a/vault/resource_kubernetes_secret_backend.go b/vault/resource_kubernetes_secret_backend.go index a5f76f403..7dd917fae 100644 --- a/vault/resource_kubernetes_secret_backend.go +++ b/vault/resource_kubernetes_secret_backend.go @@ -16,13 +16,6 @@ import ( "github.com/hashicorp/terraform-provider-vault/util" ) -const ( - fieldKubernetesHost = "kubernetes_host" - fieldKubernetesCACert = "kubernetes_ca_cert" - fieldServiceAccountJWT = "service_account_jwt" - fieldDisableLocalCAJWT = "disable_local_ca_jwt" -) - func kubernetesSecretBackendResource() *schema.Resource { resource := &schema.Resource{ CreateContext: provider.MountCreateContextWrapper(kubernetesSecretBackendCreateUpdate, provider.VaultVersion111), @@ -33,19 +26,19 @@ func kubernetesSecretBackendResource() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, Schema: map[string]*schema.Schema{ - fieldKubernetesHost: { + consts.FieldKubernetesHost: { Type: schema.TypeString, Description: "The Kubernetes API URL to connect to.", Optional: true, }, - fieldKubernetesCACert: { + consts.FieldKubernetesCACert: { Type: schema.TypeString, Description: "A PEM-encoded CA certificate used by the secret engine to " + "verify the Kubernetes API server certificate. Defaults to the " + "local pod’s CA if found, or otherwise the host's root CA set.", Optional: true, }, - fieldServiceAccountJWT: { + consts.FieldServiceAccountJWT: { Type: schema.TypeString, Description: "The JSON web token of the service account used by the " + "secrets engine to manage Kubernetes credentials. Defaults to the " + @@ -53,7 +46,7 @@ func kubernetesSecretBackendResource() *schema.Resource { Optional: true, Sensitive: true, }, - fieldDisableLocalCAJWT: { + consts.FieldDisableLocalCAJWT: { Type: schema.TypeBool, Description: "Disable defaulting to the local CA certificate and service " + "account JWT when running in a Kubernetes pod.", @@ -91,9 +84,9 @@ func kubernetesSecretBackendCreateUpdate(ctx context.Context, d *schema.Resource data := make(map[string]interface{}) fields := []string{ - fieldKubernetesCACert, - fieldServiceAccountJWT, - fieldDisableLocalCAJWT, + consts.FieldKubernetesCACert, + consts.FieldServiceAccountJWT, + consts.FieldDisableLocalCAJWT, } for _, k := range fields { if d.HasChange(k) { @@ -104,7 +97,7 @@ func kubernetesSecretBackendCreateUpdate(ctx context.Context, d *schema.Resource // kubernetes_host always needs to be provided on configuration updates. // Otherwise, an error will occur if the KUBERNETES_SERVICE_HOST and // KUBERNETES_SERVICE_PORT_HTTPS environment variables aren't set. - data[fieldKubernetesHost] = d.Get(fieldKubernetesHost) + data[consts.FieldKubernetesHost] = d.Get(consts.FieldKubernetesHost) configPath := fmt.Sprintf("%s/config", path) if _, err := client.Logical().Write(configPath, data); err != nil { @@ -136,9 +129,9 @@ func kubernetesSecretBackendRead(_ context.Context, d *schema.ResourceData, meta // fieldServiceAccountJWT can't be read from the API // and is intentionally omitted from this list fields := []string{ - fieldKubernetesHost, - fieldKubernetesCACert, - fieldDisableLocalCAJWT, + consts.FieldKubernetesHost, + consts.FieldKubernetesCACert, + consts.FieldDisableLocalCAJWT, } for _, k := range fields { if err := d.Set(k, resp.Data[k]); err != nil { diff --git a/vault/resource_kubernetes_secret_backend_role_test.go b/vault/resource_kubernetes_secret_backend_role_test.go index 500aa2b8a..5258800fa 100644 --- a/vault/resource_kubernetes_secret_backend_role_test.go +++ b/vault/resource_kubernetes_secret_backend_role_test.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/internal/provider" "github.com/hashicorp/terraform-provider-vault/testutil" @@ -81,7 +82,7 @@ func TestAccKubernetesSecretBackendRole(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{fieldServiceAccountJWT}, + ImportStateVerifyIgnore: []string{consts.FieldServiceAccountJWT}, }, }, }) diff --git a/vault/resource_kubernetes_secret_backend_test.go b/vault/resource_kubernetes_secret_backend_test.go index cda9f51da..808413e06 100644 --- a/vault/resource_kubernetes_secret_backend_test.go +++ b/vault/resource_kubernetes_secret_backend_test.go @@ -37,9 +37,9 @@ func TestAccKubernetesSecretBackend(t *testing.T) { resource.TestCheckResourceAttr(resourceName, consts.FieldAuditNonHMACResponseKeys+".#", "0"), resource.TestCheckResourceAttr(resourceName, consts.FieldSealWrap, "false"), resource.TestCheckResourceAttr(resourceName, consts.FieldExternalEntropyAccess, "false"), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesHost, ""), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesCACert, ""), - resource.TestCheckResourceAttr(resourceName, fieldDisableLocalCAJWT, "false"), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesHost, ""), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr(resourceName, consts.FieldDisableLocalCAJWT, "false"), ), }, { @@ -54,9 +54,9 @@ func TestAccKubernetesSecretBackend(t *testing.T) { resource.TestCheckResourceAttr(resourceName, consts.FieldAuditNonHMACResponseKeys+".0", "test_res"), resource.TestCheckResourceAttr(resourceName, consts.FieldSealWrap, "true"), resource.TestCheckResourceAttr(resourceName, consts.FieldExternalEntropyAccess, "true"), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesHost, ""), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesCACert, ""), - resource.TestCheckResourceAttr(resourceName, fieldDisableLocalCAJWT, "false"), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesHost, ""), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesCACert, ""), + resource.TestCheckResourceAttr(resourceName, consts.FieldDisableLocalCAJWT, "false"), ), }, { @@ -71,16 +71,16 @@ func TestAccKubernetesSecretBackend(t *testing.T) { resource.TestCheckResourceAttr(resourceName, consts.FieldAuditNonHMACResponseKeys+".#", "0"), resource.TestCheckResourceAttr(resourceName, consts.FieldSealWrap, "false"), resource.TestCheckResourceAttr(resourceName, consts.FieldExternalEntropyAccess, "false"), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesHost, "https://127.0.0.1:63247"), - resource.TestCheckResourceAttr(resourceName, fieldKubernetesCACert, "test_ca_cert"), - resource.TestCheckResourceAttr(resourceName, fieldDisableLocalCAJWT, "true"), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesHost, "https://127.0.0.1:63247"), + resource.TestCheckResourceAttr(resourceName, consts.FieldKubernetesCACert, "test_ca_cert"), + resource.TestCheckResourceAttr(resourceName, consts.FieldDisableLocalCAJWT, "true"), ), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{fieldServiceAccountJWT}, + ImportStateVerifyIgnore: []string{consts.FieldServiceAccountJWT}, }, }, }) diff --git a/vault/resource_quota_rate_limit.go b/vault/resource_quota_rate_limit.go index 0d0c55cb6..5308e9f0b 100644 --- a/vault/resource_quota_rate_limit.go +++ b/vault/resource_quota_rate_limit.go @@ -9,8 +9,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/hashicorp/terraform-provider-vault/internal/consts" + "github.com/hashicorp/terraform-provider-vault/internal/consts" "github.com/hashicorp/terraform-provider-vault/internal/provider" )