PR for Portal RI DevOps removal (USER STORY 25574) (#1310)

Co-authored-by: Jack Tracey <41163455+jtracey93@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Panagiotis Korologos 2023-05-09 18:25:35 +03:00 коммит произвёл GitHub
Родитель 09aea43243
Коммит 3c50bc3f9b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 9 добавлений и 988 удалений

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

@ -1,288 +1,11 @@
## Azure landing zone portal deployment for Platform DevOps and Automation
### In this section:
### Important Notice:
- [Enable deployment of Landing Zones with Infrastructure as Code using Github and Github Actions](#reference-implementation-deployment)
- [Validation post deployment (GitHub)](#validation-post-deployment-github)
- [Operating the Azure platform using AzOps (Infrastructure as Code with GitHub Actions)](#operating-the-azure-platform-using-azops-infrastructure-as-code-with-github-actions)
As of May 2023, the Azure Portal experience (accelerator) of the ALZ Reference Implementation (RI), will not include the "Platform DevOps and automation" section anymore.
---
Consequently, users interested in Platform DevOps and Automation, are encouraged to use either the respective ALZ Bicep Modules (https://github.com/Azure/ALZ-Bicep), or the ALZ Terraform Module (https://github.com/Azure/terraform-azurerm-caf-enterprise-scale).
### Enable deployment of Landing Zones with Infrastructure as Code using Github and Github Actions
> [AzOps](https://github.com/Azure/AzOps) can still be used, if desired, but please see the [AzOps](https://github.com/Azure/AzOps) repo for setup and configuration instructions as well as any support requirements via the repos issues.
You can choose to bootstrap your CI/CD pipeline (GitHub with GitHub actions). Provide your GitHub user/org name, the preferred name of the GitHub repository that is to be created, as well as the PA token that the deployment will use to create a new repository and discover the Enterprise-Scale deployment ARM templates and merge them into your main branch.
![Graphical user interface, text, application Description automatically generated](./media/clip_image015.png)
1.1.1 To create a PA token, follow the instructions here: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token
1.1.2 Ensure the PA token has the following permissions:
![Graphical user interface, text, application Description automatically generated](./media/github_developer_createPAT.png)
> For Microsoft employees who are enrolled into the Azure GitHub organization, you must also authorize the PA token to this Org!
![Graphical user interface, text, application, email Description automatically generated](./media/github_developer_enablesso.png)
![Graphical user interface, text, application, email Description automatically generated](./media/github_developer_disablesso.png)
1.2 Lastly, a Service Principal is required for Git to authenticate to – and be authorized to your Azure tenant. You can either use an existing Service Principal or create a new one. The Service Principal will be granted *Owner* permission on the top level Management Group that gets created.
1.2.1 If using an existing Service Principal, ensure you have the *client secret* as this must be provided as the *Password* for the service principal and confirm it has the right level of permission.
![Graphical user interface, text, application Description automatically generated](./media/clip_image020.jpg)
1.2.2 If creating a new Service Principal, select "Create New" and click on Make selection” and the portal will open a new blade for app registration
![img](./media/clip_image022.png)
![img](./media/clip_image024.png)
Once the App has been registered, you must explicitly create a new secret.
![img](./media/clip_image026.png)
![img](./media/clip_image028.jpg)
Make sure to note down the “Value” of the new client secret.
![img](./media/clip_image030.jpg)
The default API Permissions for this App are “User.Read”, as depicted below:
![img](./media/clip_image032.jpg)
After copying the secret, go to “Enterprise-Scale Landing Zones” (in the upper left) to return to the deployment.
![img](./media/clip_image034.png)
At this point, paste the client secret value of the newly created client secret from a few step above into the Password field.
![Graphical user interface, application Description automatically generated](./media/clip_image035.png)
### Validation post deployment (GitHub)
Once Enterprise-Scale has deployed and you enabled the CI/CD bootstrap, you should validate in your GitHub account that:
* A new repository has been created, with the name provided during setup.
![Graphical user interface, text, application Description automatically generated](./media/clip_image040.png)
* 4 Secrets are created into this GitHub repository.
ARM_CLIENT_ID = Service Principal
ARM_CLIENT_SECRET = Service Principal Client Secret created in the Tenant
ARM_SUBSCRIPTION_ID = The management subscription ID created in the Tenant
ARM_TENANT_ID = Tenant ID of the Azure Tenant that was used to create ESLZ
![img](./media/clip_image042.jpg)
* A Pull Request is either in progress or has completed and automatically merged into the main branch.
![img](./media/clip_image044.png)
* The Azure hierarchy that got created using ARM templates as part of the Enterprise-Scale setup, such as management groups, subscription organization as well as policy definitions, policy assignments and role assignments are hydrated and organized into Git:
![Graphical user interface Description automatically generated with medium confidence](./media/clip_image046.jpg)
![Graphical user interface, application Description automatically generated](./media/clip_image048.jpg)
* In each folder, you will find the ARM templates that were deployed at the scopes during the Enterprise-Scale setup. E.g., on the intermediate root group, you will find all policy definitions, and depending on the selection you made during the deployment, you will find resource templates in the platform subscriptions. Users can – whenever they are ready, start using these templates and bring their own templates to manage the platform using ARM templates and infrastructure as code.
![Graphical user interface, application Description automatically generated](./media/clip_image050.jpg)
## Operating the Azure platform using AzOps (Infrastructure as Code with GitHub Actions)
When you have deployed Enterprise-Scale with GitHub integration, you will have a ready-to-go repository with integrated GitHub Actions containing all the ARM templates that were used during deployment, organized in the following way:
* Management group tree structure represented as folders in Git
* Subscriptions represented as folders in their respective management group folder in Git
* Resource Groups represented as folders in their respective subscription folder in Git
* Policy Definitions, Policy Set Definitions, Role Definitions, and Role Assignments as composite ARM resource templates partitioned at the folder representing the respective scope in Azure (management group, subscription)
* Resources (e.g., virtual networks, Log Analytics workspace, Automation account etc.) represented as composite ARM resource templates into their respective resource group (folder)
You can edit/update the existing ARM templates in your repository and GitHub actions will push (deploy) to the respective Azure scope. You can also author and bring your own ARM templates and deploy them to the respective Azure scope.
The following section will demonstrate how one can operationalize the Enterprise-Scale platform using ARM templates, via the GitHub repository that got created using AzOps (GitHub Actions).
### What is AzOps?
AzOps is an opinionated CI/CD pipeline to operationalize the Azure *platform* and *landing zones* that enables organizations to focus on the ARM template development, and not having to deal with multiple deployment scripts targeting different Azure scopes. The organization and folder structure in Git is dynamically representing the Azure graph (management groups (parent, child relationships), and subscription organization), so the platform operators can easily determine at which *scope* they want to invoke the ARM template deployment by simply making a PR with the ARM template(s) and parameter files (optionally), and AzOps will invoke the deployment accordingly.
Also, when theres a new *scope* (management groups, subscriptions, and resource groups) being created, either explicitly via the pipeline – and also out of band (via Portal, CLI, PS etc.), AzOps will discover these and represent them correctly back into Git.
### Create new Policy Assignment for validation
Enterprise-Scale with its Policy Driven Governance principle relies heavily on Azure Policy to determine the goal state of the overall platform. As an example, this exercise will demonstrate how a developer can make a new policy assignment at the “Online” landing zone management group scope.
1. In GitHub, navigate to your repository and click on the azops folder. From here, navigate to your <prefix>-online folder which represents the management group for all your online landing zones.
![img](./media/clip_image052.jpg)
2. Click on Add file, and Create new file.
3. Name the file locationAssignment.json
4. Copy and paste the following ARM template json
``` json
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"policyAssignmentEnforcementMode": {
"type": "string",
"allowedValues": [
"Default",
"DoNotEnforce"
],
"defaultValue": "DoNotEnforce",
"metadata": {
"description": "Input will determine if the policyAssignment should be enforced or not."
}
},
"policyDefinitionId": {
"type": "string",
"defaultValue": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
"metadata": {
"description": "Provide the policyDefinition resourceId"
}
},
"policyAssignmentName": {
"type": "string",
"defaultValue": "AllowedLocations"
},
"policyDescription": {
"type": "string",
"defaultValue": "Policy to ringfence Azure regions."
},
"listOfAllowedLocations": {
"type": "array",
"defaultValue": [
"westeurope",
"northeurope"
]
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"name": "[parameters('policyAssignmentName')]",
"identity": {
"type": "SystemAssigned"
},
"location": "[deployment().location]",
"properties": {
"description": "[parameters('policyDescription')]",
"displayName": "[parameters('policyDescription')]",
"policyDefinitionId": "[parameters('policyDefinitionId')]",
"enforcementMode": "[parameters('policyAssignmentEnforcementMode')]",
"parameters": {
"listOfAllowedLocations": {
"value": "[parameters('listOfAllowedLocations')]"
}
}
}
}
]
}
```
5. Examine the file and note that we are using default values for the parameters. You could modify these, or you could also provide a locationAssignment.parameters.json file to provide the parameters.
6. On the Commit new file option, select Create a new branch for this commit and start a pull request, and give it a name.
![Graphical user interface, text, application, email Description automatically generated](./media/ESLZ-location-assignment-policy.JPG)
7. Click Propose new file' and on the next page, click 'Create Pull Request." A new Pull Request is being created which will trigger the Push workflow. Go to Actions to monitor the process.
![Graphical user interface, text, application, chat or text message Description automatically generated](./media/clip_image056.jpg)
8. Once completed, the pull request should automatically merge.
9. In Azure portal, you can navigate to the <prefix>-online management group and verify that the deployment resource got created and deployed successfully. Each deployment invoked via AzOps will have an AzOps prefix.
![Graphical user interface, text, application, email Description automatically generated](./media/clip_image058.jpg)
10. Navigate to Policies on the <prefix>-online management group and verify that theres a new assignment called Policy to ring-fence Azure regions.
![Graphical user interface, text, application, email Description automatically generated](./media/clip_image060.jpg)
11. Click on Edit assignment to verify that the Policy is not being enforced but will only scan for compliance and validate resources per the policy rule defined in the policy definition.
![Text Description automatically generated with low confidence](./media/clip_image062.jpg)
Once the policy compliance scan has completed, you will get a compliance result for the policy you assigned to validate the effect is working as intended, before going to the next step to update the enforcement mode. I.e., this policy will prevent resources being created outside of the allowed locations specified.
You can now merge the pull request and delete the branch.
### Update a Policy Assignment to enforce
In this exercise, we will modify the existing policy assignment to ensure the policy effect will be enforced.
1. Navigate the locationAssignment.json file you placed into the <prefix>-online folder, representing the online landing zone.
2. Click on Edit this file ![img](./media/clip_image063.png)
3. Change the parameter “policyAssignmentEnforcementMode” default value to be Default.
![Graphical user interface, text, application, email Description automatically generated](./media/clip_image065.jpg)
4. On the Commit changes dialogue box, select Create a new branch for this commit and start a pull request, and provide a branch name. Click Propose changes and create the pull request
![Graphical user interface, text, application, email Description automatically generated](./media/ESLZ-Update-location-assignment-policy.JPG)
This will now start the AzOps push workflow and deploy the template with the updated property so that the policy effect will be enforced (in this case, deny resource creation outside of the ringfenced Azure regions).
Once the job has completed, you can revisit the policy in Azure portal and see that the policy enforcement is set to Enabled.
![Graphical user interface, text, application, email Description automatically generated](./media/clip_image069.jpg)
You can now merge the pull request and delete the branch.
### Create new Role Assignment on a landing zone
To grant a user, a group, or a service principal access to a landing zone (subscription), you can use the following ARM template where you provide the principalId (object id of the user, group, or service principal) as input to the parameter, and place the template into the subscription folder into your landing zone management group(s).
Replace Provide-Principal-Id with Id of the principal.
```json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"type": "string",
"defaultValue": "<Provide-Principal-Id>",
"metadata": {
"description": "Provide the objectId of the principal (user, group, SPN, managed identity etc.) that will be granted RBAC at scope."
}
},
"roleDefinitionId": {
"type": "string",
"defaultValue": "b24988ac-6180-42a0-ab88-20f7382dd24c",
"metadata": {
"description": "Provide the id of the built-in roleDefinition. Default is 'Contributor'."
}
}
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2017-09-01",
"name": "[guid(parameters('principalId'))]",
"properties": {
"principalId": "[parameters('principalId')]",
"roleDefinitionId": "[concat('/providers/Microsoft.Authorization/roleDefinitions/', parameters('roleDefinitionId'))]"
}
}
]
}
```
---

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

@ -36,12 +36,10 @@ Enterprise Scale/Azure Landing Zones is updated regularly. This page is where yo
- Azure Policy changes
- Bug fixes
- Tooling updates:
- [AzOps](https://github.com/azure/azops)
- [Releases](https://github.com/Azure/AzOps/releases)
- [Terraform Module for Cloud Adoption Framework Enterprise-scale](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale)
- [Releases](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/releases)
- [ALZ-Bicep Modules](https://github.com/Azure/ALZ-Bicep)
- [Releases](https://github.com/Azure/ALZ-Bicep/releases)
- [Terraform Module for Cloud Adoption Framework Enterprise-scale](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale)
- [Releases](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/releases)
> **Note:** Please check the latest release notes for each of the tools, as these will contain more detailed notes relating to changes in each of the tools.
@ -62,12 +60,14 @@ Here's what's changed in Enterprise Scale/Azure Landing Zones:
- Updated the ALZ Policy Assignments Excel spreadsheet to include a release version column so users can track when those policies last changed and verified all assignments have a relevant AzAdvertizer link for policy details.
- [Azure Enablement Show: Updating your Azure landing zones](https://www.youtube.com/watch?v=VvZDftlF20w) published
- [Tech Community Blog: Azure Monitor Baseline Alerts (Preview)](https://techcommunity.microsoft.com/t5/azure-governance-and-management/azure-monitor-baseline-alerts-preview/ba-p/3810463) published
- Updated wiki documentation to so reflect the removal of the "Platform DevOps and automation" section from ALZ Portal Accelerator
#### Tooling
- ALZ Bicep [`v0.14.0`](https://github.com/Azure/ALZ-Bicep/releases/tag/v0.14.0) released
- [ALZ Bicep Accelerator (MVP) launched](https://github.com/Azure/ALZ-Bicep/wiki/Accelerator)
- ALZ Terraform (`caf-enterprise-scale`) [`v4.0.0`](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/releases/tag/v4.0.0) released
- ALZ Portal Accelerator: "Platform DevOps and automation" section removed
### April 2023

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

@ -917,172 +917,6 @@
}
]
},
{
"name": "automation",
"label": "Platform DevOps and automation",
"subLabel": {},
"bladeTitle": "ALZ - Automation Settings",
"elements": [
{
"name": "automationBlankNote",
"type": "Microsoft.Common.InfoBox",
"visible": true,
"options": {
"text": "Please ensure you have selected a management or platform subscription on the 'Platform management, security, and governance' blade",
"uri": "https://github.com/Azure/Enterprise-Scale/wiki/Deploying-ALZ-Platform-DevOps",
"style": "Warning"
}
},
{
"name": "info",
"type": "Microsoft.Common.InfoBox",
"visible": "[or(not(empty(steps('management').esMgmtSubSection.esMgmtSub)), not(empty(steps('core').singleSubscription.selector)))]",
"options": {
"text": "Azure Landing Zones provides an integrated CI/CD pipeline via AzOps that can be used with either GitHub Actions or Azure DevOps pipelines.",
"uri": "https://github.com/azure/azops-accelerator/wiki/introduction",
"style": "Info"
}
},
{
"name": "correction",
"type": "Microsoft.Common.InfoBox",
"visible": "[and(equals(steps('management').enableLogAnalytics, 'No'), not(equals(steps('core').platformSubscription, 'Single')))]",
"options": {
"text": "Azure Landing Zones provides an integrated CI/CD pipeline via AzOps that can be used with either GitHub Actions or Azure DevOps pipelines, but requires a dedicated subscription for platform management in the previous step. Please add a subscription or continue without setting up the CI/CD integration.",
"uri": "https://github.com/azure/azops-accelerator/wiki/introduction",
"style": "Warning"
}
},
{
"name": "enableAzOps",
"type": "Microsoft.Common.OptionsGroup",
"label": "Deploy integrated CI/CD pipeline?",
"defaultValue": "No",
"toolTip": "",
"constraints": {
"allowedValues": [
{
"label": "Yes",
"value": "Yes"
},
{
"label": "No",
"value": "No"
}
],
"required": true
},
"visible": "[or(not(empty(steps('management').esMgmtSubSection.esMgmtSub)), not(empty(steps('core').singleSubscription.selector)))]"
},
{
"name": "Instructions",
"type": "Microsoft.Common.TextBlock",
"visible": "[equals(steps('automation').enableAzOps,'Yes')]",
"options": {
"text": "Provide the credentials to initialize the repository with the ARM templates for Azure Landing Zones.",
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization"
}
}
},
{
"name": "optionsGroup1",
"type": "Microsoft.Common.OptionsGroup",
"label": "Select CI/CD option",
"defaultValue": "GitHub Actions",
"toolTip": "Azure Landing Zones will provide options for both GitHub Actions and Azure DevOps pipelines. For now, only GitHub Actions is available",
"constraints": {
"allowedValues": [
{
"label": "GitHub Actions",
"value": "actions"
}
],
"required": true
},
"visible": "[equals(steps('automation').enableAzOps,'Yes')]"
},
{
"name": "gitHubUserNameOrOrg",
"type": "Microsoft.Common.TextBox",
"label": "GitHub organization or username",
"toolTip": "Provide Git org/username.",
"visible": "[equals(steps('automation').enableAzOps,'Yes')]",
"defaultValue": "",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,39}$",
"validationMessage": "The GitHub org/username must be 1-39 characters."
}
},
{
"name": "repositoryName",
"type": "Microsoft.Common.TextBox",
"label": "New GitHub repository name",
"toolTip": "Provide a name for the new repository that will be created",
"defaultValue": "",
"visible": "[equals(steps('automation').enableAzOps,'Yes')]",
"placeholder": "",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,100}$",
"validationMessage": "The repository name must be 1-100 characters."
}
},
{
"name": "paToken",
"type": "Microsoft.Common.PasswordBox",
"label": {
"password": "GitHub personal access token",
"confirmPassword": "Confirm PA Token"
},
"toolTip": "Provide the personal access token to access your GitHub account or organization. For more information see this link: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token",
"constraints": {
"required": true,
"validationMessage": "Password must be at least 8 characters long, contain only numbers and letters"
},
"options": {
"hideConfirmation": true
},
"visible": "[equals(steps('automation').enableAzOps,'Yes')]"
},
{
"name": "spnSection",
"type": "Microsoft.Common.Section",
"label": "",
"elements": [
{
"name": "esServicePrincipal",
"type": "Microsoft.Common.ServicePrincipalSelector",
"visible": "[equals(steps('automation').enableAzOps,'Yes')]",
"label": {
"password": "Password",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type",
"sectionHeader": "Service Principal"
},
"toolTip": {
"password": "Provide the application secret as it will be used to authenticate with Azure AD",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type"
},
"defaultValue": {
"principalId": "",
"name": ""
},
"constraints": {
"required": true
},
"options": {
"hideCertificate": true
}
}
],
"visible": "[equals(steps('automation').enableAzOps,'Yes')]"
}
]
},
{
"name": "connectivity",
"label": "Network topology and connectivity",
@ -3014,14 +2848,6 @@
"enableAscForContainers": "[steps('management').enableAscForContainers]",
"enableMDEndpoints": "[steps('management').enableMDEndpoints]",
"enableSecuritySolution": "[steps('management').enableSecuritySolution]",
"enableAzOps": "[steps('automation').enableAzOps]",
"gitHubUserNameOrOrg": "[steps('automation').gitHubUserNameOrOrg]",
"repositoryName": "[steps('automation').repositoryName]",
"paToken": "[steps('automation').paToken]",
"principalId": "[steps('automation').spnSection.esServicePrincipal.objectId]",
"principalSecret": "[steps('automation').spnSection.esServicePrincipal.password]",
"appId": "[steps('automation').spnSection.esServicePrincipal.appId]",
"azOpsSubscriptionId": "[steps('management').esMgmtSubSection.esMgmtSub]",
"connectivitySubscriptionId": "[if(not(equals(steps('connectivity').esNwSubSection.esNwSub,steps('management').esMgmtSubSection.esMgmtSub)),steps('connectivity').esNwSubSection.esNwSub,'')]",
"addressPrefix": "[coalesce(steps('connectivity').esAddressHubVWAN, steps('connectivity').esAddressHubHS, '')]",
"connectivityLocation": "[steps('connectivity').connectivityLocation]",

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

@ -259,43 +259,6 @@
"No"
]
},
"enableAzOps": {
"type": "string",
"allowedValues": [
"Yes",
"No"
],
"defaultValue": "No"
},
"gitHubUserNameOrOrg": {
"type": "string",
"defaultValue": ""
},
"repositoryName": {
"type": "string",
"defaultValue": ""
},
"paToken": {
"type": "securestring",
"defaultValue": ""
},
"principalId": {
"type": "array",
"defaultValue": []
},
"principalSecret": {
"type": "securestring",
"defaultValue": ""
},
"appId": {
"type": "string",
"defaultValue": ""
},
"azOpsSubscriptionId": {
"type": "string",
"defaultValue": "",
"maxLength": 36
},
"connectivitySubscriptionId": {
"type": "string",
"defaultValue": "",
@ -798,10 +761,8 @@
"nvaConnectivityHub": "[uri(deployment().properties.templateLink.uri, 'subscriptionTemplates/nvahubspoke-connectivity.json')]",
"subscriptionPlacement": "[uri(deployment().properties.templateLink.uri, 'managementGroupTemplates/subscriptionOrganization/subscriptionOrganization.json')]",
"monitoring": "[uri(deployment().properties.templateLink.uri, 'subscriptionTemplates/logAnalyticsWorkspace.json')]",
"azOpsRBAC": "[uri(deployment().properties.templateLink.uri, 'managementGroupTemplates/roleAssignments/azOpsRoleAssignment.json')]",
"resourceGroup": "[uri(deployment().properties.templateLink.uri, 'subscriptionTemplates/resourceGroup.json')]",
"ddosProtection": "[uri(deployment().properties.templateLink.uri, 'resourceGroupTemplates/ddosProtection.json')]",
"azOpsSetup": "[uri(deployment().properties.templateLink.uri, 'resourceGroupTemplates/azOpsArm.json')]",
"logAnalyticsPolicyAssignment": "[uri(deployment().properties.templateLink.uri, 'managementGroupTemplates/policyAssignments/DINE-LogAnalyticsPolicyAssignment.json')]",
"monitoringSolutions": "[uri(deployment().properties.templateLink.uri, 'subscriptionTemplates/logAnalyticsSolutions.json')]",
"asbPolicyInitiative": "[uri(deployment().properties.templateLink.uri, 'managementGroupTemplates/policyAssignments/DINE-ASBPolicyAssignment.json')]",
@ -856,13 +817,10 @@
"identitySubscriptionPlacement": "[take(concat('alz-IdentitySub', variables('deploymentSuffix')), 64)]",
"roleDefsDeploymentName": "[take(concat('alz-RoleDefs', variables('deploymentSuffix')), 64)]",
"policyDeploymentName": "[take(concat('alz-Policy', variables('deploymentSuffix')), 64)]",
"azOpsRbacDeploymentName": "[take(concat('alz-AzOpsRbac', variables('deploymentSuffix')), 64)]",
"azOpsRgDeploymentName": "[take(concat('alz-AzOpsRg', variables('deploymentSuffix')), 64)]",
"ddosRgDeploymentName": "[take(concat('alz-DDoSRg', variables('deploymentSuffix')), 64)]",
"ddosDeploymentName": "[take(concat('alz-DDoS', variables('deploymentSuffix')), 64)]",
"ddosHubPolicyDeploymentName": "[take(concat('alz-DDoSHubPolicy', variables('deploymentSuffix')), 64)]",
"ddosLzPolicyDeploymentName": "[take(concat('alz-DDoSLZPolicy', variables('deploymentSuffix')), 64)]",
"azOpsSetupDeploymentName": "[take(concat('alz-AzOpsSetup', variables('deploymentSuffix')), 64)]",
"monitoringDeploymentName": "[take(concat('alz-Monitoring', variables('deploymentSuffix')), 64)]",
"logAnalyticsPolicyDeploymentName": "[take(concat('alz-LAPolicy', variables('deploymentSuffix')), 64)]",
"monitoringSolutionsDeploymentName": "[take(concat('alz-Solutions', variables('deploymentSuffix')), 64)]",
@ -935,9 +893,6 @@
"vnetConnectivityHubLiteDeploymentName": "[take(concat('alz-VnetHubLite', variables('deploymentSuffix')), 64)]",
"vwanConnectivityHubLiteDeploymentName": "[take(concat('alz-VWanHubLite', variables('deploymentSuffix')), 64)]",
"nvaConnectivityHubLiteDeploymentName": "[take(concat('alz-NVAHubLite', variables('deploymentSuffix')), 64)]",
"azOpsSetupLiteDeploymentName": "[take(concat('alz-AzOpsSetupLite', variables('deploymentSuffix')), 64)]",
"azOpsRbacLiteDeploymentName": "[take(concat('alz-AzOpsRbacLite', variables('deploymentSuffix')), 64)]",
"azOpsRgLiteDeploymentName": "[take(concat('alz-AzOpsRgLite', variables('deploymentSuffix')), 64)]",
"ddosRgLiteDeploymentName": "[take(concat('alz-DDoSRgLite', variables('deploymentSuffix')), 64)]",
"ddosLiteDeploymentName": "[take(concat('alz-DDoSLite', variables('deploymentSuffix')), 64)]",
"ddosHubLitePolicyDeploymentName": "[take(concat('alz-DDoSHubPolicyLite', variables('deploymentSuffix')), 64)]",
@ -947,7 +902,6 @@
// Declaring deterministic names for Resource Groups that will be created for platform resources
"platformRgNames": {
"mgmtRg": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-mgmt')]",
"azOpsRg": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-azops')]",
"connectivityRg": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-vnethub-', parameters('connectivityLocation'))]",
"ddosRg": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-ddos')]",
"privateDnsRg": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-privatedns')]",
@ -971,8 +925,6 @@
"identityVnet": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-vnet-', parameters('connectivityLocation'))]",
"lzVnet": "[concat(parameters('enterpriseScaleCompanyPrefix'), '-vnet-', parameters('connectivityLocation'))]"
},
// Declaring subscriptionId for AzOps
"azOpsSubscriptionId": "[if(empty(parameters('azOpsSubscriptionId')), parameters('singlePlatformSubscriptionId'), parameters('azOpsSubscriptionId'))]",
// Declaring deterministic resourceId's for platform resources that will be created
"singleVsDedicatedMgmtSub": "[if(empty(parameters('managementSubscriptionId')), parameters('singlePlatformSubscriptionId'), parameters('managementSubscriptionId'))]",
"singleVsDedicatedConnectivitySub": "[if(empty(parameters('connectivitySubscriptionId')), parameters('singlePlatformSubscriptionId'), parameters('connectivitySubscriptionId'))]",
@ -2215,122 +2167,6 @@
}
}
},
/*
The following optional deployment will configure and setup AzOps with GitHub for your ESLZ deployment
*/
{
// Creating roleAssignment for the dedicated Service Principal for AzOps
"condition": "[and(equals(parameters('enableAzOps'), 'Yes'), not(empty(parameters('principalSecret'))))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[variables('deploymentNames').azOpsRbacDeploymentName]",
"scope": "[variables('scopes').eslzRootManagementGroup]",
"location": "[deployment().location]",
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').mgmtSubscriptionPlacement)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLiteDeploymentNames').platformLiteSubscriptionPlacement)]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"contentVersion": "1.0.0.0",
"uri": "[variables('deploymentUris').azOpsRBAC]"
},
"parameters": {
"topLevelManagementGroupPrefix": {
"value": "[parameters('enterpriseScaleCompanyPrefix')]"
},
"principalId": {
"value": "[parameters('principalId')]"
}
}
}
},
{
// Creating resource group for AzOps
"condition": "[and(equals(parameters('enableAzOps'), 'Yes'), not(empty(parameters('principalSecret'))))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[variables('deploymentNames').azOpsRgDeploymentName]",
"subscriptionId": "[variables('azOpsSubscriptionId')]",
"location": "[deployment().location]",
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').mgmtSubscriptionPlacement)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').azOpsRbacDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLiteDeploymentNames').platformLiteSubscriptionPlacement)]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"contentVersion": "1.0.0.0",
"uri": "[variables('deploymentUris').resourceGroup]"
},
"parameters": {
"rgName": {
"value": "[variables('platformRgNames').azOpsRg]"
},
"location": {
"value": "[deployment().location]"
}
}
}
},
{
// Creating GitHub repository and bootstraps the CICD pipeline
"condition": "[and(equals(parameters('enableAzOps'), 'Yes'), not(empty(parameters('principalSecret'))))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[variables('deploymentNames').azOpsSetupDeploymentName]",
"subscriptionId": "[variables('azOpsSubscriptionId')]",
"resourceGroup": "[variables('platformRgNames').azOpsRg]",
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').mgmtSubscriptionPlacement)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').azOpsRbacDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').azOpsRgDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLiteDeploymentNames').platformLiteSubscriptionPlacement)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLitedeploymentNames').vnetConnectivityHubLiteDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLitedeploymentNames').vwanConnectivityHubLiteDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLitedeploymentNames').nvaConnectivityHubLiteDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('esLitedeploymentNames').monitoringSolutionsLiteDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').policyDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').monitoringSolutionsDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').activityDiagnosticsPolicyDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').identitySubscriptionPlacement)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').vnetConnectivityHubDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').vwanConnectivityHubDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').nvaConnectivityHubDeploymentName)]",
"[resourceId('Microsoft.Resources/deployments', variables('deploymentNames').resourceDiagnosticsPolicyDeploymentName)]",
"corpLzs",
"onlineLzs"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"contentVersion": "1.0.0.0",
"uri": "[variables('deploymentUris').azOpsSetup]"
},
"parameters": {
"paToken": {
"value": "[parameters('paToken')]"
},
"principalSecret": {
"value": "[parameters('principalSecret')]"
},
"gitHubUserNameOrOrg": {
"value": "[parameters('gitHubUserNameOrOrg')]"
},
"topLevelManagementGroupPrefix": {
"value": "[parameters('enterpriseScaleCompanyPrefix')]"
},
"appId": {
"value": "[parameters('appId')]"
},
"repositoryName": {
"value": "[parameters('repositoryName')]"
}
}
}
},
/*
The following deployments will deploy and configure the Azure policy governance for the landing zones
*/

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

