Create SQL Server via Azure Resource Manager (ARM) template - sql-server

I am trying to create a new Azure instance of SQL Server in which I would like to then create a few new databases.
I know from the Azure Portal that some sort of admin users could be:
an SA user (I think this means "Server Admin" and it looks like some sort of old way of managing a SQL Server instance, but at the same time very "basic" and proved to work)
an Active Directory user (not sure about Azure terminology here, but it looks like this could be some "broad user" for the whole Azure platform, like e.g. my own login user for the Azure Portal, this is not specific to databases world).
I would like to create a SQL Server with a SA user to administer the server. From the Azure portal I can not find a way to generate an ARM template for a SA user for the SQL Server instance.
I am copy pasting from a 10000 lines ARM template for a very long list of SQL servers and databases but I am not able to isolate the basic steps to have a hopefully clean and short ARM template to start with.
This is the ARM template I am trying to deploy on Azure:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "westeurope"
},
"foo_sql_server_name": {
"defaultValue": "foo-sql-server",
"type": "String"
}
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"kind": "v12.0",
"name": "[parameters('foo_sql_server_name')]",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('location')]",
"scale": null,
"properties": {
"administratorLogin": "<MY_SA_USER_THAT_I_CAN_NOT_CREATE>",
"version": "12.0"
},
"dependsOn": []
}
]
}
When running the above with:
az group deployment create \
--name "deployDBs" \
--resource-group "MyCustomResourceGroup" \
--template-file ./templates/db.json # --verbose --debug
Then I get the following error message:
Deployment failed. Correlation ID: <A_CUSTOM_GUID>. {
"status": "Failed",
"error": {
"code": "ResourceDeploymentFailure",
"message": "The resource operation completed with terminal provisioning state 'Failed'.",
"details": [
{
"code": "InvalidParameterValue",
"message": "Invalid value given for parameter Password. Specify a valid parameter value."
}
]
}
}
When removing the JSON field administratorLogin (because hopefully I could create the SA user somehow somewhere else that I yet have to figure out), then I get the following error message:
Deployment failed. Correlation ID: <ANOTHER_CUSTOM_GUID>. {
"status": "Failed",
"error": {
"code": "ResourceDeploymentFailure",
"message": "The resource operation completed with terminal provisioning state 'Failed'.",
"details": [
{
"code": "InvalidParameterValue",
"message": "Invalid value given for parameter Login. Specify a valid parameter value."
}
]
}
}
I am not able to find the definition for the pair "username password" for the SA user (Server Admin) from the 10000 lines auto-generated ARM template.
How could I create/inject a SA user for the SQL Server while deploying a new instance of a SQL Server?

