scripts/deployments/RunWorkflows.ps1 (340 lines of code) (raw):
<#
----------------------------------------------------------------------------------
Copyright (c) Microsoft Corporation.
Licensed under the MIT license.
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------------------------------------
#>
<#
.SYNOPSIS
Runs CanadaPubSecALZ workflows.
.DESCRIPTION
This script is used to run one or more workflows for management groups, roles,
logging, policies, networking, and subscriptions.
.PARAMETER DeployManagementGroups
If true, run the management group workflow.
.PARAMETER DeployRoles
If true, run the role workflow.
.PARAMETER RoleNames
An array of role definitions to deploy. Role name must match the file names (without .bicep extension) in ./roles directory. When not set, defaults to 'la-vminsights-readonly', 'lz-appowner', 'lz-netops', 'lz-secops', 'lz-subowner'.
.PARAMETER DeployLogging
If true, run the logging workflow.
.PARAMETER DeployCustomPolicyDefinitions
If true, run the policy workflow for deploying custom policy definitions
.PARAMETER DeployCustomPolicySetDefinitions
If true, run the policy workflow for deploying custom policy set definitions
.PARAMETER CustomPolicySetDefinitionNames
An array of custom policy set definitions to deploy. When not set, defaults to 'AKS', 'DefenderForCloud', 'LogAnalytics', 'Network', 'DNSPrivateEndpoints', 'Tags'.
.PARAMETER DeployCustomPolicySetAssignments
If true, run the policy workflow for deploying custom policy set assignments
.PARAMETER CustomPolicySetAssignmentManagementGroupId
The management group ID to assign custom policy set assignments to. When not set, defaults to top level management group (e.g. pubsec) based on management group hierarchy configuration.
.PARAMETER CustomPolicySetAssignmentNames
An array of custom policy set assignments to deploy. When not set, defaults to 'AKS', 'DefenderForCloud', 'LogAnalytics', 'Network', 'Tags'.
.PARAMETER DeployBuiltinPolicySetAssignments
If true, run the policy workflow for deploying builtin policy definitions and assignments such as regulatory compliances.
.PARAMETER BuiltinPolicySetAssignmentManagementGroupId
The management group ID to assign built-in policy set assignments to. When not set, defaults to top level management group (e.g. pubsec) based on management group hierarchy configuration.
.PARAMETER BuiltinPolicySetAssignmentNames
An array of built-in policy set assignments to deploy. When not set, defaults to 'asb', 'nist80053r4', 'nist80053r5', 'pbmm', 'cis-msft-130', 'fedramp-moderate', 'hitrust-hipaa', 'location'.
.PARAMETER DeployHubNetworkWithAzureFirewall
If true, run the Azure Firewall hub network workflow.
.PARAMETER DeployHubNetworkWithNVA
If true, run the NVA hub network workflow.
.PARAMETER DeployIdentity
If true, run the Identity workflow.
.PARAMETER DeploySubscriptionIds
Comma separated list of quoted subscription ids to run the subscription workflow against.
.PARAMETER EnvironmentName
The name of the environment to run the workflow against.
Used primarily for running interactively.
.PARAMETER GitHubRepo
The GitHub repo to use for the workflow.
.PARAMETER GitHubRef
The GitHub ref to use for the workflow.
.PARAMETER LoginInteractiveTenantId
If set, prompt for credentials and login to the specified tenant.
.PARAMETER LoginServicePrincipalJson
If set, login using the JSON credentials for the specified service principal.
.PARAMETER WorkingDirectory
The directory to use for the workflow.
.PARAMETER NvaUsername
The firewall username to use for the Hub network with NVA workflow.
.PARAMETER NvaPassword
The firewall password to use for the Hub Network with NVA workflow.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -LoginInteractiveTenantId '8188040d-6c67-4c5c-b112-36a304b66dad' -DeployManagementGroups
Deploy management groups interactively.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -LoginInteractiveTenantId '8188040d-6c67-4c5c-b112-36a304b66dad' -DeployManagementGroups -DeployRoles -DeployLogging -DeployCustomPolicyDefinitions -DeployCustomPolicySetDefinitions -DeployCustomPolicySetAssignments -DeployBuiltinPolicySetAssignments -DeployAzureFirewallPolicy -DeployHubNetworkWithAzureFirewall
Deploy all platform components interactively, with Azure Firewall.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -LoginInteractiveTenantId '8188040d-6c67-4c5c-b112-36a304b66dad' -DeploySubscriptionIds 'a188040e-6c67-4c5c-b112-36a304b66dad,7188030d-6c67-4c5c-b112-36a304b66dac'
Deploy 2 subscriptions interactively.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -DeployCustomPolicyDefinitions -DeployCustomPolicySetDefinitions -DeployCustomPolicySetAssignments -DeployBuiltinPolicySetAssignments
Deploy Built-In & Custom Policy Sets, including all default custom policy/policy set definitions.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -DeployCustomPolicyDefinitions
Deploy Custom Policy Definitions only.
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -DeployCustomPolicySetAssignments -CustomPolicySetAssignmentManagementGroupId pubsec -CustomPolicySetAssignmentNames DefenderForCloud
Deploy one Custom Policy Set Assignment at management group
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -DeployBuiltinPolicySetAssignments
Deploy Built In Policy Assignments
.EXAMPLE
PS> .\RunWorkflows.ps1 -EnvironmentName CanadaPubSecALZ-main -DeployBuiltinPolicySetAssignments -BuiltinPolicySetAssignmentManagementGroupId pubsec -BuiltinPolicySetAssignmentNames asb
Deploy one Built In Policy Assignment at management group
.EXAMPLE
PS> .\RunWorkflows.ps1 -GitHubRepo 'Azure/CanadaPubSecALZ' -GitHubRef 'refs/head/main' -LoginServicePrincipalJson (ConvertTo-SecureString -String '<output from: az ad sp create-for-rbac>' -AsPlainText -Force) -DeployManagementGroups
Deploy management groups using service principal authentication.
The action in the GitHub workflow could look like this:
- name: Deploy Management Groups
run: |
./RunWorkflows.ps1 `
-DeployManagementGroups `
-LoginServicePrincipalJson (ConvertTo-SecureString -String '${{secrets.ALZ_CREDENTIALS}}' -AsPlainText -Force) `
-GitHubRepo ${env:GITHUB_REPOSITORY} `
-GitHubRef ${env:GITHUB_REF}
#>
[CmdletBinding()]
Param(
# What to deploy
[switch]$DeployManagementGroups,
[switch]$DeployRoles,
[string[]]$RoleNames=@('la-vminsights-readonly', 'lz-appowner', 'lz-netops', 'lz-secops', 'lz-subowner'),
[switch]$DeployLogging,
[switch]$DeployCustomPolicyDefinitions,
[switch]$DeployCustomPolicySetDefinitions,
[string[]]$CustomPolicySetDefinitionNames=$('AKS', 'DefenderForCloud', 'LogAnalytics', 'Network', 'DNSPrivateEndpoints', 'Tags'),
[switch]$DeployCustomPolicySetAssignments,
[string]$CustomPolicySetAssignmentManagementGroupId=$null,
[string[]]$CustomPolicySetAssignmentNames=$('AKS', 'DefenderForCloud', 'LogAnalytics', 'Network', 'Tags'),
[switch]$DeployBuiltinPolicySetAssignments,
[string]$BuiltinPolicySetAssignmentManagementGroupId=$null,
[string[]]$BuiltinPolicySetAssignmentNames=$('asb', 'nist80053r4', 'nist80053r5', 'pbmm', 'cis-msft-130', 'fedramp-moderate', 'hitrust-hipaa', 'location'),
[switch]$DeployAzureFirewallPolicy,
[switch]$DeployHubNetworkWithNVA,
[switch]$DeployHubNetworkWithAzureFirewall,
[switch]$DeployIdentity,
[string[]]$DeploySubscriptionIds=@(),
# How to deploy
[string]$EnvironmentName="",
[string]$GitHubRepo=$null,
[string]$GitHubRef=$null,
[string]$LoginInteractiveTenantId=$null,
[SecureString]$LoginServicePrincipalJson=$null,
[string]$WorkingDirectory=(Resolve-Path "../.."),
[SecureString]$NvaUsername=$null,
[SecureString]$NvaPassword=$null
)
$ErrorActionPreference = "Stop"
# In order to use this End to End script, you must configure ARM template configurations for Logging, Networking and Subscriptions.
# Please follow the instructions on https://github.com/Azure/CanadaPubSecALZ/blob/main/docs/onboarding/azure-devops-pipelines.md
# to setup the configuration files. Once the configuration files are setup, you can choose to run this script or use Azure DevOps.
# Use $EnvironmentName parameter if specified, otherwise derive from GitHub or Azure DevOps environment.
if ([string]::IsNullOrEmpty($EnvironmentName)) {
# Construct environment name from GitHub repo and ref (result: <repo>-<branch>)
if ((-not [string]::IsNullOrEmpty($GitHubRepo)) -and (-not [string]::IsNullOrEmpty($GitHubRef))) {
$EnvironmentName = `
$GitHubRepo.Split('/')[1] + '-' + `
$GitHubRef.Split('/')[$GitHubRef.Split('/').Count-1]
Write-Host "Environment name: $EnvironmentName"
}
# Construct environment name from Azure DevOps (result: <repo>-<branch>)
<#
TO BE IMPLEMENTED
#>
}
# Load functions
Write-Host "Loading functions..."
. ".\Functions\EnvironmentContext.ps1"
. ".\Functions\ManagementGroups.ps1"
. ".\Functions\Roles.ps1"
. ".\Functions\Logging.ps1"
. ".\Functions\Policy.ps1"
. ".\Functions\HubNetworkWithNVA.ps1"
. ".\Functions\HubNetworkWithAzureFirewall.ps1"
. ".\Functions\Identity.ps1"
. ".\Functions\Subscriptions.ps1"
# Az Login interactively
if (-not [string]::IsNullOrEmpty($LoginInteractiveTenantId)) {
Write-Host "Logging in to Azure interactively..."
Connect-AzAccount `
-UseDeviceAuthentication `
-TenantId $LoginInteractiveTenantId
}
# Az Login via Service Principal
if ($LoginServicePrincipalJson -ne $null) {
Write-Host "Logging in to Azure using service principal..."
$ServicePrincipal = ($LoginServicePrincipalJson | ConvertFrom-SecureString -AsPlainText) | ConvertFrom-Json
$Password = ConvertTo-SecureString $ServicePrincipal.password -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ServicePrincipal.appId, $Password
Connect-AzAccount -ServicePrincipal -TenantId $ServicePrincipal.tenant -Credential $Credential
}
# Set Azure Landing Zones Context
Write-Host "Setting Azure Landing Zones Context..."
$Context = New-EnvironmentContext -Environment $EnvironmentName -WorkingDirectory $WorkingDirectory
# Deploy Management Groups
if ($DeployManagementGroups) {
Write-Host "Deploying Management Groups..."
Set-ManagementGroups `
-Context $Context `
-ManagementGroupHierarchy $Context.ManagementGroupHierarchy
}
# Deploy Roles
if ($DeployRoles) {
Write-Host "Deploying Roles..."
Set-Roles `
-Context $Context `
-RolesDirectory $Context.RolesDirectory `
-RoleNames $RoleNames `
-ManagementGroupId $Context.TopLevelManagementGroupId
}
# Deploy Logging
if ($DeployLogging) {
Write-Host "Deploying Logging..."
Set-Logging `
-Context $Context `
-Region $Context.Variables['var-logging-region'] `
-ManagementGroupId $Context.Variables['var-logging-managementGroupId'] `
-SubscriptionId $Context.Variables['var-logging-subscriptionId'] `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])"
}
# Deploy Policy
if ($DeployCustomPolicyDefinitions) {
Write-Host "Deploying custom policy definitions ..."
Set-Policy-Definitions `
-PolicyDefinitionsDirectory $Context.PolicyCustomDefinitionDirectory `
-ManagementGroupId $Context.TopLevelManagementGroupId
}
if ($DeployCustomPolicySetDefinitions) {
Write-Host "Deploying custom policy set definitions ..."
Set-PolicySet-Defintions `
-Context $Context `
-PolicySetDefinitionsDirectory $Context.PolicySetCustomDefinitionDirectory `
-ManagementGroupId $Context.TopLevelManagementGroupId `
-PolicySetDefinitionNames $CustomPolicySetDefinitionNames
}
if ($DeployCustomPolicySetAssignments) {
Write-Host "Deploying custom policy set assignments ..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
$AssignmentScope = $Context.TopLevelManagementGroupId
if ([string]::IsNullOrEmpty($CustomPolicySetAssignmentManagementGroupId) -eq $false) {
$AssignmentScope = $CustomPolicySetAssignmentManagementGroupId
}
Set-PolicySet-Assignments `
-Context $Context `
-PolicySetAssignmentsDirectory $Context.PolicySetCustomAssignmentsDirectory `
-PolicySetAssignmentManagementGroupId $AssignmentScope `
-PolicySetAssignmentNames $CustomPolicySetAssignmentNames `
-LogAnalyticsWorkspaceResourceGroupName $LoggingConfiguration.ResourceGroupName `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId `
-LogAnalyticsWorkspaceId $LoggingConfiguration.LogAnalyticsWorkspaceId `
-LogAnalyticsWorkspaceRetentionInDays $LoggingConfiguration.LogRetentionInDays
}
if ($DeployBuiltinPolicySetAssignments) {
Write-Host "Deploying built-in policy set assignments ..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
$AssignmentScope = $Context.TopLevelManagementGroupId
if ([string]::IsNullOrEmpty($BuiltinPolicySetAssignmentManagementGroupId) -eq $false) {
$AssignmentScope = $BuiltinPolicySetAssignmentManagementGroupId
}
# Built In Policy Set Assignments
Set-PolicySet-Assignments `
-Context $Context `
-PolicySetAssignmentsDirectory $Context.PolicySetBuiltInAssignmentsDirectory `
-PolicySetAssignmentManagementGroupId $AssignmentScope `
-PolicySetAssignmentNames $BuiltinPolicySetAssignmentNames `
-LogAnalyticsWorkspaceResourceGroupName $LoggingConfiguration.ResourceGroupName `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId `
-LogAnalyticsWorkspaceId $LoggingConfiguration.LogAnalyticsWorkspaceId `
-LogAnalyticsWorkspaceRetentionInDays $LoggingConfiguration.LogRetentionInDays
}
# Deploy Hub Networking with NVA
if ($DeployHubNetworkWithNVA) {
Write-Host "Deploying Hub Networking with NVA..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
Set-HubNetwork-With-NVA `
-Context $Context `
-Region $Context.Variables['var-hubnetwork-region'] `
-ManagementGroupId $Context.Variables['var-hubnetwork-managementGroupId'] `
-SubscriptionId $Context.Variables['var-hubnetwork-subscriptionId'] `
-ConfigurationFilePath "$($Context.NetworkingDirectory)/$($Context.Variables['var-hubnetwork-nva-configurationFileName'])" `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId `
-NvaUsername $NvaUsername `
-NvaPassword $NvaPassword
}
# Azure Firewall Policy
if ($DeployAzureFirewallPolicy) {
# Create Azure Firewall Policy
Set-AzureFirewallPolicy `
-Context $Context `
-Region $Context.Variables['var-hubnetwork-region'] `
-SubscriptionId $Context.Variables['var-hubnetwork-subscriptionId'] `
-ConfigurationFilePath "$($Context.NetworkingDirectory)/$($Context.Variables['var-hubnetwork-azfwPolicy-configurationFileName'])"
}
# Hub Networking with Azure Firewall
if ($DeployHubNetworkWithAzureFirewall) {
Write-Host "Deploying Hub Networking with Azure Firewall..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
# Retrieve Azure Firewall Policy
$AzureFirewallPolicyConfiguration = Get-AzureFirewallPolicy `
-SubscriptionId $Context.Variables['var-hubnetwork-subscriptionId'] `
-ConfigurationFilePath "$($Context.NetworkingDirectory)/$($Context.Variables['var-hubnetwork-azfwPolicy-configurationFileName'])"
# Create Hub Networking with Azure Firewall
Set-HubNetwork-With-AzureFirewall `
-Context $Context `
-Region $Context.Variables['var-hubnetwork-region'] `
-ManagementGroupId $Context.Variables['var-hubnetwork-managementGroupId'] `
-SubscriptionId $Context.Variables['var-hubnetwork-subscriptionId'] `
-ConfigurationFilePath "$($Context.NetworkingDirectory)/$($Context.Variables['var-hubnetwork-azfw-configurationFileName'])" `
-AzureFirewallPolicyResourceId $AzureFirewallPolicyConfiguration.AzureFirewallPolicyResourceId `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId
}
# Deploy Identity Subscription
if ($DeployIdentity) {
Write-Host "Deploying Identity Subscription..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
#Create Identity Subscription
Set-Identity `
-Context $Context `
-Region $Context.Variables['var-identity-region'] `
-ManagementGroupId $Context.Variables['var-identity-managementGroupId'] `
-SubscriptionId $Context.Variables['var-identity-subscriptionId'] `
-ConfigurationFilePath "$($Context.IdentityDirectory)/$($Context.Variables['var-identity-configurationFileName'])" `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId
}
# Deploy Subscription archetypes
if (($null -ne $DeploySubscriptionIds) -and ($DeploySubscriptionIds.Count -gt 0)) {
Write-Host "Deploying Subscriptions..."
# Get Logging information using logging config file
$LoggingConfiguration = Get-LoggingConfiguration `
-ConfigurationFilePath "$($Context.LoggingDirectory)/$($Context.Variables['var-logging-configurationFileName'])" `
-SubscriptionId $Context.Variables['var-logging-subscriptionId']
# Deploy archetypes
# Replace subscription id example below with your subscription ids
Set-Subscriptions `
-Context $Context `
-Region $Context.DeploymentRegion `
-SubscriptionIds $DeploySubscriptionIds `
-LogAnalyticsWorkspaceResourceId $LoggingConfiguration.LogAnalyticsWorkspaceResourceId
}