Create Key Vault certificate using ARM template - azure

I want to create a Key Vault and add secrets as well as certificates to it using an ARM template. I have been able to find a way of creating a Key Vault as well as adding secrets to it, but couldn't find any relevant solution of adding a new Self-signed certificate into Key Vault using just the ARM template.
Is this feature currently supported in ARM template ?

No, this is currently not supported. You can only create secrets using ARM Templates.

What i have done is:
Set up a endpoint that creates a random certificate for every request:
https://management.dotnetdevops.org/providers/DotNetDevOps.AzureTemplates/templates/KeyVault/certificates/demo/parameters?secretName=test&keyVaultName=test
It outputs the following:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"keyVaultName": {
"value": "test"
},
"secretName": {
"value": "test"
},
"secretValue": {
"value": "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"
},
"certificateThumbprint": {
"value": "AD99382EECC21A3456FFDD0B10FDB0399C53BF10"
}
}
}
this is deployed using a nested template
{
"type": "Microsoft.Resources/deployments",
"name": "CreateCertificate",
"apiVersion": "2016-09-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat('https://management.dotnetdevops.org/providers/DotNetDevOps.AzureTemplates/templates/KeyVault/certificates/demo?secretName=test&keyVaultName=',reference('DeployKeyvault').outputs.keyVaultName.value)]",
"contentVersion": "1.0.0.0"
},
"parametersLink": {
"uri": "[concat('https://management.dotnetdevops.org/providers/DotNetDevOps.AzureTemplates/templates/KeyVault/certificates/demo/parameters?secretName=test&keyVaultName=',reference('DeployKeyvault').outputs.keyVaultName.value)]",
"contentVersion": "1.0.0.0"
}
}
},
This works nice for this usecase.

As it was said, this feature is currently not supported.
What you can do is create powershell script for importing certificates.
Import-AzureKeyVaultCertificate will definitely help you with it.
Just run script after the deployment of Key Vault itself is finished and certificates will be imported.
Hope that will help you.

The certificate is currently not supported. You can only create secrets using ARM Templates.
You can use custom PowerShell script in the ARM template so that you can achieve whatever you are trying
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deployment-script-template?tabs=CLI

Related

Automatically create an Azure DevOps Organization with an ARM Template

Since it is not possible to create an organization with the DevOps Rest API and the SDK for organizations is still in preview and not functional, we currently try to programmatically create an organization with an ARM template.
In the Azure Portal, it is possible to create a new organization with an ARM template like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/Microsoft.Resources.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"organizationName": {
"type": "string",
"defaultValue": ""
},
"organizationIdentifier": {
"type": "string",
"defaultValue": ""
},
"administrator": {
"type": "string",
"defaultValue": ""
}
},
"resources": [
{
"name": "[parameters('organizationIdentifier')]",
"type": "microsoft.visualstudio/account",
"location": "West Europe",
"description": "[parameters('organizationName')]",
"apiVersion": "2014-02-26",
"properties": {
"operationType": "Create",
"accountName": "[parameters('organizationIdentifier')]",
"ownerUpn": "[parameters('administrator')]"
}
}
]
}
Unfortunately we couldn't find a solution to create this within a C# Azure Function programmatically, since the SDK would want a resource group, which doesn't make sense in this context. Is there a way to do this or is it simply not possible to create an organization automatically at this point?
Yes, as of now there is no ways to create an DevOps organization using REST API.
The way to create Azure DevOps Organization is Manual creation or using ARM Template.
Using ARM Template, you have to specify the Resource name as a parameter. That is also we need to mention the Organization Name before deploying the ARM Template.
As of now the REST API is available for some of the services.
References
-Automating organization and project creation in Azure DevOps Blog gives the clear view

Parallel deployment of Azure AppService using ARM template

I am trying to solve a use-case of deploying 20 to 30 Azure AppServices using ARM template based on Admin decision.
This is happening through c# webapi using Microsoft Fluent library(Microsoft.Azure.Management.Fluent & Microsoft.Azure.Management.ResourceManager.Fluent),
var creds = new AzureCredentialsFactory().FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);
var deployment = azure.Deployments.Define($"deployment-{userName}")
.WithExistingResourceGroup(resourceGroupName)
.WithTemplate(templateJson.ToString())
.WithParametersLink(templateParamsBlobURL, "1.0.0.0")
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
Problem statement
When the admin decides to run 20 AppServices, then the above lines of code will execute and provision these AppServices, the decision is based on admin.
For me the Deployment is happening in sequential manner i.e., upon completing one AppService deployment then it triggers the next AppService deployment, which takes huge time to complete the entire operation. I am trying to achieve the deployment of 20 AppServices(decided by admin) in parallel so that the provisioning completes at the earliest
Kindly assist me on how to achieve the parallel deployment of AppServices using ARM template
Thanks for confirming #Guptha, posted the same as an answer to help other community members for the similar query , To iteration multiple resources at a time in ARM TEMPLATE .
Use your Azure Resource Manager template to create multiple instances
of a resource (ARM template). You can dynamically set the quantity of
resources to deploy by adding a copy loop to the resources section of
your template.
For example to create multiple storage accounts ;
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageCount": {
"type": "int",
"defaultValue": 3
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {},
"copy": {
"name": "storagecopy",
"count": "[parameters('storageCount')]"
}
}
]
}
For complete setup please refer this MICROSOFT DOCUMENTATION|Resource iteration in ARM templates

Azure Functions ARM Template deploy deletes Functions

