Passing a secret to a PowerShell script in Azure DevOps pipeline
I have been testing how I would connect to the Microsoft graph in recent weeks. One way to connect is using a certificate. Part of this is done by creating a step to download the certificate. Then I have also protected the certificate with a password. I store these secrets in the pipeline variables which you can access usually on the top right of a pipeline in Azure DevOps.
Additionally I also had to includ the trusted Root CAs as a secret. I think it was because of the Azure DevOps build agent is using a version of Node.js that doesn't use the Windows Certificate Store. I found the solution here.
You then get this list where you can add variables including secrets.
Map to an environment variable in YAML
The recommended way to map a secret is to use environment variable as explained here. In the example below you can see how I map it in the env:
section.
trigger: none
pool: pool1
steps:
- task: DownloadSecureFile@1
displayName: 'download Certificate'
inputs:
secureFile: 'MSgraph.pfx'
env:
NODE_EXTRA_CA_CERTS: $(CA_CERTS)
- task: PowerShell@2
displayName: 'Get Certificate'
inputs:
filePath: '$(System.DefaultWorkingDirectory)\Script.ps1'
pwsh: true
env:
CERT_PASSWORD: $(certPassword)
Reference variable in the PowerShell script
If I then wanted to use the secret mapped in the YAML file inside the script I would reference it using the ${env:CERT_PASSWORD}
# Get pipeline variables
$certDir = $env:Agent_TempDirectory
$certName = ${env:CERTNAME}
$certpassword = ${env:CERT_PASSWORD}
# Define certificate path
$certPath = Join-Path $certDir $certName
Write-Output "certPath: [$certPath]"
# Get Certificate
$password = ConvertTo-SecureString $certpassword -AsPlainText -Force
$splat = @{
FilePath = $certPath
password = $certpassword
}
$cert = Get-PfxCertificate @splat
# Connect to Graph
$splat = @{
ClientId = ''
TenantId = ''
Certificate = $cert
}
Connect-MgGraph @splat
I deleted the client ID and tenant ID for obvious reasons, but these could also have been secrets passed into the script.
I have also used script parameters to pass secrets from the pipeline variables, which is probably easier to see and understand, but the above seems to be recommended way.