Framework/Core/SubscriptionSecurity/ARMPolicies.ps1
using namespace System.Management.Automation Set-StrictMode -Version Latest # Class to implement Subscription ARM Policy controls class ARMPolicy: CommandBase { hidden [ARMPolicyModel] $ARMPolicyObj = $null; hidden [PSObject[]] $ApplicableARMPolicies = $null; #hidden [PSObject[]] $PolicyAssignments = $null; ARMPolicy([string] $subscriptionId, [InvocationInfo] $invocationContext, [string] $tags): Base($subscriptionId, $invocationContext) { $this.ARMPolicyObj = [ARMPolicyModel] $this.LoadServerConfigFile("Subscription.ARMPolicies.json"); $this.FilterTags = $this.ConvertToStringArray($tags); } hidden [PSObject[]] GetApplicableARMPolices() { if($null -eq $this.ApplicableARMPolicies) { $this.ApplicableARMPolicies = @(); $subscriptionId = $this.SubscriptionContext.SubscriptionId; if(($this.FilterTags | Measure-Object).Count -ne 0) { $this.ARMPolicyObj.Policies | ForEach-Object { $currentItem = $_; if(($currentItem.Tags | Where-Object { $this.FilterTags -Contains $_ } | Measure-Object).Count -ne 0) { # Resolve the value of SubscriptionId $currentItem.Scope = $global:ExecutionContext.InvokeCommand.ExpandString($currentItem.Scope); if([string]::IsNullOrWhiteSpace($currentItem.Scope)) { $currentItem.Scope = "/subscriptions/$subscriptionId" } $this.ApplicableARMPolicies += $currentItem; } } } } return $this.ApplicableARMPolicies; } [MessageData[]] SetARMPolicies() { [MessageData[]] $messages = @(); if($this.Force -or -not ($this.IsLatestVersionConfiguredOnSub($this.ARMPolicyObj.Version,[Constants]::ARMPolicyConfigVersionTagName,"ARMPolicy"))) { if(($this.ARMPolicyObj.Policies | Measure-Object).Count -ne 0) { if($this.GetApplicableARMPolices() -ne 0) { $startMessage = [MessageData]::new("Processing AzSK ARM policies. Total policies: $($this.GetApplicableARMPolices().Count)"); $messages += $startMessage; $this.PublishCustomMessage($startMessage); $this.PublishCustomMessage("Note: Configuring ARM policies can take about 2-3 min...", [MessageType]::Warning); $disabledPolicies = $this.GetApplicableARMPolices() | Where-Object { -not $_.Enabled }; if(($disabledPolicies | Measure-Object).Count -ne 0) { $disabledMessage = "Found ARM policies which are disabled. Total disabled policies: $($disabledPolicies.Count)"; $messages += [MessageData]::new($disabledMessage, $disabledPolicies); $this.PublishCustomMessage($disabledMessage, [MessageType]::Warning); } $enabledPolicies = @(); $enabledPolicies += $this.GetApplicableARMPolices() | Where-Object { $_.Enabled }; if($enabledPolicies.Count -ne 0) { $messages += [MessageData]::new([Constants]::SingleDashLine + "`r`nAdding following ARM policies to the subscription. Total policies: $($enabledPolicies.Count)", $enabledPolicies); [Helpers]::RegisterResourceProviderIfNotRegistered("Microsoft.Scheduler"); $armPoliciesDefns = @{}; $enabledPolicies | ForEach-Object { $policyName = $_.PolicyDefinitionName; # Add ARM policy try { $armPolicy = New-AzureRmPolicyDefinition -Name $_.PolicyDefinitionName -Description $_.Description -Policy ([string]$_.PolicyDefinition) -ErrorAction Stop $armPoliciesDefns.Add($_,$armPolicy); } catch { $messages += [MessageData]::new("Error while adding ARM policy [$policyName] to the subscription", $_, [MessageType]::Error); } }; Start-Sleep -Seconds 15 $errorCount = 0; $currentCount = 0; $armPoliciesDefns.Keys | ForEach-Object { $armPolicy = $_; $armPolicyDefn = $armPoliciesDefns[$_]; $policyName = $armPolicy.PolicyDefinitionName; $currentCount += 1; # Add ARM policy try { New-AzureRmPolicyAssignment -Name $policyName -PolicyDefinition $armPolicyDefn -Scope $armPolicy.Scope -ErrorAction Stop | Out-Null } catch { $messages += [MessageData]::new("Error while adding ARM policy [$policyName] to the subscription", $armPolicy, [MessageType]::Error); $errorCount += 1; } $this.CommandProgress($enabledPolicies.Count, $currentCount, 2); }; [MessageData[]] $resultMessages = @(); if($errorCount -eq 0) { #setting the version tag at AzSKRG $azskRGName = [ConfigurationManager]::GetAzSKConfigData().AzSKRGName; [Helpers]::SetResourceGroupTags($azskRGName,@{[Constants]::ARMPolicyConfigVersionTagName=$this.ARMPolicyObj.Version}, $false) $resultMessages += [MessageData]::new("All AzSK ARM policies have been added to the subscription successfully`r`n" + [Constants]::SingleDashLine, [MessageType]::Update); } elseif($errorCount -eq $enabledPolicies.Count) { $resultMessages += [MessageData]::new("No AzSK ARM policies were added to the subscription due to an error. Please add the ARM policies manually.`r`n" + [Constants]::SingleDashLine, [MessageType]::Error); } else { $resultMessages += [MessageData]::new("$errorCount/$($enabledPolicies.Count) ARM policy(ies) have not been added to the subscription. Please add the ARM policies manually or contact AzSK support team.", [MessageType]::Error); $resultMessages += [MessageData]::new("$($enabledPolicies.Count - $errorCount)/$($enabledPolicies.Count) ARM policy(ies) have been added to the subscription successfully`r`n" + [Constants]::SingleDashLine, [MessageType]::Update); } $messages += $resultMessages; $this.PublishCustomMessage($resultMessages); } } else { $this.PublishCustomMessage("No ARM policies have been found that matches the specified tags. Tags:[$([string]::Join(",", $this.FilterTags))].", [MessageType]::Warning); } } else { $this.PublishCustomMessage("No ARM policies found in the ARM policy file", [MessageType]::Warning); } } return $messages; } [MessageData[]] RemoveARMPolicies() { [MessageData[]] $messages = @(); if(($this.ARMPolicyObj.Policies | Measure-Object).Count -ne 0) { if($this.GetApplicableARMPolices() -ne 0) { $startMessage = [MessageData]::new("Processing ARM policies. Tags:[$([string]::Join(",", $this.FilterTags))]. Total policies: $($this.GetApplicableARMPolices().Count)"); $messages += $startMessage; $this.PublishCustomMessage($startMessage); $this.PublishCustomMessage("Note: Removing ARM policies can take few minutes depending on number of policies to be processed...", [MessageType]::Warning); $disabledPolicies = $this.GetApplicableARMPolices() | Where-Object { -not $_.Enabled }; if(($disabledPolicies | Measure-Object).Count -ne 0) { $disabledMessage = "Found ARM policies which are disabled and will not be removed. Total disabled policies: $($disabledPolicies.Count)"; $messages += [MessageData]::new($disabledMessage, $disabledPolicies); $this.PublishCustomMessage($disabledMessage, [MessageType]::Warning); } $currentPolicies = @(); $currentPolicies += Get-AzureRmPolicyAssignment | Select-Object -Property Name | Select-Object -ExpandProperty Name $enabledPolicies = @(); if($currentPolicies.Count -ne 0) { $enabledPolicies += $this.GetApplicableARMPolices() | Where-Object { $_.Enabled -and $currentPolicies -contains $_.policyDefinitionName }; } if($enabledPolicies.Count -ne 0) { $messages += [MessageData]::new([Constants]::SingleDashLine + "`r`nRemoving following ARM policies from the subscription. Total policies: $($enabledPolicies.Count)", $enabledPolicies); $errorCount = 0; $currentCount = 0; $enabledPolicies | ForEach-Object { $policyName = $_.PolicyDefinitionName; $currentCount += 1; # Remove ARM policy try { Remove-AzureRmPolicyAssignment -Name $_.PolicyDefinitionName -Scope $_.Scope -ErrorAction Stop | Out-Null Start-Sleep -Seconds 15 Remove-AzureRmPolicyDefinition -Name $_.PolicyDefinitionName -Force -ErrorAction Stop | Out-Null } catch { $messages += [MessageData]::new("Error while removing ARM policy [$policyName] from the subscription", $_, [MessageType]::Error); $errorCount += 1; } $this.CommandProgress($enabledPolicies.Count, $currentCount, 2); }; [MessageData[]] $resultMessages = @(); if($errorCount -eq 0) { #removing the version tag at AzSKRG $azskRGName = [ConfigurationManager]::GetAzSKConfigData().AzSKRGName; [Helpers]::SetResourceGroupTags($azskRGName,@{[Constants]::ARMPolicyConfigVersionTagName=$this.ARMPolicyObj.Version}, $true) $resultMessages += [MessageData]::new("All ARM policies have been removed from the subscription successfully`r`n" + [Constants]::SingleDashLine, [MessageType]::Update); } elseif($errorCount -eq $enabledPolicies.Count) { $resultMessages += [MessageData]::new("No ARM policies have been removed from the subscription due to error occurred. Please remove the ARM policies manually.`r`n" + [Constants]::SingleDashLine, [MessageType]::Error); } else { $resultMessages += [MessageData]::new("$errorCount/$($enabledPolicies.Count) ARM policy(ies) have not been removed from the subscription. Please remove the ARM policies manually or contact AzSK support team.", [MessageType]::Error); $resultMessages += [MessageData]::new("$($enabledPolicies.Count - $errorCount)/$($enabledPolicies.Count) ARM policy(ies) have been removed from the subscription successfully`r`n" + [Constants]::SingleDashLine, [MessageType]::Update); } $messages += $resultMessages; $this.PublishCustomMessage($resultMessages); } else { $noPolicyMessage = [MessageData]::new("No ARM policies have been configured by AzSK on the subscription. No ARM policies have been removed. ", [MessageType]::Warning); $messages += $noPolicyMessage; $this.PublishCustomMessage($noPolicyMessage); $azskRGName = [ConfigurationManager]::GetAzSKConfigData().AzSKRGName; [Helpers]::SetResourceGroupTags($azskRGName,@{[Constants]::ARMPolicyConfigVersionTagName=$this.ARMPolicyObj.Version}, $true) } } else { $this.PublishCustomMessage("No ARM policies have been found that matches the specified tags. Tags:[$([string]::Join(",", $this.FilterTags))].", [MessageType]::Warning); } } else { $this.PublishCustomMessage("No ARM policies found in the ARM policy file", [MessageType]::Warning); } return $messages; } [void] RemoveARMPolicies([string] $PolicyPrefix, [string] $scope) { [MessageData[]] $messages = @(); $policies = Get-AzureRmPolicyDefinition if(($policies | Measure-Object).Count -le 0) { #return if no policies are found return; } $filteredPolicies = $policies | Where-Object { $_.Name -like "$PolicyPrefix*" } if(($filteredPolicies |Measure-Object).Count -le 0) { #return if no policies are found matching the prefix return; } $policyAssignments = Get-AzureRmPolicyAssignment -Scope $scope $filteredPolicies | ForEach-Object { try{ $policy = $_; $subPolicyAssignments = @(); $subPolicyAssignments += $policyAssignments | Where-Object { $_.properties.policyDefinitionId -eq $policy.PolicyDefinitionId } if(($subPolicyAssignments | Measure-Object).Count -gt 0) { $subPolicyAssignments | ForEach-Object { Remove-AzureRmPolicyAssignment -Name $_.Name -Scope $_.properties.scope -ErrorAction Stop | Out-Null } } } catch { $this.PublishException($_); } } Start-Sleep -Seconds 15 $filteredPolicies | ForEach-Object { try{ $policy = $_; Remove-AzureRmPolicyDefinition -Id $policy.PolicyDefinitionId -Force -ErrorAction Stop | Out-Null } catch { $this.PublishException($_); } } } } class ARMPolicyModel { [string] $Version [PSObject[]] $Policies } |