Azure Key Vault access from ARM Template - azure

I was trying to add Azure key vault integration with our ARM deployment, so we can keep all password in Azure Key-Vault.
I was following this to try to access secret (adminPassword) I have created in Azure KeyVault (dSentienceAnalytics). Here is my template
I tried to deploy this template through Powershell, but it asked me to enter value for variable “adminPassword”, which it supposed to retrieve from Azure key vault.
Do you see what I am missing here?

You cannot use a KeyVault reference in the template itself, only in the parameters file. So your template will not look any differently if you're using KeyVault, the adminPassword parameter will simply be defined as a secureString. The template's use of the password can look exactly like this:
https://github.com/Azure/azure-quickstart-templates/blob/master/101-vm-simple-linux/azuredeploy.json
The parameters file, is where the reference will be used. The first code sample here:
https://azure.microsoft.com/en-us/documentation/articles/resource-manager-keyvault-parameter/#reference-a-secret-with-static-id
Is showing you the parameters file, not the template file's parameter object (it is a bit confusing).
For a really simple example, see the KeyVaultUse.json and KeyVaultUse.parameters.json here:
https://github.com/rjmax/ArmExamples/tree/master/keyvaultexamples
Note that there's nothing unique or different about KeyVaultUse.json, the "key" is in the parameters file.
That help?

You can create a linked template and pass the keyvault secret to that as a parameter. Your linked template will need to be accessible to Azure at some uri.
"name": "linked-template",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri":"<your linked template uri, e.g. a blob-store file with a sas token>"
},
"parameters": {
"password": {
"reference": {
"keyVault": {
"id": "[variables('keyVaultId')]"
},
"secretName": "password"
}
},
You will need the id of your key vault, e.g. here, it's assume to be in a variable constructed from parameters on the top-level template where the user specifies a resource group and name for the key-vault:
"deploymentKeyVaultId" : "[resourceid(subscription().subscriptionId,
parameters('keyVaultResourceGroup'), 'Microsoft.KeyVault/vaults',
parameters('keyVaultName'))]",

What are you trying to deploy? If it is an app service you can retrieve the secret from Key Vault with the combination of leveraging Managed Service Identity and access policy on the Key Vault. Here's how to turn on MSI authentication for App Service and add access policy
In the App Service can add something like this:
{
"apiVersion": "2018-11-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', WEBSITE NAME))]",
"Microsoft.ApplicationInsights.AzureWebSites",
"[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('secretName'))]"
],
"properties": {
"ConnectionSecret": "[concat('#Microsoft.KeyVault(SecretUri=', reference(SECRET NAME).secretUriWithVersion, ')')]"
}

Related

Azure Logic App deployment via Powershell

I have developed a powershell script that allows me to download the Logic Apps from the portal in Visual Studio. Along with the JSON template it also downloads the parameters defined in the Logic App (which is how I wanted). We had established connections with Dataverse and Salesforce via Sign in method. But the problem is that when I download the template via Powershell script and update the parameter file to deploy to a different environment it asks for the credentials which are for service principal login. I haven't used service principal login when creating the connection and I don't have those credentials. I tried removing those parameters from both the parameter file and .JSON file but I am getting error as below:
Error: Code=InvalidDeploymentParameterValue; Message=The value of deployment parameter 'commondataservice-5_token:clientSecret' is null. Please specify the value or use the parameter reference.
These parameters were automatically added in my parameter.json file.
"commondataservice-5_token:clientId": {
"value": null
},
"commondataservice-5_token:clientSecret": {
"value": null
},
"commondataservice-5_token:resourceUri": {
"value": null
},
"commondataservice-5_token:grantType": {
"value": "code"
}
This is how the main Logic App template looks like for the dataverse connection
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"location": "[parameters('logicAppLocation')]",
"name": "[parameters('commondataservice-5_name')]",
"properties": {
"api": {
"id": "[concat('/subscriptions/',subscription().subscriptionId,'/providers/Microsoft.Web/locations/',parameters('logicAppLocation'),'/managedApis/commondataservice')]"
},
"displayName": "[parameters('commondataservice-5_displayName')]",
"parameterValues": {
"token:clientId": "[parameters('commondataservice-5_token:clientId')]",
"token:clientSecret": "[parameters('commondataservice-5_token:clientSecret')]",
"token:TenantId": "[parameters('commondataservice-5_token:TenantId')]",
"token:resourceUri": "[parameters('commondataservice-5_token:resourceUri')]",
"token:grantType": "[parameters('commondataservice-5_token:grantType')]"
}
}
}
Below is the Powershell command to get the LA template:
Get-LogicAppTemplate -LogicApp fc-cus-dev-int-test-param-dynamicexpression -ResourceGroup FC-CUS-DEV-INT-RG -SubscriptionId xxxxx-xxxxxx -Verbose | Out-File "C:\Users\xxxxxx\Desktop\DynamicExpression-NA.LogicApp.json"
#Powershell command to get the Parameters:
Get-ParameterTemplate -TemplateFile "C:\Users\xxxxx\Desktop\DynamicExpression-NA.LogicApp.json" | Out-File "C:\Users\xxxxxx\DynamicExpression-NA.LAparameters.json"
I have followed this article to download the Logic App: https://blog.sandro-pereira.com/2020/12/21/logic-apps-moving-from-azure-portal-to-visual-studio/
I am having a hard time trying to remove the connection parameters from the parameter file and deploying the LA. Any suggestions or pointers are highly appreciated
You have to update the parameter file with actual values. When you extract a template it creates the parameter file but for for security reasons any value that should not be public (i.e. password) it does not retrieve the existing value. Those values all show as null in your parameter file. You need to get those values and update the parameter file before deploying.

