Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azd env add secret #4517

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft

azd env add secret #4517

wants to merge 12 commits into from

Conversation

vhvb1989
Copy link
Member

@vhvb1989 vhvb1989 commented Nov 6, 2024

Adding azd env set-secret

Description:

With this change, AZD allows customers to set Azure Key Vault Secrets (Akvs) within the azd environment.

Adding a Akvs

Folks run azd env set-secret <name> and they can select to either Akvs or select an existing one. For the Create a new Akvs, folks can select an existing Azure Key Vault Account or Create a new one. See the next table for the options for a user:

Flow Description
1) Create akvs && Account && RG Creating a new Resource Group with one Azure Key Vault Account and one akvs in it. User must select a Subscription, location and provide a name for the rg and kv account
2) Create akvs && Account && Existing RG Creating Azure Key Vault Account and one akvs in it on existing Resource Group. User must select a Subscription, location and provide a name for the kv account
3) Create akvs && Existing Account Creating one akvs in existing Key Vault Account. User must select a Subscription where the Key Vault Account is
4) Existing akvs Selecting existing akvs in existing Key Vault Account. User must select a Subscription where the Key Vault Account is. *If no key vault accounts are found in the subscription, the create account option is turned ON

At the end of the flow, the akvs is persisted within the .env file (the azd environment) using the <name> provided by the user for the secret and the reference to the akvs as the value, which looks like:

NAME="akvs://key-vault-account-name/akvs-name"

Azd uses the prefix akvs:// as a way to identify a reference to an Azure key Vault Secret.

Using secrets

AZD can get the akvs value during the next flows:

  1. azd provision + bicep + main.parameters.json.
    • Adding input parameter like:
@secure
input parameterName type

The type can be any supported type. The main requirement is to make the parameter secure.
AZD will not get akvs values for non-secure parameters.

  • Create a mapping in main.parameters.json for the parameter to the secret from the .env. For example, when calling azd env set-secret OPEN_ID_KEY the mapping would look like:
"parameterName": {
  "value": "${OPEN_ID_KEY}"
},
  • When AZD notices the parameter is secured, it will check if the value in the .env is an akvs reference and if yes, it will try to pull the value.
  1. azd provision + bicep + .bicepparams. -> WIP

  2. azd hooks:

    • When azd runs a hook, it uses its .env for the hook invocation. The hook implementation can access the values from azd .env as environment variables. However, if there are akvs in the .env, the values are NOT automatically converted to its value.
    • If folks want to get akvs values, they need to create a mapping in the hook definition, like:
hooks:
  preprovision:
    posix:
      shell: sh
      run: ./infra/azd/hooks/postprovision.sh
      secrets:
        OPEN_ID_KEY_VALUE: OPEN_ID_KEY
- On this example, azd will add one addional env var `OPEN_ID_KEY_VALUE` after pulling the value from the akvs reference.

Any other interaction with Azd environment will not resolve akvs into values. For example, running azd env get-values will display the akvs reference.  

Copy link
Contributor

@wbreza wbreza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good but just have some questions and concerns about when and where the secret reference to secret value translation occurs.

Comment on lines +325 to +334
e.console.ShowSpinner(ctx, "Adding Administrator Role", input.Step)
principalId, err := azureutil.GetCurrentPrincipalId(ctx, e.userProfileService, tenantId)
e.console.StopSpinner(ctx, "", input.Step)
if err != nil {
return nil, fmt.Errorf("getting current principal ID: %w", err)
}
err = e.entraIdService.CreateRbac(ctx, subId, kvAccount.Id, keyvault.RoleIdKeyVaultAdministrator, principalId)
if err != nil {
return nil, fmt.Errorf("creating Key Vault RBAC: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the expectation when a template runs in CI that has these vault references? Perhaps we should check if the project has a service principal id set and if so also automatically add secret reader rbac assignment to the SP? Otherwise it would need to be a manual process.

Comment on lines +144 to +159
err := h.serviceLocator.Invoke(func(keyvaultService keyvault.KeyVaultService) error {
for key, value := range hookConfig.Secrets {
setValue := value
if valueFromEnv, exists := h.env.LookupEnv(value); exists {
if keyvault.IsAkvs(valueFromEnv) {
secretValue, err := keyvaultService.SecretFromAkvs(ctx, h.env.GetSubscriptionId(), valueFromEnv)
if err != nil {
return err
}
valueFromEnv = secretValue
}
setValue = valueFromEnv
}
hookEnv.DotenvSet(key, setValue)
}
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like the secret references => secret value should be a concern handled internally by the environment manager instead of the hook runner having to awkwardly inject the keyvault service to get the value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants