I have tried to deploy the logic app via ARM template, Which is getting deployed successfully, But issue is with the JOB scheduler, which is not picking up in connection id, But the job is getting deployed when I use my credentials but that should not be the case.
ARM Script for Logic App Deployment:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workflows_logicapp_xyz_name": {
"defaultValue": " logicapp_xyz ",
"type": "String"
},
"connections_azureautomation_1_externalid": {
"defaultValue": "/subscriptions/xyz6c051-f4ef-4a30-8ce7-c9fb99ff0xyz/resourceGroups/ResourceGroup-A/providers/Microsoft.Web/connections/azureautomation-123",
"type": "String"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2017-07-01",
"name": "[parameters('workflows_logicapp_xyz_name')]",
"location": "region",
"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": {
"Recurrence": {
"recurrence": {
"frequency": "Minute",
"interval": 1
},
"type": "Recurrence"
}
},
"actions": {
"Create_job": {
"runAfter": {},
"type": "ApiConnection",
"inputs": {
"body": {
"properties": {
"parameters": {
"Uri": "http://10.xyz.0.xyz:443/BrowserWeb/servlet/BrowserServlet?,
http:// 10.xyz.0.xyz:443/BrowserWeb/servlet/BrowserServlet?, http:// 10.xyz.0.xyz:443/BrowserWeb/servlet/BrowserServlet?"
},
"runOn": "Hybrid_worker-Resourcegroup"
}
},
"host": {
"connection": {
"name": "#parameters('$connections')['azureautomation']['connectionId']"
}
},
"method": "put",
"path": "/subscriptions/#{encodeURIComponent('xyz6c051-f4ef-4a30-8ce7-c9fb99ffxyz')}/resourceGroups/#{encodeURIComponent('DevOpsTestRG-B')}/providers/Microsoft.Automation/automationAccounts/#{encodeURIComponent('AAC-SUB-01')}/jobs",
"queries": {
"runbookName": "Hybridrunbook-Resourcegroup",
"wait": false,
"x-ms-api-version": "2015-10-31"
}
}
},
"Create_job_2": {
"runAfter": {
"Create_job": [
"Succeeded"
]
},
"type": "ApiConnection",
"inputs": {
"body": {
"properties": {
"parameters": {
"configXml": "C://Users/devops/Desktop/ServiceMonitor/xyz_LoginPageMonitorConfig.xml"
},
"runOn": "Hybrid account-Resourcegroup"
}
},
"host": {
"connection": {
"name": "#parameters('$connections')['azureautomation']['connectionId']"
}
},
"method": "put",
"path": "/subscriptions/#{encodeURIComponent('4776c051-f4ef-4a30-8ce7-c9fb99ff0xyz')}/resourceGroups/#{encodeURIComponent('Resourcegroup-B')}/providers/Microsoft.Automation/automationAccounts/#{encodeURIComponent('XYZ-SUB-01')}/jobs",
"queries": {
"runbookName": "Hybridrunbook-Resource group",
"wait": false,
"x-ms-api-version": "2015-10-31"
}
}
}
},
"outputs": {}
},
"parameters": {
"$connections": {
"value": {
"azureautomation": {
"connectionId": "[parameters('connections_azureautomation_1_externalid')]",
"connectionName": "azureautomation-1",
"id": "/subscriptions/4776c051-f4ef-4a30-8ce7-c9fb99ff0xyz/providers/Microsoft.Web/locations/northeurope/managedApis/azureautomation"
}
}
}
}
}
}
]
}
After deployment, the logic app works end-to-end with valid parameters. However, you must still authorize OAuth connections to generate a valid access token. For automated deployments, you can use a script that consents to each OAuth connection, such as this example script in the GitHub LogicAppConnectionAuth project. You can also authorize OAuth connections through the Azure portal or in Visual Studio by opening your logic app in the Logic Apps Designer.
You used like Export template to get the template just like Thomas said it doesn't contain credentials. And if you deploy to other groups it also doesn't create the API Connection so it won't connect.
So you could download from Azure, then deploy with this json template, it will contain connection details. I test with Custom deployment, it will detect the API connection.
Related
Based on information from Microsoft site, it is possible get key vault secrets during the implementation. I would like to have similar solution but for 5 VMs and reuse templates in Loop to create 5 VMs with different password from key vault. The key vault already exists with the secrets name. The secrets name are like: Secrets0...Secrets4.
Does anyone has any idea of how to do this? Below my solution with Loop but doesn't works for me.
I appreciate for your support.
{
"$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": "The location where the resources will be deployed."
}
},
"vaultName": {
"type": "string",
"metadata": {
"description": "The name of the keyvault that contains the secret."
}
},
"secretName": {
"type": "string",
"metadata": {
"description": "The name of the secret."
}
},
"vaultResourceGroupName": {
"type": "string",
"metadata": {
"description": "The name of the resource group that contains the keyvault."
}
},
"vaultSubscription": {
"type": "string",
"defaultValue": "[subscription().subscriptionId]",
"metadata": {
"description": "The name of the subscription that contains the keyvault."
}
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[concat('DynamicSecret,copyIndex('VMsLoop'))]"
"copy": {
"name": "VMsLoop",
"count": 5,
"mode": "Serial",
"batchSize": 1
},
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminLogin": {
"type": "string"
},
"adminPassword": {
"type": "securestring"
},
"location": {
"type": "string"
}
},
"variables": {
"sqlServerName": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2018-06-01-preview",
"name": "[variables('sqlServerName')]",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('adminLogin')]",
"administratorLoginPassword": "[parameters('adminPassword')]"
}
}
],
"outputs": {
"sqlFQDN": {
"type": "string",
"value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
}
}
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"adminLogin": {
"value": "ghuser"
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
},
"secretName": "[concat(parameters('secretName'),copyIndex('VMsLoop'))]"
}
}
}
}
}
],
"outputs": {
}
}
The template you have provided actually works (except for one tiny typo - missing closing quote after DynamicSecret at "[concat('DynamicSecret,copyIndex('VMsLoop'))]" ).
However, since the uniquestring function that is used to generate the sql server name is deterministic (i.e. generated using the passed parameters of resoure group name and 'sql' string - uniqueString(resourceGroup().id, 'sql'). So the loop is hitting the same server instance just changing the password to the next secret in the list.
You can either promote the sqlServerName to parameter and suffix it with the loop index, or keep it as a variable and expand the uniqueString function with the deployment (i.e. uniqueString(resourceGroup().id, deployment().name, 'sql') ).
I am trying to deploy a Active Directory forest with two DCs. I've managed to deploy the DCs and install the ADDS features on both VMs. The "PDC" had a DSC script that runs and configures the forest, again that works great. The issue I have is trying to run a second DSC script on the second DC, this script runs the ADDS configuration to promote the VM to a DC and join it to the forest. I've created a nested JSON template that gets called by the main template. But I am hitting this error:
"Multiple VMExtensions per handler not supported for OS type 'Windows'. VMExtension 'PrepareBDC' with handler 'Microsoft.Powershell.DSC' already added or specified in input."
I've spent the last hour or so whizzing around the internet looking for answers and everyone seems to say the same thing...you can't install the same extension twice. Ok, I can see why that would make sense, my question is can I configure the nested template so it doesn't try and install the extension, just uses what's already installed on the VM?
Main template snippet:
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('dc2name'), '/PrepareDC2AD')]",
"apiVersion": "2018-06-01",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', variables('dc2name'))]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.19",
"autoUpgradeMinorVersion": true,
"settings": {
"ModulesUrl": "[concat(parameters('Artifacts Location'), '/dsc/PrepareADBDC.zip', parameters('Artifacts Location SAS Token'))]",
"ConfigurationFunction": "PrepareADBDC.ps1\\PrepareADBDC",
"Properties": {
"DNSServer": "[variables('dc1ipaddress')]"
}
}
}
},
{
"name": "ConfiguringDC2",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-09-01",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/',variables('dc1name'),'/extensions/CreateADForest')]",
"[concat('Microsoft.Compute/virtualMachines/',variables('dc2name'),'/extensions/PrepareDC2AD')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('Artifacts Location'), '/nestedtemplates/configureADBDC.json', parameters('Artifacts Location SAS Token'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"adBDCVMName": {
"value": "[variables('dc2name')]"
},
"location": {
"value": "[resourceGroup().location]"
},
"adminUsername": {
"value": "[parameters('Administrator User')]"
},
"adminPassword": {
"value": "[parameters('Administrator Password')]"
},
"domainName": {
"value": "[parameters('Domain Name')]"
},
"adBDCConfigurationFunction": {
"value": "ConfigureADBDC.ps1\\ConfigureADBDC"
},
"adBDCConfigurationModulesURL": {
"value": "[concat(parameters('Artifacts Location'), '/dsc/ConfigureADBDC.zip', parameters('Artifacts Location SAS Token'))]"
}
}
}
},
The nested template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adBDCVMName": {
"type": "string"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
},
"adminUsername": {
"type": "string"
},
"adminPassword": {
"type": "securestring"
},
"domainName": {
"type": "string"
},
"adBDCConfigurationFunction": {
"type": "string"
},
"adBDCConfigurationModulesURL": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('adBDCVMName'),'/PrepareBDC')]",
"apiVersion": "2016-03-30",
"location": "[parameters('location')]",
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.21",
"autoUpgradeMinorVersion": true,
"forceUpdateTag": "1.0",
"settings": {
"modulesURL": "[parameters('adBDCConfigurationModulesURL')]",
"wmfVersion": "4.0",
"configurationFunction": "[parameters('adBDCConfigurationFunction')]",
"properties": {
"domainName": "[parameters('domainName')]",
"adminCreds": {
"userName": "[parameters('adminUsername')]",
"password": "privateSettingsRef:adminPassword"
}
}
},
"protectedSettings": {
"items": {
"adminPassword": "[parameters('adminPassword')]"
}
}
}
}
]
}
this error means exactly what it says: you cannot have multiple copies of the same extension, what you need to do is apply the same extension to the vm, all the inputs have to be the same. you can have a look at this example which does exactly that. This particular template installs the extension for the second time to join bdc to the domain.
But, I don't like that approach. I use Powershell DSC to just wait for the domain to get created and join the bdc to the domain in one go. you would use this powershell dsc snippet:
xWaitForADDomain DscForestWait {
DomainName = $DomainName
DomainUserCredential = $DomainCreds
RetryCount = $RetryCount
RetryIntervalSec = $RetryIntervalSec
}
Here's a complete example
Im having an issue about how to add a Runbook action to my metric alert, there is a lot of dosumentation about sending email to owner, but none of them tells about an action Runbook.
This is my template to create a Metric alert:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"AlertName": {
"type": "string"
},
"Description": {
"type": "string"
},
"VirtualMachineId": {
"type": "string"
},
"MetricName": {
"type": "string"
},
"Operator": {
"type": "string"
},
"Threshold": {
"type": "string"
},
"Aggregation": {
"type": "string"
},
"WindowSize": {
"type": "string"
}
},
"variables": {
},
"resources": [
{
"type": "microsoft.insights/alertRules",
"name": "[parameters('AlertName')]",
"location": "[resourceGroup().location]",
"apiVersion": "2016-03-01",
"properties": {
"name": "[parameters('AlertName')]",
"description": "[parameters('Description')]",
"isEnabled": "true",
"windowSize": "[parameters('WindowSize')]",
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('Microsoft.Compute/virtualMachines',parameters('VirtualMachineId'))]",
"metricName": "[parameters('MetricName')]"
},
"operator": "[parameters('Operator')]",
"threshold": "[parameters('Threshold')]",
"windowSize": "[parameters('WindowSize')]",
"timeAggregation": "[parameters('Aggregation')]"
},
"actions": [
{
"odata.type": "RuleAction"
//Runbook....
}
]
}
}
]
}
There is no documentation about adding a RuleAction and im stuck at this point after creating a virtual machine with a Json Template.
Thank you.
You could follow the steps below.
1.Navigate to your Runbook in the portal, go to Webhooks -> Add Webhook, create a new webhook and copy the URL. For more details, refer to this link.
2.In your template, add the sample below to the actions, and specify the webhookUrl with your webhook URL , refer to this link.
"actions": [
{
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": "[variables('sendToServiceOwners')]",
"customEmails": "[variables('customEmails')]"
},
{
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleWebhookAction",
"serviceUri": "[variables('webhookUrl')]",
"properties": {}
}
]
Create the alert and check it in the portal, it works fine on my side.
We're trying to create an ARM template which will allow us to specify our own encryption key. I have the script below, this encrypts the storage account, however this doesn't allow us to add our own key.
Is there a way to add it programatically, I know it can be done using the portal.
The script I have is
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageNamePrefix": {
"type": "string",
"metadata": {
"description": "The prefix string to add to a generated name."
}
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_RAGRS",
"Standard_ZRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type."
}
},
"blobEncryptionEnabled": {
"type": "bool",
"defaultValue": true,
"allowedValues": [
true,
false
],
"metadata": {
"description": "Enable or disable Blob encryption."
}
}
},
"variables": {
"storageAccountName": "[tolower( concat( parameters('storageNamePrefix'), uniqueString(subscription().id, resourceGroup().id) ))]",
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2016-01-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "Storage",
"properties": {
"encryption": {
"keySource": "Microsoft.Storage",
"services": {
"blob": {
"enabled": "[parameters('blobEncryptionEnabled')]"
}
}
}
}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[variables('storageAccountName')]"
}
}
}
I've seen this on Azure Quickstart Templates, which seems to have the title of what I need, but I can't see where or how to add the key I would like to use..
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_RAGRS",
"Standard_ZRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type."
}
},
"blobEncryptionEnabled": {
"type": "bool",
"defaultValue": true,
"metadata": {
"description": "Enable or disable Blob encryption at Rest."
}
}
},
"variables": {
"storageAccountName": "[tolower( concat('sawithsse', substring(parameters('storageAccountType'), 0, 2), uniqueString(subscription().id, resourceGroup().id) ))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2016-12-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "Storage",
"properties": {
"encryption": {
"keySource": "Microsoft.Storage",
"services": {
"blob": {
"enabled": "[parameters('blobEncryptionEnabled')]"
}
}
}
}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[variables('storageAccountName')]"
}
}
}
The portal way of enabling customer key for encryption is outlined in the below link:
https://learn.microsoft.com/en-us/azure/storage/common/storage-service-encryption-customer-managed-keys
This link mentions the ability to use Powershell, but I can't find any reference for it.
Hope this makes sense.
Thanks in advance.. :)
Something like this:
"properties": {
"encryption": {
"keySource": "Microsoft.Keyvault",
"keyvaultproperties": {
"keyname": xxx,
"keyvaulturi": xxx,
"keyversion": xxx
}
}
}
Source: https://learn.microsoft.com/en-us/rest/api/storagerp/storageaccounts/create#keyvaultproperties
another way, do it with powershell, add -debug and capture the rest call, port it to template.
According to https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration it should be possible to create multiple values on a resource using copy but I can't make it work. Here is my code...
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appServiceName": {
"type": "string",
"metadata": {
"description": "Name of app service to apply SSL to."
}
},
"certificateName": {
"type": "string",
"metadata": {
"description": "User friendly certificate resource name"
}
},
"appServicePlan": {
"type": "string",
"metadata": {
"description": "App Service Plan Name"
}
},
"keyVaultId": {
"type": "string",
"metadata": {
"description": "Existing Key Vault resource Id with an access policy to allow Microsoft.Web RP to read Key Vault secrets (Checkout README.md for more information)"
}
},
"hostname": {
"type": "array",
"metadata": {
"description": "Custom hostname for creating SSL binding. This hostname should already be assigned to the Web App"
}
}
},
"resources": [
{
"apiVersion": "2017-03-30",
"type": "Microsoft.Web/sites",
"name": "[parameters('appServiceName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]"
],
"properties": {
"copy": [
{
"name": "hostnames",
"count": "[length(parameters('hostname'))]",
"input": {
"name": "[copyIndex('hostnames')]",
"properties": {
"hostNameSslStates": [
{
"name": "[[copyIndex(hostname)]]",
"sslState": "SniEnabled",
"thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]",
"toUpdate": true
}
]
}
}
}
]
}
},
{
"type": "Microsoft.Web/certificates",
"name": "[parameters('certificateName')]",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"keyVaultId": "[parameters('keyVaultId')]",
"keyVaultSecretName": "[parameters('certificateName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms',parameters('appServicePlan'))]"
}
}
]
}
And it returns Error: Code=InvalidTemplate; Message=Deployment template l
anguage expression evaluation failed: 'Unable to parse language expression 'copyIndex(hostname)]': expecte
d token 'LeftParenthesis' and actual 'RightParenthesis'.'. Please see https://aka.ms/arm-template-expressi
ons for usage details.
Any ideas what am I doing wrong?
Thanks in advance!
the error gives is away:
change "[[copyIndex(hostname)]]", to "[copyIndex('hostname')]"
you even have it right in other places, why not here?
and you probably want to do this:
"[parameters('hostname')[copyIndex('hostname')]]"