This commit is contained in:
Kristian Nese 2021-02-02 21:09:52 +01:00 коммит произвёл GitHub
Родитель 8927941e42
Коммит 6c6f51902c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 537 добавлений и 5 удалений

Просмотреть файл

@ -29,9 +29,11 @@ Business units and/or application portfolio owners can use their preferred tool
The following deployment experiences can be leveraged to create multiple landing zones (subscriptions) and target individual management groups (e.g., 'online', 'corp' etc.).
To deploy the ARM templates below to create new subscriptions, you must have Management Group Contributor or Owner permission on the Management Group where you will invoke the deployment and the targeted Management Groups for the new subscriptions.
To deploy the ARM templates below to create new subscriptions, you must have Management Group Contributor or Owner permission on the Management Group where you will invoke the deployment and the targeted Management Groups for the new subscriptions, as well as subscription write permissions on the billing account.
| Agreement types | ARM Template | Description
|:-------------------------|:-------------|:--------------|
| Enterprise Agreement (EA) |[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fdocs%2Freference%2Flzs%2FarmTemplates%2Feslz.json/createUIDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fdocs%2Freference%2Flzs%2FarmTemplates%2Fportal-eslz.json) | Create N subscriptions into multiple management groups
| Enterprise Agreement (EA) |[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fexamples%2Flanding-zones%2Fsubscription-with-rbac%2FFsubscriptionWithRbac.json/createUIDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fexamples%2Flanding-zones%2Fsubscription-with-rbac%2Fportal-subscriptionWithRbac.json)| Create subscription with RBAC for SPN
| Agreement types | ARM Template |
|:-------------------------|:-------------|
| Enterprise Agreement (EA) |[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fdocs%2Freference%2Flzs%2FarmTemplates%2Feslz.json/createUIDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fdocs%2Freference%2Flzs%2FarmTemplates%2Fportal-eslz.json)
| Microsoft Customer Agreement | Coming soon

Просмотреть файл

