hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.58k stars 4.62k forks source link

Support for key vault reference secrets in container apps #21739

Closed GurliGebis closed 6 months ago

GurliGebis commented 1 year ago

Is there an existing issue for this?

Community Note

Description

Microsoft has added support (in public preview) for referencing key vault secrets inside Container Apps, so the secret value is read from there. Since the Azure CLI and ARM templates can do this, the API's we are calling should be able to handle the setup. Right now you can change the secret in the container app after it has been created, to point to the key vault secret, but the next time any changes is deployed from terraform, it is changed back to a normal secret, and the values is stored in there.

New or Affected Resource(s)/Data Source(s)

azurerm_container_app

Potential Terraform Configuration

resource "azurerm_container_app_environment" "environment" {
  name                         = "my_environment"
  resource_group_name          = var.resource_group_name
  location                     = var.resource_group_location
  log_analytics_workspace_id   = var.workspace_id
}

data "azurerm_key_vault" "vault" {
  name                = "mykeyvault"
  resource_group_name = var.resource_group_name
}

data "azurerm_key_vault_secret" "my_secret" {
  name         = "my-secret"
  key_vault_id = data.azurerm_key_vault.vault.id
}

resource "azurerm_container_app" "app" {
  name                         = "app"
  container_app_environment_id = azurerm_container_app_environment.environment.id
  resource_group_name          = var.resource_group_name
  revision_mode                = "Single"

  secret {
    name  = "my-secret"
    keyvault_secret_id = data.azurerm_key_vault_secret.my_secret.resource_id
    keyvault_identity_id = var.identity_id
  }

  template {
    container {
      name   = "app"
      image  = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
      cpu    = 0.25
      memory = "0.5Gi"

      env {
        name = "MY_SECRET"
        secret_name = "my-secret"
      }
    }

    min_replicas = 1
    max_replicas = 1
  }

  identity {
    type = "UserAssigned"
    identity_ids = [ var.identity_id ]
  }
}

References

No response

hfalk commented 1 year ago

Bump

davegodbold commented 1 year ago

I am interested in working on a change for this.

sambowenhughes commented 1 year ago

+1 for this

paulh-utilita commented 1 year ago

Sadly this is something I would be highly interested in seeing enabled too. Currently only doing a Proof of Concept for Container Apps at present and I did do a nasty workaround for this which as you can imagine is far from ideal but it did feed through and the container app was able to use it;

secret { name = "mysql-example-pw" value = azurerm_key_vault_secret.tf_example_kv_mysql_pw.value }

so the value of the secret can go through but it does mean that folks can see that within the Container App under secrets just revealing that. Again, far from the best in the world as a workaround, fine for POC but very uneasy for anything production. Unsure if this is something MS have to update to allow first before then Hashicorp updates the provider.

philwelz commented 1 year ago

is there any ETA for this since its GA now @katbyte @tombuildsstuff @jackofallops ?

hikerninja commented 1 year ago

I would suggest also allowing:

keyvault_secret_uri = <secret url (i.e. https://my-keyvault.vault.azure.net/secrets/my-secret)>

DenisBalan commented 1 year ago

Any ETA on this? as this is highly recomended from security point of view.

alexpovel commented 1 year ago

So, for azure terraform container app key vault, Google actually spits out a Medium article (and the present issue only as a second result). Has anyone given what's mentioned in that article a shot? Don't think it works but would like some outside confirmation (missing the forest for the trees and all that).

It suggests:

resource "azurerm_container_app" "app" {
  # ...
  # Other definitions omitted
  # ...
  secret { 
    name  = "some-secret"
    value = "${data.azurerm_key_vault.some_vault.vault_uri}/secrets/some-secret"
  }
}

That definition will show up, of course, as a "Container Apps Secret" in the Azure portal:

image

Its value will be along the lines of https://some-vault.vault.azure.net/secrets/some-secret. When this is handed to an environment variable via:

      env {
        name        = "SOME_SECRET"
        secret_name = "some-secret"
      }

that variable's value will predictably be the above URL, and not the reference it's pointing to.

Unsurprising, but the reason I still gave it a shot was because when manually defining a secret using a Key Vault reference, one can "click to show value" in the UI and the revealed value is identical to the above URL. So two secrets, one as a direct, "Container App Secret", the other as a "Key Vault reference", will have identical values when revealed in the UI. Only in the eventual runtime, the reference secret will have its pointer dereferenced, and the secret value from the key vault is inserted. (I was hoping this could work when faking it manually too, exploiting some mechanism where the URL is detected etc.)

So... am I missing something, or does that article simply have good SEO but just... doesn't work?

EDIT: related issues: https://github.com/microsoft/azure-container-apps/issues/528 , https://github.com/microsoft/azure-container-apps/issues/7

alexpovel commented 1 year ago

As for workarounds, the one of @paulh-utilita works but as they themselves mention has a couple drawbacks:

I realize we're in azurerm, but as having a proper key vault reference secret is so important, another workaround to achieve that is using azapi_update_resource. So create azurerm_container_app as usual, then afterwards do something along the lines of:

resource "azapi_update_resource" "containerapp_secret" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = azurerm_container_app.app.id

  body = jsonencode({
    properties = {
      configuration = {
        secrets = [
          # https://learn.microsoft.com/en-us/rest/api/containerapps/stable/container-apps/create-or-update?tabs=HTTP#secret
          {
            name        = "some-secret"
            # `vault_uri` has trailing slash already; putting an extra one (aka `/secrets`) will error out.
            keyVaultUrl = "${azurerm_key_vault.some_vault.vault_uri}secrets/some-secret"
            identity    = azurerm_user_assigned_identity.some_identity.id
          }
        ]
      }
    }
  })
}

