Azure Storage blob container assign RBAC using ARM - azure

We currently have ARM templates that create storage accounts and containers in a solution however I can't seem to manage to assign the RBAC access to the container in the ARM template. I have tried using Erik's solution here
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"apiVersion": "2017-09-01",
"name": "[concat(parameters('storageAccountName'),'/default/filedrop/Microsoft.Authorization/{NEW GUID}')]",
"properties": {
"roleDefinitionId": "ba92f5b4-2d11-453d-a403-e96b0029c9fe",
"principalId": "[parameters('ServicePrincipalId')]"
}
The error I get is "error": {
"code": "BadRequestFormat",
"message": "The request was incorrectly formatted."
}
Anyone see where I'm going wrong?

Here is what I used: https://github.com/juunas11/managedidentity-filesharing/blob/8410ed3f3d4061de7d40531c025bf6e474489135/Joonasw.ManagedIdentityFileSharingDemo.ARM/azuredeploy.json#L223-L236
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"apiVersion": "2018-01-01-preview",
"name": "[concat(parameters('storageAccountName'), '/default/', parameters('storageContainerName'), '/Microsoft.Authorization/', guid(resourceGroup().id, 'webAppFilesAccess'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), 'default', parameters('storageContainerName'))]",
"[resourceId('Microsoft.Web/sites', parameters('webAppName'))]"
],
"properties": {
"principalId": "[reference(resourceId('Microsoft.Web/sites', parameters('webAppName')), '2016-08-01', 'Full').identity.principalId]",
"roleDefinitionId": "[variables('storageBlobContributorRoleId')]"
}
}
The main difference I can see is that I have a higher API version + I use parameters for a lot of things.
The guid() function is pretty handy since you can give it some text, and if the text is same, it'll give the same GUID every time.

Related

ARM Template Issues Create resource with cyclical dependancy (Webapp Custom Domain, Self Managed Cert then Bind Cert)

I have a real chicken and egg situation. Also i am quite new to ARM so maybe missing something glaringly obvious.
Previously we had an arm template that worked using a certificate from a keyvault which was fine.
hostnamebindings resources created the custom domain and binding.
However we want to move to use the explicit self managed certificates in azure for the web service but are hitting some issues at the last hurdle.
The certificate is dependant on the custom domain as without it it fails to deploy but we can not reference the same resource twice in the template without it erroring.
Order must be:
Create custom domain
Create certificate
Bind certificate
ARM template extract below.
{
"condition": "[equals(parameters('UseCustomDomain'),'True')]",
"Comments": "If custom domain is selected then add to the webapplication",
"type": "Microsoft.Web/sites/hostnameBindings",
"apiVersion": "2022-03-01",
"name": "[concat(variables('appName'), '/', variables('DomainName'))]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('appName'))]"
],
"properties": {
"domainId": null,
"hostNameType": "Verified",
"siteName": "variables('DomainName')"
}
},
{
"type": "Microsoft.Web/certificates",
"apiVersion": "2021-03-01",
"name": "[variables('DomainName')]",
"Comments": "Creating Subdomain Certificate",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('AppName'))]",
"[resourceId('Microsoft.Web/sites/hostnameBindings/',variables('appName'), variables('DomainName'))]"
],
"properties": {
"hostNames": [
"[variables('DomainName')]"
],
"canonicalName": "[variables('DomainName')]",
"serverFarmId": "[variables('ServerFarmID')]"
}
},
What I would like to do is add the following properties after the the certificate is created to the hostnamebindings resource.
"sslState": "[if(variables('enableSSL'), 'SniEnabled', json('null'))]",
"thumbprint": "[if(variables('enableSSL'), reference(resourceId('Microsoft.Web/certificates', variables('DomainName'))).Thumbprint, json('null'))]"
Is there a way to make individual properties dependant on a resource? When i try the below in the hostname bindings properities i get a "Deployment template validation failed: 'Circular dependency detected on resource"
"properties": { "domainId": null, "hostNameType": "Verified", "siteName": "variables('DomainName')", "dependsOn": [ "[resourceId('Microsoft.Web/certificates', variables('DomainName'))]" ], "sslState": "[if(variables('enableSSL'), 'SniEnabled', json('null'))]", "thumbprint": "[if(variables('enableSSL'), reference(resourceId('Microsoft.Web/certificates', variables('DomainName'))).Thumbprint, json('null'))]" }
Any help greatly appreciated.

