Framework/Core/SubscriptionSecurity/ARMPolicy.ps1

using namespace System.Management.Automation
Set-StrictMode -Version Latest 

# Class to implement Subscription ARM Policy controls
class ARMPolicy: CommandBase
{    
    hidden [PSObject[]] $Policy = $null;
    
    hidden [PSObject[]] $ApplicableARMPolicies = $null;
    #hidden [PSObject[]] $PolicyAssignments = $null;

    ARMPolicy([string] $subscriptionId, [InvocationInfo] $invocationContext, [string] $tags): 
        Base($subscriptionId, $invocationContext)
    { 
        $this.Policy = [array] $this.LoadServerConfigFile("Subscription.ARMPolicies.json"); 
        $this.FilterTags = $this.ConvertToStringArray($tags) | Select-Object -Unique;
    }

    hidden [PSObject[]] GetApplicableARMPolices()
    {
        if($null -eq $this.ApplicableARMPolicies)
        {
            $this.ApplicableARMPolicies = @();

            $subscriptionId = $this.SubscriptionContext.SubscriptionId;
            if(($this.FilterTags | Measure-Object).Count -ne 0)
            {
                $this.Policy | 
                    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[]] SetARMPolicy()
    {    
        [MessageData[]] $messages = @();
        if(($this.Policy | 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: Configuring 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. 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);                                            

                    $errorCount = 0;
                    $currentCount = 0;
                    $enabledPolicies | ForEach-Object {
                        $policyName = $_.PolicyDefinitionName;
                        $currentCount += 1;
                        # Add ARM policy
                        try
                        {
                            $armPolicy = New-AzureRmPolicyDefinition -Name $_.PolicyDefinitionName -Description $_.Description -Policy ([string]$_.PolicyDefinition) -ErrorAction Stop 
                            Start-Sleep -Seconds 10
                            New-AzureRmPolicyAssignment -Name $_.PolicyDefinitionName -PolicyDefinition $armPolicy -Scope $_.Scope -ErrorAction Stop | Out-Null
                        }
                        catch
                        {
                            $messages += [MessageData]::new("Error while adding ARM policy [$policyName] to the subscription", $_, [MessageType]::Error);
                            $errorCount += 1;
                        }

                        $this.CommandProgress($enabledPolicies.Count, $currentCount, 5);
                    };

                    [MessageData[]] $resultMessages = @();
                    if($errorCount -eq 0)
                    {
                        $resultMessages += [MessageData]::new("All ARM policies have been added to the subscription successfully`r`n" + [Constants]::SingleDashLine, [MessageType]::Update);
                    }
                    elseif($errorCount -eq $enabledPolicies.Count)
                    {
                        $resultMessages += [MessageData]::new("No ARM policies have been added to the subscription due to error occured. Please add the ARM policies manually.`r`n" + [Constants]::SingleDashLine, [MessageType]::Error);
                    }
                    else
                    {
                        $resultMessages += [MessageData]::new("[$errorCount] ARM policies have not been added to the subscription. Please add the ARM policies manually.", [MessageType]::Error);
                        $resultMessages += [MessageData]::new("[$($enabledPolicies.Count - $errorCount)] ARM policies 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[]] RemoveARMPolicy()
    {    
        [MessageData[]] $messages = @();
        if(($this.Policy | 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);
                }

                $enabledPolicies = @();
                $enabledPolicies += $this.GetApplicableARMPolices() | Where-Object { $_.Enabled };
                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 10
                            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, 5);
                    };

                    [MessageData[]] $resultMessages = @();
                    if($errorCount -eq 0)
                    {
                        $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 occured. Please remove the ARM policies manually.`r`n" + [Constants]::SingleDashLine, [MessageType]::Error);
                    }
                    else
                    {
                        $resultMessages += [MessageData]::new("[$errorCount] ARM policies have not been removed from the subscription. Please remove the ARM policies manually.", [MessageType]::Error);
                        $resultMessages += [MessageData]::new("[$($enabledPolicies.Count - $errorCount)] ARM policies have been removed from 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;
    }

}