Azure sql private endpoint ARM template help needed - sql-server

{
"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')]"
}
}
}
]
}
}
]
}
---

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?

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

Microsoft Flow Custom Connector webhook trigger definition and implementation : 404 not found after flow creation

I'm trying to create a custom connector for my API in Microsoft Flow so users can trigger flows based on a webhook implementation.
The authentication part seems to be working properly (I'm able to create connections). After creating a flow using my custom trigger, it never gets triggered. When checking the data on my end it seems that Flow was never able to register the subscription properly.
If I navigate to the management page for the flow, I get the following error message.
When I click on fix the trigger I get the following details where the Id parameter matches the id of the resource we're trying to subscribe to.
Here is the trigger definition:
{
"/AlertRules/{id}/webhooks": {
"x-ms-notification-content": {
"schema": {
"type": "object",
"properties": {
"Title": {
"type": "string",
"description": "Title"
},
"Text": {
"type": "string",
"description": "Text"
},
"Data": {
"type": "array",
"items": {
"$ref": "#/definitions/DataApi.Models.AlertEvent"
},
"description": "Data"
}
}
},
"description": ""
},
"post": {
"responses": {
"201": {
"description": "Created",
"schema": {
"type": "string"
}
}
},
"x-ms-trigger": "single",
"operationId": "NewAlertEvent",
"summary": "When a new Alert Event is created or updated",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "string",
"x-ms-visibility": "important",
"x-ms-dynamic-values": {
"operationId": "AlertRules.AlertRule.ListAlertRule",
"value-path": "Id",
"value-collection": "value",
"value-title": "Description"
}
},
{
"name": "body",
"in": "body",
"required": false,
"schema": {
"type": "string",
"x-ms-visibility": "internal",
"title": "",
"x-ms-notification-url": true
},
"x-ms-visibility": "internal"
}
]
}
}
The description of my delete operation
{
"/AlertRuleSubscriptions({Id})": {
"delete": {
"tags": [
"AlertRuleSubscriptions.AlertRuleSubscription"
],
"summary": "Delete entity from AlertRuleSubscriptions",
"operationId": "AlertRuleSubscriptions.AlertRuleSubscription.DeleteAlertRuleSubscription",
"parameters": [
{
"in": "path",
"name": "Id",
"description": "key: Id",
"required": true,
"type": "string",
"format": "uuid",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
"x-ms-docs-key-type": "AlertRuleSubscription"
},
{
"in": "header",
"name": "If-Match",
"description": "ETag",
"type": "string"
}
],
"responses": {
"204": {
"description": "Success"
},
"default": {
"$ref": "#/responses/error"
}
},
"x-ms-docs-operation-type": "operation"
}
}
}
And my post operation does reply with a Location header which matches the format of the delete operation described above.
My questions are:
What is missing in my trigger declaration?
How can I get more details on the subscription creation and the error Microsoft Flow is generating?
After some internal discussions with Microsoft we found two main issues.
First I updated the body parameter of the POST request to create the subscription to this.
{
"name": "body",
"in": "body",
"required": false,
"schema": {
"type": "object",
"properties": {
"callbackUrl": {
"type": "string",
"required": true,
"description": "callbackUrl",
"x-ms-notification-url": true,
"x-ms-visibility": "internal"
}
}
}
}
That is because the connector definitions don't support sending the callback URL in the body without using JSON formatting and because Flow was implemented using the Open API callback specification.
Second I updated my API to support the specification mentioned above.

Create SQL Server via Azure Resource Manager (ARM) template

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

Non-Primitive Values from a Registered Content Provider are not showing a value

I'm using the /v2/registrations endpoint to register a content provider with the legacyForwarding flag being set. Therefore my Content Provider is offering the v1/queryContext endpoint
When I am returning a simple value (Integer, String etc.) such as a temperature the data is added to the context correctly:
{
"contextResponses": [
{
"contextElement": {
"attributes": [
{
"name": "temperature",
"type": "Number",
"value": 27
}
],
"id": "urn:ngsi-ld:Store:001",
"isPattern": "false",
"type": "Store"
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
However when trying to return an array of strings as shown from a Context Provider.
{
"contextResponses": [
{
"contextElement": {
"attributes": [
{
"name": "tweets",
"type": "Array",
"value": [
"String 1",
"String 2"
]
}
],
"id": "urn:ngsi-ld:Store:002",
"isPattern": "false",
"type": "Store"
},
"statusCode": {
"code": "200",
"reasonPhrase": "OK"
}
}
]
}
I can see the request being sent in the log and I can retrieve the following entity:
{
"id": "urn:ngsi-ld:Store:002",
"type": "Store",
"address": {
"type": "PostalAddress",
"value": "",
"metadata": {}
},
"location": {
"type": "geo:json",
"value": "",
"metadata": {}
},
"name": {
"type": "Text",
"value": "Checkpoint Markt",
"metadata": {}
},
"tweets": {
"type": "Array",
"value": "",
"metadata": {}
}
}
As you can see the "tweets" value is blank, but the attribute exists and the type has been successfully received.
My question is how should I return an Array or an Object as a value from a Content Provider so that Orion is able to display the data received correctly?
Further investigation from the Orion Team shows that this was indeed a bug and an issue was raised against Orion 2.0.0. With the latest release, the bug has now been fixed.
The solution is to upgrade to a later version of Orion - currently 2.1.0 (at the time of writing)

Resources