@ -92,27 +92,6 @@
"enableSecuritySolution": {
"value": "Yes"
},
"enableAzOps": {
"value": "No"
},
"gitHubUserNameOrOrg": {
"value": ""
},
"repositoryName": {
"value": ""
},
"paToken": {
"value": ""
},
"principalId": {
"value": []
},
"principalSecret": {
"value": ""
},
"appId": {
"value": ""
},
"addressPrefix": {
"value": "10.100.0.0/16"
},

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

@ -560,162 +560,6 @@
}
]
},
{
"name": "lzDevOps",
"label": "Platform DevOps and automation",
"subLabel": {},
"bladeTitle": "lz Dev Ops",
"elements": [
{
"name": "info",
"type": "Microsoft.Common.InfoBox",
"visible": "[or(not(empty(steps('esGoalState').esMgmtSubSection.esMgmtSub)), not(empty(steps('lzSettings').esSingleSubSection.esSingleSub)))]",
"options": {
"text": "Azure Landing Zones provides an integrated CICD pipeline via AzOps that can be used with either GitHub Actions or Azure DevOps pipelines.",
"uri": "https://github.com/azure/azops-accelerator/wiki/introduction",
"style": "Info"
}
},
{
"name": "correction",
"type": "Microsoft.Common.InfoBox",
"visible": "[and(equals(steps('esGoalState').esLogAnalytics, 'No'), not(equals(steps('lzSettings').subOrgsOption, 'Single')))]",
"options": {
"text": "Azure Landing Zones provides an integrated CICD pipeline via AzOps that can be used with either GitHub Actions or Azure DevOps pipelines, but requires a dedicated subscription for platform management in the previous step. Please add a subscription or continue without setting up the CICD integration.",
"uri": "https://github.com/azure/azops-accelerator/wiki/introduction",
"style": "Warning"
}
},
{
"name": "cicdOption",
"type": "Microsoft.Common.OptionsGroup",
"label": "Deploy integrated CICD pipeline?",
"defaultValue": "Yes (recommended)",
"toolTip": "",
"constraints": {
"allowedValues": [
{
"label": "Yes (recommended)",
"value": "Yes"
},
{
"label": "No",
"value": "No"
}
],
"required": true
},
"visible": "[or(not(empty(steps('esGoalState').esMgmtSubSection.esMgmtSub)), not(empty(steps('lzSettings').esSingleSubSection.esSingleSub)))]"
},
{
"name": "Instructions",
"type": "Microsoft.Common.TextBlock",
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]",
"options": {
"text": "Provide the credentials to initialize the repository with the ARM templates for Azure Landing Zones.",
"link": {
"label": "Learn more",
"uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization"
}
}
},
{
"name": "optionsGroup1",
"type": "Microsoft.Common.OptionsGroup",
"label": "Select CICD option",
"defaultValue": "GitHub Actions",
"toolTip": "Azure Landing Zones will provide options for both GitHub Actions and Azure DevOps pipelines. For now, only GitHub Actions is available",
"constraints": {
"allowedValues": [
{
"label": "GitHub Actions",
"value": "actions"
}
],
"required": true
},
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]"
},
{
"name": "esGit",
"type": "Microsoft.Common.TextBox",
"label": "GitHub organization or username",
"toolTip": "Provide Git org/username.",
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]",
"defaultValue": "",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,39}$",
"validationMessage": "The GitHub org/username must be 1-39 characters."
}
},
{
"name": "esGitRepoName",
"type": "Microsoft.Common.TextBox",
"label": "New GitHub repository name",
"toolTip": "Provide a name for the new repository that will be created",
"defaultValue": "",
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]",
"placeholder": "",
"constraints": {
"required": true,
"regex": "^[a-z0-9A-Z-]{1,100}$",
"validationMessage": "The repository name must be 1-100 characters."
}
},
{
"name": "esPaToken",
"type": "Microsoft.Common.PasswordBox",
"label": {
"password": "GitHub personal access token",
"confirmPassword": "Confirm PA Token"
},
"toolTip": "Provide the personal access token to access your GitHub account or organization. For more information see this link: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token",
"constraints": {
"required": true,
"validationMessage": "Password must be at least 8 characters long, contain only numbers and letters"
},
"options": {
"hideConfirmation": true
},
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]"
},
{
"name": "spnSection",
"type": "Microsoft.Common.Section",
"label": "",
"elements": [
{
"name": "esServicePrincipal",
"type": "Microsoft.Common.ServicePrincipalSelector",
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]",
"label": {
"password": "Password",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type",
"sectionHeader": "Service Principal"
},
"toolTip": {
"password": "Provide the application secret as it will be used to authenticate with Azure AD",
"certificateThumbprint": "Certificate thumbprint",
"authenticationType": "Authentication Type"
},
"defaultValue": {
"principalId": "",
"name": ""
},
"constraints": {
"required": true
},
"options": {
"hideCertificate": true
}
}
],
"visible": "[equals(steps('lzDevOps').cicdOption,'Yes')]"
}
]
},
{
"name": "esConnectivityGoalState",
"label": "Network topology and connectivity",
@ -2369,14 +2213,6 @@
"vpnOrErZones": "[steps('esConnectivityGoalState').esGwRegionalOrAz]",
"firewallSku": "[steps('esConnectivityGoalState').esAzFwSku]",
"firewallZones": "[steps('esConnectivityGoalState').esFwAz]",
"paToken": "[steps('lzDevOps').esPaToken]",
"principalId": "[steps('lzDevOps').spnSection.esServicePrincipal.objectId]",
"principalSecret": "[steps('lzDevOps').spnSection.esServicePrincipal.password]",
"gitHubUserNameOrOrg": "[steps('lzDevOps').esGit]",
"appId": "[steps('lzDevOps').spnSection.esServicePrincipal.appId]",
"enableAzOps": "[steps('lzDevOps').cicdOption]",
"subscriptionId": "[steps('esGoalState').esMgmtSubSection.esMgmtSub.subscriptionId]",
"repositoryName": "[steps('lzDevOps').esGitRepoName]",
"gwRegionalOrAz": "[steps('esConnectivityGoalState').esGwRegionalOrAz]",
"gwAzSku": "[steps('esConnectivityGoalState').esGwAzSku]",
"gwRegionalSku": "[if(empty(steps('esConnectivityGoalState').esGwRegionalSku), steps('esConnectivityGoalState').esGwNoAzSku, steps('esConnectivityGoalState').esGwRegionalSku)]",

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

@ -1,29 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"topLevelManagementGroupPrefix": {
"type": "string"
},
"principalId": {
"type": "array"
}
},
"variables": {
"formattedPrincipalId": "[replace(replace(replace(string(parameters('principalId')), '\"', ''), '[', ''), ']', '')]",
"roleDefinitionOwner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
"roleDefinitionId": "[concat('/providers/Microsoft.Authorization/roleDefinitions/', variables('roleDefinitionOwner'))]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2019-04-01-preview",
"name": "[guid(concat(parameters('topLevelManagementGroupPrefix'), variables('formattedPrincipalId')))]",
"properties": {
"principalType": "ServicePrincipal",
"roleDefinitionId": "[variables('roleDefinitionId')]",
"principalId": "[variables('formattedPrincipalId')]"
}
}
]
}

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