Adding an access policy to a Key Vault which is in another resource group

I am trying to add access policy to an existing key vault which belongs to a different resource group. There was a suggestion from stackoverflow but I have authorization issue on implementing write. .
How to add Access Policy to a Keyvault in different Resource Group through ARM Templates
I am trying a different way as below. I am adding the resource group in the name. But I am getting "different segment length" error
"resources": [
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat("/",parameters('resourceGroupName'),"/",parameters('keyVaultName'), '/add')]",
"apiVersion": "2019-09-01",
"properties": {
"accessPolicies": [
{
"tenantId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').tenantId]",
"objectId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppName'), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]",
"permissions": {
"secrets": [
"get",
"list"
]
}
}
]
}
}
]
Is this even possible to add the resource group in the name?
As you are using resources in another resource group, you need to change the deployment scope to Subscription.
As suggested by Matt Stannett, you can either use Azure CLI or PowerShell script task in Octopus to get the Resource ID of your key vault

Deploy a Web App certificate from Key Vault secret and use it for creating SSL binding - LinkedAuthorizationFailed

I'm trying to add a custom domain with an SSL-binding to a web app with an ARM-template. I can do it manually in the Azure Portal but I want it to work with an ARM-template.
The certificate is in a key vault which is not in the same resource group as the web app. I have no problem accessing ordinary secrets from the key vault in my release pipeline like databaseconnectionstrings. The problem is when I try to access certificates. I have GET permissions to the keyvault certificates.
I'm using this github template
https://github.com/Azure/azure-quickstart-templates/tree/master/201-web-app-certificate-from-key-vault
This is the error I get when I try to deploy the ARM-template with a release pipeline.
"error": { 
"code": "LinkedAuthorizationFailed", 
"message": "The client 'xxxx' with object id 'xxxx' has permission to perform action 'Microsoft.Web/certificates/write' on scope '***/providers/Microsoft.Web/certificates/xxxxx'; however, it does not have permission to perform action 'write' on the linked scope(s) '/subscriptions/xxxx/resourceGroups/xxx/providers/Microsoft.KeyVault/vaults/xxxxx'."
}
You could try increasing the permissions the Azure DevOps service connection has on the key vault certificates under Access Policies, maybe start with all certificate permissions as a troubleshooting step to confirm it's permission related, then reduce as required, may just need Get and Create?
I solved it by creating 4 resources in the ARM template. A certificate, an app service plan, a web app and a hostname binding. Just like this github azure-quickstart-template https://github.com/Azure/azure-quickstart-templates/tree/master/201-web-app-custom-domain-and-ssl.
The key for me was modifying the certificate resource by adding a pxfBlob and removing the key vault properties, see the code below. The certificatePfx is a securestring which is set in the release pipeline from the keyVault.
{
"type": "Microsoft.Web/certificates",
"name": "[parameters('certificateName')]",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"name": "[parameters('webAppName')]",
"serverFarmId": "[concat(resourceId('Microsoft.Web/serverFarms', parameters('appServicePlanName')))]",
"hostNames": [
"parameters('hostname_wildcard')",
"parameters('hostname_domain')"
],
"pfxBlob": "[parameters('certificatePfx')]"
},
"dependsOn": [
"[concat('Microsoft.Web/sites/',parameters('webAppName'))]"
]
},

