Azure Container Apps using key vault secrets

750 Views Asked by At

I'd like to use Azure Container Apps (ACA) and avoid AKS management

my understanding is that I can create an Azure Container App Environment (ACE) in TF without creating any ACA instances. Then I could use the AzureContainerApps@1 task to deploy my containers to the ACE.

assuming this is all correct, I'm still struggling with how I get secrets from my Key Vault into my ACA instance.

I'm reading store-secret-value-in-container-apps and I noticed they don't even show an option for using the ADO task.

Is what I'm trying to do possible? Where are some decent docs?

TL/DR - I'm really trying to avoid defining my ACA Instance(s) in Terraform. TF is a tool for creating infrastructure.... NOT managing deployments

1

There are 1 best solutions below

4
On

If it is suitable for you to use a Dapr component to link your (Azure Container) App to Key Vault, you would define your infrastructure like this:

https://github.com/dapr-in-prod/samples/tree/main/chapter-2/infra/aca-terraform

A Dapr component to reference Key Vault:

resource "azurerm_container_app_environment_dapr_component" "dapr_component_secretstore" {
  name                         = "secretstore"
  container_app_environment_id = module.aca.CONTAINER_APP_ENV_ID
  component_type               = "secretstores.azure.keyvault"
  version                      = "v1"
  metadata {
    name  = "vaultName"
    value = module.keyvault.KEYVAULT_NAME
  }
  metadata {
    name  = "spnClientId"
    value = module.keyvault.KEYVAULT_CONSUMER_CLIENT_ID
  }
}

A Key Vault with a consumer identity assigned:

data "azurerm_client_config" "current" {}

resource "azurerm_key_vault" "kv" {
  name                = "${var.resource_prefix}-kv"
  resource_group_name = var.resource_group_name
  location            = var.location
  tags                = var.tags

  sku_name = "standard"

  tenant_id                  = data.azurerm_client_config.current.tenant_id
  soft_delete_retention_days = var.soft_delete_retention_days
  purge_protection_enabled   = var.purge_protection_enabled
  enable_rbac_authorization  = true
}

resource "azurerm_user_assigned_identity" "kv_consumer_identity" {
  name                = "${var.resource_prefix}-kvconsumer"
  resource_group_name = var.resource_group_name
  location            = var.location
  tags                = var.tags
}

resource "azurerm_role_assignment" "kv_consumer_assignment" {
  principal_id         = azurerm_user_assigned_identity.kv_consumer_identity.principal_id
  role_definition_name = "Key Vault Secrets User"
  scope                = azurerm_key_vault.kv.id
}

A separate App deployment with what ever you choose (e.g. Azure CLI) which binds the consumer identity to the App https://github.com/dapr-in-prod/samples/blob/main/chapter-2/apps/simple-js/aca-deploy.sh:

    az containerapp create -n $APP_NAME -g $RESOURCE_GROUP \
        --environment $ACA_NAME \
        --min-replicas 1 --max-replicas 1 \
        --registry-server $ACR_LOGIN_SERVER --registry-identity $ACR_PULL_ID \
        --user-assigned $KV_CONSUMER_ID \
        --ingress external --target-port 5001 \
        --enable-dapr --dapr-app-id $APP_NAME --dapr-app-port 5001 \
        --image $IMAGE \
        --revision-suffix ts$REVISION

Then you could use a secret simply like in https://github.com/dapr-in-prod/samples/blob/main/chapter-2/apps/simple-js/index.js:

app.get('/show-secret', async (req, res) => {
    let port = process.env.DAPR_HTTP_PORT ?? daprPortDefault;
    let url = `http://${daprHost}:${port}/v1.0/secrets/secretstore/simple-js-secret`;
    console.log(url);
    try {
        let secret_response = await fetch(url);
        let secret = await secret_response.json();
        return res.status(200).send(secret);
    } catch (error) {
        console.log(error);
    }    
});

Even if you would not want to use Dapr, the elements in the repository shown should give you a general idea on how to link and consume KV secrets in an Azure Container App.