ARM Create nested Management Group

I try to create an ARM Template for building the ground structure with ManagementGroups
and Subscriptions. My current problem is that I can't create nested Management Groups,
did somebody already something similiar?
I already have seen this Doc Article:
https://learn.microsoft.com/en-us/azure/templates/microsoft.management/managementgroups?tabs=json
See https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deploy-to-management-group?tabs=azure-cli#management-group
You need to specify properties.details.parent.id:
"resources": [
{
"name": "[parameters('mgName')]",
"type": "Microsoft.Management/managementGroups",
"apiVersion": "2020-05-01",
"scope": "/",
"location": "eastus",
"properties": {
"details": {
"parent": {
"id": "[tenantResourceId('Microsoft.Management/managementGroups', parameters('parentMG'))]"
}
}
}
}
],

How to assign RBAC to multiple user using arm template in azure

I have two AAD Application(Service principal) and want to add RBAC to these two Application using arm template.
I tried deploying with arm template below.
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[concat(parameters('StorageAccountName'), '/default/',parameters('ContainerName'), '/Microsoft.Authorization/', parameters('roleNameGuid'))]",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
"principalId": "[parameters('principalId')]"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[concat(parameters('StorageAccountName'), '/default/',parameters('ContainerName'), '/Microsoft.Authorization/', parameters('roleNameGuid'))]",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
"principalId": "[parameters('principalId2')]"
}
}
When I deploy with this arm template, I got error below.
Deployment template validation failed: 'The resource 'Microsoft.Storage/storageAccounts/MystorageAccounts/blobServices/default/containers/test/providers/Microsoft.Authorization/roleAssignments/aacd4b89-a70f-4be9-a0ba-6b8698dd7129' at line '52' and column '9' is defined multiple times in a template. Please see https://aka.ms/arm-template/#resources for usage details.'. (Code: InvalidTemplate)
You need to use different names for the name option in the resource. For example, you can append a number at the end of the name to distinguish the difference.
Wouldn't this work as well, and take away the hardcoded value of the guid?:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-string#guid
Yes it will require some input to calculate a different GUID, but you could use property iteration to change that:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration

Deploy nested resources separately

