4
votes

I've got kv with secret dbname = "DatabaseName".

In Azure DevOps, I'm using two tasks one for reading secrets from Key Vault and second one is Azure Powershell where is my code line Write-Host $(dbname).

Output in logs is ***.

And I want to get DatabaseName as output.

The only thing that I found is

$DWH = "$(dbname)"
Write-Host "$($DWH.ToCharArray() -join ' ' )"

And the output is D a t a b a s e N a m e.

Is there a possibility to get DatabaseName instead of *** or D a t a b a s e N a m e?

3
No. That's done on purpose to hide secrets from logs. Database name really shouldn't be a secret anywayNick.McDermaid
@Nick.McDermaid this database name was only an example. I get it that's done on purpose but still logs with this *** looks awful and i'm just curious if there is some kind of workaroundsi0two

3 Answers

1
votes

According to the docs, Microsoft mask the secret variables from the logs, so you can't print it normally.

You can install the Read Secrets from Key Vault extension that read the secrets from Key Vault and store them in a regular variables (and not in secret variables like the Microsoft built-in task).

1
votes

I am afraid that you cannot get what you want.

For security reason, you cannot show secrets directly in logs. It is designed as that.

But it doesn't not affect your use of it. For example, I just downloaded secrets from Azure Keyvault, and I can check them in next PowerShell task:

enter image description here

Result

enter image description here

0
votes

According to the documentation, one can split the secrets and output substrings:

We make an effort to mask secrets from appearing in Azure Pipelines output, but you still need to take precautions. Never echo secrets as output. Some operating systems log command line arguments. Never pass secrets on the command line. Instead, we suggest that you map your secrets into environment variables.

We never mask substrings of secrets. If, for example, "abc123" is set as a secret, "abc" isn't masked from the logs. This is to avoid masking secrets at too granular of a level, making the logs unreadable. For this reason, secrets should not contain structured data. If, for example, "{ "foo": "bar" }" is set as a secret, "bar" isn't masked from the logs.

Here is an example in bash, which can potentially be transferred to Powershell:

- task: Bash@3
  inputs:
    targetType: inline
    script: |
      # let's say the secret is Passw0rd

      # Direct output is masked:
      echo $MYSECRET
      # OUTPUTS "***"
    
      # Concatenated output is masked:
      echo "ABC$MYSECRET DDD"
      # outputs "ABC*** DDD"

      
      # Experimenting with substrings:
      firstPart=${MYSECRET::-2}
      secondPart=${MYSECRET: -2}

      # Substrings are displayed:
      echo $firstPart
      # outputs "Passw0"

      echo $secondPart
      # outputs "rd"

      # Substrings concatenated with other strings are displayed:
      echo "$firstPart-$secondPart"
      # outputs "Passw0-rd"

      # Directly concatenated substrings are masked:
      echo "$firstPart$secondPart"
      # outputs "***"

      # Secrets can be written to a file:
      echo "$MYSECRET" > test.txt

      # Secrets are even masked when being displayed as part of a file:
      cat test.txt
      # outputs "***"
    env:
      MYSECRET: $(my_secret) # This is defined in a variable group

- task: PublishPipelineArtifact@1
  inputs:
    targetPath: 'test.txt' # This pipeline artifact contains the secret unmasked
    artifact: 'TestArtifact'
    publishLocation: 'pipeline'
  displayName: 'Publish PipelineRunData artifact'

We therefore have two options to get the secret:

  1. Output the secret partially and concatenate manually
  2. Download pipeline artifact

Probably not ideal from a security perspective, but it is extremely important to understand the limitations of the system: Whoever has access to modifying a pipeline can potentially get access to the secrets used by the pipeline.