Azure DevOps Pipeline failure because of secret password with special characters
Asked Answered
S

2

9

I am building a project server solution with azure devops.

In my release pipeline I have multiple powershell scripts that requre user credentials as parameters. The password is saved in a secret variable in DevOps and contains a single quote.

Password: abcd'efgh

This leads to the pipeline throwing an error: "The string is missing the terminator: '."

When I hard code the password into the pipeline with double quotes the script executes perfectly.

Argument: -password "abcd'efgh"

When I put the DevOps secret variable in double quotes the script executes, but gives me an error when trying to authenticate at the server, possible because the password that is passed is "***".

Argument: -password "$(passwordVariable)"

Here is the relevant part of the script that is being executed by the pipeline. Any help is greatly appreciated.

param(
  $siteUrl,
  $username,
  $password
)
$encpassword = convertto-securestring -String $password -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
Connect-PnPOnline -Url $siteUrl -Credentials $cred

How do I get the password into the script?

Sullen answered 20/9, 2019 at 9:59 Comment(3)
Take a look at this extension: marketplace.visualstudio.com/… this might be usefulDynamometry
@Sullen I am facing this exact same situation. Did you ever get this resolved (without the use of a marketplace extension)?Afebrile
I have the same problem with an @ symbol. "[email protected]" is converted to "***". If I remove domain info, it is fine, "myname" remains "myname".Rybinsk
V
4

The problem you are facing is that $(passwordVariable) variable reference is expanded in the script body, before it is executed by Powershell. This means that Powershell sees the variable value and interprets special characters in it. You could prepend all the special characters with Powershell escape char (`), but that's not very elegant.

A safer way of accessing variables in scripts is via env variables - each variable you set in your pipeline creates an environment variable (The name is upper-cased, and the . is replaced with the _).

For a regular (non-encrypted) variable, you would have:

Do-Something -password "$($env:PASSWORDVARIABLE)"

For secret (encrypted) variables, you have to explicitly map them to script's env variables. In a classic pipeline, use Environment section. In yaml, it would look like this:

- pwsh: |
    Do-Something -Password $($env:MAPPED_PASSWORD)
  env:
    MAPPED_PASSWORD: $(passwordVariable)

One caveat: don't prefix mapped variables with SECRET_ - it won't work, because this prefix is used by DevOps internally.

Vomit answered 6/4, 2021 at 5:50 Comment(0)
I
0

For those who still having same issue, here is the easy solution. All you have to do is encode your password in Base64 and store it under variable.

# Pass Encode
# [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("pass"))

Then use the function bellow to decode the password while executing the script.

# Decode base64 password
function Decode-Base64Password {
    param (
        [string]$Base64EncodedPassword
    )
    # Convert the Base64 encoded string to a byte array
    $passwordBytes = [Convert]::FromBase64String($Base64EncodedPassword)    
    # Convert the byte array to a plain text string
    $password = [Text.Encoding]::UTF8.GetString($passwordBytes)    
    return $password
}
Imbed answered 9/8, 2024 at 11:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.