Terraform import not working properly for GCP crypto keys

I created some crypto-keys manually and now wanted to import them to terraform state so that it’s managed by terraform, which I did using following command which completes successfully:

$ terraform import google_kms_crypto_key.some-key some-gcp-project-id/us/some-keyring/some-key
google_kms_crypto_key.some-key: Refreshing state... [id=projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Even after the import, on doing terraform apply I am still getting resource already exists error:

Error: Error creating CryptoKey: googleapi: Error 409: CryptoKey projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key already exists.

Since this resource has been imported, I believe I shouldn’t be getting this “Error 409”. In terrform plan steps, it first destroys the existing key contents and then tries to re-create the key - which leads to error since the key already exists. Since I have already imported the key I do not want terraform to destroy the key. Why is terraform trying to destroy a key which has already been imported?

The output of terraform plan will be very relevant here - please post it.

I figured few things. I was using for_each to generate multiple keys; the parameter name = each.value . The problem was that the key_id was printed as known after apply . Because of this terraform cannot determine whether the key exists or not (since it cannot compute key_id before apply). So terraform tries to destroy the key-contents first, and then re-create the key which leads to error. Any way to get around this? To resolve this I think we would need each.value to be computed before apply (we don’t want known after apply ).

This is the relevant part of terrform plan output

# google_kms_crypto_key.some-key[1] will be destroyed
  - resource "google_kms_crypto_key" "some-key" {
      - destroy_scheduled_duration    = "86400s" -> null
      - id                            = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key" -> null
      - import_only                   = false -> null
      - key_ring                      = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring" -> null
      - labels                        = {} -> null
      - name                          = "some-key" -> null
      - purpose                       = "ENCRYPT_DECRYPT" -> null
      - rotation_period               = "2592000s" -> null
      - skip_initial_version_creation = false -> null

      - timeouts {}

      - version_template {
          - algorithm        = "GOOGLE_SYMMETRIC_ENCRYPTION" -> null
          - protection_level = "SOFTWARE" -> null

  # google_kms_crypto_key.some-key["some-key"] will be created
  + resource "google_kms_crypto_key" "some-key" {
      + destroy_scheduled_duration = (known after apply)
      + id                         = (known after apply)
      + import_only                = (known after apply)
      + key_ring                   = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring"
      + name                       = "some-key"
      + purpose                    = "ENCRYPT_DECRYPT"
      + rotation_period            = "2592000s"

      + version_template {
          + algorithm        = (known after apply)
          + protection_level = (known after apply)

Notice that the addresses that Terraform is proposing to manipulate include instance keys in brackets at the end [1] and ["some-key"].

You showed an import command which didn’t include any such instance key and so I think you’ve effectively imported into a resource instance that doesn’t exist in your configuration and so Terraform now understands that you want to destroy the object.

If that’s right then you can tell Terraform to use the new address for that existing object:

terraform state mv 'google_kms_crypto_key.some-key[1]' 'google_kms_crypto_key.some-key["some-key"]'

Terraform uses these instance addresses to bind the objects in the remote API to objects declared in your configuration, so it’s important to select the correct instance address when you are importing so Terraform will see which configuration object the remote object is supposed to belong to.

1 Like

Right. After using following import statement I am not facing this error:

terraform import google_kms_crypto_key.some-key[\"some-key\"] some-gcp-project-id/us/some-keyring/some-key