Edit

Share via


Manage secrets in Azure Container Apps

Azure Container Apps allows your application to securely store sensitive configuration values. Once secrets are defined at the application level, secured values are available to revisions in your container apps. Additionally, you can reference secured values inside scale rules. For information on using secrets with Dapr, refer to Dapr integration.

  • Secrets are scoped to an application, outside of any specific revision of an application.
  • Adding, removing, or changing secrets doesn't generate new revisions.
  • Each application revision can reference one or more secrets.
  • Multiple revisions can reference the same secret(s).

An updated or deleted secret doesn't automatically affect existing revisions in your app. When a secret is updated or deleted, you can respond to changes in one of two ways:

  1. Deploy a new revision.
  2. Restart an existing revision.

Before you delete a secret, deploy a new revision that no longer references the old secret. Then deactivate all revisions that reference the secret.

Defining secrets

Secrets are defined as a set of name/value pairs. The value of each secret is specified directly or as a reference to a secret stored in Azure Key Vault.

Store secret value in Container Apps

When you define secrets through the portal, or via different command line options.

Secrets are defined at the application level in the resources.properties.configuration.secrets section.

"resources": [
{
    ...
    "properties": {
        "configuration": {
            "secrets": [
            {
                "name": "queue-connection-string",
                "value": "<MY-CONNECTION-STRING-VALUE>"
            }],
        }
    }
}

Here, a connection string to a queue storage account is declared in the secrets array. In this example, you would replace <MY-CONNECTION-STRING-VALUE> with the value of your connection string.

Reference secret from Key Vault

When you define a secret, you create a reference to a secret stored in Azure Key Vault. Container Apps automatically retrieves the secret value from Key Vault and makes it available as a secret in your container app.

To reference a secret from Key Vault, you must first enable managed identity in your container app and grant the identity access to the Key Vault secrets.

To enable managed identity in your container app, see Managed identities.

To grant access to Key Vault secrets, create an access policy in Key Vault for the managed identity you created. Enable the "Get" secret permission on this policy.

Secrets are defined at the application level in the resources.properties.configuration.secrets section.

"resources": [
{
    ...
    "properties": {
        "configuration": {
            "secrets": [
            {
                "name": "queue-connection-string",
                "keyVaultUrl": "<KEY-VAULT-SECRET-URI>",
                "identity": "system"
            }],
        }
    }
}

Here, a connection string to a queue storage account is declared in the secrets array. Its value is automatically retrieved from Key Vault using the specified identity. To use a user managed identity, replace system with the identity's resource ID.

Replace <KEY-VAULT-SECRET-URI> with the URI of your secret in Key Vault.

Note

If you're using UDR With Azure Firewall, you will need to add the AzureKeyVault service tag and the login.microsoft.com FQDN to the allow list for your firewall. Refer to configuring UDR with Azure Firewall to decide which additional service tags you need.

Key Vault secret URI and secret rotation

The Key Vault secret URI must be in one of the following formats:

  • https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931: Reference a specific version of a secret.
  • https://myvault.vault.azure.net/secrets/mysecret: Reference the latest version of a secret.

If a version isn't specified in the URI, then the app uses the latest version that exists in the key vault. When newer versions become available, the app automatically retrieves the latest version within 30 minutes. Any active revisions that reference the secret in an environment variable is automatically restarted to pick up the new value.

For full control of which version of a secret is used, specify the version in the URI.

Referencing secrets in environment variables

After declaring secrets at the application level as described in the defining secrets section, you can reference them in environment variables when you create a new revision in your container app. When an environment variable references a secret, its value is populated with the value defined in the secret.

Example

The following example shows an application that declares a connection string at the application level. This connection is referenced in a container environment variable and in a scale rule.

In this example, the application connection string is declared as queue-connection-string and becomes available elsewhere in the configuration sections.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "String"
        },
        "environment_id": {
            "type": "String"
        },
        "queue-connection-string": {
            "type": "String"
        }
    },
    "variables": {},
    "resources": [
    {
        "name": "queuereader",
        "type": "Microsoft.App/containerApps",
        "apiVersion": "2022-03-01",
        "kind": "containerapp",
        "location": "[parameters('location')]",
        "properties": {
            "managedEnvironmentId": "[parameters('environment_id')]",
            "configuration": {
                "activeRevisionsMode": "single",
                "secrets": [
                {
                    "name": "queue-connection-string",
                    "value": "[parameters('queue-connection-string')]"
                }]
            },
            "template": {
                "containers": [
                    {
                        "image": "myregistry/myQueueApp:v1",
                        "name": "myQueueApp",
                        "env": [
                            {
                                "name": "QueueName",
                                "value": "myqueue"
                            },
                            {
                                "name": "ConnectionString",
                                "secretRef": "queue-connection-string"
                            }
                        ]
                    }
                ],
                "scale": {
                    "minReplicas": 0,
                    "maxReplicas": 10,
                    "rules": [
                        {
                            "name": "myqueuerule",
                            "azureQueue": {
                                "queueName": "demoqueue",
                                "queueLength": 100,
                                "auth": [
                                    {
                                        "secretRef": "queue-connection-string",
                                        "triggerParameter": "connection"
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        }
    }]
}

Here, the environment variable named connection-string gets its value from the application-level queue-connection-string secret. Also, the Azure Queue Storage scale rule's authentication configuration uses the queue-connection-string secret as to define its connection.

To avoid committing secret values to source control with your ARM template, pass secret values as ARM template parameters.

Mounting secrets in a volume

After declaring secrets at the application level as described in the defining secrets section, you can reference them in volume mounts when you create a new revision in your container app. When you mount secrets in a volume, each secret is mounted as a file in the volume. The file name is the name of the secret, and the file contents are the value of the secret. You can load all secrets in a volume mount, or you can load specific secrets.

Example

In this example, two secrets are declared at the application level. These secrets are mounted in a volume named mysecrets of type Secret. The volume is mounted at the path /mnt/secrets. The application can then reference the secrets in the volume mount.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "String"
        },
        "environment_id": {
            "type": "String"
        },
        "queue-connection-string": {
            "type": "Securestring"
        },
        "api-key": {
            "type": "Securestring"
        }
    },
    "variables": {},
    "resources": [
    {
        "name": "queuereader",
        "type": "Microsoft.App/containerApps",
        "apiVersion": "2022-11-01-preview",
        "kind": "containerapp",
        "location": "[parameters('location')]",
        "properties": {
            "managedEnvironmentId": "[parameters('environment_id')]",
            "configuration": {
                "activeRevisionsMode": "single",
                "secrets": [
                    {
                        "name": "queue-connection-string",
                        "value": "[parameters('queue-connection-string')]"
                    },
                    {
                        "name": "api-key",
                        "value": "[parameters('api-key')]"
                    }
                ]
            },
            "template": {
                "containers": [
                    {
                        "image": "myregistry/myQueueApp:v1",
                        "name": "myQueueApp",
                        "volumeMounts": [
                            {
                                "name": "mysecrets",
                                "mountPath": "/mnt/secrets"
                            }
                        ]
                    }
                ],
                "volumes": [
                    {
                        "name": "mysecrets",
                        "storageType": "Secret"
                    }
                ]
            }
        }
    }]
}

To load specific secrets and specify their paths within the mounted volume, you define the secrets in the secrets array of the volume object. The following example shows how to load only the queue-connection-string secret in the mysecrets volume mount with a file name of connection-string.txt.

{
    "properties": {
        ...
        "configuration": {
            ...
            "secrets": [
                {
                    "name": "queue-connection-string",
                    "value": "[parameters('queue-connection-string')]"
                },
                {
                    "name": "api-key",
                    "value": "[parameters('api-key')]"
                }
            ]
        },
        "template": {
            "containers": [
                {
                    "image": "myregistry/myQueueApp:v1",
                    "name": "myQueueApp",
                    "volumeMounts": [
                        {
                            "name": "mysecrets",
                            "mountPath": "/mnt/secrets"
                        }
                    ]
                }
            ],
            "volumes": [
                {
                    "name": "mysecrets",
                    "storageType": "Secret",
                    "secrets": [
                        {
                            "secretRef": "queue-connection-string",
                            "path": "connection-string.txt"
                        }
                    ]
                }
            ]
        }
        ...
    }
    ...
}

In your app, you can read the secret from a file located at /mnt/secrets/connection-string.txt.

Next steps