Problem with Incremental Keyvault ARM Template Deployment

Today I want to share the problem that I was facing while deploying Keyvault using the ARM template.

Most of you probably are familiar with the keyvault and how it works, so I am not going to write about it. But if you would like to know more, here is Azure documentation that you can take a read.

The whole setup I have is VSTS custom script extension, which triggers the runbook via webhook, and runbook triggers the ARM template deployment. Runbook code, which triggers the keyvault deployment is as per below.


        $KeyVaultDeploymentParameters = @{
            Name                    = $DeploymentName;
            ResourceGroupName       = $rname;
            Mode                    = 'Incremental';
            TemplateFile            = $templatefileuri;
            TemplateParameterObject = @{
                keyVaultName                   = $kvName;
                tenantId                       = $TenantId;
                objectId                       = $requestorObjectID;
                keysPermissions                = $requestorKeysPermissions;
                secretsPermissions             = $requestorSecretsPermissions;
                certPermissions                = $requestorCertPermissions;
                vaultSku                       = $keyvaultSku;
                enabledForDeployment           = $false;
                enabledForTemplateDeployment   = $false;
                enableVaultForVolumeEncryption = $false;
                location                       = $rloc;
            }
        }

        New-AzureRmResourceGroupDeployment @KeyVaultDeploymentParameters -Verbose

So far so good. Now let’s check into the deployment mode, which is incremental. With this mode, your deployment is not going to provision any new resources, but will add new resources to the deployment. And with this approach, to get provisioned new keyvault all works fine.

What about, if you already have a keyvault deployed, key and secret permissions are already set for the current users or groups and you want to trigger incremental deployment to add another secret or key. And this is where it messes up everything.

For example, you have 10 users, service principles, who have access to keyvault keys and secrets. By triggering the incremental ARM deployment, it will remove all the current users access to keyvault keys and secrets and will leave only the current one. So you have to be careful with this approach, because if you have any service principles using keyvault keys or secrets, doing some scheduled automation tasks, you will get lots of errors, as those service principles will not have access to keys and secrets.

This issue is already known and been suggested for further implementations. Feel free to give your vote as well.

As a solution I was doing the following. If it is a new keyvault deployment, trigger the ARM deployment. If new key or secret has to be added to the current keyvault, use old-good powershell cmdlets.

 



Function AddKeyOrSecret([string] $feature, [string] $kvName, [string] $type, [string]$KeyOrSecretName, [string]$secretValue)
{
    if ($type.toLower() -eq 'key')
    {
        $startDate = (Get-Date).AddDays(-1)
        $endDate = $startDate.AddYears(99)
        Add-AzureKeyVaultKey -VaultName $kvName -Name $KeyOrSecretName  -Destination 'software' -Expires $endDate -NotBefore $startDate
        Write-Output "Key: $KeyOrSecretName added to the Key Vault: $kvName"

    }
    elseif ($type.toLower() -eq 'secret')
    {
        if ($secretValue.Length -gt 0)
        {
            write-output " $feature "
            write-output "Secret name is : $KeyOrSecretName ; secret value is : $secretValue"
            Write-output "Converting Secret to secure String."
            $secretSecureString = ConvertTo-SecureString $secretValue -AsPlainText -Force            
            Write-output "Adding secure Secret to Key vault : $secretSecureString "
            Set-AzureKeyVaultSecret -VaultName $kvName -Name $KeyOrSecretName -SecretValue $secretSecureString
        }
        else
        {
            write-output 'Secret Value field cannot be empy. Please provide a value.'
        }
        
    } 
}

Hope it makes all sense and made your life a bit easier. If you have any questions or suggestions, feel free to comment below or drop me an email.

 

Leave a Reply

Your email address will not be published.