orchestration/scripts/New-Compliance.ps1 (603 lines of code) (raw):

# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. <# .SYNOPSIS The powershell script deploys policies as part of SLZ deployment. #> param ( $parAttendedLogin = $true ) . ".\Invoke-Helper.ps1" . ".\New-PolicyExemption.ps1" -parAttendedLogin $parAttendedLogin . ".\New-PolicyRemediation.ps1" -parAttendedLogin $parAttendedLogin #variables $varDefaultComplianceBicepFilePath = '..\defaultCompliance\defaultCompliance.bicep' $varCustomComplianceBicepFilePath = '..\customCompliance\customCompliance.bicep' $varPolicyInstallationBicepFilePath = '..\policyInstallation\policyInstallation.bicep' $varComplianceRequiredParams = @('parDeploymentPrefix', 'parAllowedLocations', 'parAllowedLocationsForConfidentialComputing', 'parDeploymentLocation') $varAlzDefaultPolicyRequiredParams = @('parLogAnalyticsWorkspaceId', 'parAutomationAccountName', 'parPrivateDnsResourceGroupId') <# .Description Deletes the custom and default policy assignments for each of the SLZ management groups. #> function Get-PolicyAssignmentsandExemptions { param ($parParameters) $varLoopCounter = 0; while ($varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { try { Write-Information ">>> Verifying policy assignments are present in SLZ" -InformationAction Continue $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" $varScope = "/providers/Microsoft.Management/managementGroups/" + $varManagementGroupId $varPolicyAssignmentsList = Get-AzPolicyAssignment -Scope $varScope -WarningAction Ignore if ($null -eq $varPolicyAssignmentsList) { Write-Information ">>> Policy assignments are not deployed in the env." -InformationAction Continue return } Write-Information ">>> Policy assignments found. Fetching policy set definition files for version check" -InformationAction Continue $varPolicySetDefinitionDict = Get-PolicySetDefinitionVersion Write-Information ">>> For deployed SLZ Policy Sets, checking if there's a version update" -InformationAction Continue [System.Collections.ArrayList]$varListOfUpdatedPolicySetDefinitionIds = @() if (Confirm-AzResourceVersion) { $varPolicySetDefinitions = Get-AzPolicySetDefinition -ManagementGroupName $varManagementGroupId -BackwardCompatible -WarningAction Ignore } else { $varPolicySetDefinitions = Get-AzPolicySetDefinition -ManagementGroupName $varManagementGroupId -WarningAction Ignore } foreach ($varUpcomingPolicySet in $varPolicySetDefinitionDict.GetEnumerator()) { $varPolicySetDefinition = $varPolicySetDefinitions | Where-Object { $_.Name -eq $varUpcomingPolicySet.Key -or $_.Name -match "$($varUpcomingPolicySet.Key).v" } $varPolicySetDefinitionVersion = $varUpcomingPolicySet.Value foreach ($varPolicyset in $varPolicySetDefinition) { $varDeployedPolicySetDefinitonVersion = $varPolicyset.Properties.Metadata.version if ($varPolicySetDefinitionVersion -gt $varDeployedPolicySetDefinitonVersion) { $varListOfUpdatedPolicySetDefinitionIds.add($varPolicyset.Name) >> $null } } } return $varListOfUpdatedPolicySetDefinitionIds } catch { $varLoopCounter++ $varException = $_.Exception $varErrorDetails = $_.ErrorDetails $varTrace = $_.ScriptStackTrace Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) { Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue Write-Error ">>> Error ocurred during getting policy assignment. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } } } } <# .Description Deletes the custom and default policy assignments for each of the SLZ management groups. #> function Remove-PolicyAssignmentsandExemptions { param ($varListOfUpdatedPolicySetDefinitionIds) $varLoopCounter = 0; $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" while ($varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { try { Write-Information ">>> Cleaning old policy assignments in SLZ" -InformationAction Continue if (!$varListOfUpdatedPolicySetDefinitionIds) { Write-Information ">>> No updates to policy set definiton id version." -InformationAction Continue } else { Write-Information ">>> Policy assignment and exemption clean up started" -InformationAction Continue $varManagementGroupNames = $varManagementGroupId, "decommissioned", "landingzones", "landingzones-confidential-corp", "landingzones-confidential-online", "landingzones-corp", "landingzones-online", "platform", "platform-connectivity", "platform-identity", "platform-management", "sandbox" $varManagementGroupNames | ForEach-Object { if ($_ -eq $varManagementGroupId) { $varScope = "/providers/Microsoft.Management/managementGroups/" + $varManagementGroupId } else { $varScope = "/providers/Microsoft.Management/managementGroups/" + $parDeploymentPrefix + "-" + $_ + $parDeploymentSuffix } [System.Collections.ArrayList]$varListOfUpdatedPolicyAssignmentNames = @() $varAssignments = Get-AzPolicyAssignment -Scope $varScope -WarningAction Ignore if ($null -ne $varAssignments) { $varAssignments | ForEach-Object { $varPolicyDefinitionId = $_.Properties.PolicyDefinitionId.Substring($_.Properties.PolicyDefinitionId.LastIndexOf('/') + 1) if ($varListOfUpdatedPolicySetDefinitionIds.Contains($varPolicyDefinitionId)) { $varListOfUpdatedPolicyAssignmentNames.Add($_.name) >> $null Remove-AzPolicyAssignment -Scope $varScope -Name $_.name -WarningAction Ignore >> $null } } } $varExemptions = Get-AzPolicyExemption -Scope $varScope -WarningAction Ignore if ($null -ne $varExemptions) { $varExemptions | ForEach-Object { if ($varListOfUpdatedPolicyAssignmentNames.Contains($_.name)) { Remove-AzPolicyExemption -Scope $varScope -Name $_.name -WarningAction Ignore -Confirm:$false >> $null } } } } Write-Information ">>> Policy assignment and exemption clean up completed. Executing the next steps after waiting for $varRetryWaitTimeTransientErrorRetry seconds." -InformationAction Continue } return } catch { $varLoopCounter++ $varException = $_.Exception $varErrorDetails = $_.ErrorDetails $varTrace = $_.ScriptStackTrace Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) { Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue Write-Error ">>> An error occurred during Remove-PolicyAssignmentsandExemptions. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } } } } <# .Description Installs the custom and default policy sets at the root of the SLZ management group. #> function New-InstallPolicySets { param () $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" $parDeploymentLocation = $parParameters.parDeploymentLocation.value $varDeploymentName = "deploy-policyinstallation-$vartimeStamp" $varParams = @{ parDeploymentPrefix = $parDeploymentPrefix parDeploymentSuffix = $parDeploymentSuffix parDeploymentLocation = $parDeploymentLocation parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value } $varLoopCounter = 0; $varRetry = $true while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { $modDeployPolicyInstallation = $null try { Write-Information ">>> Policy Installation started" -InformationAction Continue $modDeployPolicyInstallation = New-AzManagementGroupDeployment ` -Name $varDeploymentName ` -Location $parDeploymentLocation ` -TemplateFile $varPolicyInstallationBicepFilePath ` -ManagementGroupId $varManagementGroupId ` -TemplateParameterObject $varParams ` -WarningAction Ignore if (!$modDeployPolicyInstallation) { $varRetry = $false Write-Error "`n Error while executing policy installation" -ErrorAction Stop } if ($modDeployPolicyInstallation.ProvisioningState -eq "Failed") { Write-Error "`n Error while executing policy installation" -ErrorAction Stop } Write-Information ">>> Policy installation completed" -InformationAction Continue return } catch { $varException = $_.Exception $varErrorDetails = $_.ErrorDetails $varTrace = $_.ScriptStackTrace if (!$varRetry) { Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } if (!$modDeployPolicyInstallation) { Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } else { $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment if ($null -eq $varDeploymentErrorCodes) { $varRetry = $false } else { $varLoopCounter++ $varRetry = Confirm-Retry $varDeploymentErrorCodes if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry } else { $varRetry = $false Write-Error ">>> Error occurred in install policy sets. Please try after addressing the above error." -ErrorAction Stop } } } } } } <# .Description Assigns the custom policy sets to the SLZ management groups based on convention #> function New-CustomCompliance { param() $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" $parDeploymentLocation = $parParameters.parDeploymentLocation.value $varCustomerPolicySets = Convert-ToArray($parParameters.parCustomerPolicySets.value) $varCustomerPolicySets.foreach({ if ($null -ne $_.policyParameterFilePath -and $_.policyParameterFilePath -ne "") { $_.policyAssignmentParameters = (Get-Content -Path $_.policyParameterFilePath -Raw) -replace '\r?\n', '' } else { $_.policyAssignmentParameters = '{}' } }) $varParams = @{ parDeploymentPrefix = $parDeploymentPrefix parDeploymentSuffix = $parDeploymentSuffix parRequireOwnerRolePermission = $parParameters.parRequireOwnerRolePermission.value parCustomerPolicySets = $varCustomerPolicySets parPolicyAssignmentEnforcementMode = $parParameters.parPolicyAssignmentEnforcementMode.value } $varDeploymentName = "deploy-customcompliance-$vartimeStamp" $varCustomPolicySetExists = Confirm-PolicySetExists $varManagementGroupId "custom" if ($varCustomPolicySetExists -eq $true) { $varLoopCounter = 0; $varRetry = $true while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { $modDeployCustomCompliance = $null try { Write-Information ">>> Custom compliance deployment started" -InformationAction Continue $modDeployCustomCompliance = New-AzManagementGroupDeployment ` -Name $varDeploymentName ` -Location $parDeploymentLocation ` -TemplateFile $varCustomComplianceBicepFilePath ` -ManagementGroupId $varManagementGroupId ` -TemplateParameterObject $varParams ` -WarningAction Ignore if (!$modDeployCustomCompliance) { Write-Error "`n>>> Error occurred in custom policy set assignment." -ErrorAction Stop } if ($modDeployCustomCompliance.ProvisioningState -eq "Failed") { Write-Error "Error occurred during custom compliance deployment." -ErrorAction Stop } Write-Information ">>> Custom compliance completed `n" -InformationAction Continue return $modDeployCustomCompliance } catch { $varException = $_.Exception $varErrorDetails = $_.ErrorDetails $varTrace = $_.ScriptStackTrace if (!$varRetry) { Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } if (!$modDeployCustomCompliance) { Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } else { $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment if ($null -eq $varDeploymentErrorCodes) { $varRetry = $false } else { $varLoopCounter++ $varRetry = Confirm-Retry $varDeploymentErrorCodes if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry } else { $varRetry = $false Write-Error ">>> Error occurred in custom compliance deployment. Please try after addressing the above error." -ErrorAction Stop } } } } } } else { Write-Error ">>> The required custom policy sets were not found. Please try again after some time." -ErrorAction Stop } } <# .Description Assigns the default policy sets to the SLZ management groups based on convention #> function New-DefaultCompliance { param($parDdosProtectionResourceId, $parLogAnalyticsWorkspaceId, $parAutomationAccountName, $parPrivateDnsResourceGroupId) $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" $parDeploymentLocation = $parParameters.parDeploymentLocation.value $parAllowedLocations = $parParameters.parAllowedLocations.value $parAllowedLocationsForConfidentialComputing = $parParameters.parAllowedLocationsForConfidentialComputing.value if ($parAllowedLocations -is [string]) { $parAllowedLocations = -split $parAllowedLocations } if ($parAllowedLocationsForConfidentialComputing -is [string]) { $parAllowedLocationsForConfidentialComputing = -split $parAllowedLocationsForConfidentialComputing } $varParams = @{ parDeploymentPrefix = $parDeploymentPrefix parDeploymentSuffix = $parDeploymentSuffix parAllowedLocations = $parAllowedLocations parAllowedLocationsForConfidentialComputing = $parAllowedLocationsForConfidentialComputing parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value parDdosPlanResourceId = $parDdosProtectionResourceId parLogAnalyticsWorkspaceId = $parLogAnalyticsWorkspaceId parAutomationAccountName = $parAutomationAccountName parLogAnalyticsWorkSpaceAndAutomationAccountLocation = $parDeploymentLocation parPrivateDnsResourceGroupId = $parPrivateDnsResourceGroupId parLogAnalyticsWorkspaceLogRetentionInDays = ($parParameters.parLogRetentionInDays.value).ToString() parMsDefenderForCloudEmailSecurityContact = $parParameters.parMsDefenderForCloudEmailSecurityContact.value parPolicyEffect = $parParameters.parPolicyEffect.value parPolicyAssignmentEnforcementMode = $parParameters.parPolicyAssignmentEnforcementMode.value parExcludedALZPolicyAssignments = Get-ALZPolicyAssignmentNames } $varDeploymentName = "deploy-defaultcompliance-$vartimeStamp" $varRetry = $true while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { $modDeployDefaultCompliance = $null; try { Write-Information ">>> Default compliance deployment started" -InformationAction Continue $modDeployDefaultCompliance = New-AzManagementGroupDeployment ` -Name $varDeploymentName ` -Location $parDeploymentLocation ` -TemplateFile $varDefaultComplianceBicepFilePath ` -ManagementGroupId $varManagementGroupId ` -TemplateParameterObject $varParams ` -WarningAction Ignore if (!$modDeployDefaultCompliance) { $varRetry = $false Write-Error "`n>>> Error occurred in default policy set assignment." -ErrorAction Stop } if ($modDeployDefaultCompliance.ProvisioningState -eq "Failed") { Write-Error "Error occurred during default compliance deployment." -ErrorAction Stop } Write-Information ">>> Default compliance completed" -InformationAction Continue return $modDeployDefaultCompliance } catch { $varException = $_.Exception $varErrorDetails = $_.ErrorDetails $varTrace = $_.ScriptStackTrace if (!$varRetry) { Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } if (!$modDeployDefaultCompliance) { Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop } else { $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment if ($null -eq $varDeploymentErrorCodes) { $varRetry = $false } else { $varLoopCounter++ $varRetry = Confirm-Retry $varDeploymentErrorCodes if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry } else { $varRetry = $false Write-Error ">>> Error occurred in default compliance deployment. Please try after addressing the above error." -ErrorAction Stop } } } } } else { Write-Error ">>> The required default policy sets were not found. Please try again after some time." -ErrorAction Stop return $false } } <# .Description Get the list of all ALZ Policy Assignments. #> function Get-ALZPolicyAssignmentNames { # The SLZ baseline policies $varSLZBaseline = @( "/providers/Microsoft.Authorization/policySetDefinitions/03de05a4-c324-4ccd-882f-a814ea8ab9ea", "/providers/Microsoft.Authorization/policySetDefinitions/c1cbff38-87c0-4b9f-9f70-035c7a3b5523" ) try { $varALZPolicyAssignmentsRootPath = "../../dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments" $varPolicySetAssignmentFiles = Get-ChildItem -Path "$varALZPolicyAssignmentsRootPath/*.json" $varObjArray = @() foreach ($varFile in $varPolicySetAssignmentFiles) { Write-Information "Processing $varFile.Name" -InformationAction Continue $varFilePath = $varALZPolicyAssignmentsRootPath + "/" + $varFile.Name $varJsonContent = Get-Content $varFilePath | ConvertFrom-Json if ($null -ne $varJsonContent -and !$varSLZBaseline.contains($varJsonContent.properties.policyDefinitionId)) { $varObjArray += $varJsonContent.Name } } return , $varObjArray } catch { $varTrace = $_.ScriptStackTrace Write-Error ">>> Error occurred during executing Get-ALZPolicyAssignmentNames. Please try after addressing the below error: $_ $varTrace" -ErrorAction Stop } } <# .Description On demand policy evaluation #> function Invoke-PolicyEvaluation { param() if ($parAttendedLogin) { Write-Information ">>> In order to reflect the latest compliance data of policies, you will now be logged out of Azure and asked to re-login. Please authenticate when prompted." -InformationAction Continue Disconnect-AzAccount Connect-AzAccount } else { return } Write-Information ">>> Trigerring policy scan." -InformationAction Continue try { $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value $varSubscriptions = $null; if (!$parParameters.parIdentitySubscriptionId.value -and !$parParameters.parConnectivitySubscriptionId.value -and !$parParameters.parManagementSubscriptionId.value) { $varSubscriptions = Get-AzSubscription | Where-Object { $_.Name -like "$parDeploymentPrefix*$parDeploymentSuffix" -and $_.State -eq 'Enabled' } } else { $varIdentitySubscriptionId = $parParameters.parIdentitySubscriptionId.value $parConnectivitySubscriptionId = $parParameters.parConnectivitySubscriptionId.value $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value $varSubscriptions = Get-AzSubscription | Where-Object { ($_.Id -eq "$varIdentitySubscriptionId" -or $_.Id -eq "$parConnectivitySubscriptionId" -or $_.Id -eq "$varManagementSubscriptionId") -and $_.State -eq 'Enabled' } } if (!$varSubscriptions) { Write-Error "Error while executing subscription list command" -ErrorAction Stop } $varSubscriptionCount = $varSubscriptions.count if ($varSubscriptionCount -eq 0) { Write-Information ">>> No subscriptions found" -InformationAction Continue } $parInvokePolicyScanSync = $parParameters.parInvokePolicyScanSync.value if ($parInvokePolicyScanSync) { Write-Information ">>> Policy scan will be executed in synchronous mode. The process may take up to an hour." -InformationAction Continue } else { Write-Information ">>> Policy scan will be executed in asynchronous mode." -InformationAction Continue } $varSubscriptionCounter = 1 foreach ($varSubscription in $varSubscriptions) { $varSubscriptionId = $varSubscription.Id; Write-Information "Executing policy evaluation scan for subscription id: $varSubscriptionId . Processing $varSubscriptionCounter out of $varSubscriptionCount. " -InformationAction Continue $varSubscriptionCounter++ # This is not logic requirement, but have to register Microsoft.Network early to avoid Subscription XXXXX-XXXXX-XXXXXXX-XXXXXXX is not registered with NRP because of registration delay. Write-Information ">>> Registering Microsoft.Network resource provider for existing subscriptions..." -InformationAction Continue Set-AzContext -Subscription "$varSubscriptionId" Register-AzResourceProvider -ProviderNamespace Microsoft.Network Write-Information "Registering policy insights resource provider for subscription id: $varSubscriptionId (May take upto 2 minutes)...." -InformationAction Continue Set-AZContext -Subscription $varSubscriptionId $varJob = Register-AzResourceProvider ` -ProviderNamespace 'Microsoft.PolicyInsights' ` -AsJob $varJob | Wait-Job if ($parInvokePolicyScanSync) { $varJob = Start-AzPolicyComplianceScan -AsJob $varJob | Wait-Job } else { Start-AzPolicyComplianceScan -AsJob } } Write-Information "Policy scan completed." -InformationAction Continue } catch { $_ Write-Error ">>> Error occurred during policy evaluation. Please try after addressing the above error." -ErrorAction Stop } } <# .Description Generates the Policies. #> function Invoke-PolicyGeneration { try { Write-Information ">>> Initiating Policy generation script" -InformationAction Continue $varInvokeSLZCustomPolicy = '.\Invoke-SlzCustomPolicyToBicep.ps1' & $varInvokeSLZCustomPolicy -parAttendedLogin $parAttendedLogin -ErrorAction Stop Write-Information ">>> Policy generation complete" -InformationAction Continue return } catch { $varTrace = $_.ScriptStackTrace Write-Error ">>> Error occurred during executing policy generation script. Please try after addressing the below error: $_ $varTrace" -ErrorAction Stop } } <# .Description Gets the default and custom policy set definition name and versions. #> function Get-PolicySetDefinitionVersion { $varTargetDirectories = "../../custom/policies/definitions" $varPolicySetDefinitionDict = @{} foreach ($varDirectory in $varTargetDirectories) { $varSlzPolicySetDefinitionFiles = Get-ChildItem -Path "$varDirectory/*.json" foreach ($varFile in $varSlzPolicySetDefinitionFiles) { $varFileName = $varFile.Name Write-Debug "Processing $varFileName" $varFilePath = $varDirectory + "/" + $varFileName $varJsonContent = Get-Content $varFilePath | ConvertFrom-Json if ($varJsonContent.properties.policyDefinitions.Length -gt 0 -and $varJsonContent.name) { $varPolicySetDefinitionDict[$varJsonContent.name] = $varJsonContent.properties.metadata.version } else { Write-Information ">>> $varFileName not checked for version" -InformationAction Continue } } return $varPolicySetDefinitionDict } } <# .Description Creates the management group hierarchy and subscriptions at tenant level Parameters: parComplianceParametersFilePath -> path to the parameter file containing required parameters to deploy policies varParameters -> hash table containing parameter name and value modDeploySovereignPlatformOutputs -> hash table containing parameter outputs from platform deployment #> function New-Compliance { param($parComplianceParametersFilePath, $parParameters, $parDeploySovereignPlatformOutputs) if (!$parParameters -and !$parDeploySovereignPlatformOutputs) { $parParameters = Read-ParametersValue($parComplianceParametersFilePath) $parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value if ($parDeployAlzDefaultPolicies) { $varComplianceRequiredParams = $varComplianceRequiredParams + $varAlzDefaultPolicyRequiredParams } Confirm-Parameters($varComplianceRequiredParams) Get-DonotRetryErrorCodes } if ($parDeploySovereignPlatformOutputs) { $varDeployHubNetwork = $parParameters.parDeployHubNetwork.value $varDeployDdosProtection = $parParameters.parDeployDdosProtection.value if ($varDeployHubNetwork -and $varDeployDdosProtection) { $varDdosProtectionResourceId = $parDeploySovereignPlatformOutputs.outputs.outDdosProtectionResourceId.value } else { $varDdosProtectionResourceId = $parParameters.parDdosProtectionResourceId.value } $varDeployLogAnalyticsWorkspace = $parParameters.parDeployLogAnalyticsWorkspace.value if ($varDeployLogAnalyticsWorkspace) { $parLogAnalyticsWorkspaceId = $parDeploySovereignPlatformOutputs.outputs.outLogAnalyticsWorkspaceId.value } else { $parLogAnalyticsWorkspaceId = $parParameters.parLogAnalyticsWorkspaceId.value } $varAutomationAccountName = $parDeploySovereignPlatformOutputs.outputs.outAutomationAccountName.value $varPrivateDnsZones = $parDeploySovereignPlatformOutputs.outputs.outPrivateDNSZones.value $varPrivateDnsResourceGroupId = Get-PrivateDnsResourceGroupId $varPrivateDnsZones $parParameters } else { $varDdosProtectionResourceId = $parParameters.parDdosProtectionResourceId.value $parLogAnalyticsWorkspaceId = $parParameters.parLogAnalyticsWorkspaceId.value $varAutomationAccountName = $parParameters.parAutomationAccountName.value $varPrivateDnsResourceGroupId = $parParameters.parPrivateDnsResourceGroupId.value } # Get the old policy assignments $varListOfUpdatedPolicySetDefinitionIds = Get-PolicyAssignmentsandExemptions $parParameters # Generate Default and custom policy sets Invoke-PolicyGeneration #Install default and custom policy sets New-InstallPolicySets # Assign default policy sets $modDeployDefaultCompliance = New-DefaultCompliance $varDdosProtectionResourceId $parLogAnalyticsWorkspaceId $varAutomationAccountName $varPrivateDnsResourceGroupId if (!$modDeployDefaultCompliance) { Write-Error "Default compliance deployment script failed." -ErrorAction Stop } # Assign custom policy sets $modDeployCustomCompliance = New-CustomCompliance if (!$modDeployCustomCompliance) { Write-Error "Custom compliance deployment script failed." -ErrorAction Stop } #Run policy exemption Invoke-PolicyExemption $null $parParameters #Run policy evaluation to update policy compliance state Invoke-PolicyEvaluation $parInvokePolicyScanSync = $parParameters.parInvokePolicyScanSync.value if (!$parInvokePolicyScanSync) { Write-Information ">>> Currently it is not possible to track progress of policy scan when executed asynchronously. Please execute the policy remediation after 24 hours by selecting the 'policyremediation' deployment option." -InformationAction Continue } else { #Run policy remediation to reflect policy compliance state Invoke-PolicyRemediation $null $parParameters } #Removes the old policy assignments Remove-PolicyAssignmentsandExemptions $varListOfUpdatedPolicySetDefinitionIds }