The sa login you use on an on-premises SQL Server instance is known on Azure SQL as the Admin login. You can provide the name of the admin login and its password as parameter as shown on below sample template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"yourservernameName": {
"type": "string",
"defaultValue": "yourservername2"
},
"yourservernameAdminLogin": {
"type": "string",
"defaultValue": "VeryWiseAdmin",
"minLength": 1
},
"yourservernameAdminLoginPassword": {
"type": "securestring",
"defaultValue": "ReplaceWithTheMostSecurePasswordThatEverExisted&NeverShareLikeThisWithAnyone!"
},
"dbnameName": {
"type": "string",
"defaultValue": "dbname",
"minLength": 1
},
"dbnameCollation": {
"type": "string",
"minLength": 1,
"defaultValue": "SQL_Latin1_General_CP1_CI_AS"
},
"dbnameEdition": {
"type": "string",
"defaultValue": "Basic"
},
"dbnameRequestedServiceObjectiveName": {
"type": "string",
"defaultValue": "Basic"
}
},
"variables": {
},
"resources": [
{
"name": "[parameters('yourservernameName')]",
"type": "Microsoft.Sql/servers",
"location": "West Europe",
"apiVersion": "2014-04-01-preview",
"dependsOn": [],
"tags": {
"displayName": "yourservername"
},
"properties": {
"administratorLogin": "[parameters('yourservernameAdminLogin')]",
"administratorLoginPassword": "[parameters('yourservernameAdminLoginPassword')]",
"version": "12.0"
},
"resources": [
{
"name": "[concat(parameters('yourservernameName'),'/AllowAllWindowsAzureIps')]",
"type": "Microsoft.Sql/servers/firewallRules",
"location": "[resourceGroup().location]",
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('yourservernameName'))]"
],
"properties": {
"startIpAddress": "0.0.0.0",
"endIpAddress": "0.0.0.0"
}
},
{
"name": "[concat(parameters('yourservernameName'),'/',parameters('dbnameName'))]",
"type": "Microsoft.Sql/servers/databases",
"location": "West Europe",
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('yourservernameName'))]"
],
"tags": {
"displayName": "dbname"
},
"properties": {
"collation": "[parameters('dbnameCollation')]",
"edition": "[parameters('dbnameEdition')]",
"maxSizeBytes": "1073741824",
"requestedServiceObjectiveName": "[parameters('dbnameRequestedServiceObjectiveName')]"
}
}
]
}
],
"outputs": {
"SomeString": {
"type": "string",
"value": "What ever you want to put here"
},
"ServerNameParam": {
"type": "string",
"value": "[parameters('yourservernameName')]"
},
"ServerResourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Sql/servers', parameters('yourservernameName'))]"
},
"ServerObject": {
"type": "object",
"value": "[reference(parameters('yourservernameName'))]"
},
"SqlServerURL": {
"type": "string",
"value": "[reference(parameters('yourservernameName')).fullyQualifiedDomainName]"
},
"DbResourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Sql/servers/databases', parameters('yourservernameName'), parameters('dbnameName'))]"
},
"DbObject": {
"type": "object",
"value": "[reference(parameters('dbnameName'))]"
},
"DbAdoConnString": {
"type": "string",
"value": "[concat('Server=tcp:',reference(parameters('yourservernameName')).fullyQualifiedDomainName,',1433;Initial Catalog=',parameters('dbnameName'),';Persist Security Info=False;User ID=',reference(parameters('yourservernameName')).administratorLogin,';Password=',reference(parameters('yourservernameName')).administratorLoginPassword,';MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;')]"
}
}
}

Working sample:
"name": "name",
"type": "Microsoft.Sql/servers",
"location": "[resourceGroup().location]",
"apiVersion": "2014-04-01",
"properties": {
"administratorLogin": "somelogin",
"administratorLoginPassword": "somepasswordD1!"
}
please note that SA might not be allowed as a username and password has complexity requirements

We wanted to create a temporary unique password per resource group and don't have to worry about passwords in template or parameters files since these are checked into git. Solved it like this:
template.json:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vulnerabilityAssessments_Default_storageContainerPath": {
"type": "SecureString"
},
"servers_dev_name": {
"defaultValue": "dev-app",
"type": "String"
}
},
"variables": {
"servers_dev_password": "[concat('P', uniqueString(resourceGroup().id, '224F5A8B-51DB-46A3-A7C8-59B0DD584A41'), 'x', '!')]",
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2019-06-01-preview",
"name": "[parameters('servers_dev_name')]",
"location": "northeurope",
"kind": "v12.0",
"properties": {
"administratorLogin": "OurSaName",
"administratorLoginPassword": "[variables('servers_dev_password')]",
"version": "12.0",
"publicNetworkAccess": "Enabled"
}
},
"To make sure that we are compliant with the Azure SQL database policy "Your password must contain characters from three of the following categories – English uppercase letters, English lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, #, %, etc.)", we insert one character for each category before and after the unique string."
Sources:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-string#uniquestring
https://vivien-chevallier.com/Articles/automatically-generate-a-password-for-an-azure-sql-database-with-arm-template
Warning:
If you add to your parameters.json:
"servers_dev_password": {
"value": "[uniqueString(resourceGroup().id)]"
}
and add the parameter to template.json the actual password will be:[uniqueString(resourceGroup().id)].
"servers_dev_password": {
"type": "SecureString"
}
A thing to note is that the definition for uniqueString is:
Creates a deterministic hash string based on the values provided as
parameters.
This means that if you want to create a unique password per deployment it would have to look something like this:
"parameters": {
"newGuid": {
"type": "string",
"defaultValue": "[newGuid()]"
}
}
"variables": {
"sqlserverAdminPassword": "[concat(uniqueString(guid(resourceGroup().id, deployment().name)), parameters('newGuid'), 'Tg2%')]"
}
Your password would then be updated on every deploy.
https://stackoverflow.com/a/70325944/3850405

