From 4242aaba7b58e5668e0a9c5a06164658b9e27050 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 12 Nov 2021 21:57:37 +0000 Subject: [PATCH 01/29] select subscriptions from form --- src/bicep/form/portal.missionLandingZone.json | 263 ++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 src/bicep/form/portal.missionLandingZone.json diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json new file mode 100644 index 000000000..2136611cc --- /dev/null +++ b/src/bicep/form/portal.missionLandingZone.json @@ -0,0 +1,263 @@ +{ + "$schema": "", + "view": { + "kind": "Form", + "properties": { + "title": "Mission Landing Zone", + "steps": [ + { + "name": "basics", + "label": "Basics", + "elements": [ + { + "name": "infoBoxMissionLandingZone", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit 'aka.ms/missionlz' for more details about the solution pattern.", + "style": "Info", + "uri": "https://aka.ms/missionlz" + } + }, + { + "name": "deploymentDetails", + "label": "Deployment Details", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "subscriptionApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "subscriptions?api-version=2020-01-01" + } + }, + { + "name": "locationsApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "locations?api-version=2019-11-01" + } + }, + { + "name": "deploymentDetailsText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Select the subscription and location for your Mission Landing Zone deployment. This subscription will also provision the Mission Landing Zone Hub resources.", + "link": { + "label": "", + "uri": "" + } + } + }, + { + "name": "hubSubscriptionId", + "label": "Hub Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and resources.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "identitySubscriptionId", + "label": "Identity Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Identity network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "operationsSubscriptionId", + "label": "Operations Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Operations network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "sharedServicesSubscriptionId", + "label": "Shared Services Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Shared Services network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "infoBoxLocation", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Since not all service features are available in all regions, Mission Landing Zone is available in a subset of regions.", + "style": "Info" + } + }, + { + "name": "locationName", + "label": "Location", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Location for your Mission Landing Zone.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(filter(steps('basics').deploymentDetails.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", + "required": true + } + } + ] + }, + { + "name": "missionLandingZoneName", + "label": "Mission Landing Zone Name", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "missionLandingZonePrefix", + "label": "Resource Naming Prefix", + "type": "Microsoft.Common.TextBox", + "visible": true, + "defaultValue": "", + "toolTip": "Specify a prefix (min 1 and max 10 lowercase characters and numbers) to prepend to all resources.", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^[a-z0-9]{1,10}$", + "message": "The prefix must be between 1-10 lowercase characters and numbers." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi001.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi002.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi003.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi004.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + } + ] + } + }, + { + "name": "storageAccountNameApi001", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'hub')]", + "type": "Microsoft.Storage/storageAccounts" + } + } + }, + { + "name": "storageAccountNameApi002", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'identity')]", + "type": "Microsoft.Storage/storageAccounts" + } + } + }, + { + "name": "storageAccountNameApi003", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'operation')]", + "type": "Microsoft.Storage/storageAccounts" + } + } + }, + { + "name": "storageAccountNameApi004", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'sharesvc')]", + "type": "Microsoft.Storage/storageAccounts" + } + } + } + ] + } + ] + }, + { + "name": "networking", + "label": "Networking", + "elements": [] + }, + { + "name": "policy", + "label": "Policy", + "elements": [] + }, + { + "name": "remoteAccess", + "label": "Remote Access", + "elements": [] + } + ], + "outputs": { + } + } + } + } \ No newline at end of file From 23f6511b1f315cbd790f78ea6143396ece4fe39e Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:05:23 +0000 Subject: [PATCH 02/29] update tooltip on hub sub --- src/bicep/form/portal.missionLandingZone.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 2136611cc..1f54e4fc2 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -59,7 +59,7 @@ "type": "Microsoft.Common.DropDown", "visible": true, "defaultValue": "", - "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and resources.", + "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and remote access resources.", "multiselect": false, "selectAll": false, "filter": true, From 46384b9b2308a8ddd941b4ec5c51f2a22fe2f0d8 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:06:09 +0000 Subject: [PATCH 03/29] update deploymentDetailsText --- src/bicep/form/portal.missionLandingZone.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 1f54e4fc2..40c58046b 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -46,7 +46,7 @@ "type": "Microsoft.Common.TextBlock", "visible": true, "options": { - "text": "Select the subscription and location for your Mission Landing Zone deployment. This subscription will also provision the Mission Landing Zone Hub resources.", + "text": "Select the subscription(s) and location for your Mission Landing Zone deployment.", "link": { "label": "", "uri": "" From 546405a0f0ba7963b0bfbaf9d462bf307682998d Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Fri, 12 Nov 2021 22:17:05 +0000 Subject: [PATCH 04/29] add json formatter --- .vscode/settings.json | 9 +- src/bicep/form/portal.missionLandingZone.json | 503 +++++++++--------- 2 files changed, 259 insertions(+), 253 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ff924c340..2f1beeb98 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,10 +4,17 @@ "[terraform]": { "editor.formatOnSave": true }, + "[json]": { + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.detectIndentation": false + }, "shellcheck.enableQuickFix": true, "markdownlint.config": { "default": true, - "MD013": { "line_length": 400 }, + "MD013": { + "line_length": 400 + }, "MD029": false }, "terminal.integrated.scrollback": 10000 diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 40c58046b..4de7cb7e9 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -1,263 +1,262 @@ { - "$schema": "", - "view": { - "kind": "Form", - "properties": { - "title": "Mission Landing Zone", - "steps": [ - { - "name": "basics", - "label": "Basics", - "elements": [ - { - "name": "infoBoxMissionLandingZone", - "type": "Microsoft.Common.InfoBox", - "visible": true, - "options": { - "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit 'aka.ms/missionlz' for more details about the solution pattern.", - "style": "Info", - "uri": "https://aka.ms/missionlz" - } - }, - { - "name": "deploymentDetails", - "label": "Deployment Details", - "type": "Microsoft.Common.Section", - "visible": true, - "elements": [ - { - "name": "subscriptionApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "GET", - "path": "subscriptions?api-version=2020-01-01" - } - }, - { - "name": "locationsApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "GET", - "path": "locations?api-version=2019-11-01" - } - }, - { - "name": "deploymentDetailsText", - "type": "Microsoft.Common.TextBlock", - "visible": true, - "options": { - "text": "Select the subscription(s) and location for your Mission Landing Zone deployment.", - "link": { - "label": "", - "uri": "" - } - } - }, - { - "name": "hubSubscriptionId", - "label": "Hub Subscription", - "type": "Microsoft.Common.DropDown", - "visible": true, - "defaultValue": "", - "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and remote access resources.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", - "required": true - } - }, - { - "name": "identitySubscriptionId", - "label": "Identity Subscription", - "type": "Microsoft.Common.DropDown", - "visible": true, - "defaultValue": "", - "toolTip": "Select the Subscription for your Mission Landing Zone Identity network.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", - "required": true - } - }, - { - "name": "operationsSubscriptionId", - "label": "Operations Subscription", - "type": "Microsoft.Common.DropDown", - "visible": true, - "defaultValue": "", - "toolTip": "Select the Subscription for your Mission Landing Zone Operations network.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", - "required": true - } - }, - { - "name": "sharedServicesSubscriptionId", - "label": "Shared Services Subscription", - "type": "Microsoft.Common.DropDown", - "visible": true, - "defaultValue": "", - "toolTip": "Select the Subscription for your Mission Landing Zone Shared Services network.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", - "required": true - } - }, - { - "name": "infoBoxLocation", - "type": "Microsoft.Common.InfoBox", - "visible": true, - "options": { - "text": "Since not all service features are available in all regions, Mission Landing Zone is available in a subset of regions.", - "style": "Info" - } - }, - { - "name": "locationName", - "label": "Location", - "type": "Microsoft.Common.DropDown", - "visible": true, - "defaultValue": "", - "toolTip": "Select the Location for your Mission Landing Zone.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "constraints": { - "allowedValues": "[map(filter(steps('basics').deploymentDetails.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", - "required": true - } + "$schema": "", + "view": { + "kind": "Form", + "properties": { + "title": "Mission Landing Zone", + "steps": [ + { + "name": "basics", + "label": "Basics", + "elements": [ + { + "name": "infoBoxMissionLandingZone", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit 'aka.ms/missionlz' for more details about the solution pattern.", + "style": "Info", + "uri": "https://aka.ms/missionlz" + } + }, + { + "name": "deploymentDetails", + "label": "Deployment Details", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "subscriptionApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "subscriptions?api-version=2020-01-01" } - ] - }, - { - "name": "missionLandingZoneName", - "label": "Mission Landing Zone Name", - "type": "Microsoft.Common.Section", - "visible": true, - "elements": [ - { - "name": "missionLandingZonePrefix", - "label": "Resource Naming Prefix", - "type": "Microsoft.Common.TextBox", - "visible": true, - "defaultValue": "", - "toolTip": "Specify a prefix (min 1 and max 10 lowercase characters and numbers) to prepend to all resources.", - "constraints": { - "required": true, - "validations": [ - { - "regex": "^[a-z0-9]{1,10}$", - "message": "The prefix must be between 1-10 lowercase characters and numbers." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi001.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi002.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi003.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi004.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - } - ] + }, + { + "name": "locationsApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "locations?api-version=2019-11-01" + } + }, + { + "name": "deploymentDetailsText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Select the subscription(s) and location for your Mission Landing Zone deployment.", + "link": { + "label": "", + "uri": "" } - }, - { - "name": "storageAccountNameApi001", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'hub')]", - "type": "Microsoft.Storage/storageAccounts" + } + }, + { + "name": "hubSubscriptionId", + "label": "Hub Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and remote access resources.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "identitySubscriptionId", + "label": "Identity Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Identity network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "operationsSubscriptionId", + "label": "Operations Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Operations network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "sharedServicesSubscriptionId", + "label": "Shared Services Subscription", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Subscription for your Mission Landing Zone Shared Services network.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "required": true + } + }, + { + "name": "infoBoxLocation", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Since not all service features are available in all regions, Mission Landing Zone is available in a subset of regions.", + "style": "Info" + } + }, + { + "name": "locationName", + "label": "Location", + "type": "Microsoft.Common.DropDown", + "visible": true, + "defaultValue": "", + "toolTip": "Select the Location for your Mission Landing Zone.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(filter(steps('basics').deploymentDetails.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", + "required": true + } + } + ] + }, + { + "name": "missionLandingZoneName", + "label": "Mission Landing Zone Name", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "missionLandingZonePrefix", + "label": "Resource Naming Prefix", + "type": "Microsoft.Common.TextBox", + "visible": true, + "defaultValue": "", + "toolTip": "Specify a prefix (min 1 and max 10 lowercase characters and numbers) to prepend to all resources.", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^[a-z0-9]{1,10}$", + "message": "The prefix must be between 1-10 lowercase characters and numbers." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi001.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi002.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi003.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." + }, + { + "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi004.nameAvailable, false))]", + "message": "Prefix currently unavailable. Please choose a different one." } + ] + } + }, + { + "name": "storageAccountNameApi001", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'hub')]", + "type": "Microsoft.Storage/storageAccounts" } - }, - { - "name": "storageAccountNameApi002", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'identity')]", - "type": "Microsoft.Storage/storageAccounts" - } + } + }, + { + "name": "storageAccountNameApi002", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'identity')]", + "type": "Microsoft.Storage/storageAccounts" } - }, - { - "name": "storageAccountNameApi003", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'operation')]", - "type": "Microsoft.Storage/storageAccounts" - } + } + }, + { + "name": "storageAccountNameApi003", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'operation')]", + "type": "Microsoft.Storage/storageAccounts" } - }, - { - "name": "storageAccountNameApi004", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'sharesvc')]", - "type": "Microsoft.Storage/storageAccounts" - } + } + }, + { + "name": "storageAccountNameApi004", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "POST", + "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "body": { + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'sharesvc')]", + "type": "Microsoft.Storage/storageAccounts" } } - ] - } - ] - }, - { - "name": "networking", - "label": "Networking", - "elements": [] - }, - { - "name": "policy", - "label": "Policy", - "elements": [] - }, - { - "name": "remoteAccess", - "label": "Remote Access", - "elements": [] - } - ], - "outputs": { + } + ] + } + ] + }, + { + "name": "networking", + "label": "Networking", + "elements": [] + }, + { + "name": "policy", + "label": "Policy", + "elements": [] + }, + { + "name": "remoteAccess", + "label": "Remote Access", + "elements": [] } - } + ], + "outputs": {} } - } \ No newline at end of file + } +} \ No newline at end of file From 84d3b67e8d5ea41a19298005bf5e52da86a43d90 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:33:43 -0500 Subject: [PATCH 05/29] add compliance networking remote access blades --- src/bicep/form/portal.missionLandingZone.json | 606 +++++++++++++++++- 1 file changed, 579 insertions(+), 27 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 4de7cb7e9..349a30413 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -12,7 +12,6 @@ { "name": "infoBoxMissionLandingZone", "type": "Microsoft.Common.InfoBox", - "visible": true, "options": { "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit 'aka.ms/missionlz' for more details about the solution pattern.", "style": "Info", @@ -23,7 +22,6 @@ "name": "deploymentDetails", "label": "Deployment Details", "type": "Microsoft.Common.Section", - "visible": true, "elements": [ { "name": "subscriptionApi", @@ -44,20 +42,14 @@ { "name": "deploymentDetailsText", "type": "Microsoft.Common.TextBlock", - "visible": true, "options": { - "text": "Select the subscription(s) and location for your Mission Landing Zone deployment.", - "link": { - "label": "", - "uri": "" - } + "text": "Select the subscription(s) and location for your Mission Landing Zone deployment." } }, { "name": "hubSubscriptionId", "label": "Hub Subscription", "type": "Microsoft.Common.DropDown", - "visible": true, "defaultValue": "", "toolTip": "Select the Subscription for your Mission Landing Zone Hub network, firewall, and remote access resources.", "multiselect": false, @@ -74,7 +66,6 @@ "name": "identitySubscriptionId", "label": "Identity Subscription", "type": "Microsoft.Common.DropDown", - "visible": true, "defaultValue": "", "toolTip": "Select the Subscription for your Mission Landing Zone Identity network.", "multiselect": false, @@ -91,7 +82,6 @@ "name": "operationsSubscriptionId", "label": "Operations Subscription", "type": "Microsoft.Common.DropDown", - "visible": true, "defaultValue": "", "toolTip": "Select the Subscription for your Mission Landing Zone Operations network.", "multiselect": false, @@ -108,7 +98,6 @@ "name": "sharedServicesSubscriptionId", "label": "Shared Services Subscription", "type": "Microsoft.Common.DropDown", - "visible": true, "defaultValue": "", "toolTip": "Select the Subscription for your Mission Landing Zone Shared Services network.", "multiselect": false, @@ -124,7 +113,6 @@ { "name": "infoBoxLocation", "type": "Microsoft.Common.InfoBox", - "visible": true, "options": { "text": "Since not all service features are available in all regions, Mission Landing Zone is available in a subset of regions.", "style": "Info" @@ -134,7 +122,6 @@ "name": "locationName", "label": "Location", "type": "Microsoft.Common.DropDown", - "visible": true, "defaultValue": "", "toolTip": "Select the Location for your Mission Landing Zone.", "multiselect": false, @@ -146,6 +133,38 @@ "allowedValues": "[map(filter(steps('basics').deploymentDetails.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", "required": true } + }, + { + "name": "environment", + "label": "Environment", + "type": "Microsoft.Common.DropDown", + "defaultValue": "Development", + "toolTip": "Select the environment for the deployment.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items...", + "multiLine": true, + "constraints": { + "allowedValues": [ + { + "label": "Development", + "description": "Select if you want to deploy a development environment.", + "value": "dev" + }, + { + "label": "Test", + "description": "Select if you want to deploy a test environment.", + "value": "tst" + }, + { + "label": "Production", + "description": "Select if you want to deploy a production environment.", + "value": "prd" + } + ], + "required": true + } } ] }, @@ -153,13 +172,11 @@ "name": "missionLandingZoneName", "label": "Mission Landing Zone Name", "type": "Microsoft.Common.Section", - "visible": true, "elements": [ { "name": "missionLandingZonePrefix", "label": "Resource Naming Prefix", "type": "Microsoft.Common.TextBox", - "visible": true, "defaultValue": "", "toolTip": "Specify a prefix (min 1 and max 10 lowercase characters and numbers) to prepend to all resources.", "constraints": { @@ -195,7 +212,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'hub')]", + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'hub')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -207,7 +224,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'identity')]", + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'identity')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -219,7 +236,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'operation')]", + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'operation')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -231,7 +248,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, 'sharesvc')]", + "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'sharesvc')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -241,19 +258,554 @@ ] }, { - "name": "networking", - "label": "Networking", - "elements": [] + "name": "compliance", + "label": "Compliance", + "elements": [ + { + "name": "policy", + "label": "Policy", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "deploymentDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling policies is optional, but recommended. Mission Landing Zone comes bundled with some built-in policies." + } + }, + { + "name": "deployPolicy", + "type": "Microsoft.Common.CheckBox", + "label": "Create policy assignments?", + "toolTip": "Check here to create policy assignments for the resources created by Mission Landing Zone.", + "constraints": { + "required": false + } + }, + { + "name": "policy", + "type": "Microsoft.Common.DropDown", + "label": "Policy Assignment", + "placeholder": "", + "defaultValue": "NIST SP 800-53", + "toolTip": "IL5 is only available for AzureUsGovernment and will switch to NIST if tried in AzureCloud.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "defaultDescription": "Select one of the bundled built-in policy assignments.", + "constraints": { + "allowedValues": [ + { + "label": "NIST SP 800-53", + "description": "The US National Institute of Standards and Technology (NIST) publishes a catalog of security and privacy controls, Special Publication (SP) 800-53, for all federal information systems in the United States (except those related to national security).", + "value": "NIST" + }, + { + "label": "DoD IL5", + "description": "The Defense Information Systems Agency (DISA) is an agency of the US Department of Defense (DoD) that is responsible for developing and maintaining the DoD Cloud Computing Security Requirements Guide (SRG). These policies are only available for AzureUsGovernment and will switch to NIST if tried in AzureCloud.", + "value": "IL5" + }, + { + "label": "CMMC", + "description": "The Cybersecurity Maturity Model Certification (CMMC) is a new framework developed by the US Department of Defense (DoD) that requires formal third-party audits of defense industrial base (DIB) contractor cybersecurity practices.", + "value": "CMMC" + } + ] + }, + "visible": "[steps('compliance').policy.deployPolicy]" + } + ] + }, + { + "name": "securityCenter", + "label": "Security Center", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "deploymentDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling Azure Security Center is optional, but recommended. Mission Landing Zone can enable Azure Security Center for the subscriptions it is deploying into." + } + }, + { + "name": "deployASC", + "type": "Microsoft.Common.CheckBox", + "label": "Enable Azure Security Center?", + "toolTip": "Check here to enable Azure Security Center for the subscriptions used to deploy Mission Landing Zone.", + "constraints": { + "required": false + } + }, + { + "name": "emailSecurityContact", + "type": "Microsoft.Common.TextBox", + "label": "Security Contact E-Mail Address", + "defaultValue": "", + "toolTip": "Provide an e-mail address as a security contact for Azure Security Center", + "placeholder": "johndoe@contoso.com", + "multiLine": false, + "constraints": { + "required": "[steps('compliance').securityCenter.deployASC]", + "validations": [ + { + "regex": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", + "message": "Provide a valid e-mail address" + } + ] + }, + "visible": "[steps('compliance').securityCenter.deployASC]" + } + ] + } + ] }, { - "name": "policy", - "label": "Policy", - "elements": [] + "name": "networking", + "label": "Networking", + "elements": [ + { + "name": "infoBoxVirtualNetworkOverlap", + "type": "Microsoft.Common.InfoBox", + "options": { + "text": "Make sure that the address spaces do not overlap with each other for the Hub, Identity, Operations, or Shared Services networks.", + "style": "Info" + } + }, + { + "name": "hubVirtualNetwork", + "label": "Hub Virtual Network", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "virtualNetworkAddressCidrRange", + "label": "Hub Virtual Network CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.100.0/24", + "toolTip": "Specify an address CIDR range within the range [10,24].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + } + ] + } + }, + { + "name": "subnetAddressCidrRange", + "label": "Hub Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.100.128/27", + "toolTip": "Specify a CIDR range for the default subnet within the Hub Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').hubVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').hubVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').hubVirtualNetwork.subnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + }, + { + "name": "firewallClientSubnetAddressCidrRange", + "label": "Firewall Client Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.100.64/26", + "toolTip": "Specify a CIDR range for the Azure Firewall Client subnet within the Hub Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + }, + { + "name": "firewallManagementSubnetAddressCidrRange", + "label": "Firewall Management Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.100.0/26", + "toolTip": "Specify a CIDR range for the Azure Firewall Management subnet within the Hub Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + }, + { + "name": "bastionSubnetAddressCidrRange", + "label": "Azure Bastion Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.100.128/26", + "toolTip": "Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range. It must be of size /26 or larger.", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + } + ] + }, + { + "name": "identityVirtualNetwork", + "label": "Identity Virtual Network", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "virtualNetworkAddressCidrRange", + "label": "Identity Virtual Network CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.110.0/26", + "toolTip": "Specify an address CIDR range within the range [10,24].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + } + ] + } + }, + { + "name": "subnetAddressCidrRange", + "label": "Identity Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.110.0/27", + "toolTip": "Specify a CIDR range for the default subnet within the Identity Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').identityVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').identityVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').identityVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').identityVirtualNetwork.subnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + } + ] + }, + { + "name": "operationsVirtualNetwork", + "label": "Operations Virtual Network", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "virtualNetworkAddressCidrRange", + "label": "Operations Virtual Network CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.115.0/26", + "toolTip": "Specify an address CIDR range within the range [10,24].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + } + ] + } + }, + { + "name": "subnetAddressCidrRange", + "label": "Operations Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.115.0/27", + "toolTip": "Specify a CIDR range for the default subnet within the Operations Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').operationsVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').operationsVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').operationsVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').operationsVirtualNetwork.subnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + } + ] + }, + { + "name": "sharedServicesVirtualNetwork", + "label": "Shared Services Virtual Network", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "virtualNetworkAddressCidrRange", + "label": "Shared Services Virtual Network CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.120.0/26", + "toolTip": "Specify an address CIDR range within the range [10,24].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + } + ] + } + }, + { + "name": "subnetAddressCidrRange", + "label": "Shared Services Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "defaultValue": "10.0.120.0/27", + "toolTip": "Specify a CIDR range for the default subnet within the Shared Services Virtual Network range [24,28].", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "CIDR range not within virtual network CIDR range (first octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "CIDR range not within virtual network CIDR range (second octet)." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "CIDR range not within virtual network CIDR range (third octet)." + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange, '/')))]", + "message": "CIDR range not within virtual network CIDR range (subnet mask)." + } + ] + } + } + ] + } + ] }, { "name": "remoteAccess", "label": "Remote Access", - "elements": [] + "elements": [ + { + "name": "windowsVmConfiguration", + "label": "Windows Virtual Machine Configuration", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "windowsVmAdminUsername", + "type": "Microsoft.Compute.UserNameTextBox", + "label": "Username", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z]{1,30}$", + "validationMessage": "Only alphanumeric characters are allowed, and the value must be 1-30 characters long." + }, + "osPlatform": "Windows", + "visible": true + }, + { + "name": "windowsVmAdminPassword", + "label": { + "password": "Password", + "confirmPassword": "Confirm password" + }, + "type": "Microsoft.Compute.CredentialsCombo", + "defaultValue": "", + "toolTip": { + "password": "Specify an administrator password for the Windows virtual machine used to remote into the network." + }, + "constraints": { + "required": true, + "customPasswordRegex": "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{12,128}$", + "customValidationMessage": "The password must be alphanumeric, contain at least 12 characters, and have at least 1 letter, 1 number and one special character." + }, + "options": { + "hideConfirmation": false + }, + "osPlatform": "Windows" + } + ] + }, + { + "name": "linuxVmConfiguration", + "label": "Linux Virtual Machine Configuration", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "linuxVmAdminUsername", + "type": "Microsoft.Compute.UserNameTextBox", + "label": "Username", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z]{1,30}$", + "validationMessage": "Only alphanumeric characters are allowed, and the value must be 1-30 characters long." + }, + "osPlatform": "Linux", + "visible": true + }, + { + "name": "linuxVmAdminPasswordOrKey", + "type": "Microsoft.Compute.CredentialsCombo", + "label": { + "authenticationType": "Authentication type", + "password": "Password", + "confirmPassword": "Confirm password", + "sshPublicKey": "SSH public key" + }, + "toolTip": { + "authenticationType": "Select an authentication type", + "password": "Specify an administrator password for the Linux virtual machine used to remote into the network.", + "sshPublicKey": "Paste in an SSH Public Key for the Linux virtual machine used to remote into the network." + }, + "constraints": { + "required": true, + "customPasswordRegex": "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{12,}$", + "customValidationMessage": "The password must be alphanumeric, contain at least 12 characters, and have at least 1 letter and 1 number." + }, + "options": { + "hideConfirmation": false, + "hidePassword": false + }, + "osPlatform": "Linux" + } + ] + } + ] + }, + { + "name": "tags", + "label": "Tags", + "subLabel": { + "preValidation": "Provide tags that will be used for all resources.", + "postValidation": "Done" + }, + "bladeTitle": "Tags", + "bladeSubtitle": "Tags", + "elements": [ + { + "name": "tagsByResource", + "label": "Tags by Resource", + "type": "Microsoft.Common.TagsByResource", + "visible": true, + "resources": [ + "MissionLandingZone" + ] + } + ] } ], "outputs": {} From b1289c7ab87e912e6305a2393c00a8892f5a6462 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 1 Dec 2021 10:50:25 -0500 Subject: [PATCH 06/29] add blade titles --- src/bicep/form/portal.missionLandingZone.json | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 349a30413..8a619132f 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -13,7 +13,7 @@ "name": "infoBoxMissionLandingZone", "type": "Microsoft.Common.InfoBox", "options": { - "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit 'aka.ms/missionlz' for more details about the solution pattern.", + "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit http://aka.ms/missionlz for more details about the solution pattern.", "style": "Info", "uri": "https://aka.ms/missionlz" } @@ -212,7 +212,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'hub')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'hub')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -224,7 +224,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'identity')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'id')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -236,7 +236,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'operation')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'op')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -248,7 +248,7 @@ "method": "POST", "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stdiag', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'sharesvc')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'svcs')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -261,6 +261,15 @@ "name": "compliance", "label": "Compliance", "elements": [ + { + "name": "complianceDescriptionInfoBox", + "type": "Microsoft.Common.InfoBox", + "options": { + "text": "Mission Landing Zone comes bundled with built-in policies that can be applied to the resources it deploys and the ability to enable Azure Security Center: https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction", + "style": "Info", + "uri": "https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction" + } + }, { "name": "policy", "label": "Policy", @@ -288,7 +297,7 @@ "label": "Policy Assignment", "placeholder": "", "defaultValue": "NIST SP 800-53", - "toolTip": "IL5 is only available for AzureUsGovernment and will switch to NIST if tried in AzureCloud.", + "toolTip": "DoD IL5 is only available in AzureUsGovernment and will switch to NIST if tried in AzureCloud.", "multiselect": false, "selectAll": false, "filter": true, @@ -696,11 +705,27 @@ "name": "remoteAccess", "label": "Remote Access", "elements": [ + { + "name": "remoteAccessDescriptionInfoBox", + "type": "Microsoft.Common.InfoBox", + "options": { + "text": "Mission Landing Zone provisions a Windows and a Linux virtual machine to remotely access the network using Azure Bastion hosts. For more information on how to use Azure Bastion check out: https://docs.microsoft.com/en-us/azure/bastion/bastion-overview", + "style": "Info", + "uri": "https://docs.microsoft.com/en-us/azure/bastion/bastion-overview" + } + }, { "name": "windowsVmConfiguration", - "label": "Windows Virtual Machine Configuration", + "label": "Windows Virtual Machine", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "windowsVmDescriptionTextblock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Provide an administrator username and password for the Windows virtual machine." + } + }, { "name": "windowsVmAdminUsername", "type": "Microsoft.Compute.UserNameTextBox", @@ -740,9 +765,16 @@ }, { "name": "linuxVmConfiguration", - "label": "Linux Virtual Machine Configuration", + "label": "Linux Virtual Machine", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "windowsVmDescriptionTextblock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Provide an administrator username and password (or SSH public key) for the Linux virtual machine." + } + }, { "name": "linuxVmAdminUsername", "type": "Microsoft.Compute.UserNameTextBox", From eca1e786c90476b48cdb09cc73ead60d10bc8f77 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 1 Dec 2021 15:06:15 -0500 Subject: [PATCH 07/29] add helpful labels --- src/bicep/form/portal.missionLandingZone.json | 111 +++++++++++++++--- 1 file changed, 92 insertions(+), 19 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 8a619132f..2a605836b 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -10,12 +10,14 @@ "label": "Basics", "elements": [ { - "name": "infoBoxMissionLandingZone", - "type": "Microsoft.Common.InfoBox", + "name": "basicsDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", "options": { - "text": "Mission Landing Zone is a prescriptive reference architecture for data with reference implementation provided by Microsoft. Visit http://aka.ms/missionlz for more details about the solution pattern.", - "style": "Info", - "uri": "https://aka.ms/missionlz" + "text": "Mission Landing Zone is a prescriptive reference architecture with reference implementation of a SCCA compliant Hub and Spoke virtual network provided by Microsoft.", + "link": { + "label": "https://aka.ms/missionlz", + "uri": "https://aka.ms/missionlz" + } } }, { @@ -46,6 +48,13 @@ "text": "Select the subscription(s) and location for your Mission Landing Zone deployment." } }, + { + "name": "subscriptionDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone is configured for deployment into a single subscription or many subscriptions depending on your needs for resource counts, subscription boundaries, or billing." + } + }, { "name": "hubSubscriptionId", "label": "Hub Subscription", @@ -262,12 +271,14 @@ "label": "Compliance", "elements": [ { - "name": "complianceDescriptionInfoBox", - "type": "Microsoft.Common.InfoBox", + "name": "complianceDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", "options": { - "text": "Mission Landing Zone comes bundled with built-in policies that can be applied to the resources it deploys and the ability to enable Azure Security Center: https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction", - "style": "Info", - "uri": "https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction" + "text": "Mission Landing Zone comes bundled with built-in policies that can be applied to the resources it deploys and the ability to enable Azure Security Center for the subscriptions it is deployed into.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction" + } } }, { @@ -276,10 +287,17 @@ "type": "Microsoft.Common.Section", "elements": [ { - "name": "deploymentDetailsText", + "name": "policyOptionalTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling policies is optional, but recommended." + } + }, + { + "name": "policySubsetDetailsTextBlock", "type": "Microsoft.Common.TextBlock", "options": { - "text": "Enabling policies is optional, but recommended. Mission Landing Zone comes bundled with some built-in policies." + "text": "Mission Landing Zone comes bundled with a subset of available Azure policies." } }, { @@ -333,10 +351,17 @@ "type": "Microsoft.Common.Section", "elements": [ { - "name": "deploymentDetailsText", + "name": "securityCenterOptionalDetailsText", "type": "Microsoft.Common.TextBlock", "options": { - "text": "Enabling Azure Security Center is optional, but recommended. Mission Landing Zone can enable Azure Security Center for the subscriptions it is deploying into." + "text": "Enabling Azure Security Center is optional, but recommended." + } + }, + { + "name": "securityCenterSubscriptionDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Checking this box will activate Azure Security Center for subscription Mission Landing Zone is deployed into." } }, { @@ -375,6 +400,24 @@ "name": "networking", "label": "Networking", "elements": [ + { + "name": "networkDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone deploys virtual networks configured for SCCA compliance." + } + }, + { + "name": "dodNeedsDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "SCCA guidance and architectures are specific to DoD customers, but they also help civilian customers comply with Trusted Internet Connections (TIC) guidance and help commercial customers that want to implement a secure DMZ to protect their Azure environments.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/en-us/azure/azure-government/compliance/secure-azure-computing-architecture" + } + } + }, { "name": "infoBoxVirtualNetworkOverlap", "type": "Microsoft.Common.InfoBox", @@ -388,6 +431,13 @@ "label": "Hub Virtual Network", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "hubVirtualNetworkDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network. This network also houses the Azure Bastion hosts for remote access into the other networks." + } + }, { "name": "virtualNetworkAddressCidrRange", "label": "Hub Virtual Network CIDR Range", @@ -539,6 +589,13 @@ "label": "Identity Virtual Network", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "hubVirtualNetworkDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Identity spoke virtual network can be used to house Active Directory and other AuthN and AuthZ solutions." + } + }, { "name": "virtualNetworkAddressCidrRange", "label": "Identity Virtual Network CIDR Range", @@ -594,6 +651,13 @@ "label": "Operations Virtual Network", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "hubVirtualNetworkDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Operations spoke virtual network can be used for operational tasks like logging and administration of workloads." + } + }, { "name": "virtualNetworkAddressCidrRange", "label": "Operations Virtual Network CIDR Range", @@ -649,6 +713,13 @@ "label": "Shared Services Virtual Network", "type": "Microsoft.Common.Section", "elements": [ + { + "name": "hubVirtualNetworkDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Shared Services spoke virtual network can be used for services that are used by multiple workloads like source control and container registries." + } + }, { "name": "virtualNetworkAddressCidrRange", "label": "Shared Services Virtual Network CIDR Range", @@ -706,12 +777,14 @@ "label": "Remote Access", "elements": [ { - "name": "remoteAccessDescriptionInfoBox", - "type": "Microsoft.Common.InfoBox", + "name": "complianceDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", "options": { - "text": "Mission Landing Zone provisions a Windows and a Linux virtual machine to remotely access the network using Azure Bastion hosts. For more information on how to use Azure Bastion check out: https://docs.microsoft.com/en-us/azure/bastion/bastion-overview", - "style": "Info", - "uri": "https://docs.microsoft.com/en-us/azure/bastion/bastion-overview" + "text": "Mission Landing Zone provisions a Windows and a Linux virtual machine to securely access the network remotely using Azure Bastion hosts.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/en-us/azure/bastion/bastion-overview" + } } }, { From b173964dfa8795cd107efabb294f201b84065244 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:41:20 -0500 Subject: [PATCH 08/29] firewall subnet size regex --- src/bicep/form/portal.missionLandingZone.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 2a605836b..be7fb5b7c 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -491,13 +491,13 @@ "label": "Firewall Client Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.100.64/26", - "toolTip": "Specify a CIDR range for the Azure Firewall Client subnet within the Hub Virtual Network range [24,28].", + "toolTip": "Specify a CIDR range for the Azure Firewall Client subnet within the Hub Virtual Network range [24,26].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." }, { "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange, '/')), '.'), 1))), true)]", @@ -523,13 +523,13 @@ "label": "Firewall Management Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.100.0/26", - "toolTip": "Specify a CIDR range for the Azure Firewall Management subnet within the Hub Virtual Network range [24,28].", + "toolTip": "Specify a CIDR range for the Azure Firewall Management subnet within the Hub Virtual Network range [24,26].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." }, { "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange, '/')), '.'), 1))), true)]", From 33107f8eee73ddce025b3653b5baf2481062049e Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 1 Dec 2021 17:17:27 -0500 Subject: [PATCH 09/29] add sections for hub and spokes --- src/bicep/form/portal.missionLandingZone.json | 214 +++++++++++------- 1 file changed, 128 insertions(+), 86 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index be7fb5b7c..55d900510 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -21,8 +21,8 @@ } }, { - "name": "deploymentDetails", - "label": "Deployment Details", + "name": "armApiControls", + "label": "", "type": "Microsoft.Common.Section", "elements": [ { @@ -40,9 +40,16 @@ "method": "GET", "path": "locations?api-version=2019-11-01" } - }, + } + ] + }, + { + "name": "selectSubscriptions", + "label": "Select Subscription(s)", + "type": "Microsoft.Common.Section", + "elements": [ { - "name": "deploymentDetailsText", + "name": "selectSubscriptionsText", "type": "Microsoft.Common.TextBlock", "options": { "text": "Select the subscription(s) and location for your Mission Landing Zone deployment." @@ -54,6 +61,20 @@ "options": { "text": "Mission Landing Zone is configured for deployment into a single subscription or many subscriptions depending on your needs for resource counts, subscription boundaries, or billing." } + } + ] + }, + { + "name": "hubDetails", + "label": "Hub", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "hubDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network. This network also houses the Azure Bastion hosts for remote access into the other networks." + } }, { "name": "hubSubscriptionId", @@ -67,9 +88,23 @@ "filterPlaceholder": "Filter items ...", "multiLine": true, "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "allowedValues": "[map(steps('basics').armApiControls.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", "required": true } + } + ] + }, + { + "name": "identityDetails", + "label": "Identity", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "identityDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Identity spoke is used to house Active Directory and other AuthN and AuthZ solutions." + } }, { "name": "identitySubscriptionId", @@ -83,9 +118,23 @@ "filterPlaceholder": "Filter items ...", "multiLine": true, "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "allowedValues": "[map(steps('basics').armApiControls.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", "required": true } + } + ] + }, + { + "name": "operationsDetails", + "label": "Operations", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "operationsDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Operations spoke can be used for operational tasks like logging and administration of workloads." + } }, { "name": "operationsSubscriptionId", @@ -99,9 +148,23 @@ "filterPlaceholder": "Filter items ...", "multiLine": true, "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "allowedValues": "[map(steps('basics').armApiControls.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", "required": true } + } + ] + }, + { + "name": "sharedServicesDetails", + "label": "Shared Services", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "sharedServicesDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "The Shared Services spoke can be used to host services that are used by multiple workloads like source control and container registries." + } }, { "name": "sharedServicesSubscriptionId", @@ -115,10 +178,17 @@ "filterPlaceholder": "Filter items ...", "multiLine": true, "constraints": { - "allowedValues": "[map(steps('basics').deploymentDetails.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", + "allowedValues": "[map(steps('basics').armApiControls.subscriptionApi.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]", "required": true } - }, + } + ] + }, + { + "name": "missionLandingZoneLocation", + "label": "Location", + "type": "Microsoft.Common.Section", + "elements": [ { "name": "infoBoxLocation", "type": "Microsoft.Common.InfoBox", @@ -139,39 +209,7 @@ "filterPlaceholder": "Filter items ...", "multiLine": true, "constraints": { - "allowedValues": "[map(filter(steps('basics').deploymentDetails.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", - "required": true - } - }, - { - "name": "environment", - "label": "Environment", - "type": "Microsoft.Common.DropDown", - "defaultValue": "Development", - "toolTip": "Select the environment for the deployment.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items...", - "multiLine": true, - "constraints": { - "allowedValues": [ - { - "label": "Development", - "description": "Select if you want to deploy a development environment.", - "value": "dev" - }, - { - "label": "Test", - "description": "Select if you want to deploy a test environment.", - "value": "tst" - }, - { - "label": "Production", - "description": "Select if you want to deploy a production environment.", - "value": "prd" - } - ], + "allowedValues": "[map(filter(steps('basics').armApiControls.locationsApi.value,(item) => contains(split('eastus,eastus2,southcentralus,westus,westus2,usgovvirginia,usgovarizona,ussec,usnat', ','), item.name)),(item) => parse(concat('{\"label\":\"', item.regionalDisplayName, '\",\"value\":\"', item.name, '\"}')))]", "required": true } } @@ -196,68 +234,100 @@ "message": "The prefix must be between 1-10 lowercase characters and numbers." }, { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi001.nameAvailable, false))]", + "isValid": "[not(equals(steps('basics').missionLandingZoneName.hubStorageAccountApi.nameAvailable, false))]", "message": "Prefix currently unavailable. Please choose a different one." }, { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi002.nameAvailable, false))]", + "isValid": "[not(equals(steps('basics').missionLandingZoneName.identityStorageAccountApi.nameAvailable, false))]", "message": "Prefix currently unavailable. Please choose a different one." }, { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi003.nameAvailable, false))]", + "isValid": "[not(equals(steps('basics').missionLandingZoneName.operationsStorageAccountApi.nameAvailable, false))]", "message": "Prefix currently unavailable. Please choose a different one." }, { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.storageAccountNameApi004.nameAvailable, false))]", + "isValid": "[not(equals(steps('basics').missionLandingZoneName.sharedServicesStorageAccountApi.nameAvailable, false))]", "message": "Prefix currently unavailable. Please choose a different one." } ] } }, { - "name": "storageAccountNameApi001", + "name": "environment", + "label": "Environment", + "type": "Microsoft.Common.DropDown", + "defaultValue": "Development", + "toolTip": "Select the environment for the deployment.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items...", + "multiLine": true, + "constraints": { + "allowedValues": [ + { + "label": "Development", + "description": "Select if you want to deploy a development environment.", + "value": "dev" + }, + { + "label": "Test", + "description": "Select if you want to deploy a test environment.", + "value": "tst" + }, + { + "label": "Production", + "description": "Select if you want to deploy a production environment.", + "value": "prd" + } + ], + "required": true + } + }, + { + "name": "hubStorageAccountApi", "type": "Microsoft.Solutions.ArmApiControl", "request": { "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "path": "[concat(steps('basics').hubDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'hub')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'hub')]", "type": "Microsoft.Storage/storageAccounts" } } }, { - "name": "storageAccountNameApi002", + "name": "identityStorageAccountApi", "type": "Microsoft.Solutions.ArmApiControl", "request": { "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "path": "[concat(steps('basics').identityDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'id')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'id')]", "type": "Microsoft.Storage/storageAccounts" } } }, { - "name": "storageAccountNameApi003", + "name": "operationsStorageAccountApi", "type": "Microsoft.Solutions.ArmApiControl", "request": { "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "path": "[concat(steps('basics').operationsDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'op')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'op')]", "type": "Microsoft.Storage/storageAccounts" } } }, { - "name": "storageAccountNameApi004", + "name": "sharedServicesStorageAccountApi", "type": "Microsoft.Solutions.ArmApiControl", "request": { "method": "POST", - "path": "[concat(steps('basics').deploymentDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", + "path": "[concat(steps('basics').sharedServicesDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').environment, 'svcs')]", + "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'svcs')]", "type": "Microsoft.Storage/storageAccounts" } } @@ -431,13 +501,6 @@ "label": "Hub Virtual Network", "type": "Microsoft.Common.Section", "elements": [ - { - "name": "hubVirtualNetworkDetailsTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network. This network also houses the Azure Bastion hosts for remote access into the other networks." - } - }, { "name": "virtualNetworkAddressCidrRange", "label": "Hub Virtual Network CIDR Range", @@ -589,13 +652,6 @@ "label": "Identity Virtual Network", "type": "Microsoft.Common.Section", "elements": [ - { - "name": "hubVirtualNetworkDetailsTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "The Identity spoke virtual network can be used to house Active Directory and other AuthN and AuthZ solutions." - } - }, { "name": "virtualNetworkAddressCidrRange", "label": "Identity Virtual Network CIDR Range", @@ -651,13 +707,6 @@ "label": "Operations Virtual Network", "type": "Microsoft.Common.Section", "elements": [ - { - "name": "hubVirtualNetworkDetailsTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "The Operations spoke virtual network can be used for operational tasks like logging and administration of workloads." - } - }, { "name": "virtualNetworkAddressCidrRange", "label": "Operations Virtual Network CIDR Range", @@ -713,13 +762,6 @@ "label": "Shared Services Virtual Network", "type": "Microsoft.Common.Section", "elements": [ - { - "name": "hubVirtualNetworkDetailsTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "The Shared Services spoke virtual network can be used for services that are used by multiple workloads like source control and container registries." - } - }, { "name": "virtualNetworkAddressCidrRange", "label": "Shared Services Virtual Network CIDR Range", From 26ebb37757e8dbd61de7467a70899b4aa955f822 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 1 Dec 2021 18:40:07 -0500 Subject: [PATCH 10/29] update validation --- src/bicep/form/portal.missionLandingZone.json | 430 ++++++++++-------- 1 file changed, 231 insertions(+), 199 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 55d900510..274ac4c91 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -48,13 +48,6 @@ "label": "Select Subscription(s)", "type": "Microsoft.Common.Section", "elements": [ - { - "name": "selectSubscriptionsText", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Select the subscription(s) and location for your Mission Landing Zone deployment." - } - }, { "name": "subscriptionDetailsText", "type": "Microsoft.Common.TextBlock", @@ -73,7 +66,7 @@ "name": "hubDetailsTextBlock", "type": "Microsoft.Common.TextBlock", "options": { - "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network. This network also houses the Azure Bastion hosts for remote access into the other networks." + "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network and houses the Azure Bastion host for secure remote access into the network." } }, { @@ -103,7 +96,7 @@ "name": "identityDetailsTextBlock", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The Identity spoke is used to house Active Directory and other AuthN and AuthZ solutions." + "text": "The Identity spoke can be used to house Active Directory and other AuthN and AuthZ solutions." } }, { @@ -336,136 +329,6 @@ } ] }, - { - "name": "compliance", - "label": "Compliance", - "elements": [ - { - "name": "complianceDescriptionTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Mission Landing Zone comes bundled with built-in policies that can be applied to the resources it deploys and the ability to enable Azure Security Center for the subscriptions it is deployed into.", - "link": { - "label": "Learn more", - "uri": "https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction" - } - } - }, - { - "name": "policy", - "label": "Policy", - "type": "Microsoft.Common.Section", - "elements": [ - { - "name": "policyOptionalTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Enabling policies is optional, but recommended." - } - }, - { - "name": "policySubsetDetailsTextBlock", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Mission Landing Zone comes bundled with a subset of available Azure policies." - } - }, - { - "name": "deployPolicy", - "type": "Microsoft.Common.CheckBox", - "label": "Create policy assignments?", - "toolTip": "Check here to create policy assignments for the resources created by Mission Landing Zone.", - "constraints": { - "required": false - } - }, - { - "name": "policy", - "type": "Microsoft.Common.DropDown", - "label": "Policy Assignment", - "placeholder": "", - "defaultValue": "NIST SP 800-53", - "toolTip": "DoD IL5 is only available in AzureUsGovernment and will switch to NIST if tried in AzureCloud.", - "multiselect": false, - "selectAll": false, - "filter": true, - "filterPlaceholder": "Filter items ...", - "multiLine": true, - "defaultDescription": "Select one of the bundled built-in policy assignments.", - "constraints": { - "allowedValues": [ - { - "label": "NIST SP 800-53", - "description": "The US National Institute of Standards and Technology (NIST) publishes a catalog of security and privacy controls, Special Publication (SP) 800-53, for all federal information systems in the United States (except those related to national security).", - "value": "NIST" - }, - { - "label": "DoD IL5", - "description": "The Defense Information Systems Agency (DISA) is an agency of the US Department of Defense (DoD) that is responsible for developing and maintaining the DoD Cloud Computing Security Requirements Guide (SRG). These policies are only available for AzureUsGovernment and will switch to NIST if tried in AzureCloud.", - "value": "IL5" - }, - { - "label": "CMMC", - "description": "The Cybersecurity Maturity Model Certification (CMMC) is a new framework developed by the US Department of Defense (DoD) that requires formal third-party audits of defense industrial base (DIB) contractor cybersecurity practices.", - "value": "CMMC" - } - ] - }, - "visible": "[steps('compliance').policy.deployPolicy]" - } - ] - }, - { - "name": "securityCenter", - "label": "Security Center", - "type": "Microsoft.Common.Section", - "elements": [ - { - "name": "securityCenterOptionalDetailsText", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Enabling Azure Security Center is optional, but recommended." - } - }, - { - "name": "securityCenterSubscriptionDetailsText", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Checking this box will activate Azure Security Center for subscription Mission Landing Zone is deployed into." - } - }, - { - "name": "deployASC", - "type": "Microsoft.Common.CheckBox", - "label": "Enable Azure Security Center?", - "toolTip": "Check here to enable Azure Security Center for the subscriptions used to deploy Mission Landing Zone.", - "constraints": { - "required": false - } - }, - { - "name": "emailSecurityContact", - "type": "Microsoft.Common.TextBox", - "label": "Security Contact E-Mail Address", - "defaultValue": "", - "toolTip": "Provide an e-mail address as a security contact for Azure Security Center", - "placeholder": "johndoe@contoso.com", - "multiLine": false, - "constraints": { - "required": "[steps('compliance').securityCenter.deployASC]", - "validations": [ - { - "regex": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", - "message": "Provide a valid e-mail address" - } - ] - }, - "visible": "[steps('compliance').securityCenter.deployASC]" - } - ] - } - ] - }, { "name": "networking", "label": "Networking", @@ -554,7 +417,7 @@ "label": "Firewall Client Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.100.64/26", - "toolTip": "Specify a CIDR range for the Azure Firewall Client subnet within the Hub Virtual Network range [24,26].", + "toolTip": "Specify a CIDR range for the Azure Firewall Client subnet within the Hub Virtual Network range. It must be of size /26 or larger.", "constraints": { "required": true, "validations": [ @@ -586,7 +449,7 @@ "label": "Firewall Management Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.100.0/26", - "toolTip": "Specify a CIDR range for the Azure Firewall Management subnet within the Hub Virtual Network range [24,26].", + "toolTip": "Specify a CIDR range for the Azure Firewall Management subnet within the Hub Virtual Network range. It must be of size /26 or larger.", "constraints": { "required": true, "validations": [ @@ -612,38 +475,6 @@ } ] } - }, - { - "name": "bastionSubnetAddressCidrRange", - "label": "Azure Bastion Subnet CIDR Range", - "type": "Microsoft.Common.TextBox", - "defaultValue": "10.0.100.128/26", - "toolTip": "Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range. It must be of size /26 or larger.", - "constraints": { - "required": true, - "validations": [ - { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-6]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." - }, - { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 1))), true)]", - "message": "CIDR range not within virtual network CIDR range (first octet)." - }, - { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 2))), true)]", - "message": "CIDR range not within virtual network CIDR range (second octet)." - }, - { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')), '.'), 3))), true)]", - "message": "CIDR range not within virtual network CIDR range (third octet)." - }, - { - "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('networking').hubVirtualNetwork.bastionSubnetAddressCidrRange, '/')))]", - "message": "CIDR range not within virtual network CIDR range (subnet mask)." - } - ] - } } ] }, @@ -657,13 +488,13 @@ "label": "Identity Virtual Network CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.110.0/26", - "toolTip": "Specify an address CIDR range within the range [10,24].", + "toolTip": "Specify an address CIDR range within the range [10,26].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-7]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,27]." } ] } @@ -673,13 +504,13 @@ "label": "Identity Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.110.0/27", - "toolTip": "Specify a CIDR range for the default subnet within the Identity Virtual Network range [24,28].", + "toolTip": "Specify a CIDR range for the default subnet within the Identity Virtual Network range [26,28].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[6-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [26,28]." }, { "isValid": "[if(greaterOrEquals(last(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').identityVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", @@ -712,13 +543,13 @@ "label": "Operations Virtual Network CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.115.0/26", - "toolTip": "Specify an address CIDR range within the range [10,24].", + "toolTip": "Specify an address CIDR range within the range [10,26].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,26]." } ] } @@ -728,13 +559,13 @@ "label": "Operations Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.115.0/27", - "toolTip": "Specify a CIDR range for the default subnet within the Operations Virtual Network range [24,28].", + "toolTip": "Specify a CIDR range for the default subnet within the Operations Virtual Network range [26,28].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[6-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [26,28]." }, { "isValid": "[if(greaterOrEquals(last(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').operationsVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", @@ -767,13 +598,13 @@ "label": "Shared Services Virtual Network CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.120.0/26", - "toolTip": "Specify an address CIDR range within the range [10,24].", + "toolTip": "Specify an address CIDR range within the range [10,26].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [10,24]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,26]." } ] } @@ -783,24 +614,24 @@ "label": "Shared Services Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "defaultValue": "10.0.120.0/27", - "toolTip": "Specify a CIDR range for the default subnet within the Shared Services Virtual Network range [24,28].", + "toolTip": "Specify a CIDR range for the default subnet within the Shared Services Virtual Network range [26,28].", "constraints": { "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [24,28]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[6-8]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [26,28]." }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 1))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 1))), true)]", "message": "CIDR range not within virtual network CIDR range (first octet)." }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 2))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 2))), true)]", "message": "CIDR range not within virtual network CIDR range (second octet)." }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').virtualNetworkConfiguration.subnetAddressCidrRange, '/')), '.'), 3))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange, '/')), '.'), 3))), true)]", "message": "CIDR range not within virtual network CIDR range (third octet)." }, { @@ -814,25 +645,227 @@ } ] }, + { + "name": "compliance", + "label": "Compliance", + "elements": [ + { + "name": "complianceDescriptionTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone comes bundled with built-in policies that can be applied to the resources it deploys and the ability to enable Azure Security Center for the subscriptions it is deployed into.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction" + } + } + }, + { + "name": "policy", + "label": "Enable Azure Policy", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "policySubsetDetailsTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone comes bundled with a relevant subset of available Azure policies." + } + }, + { + "name": "policyOptionalTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling policies is optional, but recommended." + } + }, + { + "name": "deployPolicy", + "type": "Microsoft.Common.CheckBox", + "label": "Create policy assignments?", + "toolTip": "Check here to create policy assignments for the resources created by Mission Landing Zone.", + "constraints": { + "required": false + } + }, + { + "name": "policy", + "type": "Microsoft.Common.DropDown", + "label": "Policy Assignment", + "placeholder": "", + "defaultValue": "NIST SP 800-53", + "toolTip": "DoD IL5 is only available in AzureUsGovernment and will switch to NIST if tried in AzureCloud.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "defaultDescription": "Select one of the bundled built-in policy assignments.", + "constraints": { + "allowedValues": [ + { + "label": "NIST SP 800-53", + "description": "The US National Institute of Standards and Technology (NIST) publishes a catalog of security and privacy controls, Special Publication (SP) 800-53, for all federal information systems in the United States (except those related to national security).", + "value": "NIST" + }, + { + "label": "DoD IL5", + "description": "The Defense Information Systems Agency (DISA) is an agency of the US Department of Defense (DoD) that is responsible for developing and maintaining the DoD Cloud Computing Security Requirements Guide (SRG). These policies are only available for AzureUsGovernment and will switch to NIST if tried in AzureCloud.", + "value": "IL5" + }, + { + "label": "CMMC", + "description": "The Cybersecurity Maturity Model Certification (CMMC) is a new framework developed by the US Department of Defense (DoD) that requires formal third-party audits of defense industrial base (DIB) contractor cybersecurity practices.", + "value": "CMMC" + } + ] + }, + "visible": "[steps('compliance').policy.deployPolicy]" + } + ] + }, + { + "name": "securityCenter", + "label": "Enable Azure Security Center", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "securityCenterSubscriptionDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone can activate Azure Security Center for each subscription it is deployed into." + } + }, + { + "name": "securityCenterOptionalDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling Azure Security Center is optional, but recommended." + } + }, + { + "name": "deployASC", + "type": "Microsoft.Common.CheckBox", + "label": "Enable Azure Security Center?", + "toolTip": "Check here to enable Azure Security Center for the subscriptions used to deploy Mission Landing Zone.", + "constraints": { + "required": false + } + }, + { + "name": "emailSecurityContact", + "type": "Microsoft.Common.TextBox", + "label": "Security Contact E-Mail Address", + "defaultValue": "", + "toolTip": "Provide an e-mail address as a security contact for Azure Security Center", + "placeholder": "johndoe@contoso.com", + "multiLine": false, + "constraints": { + "required": "[steps('compliance').securityCenter.deployASC]", + "validations": [ + { + "regex": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", + "message": "Provide a valid e-mail address" + } + ] + }, + "visible": "[steps('compliance').securityCenter.deployASC]" + } + ] + } + ] + }, { "name": "remoteAccess", "label": "Remote Access", "elements": [ { - "name": "complianceDescriptionTextBlock", + "name": "remoteAccessDescriptionTextBlock", "type": "Microsoft.Common.TextBlock", "options": { - "text": "Mission Landing Zone provisions a Windows and a Linux virtual machine to securely access the network remotely using Azure Bastion hosts.", + "text": "Mission Landing Zone can provision a Windows and a Linux virtual machine to securely access the network remotely using Azure Bastion hosts.", "link": { "label": "Learn more", "uri": "https://docs.microsoft.com/en-us/azure/bastion/bastion-overview" } } }, + { + "name": "remoteAccessCheckbox", + "label": "Enable Remote Access", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "remoteAccessOptionalTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling remote access is optional, but recommended." + } + }, + { + "name": "deployRemoteAccess", + "type": "Microsoft.Common.CheckBox", + "label": "Remotely access the network?", + "toolTip": "Check here to create an Azure Bastion Host and virtual machines to remotely access the network.", + "constraints": { + "required": false + } + } + ] + }, + { + "name": "azureBastionSubnet", + "label": "Azure Bastion Subnet", + "type": "Microsoft.Common.Section", + "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "elements": [ + { + "name": "remoteAccessSubnetTextBlock", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range. It must be of size /26 or larger." + } + }, + { + "name": "bastionSubnetAddressCidrRange", + "label": "Azure Bastion Subnet CIDR Range", + "type": "Microsoft.Common.TextBox", + "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "defaultValue": "10.0.100.128/26", + "toolTip": "[concat('Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '. It must be of size /26 or larger.')]", + "constraints": { + "required": true, + "validations": [ + { + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 1))), true)]", + "message": "[concat('First octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 2))), true)]", + "message": "[concat('Second octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" + }, + { + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 3))), true)]", + "message": "[concat('Third octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" + }, + { + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')))]", + "message": "[concat('Subnet mask not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" + } + ] + } + } + ] + }, { "name": "windowsVmConfiguration", "label": "Windows Virtual Machine", "type": "Microsoft.Common.Section", + "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", "elements": [ { "name": "windowsVmDescriptionTextblock", @@ -882,6 +915,7 @@ "name": "linuxVmConfiguration", "label": "Linux Virtual Machine", "type": "Microsoft.Common.Section", + "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", "elements": [ { "name": "windowsVmDescriptionTextblock", @@ -919,9 +953,7 @@ "sshPublicKey": "Paste in an SSH Public Key for the Linux virtual machine used to remote into the network." }, "constraints": { - "required": true, - "customPasswordRegex": "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{12,}$", - "customValidationMessage": "The password must be alphanumeric, contain at least 12 characters, and have at least 1 letter and 1 number." + "required": true }, "options": { "hideConfirmation": false, From 69ceaa2fa62e4e7043159fd249cbf3564d2a770a Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:14:13 +0000 Subject: [PATCH 11/29] make it a wizard --- src/bicep/form/portal.missionLandingZone.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 274ac4c91..459fa7992 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -4,6 +4,7 @@ "kind": "Form", "properties": { "title": "Mission Landing Zone", + "isWizard": true, "steps": [ { "name": "basics", From 4e4b69f9300fb5dae17aee57da595fa88043731b Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:20:03 +0000 Subject: [PATCH 12/29] rename to resourcePrefix and resourceSuffix, remove storage account API controls --- src/bicep/form/portal.missionLandingZone.json | 74 ++----------------- 1 file changed, 5 insertions(+), 69 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 459fa7992..57d95292e 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -210,7 +210,7 @@ ] }, { - "name": "missionLandingZoneName", + "name": "resourcePrefix", "label": "Mission Landing Zone Name", "type": "Microsoft.Common.Section", "elements": [ @@ -226,29 +226,13 @@ { "regex": "^[a-z0-9]{1,10}$", "message": "The prefix must be between 1-10 lowercase characters and numbers." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.hubStorageAccountApi.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.identityStorageAccountApi.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.operationsStorageAccountApi.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." - }, - { - "isValid": "[not(equals(steps('basics').missionLandingZoneName.sharedServicesStorageAccountApi.nameAvailable, false))]", - "message": "Prefix currently unavailable. Please choose a different one." } ] } }, { - "name": "environment", - "label": "Environment", + "name": "resourceSuffix", + "label": "Resource Suffix", "type": "Microsoft.Common.DropDown", "defaultValue": "Development", "toolTip": "Select the environment for the deployment.", @@ -267,64 +251,16 @@ { "label": "Test", "description": "Select if you want to deploy a test environment.", - "value": "tst" + "value": "test" }, { "label": "Production", "description": "Select if you want to deploy a production environment.", - "value": "prd" + "value": "prod" } ], "required": true } - }, - { - "name": "hubStorageAccountApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').hubDetails.hubSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'hub')]", - "type": "Microsoft.Storage/storageAccounts" - } - } - }, - { - "name": "identityStorageAccountApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').identityDetails.identitySubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'id')]", - "type": "Microsoft.Storage/storageAccounts" - } - } - }, - { - "name": "operationsStorageAccountApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').operationsDetails.operationsSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'op')]", - "type": "Microsoft.Storage/storageAccounts" - } - } - }, - { - "name": "sharedServicesStorageAccountApi", - "type": "Microsoft.Solutions.ArmApiControl", - "request": { - "method": "POST", - "path": "[concat(steps('basics').sharedServicesDetails.sharedServicesSubscriptionId, '/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01')]", - "body": { - "name": "[concat('stg', steps('basics').missionLandingZoneName.missionLandingZonePrefix, steps('basics').missionLandingZoneName.environment, 'svcs')]", - "type": "Microsoft.Storage/storageAccounts" - } - } } ] } From ef9f657900fbd289de6dedd41241f92834a14c39 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:53:54 +0000 Subject: [PATCH 13/29] add outputs --- src/bicep/form/portal.missionLandingZone.json | 131 +++++++++++++----- 1 file changed, 98 insertions(+), 33 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 57d95292e..a61620220 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -59,12 +59,12 @@ ] }, { - "name": "hubDetails", + "name": "hubSection", "label": "Hub", "type": "Microsoft.Common.Section", "elements": [ { - "name": "hubDetailsTextBlock", + "name": "hubSectionTextBlock", "type": "Microsoft.Common.TextBlock", "options": { "text": "All network traffic is directed through the Azure Firewall residing in the Hub Virtual Network and houses the Azure Bastion host for secure remote access into the network." @@ -89,12 +89,12 @@ ] }, { - "name": "identityDetails", + "name": "identitySection", "label": "Identity", "type": "Microsoft.Common.Section", "elements": [ { - "name": "identityDetailsTextBlock", + "name": "identitySectionTextBlock", "type": "Microsoft.Common.TextBlock", "options": { "text": "The Identity spoke can be used to house Active Directory and other AuthN and AuthZ solutions." @@ -119,12 +119,12 @@ ] }, { - "name": "operationsDetails", + "name": "operationsSection", "label": "Operations", "type": "Microsoft.Common.Section", "elements": [ { - "name": "operationsDetailsTextBlock", + "name": "operationsSectionTextBlock", "type": "Microsoft.Common.TextBlock", "options": { "text": "The Operations spoke can be used for operational tasks like logging and administration of workloads." @@ -149,12 +149,12 @@ ] }, { - "name": "sharedServicesDetails", + "name": "sharedServicesSection", "label": "Shared Services", "type": "Microsoft.Common.Section", "elements": [ { - "name": "sharedServicesDetailsTextBlock", + "name": "sharedServicesSectionTextBlock", "type": "Microsoft.Common.TextBlock", "options": { "text": "The Shared Services spoke can be used to host services that are used by multiple workloads like source control and container registries." @@ -179,7 +179,7 @@ ] }, { - "name": "missionLandingZoneLocation", + "name": "locationSection", "label": "Location", "type": "Microsoft.Common.Section", "elements": [ @@ -192,7 +192,7 @@ } }, { - "name": "locationName", + "name": "location", "label": "Location", "type": "Microsoft.Common.DropDown", "defaultValue": "", @@ -210,12 +210,12 @@ ] }, { - "name": "resourcePrefix", + "name": "namingSection", "label": "Mission Landing Zone Name", "type": "Microsoft.Common.Section", "elements": [ { - "name": "missionLandingZonePrefix", + "name": "resourcePrefix", "label": "Resource Naming Prefix", "type": "Microsoft.Common.TextBox", "defaultValue": "", @@ -232,10 +232,10 @@ }, { "name": "resourceSuffix", - "label": "Resource Suffix", + "label": "Resource Naming Suffix", "type": "Microsoft.Common.DropDown", "defaultValue": "Development", - "toolTip": "Select the environment for the deployment.", + "toolTip": "Select a resource naming suffix to append to all resources.", "multiselect": false, "selectAll": false, "filter": true, @@ -598,7 +598,7 @@ } }, { - "name": "policy", + "name": "policySection", "label": "Enable Azure Policy", "type": "Microsoft.Common.Section", "elements": [ @@ -657,12 +657,12 @@ } ] }, - "visible": "[steps('compliance').policy.deployPolicy]" + "visible": "[steps('compliance').policySection.deployPolicy]" } ] }, { - "name": "securityCenter", + "name": "securityCenterSection", "label": "Enable Azure Security Center", "type": "Microsoft.Common.Section", "elements": [ @@ -698,7 +698,7 @@ "placeholder": "johndoe@contoso.com", "multiLine": false, "constraints": { - "required": "[steps('compliance').securityCenter.deployASC]", + "required": "[steps('compliance').securityCenterSection.deployASC]", "validations": [ { "regex": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", @@ -706,7 +706,37 @@ } ] }, - "visible": "[steps('compliance').securityCenter.deployASC]" + "visible": "[steps('compliance').securityCenterSection.deployASC]" + } + ] + }, + { + "name": "sentinelSection", + "label": "Enable Azure Sentinel", + "type": "Microsoft.Common.Section", + "elements": [ + { + "name": "sentinelSectionDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Mission Landing Zone can activate Azure Sentinel for the Log Analytics Workspace it deploys." + } + }, + { + "name": "sentinelOptionalDetailsText", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "Enabling Azure Sentinel is optional, but recommended." + } + }, + { + "name": "deploySentinel", + "type": "Microsoft.Common.CheckBox", + "label": "Enable Azure Sentinel?", + "toolTip": "Check here to enable Azure Sentinel Center for the Log Analytics Workspace Mission Landing Zone deploys.", + "constraints": { + "required": false + } } ] } @@ -728,7 +758,7 @@ } }, { - "name": "remoteAccessCheckbox", + "name": "remoteAccessSection", "label": "Enable Remote Access", "type": "Microsoft.Common.Section", "elements": [ @@ -751,10 +781,10 @@ ] }, { - "name": "azureBastionSubnet", + "name": "azureBastionSubnetSection", "label": "Azure Bastion Subnet", "type": "Microsoft.Common.Section", - "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "visible": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "elements": [ { "name": "remoteAccessSubnetTextBlock", @@ -767,7 +797,7 @@ "name": "bastionSubnetAddressCidrRange", "label": "Azure Bastion Subnet CIDR Range", "type": "Microsoft.Common.TextBox", - "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "visible": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "defaultValue": "10.0.100.128/26", "toolTip": "[concat('Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '. It must be of size /26 or larger.')]", "constraints": { @@ -778,19 +808,19 @@ "message": "Invalid CIDR range. The address prefix must be in the range [24,26]." }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 1))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange, '/')), '.'), 1))), true)]", "message": "[concat('First octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 2))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange, '/')), '.'), 2))), true)]", "message": "[concat('Second octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" }, { - "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')), '.'), 3))), true)]", + "isValid": "[if(greaterOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange, '/')), '.'), 3))), true)]", "message": "[concat('Third octet not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" }, { - "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('remoteAccess').azureBastionSubnet.bastionSubnetAddressCidrRange, '/')))]", + "isValid": "[lessOrEquals(last(split(steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '/')), last(split(steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange, '/')))]", "message": "[concat('Subnet mask not within the Hub virtual network CIDR range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange)]" } ] @@ -799,10 +829,10 @@ ] }, { - "name": "windowsVmConfiguration", + "name": "windowsVmSection", "label": "Windows Virtual Machine", "type": "Microsoft.Common.Section", - "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "visible": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "elements": [ { "name": "windowsVmDescriptionTextblock", @@ -849,13 +879,13 @@ ] }, { - "name": "linuxVmConfiguration", + "name": "linuxVmSection", "label": "Linux Virtual Machine", "type": "Microsoft.Common.Section", - "visible": "[steps('remoteAccess').remoteAccessCheckbox.deployRemoteAccess]", + "visible": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "elements": [ { - "name": "windowsVmDescriptionTextblock", + "name": "linuxVmDescriptionTextblock", "type": "Microsoft.Common.TextBlock", "options": { "text": "Provide an administrator username and password (or SSH public key) for the Linux virtual machine." @@ -924,7 +954,42 @@ ] } ], - "outputs": {} + "outputs": { + "kind": "Subscription", + "location": "[steps('basics').locationSection.location]", + "subscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", + "parameters": { + "resourcePrefix": "[steps('basics').namingSection.resourcePrefix]", + "resourceSuffix": "[steps('basics').namingSection.resourceSuffix]", + "hubSubscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", + "identitySubscriptionId": "[steps('basics').identitySection.identitySubscriptionId]", + "operationsSubscriptionId": "[steps('basics').operationsSection.operationsSubscriptionId]", + "sharedServicesSubscriptionId": "[steps('basics').sharedServicesSection.sharedServicesSubscriptionId]", + "tags": "[steps('tags').tagsByResource]", + "hubVirtualNetworkAddressPrefix": "[steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange]", + "hubSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.subnetAddressCidrRange]", + "firewallClientSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange]", + "firewallManagementSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange]", + "identityVirtualNetworkAddressPrefix": "[steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange]", + "identitySubnetAddressPrefix": "[steps('networking').identityVirtualNetwork.subnetAddressCidrRange]", + "operationsVirtualNetworkAddressPrefix": "[steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange]", + "operationsSubnetAddressPrefix": "[steps('networking').operationsVirtualNetwork.subnetAddressCidrRange]", + "sharedServicesVirtualNetworkAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange]", + "sharedServicesSubnetAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange]", + "deployPolicy": "[steps('compliance').policySection.deployPolicy]", + "policy": "[steps('compliance').policySection.policy]", + "deployASC": "[steps('compliance').securityCenterSection.deployASC]", + "emailSecurityContact": "[steps('compliance').securityCenterSection.emailSecurityContact]", + "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", + "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", + "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", + "windowsVmAdminUsername": "[steps('remoteAccess').windowsVmSection.windowsVmAdminUsername]", + "windowsVmAdminPassword": "[steps('remoteAccess').windowsVmSection.windowsVmAdminPassword]", + "linuxVmAdminUsername": "[steps('remoteAccess').linuxVmSection.linuxVmAdminUsername]", + "linuxVmAuthenticationType": "[steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType]", + "linuxVmAdminPasswordOrKey": "[if(equals(steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType, 'password'), steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.password, steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.sshPublicKey)]" + } + } } } } \ No newline at end of file From 490913d54ef00ddb9c181e25cfc625d8201e19ce Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 21:59:06 +0000 Subject: [PATCH 14/29] add the relevant subscription id to the storage account seed --- src/bicep/mlz.bicep | 18 +++++++++++++----- src/bicep/mlz.json | 20 ++++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index 9035f55a2..ecf5a60c2 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -474,7 +474,7 @@ var networkInterfaceNamingConvention = replace(namingConvention, resourceToken, var networkSecurityGroupNamingConvention = replace(namingConvention, resourceToken, 'nsg') var publicIpAddressNamingConvention = replace(namingConvention, resourceToken, 'pip') var resourceGroupNamingConvention = replace(namingConvention, resourceToken, 'rg') -var storageAccountNamingConvention = toLower('${resourcePrefix}st${nameToken}${uniqueString(resourcePrefix, resourceSuffix)}') // we use uniqueString() here to generate uniqueness +var storageAccountNamingConvention = toLower('${resourcePrefix}st${nameToken}unique_storage_token') // we replace `unique_storage_token` with a uniqueString() calculated by resourcePrefix, resourceSuffix, and the subscription ID var subnetNamingConvention = replace(namingConvention, resourceToken, 'snet') var virtualMachineNamingConvention = replace(namingConvention, resourceToken, 'vm') var virtualNetworkNamingConvention = replace(namingConvention, resourceToken, 'vnet') @@ -484,7 +484,9 @@ var virtualNetworkNamingConvention = replace(namingConvention, resourceToken, 'v var hubName = 'hub' var hubShortName = 'hub' var hubResourceGroupName = replace(resourceGroupNamingConvention, nameToken, hubName) -var hubLogStorageAccountName = take(replace(storageAccountNamingConvention, nameToken, hubShortName), 23) +var hubLogStorageAccountShortName = replace(storageAccountNamingConvention, nameToken, hubShortName) +var hubLogStorageAccountUniqueName = replace(hubLogStorageAccountShortName, 'unique_storage_token', uniqueString(resourcePrefix, resourceSuffix, hubSubscriptionId)) +var hubLogStorageAccountName = take(hubLogStorageAccountUniqueName, 23) var hubVirtualNetworkName = replace(virtualNetworkNamingConvention, nameToken, hubName) var hubNetworkSecurityGroupName = replace(networkSecurityGroupNamingConvention, nameToken, hubName) var hubSubnetName = replace(subnetNamingConvention, nameToken, hubName) @@ -494,7 +496,9 @@ var hubSubnetName = replace(subnetNamingConvention, nameToken, hubName) var identityName = 'identity' var identityShortName = 'id' var identityResourceGroupName = replace(resourceGroupNamingConvention, nameToken, identityName) -var identityLogStorageAccountName = take(replace(storageAccountNamingConvention, nameToken, identityShortName), 23) +var identityLogStorageAccountShortName = replace(storageAccountNamingConvention, nameToken, identityShortName) +var identityLogStorageAccountUniqueName = replace(identityLogStorageAccountShortName, 'unique_storage_token', uniqueString(resourcePrefix, resourceSuffix, identitySubscriptionId)) +var identityLogStorageAccountName = take(identityLogStorageAccountUniqueName, 23) var identityVirtualNetworkName = replace(virtualNetworkNamingConvention, nameToken, identityName) var identityNetworkSecurityGroupName = replace(networkSecurityGroupNamingConvention, nameToken, identityName) var identitySubnetName = replace(subnetNamingConvention, nameToken, identityName) @@ -504,7 +508,9 @@ var identitySubnetName = replace(subnetNamingConvention, nameToken, identityName var operationsName = 'operations' var operationsShortName = 'ops' var operationsResourceGroupName = replace(resourceGroupNamingConvention, nameToken, operationsName) -var operationsLogStorageAccountName = take(replace(storageAccountNamingConvention, nameToken, operationsShortName), 23) +var operationsLogStorageAccountShortName = replace(storageAccountNamingConvention, nameToken, operationsShortName) +var operationsLogStorageAccountUniqueName = replace(operationsLogStorageAccountShortName, 'unique_storage_token', uniqueString(resourcePrefix, resourceSuffix, operationsSubscriptionId)) +var operationsLogStorageAccountName = take(operationsLogStorageAccountUniqueName, 23) var operationsVirtualNetworkName = replace(virtualNetworkNamingConvention, nameToken, operationsName) var operationsNetworkSecurityGroupName = replace(networkSecurityGroupNamingConvention, nameToken, operationsName) var operationsSubnetName = replace(subnetNamingConvention, nameToken, operationsName) @@ -514,7 +520,9 @@ var operationsSubnetName = replace(subnetNamingConvention, nameToken, operations var sharedServicesName = 'sharedServices' var sharedServicesShortName = 'svcs' var sharedServicesResourceGroupName = replace(resourceGroupNamingConvention, nameToken, sharedServicesName) -var sharedServicesLogStorageAccountName = take(replace(storageAccountNamingConvention, nameToken, sharedServicesShortName), 23) +var sharedServicesLogStorageAccountShortName = replace(storageAccountNamingConvention, nameToken, sharedServicesShortName) +var sharedServicesLogStorageAccountUniqueName = replace(sharedServicesLogStorageAccountShortName, 'unique_storage_token', uniqueString(resourcePrefix, resourceSuffix, sharedServicesSubscriptionId)) +var sharedServicesLogStorageAccountName = take(sharedServicesLogStorageAccountUniqueName, 23) var sharedServicesVirtualNetworkName = replace(virtualNetworkNamingConvention, nameToken, sharedServicesName) var sharedServicesNetworkSecurityGroupName = replace(networkSecurityGroupNamingConvention, nameToken, sharedServicesName) var sharedServicesSubnetName = replace(subnetNamingConvention, nameToken, sharedServicesName) diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index f481bcb2c..b34bf6bbd 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1008.15138", - "templateHash": "15591717121098622944" + "templateHash": "14777299620783253257" } }, "parameters": { @@ -765,35 +765,43 @@ "networkSecurityGroupNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'nsg')]", "publicIpAddressNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'pip')]", "resourceGroupNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'rg')]", - "storageAccountNamingConvention": "[toLower(format('{0}st{1}{2}', parameters('resourcePrefix'), variables('nameToken'), uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'))))]", + "storageAccountNamingConvention": "[toLower(format('{0}st{1}unique_storage_token', parameters('resourcePrefix'), variables('nameToken')))]", "subnetNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'snet')]", "virtualMachineNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'vm')]", "virtualNetworkNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'vnet')]", "hubName": "hub", "hubShortName": "hub", "hubResourceGroupName": "[replace(variables('resourceGroupNamingConvention'), variables('nameToken'), variables('hubName'))]", - "hubLogStorageAccountName": "[take(replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('hubShortName')), 23)]", + "hubLogStorageAccountShortName": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('hubShortName'))]", + "hubLogStorageAccountUniqueName": "[replace(variables('hubLogStorageAccountShortName'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('hubSubscriptionId')))]", + "hubLogStorageAccountName": "[take(variables('hubLogStorageAccountUniqueName'), 23)]", "hubVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), variables('hubName'))]", "hubNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), variables('hubName'))]", "hubSubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), variables('hubName'))]", "identityName": "identity", "identityShortName": "id", "identityResourceGroupName": "[replace(variables('resourceGroupNamingConvention'), variables('nameToken'), variables('identityName'))]", - "identityLogStorageAccountName": "[take(replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('identityShortName')), 23)]", + "identityLogStorageAccountShortName": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('identityShortName'))]", + "identityLogStorageAccountUniqueName": "[replace(variables('identityLogStorageAccountShortName'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('identitySubscriptionId')))]", + "identityLogStorageAccountName": "[take(variables('identityLogStorageAccountUniqueName'), 23)]", "identityVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), variables('identityName'))]", "identityNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), variables('identityName'))]", "identitySubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), variables('identityName'))]", "operationsName": "operations", "operationsShortName": "ops", "operationsResourceGroupName": "[replace(variables('resourceGroupNamingConvention'), variables('nameToken'), variables('operationsName'))]", - "operationsLogStorageAccountName": "[take(replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('operationsShortName')), 23)]", + "operationsLogStorageAccountShortName": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('operationsShortName'))]", + "operationsLogStorageAccountUniqueName": "[replace(variables('operationsLogStorageAccountShortName'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('operationsSubscriptionId')))]", + "operationsLogStorageAccountName": "[take(variables('operationsLogStorageAccountUniqueName'), 23)]", "operationsVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), variables('operationsName'))]", "operationsNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), variables('operationsName'))]", "operationsSubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), variables('operationsName'))]", "sharedServicesName": "sharedServices", "sharedServicesShortName": "svcs", "sharedServicesResourceGroupName": "[replace(variables('resourceGroupNamingConvention'), variables('nameToken'), variables('sharedServicesName'))]", - "sharedServicesLogStorageAccountName": "[take(replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('sharedServicesShortName')), 23)]", + "sharedServicesLogStorageAccountShortName": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), variables('sharedServicesShortName'))]", + "sharedServicesLogStorageAccountUniqueName": "[replace(variables('sharedServicesLogStorageAccountShortName'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('sharedServicesSubscriptionId')))]", + "sharedServicesLogStorageAccountName": "[take(variables('sharedServicesLogStorageAccountUniqueName'), 23)]", "sharedServicesVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), variables('sharedServicesName'))]", "sharedServicesNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), variables('sharedServicesName'))]", "sharedServicesSubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), variables('sharedServicesName'))]", From 8d72aef4121bb53844fdafd9ca9f4c16bd146d82 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:02:57 +0000 Subject: [PATCH 15/29] add a temporary deploy to azure button --- src/bicep/form/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/bicep/form/README.md diff --git a/src/bicep/form/README.md b/src/bicep/form/README.md new file mode 100644 index 000000000..4df5abbad --- /dev/null +++ b/src/bicep/form/README.md @@ -0,0 +1,5 @@ +# sec/bicep/form + +A form to deploy Mission LZ: + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) \ No newline at end of file From 61bcd1348b31d6f0de1b61184ed29a043c954dbf Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:04:49 +0000 Subject: [PATCH 16/29] put the outputs in the right place --- src/bicep/form/portal.missionLandingZone.json | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index a61620220..434c3e27c 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -953,42 +953,42 @@ } ] } - ], - "outputs": { - "kind": "Subscription", - "location": "[steps('basics').locationSection.location]", - "subscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", - "parameters": { - "resourcePrefix": "[steps('basics').namingSection.resourcePrefix]", - "resourceSuffix": "[steps('basics').namingSection.resourceSuffix]", - "hubSubscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", - "identitySubscriptionId": "[steps('basics').identitySection.identitySubscriptionId]", - "operationsSubscriptionId": "[steps('basics').operationsSection.operationsSubscriptionId]", - "sharedServicesSubscriptionId": "[steps('basics').sharedServicesSection.sharedServicesSubscriptionId]", - "tags": "[steps('tags').tagsByResource]", - "hubVirtualNetworkAddressPrefix": "[steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange]", - "hubSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.subnetAddressCidrRange]", - "firewallClientSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange]", - "firewallManagementSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange]", - "identityVirtualNetworkAddressPrefix": "[steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange]", - "identitySubnetAddressPrefix": "[steps('networking').identityVirtualNetwork.subnetAddressCidrRange]", - "operationsVirtualNetworkAddressPrefix": "[steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange]", - "operationsSubnetAddressPrefix": "[steps('networking').operationsVirtualNetwork.subnetAddressCidrRange]", - "sharedServicesVirtualNetworkAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange]", - "sharedServicesSubnetAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange]", - "deployPolicy": "[steps('compliance').policySection.deployPolicy]", - "policy": "[steps('compliance').policySection.policy]", - "deployASC": "[steps('compliance').securityCenterSection.deployASC]", - "emailSecurityContact": "[steps('compliance').securityCenterSection.emailSecurityContact]", - "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", - "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", - "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", - "windowsVmAdminUsername": "[steps('remoteAccess').windowsVmSection.windowsVmAdminUsername]", - "windowsVmAdminPassword": "[steps('remoteAccess').windowsVmSection.windowsVmAdminPassword]", - "linuxVmAdminUsername": "[steps('remoteAccess').linuxVmSection.linuxVmAdminUsername]", - "linuxVmAuthenticationType": "[steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType]", - "linuxVmAdminPasswordOrKey": "[if(equals(steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType, 'password'), steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.password, steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.sshPublicKey)]" - } + ] + }, + "outputs": { + "kind": "Subscription", + "location": "[steps('basics').locationSection.location]", + "subscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", + "parameters": { + "resourcePrefix": "[steps('basics').namingSection.resourcePrefix]", + "resourceSuffix": "[steps('basics').namingSection.resourceSuffix]", + "hubSubscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", + "identitySubscriptionId": "[steps('basics').identitySection.identitySubscriptionId]", + "operationsSubscriptionId": "[steps('basics').operationsSection.operationsSubscriptionId]", + "sharedServicesSubscriptionId": "[steps('basics').sharedServicesSection.sharedServicesSubscriptionId]", + "tags": "[steps('tags').tagsByResource]", + "hubVirtualNetworkAddressPrefix": "[steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange]", + "hubSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.subnetAddressCidrRange]", + "firewallClientSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange]", + "firewallManagementSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallManagementSubnetAddressCidrRange]", + "identityVirtualNetworkAddressPrefix": "[steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange]", + "identitySubnetAddressPrefix": "[steps('networking').identityVirtualNetwork.subnetAddressCidrRange]", + "operationsVirtualNetworkAddressPrefix": "[steps('networking').operationsVirtualNetwork.virtualNetworkAddressCidrRange]", + "operationsSubnetAddressPrefix": "[steps('networking').operationsVirtualNetwork.subnetAddressCidrRange]", + "sharedServicesVirtualNetworkAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange]", + "sharedServicesSubnetAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange]", + "deployPolicy": "[steps('compliance').policySection.deployPolicy]", + "policy": "[steps('compliance').policySection.policy]", + "deployASC": "[steps('compliance').securityCenterSection.deployASC]", + "emailSecurityContact": "[steps('compliance').securityCenterSection.emailSecurityContact]", + "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", + "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", + "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", + "windowsVmAdminUsername": "[steps('remoteAccess').windowsVmSection.windowsVmAdminUsername]", + "windowsVmAdminPassword": "[steps('remoteAccess').windowsVmSection.windowsVmAdminPassword]", + "linuxVmAdminUsername": "[steps('remoteAccess').linuxVmSection.linuxVmAdminUsername]", + "linuxVmAuthenticationType": "[steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType]", + "linuxVmAdminPasswordOrKey": "[if(equals(steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType, 'password'), steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.password, steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.sshPublicKey)]" } } } From 7ca9338d8ba38ac511cebe99a60123d83a01c301 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:08:40 +0000 Subject: [PATCH 17/29] tidying up the dummy readme --- src/bicep/form/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bicep/form/README.md b/src/bicep/form/README.md index 4df5abbad..010e01374 100644 --- a/src/bicep/form/README.md +++ b/src/bicep/form/README.md @@ -1,5 +1,5 @@ -# sec/bicep/form +# src/bicep/form A form to deploy Mission LZ: -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) \ No newline at end of file +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) From 38f1932eb7dcfd359983d9e34597172f8588fd7b Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:21:25 +0000 Subject: [PATCH 18/29] remove subscriptionResourceId from outputs --- src/bicep/mlz.bicep | 6 ++---- src/bicep/mlz.json | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index ecf5a60c2..00ec4fe38 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -954,8 +954,7 @@ output firewallPrivateIPAddress string = hubNetwork.outputs.firewallPrivateIPAdd output hub object = { subscriptionId: hubSubscriptionId - resourceGroupName: hubResourceGroup.outputs.name - resourceGroupResourceId: hubResourceGroup.outputs.id + resourceGroupName: hubResourceGroupName virtualNetworkName: hubNetwork.outputs.virtualNetworkName virtualNetworkResourceId: hubNetwork.outputs.virtualNetworkResourceId subnetName: hubNetwork.outputs.subnetName @@ -972,8 +971,7 @@ output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.outputs.id output spokes array = [for (spoke, i) in spokes: { name: spoke.name subscriptionId: spoke.subscriptionId - resourceGroupName: spokeResourceGroups[i].outputs.name - resourceGroupId: spokeResourceGroups[i].outputs.id + resourceGroupName: spoke.resourceGroupName virtualNetworkName: spokeNetworks[i].outputs.virtualNetworkName virtualNetworkResourceId: spokeNetworks[i].outputs.virtualNetworkResourceId subnetName: spokeNetworks[i].outputs.subnetName diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index b34bf6bbd..bad4ddb66 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1008.15138", - "templateHash": "14777299620783253257" + "templateHash": "11646845191616819939" } }, "parameters": { @@ -6015,8 +6015,7 @@ "type": "object", "value": { "subscriptionId": "[parameters('hubSubscriptionId')]", - "resourceGroupName": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", - "resourceGroupResourceId": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", + "resourceGroupName": "[variables('hubResourceGroupName')]", "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", @@ -6041,8 +6040,7 @@ "input": { "name": "[variables('spokes')[copyIndex()].name]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", - "resourceGroupName": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", - "resourceGroupId": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", + "resourceGroupName": "[variables('spokes')[copyIndex()].resourceGroupName]", "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", From 2ead93283886b61f55e3c20dd816be48cecbed4f Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Thu, 9 Dec 2021 22:30:30 +0000 Subject: [PATCH 19/29] remove outputs entirely --- src/bicep/mlz.bicep | 50 ----------------------------------------- src/bicep/mlz.json | 54 ++------------------------------------------- 2 files changed, 2 insertions(+), 102 deletions(-) diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index 00ec4fe38..7c4353219 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -930,53 +930,3 @@ module remoteAccess './modules/remoteAccess.bicep' = if (deployRemoteAccess) { logAnalyticsWorkspaceId: logAnalyticsWorkspace.outputs.id } } - -/* - - OUTPUTS - - Here, we emit objects to be used post-deployment. - - A user can reference these outputs with the `az deployment sub show` command like this: - - az deployment sub show --name --query properties.outputs - - With that output as JSON you could pass it as arguments to another deployment using the Shared Variable File Pattern: - https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/patterns-shared-variable-file - - The output is a JSON object, you can use your favorite tool, like PowerShell or jq, to parse the values you need. - -*/ - -output mlzResourcePrefix string = resourcePrefix - -output firewallPrivateIPAddress string = hubNetwork.outputs.firewallPrivateIPAddress - -output hub object = { - subscriptionId: hubSubscriptionId - resourceGroupName: hubResourceGroupName - virtualNetworkName: hubNetwork.outputs.virtualNetworkName - virtualNetworkResourceId: hubNetwork.outputs.virtualNetworkResourceId - subnetName: hubNetwork.outputs.subnetName - subnetResourceId: hubNetwork.outputs.subnetResourceId - subnetAddressPrefix: hubNetwork.outputs.subnetAddressPrefix - networkSecurityGroupName: hubNetwork.outputs.networkSecurityGroupName - networkSecurityGroupResourceId: hubNetwork.outputs.networkSecurityGroupResourceId -} - -output logAnalyticsWorkspaceName string = logAnalyticsWorkspace.outputs.name - -output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.outputs.id - -output spokes array = [for (spoke, i) in spokes: { - name: spoke.name - subscriptionId: spoke.subscriptionId - resourceGroupName: spoke.resourceGroupName - virtualNetworkName: spokeNetworks[i].outputs.virtualNetworkName - virtualNetworkResourceId: spokeNetworks[i].outputs.virtualNetworkResourceId - subnetName: spokeNetworks[i].outputs.subnetName - subnetResourceId: spokeNetworks[i].outputs.subnetResourceId - subnetAddressPrefix: spokeNetworks[i].outputs.subnetAddressPrefix - networkSecurityGroupName: spokeNetworks[i].outputs.networkSecurityGroupName - networkSecurityGroupResourceId: spokeNetworks[i].outputs.networkSecurityGroupResourceId -}] diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index bad4ddb66..f91a08279 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1008.15138", - "templateHash": "11646845191616819939" + "templateHash": "14481563763282316594" } }, "parameters": { @@ -6001,55 +6001,5 @@ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix')))]" ] } - ], - "outputs": { - "mlzResourcePrefix": { - "type": "string", - "value": "[parameters('resourcePrefix')]" - }, - "firewallPrivateIPAddress": { - "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.firewallPrivateIPAddress.value]" - }, - "hub": { - "type": "object", - "value": { - "subscriptionId": "[parameters('hubSubscriptionId')]", - "resourceGroupName": "[variables('hubResourceGroupName')]", - "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", - "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", - "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", - "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", - "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", - "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", - "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" - } - }, - "logAnalyticsWorkspaceName": { - "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" - }, - "logAnalyticsWorkspaceResourceId": { - "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" - }, - "spokes": { - "type": "array", - "copy": { - "count": "[length(variables('spokes'))]", - "input": { - "name": "[variables('spokes')[copyIndex()].name]", - "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", - "resourceGroupName": "[variables('spokes')[copyIndex()].resourceGroupName]", - "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", - "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", - "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", - "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", - "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", - "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", - "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" - } - } - } - } + ] } \ No newline at end of file From 89137825449729375c6313e724700ac69199a6e2 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 16:54:44 +0000 Subject: [PATCH 20/29] revert mlz.bicep --- src/bicep/mlz.bicep | 52 +++++++++++++++++++++++++++++++++++++++++ src/bicep/mlz.json | 56 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index 553a2a909..b0473c3ee 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -931,3 +931,55 @@ module remoteAccess './modules/remoteAccess.bicep' = if (deployRemoteAccess) { logAnalyticsWorkspaceId: logAnalyticsWorkspace.outputs.id } } + +/* + + OUTPUTS + + Here, we emit objects to be used post-deployment. + + A user can reference these outputs with the `az deployment sub show` command like this: + + az deployment sub show --name --query properties.outputs + + With that output as JSON you could pass it as arguments to another deployment using the Shared Variable File Pattern: + https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/patterns-shared-variable-file + + The output is a JSON object, you can use your favorite tool, like PowerShell or jq, to parse the values you need. + +*/ + +output mlzResourcePrefix string = resourcePrefix + +output firewallPrivateIPAddress string = hubNetwork.outputs.firewallPrivateIPAddress + +output hub object = { + subscriptionId: hubSubscriptionId + resourceGroupName: hubResourceGroup.outputs.name + resourceGroupResourceId: hubResourceGroup.outputs.id + virtualNetworkName: hubNetwork.outputs.virtualNetworkName + virtualNetworkResourceId: hubNetwork.outputs.virtualNetworkResourceId + subnetName: hubNetwork.outputs.subnetName + subnetResourceId: hubNetwork.outputs.subnetResourceId + subnetAddressPrefix: hubNetwork.outputs.subnetAddressPrefix + networkSecurityGroupName: hubNetwork.outputs.networkSecurityGroupName + networkSecurityGroupResourceId: hubNetwork.outputs.networkSecurityGroupResourceId +} + +output logAnalyticsWorkspaceName string = logAnalyticsWorkspace.outputs.name + +output logAnalyticsWorkspaceResourceId string = logAnalyticsWorkspace.outputs.id + +output spokes array = [for (spoke, i) in spokes: { + name: spoke.name + subscriptionId: spoke.subscriptionId + resourceGroupName: spokeResourceGroups[i].outputs.name + resourceGroupId: spokeResourceGroups[i].outputs.id + virtualNetworkName: spokeNetworks[i].outputs.virtualNetworkName + virtualNetworkResourceId: spokeNetworks[i].outputs.virtualNetworkResourceId + subnetName: spokeNetworks[i].outputs.subnetName + subnetResourceId: spokeNetworks[i].outputs.subnetResourceId + subnetAddressPrefix: spokeNetworks[i].outputs.subnetAddressPrefix + networkSecurityGroupName: spokeNetworks[i].outputs.networkSecurityGroupName + networkSecurityGroupResourceId: spokeNetworks[i].outputs.networkSecurityGroupResourceId +}] diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index f91a08279..b34bf6bbd 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1008.15138", - "templateHash": "14481563763282316594" + "templateHash": "14777299620783253257" } }, "parameters": { @@ -6001,5 +6001,57 @@ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix')))]" ] } - ] + ], + "outputs": { + "mlzResourcePrefix": { + "type": "string", + "value": "[parameters('resourcePrefix')]" + }, + "firewallPrivateIPAddress": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.firewallPrivateIPAddress.value]" + }, + "hub": { + "type": "object", + "value": { + "subscriptionId": "[parameters('hubSubscriptionId')]", + "resourceGroupName": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", + "resourceGroupResourceId": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", + "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", + "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", + "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", + "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", + "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", + "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", + "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" + } + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + }, + "logAnalyticsWorkspaceResourceId": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + }, + "spokes": { + "type": "array", + "copy": { + "count": "[length(variables('spokes'))]", + "input": { + "name": "[variables('spokes')[copyIndex()].name]", + "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", + "resourceGroupName": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", + "resourceGroupId": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", + "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", + "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", + "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", + "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", + "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", + "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", + "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" + } + } + } + } } \ No newline at end of file From 23effe775d4b5a3aa2e01c9ba418ec5ff9e4b325 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 17:07:35 +0000 Subject: [PATCH 21/29] get subscription ids --- src/bicep/form/portal.missionLandingZone.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 434c3e27c..37feab0c4 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -962,11 +962,12 @@ "parameters": { "resourcePrefix": "[steps('basics').namingSection.resourcePrefix]", "resourceSuffix": "[steps('basics').namingSection.resourceSuffix]", - "hubSubscriptionId": "[steps('basics').hubSection.hubSubscriptionId]", - "identitySubscriptionId": "[steps('basics').identitySection.identitySubscriptionId]", - "operationsSubscriptionId": "[steps('basics').operationsSection.operationsSubscriptionId]", - "sharedServicesSubscriptionId": "[steps('basics').sharedServicesSection.sharedServicesSubscriptionId]", - "tags": "[steps('tags').tagsByResource]", + "hubSubscriptionId": "[replace(steps('basics').hubSection.hubSubscriptionId, '/subscriptions/', '')]", + "identitySubscriptionId": "[replace(steps('basics').identitySection.identitySubscriptionId, '/subscriptions/', '')]", + "operationsSubscriptionId": "[replace(steps('basics').operationsSection.operationsSubscriptionId, '/subscriptions/', '')]", + "sharedServicesSubscriptionId": "[replace(steps('basics').sharedServicesSection.sharedServicesSubscriptionId, '/subscriptions/', '')]", + "location": "[steps('basics').locationSection.location]", + "tags": "[if(not(contains(steps('tags').tagsByResource, 'MissionLandingZone')), parse('{}'), first(map(parse(concat('[', string(steps('tags').tagsByResource), ']')), (item) => item.MissionLandingZone)))]", "hubVirtualNetworkAddressPrefix": "[steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange]", "hubSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.subnetAddressCidrRange]", "firewallClientSubnetAddressPrefix": "[steps('networking').hubVirtualNetwork.firewallClientSubnetAddressCidrRange]", @@ -977,11 +978,11 @@ "operationsSubnetAddressPrefix": "[steps('networking').operationsVirtualNetwork.subnetAddressCidrRange]", "sharedServicesVirtualNetworkAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.virtualNetworkAddressCidrRange]", "sharedServicesSubnetAddressPrefix": "[steps('networking').sharedServicesVirtualNetwork.subnetAddressCidrRange]", + "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", "deployPolicy": "[steps('compliance').policySection.deployPolicy]", "policy": "[steps('compliance').policySection.policy]", "deployASC": "[steps('compliance').securityCenterSection.deployASC]", "emailSecurityContact": "[steps('compliance').securityCenterSection.emailSecurityContact]", - "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", "windowsVmAdminUsername": "[steps('remoteAccess').windowsVmSection.windowsVmAdminUsername]", From 505632d7073445cfc676b8d27657283e213f0838 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 17:32:27 +0000 Subject: [PATCH 22/29] windows password output --- src/bicep/form/portal.missionLandingZone.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 37feab0c4..9f38ff070 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -986,7 +986,7 @@ "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", "windowsVmAdminUsername": "[steps('remoteAccess').windowsVmSection.windowsVmAdminUsername]", - "windowsVmAdminPassword": "[steps('remoteAccess').windowsVmSection.windowsVmAdminPassword]", + "windowsVmAdminPassword": "[steps('remoteAccess').windowsVmSection.windowsVmAdminPassword.password]", "linuxVmAdminUsername": "[steps('remoteAccess').linuxVmSection.linuxVmAdminUsername]", "linuxVmAuthenticationType": "[steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType]", "linuxVmAdminPasswordOrKey": "[if(equals(steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType, 'password'), steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.password, steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.sshPublicKey)]" From 65e006da660b21c5df5bc752a63d880634796f93 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 17:41:36 +0000 Subject: [PATCH 23/29] consistent CIDR ranges --- src/bicep/form/portal.missionLandingZone.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 9f38ff070..8609c7283 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -430,8 +430,8 @@ "required": true, "validations": [ { - "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-7]))$", - "message": "Invalid CIDR range. The address prefix must be in the range [10,27]." + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-6]))$", + "message": "Invalid CIDR range. The address prefix must be in the range [10,26]." } ] } From afdc18e82e5f4919b8d768d4ea8cb2a7d9296168 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 18:07:49 +0000 Subject: [PATCH 24/29] update default bastion subnet --- src/bicep/form/portal.missionLandingZone.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/portal.missionLandingZone.json index 8609c7283..962add00c 100644 --- a/src/bicep/form/portal.missionLandingZone.json +++ b/src/bicep/form/portal.missionLandingZone.json @@ -798,7 +798,7 @@ "label": "Azure Bastion Subnet CIDR Range", "type": "Microsoft.Common.TextBox", "visible": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", - "defaultValue": "10.0.100.128/26", + "defaultValue": "10.0.100.192/26", "toolTip": "[concat('Specify a CIDR range for the Azure Bastion Host subnet within the Hub Virtual Network range: ', steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange, '. It must be of size /26 or larger.')]", "constraints": { "required": true, From 36cf740b0f95b2c79957fb40af9bb8b41b3cabf2 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 19:36:51 +0000 Subject: [PATCH 25/29] add the deploy to azure button to the root readme --- .devcontainer/devcontainer.json | 3 +- README.md | 69 ++++++++++++++++++++++++--------- src/bicep/form/README.md | 5 --- 3 files changed, 53 insertions(+), 24 deletions(-) delete mode 100644 src/bicep/form/README.md diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b5e255671..a9689b9ea 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,7 +23,8 @@ "davidanson.vscode-markdownlint", "github.vscode-pull-request-github", "timonwong.shellcheck", - "ms-azuretools.vscode-bicep" + "ms-azuretools.vscode-bicep", + "bierner.markdown-preview-github-styles" ], // Additional args to pass to the 'docker run' command diff --git a/README.md b/README.md index 17e1f8bb1..74fa9e09c 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,21 @@ # Mission LZ -Mission Landing Zone is a highly opinionated template which IT oversight organizations can use to create a cloud management system to deploy Azure environments for their teams. It addresses a narrowly scoped, specific need for an SCCA compliant hub and spoke infrastructure. +## What is Mission Landing Zone? -Mission LZ is: +Mission Landing Zone is a highly opinionated Infrastructure-as-Code (IaC) template which IT oversight organizations can use to create a cloud management system to deploy Azure environments for their teams. -- Designed for US Gov mission customers​ +It addresses a narrowly scoped, specific need for an SCCA compliant hub and spoke infrastructure. + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) + +Mission Landing Zone is: + +- Designed for US Gov mission customers - Implements [SCCA](https://docs.microsoft.com/en-us/azure/azure-government/compliance/secure-azure-computing-architecture) requirements following Microsoft's [SACA](https://aka.ms/saca) implementation guidance - Deployable in commercial, government, and air-gapped Azure clouds -- A narrow scope for a specific common need​ -- A simple solution with low configuration​ -- Written in Terraform and Bicep +- A narrow scope for a specific common need +- A simple solution with low configuration +- Written as [Bicep](./src/bicep/README.md) and [Terraform](./src/terraform/README.md) templates Mission Landing Zone is the right solution when: @@ -34,23 +40,48 @@ Our intent is to enable IT Admins to use this software to: ## Quickstart -To get up and running quickly execute the following code from Azure Cloud Shell, or from wherever you have Azure CLI installed. +You can get up and running quickly by deploying Mission Landing Zone with the Azure Portal or executing some Azure CLI commands. + +### Deploy from the Azure Portal + +1. Use this button to deploy Mission Landing Zone from the Azure Portal: + + [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) + +1. After a successful deployment, see our [examples](./src/bicep/examples/README.md) directory for how to extend the capabilities of Mission Landing Zone. + + - Extend your Mission Landing Zone deployment with the templates at [src/bicep/examples](./src/bicep/examples/README.md) + +### Deploy using Azure CLI + +Or, you can deploy Mission Landing Zone using Azure CLI. Don't have Azure CLI? Here's how to get started with Azure Cloud Shell in your browser: -```bash -git clone https://github.com/Azure/missionlz.git -az deployment sub create \ - --name myMlzDeployment \ - --location eastus \ - --template-file ./missionlz/src/bicep/mlz.bicep -``` +1. Clone the repository: + + ```plaintext + git clone https://github.com/Azure/missionlz.git + ``` + +1. Deploy Mission Landing Zone with the `az deployment sub create` command: + + ```plaintext + az deployment sub create \ + --name myMlzDeployment \ + --location eastus \ + --template-file ./missionlz/src/bicep/mlz.bicep + ``` -You'll be prompted for the one required argument `resourcePrefix` (a unique alphanumeric string 3-10 characters in length), which is used to to generate names for your resource groups and resources: +1. You'll be prompted for the one required argument `resourcePrefix` (a unique alphanumeric string without whitespaces and 3-10 characters in length), which is used to to generate names for your resource groups and resources: -```plaintext -> Please provide string value for 'resourcePrefix' (? for help): (your unique alphanumeric string 3-10 characters in length) -``` + ```plaintext + > Please provide string value for 'resourcePrefix' (? for help): (your unique alphanumeric string without whitespaces and 3-10 characters in length) + ``` + +1. After a successful deployment, see our [examples](./src/bicep/examples/README.md) directory for how to extend the capabilities of Mission Landing Zone. + + - Extend your Mission Landing Zone deployment with the templates at [src/bicep/examples](./src/bicep/examples/README.md) ## Scope @@ -73,6 +104,7 @@ Mission LZ has the following scope: Networking is set up in a hub and spoke design, separated by tiers: T0 (Identity and Authorization), T1 (Infrastructure Operations), T2 (DevSecOps and Shared Services), and multiple T3s (Workloads). Security can be configured to allow separation of duties between all tiers. Most customers will deploy each tier to a separate Azure subscription, but multiple subscriptions are not required. + Mission LZ Networking @@ -103,6 +135,7 @@ See the [Projects](https://github.com/Azure/missionlz/projects) page for the rel Here's what the repo consists of as of May 2021: + Mission LZ as of April 2021 diff --git a/src/bicep/form/README.md b/src/bicep/form/README.md deleted file mode 100644 index 010e01374..000000000 --- a/src/bicep/form/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# src/bicep/form - -A form to deploy Mission LZ: - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fglenn%2FformUi%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) From ac950df19ee6f3b741a961a2785074ef4b8fcd72 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 20:08:02 +0000 Subject: [PATCH 26/29] update docs to include deploy to azure buttons --- README.md | 13 +++++++++---- src/bicep/README.md | 9 +++++++++ ...rtal.missionLandingZone.json => mlz.portal.json} | 0 3 files changed, 18 insertions(+), 4 deletions(-) rename src/bicep/form/{portal.missionLandingZone.json => mlz.portal.json} (100%) diff --git a/README.md b/README.md index 74fa9e09c..a108e4b5b 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Mission Landing Zone is a highly opinionated Infrastructure-as-Code (IaC) templa It addresses a narrowly scoped, specific need for an SCCA compliant hub and spoke infrastructure. -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) - Mission Landing Zone is: - Designed for US Gov mission customers @@ -42,11 +40,18 @@ Our intent is to enable IT Admins to use this software to: You can get up and running quickly by deploying Mission Landing Zone with the Azure Portal or executing some Azure CLI commands. +You must have [Owner RBAC permissions](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#owner) to the subscription(s) you deploy Mission Landing Zone into. + ### Deploy from the Azure Portal -1. Use this button to deploy Mission Landing Zone from the Azure Portal: +1. Deploy Mission Landing Zone into `AzureCloud` or `AzureUsGovernment` from the Azure Portal: - [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fportal.missionLandingZone.json) + + + | Azure Commercial | Azure Government | + | :--- | :--- | + | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fmlz.portal.json) | [![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fmlz.portal.json) | + 1. After a successful deployment, see our [examples](./src/bicep/examples/README.md) directory for how to extend the capabilities of Mission Landing Zone. diff --git a/src/bicep/README.md b/src/bicep/README.md index d5dd7442f..aaa3a8eb7 100644 --- a/src/bicep/README.md +++ b/src/bicep/README.md @@ -48,6 +48,15 @@ After a deployment is complete, you can refer to the provisioned resources progr - See [Reference Deployment Output](#Reference-Deployment-Output) for steps on how to use `az deployment` subcommands and JMESPath to query for specific properties. +### Azure Portal + + + +| Azure Commercial | Azure Government | +| :--- | :--- | +| [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fmlz.portal.json) | [![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fmlz.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fform%2Fmlz.portal.json) | + + ### Azure CLI Use `az deployment sub` to deploy MLZ across 1:M subscriptions (and `az deployment sub create --help` for more information). diff --git a/src/bicep/form/portal.missionLandingZone.json b/src/bicep/form/mlz.portal.json similarity index 100% rename from src/bicep/form/portal.missionLandingZone.json rename to src/bicep/form/mlz.portal.json From dd4d96c160a579dbea78e459ef843c36e6a6635f Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 15 Dec 2021 20:17:49 +0000 Subject: [PATCH 27/29] GitHub Action: Build Bicep to JSON --- src/bicep/mlz.json | 409 +++++++++++++++++++++------------------------ 1 file changed, 186 insertions(+), 223 deletions(-) diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index b34bf6bbd..fc4d2ea7f 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "14777299620783253257" + "version": "0.4.1124.51302", + "templateHash": "13546296569054440129" } }, "parameters": { @@ -751,7 +751,6 @@ } } }, - "functions": [], "variables": { "resourceToken": "resource_token", "nameToken": "name_token", @@ -888,7 +887,7 @@ "resources": [ { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "location": "[deployment().location]", @@ -914,8 +913,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "16793551366393102966" + "version": "0.4.1124.51302", + "templateHash": "2358208423733104980" } }, "parameters": { @@ -930,7 +929,6 @@ "defaultValue": {} } }, - "functions": [], "resources": [ { "type": "Microsoft.Resources/resourceGroups", @@ -963,7 +961,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", "location": "[deployment().location]", @@ -989,8 +987,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "16793551366393102966" + "version": "0.4.1124.51302", + "templateHash": "2358208423733104980" } }, "parameters": { @@ -1005,7 +1003,6 @@ "defaultValue": {} } }, - "functions": [], "resources": [ { "type": "Microsoft.Resources/resourceGroups", @@ -1034,7 +1031,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-laws-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('operationsSubscriptionId')]", "resourceGroup": "[variables('operationsResourceGroupName')]", @@ -1072,8 +1069,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "12414775351360753156" + "version": "0.4.1124.51302", + "templateHash": "4395124562160248941" } }, "parameters": { @@ -1114,7 +1111,6 @@ } } }, - "functions": [], "variables": { "solutions": [ { @@ -1247,7 +1243,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "resourceGroup": "[variables('hubResourceGroupName')]", @@ -1270,10 +1266,10 @@ "value": "[parameters('logStorageSkuName')]" }, "logAnalyticsWorkspaceName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" }, "virtualNetworkName": { "value": "[variables('hubVirtualNetworkName')]" @@ -1390,8 +1386,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "5914406162434941149" + "version": "0.4.1124.51302", + "templateHash": "5457795790797504613" } }, "parameters": { @@ -1557,7 +1553,6 @@ ] } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/virtualNetworks/subnets", @@ -1566,10 +1561,10 @@ "properties": { "addressPrefix": "[parameters('subnetAddressPrefix')]", "networkSecurityGroup": { - "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.id.value]" + "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.id.value]" }, "routeTable": { - "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2020-06-01').outputs.id.value]" + "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2020-10-01').outputs.id.value]" }, "serviceEndpoints": "[parameters('subnetServiceEndpoints')]", "privateEndpointNetworkPolicies": "Disabled", @@ -1584,7 +1579,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "logStorage", "properties": { "expressionEvaluationOptions": { @@ -1611,8 +1606,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "779275696574787628" + "version": "0.4.1124.51302", + "templateHash": "7484285560193853939" } }, "parameters": { @@ -1630,7 +1625,6 @@ "defaultValue": {} } }, - "functions": [], "resources": [ { "type": "Microsoft.Storage/storageAccounts", @@ -1655,7 +1649,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "networkSecurityGroup", "properties": { "expressionEvaluationOptions": { @@ -1679,7 +1673,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]" @@ -1694,8 +1688,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "4497555273030729522" + "version": "0.4.1124.51302", + "templateHash": "17232318724092975283" } }, "parameters": { @@ -1725,7 +1719,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/networkSecurityGroups", @@ -1771,7 +1764,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "virtualNetwork", "properties": { "expressionEvaluationOptions": { @@ -1813,7 +1806,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('virtualNetworkDiagnosticsLogs')]" @@ -1828,8 +1821,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "12119421388421560495" + "version": "0.4.1124.51302", + "templateHash": "11413611557719242980" } }, "parameters": { @@ -1862,7 +1855,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/virtualNetworks", @@ -1917,7 +1909,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "routeTable", "properties": { "expressionEvaluationOptions": { @@ -1941,7 +1933,7 @@ "value": "[parameters('routeTableRouteAddressPrefix')]" }, "routeNextHopIpAddress": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewall'), '2020-06-01').outputs.privateIPAddress.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewall'), '2020-10-01').outputs.privateIPAddress.value]" }, "routeNextHopType": { "value": "[parameters('routeTableRouteNextHopType')]" @@ -1953,8 +1945,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "12136081248191573008" + "version": "0.4.1124.51302", + "templateHash": "2236665956144068983" } }, "parameters": { @@ -1981,7 +1973,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/routeTables", @@ -2021,7 +2012,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "firewallClientPublicIPAddress", "properties": { "expressionEvaluationOptions": { @@ -2051,7 +2042,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('publicIPAddressDiagnosticsLogs')]" @@ -2066,8 +2057,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "9624598078084769254" + "version": "0.4.1124.51302", + "templateHash": "10197745718752567420" } }, "parameters": { @@ -2103,7 +2094,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/publicIPAddresses", @@ -2149,7 +2139,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "firewallManagementPublicIPAddress", "properties": { "expressionEvaluationOptions": { @@ -2179,7 +2169,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('publicIPAddressDiagnosticsLogs')]" @@ -2194,8 +2184,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "9624598078084769254" + "version": "0.4.1124.51302", + "templateHash": "10197745718752567420" } }, "parameters": { @@ -2231,7 +2221,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/publicIPAddresses", @@ -2277,7 +2266,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "firewall", "properties": { "expressionEvaluationOptions": { @@ -2310,25 +2299,25 @@ "value": "[parameters('firewallClientIpConfigurationName')]" }, "clientIpConfigurationSubnetResourceId": { - "value": "[format('{0}/subnets/{1}', reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.id.value, parameters('firewallClientSubnetName'))]" + "value": "[format('{0}/subnets/{1}', reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.id.value, parameters('firewallClientSubnetName'))]" }, "clientIpConfigurationPublicIPAddressResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewallClientPublicIPAddress'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewallClientPublicIPAddress'), '2020-10-01').outputs.id.value]" }, "managementIpConfigurationName": { "value": "[parameters('firewallManagementIpConfigurationName')]" }, "managementIpConfigurationSubnetResourceId": { - "value": "[format('{0}/subnets/{1}', reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.id.value, parameters('firewallManagementSubnetName'))]" + "value": "[format('{0}/subnets/{1}', reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.id.value, parameters('firewallManagementSubnetName'))]" }, "managementIpConfigurationPublicIPAddressResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewallManagementPublicIPAddress'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewallManagementPublicIPAddress'), '2020-10-01').outputs.id.value]" }, "logAnalyticsWorkspaceResourceId": { "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('firewallDiagnosticsLogs')]" @@ -2343,8 +2332,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "6929052309016745644" + "version": "0.4.1124.51302", + "templateHash": "16584291901786360410" } }, "parameters": { @@ -2412,7 +2401,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/firewallPolicies", @@ -2597,7 +2585,7 @@ { "condition": "[contains(parameters('supportedClouds'), environment().name)]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "azure-monitor-private-link", "properties": { "expressionEvaluationOptions": { @@ -2615,7 +2603,7 @@ "value": "[parameters('subnetName')]" }, "privateEndpointVnetName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.name.value]" }, "tags": { "value": "[parameters('tags')]" @@ -2627,8 +2615,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "7428452441585761239" + "version": "0.4.1124.51302", + "templateHash": "6573393806892750619" } }, "parameters": { @@ -2684,7 +2672,6 @@ } } }, - "functions": [], "variables": { "privateLinkConnectionName": "[take(format('plconn{0}{1}', parameters('logAnalyticsWorkspaceName'), parameters('uniqueData')), 80)]", "privateLinkEndpointName": "[take(format('pl{0}{1}', parameters('logAnalyticsWorkspaceName'), parameters('uniqueData')), 80)]", @@ -2910,11 +2897,11 @@ "outputs": { "virtualNetworkName": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.name.value]" }, "virtualNetworkResourceId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.id.value]" }, "subnetName": { "type": "string", @@ -2930,15 +2917,15 @@ }, "networkSecurityGroupName": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.name.value]" }, "networkSecurityGroupResourceId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.id.value]" }, "firewallPrivateIPAddress": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewall'), '2020-06-01').outputs.privateIPAddress.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'firewall'), '2020-10-01').outputs.privateIPAddress.value]" } } } @@ -2953,7 +2940,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", "resourceGroup": "[variables('spokes')[copyIndex()].resourceGroupName]", @@ -2976,10 +2963,10 @@ "value": "[parameters('logStorageSkuName')]" }, "logAnalyticsWorkspaceResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" }, "firewallPrivateIPAddress": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.firewallPrivateIPAddress.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.firewallPrivateIPAddress.value]" }, "virtualNetworkName": { "value": "[variables('spokes')[copyIndex()].virtualNetworkName]" @@ -3021,8 +3008,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "17180259987553481892" + "version": "0.4.1124.51302", + "templateHash": "15135825859294163398" } }, "parameters": { @@ -3100,11 +3087,10 @@ "defaultValue": "VirtualAppliance" } }, - "functions": [], "resources": [ { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "logStorage", "properties": { "expressionEvaluationOptions": { @@ -3131,8 +3117,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "779275696574787628" + "version": "0.4.1124.51302", + "templateHash": "7484285560193853939" } }, "parameters": { @@ -3150,7 +3136,6 @@ "defaultValue": {} } }, - "functions": [], "resources": [ { "type": "Microsoft.Storage/storageAccounts", @@ -3175,7 +3160,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "networkSecurityGroup", "properties": { "expressionEvaluationOptions": { @@ -3199,7 +3184,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]" @@ -3214,8 +3199,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "4497555273030729522" + "version": "0.4.1124.51302", + "templateHash": "17232318724092975283" } }, "parameters": { @@ -3245,7 +3230,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/networkSecurityGroups", @@ -3291,7 +3275,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "routeTable", "properties": { "expressionEvaluationOptions": { @@ -3327,8 +3311,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "12136081248191573008" + "version": "0.4.1124.51302", + "templateHash": "2236665956144068983" } }, "parameters": { @@ -3355,7 +3339,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/routeTables", @@ -3392,7 +3375,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "virtualNetwork", "properties": { "expressionEvaluationOptions": { @@ -3419,10 +3402,10 @@ "properties": { "addressPrefix": "[parameters('subnetAddressPrefix')]", "networkSecurityGroup": { - "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.id.value]" + "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.id.value]" }, "routeTable": { - "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2020-06-01').outputs.id.value]" + "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2020-10-01').outputs.id.value]" }, "serviceEndpoints": "[parameters('subnetServiceEndpoints')]" } @@ -3433,7 +3416,7 @@ "value": "[parameters('logAnalyticsWorkspaceResourceId')]" }, "logStorageAccountResourceId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2020-10-01').outputs.id.value]" }, "logs": { "value": "[parameters('virtualNetworkDiagnosticsLogs')]" @@ -3448,8 +3431,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "12119421388421560495" + "version": "0.4.1124.51302", + "templateHash": "11413611557719242980" } }, "parameters": { @@ -3482,7 +3465,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/virtualNetworks", @@ -3541,31 +3523,31 @@ "outputs": { "virtualNetworkName": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.name.value]" }, "virtualNetworkResourceId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.id.value]" }, "subnetName": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.subnets.value[0].name]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.subnets.value[0].name]" }, "subnetAddressPrefix": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.subnets.value[0].properties.addressPrefix]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.subnets.value[0].properties.addressPrefix]" }, "subnetResourceId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-06-01').outputs.subnets.value[0].id]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2020-10-01').outputs.subnets.value[0].id]" }, "networkSecurityGroupName": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.name.value]" }, "networkSecurityGroupResourceId": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-06-01').outputs.id.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2020-10-01').outputs.id.value]" } } } @@ -3577,7 +3559,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-vnet-peerings-hub-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "resourceGroup": "[variables('hubResourceGroupName')]", @@ -3588,14 +3570,14 @@ "mode": "Incremental", "parameters": { "hubVirtualNetworkName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]" }, "spokes": { "copy": [ { "name": "value", "count": "[length(variables('spokes'))]", - "input": "[createObject('type', variables('spokes')[copyIndex('value')].name, 'virtualNetworkName', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex('value')].subscriptionId, variables('spokes')[copyIndex('value')].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex('value')].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value, 'virtualNetworkResourceId', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex('value')].subscriptionId, variables('spokes')[copyIndex('value')].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex('value')].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value)]" + "input": "[createObject('type', variables('spokes')[copyIndex('value')].name, 'virtualNetworkName', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex('value')].subscriptionId, variables('spokes')[copyIndex('value')].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex('value')].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value, 'virtualNetworkResourceId', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex('value')].subscriptionId, variables('spokes')[copyIndex('value')].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex('value')].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkResourceId.value)]" } ] } @@ -3606,8 +3588,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "9442892592859818002" + "version": "0.4.1124.51302", + "templateHash": "1767605230483986077" } }, "parameters": { @@ -3618,7 +3600,6 @@ "type": "array" } }, - "functions": [], "resources": [ { "copy": { @@ -3626,7 +3607,7 @@ "count": "[length(parameters('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('hub-to-{0}-vnet-peering', parameters('spokes')[copyIndex()].type)]", "properties": { "expressionEvaluationOptions": { @@ -3647,8 +3628,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "17516021996853951284" + "version": "0.4.1124.51302", + "templateHash": "16609137319418689057" } }, "parameters": { @@ -3659,7 +3640,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", @@ -3689,7 +3669,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-vnet-peerings-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", "location": "[deployment().location]", @@ -3706,13 +3686,13 @@ "value": "[variables('spokes')[copyIndex()].resourceGroupName]" }, "spokeVirtualNetworkName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]" }, "hubVirtualNetworkName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]" }, "hubVirtualNetworkResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkResourceId.value]" } }, "template": { @@ -3721,8 +3701,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "9292126827663520366" + "version": "0.4.1124.51302", + "templateHash": "11446754582894399873" } }, "parameters": { @@ -3742,11 +3722,10 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('{0}-to-hub-vnet-peering', parameters('spokeName'))]", "resourceGroup": "[parameters('spokeResourceGroupName')]", "properties": { @@ -3768,8 +3747,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "17516021996853951284" + "version": "0.4.1124.51302", + "templateHash": "16609137319418689057" } }, "parameters": { @@ -3780,7 +3759,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", @@ -3807,7 +3785,7 @@ { "condition": "[parameters('deployPolicy')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('assign-policy-hub-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "resourceGroup": "[variables('hubResourceGroupName')]", @@ -3821,10 +3799,10 @@ "value": "[parameters('policy')]" }, "logAnalyticsWorkspaceName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceResourceGroupName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.resourceGroupName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.resourceGroupName.value]" }, "operationsSubscriptionId": { "value": "[parameters('operationsSubscriptionId')]" @@ -3836,8 +3814,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "6972319702643019380" + "version": "0.4.1124.51302", + "templateHash": "11502515675173143648" } }, "parameters": { @@ -3870,7 +3848,6 @@ } } }, - "functions": [], "variables": { "modifiedAssignment": "[if(and(equals(toLower(environment().name), toLower('AzureCloud')), equals(toLower(parameters('builtInAssignment')), toLower('IL5'))), 'NIST', parameters('builtInAssignment'))]", "assignmentName": "[format('{0} {1}', variables('modifiedAssignment'), resourceGroup().name)]", @@ -3981,7 +3958,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('Assign-Laws-Role-Policy-{0}', resourceGroup().name)]", "subscriptionId": "[parameters('operationsSubscriptionId')]", "resourceGroup": "[parameters('logAnalyticsWorkspaceResourceGroupName')]", @@ -4007,8 +3984,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "8888166109063371770" + "version": "0.4.1124.51302", + "templateHash": "17084517484392773483" } }, "parameters": { @@ -4036,7 +4013,6 @@ "defaultValue": "" } }, - "functions": [], "resources": [ { "type": "Microsoft.Authorization/roleAssignments", @@ -4070,7 +4046,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('assign-policy-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", "resourceGroup": "[variables('spokes')[copyIndex()].resourceGroupName]", @@ -4084,10 +4060,10 @@ "value": "[parameters('policy')]" }, "logAnalyticsWorkspaceName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceResourceGroupName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.resourceGroupName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.resourceGroupName.value]" }, "operationsSubscriptionId": { "value": "[parameters('operationsSubscriptionId')]" @@ -4099,8 +4075,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "6972319702643019380" + "version": "0.4.1124.51302", + "templateHash": "11502515675173143648" } }, "parameters": { @@ -4133,7 +4109,6 @@ } } }, - "functions": [], "variables": { "modifiedAssignment": "[if(and(equals(toLower(environment().name), toLower('AzureCloud')), equals(toLower(parameters('builtInAssignment')), toLower('IL5'))), 'NIST', parameters('builtInAssignment'))]", "assignmentName": "[format('{0} {1}', variables('modifiedAssignment'), resourceGroup().name)]", @@ -4244,7 +4219,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('Assign-Laws-Role-Policy-{0}', resourceGroup().name)]", "subscriptionId": "[parameters('operationsSubscriptionId')]", "resourceGroup": "[parameters('logAnalyticsWorkspaceResourceGroupName')]", @@ -4270,8 +4245,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "8888166109063371770" + "version": "0.4.1124.51302", + "templateHash": "17084517484392773483" } }, "parameters": { @@ -4299,7 +4274,6 @@ "defaultValue": "" } }, - "functions": [], "resources": [ { "type": "Microsoft.Authorization/roleAssignments", @@ -4328,7 +4302,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('activity-logs-hub-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "location": "[deployment().location]", @@ -4339,10 +4313,10 @@ "mode": "Incremental", "parameters": { "diagnosticSettingName": { - "value": "[format('log-hub-sub-activity-to-{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value)]" + "value": "[format('log-hub-sub-activity-to-{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value)]" }, "logAnalyticsWorkspaceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" } }, "template": { @@ -4351,8 +4325,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "14308840348818246166" + "version": "0.4.1124.51302", + "templateHash": "16846284475547410965" } }, "parameters": { @@ -4370,7 +4344,6 @@ ] } }, - "functions": [], "resources": [ { "condition": "[contains(parameters('supportedClouds'), environment().name)]", @@ -4430,7 +4403,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('activity-logs-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", "location": "[deployment().location]", @@ -4441,10 +4414,10 @@ "mode": "Incremental", "parameters": { "diagnosticSettingName": { - "value": "[format('log-{0}-sub-activity-to-{1}', variables('spokes')[copyIndex()].name, reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value)]" + "value": "[format('log-{0}-sub-activity-to-{1}', variables('spokes')[copyIndex()].name, reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value)]" }, "logAnalyticsWorkspaceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" } }, "template": { @@ -4453,8 +4426,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "14308840348818246166" + "version": "0.4.1124.51302", + "templateHash": "16846284475547410965" } }, "parameters": { @@ -4472,7 +4445,6 @@ ] } }, - "functions": [], "resources": [ { "condition": "[contains(parameters('supportedClouds'), environment().name)]", @@ -4527,7 +4499,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-diagnostic-logging-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('operationsSubscriptionId')]", "resourceGroup": "[variables('operationsResourceGroupName')]", @@ -4541,7 +4513,7 @@ "value": "[variables('operationsLogStorageAccountName')]" }, "logAnalyticsWorkspaceName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]" } }, "template": { @@ -4550,8 +4522,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "11315996337583372529" + "version": "0.4.1124.51302", + "templateHash": "14543561787523322977" } }, "parameters": { @@ -4569,7 +4541,6 @@ ] } }, - "functions": [], "resources": [ { "condition": "[contains(parameters('supportedClouds'), environment().name)]", @@ -4606,7 +4577,7 @@ { "condition": "[parameters('deployASC')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('set-hub-sub-security-center-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "location": "[deployment().location]", @@ -4617,7 +4588,7 @@ "mode": "Incremental", "parameters": { "logAnalyticsWorkspaceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" }, "emailSecurityContact": { "value": "[parameters('emailSecurityContact')]" @@ -4629,8 +4600,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "5100455574031231618" + "version": "0.4.1124.51302", + "templateHash": "5910850021434301527" } }, "parameters": { @@ -4661,7 +4632,6 @@ } } }, - "functions": [], "variables": { "bundle": "[if(not(equals(environment().name, 'AzureUSGovernment')), createArray('KeyVaults', 'SqlServers', 'VirtualMachines', 'StorageAccounts', 'ContainerRegistry', 'KubernetesService', 'SqlServerVirtualMachines', 'AppServices', 'Dns', 'Arm'), createArray('SqlServers', 'VirtualMachines', 'StorageAccounts', 'ContainerRegistry', 'KubernetesService', 'Dns', 'Arm'))]", "autoProvisioning": "[if(parameters('enableAutoProvisioning'), 'On', 'Off')]", @@ -4751,7 +4721,7 @@ "count": "[length(variables('spokes'))]" }, "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('set-{0}-sub-security-center', variables('spokes')[copyIndex()].name)]", "subscriptionId": "[parameters('operationsSubscriptionId')]", "location": "[deployment().location]", @@ -4762,7 +4732,7 @@ "mode": "Incremental", "parameters": { "logAnalyticsWorkspaceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" }, "emailSecurityContact": { "value": "[parameters('emailSecurityContact')]" @@ -4774,8 +4744,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "5100455574031231618" + "version": "0.4.1124.51302", + "templateHash": "5910850021434301527" } }, "parameters": { @@ -4806,7 +4776,6 @@ } } }, - "functions": [], "variables": { "bundle": "[if(not(equals(environment().name, 'AzureUSGovernment')), createArray('KeyVaults', 'SqlServers', 'VirtualMachines', 'StorageAccounts', 'ContainerRegistry', 'KubernetesService', 'SqlServerVirtualMachines', 'AppServices', 'Dns', 'Arm'), createArray('SqlServers', 'VirtualMachines', 'StorageAccounts', 'ContainerRegistry', 'KubernetesService', 'Dns', 'Arm'))]", "autoProvisioning": "[if(parameters('enableAutoProvisioning'), 'On', 'Off')]", @@ -4892,7 +4861,7 @@ { "condition": "[parameters('deployRemoteAccess')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "[format('deploy-remote-access-{0}', parameters('deploymentNameSuffix'))]", "subscriptionId": "[parameters('hubSubscriptionId')]", "resourceGroup": "[variables('hubResourceGroupName')]", @@ -4906,13 +4875,13 @@ "value": "[parameters('location')]" }, "hubVirtualNetworkName": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]" }, "hubSubnetResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetResourceId.value]" }, "hubNetworkSecurityGroupResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.networkSecurityGroupResourceId.value]" }, "bastionHostName": { "value": "[variables('bastionHostName')]" @@ -5017,7 +4986,7 @@ "value": "[parameters('windowsVmStorageAccountType')]" }, "logAnalyticsWorkspaceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" } }, "template": { @@ -5026,8 +4995,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "7553476343724456136" + "version": "0.4.1124.51302", + "templateHash": "5493952578857184506" } }, "parameters": { @@ -5159,11 +5128,10 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "remoteAccess-bastionHost", "properties": { "expressionEvaluationOptions": { @@ -5208,8 +5176,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "8312671392588769494" + "version": "0.4.1124.51302", + "templateHash": "2380768471469099549" } }, "parameters": { @@ -5245,7 +5213,6 @@ "type": "string" } }, - "functions": [], "variables": { "subnetName": "AzureBastionSubnet" }, @@ -5304,7 +5271,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "remoteAccess-linuxNetworkInterface", "properties": { "expressionEvaluationOptions": { @@ -5340,8 +5307,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "15767041695622422511" + "version": "0.4.1124.51302", + "templateHash": "8101744643505090252" } }, "parameters": { @@ -5368,7 +5335,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/networkInterfaces", @@ -5409,7 +5375,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "remoteAccess-linuxVirtualMachine", "properties": { "expressionEvaluationOptions": { @@ -5457,7 +5423,7 @@ "value": "[parameters('linuxVmAdminPasswordOrKey')]" }, "networkInterfaceName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'remoteAccess-linuxNetworkInterface'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'remoteAccess-linuxNetworkInterface'), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceId": { "value": "[parameters('logAnalyticsWorkspaceId')]" @@ -5469,8 +5435,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "9165533268589955383" + "version": "0.4.1124.51302", + "templateHash": "6195638442308081265" } }, "parameters": { @@ -5526,7 +5492,6 @@ "type": "string" } }, - "functions": [], "variables": { "linuxConfiguration": { "disablePasswordAuthentication": true, @@ -5668,7 +5633,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "remoteAccess-windowsNetworkInterface", "properties": { "expressionEvaluationOptions": { @@ -5704,8 +5669,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "15767041695622422511" + "version": "0.4.1124.51302", + "templateHash": "8101744643505090252" } }, "parameters": { @@ -5732,7 +5697,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Network/networkInterfaces", @@ -5773,7 +5737,7 @@ }, { "type": "Microsoft.Resources/deployments", - "apiVersion": "2020-06-01", + "apiVersion": "2020-10-01", "name": "remoteAccess-windowsVirtualMachine", "properties": { "expressionEvaluationOptions": { @@ -5818,7 +5782,7 @@ "value": "[parameters('windowsVmStorageAccountType')]" }, "networkInterfaceName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', 'remoteAccess-windowsNetworkInterface'), '2020-06-01').outputs.name.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'remoteAccess-windowsNetworkInterface'), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceId": { "value": "[parameters('logAnalyticsWorkspaceId')]" @@ -5830,8 +5794,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.4.1008.15138", - "templateHash": "5398822015781472627" + "version": "0.4.1124.51302", + "templateHash": "10579512088546693511" } }, "parameters": { @@ -5880,7 +5844,6 @@ "type": "string" } }, - "functions": [], "resources": [ { "type": "Microsoft.Compute/virtualMachines", @@ -6009,30 +5972,30 @@ }, "firewallPrivateIPAddress": { "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.firewallPrivateIPAddress.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.firewallPrivateIPAddress.value]" }, "hub": { "type": "object", "value": { "subscriptionId": "[parameters('hubSubscriptionId')]", - "resourceGroupName": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", - "resourceGroupResourceId": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", - "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", - "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", - "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", - "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", - "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", - "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", - "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" + "resourceGroupName": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]", + "resourceGroupResourceId": "[reference(subscriptionResourceId(parameters('hubSubscriptionId'), 'Microsoft.Resources/deployments', format('deploy-rg-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]", + "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]", + "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkResourceId.value]", + "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetName.value]", + "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetResourceId.value]", + "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetAddressPrefix.value]", + "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.networkSecurityGroupName.value]", + "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.networkSecurityGroupResourceId.value]" } }, "logAnalyticsWorkspaceName": { "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]" }, "logAnalyticsWorkspaceResourceId": { "type": "string", - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), variables('operationsResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-laws-{0}', parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]" }, "spokes": { "type": "array", @@ -6041,15 +6004,15 @@ "input": { "name": "[variables('spokes')[copyIndex()].name]", "subscriptionId": "[variables('spokes')[copyIndex()].subscriptionId]", - "resourceGroupName": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.name.value]", - "resourceGroupId": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.id.value]", - "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkName.value]", - "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.virtualNetworkResourceId.value]", - "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetName.value]", - "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetResourceId.value]", - "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.subnetAddressPrefix.value]", - "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupName.value]", - "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-06-01').outputs.networkSecurityGroupResourceId.value]" + "resourceGroupName": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.name.value]", + "resourceGroupId": "[reference(subscriptionResourceId(variables('spokes')[copyIndex()].subscriptionId, 'Microsoft.Resources/deployments', format('deploy-rg-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.id.value]", + "virtualNetworkName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkName.value]", + "virtualNetworkResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.virtualNetworkResourceId.value]", + "subnetName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetName.value]", + "subnetResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetResourceId.value]", + "subnetAddressPrefix": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.subnetAddressPrefix.value]", + "networkSecurityGroupName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.networkSecurityGroupName.value]", + "networkSecurityGroupResourceId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[copyIndex()].subscriptionId, variables('spokes')[copyIndex()].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[copyIndex()].name, parameters('deploymentNameSuffix'))), '2020-10-01').outputs.networkSecurityGroupResourceId.value]" } } } From a59bafd8e79ace3fe7113e0693c2fa0f8c5e1847 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 21:17:21 +0000 Subject: [PATCH 28/29] use dev test prod as suffix --- src/bicep/form/mlz.portal.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bicep/form/mlz.portal.json b/src/bicep/form/mlz.portal.json index 962add00c..86145b7b4 100644 --- a/src/bicep/form/mlz.portal.json +++ b/src/bicep/form/mlz.portal.json @@ -234,7 +234,7 @@ "name": "resourceSuffix", "label": "Resource Naming Suffix", "type": "Microsoft.Common.DropDown", - "defaultValue": "Development", + "defaultValue": "dev", "toolTip": "Select a resource naming suffix to append to all resources.", "multiselect": false, "selectAll": false, @@ -244,18 +244,18 @@ "constraints": { "allowedValues": [ { - "label": "Development", - "description": "Select if you want to deploy a development environment.", + "label": "dev", + "description": "Select if you want to append 'dev' to your resources.", "value": "dev" }, { - "label": "Test", - "description": "Select if you want to deploy a test environment.", + "label": "test", + "description": "Select if you want to append 'test' to your resources.", "value": "test" }, { - "label": "Production", - "description": "Select if you want to deploy a production environment.", + "label": "prod", + "description": "Select if you want to append 'prod' to your resources.", "value": "prod" } ], From 33a8c9890e7d37c398b2126da86cb495cb1c7211 Mon Sep 17 00:00:00 2001 From: Glenn Musa <4622125+glennmusa@users.noreply.github.com> Date: Wed, 15 Dec 2021 21:25:31 +0000 Subject: [PATCH 29/29] fix markdown lint error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a108e4b5b..45f0827cc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## What is Mission Landing Zone? -Mission Landing Zone is a highly opinionated Infrastructure-as-Code (IaC) template which IT oversight organizations can use to create a cloud management system to deploy Azure environments for their teams. +Mission Landing Zone is a highly opinionated Infrastructure-as-Code (IaC) template which IT oversight organizations can use to create a cloud management system to deploy Azure environments for their teams. It addresses a narrowly scoped, specific need for an SCCA compliant hub and spoke infrastructure.