terraform-provider-vault icon indicating copy to clipboard operation
terraform-provider-vault copied to clipboard

[Bug]: MFA resources imported with missing namespace

Open tdy-jbowdre opened this issue 2 years ago • 0 comments

Terraform Core Version

1.5.4

Terraform Vault Provider Version

3.20.1

Vault Server Version

1.14.0+ent

Affected Resource(s)

  • vault_identity_mfa_duo.duo
  • vault_identity_mfa_login_enforcement.duo

Expected Behavior

Importing a namespaced MFA resource should correctly populate the namespace field in the state file.

Ex:

{
  "mode": "managed",
  "type": "vault_identity_mfa_duo",
  "name": "duo",
  "provider": "provider[\"registry.terraform.io/hashicorp/vault\"]",
  "instances": [
    {
      "schema_version": 0,
      "attributes": {
        [],
        "namespace": "testing",
        "namespace_id": "R1UD8",
        "namespace_path": "sandbox/testing/",
        [],
      },
      [],
    }
  ]
}

Actual Behavior

The resource is imported with "namespace": null:

{
  "mode": "managed",
  "type": "vault_identity_mfa_duo",
  "name": "duo",
  "provider": "provider[\"registry.terraform.io/hashicorp/vault\"]",
  "instances": [
    {
      "schema_version": 0,
      "attributes": {
        [],
        "namespace": null,
        "namespace_id": "R1UD8",
        "namespace_path": "sandbox/testing/",
        [],
      },
      [],
    }
  ]
}

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

terraform {
  required_providers {
    vault = "~> 3.20.0"
  }
}

provider "vault" {
  namespace = "sandbox"
}

resource "vault_namespace" "testing" {
  path = testing
}

resource "vault_ldap_auth_backend" "ldap" {
  namespace        = "sandbox/testing"
  path             = "ldap"
  url              = var.ldap_url
  groupdn          = var.ldap_group_search_base
}

resource "vault_identity_mfa_duo" "duo" {
  namespace       = "sandbox/testing"
  integration_key = var.duo_integration_key
  secret_key      = var.duo_secret_key
  api_hostname    = var.duo_api_host
}

resource "vault_identity_mfa_login_enforcement" "duo" {
  namespace = "sandbox/testing"
  name      = var.duo_mfa_name
  mfa_method_ids = [
    vault_identity_mfa_duo.duo.id
  ]
  auth_method_accessors = [
    vault_ldap_auth_backend.ldap.accessor
  ]
}

Steps to Reproduce

  1. terraform init
  2. terraform apply
  3. Capture the ID of the created MFA method:
terraform state show vault_identity_mfa_duo.duo | grep ' id '
    id              = "cb8e59d3-bd3a-ebbf-87a5-f2387434f41e"
  1. Remove MFA resources from the state:
terraform state rm vault_identity_mfa_duo.duo
terraform state rm vault_identity_mfa_login_enforcement.duo
  1. Import MFA resources:
# reference child namespace since the parent is defined in the provider
TERRAFORM_VAULT_NAMESPACE_IMPORT=testing terraform import vault_identity_mfa_duo.duo cb8e59d3-bd3a-ebbf-87a5-f2387434f41e
TERRAFORM_VAULT_NAMESPACE_IMPORT=testing terraform import vault_identity_mfa_login_enforcement.duo EnforceDuo

Result: resources import successfully, but the state file is missing the namespace field for each resource (despite having the correct namespace_id and namespace_path info).

From that point, terraform plan indicates that it would replace the existing vault_identity_mfa_duo.duo resource (since changing the namespace forces replacement) and create a duplicate vault_identity_mfa_login_enforcement.duo:

terraform plan
[...]

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # vault_identity_mfa_duo.duo must be replaced
-/+ resource "vault_identity_mfa_duo" "duo" {
      ~ id              = "cb8e59d3-bd3a-ebbf-87a5-f2387434f41e" -> (known after apply)
      + integration_key = (sensitive value)
      ~ method_id       = "cb8e59d3-bd3a-ebbf-87a5-f2387434f41e" -> (known after apply)
      + mount_accessor  = (known after apply)
      + name            = (known after apply)
      + namespace       = "testing" # forces replacement
      ~ namespace_id    = "R1UD8" -> (known after apply)
      ~ namespace_path  = "sandbox/testing/" -> (known after apply)
      + secret_key      = (sensitive value)
      ~ type            = "duo" -> (known after apply)
      ~ uuid            = "cb8e59d3-bd3a-ebbf-87a5-f2387434f41e" -> (known after apply)
        # (3 unchanged attributes hidden)
    }

  # vault_identity_mfa_login_enforcement.duo will be created
  + resource "vault_identity_mfa_login_enforcement" "duo" {
      + auth_method_accessors = [
          + "auth_ldap_4c6a26fb",
        ]
      + id                    = (known after apply)
      + mfa_method_ids        = (known after apply)
      + name                  = "EnforceDuo"
      + namespace             = "testing"
      + namespace_id          = (known after apply)
      + namespace_path        = (known after apply)
      + uuid                  = (known after apply)
    }

Plan: 2 to add, 0 to change, 1 to destroy.

terraform apply fails, seemingly because it is unable to remove/replace the existing vault_identity_mfa_duo.duo resource which is linked to the existing login enforcement:

vault_identity_mfa_duo.duo: Destroying... [id=cb8e59d3-bd3a-ebbf-87a5-f2387434f41e]
╷
│ Error: Error making API request.
│ 
│ Namespace: sandbox
│ URL: DELETE https://vault.example.com/v1/identity/mfa/method/duo/cb8e59d3-bd3a-ebbf-87a5-f2387434f41e
│ Code: 500. Errors:
│ 
│ * 1 error occurred:
│       * methodID is still used by an enforcement configuration with ID: 798fbda8-83cb-d8a6-6fe4-f69fa8dd1a69

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

No

tdy-jbowdre avatar Sep 27 '23 18:09 tdy-jbowdre