I've got an ARM template (included below) to deploy an Azure Function App. I deploy it with:
az group deployment create --resource-group my-group --template-file my-function-app.json
This works and I can then deploy my functions successfully using the VS Code plugin or Azure Functions Core Tools.
However, if I then re-deploy the ARM template (for example to update an application setting) then I lose my functions and need to re-deploy them again. Is this expected behaviour? It's not what I observe when deploying e.g. a Web App via an ARM template. Is there something specific I can do when deploying an ARM template for a Function App to preserve my deployed functions?
my-function-app.json:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
...
},
"variables": {
...
},
"resources": [
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('collectorFunctionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp",
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"siteConfig": {
"appSettings": [
{
...
}
]
}
}
}
],
"outputs": {}
}
Are you deploying your function as a package? If so, make sure you set this setting in your template, since it will be removed when you redeploy otherwise:
{
"name": "WEBSITE_RUN_FROM_PACKAGE",
"value": "1"
}
You could try "--mode incremental" parameter although that should be the default when it is not provided.
Yes that should be the expected behavior.
ARM Template is a declarative deployment meaning anytime you deploy it will overwrite anything you have with new template information. The template should always include everything you need.

Azure ARM Template to deploy website with cname and certificate

I'm trying to build a custom ARM template that deploys a new resource group (web,sql,redis,storage) that also creates a custom CNAME record in our dnsZone hosted in a different/existing resGroup. Finally, I'd like to add a certificate binding (wildcard) from our KeyVault also stored in the other resGroup.
It seems there is support for adding a zone in the new resGroup, but can't find example of leveraging existing zone and just adding a CNAME record that points to my new web app.
It also seems there are examples of creating Key Vaults, but not binding a site up to an existing cert in an existing vault in a different resGroup.
This is a very common multi-tenant kind of scenario, sure seems it should be possible in our template, without having to rely on PowerShell or Azure CLI.
Just wrap your dnsZone resource with a deployment resource and scope it to another group.
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": %%% resource group name goes here %%%,
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
%%%% dnsZone goes here %%%
]
},
"parameters": {}
}
}
For the KV, you can use the example from the quickstarts:
https://github.com/Azure/azure-quickstart-templates/blob/master/webapp-keyvault-ssl/azuredeploy.json

Azure ARM templates - using the output of other deployments

What I am interested in is reading the output parameters of another deployment in a different resource group.
My ARM templates are something like:
platform.json - sets up the DNS, virtual networks and security
storage.json - sets up databases and other stores
app.json - sets up the web app/api
Each is deployed in different resource groups as they have different life cycles. However, when I deploy the app.json I want to pull in the outputs of the latest platform and storage deployments and use them to configure the app.
Linked templates are not a solution as the linked templates end up deployed in the same resource group as the app which defeats the purpose of segregating your resources in resource groups.
Is there any way I can read the output parameters of a deployment from a different resource group? if not, is Azure planning to support it?
I know there is a way to get the resources by id, using the resourceId function, and look at their properties but I am trying to avoid doing that to not get into a resource reference spagetti.
I know this is an old question but for others who come along, as of 03/12/18 you can definitely do this.
You need to ensure your output is formatted as per the Microsoft documentation for output variables which broadly has the format
"outputs": {
"resourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_name'))]"
}
}
You can then use these outputs in your templates by referencing the deployment using a resource reference which has the format
reference(resourceName or resourceIdentifier, [apiVersion], ['Full'])
Note that you will need to provide the api version, as the deployment may use a different api version to the one your parent template uses.
Your reference would then look something like the following
{
"comments": "This would have an output named myOutput you want to use",
"apiVersion": "2017-05-10",
"type": "Microsoft.Resources/deployments",
"name": "my-deployment",
"resourceGroup": "...",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "...",
"contentVersion": "1.0.0.0"
},
"parameters": { }
},
{
"comments": "This makes use of myOutput from my-deployment",
"apiVersion": "2017-05-10",
"type": "Microsoft.Resources/deployments",
"name": "my-dependent-deployment",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "...",
"contentVersion": "1.0.0.0"
},
"parameters": {
"myValueFromAnotherDeployment": { "value": "[reference('my-deployment', '2017-05-10').outputs.myOutput.value]" }
}
}
}
Note the slightly awkward "repackaging" of the value, where we use myOutput.value as the input to the dependent deployment, and put that in an object with the key "value": "....". This is because ARM parameters must have a 'value' property in order to be valid.
You'll get invalid template errors if you try to use the output directly (because output variables have a 'type' and this is not an allowed key in a parameter). That's why you need to get the value property and then put it back into the value in downstream templates.
How are you doing your deployments? In PowerShell you can do something like:
(Get-AzureResourceGroupDeployment NameOfResourceGroup).Outputs.NameOfOuputProperty.Value
And that will give you the output of the most recent deployment. You can also throw the entire deployment object into a var and have at it that way.
$d = Get-AzureResourceGroupDeployment NameOfResourceGroup
Which would be faster if you needed a many output properties.
That help?
Update for AzureRM cmdlet
The syntax is largely the same:
(Get-AzureRmResourceGroupDeployment -ResourceGroupName NameOfResourceGroup -Name NameOfDeployment).Outputs.NameOfOutputProperty.value
If you have multiple deployments you can use:
Get-AzureRmResourceGroupDeployment -ResourceGroupName NameOfResourceGroup
To see them all and see what the names are...
Are you using Azure DevOps Release Pipelines? You could just set the output to be created as variables so you can re-use them in the same or a different stage.
We use these extensions on our projects
ARM Outputs
https://github.com/keesschollaart81/vsts-arm-outputs
VSTS replacetokens
https://github.com/qetza/vsts-replacetokens-task

Resources