Related

Custom policy does not maintain previous values on properties array

I am creating a custom policy following this documentation.
I created one, and it is working. The JSON schema for the policy is shown below:
{
"title": "ACME Custom Basic Auth Policy",
"description": "Basic Authentication policy which enforces security according with custom consumer credentials",
"type": "object",
"properties": {
"users": {
"title": "users",
"type": "array",
"items": {
"type": "object",
"required": [
"username",
"password"
],
"properties": {
"username": {
"title": "User Name",
"type": "string",
"default": []
},
"password": {
"title": "User Password",
"type": "string",
"#context": {
"#characteristics": [
"security:sensitive"
]
}
}
}
},
"minItems": 1
}
},
"#context": {
"#vocab": "anypoint://vocabulary/policy.yaml#",
"security": "anypoint://vocabulary/policy.yaml#"
},
"$id": "allow-dynamic-resources",
"$schema": "https://json-schema.org/draft/2019-09/schema"
}
When I go to API Manager, I can configure the values on first attempt, but when I go back to change the values, they do not appear.
This happens only when I configure an array. If I configure as an object, it works. How can I fix this?

Azure sql private endpoint ARM template help needed

{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-06-01",
"name": "[variables('privateEndpointName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', variables('sqlServerName'))]"
],
"properties": {
"subnet": {
**id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')),'/subnets/default')]"')]"**
},
"privateLinkServiceConnections": [
{
"name": "[variables('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Sql/servers',variables('sqlServerName'))]",
"groupIds": [
"sqlServer"
]
Getting error Resource vnetI not found. vnet is located in different subscription to where template is running.
How to get vnet ID in different subscription using arm template?
default value is the current subscription. Specify subscription and resource group to solve the issue.
"[resourceId('11111111-1111-1111-1111-111111111111', 'otherResourceGroup', 'Microsoft.Storage/storageAccounts','examplestorage')]"
link to MS docs
The issue is just wrong reference of parameters. You can reference the other VNet in a different subscription for the parameter "id" with its ID generated from resourceId function. It returns the unique identifier of a resource. You use this function when the resource name is ambiguous or not provisioned within the same template.
Default value is the current subscription. Specify subscriptionId, resourceGroupName, resourceType and resourceName value of the other subscription as you need to retrieve a resource in another subscription.
Changes:
From:
"id": resourceId([subscriptionId], [resourceGroupName], resourceType, resourceName1, [resourceName2], ...)
To:
"id": "[resourceId('OthersubscriptionId','virtualNetworkResourceGroup', 'Microsoft.Network/virtualNetworks/subnets', 'virtualNetworkName', 'subnet1Name')]"
this is how it looks...
{
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-06-01",
"name": "[variables('privateEndpointName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', variables('sqlServerName'))]"
],
"properties": {
"subnet": {
"id": "[resourceId('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'virtualNetworkResourceGroup', 'Microsoft.Network/virtualNetworks/subnets', 'virtualNetworkName', 'subnet1Name')]"
},
"privateLinkServiceConnections": [
{
"name": "[variables('privateEndpointName')]",
"properties": {
"privateLinkServiceId": "[resourceId('Microsoft.Sql/servers',variables('sqlServerName'))]",
"groupIds": [
"sqlServer"
]
}
}
]
}
},
Refer: Here and resourceId
Update ---
Additional example: To get the resource ID for a resource in a different subscription and resource group, provide the subscription ID and resource group name.
"[resourceId('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'otherResourceGroup', 'Microsoft.Storage/storageAccounts','examplestorage')]"
The following example shows how a resource from an external resource group can easily be used:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"virtualNetworkName": {
"type": "string"
},
"virtualNetworkResourceGroup": {
"type": "string"
},
"subnet1Name": {
"type": "string"
},
"nicName": {
"type": "string"
}
},
"variables": {
"subnet1Ref": "[resourceId(parameters('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnet1Name'))]"
},
"resources": [
{
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2015-05-01-preview",
"name": "[parameters('nicName')]",
"location": "[parameters('location')]",
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('subnet1Ref')]"
}
}
}
]
}
}
]
}
---

