2

I am trying to automate the creation of certain azure resources via an Azure PowerShell script that is triggered from an Azure DevOps release pipeline. I want to create a function app, and automatically integrate reading right access to secrets in an already existing Key Vault. This Key Vault is in the same Azure subscription.

While I can create most resources following the documentation, there seems to be a lack of documentation regarding the creation of certain resources using Azure PowerShell (or I can't find it).

If I follow the sample from this link, I can accomplish it without a problem by using the UI in the Azure Portal, but I can't find any documentation on Microsoft Docs to do it using PowerShell.

    Write-Host "Creating Function App..."
    $fnApp = New-AzFunctionApp   -Name $functionAppName `
                        -ResourceGroupName $emailFunctionRg `
                        -Location "$(AzureRegion)" `
                        -StorageAccount $storageName `
                        -Runtime dotnet `
                        -FunctionsVersion '3' `
                        -IdentityType SystemAssigned
    Write-Host "Function App created!"

    Write-Host "Assigning Key Vault access..."
    $appId = Get-AzADServicePrincipal -DisplayName $functionAppName
    Set-AzKeyVaultAccessPolicy -VaultName EmailSettings -ServicePrincipalName $appId -PermissionsToSecrets Get,List
    Write-Host "Key Vault access granted!"

Running Set-AzKeyVaultAccessPolicy fails with "Insufficient privileges to complete the operation.". But I am not sure if this is the right path to follow, it was just a guess, based on the available functions in the documentation.

Any ideas?

Gustavo
  • 105
  • 1
  • 8
  • Did you try $appId.ApplicationId in Set-AzKeyVaultAccessPolicy? – akb Feb 22 '21 at 12:29
  • I haven't really thought about it. I will try that! – Gustavo Feb 22 '21 at 12:42
  • @akb , with $appId.ApplicationId, the result is "Cannot validate argument on parameter 'ServicePrincipalName'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again." – Gustavo Feb 22 '21 at 15:40
  • This indicates there is no value in $appId. can you output the value and check if you are receiving value in $appId and $appId.ApplicationId – akb Feb 22 '21 at 16:12
  • After a little bit of trial and error I just came to the conclusion I was not using the right parameter for the cmdlet. It works with `Set-AzKeyVaultAccessPolicy -VaultName -ObjectId (Get-AzADServicePrincipal -DisplayName ).Id -PermissionsToSecrets – Gustavo Feb 23 '21 at 10:43

2 Answers2

1

Two potential issues to check out here:

  1. your app creation assigns the result to $fnApp. perhaps $fnApp or as commented above, $fnApp.ApplicationId is what you should be using for the -ServicePrincipalName parameter on the access policy grant.
  2. you don't have privileges to assign RBAC roles. Go to the Key Vault, choose Access Control, then click the Role Assignments tab and verify that your user appears in the list as an Administrator, User Access Administrator, or Owner.

Edit: With respect to the RBAC privilege, since this is running in Azure Powershell from Azure DevOps, you need to check the role assignment for the Service Connection's service principal - under Azure Active Directory in the Azure Portal, look up the principal used to create the service connection, and make sure THAT gets the correct Role on the key vault.

WaitingForGuacamole
  • 3,744
  • 1
  • 8
  • 22
  • True, that is an old variable that I created to test exactly that scenario: the result is "With $appId.ApplicationId, the result is *"Cannot validate argument on parameter 'ServicePrincipalName'. (...)"* if .ApplicationId is used, and *"Insufficient privileges to complete the operation"*. As for option number 2 I don't know exactly yet which user should be assigned to a RBAC role, since it is running from an Azure DevOps pipeline. Going to have a look... – Gustavo Feb 22 '21 at 15:47
  • I added clarification to indicate that you should grant access to the Service Principal you created for the Service Connection from Azure DevOps. – WaitingForGuacamole Feb 22 '21 at 16:02
  • After a little bit of trial and error I just came to the conclusion I was not using the right parameter for the cmdlet. It works with `Set-AzKeyVaultAccessPolicy -VaultName -ObjectId (Get-AzADServicePrincipal -DisplayName ).Id -PermissionsToSecrets – Gustavo Feb 23 '21 at 10:43
  • 1
    Hello from the future. Some months after this question was asked I ran into issues with this again and I found my own post. In your answer, @waitingforguacamole, you mentioned "look up the principal used to create the service connection, and make sure THAT gets the correct Role on the key vault.", and this was extremely helpful as now I was implementing it in our production subscription and THAT service principle did not have any role in the KeyVault. – Gustavo Nov 10 '21 at 08:17
0

After a little of trial and error I just came to the conclusion I was not using the right parameter for the Set-AzKeyVaultAccessPolicy cmdlet.

The following script will work (if the service principle running it has the appropriate role, like WaitingForGuacamole mentioned in his/her answer):

Write-Host "Creating Function App..."
$fnApp = New-AzFunctionApp -Name <FnAppName> `
                    -ResourceGroupName <ResourceGroupName> `
                    -Location <AzureRegion> `
                    -StorageAccount <StorageAccount> `
                    -Runtime dotnet `
                    -FunctionsVersion '3' `
                    -IdentityType SystemAssigned
Write-Host "Function App created!"

Write-Host "Assigning Key Vault access..."
Set-AzKeyVaultAccessPolicy -VaultName <NameOfTheKeyVault> -ObjectId (Get-AzADServicePrincipal -DisplayName <FnAppName>).Id -PermissionsToSecrets <Get, List, etc...>
Write-Host "Key Vault access granted!"
Gustavo
  • 105
  • 1
  • 8