0

I am trying to copy secrets from one Azure Key Vault to another.

So I have written 2 Powershell functions -

One for reading secrets:

function GetSecretValue
{
    param(
        [String] $KeyvaultName,
        [String] $SecretName
    )

    Write-Host "Retrieving secret $SecretName from $KeyvaultName... " -NoNewline
    if ((Get-Command Get-AzKeyVaultSecret).ParameterSets.Parameters.Name -contains "AsPlainText")
    {
        # Newer Get-AzKeyVaultSecret version requires -AsPlainText parameter 
        $SecretValue = Get-AzKeyVaultSecret -VaultName $KeyvaultName -Name $SecretName -AsPlainText
    }
    else
    {
        $SecretValue = (Get-AzKeyVaultSecret -VaultName $KeyvaultName -Name $SecretName).SecretValueText
    }
    Write-Host "ok"
    return $SecretValue
}

And another one for creating secrets:

function SetSecretValue
{
    param(
        [String] $KeyvaultName,
        [String] $SecretName,
        [String] $SecretValue
    )

    Write-Host "Creating secret $SecretName in $KeyvaultName... " -NoNewline
    $SecureStr = ConvertTo-SecureString -String $SecretValue -AsPlainText -Force
    Set-AzKeyVaultSecret -VaultName $keyvaultName -Name $secretName -SecretValue $SecureStr
    Write-Host "ok"
}

They seem to work ok, but when I (a Powershell newbie) try to combine them -

SetSecretValue($DestKv, 'ClientId', GetSecretValue($SrcKv, 'ClientId'))
SetSecretValue($DestKv, 'ClientSecret', GetSecretValue($SrcKv, 'ClientSecret'))

Then I get the syntax error:

+ SetSecretValue($DestKv, 'ClientId', GetSecretValue($Src ...
+                                    ~
Missing closing ')' in expression.
Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
  • 3
    In PowerShell, no parentheses are required around the argument list, and no comma separation of separate parameter arguments should occur: ``SetSecretValue $DestKv 'ClientId' -SecretValue (GetSecretValue $srcKv 'ClientId')``. You might also want to rename your functions to follow PowerShell's `Verb-Noun` syntax (eg. `Set-SecretValue` and `Get-SecretValue`) – Mathias R. Jessen Dec 08 '21 at 17:50
  • 2
    In short: PowerShell functions, cmdlets, scripts, and external programs must be invoked _like shell commands_ - `foo arg1 arg2` - _not_ like C# methods - `foo('arg1', 'arg2')`. If you use `,` to separate arguments, you'll construct an _array_ that a command sees as a _single argument_. To prevent _accidental_ use of method syntax, use [`Set-StrictMode -Version 2`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-strictmode) or higher, but note its other effects. See [this answer](https://stackoverflow.com/a/65208621/45375) for more information. – mklement0 Dec 08 '21 at 19:19

1 Answers1

3

The issue is the way you're passing the arguments to your functions, you are using Python like ? syntax however in PowerShell:

All cmdlet parameters are either named or positional parameters. A named parameter requires that you type the parameter name and argument when calling the cmdlet. A positional parameter requires only that you type the arguments in relative order. The system then maps the first unnamed argument to the first positional parameter. The system maps the second unnamed argument to the second unnamed parameter, and so on. By default, all cmdlet parameters are named parameters.

See Types of Cmdlet Parameters for more info.


An example, using these 2 simple functions:

function GetSecretValue
{
    param(
        [String] $KeyvaultName,
        [String] $SecretName
    )
    [System.BitConverter]::ToString(
        [System.Security.Cryptography.HashAlgorithm]::Create('sha256').ComputeHash(
            [System.Text.Encoding]::UTF8.GetBytes(($KeyvaultName, $secretName))
        )
    )
}

function SetSecretValue
{
    param(
        [String] $KeyvaultName,
        [String] $SecretName,
        [String] $SecretValue
    )

    [PSCustomObject]@{
        Vault = $KeyvaultName
        SecretName = $SecretName
        SecretValue = $SecretValue
    }
}

You could do it like this, using Named parameters:

SetSecretValue -KeyvaultName VaultExample -SecretName Secret -SecretValue (GetSecretValue -KeyvaultName VaultExample -SecretName Secret)

Vault        SecretName SecretValue
-----        ---------- -----------
VaultExample Secret     D9-8F-82-B8-D3-97-E8-BB-D0-C7-14-1A-53-56-64-D6-13-AD-8B-DC-3F-22-2F-2E-F2-0D-19-18-B5-C1-77-F6

Which looks awful, luckily, splatting exists:

$params = @{
    KeyvaultName = 'VaultExample'
    SecretName   = 'Secret'
    SecretValue  = GetSecretValue -KeyvaultName VaultExample -SecretName Secret
}

SetSecretValue @params
mklement0
  • 382,024
  • 64
  • 607
  • 775
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37