Due to separation of duty I need to split an existing ARM template into two single templates - one for the resource and one for the logging
the original templates looks like this:
"resources": [
{ // https://learn.microsoft.com/en-us/azure/templates/microsoft.datafactory/factories
"type": "Microsoft.DataFactory/factories",
"name": "[variables('dataFactoryName')]",
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"tags": {},
"identity": {
"type": "SystemAssigned"
},
"properties": {},
"resources": [
{
"type": "providers/diagnosticSettings",
"name": "[concat('Microsoft.Insights/', variables('logSettingName'))]",
"dependsOn": [
"[resourceId('Microsoft.DataFactory/factories', variables('dataFactoryName'))]"
],
"apiVersion": "2017-05-01-preview",
"location": "[resourceGroup().location]",
"tags": {},
"properties": {
"name": "[variables('logSettingName')]",
"workspaceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('logAnalyticsObject').resourceGroup, '//providers/Microsoft.OperationalInsights/workspaces/', parameters('logAnalyticsObject').name)]",
"logs": "[parameters('logAnalyticsObject').adfv2.logs]",
"metrics": "[parameters('logAnalyticsObject').adfv2.metrics]"
}
}
]
}
The first part is quite easy, I just remove the sub-resource but how to get the second part (resource with "type": "providers/diagnosticSettings") correctly so it can be deployed from a different template?
Is this possible at all or are these strongly tied together?
I already tried different things like
"type": "Microsoft.DataFactory/factories/providers/diagnosticSettings",
"name": "[concat('Microsoft.Insights/', variables('name'))]",
but ended up with error messages like this:
Unable to process template language expressions for resource '/subscriptions/fb1e20c4-0878-4949-ac10-f92a9ac35db4/resourceGroups/swe-sdp-dv0
-rgp-adp/providers/Microsoft.Resources/deployments/DataFactory_LogAnalytics_Resource' at line '67' and column '5'. 'Unable to evaluate template language
function 'resourceId': function requires exactly one multi-segmented argument which must be resource type including resource provider namespace. Current
function arguments 'fb1e20c4-0878-4949-ac10-f92a9ac35db4,swe-sdp-dv0-rgp-anl,Microsoft.Insights,swe-sdp-dv0-oms-001'. Please see
https://aka.ms/arm-template-expressions/#resourceid for usage details.
I think to make it work I would need the right combination of "type", "name" and probably also "dependsOn"
ok, according to this, you would need to do this:
"type": "Microsoft.DataFactory/factories/providers/diagnosticSettings",
"name": "[concat(variables('dataFactoryName'), '/Microsoft.Insights/', variables('name'))]",
you dont need dependsOn, because resources are under different templates.

What are the properties in an ARM template for a Dynamics 365 CRM logic app connector?

Logic app connectors are closed source and the 'Automation Script' option in the Azure portal strips the authentication portions of the properties node from connectors. This is what the portal hands you when you script out the ARM template for a logic app which talks to CRM.
{
"comments": "Generalized from resource: '/subscriptions/<guid>/resourceGroups/<resource group name>/providers/Microsoft.Web/connections/dynamicsCRMconnector'.",
"type": "Microsoft.Web/connections",
"name": "[parameters('connections_dynamicsCRMconnector_name')]",
"apiVersion": "2016-06-01",
"location": "eastus",
"scale": null,
"properties": {
"displayName": "CRMConnection",
"customParameterValues": {},
"api": {
"id": "/subscriptions/<guid>/providers/Microsoft.Web/locations/eastus/managedApis/dynamicscrmonline"
}
},
"dependsOn": []
}
The other connectors (SFTP, storage account, etc.) have the missing elements node documented here and there (nothing official from MS, but blog posts and sample code) but I can't find the information for the Dynamics connectors. As an example of what I would expect to see, here is how SFTP and storage accounts can be pre-configured with authentication values in ARM:
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[variables('sftp_conn_friendly_name')]",
"location": "[resourceGroup().location]",
"properties": {
"displayName": "SFTP connection",
"parameterValues": {
"hostName": "[variables('sftp_host')]",
"userName": "[variables('sftp_user')]",
"password": "[variables('sftp_pass')]",
"portNumber": "[variables('sftp_port')]",
"giveUpSecurityAndAcceptAnySshHostKey": true,
"disableUploadFilesResumeCapability": false
},
"api": {
"id": "[variables('sftp_conn_managed_id')]"
}
}
},
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[variables('storage_conn_friendly_name')]",
"location": "[resourceGroup().location]",
"properties": {
"displayName": "Blob connection",
"parameterValues": {
"accountName": "[variables('storage_account_name')]",
"accessKey": "[listKeys(variables('storage_account_name'),'2015-05-01-preview').key1]"
},
"api": {
"id": "[variables('storage_conn_managed_id')]"
}
}
}
While not a direct answer to your question, but a more general answer giving you idea how to act in such a situation. If its not documented anywhere your only hope is reversing it (and more often than not it works).
First of all, this connecter is a resource in Azure (like the ones you've written). You can use any of the available ways to get the resource properties (https://resource.azure.com, Get-AzureRmResource, REST API, various SDKs) and see what the values are like there.
Another way of going about this - creating this connector using the portal and capturing traffic with fiddler. That way you will see the exact REST call needed to créate such a connector and would be able to replicate it using ARM Template. You might not know that ARM Templates are basically proxies for REST calls. Each resource you are creating is being converted to a REST call and performed against the appropriate resource provider.

Resources