@ -1,150 +0,0 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"paToken": {
"type": "securestring",
"metadata": {
"description": "Provide the PA Token to authorize Git and create new repository for the organization/user."
}
},
"principalSecret": {
"type": "securestring",
"metadata": {
"description": "Provide the principalId which is needed to create GitHub secret"
}
},
"gitHubUserNameOrOrg": {
"type": "string",
"metadata": {
"description": "Provide username or org name for GitHub."
}
},
"topLevelManagementGroupPrefix": {
"type": "string",
"metadata": {
"description": "Provide the prefix for your ESLZ setup."
}
},
"appId": {
"type": "string"
},
"repositoryName": {
"type": "string"
}
},
"variables": {
"keyVaultName": "[take(concat(resourceGroup().name, uniqueString(subscription().subscriptionId)), 24)]",
"keyVaultRbacName": "[concat(variables('keyVaultName'), '/Microsoft.Authorization/', guid(variables('keyVaultName')))]",
"patSecretName": "PATSecret",
"spnSecretName": "SPNSecret",
"userManagedIdentityName": "[concat(resourceGroup().name, '-umi')]",
"keyVaultAdminRbac": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483"
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "2018-11-30",
"name": "[variables('userManagedIdentityName')]",
"location": "[resourceGroup().location]"
},
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2019-09-01",
"name": "[variables('keyVaultName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('userManagedIdentityName')]"
],
"properties": {
"enabledForTemplateDeployment": true,
"enableRbacAuthorization": true,
"enablePurgeProtection": true,
"enableSoftDelete": true,
"tenantId": "[subscription().tenantId]",
"sku": {
"family": "A",
"name": "standard"
}
}
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2019-09-01",
"name": "[concat(variables('keyVaultName'), '/', variables('patSecretName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
],
"properties": {
"value": "[parameters('paToken')]"
}
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2019-09-01",
"name": "[concat(variables('keyVaultName'), '/', variables('spnSecretName'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
],
"properties": {
"value": "[parameters('principalSecret')]"
}
},
{
"type": "Microsoft.KeyVault/vaults/providers/roleAssignments",
"apiVersion": "2020-04-01-preview",
"name": "[variables('keyVaultRbacName')]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('userManagedIdentityName'))]"
],
"properties": {
"principalType": "ServicePrincipal",
"principalId": "[reference(variables('userManagedIdentityName'), '2018-11-30').principalId]",
"roleDefinitionId": "[variables('keyVaultAdminRbac')]"
}
},
{
"type": "Microsoft.Resources/deploymentScripts",
"apiVersion": "2020-10-01",
"name": "[concat(resourceGroup().name, '-GitHub')]",
"location": "[resourceGroup().location]",
"kind": "AzurePowerShell",
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('userManagedIdentityName'))]": {}
}
},
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults/providers/roleAssignments', variables('keyVaultName'), 'Microsoft.Authorization', guid(variables('keyVaultName')))]",
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('patSecretName'))]",
"[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('spnSecretName'))]"
],
"properties": {
"primaryScriptUri": "https://raw.githubusercontent.com/Azure/AzOps/main/scripts/ARMAzOpsSetup.ps1",
"arguments": "[concat('-KeyVault', ' ', variables('keyVaultName'), ' ',
'-NewRepositoryName', ' ', parameters('repositoryName'), ' ',
'-GitHubUserNameOrOrg', ' ', parameters('gitHubUserNameOrOrg'), ' ',
'-SPNSecretName', ' ', variables('spnSecretName'), ' ',
'-SpnAppId', ' ', parameters('appId'), ' ',
'-PATSecretName', ' ', variables('patSecretName'), ' ',
'-AzureTenantId', ' ', subscription().tenantId, ' ',
'-EnterpriseScalePrefix', ' ', parameters('topLevelManagementGroupPrefix'), ' ',
'-AzureSubscriptionId', ' ', subscription().subscriptionId)]",
"azPowerShellVersion": "5.5",
"timeout": "PT30M",
"cleanupPreference": "Always",
"retentionInterval": "P1D"
}
}
],
"outputs": {
"umi": {
"type": "string",
"value": "[reference(variables('userManagedIdentityName'), '2018-11-30').principalId]"
}
}
}