ARM template deployment for Logic Apps with Datalake API Connection

Error - The API connection 'azuredatalake' is not configured to support managed identity."
I tried deployment of Azure logic App along with API connection to access Azure DataLake Gen1 using Managed Identity. This failed due to above error.
Also deployed API connection separately which was successful but with status "Unauthenticated", so deploying of corresponding logic apps failed with missing api connection.
Part Template for API connection reference:
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[parameters('azuredatalake_1_Connection_Name')]",
"location": "[parameters('location')]",
"kind": "V1",
"properties": {
"displayName": "azuredatalakemsi",
"customParameterValues": {},
"api": {
"id": "[variables('managedadlsApi')]"
}
}
}
If we want to access the data stored in data lake gen1, we must configure right ACLs for the user or sp used to do auth. Otherwise, we cannot have permission to access data. For more details, please refer to the official document. Meanwhile, we cannot do that via arm template. We can do that by PowerShell or Portal.
Besides, regarding how to use MSI to access Azure data lake gen1 in azure logic app, please refer to the following steps
Enable MSI in Azure logic app
{
"apiVersion": "2016-06-01",
"type": "Microsoft.logic/workflows",
"name": "[variables('logicappName')]",
"location": "[resourceGroup().location]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {},
"parameters": {},
"triggers": {},
"contentVersion": "1.0.0.0",
"outputs": {}
},
"parameters": {},
"dependsOn": []
}
Configure ACLs
Create connection
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[parameters('azuredatalake_1_Connection_Name')]",
"location": "[parameters('location')]",
"tags": {
"CreatedTime": "2021-05-24T03:11:28.9371899Z"
},
"kind": "V1",
"properties": {
"displayName": "test",
"customParameterValues": {},
"api": {
"id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/', parameters('location'), '/managedApis/azuredatalake')]"
}
}
},
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2017-07-01",
"name": "[parameters('workflows_testlogic05_name')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/connections', parameters('azuredatalake_1_Connection_Name'))]"
],
"properties": {
"state": "Enabled",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
},
"actions": {
},
"outputs": {}
},
"parameters": {
"$connections": {
"value": {
"azuredatalake": {
"connectionId": "[resourceId('Microsoft.Web/connections', parameters('azuredatalake_1_Connection_Name'))]",
"connectionName": "azuredatalake",
"connectionProperties": {
"authentication": {
"type": "ManagedServiceIdentity"
}
},
"id": "[concat(subscription().id,'/providers/Microsoft.Web/locations/', parameters('location'), '/managedApis/azuredatalake')]"
}
}
}
}
}
}
For more details, please refer to
https://learn.microsoft.com/en-us/azure/logic-apps/create-managed-service-identity
I was able to solve this by modifying ARM Template for this API connection, that is by adding "parameterValueType" as "Alternative".
Deployment of Azure logic App along with API connection to access Azure DataLake Gen1 using Managed Identity is successful.
Part Template for API connection reference:
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[parameters('azuredatalake_1_Connection_Name')]",
"location": "[parameters('location')]",
"kind": "V1",
"properties": {
"displayName": "azuredatalakemsi",
"parameterValueType": "Alternative",
"customParameterValues": {},
"api": {
"id": "[variables('managedadlsApi')]"
}
}
}

Deploy ARM Templates Without DependsOn under Specific Subscription of Specified resource group