@ -0,0 +1,94 @@
# Create new subscription and grant an SPN access via RBAC
The ARM template provided in this folder can be used to create new subscription into corp, online, or sanboxes management group, and optionally create a new - or use existing Service Principal that will be gratned access to the subscription
## Parameters
- "subscriptionAliasName": It is recommended that the subscription alias name is the same as the displayName to ensure easier manageability
- "billingAccountId": Provide the full resourceId for the enrollmentAccount. E.g., "/providers/Microsoft.Billing/billingAccounts/{billingAccountName}/enrollmentAccounts/{enrollmentAccountName}"
- "targetManagementGroup": Provide the last segment of the management group resourceId for the target management group in order to place the subscription directly under a management group. E.g., "/providers/Microsoft.Management/managementGroups/{mgmtGroupId}" where "mgmtGroupId" is the expected input.
````json
"parameters": {
"enterpriseScaleCompanyPrefix": {
"type": "string",
"maxLength": 5,
"metadata": {
"description": "Provide the ESLZ company prefix, 5 characters max."
}
},
"subscriptionAliasName": {
"type": "string",
"metadata": {
"description": "Provide alias (and displayName) for the subscription"
}
},
"targetManagementGroup": {
"type": "string",
"metadata": {
"details": "Select targeted management group that the subscription will land into"
}
},
"billingAccountId": {
"type": "string",
"metadata": {
"description": "Provide the resourceId for the enrollment account or MCA"
}
},
"principalId": {
"type": "array",
"metadata": {
"description": "Provide principalId for the user/group/service principal that should be granted access"
}
},
````
## Scope escape
This ARM template is using the "scope escape" property on the resource in order to create a tenant level resource (subscription aliases) while being invoked as a management group deployment
````json
{
"scope": "/", // routing the request to tenant root
"name": "[parameters('subscriptionAliasName')]",
"type": "Microsoft.Subscription/aliases",
"apiVersion": "2020-09-01",
"properties": {
"workLoad": "Production",
"displayName": "[parameters('subscriptionAliasName')]",
"billingScope": "[parameters('billingAccountId')]"
}
}
````
## Deploy via Azure Portal
| Agreement types | ARM Template | Description |
|:-------------------------|:-------------|:---------------|
| Enterprise Agreement (EA) |[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fexamples%2Flanding-zones%2Fsubscription-with-rbac%2FFsubscriptionWithRbac.json/createUIDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FEnterprise-Scale%2Fmain%2Fexamples%2Flanding-zones%2Fsubscription-with-rbac%2Fportal-subscriptionWithRbac.json)| Create subscription with RBAC for SPN
| Microsoft Customer Agreement | Coming soon
## Deploy using AzOps
See these [instructions](../../../docs/Deploy/enable-subscription-creation.md) for how to use this template with the AzOps GitHub Actions/DevOps pipeline.
## Deploy using Azure PowerShell
````pwsh
New-AzManagementGroupDeployment `
-Name <name> `
-Location -<location> `
-ManagementGroupId <mgmtGroupId> `
-TemplateUri "https://raw.githubusercontent.com/Azure/Enterprise-Scale/main/examples/landing-zones/subscription-with-rbac/subscriptionWithRbac.json"
````
## Deploy using Azure CLI
````cli
az deployment mg create \
--name <name> \
--location <location> \
--management-group-id <mgmtGroupId> \
--template-uri "https://raw.githubusercontent.com/Azure/Enterprise-Scale/main/examples/landing-zones/subscription-with-rbac/subscriptionWithRbac.json"

Просмотреть файл

@ -0,0 +1,201 @@
{
"handler": "Microsoft.Azure.CreateUIDef",
"version": "0.1.2-preview",
"parameters": {
"basics": [
{}
],
"steps": [
{
"name": "lzSettings",
"label": "Billing and Enrolment account",
"bladeTitle": "Company prefix",
"elements": [
{
"name": "textBlock0",
"type": "Microsoft.Common.TextBlock",
"visible": true,
"options": {
"text": "Provide the Enterprise-Scale prefix for your management group and select the billing account and enrollment account you want to use for subscription provisioning.",
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/enterprise-enrollment-and-azure-ad-tenants"
}
}
},
{
"name": "esPrefix",
"type": "Microsoft.Common.TextBox",
"label": "Enterprise-Scale company prefix",
"placeholder": "ESLZ",
"defaultValue": "",
"toolTip": "Use only allowed characters",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,5}$",
"validationMessage": "The prefix must be 1-5 characters."
},
"visible": true
},
{
"name": "mgApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "providers/Microsoft.Management/managementGroups?api-version=2020-02-01"
}
},
{
"name": "esBillingApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "providers/Microsoft.Billing/billingAccounts?api-version=2020-05-01"
}
},
{
"name": "esBillingAccount",
"type": "Microsoft.Common.DropDown",
"label": "Billing Account",
"toolTip": "",
"multiselect": false,
"selectAll": true,
"filter": true,
"filterPlaceholder": "Filter items ...",
"multiLine": true,
"visible": true,
"constraints": {
"allowedValues": "[map(steps('lzSettings').esBillingApi.value, (billing) => parse(concat('{\"label\":\"', billing.properties.displayName, '\",\"description\":\"', billing.id, '\",\"value\":\"', toLower(billing.id), '\"}')) )]",
"required": true
}
},
{
"name": "esEaApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "[concat(steps('lzSettings').esBillingAccount, '/enrollmentAccounts/', '?api-version=2019-10-01-preview')]"
}
},
{
"name": "esEa",
"type": "Microsoft.Common.DropDown",
"label": "Enrollment Account",
"toolTip": "",
"multiselect": false,
"selectAll": true,
"filter": true,
"filterPlaceholder": "Filter items ...",
"multiLine": true,
"visible": true,
"constraints": {
"allowedValues": "[map(steps('lzSettings').esEaApi.value, (ea) => parse(concat('{\"label\":\"', ea.properties.displayName, '\",\"description\":\"', ea.id, '\",\"value\":\"', toLower(ea.id), '\"}')) )]",
"required": true
}
}
]
},
{
"name": "lzTarget",
"label": "ESLZ Landing Zone kiosk",
"bladeTitle": "Company prefix",
"elements": [
{
"name": "mgApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "GET",
"path": "providers/Microsoft.Management/managementGroups?api-version=2020-02-01"
}
},
{
"name": "lzType",
"type": "Microsoft.Common.OptionsGroup",
"label": "Select landing zone type",
"defaultValue": "",
"toolTip": "",
"constraints": {
"allowedValues": [
{
"label": "Corp",
"value": "corp"
},
{
"label": "Online",
"value": "Online"
},
{
"label": "Sandbox",
"value": "sandboxes"
}
],
"required": true
},
"visible": true
},
{
"name": "esSubAliasName",
"type": "Microsoft.Common.TextBox",
"label": "Provide prefix for your landing zone",
"placeholder": "",
"defaultValue": "",
"toolTip": "Use only allowed characters",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,10}$",
"validationMessage": "Only alphanumeric characters are allowed, and the value must be 1-10 characters long."
},
"visible": true
},
{
"name": "spnBlock",
"type": "Microsoft.Common.TextBlock",
"visible": true,
"options": {
"text": "You can optionally create a new - or use an existing Service Principal that will be granted access to the newly created landing zone to be use in context DevOps pipelines and GitHub actions for IaC for your workload deployments.",
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-with-an-existing-service-principal"
}
}
},
{
"name": "lzServicePrincipal",
"type": "Microsoft.Common.ServicePrincipalSelector",
"label": {
"password": "Password",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type",
"sectionHeader": "Service Principal"
},
"toolTip": {
"password": "Password",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type"
},
"defaultValue": {
"principalId": "<default guid>",
"name": "(New) default App Id"
},
"constraints": {
"required": true,
"regex": "^[a-zA-Z0-9]{8,}$",
"validationMessage": "Password must be at least 8 characters long, contain only numbers and letters"
},
"options": {
"hideCertificate": true
},
"visible": true
}
]
}
],
"outputs": {
"enterpriseScaleCompanyPrefix": "[steps('lzSettings').esPrefix]",
"subscriptionAliasName": "[steps('lzTarget').esSubAliasName]",
"billingAccountId": "[steps('lzSettings').esEa]",
"targetManagementGroup": "[steps('lzTarget').lzType]",
"principalId": "[steps('lzTarget').lzServicePrincipal.objectId]"
}
}
}

