Search code examples
powershelldocker-composeazure-devops-pipelines

Howto Pass a Pipeline Secret to DockerCompose@0


I'm writing a testing pipeline and dynamically creating a series of containers to setup the pieces.

I need to be able to pass a secret variable from the Pipeline into the Docker Compose construct to enable the container to connect to the database server.

I have a number of non-secret variables in the pipeline and they are all being passed successfully.

I have mapped the $env:addressdatabase_password in a powershell test to verify that my variable is available.

#To Verify if mapped secret variables are coming through (reverse the string)
- powershell: |
    $a = $env:addressdatabase_password
    Write-Host "$a"
    $b = $a.ToCharArray()
    [Array]::Reverse($b)
    $c = -join($b)
    Write-Host "$c"
  env:
    addressdatabase_password: $(database-address-password) #pipeline secret

The task in my azure-pipelines.yml looks like this (not all arguments are shown)

- task: DockerCompose@0
  displayName: 'Container Start'
  inputs:
    containerregistrytype: 'Azure Container Registry'
    azureSubscription: '$(containerSubscription)'
    azureContainerRegistry: '{"loginServer":"$(containerLoginServer)", "id" : "$(containerRegistryId)"}'
    dockerComposeFile: '**/docker-compose.yml'
    action: 'Run a Docker Compose command'
    dockerComposeCommand: 'up -d'
    arguments: mycontainer
    containerName: 'cf_$(CreateDb.buildidentifier)'
    detached: true
    dockerComposeFileArgs: |
      addressdatabase_name=$(database-address-name)
      addressdatabase_user=$(database-address-user)
      addressdatabase_pass=$(addressdatabase_password)
  env:
    addressdatabase_password: $(database-address-password) #pipeline secret

The relevant parts of the docker-compose.yml file

  mycontainer:
    image: mycontainer-runtime:latest
    ports:
      - "80:80"
    volumes:
      - ${mount_1}:C:/mount1
      - ${mount_2}:C:/mount2
    environment:
      ADDRESS_DATABASE_NAME: ${addressdatabase_name}
      ADDRESS_DATABASE_USERNAME: ${addressdatabase_user}
      ADDRESS_DATABASE_PASSWORD: ${addressdatabase_pass} #pipeline secret

The container starts up successfully, but when I examine the Environment Variables inside the container

ADDRESS_DATABASE_NAME=pr_address
ADDRESS_DATABASE_USER=test-addressuser
ADDRESS_DATABASE_PASSWORD=$(addressdatabase_password)

I'm looking for a way to get this value securely to my container without exposing it in the Pipeline.


Solution

  • Mapping pipeline secrets to env vars is just a way of passing secrets to scripts. For other types of tasks, you should be able to use the secret directly in inputs, i.e.:

    - task: DockerCompose@0
      displayName: 'Container Start'
      inputs:
        containerregistrytype: 'Azure Container Registry'
        azureSubscription: '$(containerSubscription)'
        azureContainerRegistry: '{"loginServer":"$(containerLoginServer)", "id" : "$(containerRegistryId)"}'
        dockerComposeFile: '**/docker-compose.yml'
        action: 'Run a Docker Compose command'
        dockerComposeCommand: 'up -d'
        arguments: mycontainer
        containerName: 'cf_$(CreateDb.buildidentifier)'
        detached: true
        dockerComposeFileArgs: |
          addressdatabase_name=$(database-address-name)
          addressdatabase_user=$(database-address-user)
          addressdatabase_pass=$(database-address-password) 
    

    The secret value will still be masked in the logs, no matter how you pass it.