I would like to deploy ARM templates individually rather than linked templates/nested templates/multiple resources.
Ex: Deploy a Sql Server and database
I created individual templates for Sql Server and Sql database . I deployed successfully and its working fine.
Deploy Sql Server ARM template(Specifically designed only for sql server)
Deploy Sql Server Database(Specifically designed only for sql database with above sql server name mentioning in parameters file)
While deploying Sql database arm template , I had specified accurate sql server name(deployed in Step1) in parameters file of step2 but I did not mentioned "dependson" parameter in resource section and directly deployed .Database creation successfully under the resource group I selected while deployment process.
My Query:
How can I make sure Sql database arm template is deploying under specific server name(Step1) only without dependson parameter?
or
How to use existing reference resource id in resources section without dependson?
Will output of step1(resourceid) of sql server will be any helpful?
Sql ARM Template Deploy JSON:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"collation": {
"type": "string",
"defaultValue": "SQL_Latin1_General_CP1_CI_AS",
"metadata": {
"description": "The collation of the database."
}
},
"edition": {
"type": "string",
"metadata": {
"description": "The edition of the database. The DatabaseEditions enumeration contains all the valid editions. e.g. Basic, Premium."
},
"defaultValue": "Basic"
},
"sqlservername": {
"type": "string",
"metadata": {
"description": "The name of the sql server."
}
},
"databasename": {
"type": "string",
"metadata": {
"description": "The name of the database to be operated on (updated or created)."
},
"minLength": 7,
"maxLength": 128
},
"maxSizeBytes": {
"type": "string",
"metadata": {
"description": "The max size of the database expressed in bytes."
}
},
"serviceobjectivename": {
"type": "string",
"metadata": {
"description": "The configured service level objective ID of the database. This is the service level objective that is in the process of being applied to the database."
},
"defaultValue": "Basic"
},
"tagsArray": {
"type": "object",
"metadata": {
"description": "Resource Tags helps to indentify the use of service"
}
}
},
"functions": [],
"variables": {
"sqldatabasename": "[concat(parameters('sqlservername'),'/',parameters('databasename'))]"
},
"resources": [
{
"name": "[variables('sqldatabasename')]",
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2014-04-01",
"location": "[parameters('location')]",
"tags": "[parameters('tagsArray')]",
"properties": {
"collation": "[parameters('collation')]",
"edition": "[parameters('edition')]",
"maxSizeBytes": "[parameters('maxSizeBytes')]",
"requestedServiceObjectiveName": "[parameters('serviceobjectivename')]"
}
}
],
"outputs": {
"sqldatabaseresourceId": {
"type": "object",
"value": "[reference(resourceId('Microsoft.Sql/servers/databases',parameters('sqlservername'), parameters('databasename')),'2014-04-01')]"
}
}
}
Template Parameters:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"tagsArray": {
"value": {
"Environment": "POC"
}
},
"servername": {
"value": "sql-test"
},
"sqlAdministratorLogin": {
"value": "sqladmin"
},
"sqlAdministratorLoginPassword": {
"value": "myPassword586#"
},
"firewallIpAddresses": {
"value": [
{
"start": "1.1.1.0",
"end": "1.1.1.1",
"clientName": "Clienttest1"
},
{
"start": "1.2.3.4",
"end": "1.2.3.16",
"clientName": "Clienttest2"
}
]
},
"location": {
"value": ""
}
}
}
It is important to understand that dependsOn enables you to define one resource as dependent on one or more resources within your template only, and should not be used to map relationships between your resources. As explained in the ARM Template documentation, dependsOn isn't the right approach to document how resources are interconnected.
How can I make sure Sql database arm template is deploying under specific server name(Step1) only without dependson parameter?
Microsoft.Sql/servers/databases is a child resource of Microsoft.Sql/servers, and it is the name of the child resource that defines the connection with the parent resource.
You would have had to set the dependsOn property if you were deploying the child resource after the parent resource in the same ARM template, since an implicit deployment dependency isn't automatically created between them. Specifying dependsOn in this case would ensure that the parent resource is deployed (and exists) before the child resource.
That said, when defined outside of the parent resource, you format the type and name with slashes to include the parent type and name.
"type": "{resource-provider-namespace}/{parent-resource-type}/{child-resource-type}",
"name": "{parent-resource-name}/{child-resource-name}",
So, a SQL Database might be defined as:
{
"type": "Microsoft.Sql/servers/databases",
"name": "[concat(variables('sqlServerName'), '/', parameters('databaseName'))]",
...
Coming to your next question:
How to use existing reference resource id in resources section without dependson?
Will output of step1(resourceid) of sql server will be any helpful?
As you have already deployed the parent resource (DB Server) in a different template, don't set a dependency. Instead, deploy the child resource (Database) to the same resource group and provide the name of the parent resource. That should suffice.
Example:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sqlServerName": {
"type": "string",
"defaultValue": "sqlserver"
},
"databaseName": {
"type": "string",
"defaultValue": "mydb"
}
},
"resources": [
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2014-04-01",
"name": "[concat(parameters('sqlServerName'), '/', parameters('databaseName'))]",
"location": "[resourceGroup().location]",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"edition": "Basic"
}
}
],
"outputs": {}
}