Просмотреть файл

@ -0,0 +1,235 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"enterpriseScaleCompanyPrefix": {
"type": "string",
"maxLength": 5,
"metadata": {
"description": "Provide the ESLZ company prefix, 5 characters max."
}
},
"subscriptionAliasName": {
"type": "string",
"metadata": {
"description": "Provide alias (and displayName) for the subscription"
}
},
"targetManagementGroup": {
"type": "string",
"metadata": {
"details": "Select targeted management group that the subscription will land into"
}
},
"billingAccountId": {
"type": "string",
"metadata": {
"description": "Provide the resourceId for the enrollment account or MCA"
}
},
"principalId": {
"type": "array",
"metadata": {
"description": "Provide principalId for the user/group/service principal that should be granted access"
}
}
},
"variables": {
"targetManagementGroup": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-', parameters('targetManagementGroup'))]"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "[concat('create-', parameters('subscriptionAliasName'))]",
"scope": "[concat('Microsoft.Management/managementGroups/', variables('targetManagementGroup'))]",
"location": "[deployment().location]",
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"parameters": {
// Sharing parameter values from outer to inner execution scope
"subAliasName": {
"value": "[parameters('subscriptionAliasName')]"
},
"billingId": {
"value": "[parameters('billingAccountId')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// parameters for inner scope
"subAliasName": {
"type": "string"
},
"billingId": {
"type": "string"
}
},
"resources": [
{
"scope": "/", // routing the request to tenant root
"name": "[parameters('subAliasName')]",
"type": "Microsoft.Subscription/aliases",
"apiVersion": "2020-09-01",
"properties": {
"workLoad": "Production",
"displayName": "[parameters('subAliasName')]",
"billingScope": "[parameters('billingId')]"
}
}
],
"outputs": {
// Referencing the guid generated for the subscription to be used in subsequent (optional) deployments to this subscription
"subscriptionId": {
"type": "string",
"value": "[reference(parameters('subAliasName')).subscriptionId]"
}
}
}
}
},
{
// Creating deployment to place the new/existing subscription into the management group
"scope": "[concat('Microsoft.Management/managementGroups/', variables('targetManagementGroup'))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-08-01",
"name": "[concat('mg-', parameters('subscriptionAliasName'))]",
"location": "[deployment().location]",
"dependsOn": [
"[concat('Microsoft.Resources/deployments/', 'create-', parameters('subscriptionAliasName'))]"
],
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"parameters": {
// Value coming from the previous deployment's output inner scope to be used to target subscription deployments
"targetSubscriptionId": {
"value": "[reference(concat('create-', parameters('subscriptionAliasName'))).outputs.subscriptionId.value]"
},
"mgmtGroupId": {
"value": "[variables('targetManagementGroup')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// parameters for inner scope
"targetSubscriptionId": {
"type": "string"
},
"mgmtGroupId": {
"type": "string"
}
},
"resources": [
{
// Place subscription into the management group
"scope": "/",
"type": "Microsoft.Management/managementGroups/subscriptions",
"apiVersion": "2020-10-01",
"name": "[concat(parameters('mgmtGroupId'), '/', parameters('targetSubscriptionId'))]",
"location": "[deployment().location]",
"properties": {}
}
]
}
}
},
{
// Creating deployment to invoke policyAssignment of newly created subscription
"scope": "[concat('Microsoft.Management/managementGroups/', variables('targetManagementGroup'))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-08-01",
"name": "[concat('rbac-', parameters('subscriptionAliasName'))]",
"location": "[deployment().location]",
"dependsOn": [
"[concat('Microsoft.Resources/deployments/', 'create-', parameters('subscriptionAliasName'))]"
],
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"parameters": {
// Value coming from the previous deployment's output inner scope to be used to target subscription deployments
"targetSubscriptionId": {
"value": "[reference(concat('create-', parameters('subscriptionAliasName'))).outputs.subscriptionId.value]"
},
"principalIdInner": {
"value": "[array(parameters('principalId'))]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// parameters for inner scope
"targetSubscriptionId": {
"type": "string"
},
"principalIdInner": {
"type": "array"
}
},
"resources": [
{
// subscription scoped deployment to make policy assignment
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-08-01",
"name": "subscription-dep",
"location": "[deployment().location]",
"subscriptionId": "[parameters('targetSubscriptionId')]",
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"parameters": {
"principalIdInputInner": {
"value": "[parameters('principalIdInner')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// parameters for inner scope
"principalIdInputInner": {
"type": "array"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2019-04-01-preview",
"name": "[guid(subscription().subscriptionId)]",
"properties": {
"roleDefinitionId": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
"principalId": "[replace(replace(replace(string(parameters('principalIdInputInner')), '\"', ''), '[', ''), ']', '')]"
}
}
]
}
}
}
]
}
}
}
],
"outputs": {
"subscriptionIdOuter": {
"type": "string",
"value": "[reference(concat('create-', parameters('subscriptionAliasName'))).outputs.subscriptionId.value]"
}
}
}