Can Secrets From Objects Created in ARM Templates Get Auto Added to Key Vault

If I have an Azure ARM template that can create:
Azure Container Registry
Azure Key Vault
Is there a way for the username and password for the Azure Container Registry to be automatically be added to the Azure Key Vault using ARM templates?
Is there some way to refer to the Azure Container Registry username and password secrets in ARM templates for this purpose?
UPDATE
#EdBoykin's answer is correct, this is what I ended up with:
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('key_vault_name'), '/AzureContainerRegistryKey1')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', parameters('container_registry_name')), '2017-10-01').passwords[0].value]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('key_vault_name'))]",
"[concat('Microsoft.ContainerRegistry/registries/', parameters('container_registry_name'))]"
]
}
Muhammad,
To create the secrets in KeyVault you will need to create an ARM template that looks something like this. Make sure to update the 'dependson' section so this resource depends on your ACR being created first. The username is going to be the ACR resource name. So, whatever you set that to in your ARM script, you can store in your key vault as a key vault secret.
For the passwords, or keys, this is what you do. Here is a sample template for adding a KeyVault secret
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(variables('keyVaultName'), '/{YourACRKey1SecretName}')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', parameters('YourACRName')), '2017-10-01').passwords[0].value]"
},
"dependsOn": []
}
{YourACRKey1SecretName} should be changed to the secret name for your ACR Key1 value.
To set the other key in your keyvault, create another key vault secret resource with a new name and use this for the value:
For Key 2
[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', parameters('YourACRName')), '2017-10-01').passwords[1].value]

How to access SSL in KeyVault from ARM Template

Duplicate Question?
I don't believe it is. As stated, this is working using my user from a local deployment and all (as I understand it) permissions have been granted to the Service Principal and the test user that also fails locally.
I have an ARM template that provisions and deploys a web app, part of that is to apply a certificate binding to the webapp. That part of the template looks like this:
{
"type": "Microsoft.Web/sites",
"kind": "api",
"name": "[parameters('name')]",
"apiVersion": "2015-08-01",
"location": "[resourceGroup().location]",
"properties": {
"name": "[parameters('name')]",
"serverFarmId": "[resourceId(parameters('servicePlanGroup'), 'Microsoft.Web/serverFarms', parameters('servicePlanName'))]"
},
"resources": [
{
"name": "[parameters('certificateName')]",
"apiVersion": "2014-04-01",
"type": "Microsoft.Web/certificates",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('name'))]"
],
"properties": {
"keyVaultId": "[parameters('keyVaultId')]",
"keyVaultSecretName": "[parameters('keyVaultSecretName')]"
}
}
]
}
When I run this locally from my PC it works fine, when I run it from the VSTS the deployment fails, and look like this:
Where the error is:
"operationName": {
"localizedValue": "Microsoft.Web/certificates/write",
"value": "Microsoft.Web/certificates/write"
},
"properties": {
"statusCode": "Unauthorized",
"statusMessage": "{\"error\":{\"code\":\"BadRequest\",\"message\":\"\"}}"
}
The SSL certificate and the KeyVault both have permissions added for the Service Principal that VSTS runs under for this release.
The Release Principal user has Read,List for keys and secrets in the KeyVault and is a Contributor in the subscription. My account which works locally is co-admin.
Any ideas on what permissions need to be added?
Update
I added another user testuser which has the same rights as the Service Principal and it now fails locally. I guess it will be some trial and error to add permissions and see what works.
This is not a duplicate question - as mentioned it was pointing to strange permission issue across accounts, even though the permissions were set. It turns out that for some reason the co-admin will work despite the below issue - a potential bug in the ARM/permission infrastructure, maybe?
This works for co-admin user but not anyone else.
Whereas this works for a lesser privileged user/principal.
Note the schema version change. The original schema of 2014-04-01 doesn't actually include anything about Microsoft.Web/Certificates whereas the updated schema 2015-08-01 does include this information.
Local testing using the testuser with same privileges as the VSTS service principal is working fine with this change.
Side Note for anyone else trying to achieve SSL bindings:
The location of resources in my example is all the same. I suspect if the vault is in a different location, then its resource group may also need to be specified for this to work the same - I haven't tested that theory though.

Resources