Need help to understand maintaining azure key vault in different environment and also to be able to use that in logic app

I have a logic app which makes HTTP call to Key Vault URI to get the secret needed to connect to external system. I have developed this in the dev resource group. I want to know how to setup the key vault from dev resource groups to other resource groups (test/prod). Also, how to migrate the logic app and get the secret per environment.
:) The solution is to use ARM templates and ADO/any other pipeline. You can create ARM templates with different parameters' values for different environments and use them to deploy your Logic App and Key vault to different environments.
Logic App Template sample:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
// Template parameters
"parameters": {
"<template-parameter-name>": {
"type": "<parameter-type>",
"defaultValue": "<parameter-default-value>",
"metadata": {
"description": "<parameter-description>"
}
}
},
"variables": {},
"functions": [],
"resources": [
{
// Start logic app resource definition
"properties": {
<other-logic-app-resource-properties>,
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {<action-definitions>},
// Workflow definition parameters
"parameters": {
"<workflow-definition-parameter-name>": {
"type": "<parameter-type>",
"defaultValue": "<parameter-default-value>",
"metadata": {
"description": "<parameter-description>"
}
}
},
"triggers": {
"<trigger-name>": {
"type": "<trigger-type>",
"inputs": {
// Workflow definition parameter reference
"<attribute-name>": "#parameters('<workflow-definition-parameter-name')"
}
}
},
<...>
},
// Workflow definition parameter value
"parameters": {
"<workflow-definition-parameter-name>": {
"value": "[parameters('<template-parameter-name>')]"
}
},
"accessControl": {}
},
<other-logic-app-resource-definition-attributes>
}
// End logic app resource definition
],
"outputs": {}
}
Key Vault template:
{
"name": "string",
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2018-02-14",
"location": "string",
"tags": {},
"properties": {
"tenantId": "string",
"sku": {
"family": "A",
"name": "string"
},
"accessPolicies": [
{
"tenantId": "string",
"objectId": "string",
"applicationId": "string",
"permissions": {
"keys": [
"string"
],
"secrets": [
"string"
],
"certificates": [
"string"
],
"storage": [
"string"
]
}
}
],
"vaultUri": "string",
"enabledForDeployment": "boolean",
"enabledForDiskEncryption": "boolean",
"enabledForTemplateDeployment": "boolean",
"enableSoftDelete": "boolean",
"createMode": "string",
"enablePurgeProtection": "boolean",
"networkAcls": {
"bypass": "string",
"defaultAction": "string",
"ipRules": [
{
"value": "string"
}
],
"virtualNetworkRules": [
{
"id": "string"
}
]
}
},
"resources": []
}
Moreover, you can read this article to understand more about setting up your ADO pipelines: Integrate ARM templates with Azure Pipelines

Resources