How to Create Web Site ARM Template with Managed Identity? - azure

I am attempting to create Azure Resource Manager templates for several web sites that read secrets from a key vault. In reading How to use managed identities for App Service and Azure Functions, the documentation states that the web site ARM template should contain the following upon creation for authenticating with a key vault:
"identity": {
"type": "SystemAssigned"
}
Once the web site is created, the the identity section changes to the following:
"identity": {
"type": "SystemAssigned",
"tenantId": "<TENANTID>",
"principalId": "<PRINCIPALID>"
}
Does this mean that after running the ARM templates to create the web sites that I have to go back into the ARM template(s) and update the identity section for every site so that I can run the ARM templates to update the sites if need be?

no, you dont have to do that. that is expected. it will not delete that. just rerun it and nothing will change.

Related

Enable API Management access to the REST API with ARM template

I've created the ARM template for Azure API Management deployment. In order to enable its REST API I need to select the Enable API Management REST API checkbox in Azure Portal as explained here. I'd like to activate this option within the ARM template but I'm unable to find which resource to add/modify in my template to achieve it.
This one https://learn.microsoft.com/en-us/rest/api/apimanagement/2019-01-01/tenantaccess/update. In general whatever Azure portal does it does through same public API used by templates. So usually you can open browser dev console and see what call is being made behind the scenes.
If anyone is still looking for an answer, the below template does the job of enabling Management REST API in Azure APIM
{
"type": "Microsoft.ApiManagement/service/tenant",
"apiVersion": "2020-06-01-preview",
"name": "[concat(parameters('ApimServiceName'), '/access')]",
"dependsOn": [
"[resourceId('Microsoft.ApiManagement/service', parameters('ApimServiceName'))]"
],
"properties": {
"enabled": true
}
}

How retrieve the storage account connection string from seperate resource group

I have two resource group running in one subscription and inside the subscription I have two resource group for example: RG1 and RG2. RG1 contains a storage account whereas RG2 contains a web app.I have used an arm template to create the resources. Inside the app-settings in the RG2 web app,I have to manually pass the storage accounts' connection string from RG1. Is there any way to fetch the connection string dynamically using arm script,in this case?
Have you looked at using MSI authentication for your Web App. If you are deploying ARM add this to the Web App
"identity": {
"type": "SystemAssigned"
},
This will create a Managed Service Identity which will eliminage the need to even managed the connection string.
After the App has an MSI then in the Storage account grant the MSI an RBAC role to the storage account by looking up the associated Role ID
and configuring your ARM template to include the RBAC assignment.
Personally I tend to store my roles as json objects variables since the IDs are the same across all subscriptions. It makes them easier to assign to specific object or MSI IDs.
"Contributor": {
"RoleID": "[concat(variables('roleDefinition'), 'b24988ac-6180-42a0-ab88 20f7382dd24c')]",
"RoleName": "Contributor"
},
That way when doing the assignment it would look like:
{
"type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[concat(variables('storageName'), '/Microsoft.Authorization/', guid(uniqueString(variables('storageName'),variables('Reader').RoleName,parameters('principalId'))))]",
"dependsOn": [
"[variables('storageName')]"
],
"properties": {
"roleDefinitionId": "[variables('Contributor').RoleID]",
"principalId": "[reference(resourceId('Microsoft.Web/sites', variables('webSiteName')), '2018-02-01', 'Full').identity.principalId]"
}
}
You may need to tweak since the storage account and Web App are in different resource groups but hopefully this gets you started.
If you aren't comfortable with the MSI piece or unable to other options would be to store the secret for the connection in KeyVault and have your Web App call that to get the secret.

ARM Template: Looking up a user object Id