That might be enough for some use cases. It gets more complicated for the common use case of exposing that secret in an environment variable. That cannot be done until the secret exists, so another step after the above is needed (recreating the container template with the correct env). While playing around, one might also run into:

Error: cannot remove secrets from Container Apps at this time due to a limitation in the Container Apps Service

from https://github.com/microsoft/azure-container-apps/issues/395 , or (unrelated to this issue, but an issue with azurerm_container_app in general) https://github.com/hashicorp/terraform-provider-azurerm/issues/20435 .

It gets ugly quickly, with circular-ish references, state getting messed up etc. I ended up creating the entire shebang in azapi entirely for this reason.

dss010101 commented 1 year ago

This issue really causes some major issues if you are unlucky to encounter it it requires manually destroying the resource in order to do anything with terraform going forth....as such I feel this should be a high priority item

ArenHarut commented 1 year ago

I am having similar issue too. I think overall container apps offering is a good service, but this is a real dealbreaker guys. Please add this feature because it allows secrets not to be exposed via container apps dashboard. Key Valut has it's own access policy and it is being managed separately. Doing this with ARM or via some other way is not convenient at all.

ravick4u commented 1 year ago

Is this still an issue? Based on https://github.com/microsoft/azure-container-apps/issues/528, this feature have already been included in the azure.

GurliGebis commented 1 year ago

Is this still an issue? Based on microsoft/azure-container-apps#528, this feature have already been included in the azure.

Yes, Azure support it now, but terraform is unable to manage secrets like this.

Blind-Watchmaker commented 1 year ago
Error: cannot remove secrets from Container Apps at this time due to a limitation in the Container Apps Service

I also experience this issue right now when I try to destroy my Container App with Terraform. I use something like:

resource "azurerm_container_app" "container_app" {
  container_app_environment_id = var.container_app_environment_id
  name                         = var.name
  resource_group_name          = var.resource_group
  revision_mode                = var.revision_mode

  template {
    container {
      name   = var.container_name
      image  = var.container_image
      cpu    = var.container_cpu
      memory = var.container_memory
    }
  }

  ingress {
    allow_insecure_connections = var.ingress_allow_insecure_connections
    external_enabled           = var.ingress_external_enabled
    target_port                = var.ingress_target_port
    traffic_weight {
      latest_revision = var.ingress_traffic_weight_latest_revision
      percentage      = var.ingress_traffic_weight_percentage
    }
  }

  identity {
    type = var.identity_type
  }

  tags = var.tags
}
GurliGebis commented 1 year ago

@Blind-Watchmaker that is another issue, if you search in here, you will find the issue for it. The bug it is working around has been fixed by Microsoft, so the AzureRM terraform provider just needs to have the block removed (but again, that is for another issue, since this is related to keyvault secret references.)

leandroscardua commented 1 year ago

Good Morning Team,

Do you have any update on it?

Krusty93 commented 1 year ago

According to Microsoft doc it is implemented now.

Here's a sample using System assigned managed identity:

secrets = [{
  keyVaultUrl = "${data.azurerm_key_vault.key_vault.vault_uri}secrets/<your-secret-name>"
  identity    = "system"
  name        = "my-secret-name"
}]

If you wish, you can also use versioned secrets and user managed identities

ravick4u commented 1 year ago

@Krusty93 Did you tried this?

GurliGebis commented 1 year ago

@Krusty93 that is using the AzAPI terraform provider, not this one, so no, it is not implemented yet here

Krusty93 commented 1 year ago

@Krusty93 that is using the AzAPI terraform provider, not this one, so no, it is not implemented yet here

My bad, I didn't realize it - jumped here from a Google search. Yeah, azurerm still doesn't support it and other properties as well. Jobs neither.

MikeyT111 commented 12 months ago

Hey, is there any progress on this?

Phiph commented 11 months ago

I've just hit this roadblock too!

ryanshirley-flipdish commented 11 months ago

I'm facing the same issue also. Will make it harder for a compelling case to use Container Apps without this.

leandro-scardua commented 10 months ago

Good Evenning Team,

Do have any news when this solution will be release?

davidkarlsen commented 10 months ago

Linking to other issue as well: https://github.com/hashicorp/terraform-provider-azurerm/issues/23668

github-actions[bot] commented 5 months ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.