Create database account on Azure with specific password using ARM templates - azure

I want to run Azure Resource Group Deployment as part of my deployment process. This should create two resources: App Service (asp.net core) and DocumentDB account.
After that I need to store account credentials (account name and password) in App Settings block of my App Service. Normally I could configure App Service to read the password from existing Azure Key Vault.
But if the database account is not created yet, the password is generated automatically and I would need to update it manually.
Is it possible to create the database account specifying the password (reading value from Key Vault)? This way the deployment would be automated whether the database account was created or not.

I don't see where's the problem in this one, just specify the secret in your template:
"parameters": {
"adminPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/{guid}/resourceGroups/{group-name}/providers/Microsoft.KeyVault/vaults/{vault-name}"
},
"secretName": "sqlAdminPassword"
}
}
}
https://azure.microsoft.com/en-us/documentation/articles/resource-manager-keyvault-parameter/

Related

How to read and update secrets information in parameters.json file of Azure Logic App from Azure Key Vault

I have Azure Logic App that processes messages from Service Bus session-based queue using When one or more messages arrive in a queue (peek-lock) connector and then inserting into SQL Database.
Note: In Azure Logic App, this is When one or more messages arrive in a queue (peek-lock) first trigger.
I want to protect the connection strings of Azure Service Bus and Azure SQL Database. For that I used Azure Key Vault to store connection strings information of Azure Service Bus and Azure SQL Database.
I have followed this documentation to read secrets from Azure Key Vault.
But I want to use the secrets information in parameters.json file. Because currently I have hardcoded the connection strings of Azure Service Bus and Azure SQL Database in parameters.json file.
So, can anyone suggest me ead and update secrets information in parameters.json file of Azure Logic App from Azure Key Vault.
Azure Resource Manager Templates allow for integration of parameters with KeyVault to pull secrets from it.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/key-vault-parameter?tabs=azure-cli
Which should look like this
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminLogin": {
"value": "exampleadmin"
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.KeyVault/vaults/<vault-name>"
},
"secretName": "ExamplePassword"
}
},
"sqlServerName": {
"value": "<your-server-name>"
}
}
}
Remember to add Logic Apps secret obfuscation
https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app#secure-data-in-run-history-by-using-obfuscation

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.

Specify Function App Configuration with Key Vault Reference in Azure ARM Template

Is there a way to specify KeyVault References in Function App configuration within my ARM template?
I have an ARM template that will deploy an Azure Function App with different deploy parameter for each environment. Currently I am retrieving the secret in my environment via references in the parameter:
{
"storageAccountSecret": {
"reference": {
"keyVault": {
"id": "/subscriptions/plan-id-goes-here/resourceGroups/group-name-goes-here/providers/Microsoft.KeyVault/vaults/vault-name-goes-here"
},
"secretName": "super-secret-name-goes-here"
}
}
I then reference the parameter in the ARM template, resources -> properties -> siteConfig -> appSettings
{
"name": "AzureWebJobsStorage",
"value": "[parameters('storageAccountSecret')]"
},
Above works fine! However, our team also periodically rotate our keys which change the underlying value of the secret. With my current approach, the secret on this function app config won't update until we run the ARM template again.
My get around is to use KeyVault Reference in the config, with the following syntax in the configuration.
#Microsoft.KeyVault(SecretUri=https://vault-name-goes-here.vault.azure.net/secrets/super-secret-name-goes-here/)
Now when the underlying secret changes, my function App will still get the up to date secret. However this require me to do it manually. I would love to achieve the same effect with just the ARM template alone, is that possible? 🤔
For exactly that reason you should always use the full URL to your secrets in Key Vault - including the version. See here.
When you update a secret in Key Vault, you get a new URL. Once you update the app setting (through your ARM template or any other way), the Function will be restarted. This is the desired behavior when updating app settings.

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.

Logic apps in a multi tenant environment

We are planning to build a SFTP connector using logic apps which will basically take a file uploaded to azure blob and upload it to a sftp location.
We are SaaS product and are dealing with multiple customers. Also we have storage accounts per customer or tenant.
My questions is how would this logic app should be Deployed
1. should it be a single logic app which can listen to multiple storage accounts and upload the files .Right now I cant figure out how this can be done.
2. Should it be a logic app / tenant configured one to one with the storage account of the tenant
I would like to know what is the usual pattern followed in a multi-tenant environment and are their any pros / cons of deploying a logic app / tenant.
You don't need to create one Logic App per tenant. What you could do is to create an API connection per storage account (per tenant). You could do it with ARM Templates and Azure CLI. You could give the API connection an Id based on your tenantId
Then, in your Logic App workflow you can chose at run time the API connection dynamically, depending on the tenant Id.
e.g.
"Get_blob_content": {
"inputs": {
"host": {
"connection": {
"name": "/subscriptions/<id>/resourceGroups/<id>/providers/Microsoft.Web/connections/#{variables('tenantId')}"
}
},
"method": "get",
"path": "/datasets/default/files/.../content",
"queries": {
"inferContentType": true
}
},
"metadata": {
"...": "..."
},
"runAfter": {},
"type": "ApiConnection"
}
It would be up to you to decide how to name the API Connection, how to get it at runtime, and how to get the full connectionId at runtime. But hopefully you get the idea of what you can do the code above.
HTH

Resources