How retrieve the storage account connection string from seperate resource group - azure

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.

Related

Azure "Service Catalog Managed Application" working, but not listed

I have followed this MS documentation, to create the following github "Managed App" sample. I have proven it works, because I can successfully execute the following steps:
Open my subscription (the one containing the managed app
definition).
Select "Resources".
Select "StorageApp" (which is my
custom name of my managed app). The managed app custom "StorageApp" blade opens.
Select "Deploy".
However, according to additional MS documentation, I should also be able to find my managed application by selecting "create new resource" and then choosing from the "Service Catalog Managed Application" interface. When I attempt to do that, and select "Create"...I am given the following message:
You don't have any service catalog definitions available yet. To add a service catalog definition, please see service catalog getting started.
That message is incorrect. The aforementioned custom "StorageApp" is indeed working (as stated above) - and thus should be part of my service catalog definition. Why am I unable to see it? Having followed the documentation, I am "Owner" of the resource group to which my managed app definition belongs...I would think that this entitles me to see it appear in the service catalog.
Is there some kind of Azure Service Catalog "registration" step for Managed Apps that the documentation isn't mentioning? Or perhaps I have a type of subscription that does not allow use of the Service Catalog, which the documentation didn't explain?
The link provided by the error message outlines five essential steps that must be completed. Those steps are as follows and, by using the aforementioned github Managed App sample that Microsoft supplied, I have completed all of them:
Create ARM template which defines the resources.  
Define user interface elements for Azure portal.
Create zip package containing both of the above.
Decide which user, group, or app needs access to the resource group in the user's subscription. [See caveat below]
Create managed application definition.
The only step where I could imagine something being wrong, is step 4. The "resource group in the user's subscription" is a vague statement. Presumably there is no "resource group in the user's subscription" until AFTER the managed app is deployed. Nevertheless, per instructions, there is only one defined resource group to apply this rule to. Namely, the resource group into which the Managed App Definition itself was created. I am the "Owner" of that resource group, so assuredly that is sufficient permission to see it listed.
What am I doing wrong?
For the sake of reference, when I successfully create my managed app definition from the Azure Cloud Shell, this is the output that is provided:
{
"artifacts": [
{
"name": "ApplicationResourceTemplate",
"type": "Template",
"uri": "https://prdsapplianceprodbl01.blob.core.windows.net/applicationdefinitions/8B3AF_DCC89FF251A04A29A2B22A03A34D8474_2FB5E19B164254D69C0312247435EFA170C8BF604673BD8F38FB35C648EDF21D/717c7a71e1c74c4da0727b53b6593e14/applicationResourceTemplate.json"
},
{
"name": "CreateUiDefinition",
"type": "Custom",
"uri": "https://management.azure.com/subscriptions/dcc89ff2-51a0-4a29-a2b2-2a03a34d8474/resourceGroups/msdocs-managed-rg/providers/Microsoft.Solutions/applicationDefinitions/StorageApp/applicationArtifacts/CreateUiDefinition?api-version=2017-09-01"
},
{
"name": "MainTemplateParameters",
"type": "Custom",
"uri": "https://management.azure.com/subscriptions/dcc89ff2-51a0-4a29-a2b2-2a03a34d8474/resourceGroups/msdocs-managed-rg/providers/Microsoft.Solutions/applicationDefinitions/StorageApp/applicationArtifacts/MainTemplateParameters?api-version=2017-09-01"
}
],
"authorizations": [
{
"principalId": "b306aac2-af03-4763-88b5-5eb0bd2c0840",
"roleDefinitionId": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
}
],
"createUiDefinition": null,
"description": "Managed Azure Storage Account",
"displayName": "Managed Storage Account",
"id": "/subscriptions/dcc89ff2-51a0-4a29-a2b2-2a03a34d8474/resourceGroups/msdocs-managed-rg/providers/Microsoft.Solutions/applicationDefinitions/StorageApp",
"identity": null,
"isEnabled": "True",
"location": "eastus",
"lockLevel": "ReadOnly",
"mainTemplate": null,
"managedBy": null,
"name": "StorageApp",
"packageFileUri": null,
"resourceGroup": "msdocs-managed-rg",
"sku": null,
"tags": null,
"type": "Microsoft.Solutions/applicationDefinitions"
}