I'm trying to programatically insert the object Id of a certain user account into an ARM template, like this:
"objectId": "[reference(resourceId('Microsoft.AAD/domainServices/user/read','domain','User.Name'),'2019-01-01').Id]",
I've tried many different resource providers in an attempt to get this to work. For example:
"objectId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/read','user#domain.onmicrosoft.com'),'2019-01-01').Id]",
and:
"objectId": "[reference(resourceId('Microsoft.Portal/usersettings/read','user#domain.onmicrosoft.com'),'2018-10-01').Id]"
I looked up the API call used to get a list of users, to see if that would hint at the correct provider to use (it didn't):
GET https://graph.windows.net/{TenantId}/users?api-version=1.6 HTTP/1.1
I've been looking through this list of provider operations but have found two problems with this:
1 I can't see an operation which looks relevant to what I want to do.
2 It doesn't provide information on what parameters are required.
So I guess I have two questions really:
How do I dynamically look up the ObjectId of a user in an ARM template?
How do I find out in future which lookup functions are available and which parameters are required?
You could not insert the user object Id in the ARM template.
The user account is managed by your Azure AD tenant, it is not the azure resource, the ARM template is for the azure resources in your subscription.
Reference:https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview
Azure Resource Manager is the deployment and management service for Azure. It provides a consistent management layer that enables you to create, update, and delete resources in your Azure subscription.
You can try from below code if you have VM in same template and enabled managed identity
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#remarks-1
{
"type": "Microsoft.KeyVault/vaults",
"properties": {
"tenantId": "[reference(concat('Microsoft.Compute/virtualMachines/', variables('vmName')), '2017-03-30', 'Full').identity.tenantId]",
"accessPolicies": [
{
"tenantId": "[reference(concat('Microsoft.Compute/virtualMachines/', variables('vmName')), '2017-03-30', 'Full').identity.tenantId]",
"objectId": "[reference(concat('Microsoft.Compute/virtualMachines/', variables('vmName')), '2017-03-30', 'Full').identity.principalId]",
"permissions": {
"keys": [
"all"
],
"secrets": [
"all"
]
}
}
]
I find the best way to achieve this is to expose the ID as a parameter, then when you call the ARM template deployment, simply pass the parameter into the template.
How do you get the ID into the template parameter? Well, I run my ARM deployments via Azure DevOps CI/CD and I use the pipeline task AzureAppConfiguration.azure-app-configuration-task.custom-build-release-task.AzureAppConfiguration#1 to extract the ID from my own custom configuration setup.
How do you get the ID into the Azure App Configuration service? Well, when I seed an environment for the first time there will be some initial setup, e.g. users and groups. I just then run some scripts to extract this kind of "metadata" into my Azure App Configuration service.
e.g.
APP_ID=$(az ad sp list --all --query "[?displayName=='name-of-spn'].appId" --output tsv)
az appconfig kv set --name name-of-app-config-store --key name-of-spn-app-id --value ${APP_ID}
I think I have solution.
I am tying to refer to a Client ID in a Managed User Identity generated by an ARM template.
I have declared the name of the Managed Identity as a Parameter to use as an administrator for an SQL server:
[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities',parameters('managed-identity')), '2018-11-30', 'full').properties.clientId]
Once you switch our the parameter you should be good to go.

Create SubscriptionCloudCredentials for WebSiteManagementClient without Azure AD Application

I'm looking for a simple solution to Authenticate and use the WebSiteManagementClient. The examples I've seen utilize an Azure AD Application to create the SubscriptionCloudCredentials required. I would prefer to create the SubscriptionCloudCredentials without the use of an AD Application.
If at all possible, I would prefer to just use the Web Deploy un/pw credentials found in the Publish Profile Settings XML (as I already have code that uses these to interact with the kudu api with basic auth)
I found this potential solution that instead uses a management certificate (more info). But again, if at all possible, I would prefer to just use the Web Deploy un/pw.
(I understand the management cert is at a subscription level, and the Web Deploy un/pw are at a App Service/WebSite instance level. I'm just stating what my desired solution would look like.)
Management certificates allow you to authenticate only with the classic deployment (Azure Service Management) model and not the Azure Resource Management deployment model.
If your web app is not created using the classic deployment model, you'll need a TokenCloudCredential instead of the CertificateCloudCredential.
Technically, you can still create Certificate-based SubscriptionCloudCredentials but it will only work with Azure web app created with the classic deployment model.
I would prefer to just use the Web Deploy un/pw.
If you want to upload certificate to Azure WebApp during Web Deploy then we can use ARM template , more details please refer to the document.
{
"name": "[parameters('certificateName')]",
"apiVersion": "2014-04-01",
"type": "Microsoft.Web/certificates",
"location": "[resourceGroup().location]",
"properties": {
"pfxBlob": "pfx base64 blob",
"password": "some pass"
}
}
About how to create subscriptionCloudCredentials with certificate and how to create customized cert, I did a demo for it. More details please refer to another SO thread.
If we try to run the project on the Azure. Please refer to document Using Certificates in Azure Websites Applications. Adding an app setting named WEBSITE_LOAD_CERTIFICATES with its value set to the thumbprint of the certificate will make it accessible to your web application
So we also need to add the AppSetting in the ARM template, more detail info please refer to the document.
  
{
"name": "appsettings",
    "type": "config",
    "apiVersion": "2015-08-01",
    "dependsOn": [
        "[concat('Microsoft.Web/sites/', variables('webSiteName'))]"
    ],
    "tags": {
        "displayName": "WebAppSettings"
    },
    "properties": {
        " WEBSITE_LOAD_CERTIFICATES ": "thumbprint "
    }

Configuring Azure Batch using an Azure Resource Manager template

I'm looking for any examples of configuring Azure Batch using an Azure Resource Manager template. Googling yielded nothing, and the Azure QuickStart Templates do not yet have any Batch examples, however this SO question implies that it has been done.
What I would like to achieve is, via an ARM template, to create a Batch account and configure a pool (with a minimum number of compute nodes, auto expanding to a maximum number of nodes), and then set the resulting pool ID into my API server's appsettings resource.
I'm about to start reverse engineering it using the Azure Resource Explorer, but any pre-existing examples would be very much appreciated.
Update
So far I've managed to create the resource:
{
"name": "[variables('batchAccountName')]",
"type": "Microsoft.Batch/batchAccounts",
"location": "[resourceGroup().location]",
"apiVersion": "2015-07-01",
"dependsOn": [ ],
"tags": {
"displayName": "BatchInstance"
}
}
And to configure the account settings in the appsettings of my API server:
"BATCH_ACCOUNT_URL": "[concat('https://', reference(concat('Microsoft.Batch/batchAccounts/', variables('batchAccountName'))).accountEndpoint)]",
"BATCH_ACCOUNT_KEY": "[listKeys(resourceId('Microsoft.Batch/batchAccounts', variables('batchAccountName')), providers('Microsoft.Batch', 'batchAccounts').apiVersions[0]).primary]",
"BATCH_ACCOUNT_NAME": "[variables('batchAccountName')]"
I still haven't managed to create a pool and fetch the pool ID via ARM, mainly because the pool I created using Batch Explorer never showed up in either the Azure Portal or the Azure Resource Explorer. I'll update this if I find the solution.
Unfortunately we don't have a way today to create a pool using ARM templates. The Azure Portal should show the pools created under your account (even if you didn't created them using ARM).
This is supported, please see the reference docs here: https://learn.microsoft.com/azure/templates/microsoft.batch/2019-04-01/batchaccounts/pools

Resources