Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Access Azure DevOps Secret Variables

I am attempting to read an Azure DevOps secret variable from a Powershell pipeline script. The variable looks like this within Azure:

enter image description here

I've attempted to access the secret variable both as a param such as

[CmdletBinding()]
Param (
    $SecurePassword = $env:Password
)

and simply as an environment variable such as

$SecurePassword = $env:Password

Unfortunately the variable continues to appear null using either method.

enter image description here

I have no issue accessing non-secret variables. Any help would be greatly appreciated.

---------------------------------------- EDIT ----------------------------------------

I found documentation here stating that secrets are available to scripts within the pipeline if explicitly mapped in the environment section of the task.

enter image description here

I've updated my Powershell task and attempted to map the variable as both $(Password) and Password without any luck.

enter image description here

Mapping $(Password) as above reveals the string hidden behind asterisks.

Using $(Password) returns

like image 987
pirateofebay Avatar asked Jun 26 '19 21:06

pirateofebay


2 Answers

We had a requirement to create a new project in Azure DevOps and needed to migrate all of the pipelines to the new project. Lo and behold, no one knew all of the secrets, and export / import doesn't accomplish this.

I wrote a script to output all environment variables into an "Extensions" tab next to the build summary. It's formatted and everything.

The key to outputting the secret is by altering the string by inserting the '<-eliminate->' phrase within the secret value and saving to a file. Once the file is created, we then remove all instances of the string '<-eliminate->', save the file, and there it sits as an extension page to the build summary.

I would like to somehow find All secrets dynamically, but for now manually defining the variable name does the trick.

I re-formatted for this post and removed proprietary info, please let me know if it's broken :)

function GetSecretLength ($secretVar){
     $i = 0;
     while($true){
          try { 
               $secretVar.substring(0,$i)|out-null 
          } catch { 
               break
          };
          $i++; 
     }
     if ($i -le 1) { return 1 }
     else { return $i-1 };
} 
function GetSecret($secret){
     $length = GetSecretLength($secret);
     if ($length -ge 2) {
        return $secret.substring(0,$length-1 )+"<-eliminate->"+$secret.substring($length-1,1)
    } elseif ($length -eq 1) {
        return $secret+"<-eliminate->"
    } else {
        return ""
    }
} 

$var = (gci env:*).GetEnumerator() | Sort-Object Name
$out = ""

Foreach ($v in $var) { $out = $out + "`t{0,-28} = {1,-28}`n" -f $v.Name, (GetSecret($v.Value)) }

$fileName = "$env:BUILD_ARTIFACTSTAGINGDIRECTORY\build-variables.md"
write-output "dump variables on $fileName"
set-content $fileName $out

write-output "##vso[task.addattachment type=Distributedtask.Core.Summary;name=Environment Variables;]$fileName"

((Get-Content -path $fileName -Raw) -replace '<-eliminate->', '') | Set-Content -Path $fileName

You have to add the secret variables that you want into the "Environment Variables" of the Powershell task: Environment Variables

You end up with this pretty tab: enter image description here

like image 118
patman Avatar answered Oct 22 '22 17:10

patman


Why not just store the password in a keyvault as a secret? then there are azure commands for accessing the secret, and avoid all this. Heck, we generate random passwords, store them in keyvaults, then access the contents in the appropriate resource, without ever needing to expose the decrypted secret in a powershell command, like in an ARM template for an azure sql server database.

I know this doesn't solve your initial question, but it is a workaround that does work.

like image 32
user3622356 Avatar answered Oct 22 '22 16:10

user3622356