How to manage secrets when working with an Azure Dev Space

Your services might require certain passwords, connection strings, and other secrets, such as for databases or other secure Azure services. By setting the values of these secrets in configuration files, you can make them available in your code as environment variables. These configuration files must be handled with care to avoid compromising the security of the secrets.

Storing and using runtime secrets

Azure Dev Spaces provides two recommended, streamlined options for storing secrets in Helm charts generated by the Azure Dev Spaces client tooling: in the values.dev.yaml file, and inline directly in azds.yaml. It's not recommended to store secrets in values.yaml.

Note

The following approaches show you how to store and use secrets for Helm charts generated by the client tooling. If you create your own Helm chart, you can use the Helm chart directly to manage and store secrets.

Using values.dev.yaml

In a project that you have already prepared with Azure Dev Spaces, create a values.dev.yaml file in the same folder as azds.yaml to define your secret keys and values. For example:

secrets:
  redis:
    port: "6380"
    host: "contosodevredis.redis.cache.windows.net"
    key: "secretkeyhere"

Verify the azds.yaml file references values.dev.yaml as optional using a ?. For example:

install:
  values:
  - values.dev.yaml?
  - secrets.dev.yaml?

If you have additional secret files, you can add them here as well.

Update or verify your service references your secrets as environment variables. For example:

var redisPort = process.env.REDIS_PORT
var host = process.env.REDIS_HOST
var theKey = process.env.REDIS_KEY

Run your updated services using azds up.

azds up

Use kubectl to verify your secrets have been created.

kubectl get secret --namespace default -o yaml 

Important

It's not recommended to store secrets in source control. If using Git, add values.dev.yaml to the .gitignore file to avoid committing secrets in source control.

Using azds.yaml

In a project that you have already prepared with Azure Dev Spaces, add secret keys and value using $PLACEHOLDER syntax under configurations.develop.install.set in azds.yaml. For example:

configurations:
  develop:
    ...
    install:
      set:
        secrets:
          redis:
            port: "$REDIS_PORT"
            host: "$REDIS_HOST"
            key: "$REDIS_KEY"

Note

You can enter secret values directly without using $PLACEHOLDER syntax in azds.yaml. However, this approach is not recommended since azds.yaml is stored in source control.

Create a .env file in the same folder as azds.yaml to define your $PLACEHOLDER values. For example:

REDIS_PORT=3333
REDIS_HOST=myredishost
REDIS_KEY=myrediskey

Important

It's not recommended to store secrets in source control. If using Git, add .env to the .gitignore file to avoid committing secrets in source control.

Update or verify your service references your secrets as environment variables. For example:

var redisPort = process.env.REDIS_PORT
var host = process.env.REDIS_HOST
var theKey = process.env.REDIS_KEY

Run your updated services using azds up.

azds up

Use kubectl to verify your secrets have been created.

kubectl get secret --namespace default -o yaml 

Using secrets as build arguments

The previous section showed how to store and use secrets to use at container run time. You can also use any secret at container build time, such as a password for a private NuGet, using azds.yaml.

In azds.yaml, set the build time secrets in configurations.develop.build.args using the <variable name>: ${secret.<secret name>.<secret key>} syntax. For example:

configurations:
  develop:
    build:
      dockerfile: Dockerfile.develop
      useGitIgnore: true
      args:
        BUILD_CONFIGURATION: ${BUILD_CONFIGURATION:-Debug}
        MYTOKEN: ${secret.mynugetsecret.pattoken}

In the above example, mynugetsecret is an existing secret and pattoken is an existing key.

Note

Secret names and keys may contain the . character. Use \ to escape . when passing secrets as build arguments. For example, to pass a secret named foo.bar with the key of token: MYTOKEN: ${secret.foo\.bar.token}. In addition, secrets can be evaluated with prefix and postfix text. For example, MYURL: eus-${secret.foo\.bar.token}-version1. Also, secrets available in parent and grandparent spaces can be passed as build arguments.

In your Dockerfile, use the ARG directive to consume the secret, then use that same variable later in the Dockerfile. For example:

...
ARG MYTOKEN
...
ARG NUGET_EXTERNAL_FEED_ENDPOINTS="{'endpointCredentials': [{'endpoint':'PRIVATE_NUGET_ENDPOINT', 'password':'${MYTOKEN}'}]}"
...

Update the services running in your cluster with these changes. On the command line, run the command:

azds up

Next steps

With these methods, you can now securely connect to a database, an Azure Cache for Redis, or access secure Azure services.