skip to Main Content

Context: Monorepository (Nx) with multiple applications

In Azure DevOps I’m trying to retrieve the deployment token of my applications. Since it’s not secure to store the token in a JSON on the repo, I want to save in a configuration file the name of the secret in secretName (that will be somewhere) and then retrieve it using a simple script:

    for app in $apps; do
       # Check if the deployment-config.json exists for the app
       configPath="apps/$app/deployment-configs/deployment-config.${{ parameters.target_environment }}.json"
       if [ -f "$configPath" ]; then
          secretName=$(jq -r '.secretName' "$configPath") # Retrieve secret name from config file
          # TODO: RETRIEVE SECRET STORED IN A SECURE PLACE!
       fi
    done

Now at this point I have the name of the variable containing my script.

Setting a pipeline secret doesn’t work since I need to explicitly pass all the secrets as env parameters (not ideal when you have multiple apps over 3 different environments).
So something like secretValue=${!secretName} won’t work.

Is there a way to achieve this without explicitly settings secrets as env? Using Azure KeyVault can be a valid way to implement

2

Answers


  1. It is a bit confusing to understand your requirements. If your actual concern in this post is about how to isolate the environment variables to be populated from different configuration JSON files during a pipeline run, please note that

    System and user-defined variables also get injected as environment variables.

    This includes the secrets your pipeline retrieves from Azure Key Vault via pipeline library or the AzureKeyVault@2 task, so that the secret values are accessible in subsequent steps.

    You may consider referencing the variables in different job/stage scopes. Also, if that is the case, outputting variables in future job/stages may help.

    If by any chance you would populate a secret value into a configuration JSON file, you may try with the 3rd-party marketplace extension task Replace Tokens.

    Login or Signup to reply.
  2. If you store the secrets on Azure DevOps (in a variable group or in a pipeline), it is not possible to use Azure DevOps REST API or CLI to get the values of secrets. To call the secrets in a script, you must use the ‘env‘ key to map the secrets as environment variables for use.


    For your case, you can consider storing the secrets on Azure Key Vault. In your Bash script, after fetching the name of secret, you can use the Azure CLI "az keyvault secret show" to fetch the value of secret based on the name. Also see "Retrieve a secret from Key Vault".

    So, you can set you Bash script like as below:

    for app in $apps; do
       # Check if the deployment-config.json exists for the app
       configPath="apps/$app/deployment-configs/deployment-config.${{ parameters.target_environment }}.json"
       if [ -f "$configPath" ]; then
          # Fetch the secret name from config file
          secretName=$(jq -r '.secretName' "$configPath")
          # Fetch the secret value using Azure CLI
          secretValue=$(az keyvault secret show --vault-name "keyVaultName" --name "$secretName" --query value --output tsv)
       fi
    done
    

    In the pipeline of Azure DevOps, you can use the AzureCLI@2 task to run this Bash script like as below.

    parameters:
    # The name of the ARM service connection.
    - name: ArmConnection
      type: string
      default: 'xxxx'
    
    - name: target_environment
      type: string
      default: 'xxxx'
    # the name of the Azure Key Vault.
    - name: keyVaultName
      type: string
      default: 'xxxx'
    
    steps:
    - task: AzureCLI@2
      displayName: 'Retrieve secret'
      inputs:
        azureSubscription: ${{ parameters.ArmConnection }}
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          for app in $apps; do
             configPath="apps/$app/deployment-configs/deployment-config.${{ parameters.target_environment }}.json"
             if [ -f "$configPath" ]; then
                secretName=$(jq -r '.secretName' "$configPath")
                secretValue=$(az keyvault secret show --vault-name "${{ parameters.keyVaultName }}" --name "$secretName" --query value --output tsv)
             fi
          done
    
    • The parameter ‘ArmConnection‘ use to pass the name of an Azure Resource Manager service connection. It is used to connect to the Azure Subscription and Resource group where the Azure Key Vault is in. If you do not have existing ARM connection, you can go to "Project Settings" > "Pipelines" > "Service connections" to create one.

    • The parameter ‘keyVaultName‘ use to pass the name of the Azure Key Vault where the secrets are stored in.

    In addition, after creating the ARM connection, ensure the App registration (or User Assigned Managed Identity) used by the connection has the Get and List permissions of secrets on the Azure Key Vault.

    • Find the App registration (or User Assigned Managed Identity) used by the ARM connection.

      enter image description here

    • Assign the Get and List permissions of secrets to the App registration (or User Assigned Managed Identity) on the Azure Key Vault.

      enter image description here


    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search