How to assign an App Service system managed identity App Configuration Data Reader role for a specific App Configuration resource in ARM

I would like to add role assigment from my App Configuration to my App Service. In Azure portal i can do it like this: App Configuration -> Access control (IAM) -> Add role assigment -> App Configuration Data Reader -> Assign access to Managed identity -> Select Members (choose my app service) -> Save
But now i want to do this through ARM template, currently I dont even know from where I should start, because in Microsoft ARM Docs i dont see something like this: https://learn.microsoft.com/en-us/azure/templates/microsoft.appconfiguration/configurationstores?pivots=deployment-language-arm-template
First enable the system assigned identity in configuration stores resource:
"identity": {
"type": "SystemAssigned"
}
Then better to declare a variable and get the subscription resource id by providing role definition id that you can find by going to Add role assignment screen in IAM for your app configuration service in azure portal:
"roleAppConfigDataReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', <Your role definition id for AppConfigDataReader>)]"
Then you will include it in the configuration stores resource's json:
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2018-01-01-preview",
"scope": "[format('Microsoft.AppConfiguration/configurationStores/{0}', <YourConfigStoreName>)]",
"name": "[guid(resourceId('Microsoft.Web/sites', <YourAppServiceName>)), resourceId('Microsoft.AppConfiguration/configurationStores', <YourConfigStoreName>), variables('roleAppConfigDataReader'))]",
"properties": {
"roleDefinitionId": "[variables('roleAppConfigDataReader')]",
"principalId": "[reference(resourceId('Microsoft.Web/sites', <YourAppServiceName>), '2021-02-01', 'full').identity.principalId]"
},
"dependsOn": [
"[resourceId('Microsoft.AppConfiguration/configurationStores', <YourConfigStoreName>)]"
]
}
Please take help from the samples Microsoft provides from this link:
https://learn.microsoft.com/en-us/samples/browse/?expanded=azure&products=azure-resource-manager

Azure logic app - How can I share integration account across multiple resource groups

I am trying to deploy my logic app to multiple environments using CI/CD pipeline. I am getting an error -The client 'guid' with object id ''guid' ' has permission to perform action 'Microsoft.Logic/workflows/write' on scope 'Test Resource group'; however, it does not have permission to perform action 'Microsoft.Logic/integrationAccounts/join/action' on the linked scope(s) 'Development Resource group integration account' or the linked scope(s) are invalid.
Creating another integration account for test resource group doesnt come under free tier. Is there a way to share integration account across multiple resource groups
Not sure what the permissions issue is but you might need to give more information around this.
But try the below first in your pipeline. Works for us with 3 different resource groups and two integration accounts
"parameters": {
"IntegrationAccountName": {
"type": "string",
"minLength": 1,
"defaultValue": "inter-account-name"
},
"Environment": {
"type": "string",
"minLength": 1,
"defaultValue": "dev"
}
},
"variables": {
"resourceGroupName": "[if(equals(parameters('Environment'), 'prd'),'rg-resources-production','rg-resources-staging')]",
"LogicAppIntegrationAccount": "[concat('/subscriptions/3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4/resourceGroups/',variables('resourceGroupName'),'/providers/Microsoft.Logic/integrationAccounts/',parameters('IntegrationAccount'))]",
},
In the above sample, we had two different integration accounts one for testing and one for production. This is why I have set the integration account name as a parameter as it changes between environments.
I have created a variable "resourceGroupName" this is important because this url is setting up a direct link to the integration account which is stored in a known resource group. In this sample I have included an if statement using the value set at the "environment" parameter. This helps select which resource group is going to be used.
I then create another variable which stores the new URL. Replace the subscription guid with your own: 3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4.
Once that is created you need to change the ARM template to use the variable you just created. To set it,place in the properties object.
"properties": {
"state": "Enabled",
"integrationAccount": {
"id": "[variables('LogicAppIntegrationAccount')]"
},
So for you pipeline it should just be a normal arm template but with these two parameters above being set.
Let me know if you have more questions around this.

How to Create Web Site ARM Template with Managed Identity?

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.

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.

Resources