From ef1eb7d7a270824aac90e3c4babaed6627fe7371 Mon Sep 17 00:00:00 2001 From: sebastian claesson Date: Tue, 10 Dec 2024 09:58:24 +0100 Subject: [PATCH 1/4] Adding policy to provision an a-record for container apps with internal ingress. --- .../azurepolicy.json | 123 ++++++++++++++++++ .../azurepolicy.parameters.json | 29 +++++ .../azurepolicy.rules.json | 80 ++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json create mode 100644 policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json create mode 100644 policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json new file mode 100644 index 00000000..7f0c6d87 --- /dev/null +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json @@ -0,0 +1,123 @@ +{ + "name": "0c72bb57-1591-4dbc-94c0-3f8a81c3e851", + "type": "Microsoft.Authorization/policyDefinitions", + "properties": { + "displayName": "Configure Container Apps A-record private DNS zone entry with corresponding domain suffix", + "description": "Use internal ingress to configure private networking. This policy deploys the DNS A-record (wildcard) to the private DNS zone that corresponds with the domainsuffix. (*...azurecontainerapps.io).", + "mode": "All", + "metadata": { + "category": "Container Apps", + "version": "1.0.0" + }, + "version": "1.0.0", + "parameters": { + "azureContainerAppsPrivateDnsZoneId": { + "type": "String", + "metadata": { + "displayName": "Private DNS Zone ID", + "description": "ID of the Private DNS Zone for CAE (e.g., /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/privateDnsZones/{dnsZoneName})", + "strongType": "Microsoft.Network/privateDnsZones" + } + }, + "dnsZoneName": { + "type": "String", + "metadata": { + "displayName": "DNS Zone Name", + "description": "Name of the DNS Zone for the A record" + } + }, + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.App/managedEnvironments" + }, + { + "field": "Microsoft.App/managedEnvironments/vnetConfiguration.internal", + "equals": "True" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Network/privateDnsZones/A", + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Network/privateDnsZones/A/fqdn", + "equals": "[concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0],'.',parameters('dnsZoneName'),'.')]" + } + ] + }, + "name": "[concat(parameters('dnsZoneName'), '/', concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0]))]", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7" + ], + "deployment": { + "properties": { + "mode": "incremental", + "subscriptionId": "[split(parameters('azureContainerAppsPrivateDnsZoneId'),'/')[2]]", + "resourceGroup": "[split(parameters('azureContainerAppsPrivateDnsZoneId'),'/')[4]]", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.1", + "parameters": { + "dnsZoneName": { + "type": "string" + }, + "staticIp": { + "type": "string" + }, + "recordName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2024-06-01", + "name": "[concat(parameters('dnsZoneName'), '/', parameters('recordName'))]", + "properties": { + "ttl": 3600, + "aRecords": [ + { + "ipv4Address": "[parameters('staticIp')]" + } + ] + } + } + ] + }, + "parameters": { + "dnsZoneName": { + "value": "[last(split(parameters('azureContainerAppsPrivateDnsZoneId'),'/'))]" + }, + "staticIp": { + "value": "[field('Microsoft.App/managedEnvironments/staticIp')]" + }, + "recordName": { + "value": "[concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0])]" + } + } + } + } + } + } + } + } +} diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json new file mode 100644 index 00000000..72170ae6 --- /dev/null +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json @@ -0,0 +1,29 @@ +{ + "azureContainerAppsPrivateDnsZoneId": { + "type": "String", + "metadata": { + "displayName": "Private DNS Zone ID", + "description": "ID of the Private DNS Zone for CAE (e.g., /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/privateDnsZones/{dnsZoneName})", + "strongType": "Microsoft.Network/privateDnsZones" + } + }, + "dnsZoneName": { + "type": "String", + "metadata": { + "displayName": "DNS Zone Name", + "description": "Name of the DNS Zone for the A record" + } + }, + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + } +} \ No newline at end of file diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json new file mode 100644 index 00000000..cb61f57c --- /dev/null +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json @@ -0,0 +1,80 @@ +{ + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.App/managedEnvironments" + }, + { + "field": "Microsoft.App/managedEnvironments/vnetConfiguration.internal", + "equals": "True" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Network/privateDnsZones/A", + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Network/privateDnsZones/A/fqdn", + "equals": "[concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0],'.',parameters('dnsZoneName'),'.')]" + } + ] + }, + "name": "[concat(parameters('dnsZoneName'), '/', concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0]))]", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7" + ], + "deployment": { + "properties": { + "mode": "incremental", + "subscriptionId": "[split(parameters('azureContainerAppsPrivateDnsZoneId'),'/')[2]]", + "resourceGroup": "[split(parameters('azureContainerAppsPrivateDnsZoneId'),'/')[4]]", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.1", + "parameters": { + "dnsZoneName": { + "type": "string" + }, + "staticIp": { + "type": "string" + }, + "recordName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateDnsZones/A", + "apiVersion": "2024-06-01", + "name": "[concat(parameters('dnsZoneName'), '/', parameters('recordName'))]", + "properties": { + "ttl": 3600, + "aRecords": [ + { + "ipv4Address": "[parameters('staticIp')]" + } + ] + } + } + ] + }, + "parameters": { + "dnsZoneName": { + "value": "[last(split(parameters('azureContainerAppsPrivateDnsZoneId'),'/'))]" + }, + "staticIp": { + "value": "[field('Microsoft.App/managedEnvironments/staticIp')]" + }, + "recordName": { + "value": "[concat('*.',split(field('Microsoft.App/managedEnvironments/defaultDomain'),'.')[0])]" + } + } + } + } + } + } +} \ No newline at end of file From 7b6dca2072cb93d9d04c7828d58b017fac60bd78 Mon Sep 17 00:00:00 2001 From: sebastian claesson Date: Tue, 10 Dec 2024 10:00:05 +0100 Subject: [PATCH 2/4] Adding "AuditIfNotExists" as effect. --- .../azurepolicy.json | 1 + .../azurepolicy.parameters.json | 1 + 2 files changed, 2 insertions(+) diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json index 7f0c6d87..154ab623 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json @@ -34,6 +34,7 @@ }, "allowedValues": [ "DeployIfNotExists", + "AuditIfNotExists", "Disabled" ], "defaultValue": "DeployIfNotExists" diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json index 72170ae6..3ca9a090 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json @@ -22,6 +22,7 @@ }, "allowedValues": [ "DeployIfNotExists", + "AuditIfNotExists", "Disabled" ], "defaultValue": "DeployIfNotExists" From cb1891256de3e414fa6502290c5631cc90a98fde Mon Sep 17 00:00:00 2001 From: sebastian claesson Date: Wed, 11 Dec 2024 07:24:03 +0100 Subject: [PATCH 3/4] adding description to parameter --- .../azurepolicy.json | 2 +- .../azurepolicy.parameters.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json index 154ab623..59ea0d0a 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json @@ -23,7 +23,7 @@ "type": "String", "metadata": { "displayName": "DNS Zone Name", - "description": "Name of the DNS Zone for the A record" + "description": "Name of the DNS Zone for the A record (e.g., swedencentral.azurecontainerapps.io)" } }, "effect": { diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json index 3ca9a090..33c6db20 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.parameters.json @@ -11,7 +11,7 @@ "type": "String", "metadata": { "displayName": "DNS Zone Name", - "description": "Name of the DNS Zone for the A record" + "description": "Name of the DNS Zone for the A record (e.g., swedencentral.azurecontainerapps.io)" } }, "effect": { From 82338aaa3d6b8e90f16f06940becfda597b08106 Mon Sep 17 00:00:00 2001 From: sebastian claesson Date: Wed, 11 Dec 2024 07:52:39 +0100 Subject: [PATCH 4/4] Adding defaultDomain as part of if evaluation to evalute correctly. --- .../azurepolicy.json | 4 ++++ .../azurepolicy.rules.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json index 59ea0d0a..f9650666 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.json @@ -50,6 +50,10 @@ { "field": "Microsoft.App/managedEnvironments/vnetConfiguration.internal", "equals": "True" + }, + { + "field": "Microsoft.App/managedEnvironments/defaultDomain", + "contains": "[parameters('dnsZoneName')]" } ] }, diff --git a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json index cb61f57c..a3c09fc2 100644 --- a/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json +++ b/policyDefinitions/Container Apps/deploy-container-app-internal-ingress-private-dns-zone-domainbased/azurepolicy.rules.json @@ -8,6 +8,10 @@ { "field": "Microsoft.App/managedEnvironments/vnetConfiguration.internal", "equals": "True" + }, + { + "field": "Microsoft.App/managedEnvironments/defaultDomain", + "contains": "[parameters('dnsZoneName')]" } ] },