diff --git a/docs/content/patterns/alz/Cleaning-up-a-Deployment.md b/docs/content/patterns/alz/Cleaning-up-a-Deployment.md index 94aa7a1dc..e8bad13eb 100644 --- a/docs/content/patterns/alz/Cleaning-up-a-Deployment.md +++ b/docs/content/patterns/alz/Cleaning-up-a-Deployment.md @@ -4,17 +4,18 @@ geekdocCollapseSection: true weight: 70 --- -In some scenarios, it may be necessary to remove everything deployed by the AMBA solution. The instructions below detail execution of a PowerShell script to delete all resources deployed, including: +In some scenarios, it might be necessary to remove everything deployed by the AMBA-ALZ solution. The instructions below detail execution of a PowerShell script to delete all resources deployed, including: - Metric Alerts - Activity Log Alerts -- Resource Groups (created for to contain alert resources) - Policy Assignments - Policy Definitions - Policy Set Definitions - Policy Assignment remediation identity role assignments +- Action Groups +- Alert Processing Rules -All resources deployed as part of the initial AMBA deployment and the resources created dynamically by 'deploy if not exist' policies are either tagged, marked in metadata, or in description (depending on what the resource supports) with the value `_deployed_by_amba` or `_deployed_by_amba=True`. This metadata is used to execute the cleanup of deployed resources; _if it has been removed or modified the cleanup script will not include those resources_. +All resources deployed as part of the initial AMBA-ALZ deployment and the resources created dynamically by 'deploy if not exist' policies are either tagged, marked in metadata, or in description (depending on what the resource supports) with the value `_deployed_by_amba` or `_deployed_by_amba=True`. This metadata is used to execute the cleanup of deployed resources; _if it has been removed or modified the cleanup script will not include those resources_. ## Cleanup Script Execution @@ -24,44 +25,54 @@ It is highly recommended to **thoroughly** test the script before running on pro ### Download the script file -Follow the instructions below to download the cleanup script file. Alternatively, clone the repo from GitHub and ensure you are working from the latest version of the file by fetching the latest `main` branch. +Execute the following instructions to download the cleanup script file. Alternatively, clone the repo from GitHub and ensure you are working from the latest version of the file by fetching the latest `main` branch. -1. Navigate AMBA [project in GitHub](https://github.com/Azure/azure-monitor-baseline-alerts) +1. Navigate the AMBA [project in GitHub](https://github.com/Azure/azure-monitor-baseline-alerts) 2. In the folder structure, browse to the `patterns/alz/scripts` directory -3. Open the **Start-AMBACleanup.ps1** script file +3. Open the **Start-AMBA-ALZ-Maintenance.ps1** script file 4. Click the **Raw** button -5. Save the open file as **Start-AMBACleanup.ps1** +5. Save the open file as **Start-AMBA-ALZ-Maintenance.ps1** ### Executing the Script 1. Open PowerShell -2. Install the **Az.ResourceGraph** module: `Install-Module Az.ResourceGraph` -3. Change directories to the location of the **Start-AMBACleanup.ps1** script -4. Configure the _**$pseudoRootManagementGroup**_ variable using the command below: +2. Make sure the following modules are installed: + 1. **Az.Accounts**: if not installed, use the `Install-Module Az.Accounts` to install it + 2. **Az.Resources**: if not installed, use the `Install-Module Az.Resources` to install it + 3. **Az.ResourceGraph**: if not installed, use the `Install-Module Az.ResourceGraph` to install it + 4. **Az.ManagedServiceIdentity**: if not installed, use the `Install-Module Az.ManagedServiceIdentity` to install it +3. Change directory to the location of the **Start-ALZ-Maintenance.ps1** script +4. Configure the _**$pseudoRootManagementGroup**_ variable using the following command: - ```powershell - $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" - ``` + ```powershell + $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" + ``` -5. Sign in to the Azure with the `Connect-AzAccount` command. The account you sign in as needs to have permissions to remove Policy Assignments, Policy Definitions, and resources at the desired Management Group scope. -6. Execute the script using one of the options below: +5. Sign in to Azure with the `Connect-AzAccount` command. The account you sign in with needs to have permissions to remove all the aforementioned resources (Policy Assignments, Policy Definitions, and other resources) at the desired Management Group scope. +6. Execute the script using one of the following options: - {{% include "PowerShell-ExecutionPolicy.md" %}} + {{% include "PowerShell-ExecutionPolicy.md" %}} - **Show output of what would happen if deletes executed:** + **Get full help on script usage help:** - ```powershell - ./Start-AMBACleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -WhatIf - ``` + ```powershell + Get-help ./Start-AMBA-ALZ-Maintenance.ps1 + ``` - **Execute the script asking for confirmation before deleting the resources deployed by AMBA-ALZ:** + **Show output of what would happen if deletes executed:** - ```powershell - ./Start-AMBACleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup - ``` + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz -WhatIf + ``` - **Execute the script without asking for confirmation before deleting the resources deployed by AMBA-ALZ.** + **Execute the script asking for confirmation before deleting the resources deployed by AMBA-ALZ:** - ```powershell - ./Start-AMBACleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -Confirm:$false - ``` + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz + ``` + + **Execute the script without asking for confirmation before deleting the resources deployed by AMBA-ALZ.** + + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz -Confirm:$false + ``` diff --git a/docs/content/patterns/alz/Disabling-Policies.md b/docs/content/patterns/alz/Disabling-Policies.md index 2dad3fd17..f259f53d9 100644 --- a/docs/content/patterns/alz/Disabling-Policies.md +++ b/docs/content/patterns/alz/Disabling-Policies.md @@ -4,7 +4,7 @@ geekdocCollapseSection: true weight: 60 --- -The policies in AMBA provide multiple methods to enable or disable the effects of the policy. +The policies included in AMBA-ALZ provide multiple methods to enable or disable the effects of the policy. 1. **Parameter: AlertState** - Determines the state of the alert rule. This either deploys an alert rule in a disabled state, or disables an already deployed alert rule at scale trough policy. 2. **Parameter: PolicyEffect** - Determines the effect of a Policy Definition, allowing a Policy to be deployed in a disabled state. @@ -46,22 +46,22 @@ The AlertState parameter is used for both compliance evaluation and configuratio } ``` -If "allOf" evaluates to true, the effect is satisfied and doesn't trigger the deployment. If you have implemented the alert rules before and want to disable an alert rule you can change the Alert State to "false", this will cause "allOf" to evaluate as false, which will trigger the deployment that changes the "enabled" property of the alert rule to false. +If "allOf" evaluates to true, the effect is satisfied and does not trigger the deployment. If you have implemented the alert rules before and want to disable an alert rule you can change the Alert State to "false", this will cause "allOf" to evaluate as false, which will trigger the deployment that changes the "enabled" property of the alert rule to false. ### Deployment steps These are the high-level steps that would need to take place: 1. Change the value for the AlertState parameter for the offending policies to false, either via command line or parameter file as described previously. -1. Deploy the policies and assignments as described previously. -1. After deploying and policy evaluation there will be a number of non-compliant policies depending on which alerts were to be disabled. These will then need to be remediated which can be done either through the portal, on a policy-by-policy basis or you can run the script found in [patterns/alz/scripts/Start-AMBARemediation](https://github.com/Azure/azure-monitor-baseline-alerts/blob/main/patterns/alz/scripts/Start-AMBARemediation.ps1) to remediate all ALZ-Monitor policies in scope as defined by management group pre-fix. +2. Deploy the policies and assignments as described previously. +3. Once the deployment is completed successfully and the policy evaluation is finished, there will be many non-compliant policies and resources depending on which alerts were to be disabled. These non-compliant resources need to be remediated which can be done either through the portal, on a policy-by-policy basis or you can run the script found in [patterns/alz/scripts/Start-AMBARemediation](https://github.com/Azure/azure-monitor-baseline-alerts/blob/main/patterns/alz/scripts/Start-AMBARemediation.ps1) to remediate all ALZ-Monitor policies in scope as defined by management group pre-fix. -Note that the above approach will not delete the alerts objects in Azure, merely disable them. To delete the alerts you will have to do so manually. Also note that while you can engage the PolicyEffect to avoid deploying new alerts, you should not do so until you have successfully remediated the above. Otherwise the policy will be disabled, and you will not be able to turn alerts off via policy until that is changed back. +Note that the preceding approach will not delete the alerts objects in Azure, merely disable them. To delete the alerts, you will have to do so manually. Also note that while you can engage the PolicyEffect to avoid deploying new alerts, you should not do so until you have successfully remediated what was mentioned earlier. Otherwise the policy will be disabled, and you will not be able to turn off alerts via policy until that is changed back. ## PolicyEffect parameter In general, we evaluate the alert rules on best practices, field experience, customer feedback, type of alert and possible impact. There are situations where disabling the policy makes sense to prevent receiving unnecessary and/ or duplicate alerts/ notifications. For example we deploy an alert rule for VPN Gateway Bandwidth Utilization, in turn we have disabled the alert rules for VPN Gateway Egress and Ingress. -The default is intended to provide a well balanced baseline. However you may want to Enable or Disable the creation of certain Alert rules to meet your needs. +The default is intended to provide a well-balanced baseline. However you may want to Enable or Disable the creation of certain Alert rules to meet your needs. ### Allowed values @@ -70,7 +70,7 @@ The default is intended to provide a well balanced baseline. However you may wan ### How it works -The PolicyEffect parameter is used for the configuration of the effect of the PolicyDefinition (in the initiatives and the example parameter file the parameter is named combining {resourceType}, {metricName} and PolicyEffect, for example ERCIRQoSDropBitsinPerSecPolicyEffect) . The value of the **PolicyEffect** parameter is passed on to the **effect** parameter which configures the effect of the Policy. +The PolicyEffect parameter is used for the configuration of the effect of the PolicyDefinition (in the initiatives and the example parameter file the parameter is named combining {resourceType}, {metricName} and PolicyEffect, for example ERCIRQoSDropBitsinPerSecPolicyEffect). The value of the **PolicyEffect** parameter is passed on to the **effect** parameter which configures the effect of the Policy. ```json "policyRule": { @@ -100,7 +100,7 @@ This will deploy policy definitions which will only be evaluated and remediated ### How it works -The policyRule only continues if "allOff" is true. Meaning, the deployment will continue as long as the MonitorDisableTagName tag doesn't exist or doesn't hold the any of the values listed in the MonitorDisableTagValues parameter. When the tag holds one of the configured values, the "allOff" will return "false" as *"notIn": "[[parameters('MonitorDisableTagValues')]"* is no longer satisfied, causing the evaluation and hence the remediation to stop. +The policyRule only continues if "allOff" is true. Meaning, the deployment will continue as long as the MonitorDisableTagName tag does not exist or does not hold any of the values listed in the MonitorDisableTagValues parameter. When the tag holds one of the configured values, the "allOff" will return "false" as *"notIn": "[[parameters('MonitorDisableTagValues')]"* is no longer satisfied, causing the evaluation and hence the remediation to stop. ```json "policyRule": { @@ -118,7 +118,7 @@ The policyRule only continues if "allOff" is true. Meaning, the deployment will }, ``` -Given the different resource scope that this method can be applied to, we made it working a little bit different when it comes to log-based alerts. For instance, the virtual machine alerts are scoped to subscription and tagging the subcription would result in disabling all the policies targeted at it. -For this reason, and thanks to the new **Bring Your Own User Assigned Managed Identity (BYO UAMI)*** included in the [2024-06-05](../../Whats-New#2024-06-05) release and to the ability to query Azure resource Graph using Azure Monitor (see [Quickstart: Create alerts with Azure Resource Graph and Log Analytics](https://learn.microsoft.com/en-us/azure/governance/resource-graph/alerts-query-quickstart?tabs=azure-resource-graph)), it is now possible to disable individual alerts for both Azure and hybrid virtual machines after they are created. We got requests to stop alerting fro virtual machines that were off for maintenance and this enhancement came up just in time. +Given the different resource scope that this method can be applied to, we made it working slightly different when it comes to log-based alerts. For instance, the virtual machine alerts are scoped to subscription and tagging the subscription would result in disabling all the policies targeted at it. +For this reason, and thanks to the new **Bring Your Own User Assigned Managed Identity (BYO UAMI)*** included in the [2024-06-05](../../Whats-New#2024-06-05) release and to the ability to query Azure resource Graph using Azure Monitor (see [Quickstart: Create alerts with Azure Resource Graph and Log Analytics](https://learn.microsoft.com/en-us/azure/governance/resource-graph/alerts-query-quickstart?tabs=azure-resource-graph)), it is now possible to disable individual alerts for both Azure and hybrid virtual machines after they are created. We got requests to stop alerting from virtual machines that were off for maintenance and this enhancement came up just in time. -Should you need to disable the alerts for your virtual machines after they are created, just make sure you tag the relevant resources accordingly. The alert queries have been modified to look at resource properties in [Azure Resource Graph](https://learn.microsoft.com/en-us/azure/governance/resource-graph/overview). If the resource contains the given tag name and tag value, it is made part of an exclusion list, so alerts will not be generated for them. This behavior allows you to dinamically and rapidly exclude the necessary resources from being alerted without the need of deleteing the alert, tag the resource and run the remediation again. +Should you need to disable the alerts for your virtual machines after they are created, just make sure you tag the relevant resources accordingly. The alert queries have been modified to look at resource properties in [Azure Resource Graph](https://learn.microsoft.com/en-us/azure/governance/resource-graph/overview). If the resource contains the given tag name and tag value, it is made part of an exclusion list, so alerts will not be generated for them. This behavior allows you to dynamically and rapidly exclude the necessary resources from being alerted without the need of deleting the alert, tag the resource and run the remediation again. diff --git a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-03-01.md b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-03-01.md index 6c008e7d3..0fb0184c4 100644 --- a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-03-01.md +++ b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-03-01.md @@ -4,41 +4,52 @@ geekdocCollapseSection: true weight: 100 --- +## Update + +Complete the activities documented in the [Steps to update to the latest release](.._index#steps-to-update-to-the-latest-release) page. + ## Post update actions Updating to release [2024-03-01](../../Whats-New#2024-03-01) will require running a post update script to remove the old Service Health action group(s) no longer in use. - To run the script, follow the following instructions: +To run the script, follow the following instructions: + +1. Open PowerShell +2. Make sure the following modules are installed: + 1. **Az.Accounts**: if not installed, use the `Install-Module Az.Accounts` to install it + 2. **Az.Resources**: if not installed, use the `Install-Module Az.Resources` to install it +3. Change directory to the location of the **Start-AMBA-ALZ-Maintenance.ps1** script +4. Configure the _**$pseudoRootManagementGroup**_ variable using the following command: - 1. Open PowerShell - 2. Install the **Az.ResourceGraph** module: `Install-Module Az.ResourceGraph` - 3. Change directories to the location of the **Start-AMBAOldArpCleanup.ps1** script - 4. Configure the _**$pseudoRootManagementGroup**_ variable using the following command: + ```powershell + $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" + ``` - ```powershell - $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" - ``` +5. Sign in to Azure with the `Connect-AzAccount` command. The account you sign in with needs to have permissions to all the aforementioned resources (Policy Assignments, Policy Definitions, and other resources) at the desired Management Group scope. +6. Execute the script using one of the following options: - 1. Sign in to the Azure with the `Connect-AzAccount` command. The account you sign in as needs to have permissions to remove Policy Assignments, Policy Definitions, and resources at the wanted Management Group scope. + {{% include "PowerShell-ExecutionPolicy.md" %}} - 2. Execute the script using one of the following options: + **Get full help on script usage help:** - {{% include "PowerShell-ExecutionPolicy.md" %}} + ```powershell + Get-help ./Start-AMBA-ALZ-Maintenance.ps1 + ``` - **Show output of what would happen if deletes executed:** + **Show output of what would happen if deletes executed:** - ```powershell - ./Start-AMBAOldArpCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -WhatIf - ``` + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems NotificationAssets -WhatIf + ``` - **Execute the script asking for confirmation before deleting old Service Health action group(s) deployed by AMBA-ALZ:** + **Execute the script asking for confirmation before deleting the resources deployed by AMBA-ALZ:** - ```powershell - ./Start-AMBAOldArpCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup - ``` + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems NotificationAssets + ``` - **Execute the script without asking for confirmation before deleting old Service Health action group(s) deployed by AMBA-ALZ.** + **Execute the script without asking for confirmation before deleting the resources deployed by AMBA-ALZ.** - ```powershell - ./Start-AMBAOldArpCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -Confirm:$false - ``` + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems NotificationAssets -Confirm:$false + ``` diff --git a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-04-12.md b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-04-12.md index 0c1c63f13..c8f8091a6 100644 --- a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-04-12.md +++ b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-04-12.md @@ -3,45 +3,50 @@ title: Updating to release 2024-04-12 geekdocCollapseSection: true weight: 99 --- + {{< hint type=Important >}} -***No post update action required*** for Greenfield customers or for Brownfield customers that prefer to continue using notification assets deployed by the ALZ pattern code. +**_No post-update action_** is required if you wish to continue using the notification assets deployed by the ALZ pattern. {{< /hint >}} -# Post update actions +## Update + +Complete the activities documented in the [Steps to update to the latest release](.._index#steps-to-update-to-the-latest-release) page. + +## Post update actions -Updating to release [2024-04-12](../../Whats-New#2024-04-12) might require running a post update script to remove the notification assets deployed by ALZ pattern ***if and only if*** customer decided to use existing action groups and alert processing rule. In this case, the Service Health alerts will be reconfigured to use the customer' action groups as per the _**B**ring **Y**our **O**wn **N**otifications_ (BYON) feature. +Updating to release [2024-04-12](../../Whats-New#2024-04-12) might require running a post update script to remove the notification assets deployed by ALZ pattern **_if and only if_** customer decided to use existing action groups and alert processing rule. In this case, the Service Health alerts will be reconfigured to use the customer' action groups as per the _**B**ring **Y**our **O**wn **N**otifications_ (BYON) feature. To run the script, complete the following step: - 1. Open PowerShell - 2. Install the **Az.ResourceGraph** module: `Install-Module Az.ResourceGraph` (if not present) - 3. Change directories to the location of the **Remove-AMBANotificationAssets.ps1** script - 4. Configure the ***$pseudoRootManagementGroup*** variable using the command below: +1. Open PowerShell +2. Install the **Az.ResourceGraph** module: `Install-Module Az.ResourceGraph` (if not present) +3. Change directories to the location of the **Remove-AMBANotificationAssets.ps1** script +4. Configure the **_$pseudoRootManagementGroup_** variable using the command below: - ```powershell - $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" - ``` + ```powershell + $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" + ``` - 1. Sign in to the Azure with the `Connect-AzAccount` command. The account you sign in as needs to have permissions to remove Policy Assignments, Policy Definitions, and resources at the desired Management Group scope. +5. Sign in to the Azure with the `Connect-AzAccount` command. The account you sign in as needs to have permissions to remove Policy Assignments, Policy Definitions, and resources at the desired Management Group scope. - 2. Execute the script using one of the options below: +6. Execute the script using one of the options below: - {{% include "PowerShell-ExecutionPolicy.md" %}} + {{% include "PowerShell-ExecutionPolicy.md" %}} - **Show output of what would happen if deletes executed:** + **Show output of what would happen if deletes executed:** - ```powershell - ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -WhatIf - ``` + ```powershell + ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -WhatIf + ``` - **Execute the script asking for confirmation before deleting notification asset resources deployed by AMBA-ALZ:** + **Execute the script asking for confirmation before deleting notification asset resources deployed by AMBA-ALZ:** - ```powershell - ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup - ``` + ```powershell + ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup + ``` - **Execute the script without asking for confirmation before deleting notification asset resources deployed by AMBA-ALZ.** + **Execute the script without asking for confirmation before deleting notification asset resources deployed by AMBA-ALZ.** - ```powershell - ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -Confirm:$false - ``` + ```powershell + ./Remove-AMBANotificationAssets.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -Confirm:$false + ``` diff --git a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-06-05.md b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-06-05.md index 23cdb541f..85018666d 100644 --- a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-06-05.md +++ b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-06-05.md @@ -3,11 +3,12 @@ title: Updating to release 2024-06-05 geekdocCollapseSection: true weight: 98 --- + {{< hint type=Important >}} -***The parameter file structure has changed to accommodate a new feature coming soon.*** +**_The parameter file structure has changed to accommodate a new feature coming soon._** {{< /hint >}} -# Pre update actions +## Pre update actions The parameter file structure has changed to accommodate a new feature coming soon. For this reason, updating from release [2024-06-05](../../Whats-New#2024-06-05) requires the alignment of the parameter file structure you have been using so far with the new one coming with the release. @@ -15,26 +16,30 @@ In particular the new parameter file has the following differences: 1. Contains new parameters for using an existing User Assigned Managed Identity or creating a new one during the AMBA-ALZ deployment. It's required by the new hybrid virtual machine alert set. Make sure to review and set the following parameters correctly: - 1. ***bringYourOwnUserAssignedManagedIdentity***: set it to **Yes** if you would like to use your own User Assigned Managed Identity (UAMI) or to **No** if you don't have one and would like the deployment of AMBA-ALZ to create one. + 1. **_bringYourOwnUserAssignedManagedIdentity_**: set it to **Yes** if you would like to use your own User Assigned Managed Identity (UAMI) or to **No** if you don't have one and would like the deployment of AMBA-ALZ to create one. - 2. ***bringYourOwnUserAssignedManagedIdentityResourceId***: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **Yes**: + 2. **_bringYourOwnUserAssignedManagedIdentityResourceId_**: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **Yes**: 1.1. Enter the UAMI resource ID, leaving the **managementSubscriptionId** blank - ![UAMI resource ID](../../media/alz-BYO-UAMI.png) + ![UAMI resource ID](../../media/alz-BYO-UAMI.png) - 1.2. Configure it with the ***Monitoring Reader*** role on the pseudo root Management Group. + 1.2. Configure it with the **_Monitoring Reader_** role on the pseudo root Management Group. - 3. ***userAssignedManagedIdentityName***: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **No**, leave the default value or set a different one to specify a different name for the UAMI created during the deployment. The provided default name aligns with the ALZ standard naming convention. + 3. **_userAssignedManagedIdentityName_**: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **No**, leave the default value or set a different one to specify a different name for the UAMI created during the deployment. The provided default name aligns with the ALZ standard naming convention. ![UAMI default name](../../media/alz-UAMI-Default-Name.png) - 4. ***managementSubscriptionId***: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **No**, enter the subscription ID of the subscription under the Management management group. The deployment procedure will create the UAMI in this subscription and assign it the ***Monitoring Reader*** role on the pseudo root Management Group + 4. **_managementSubscriptionId_**: If you set the **bringYourOwnUserAssignedManagedIdentity** parameter to **No**, enter the subscription ID of the subscription under the Management management group. The deployment procedure will create the UAMI in this subscription and assign it the **_Monitoring Reader_** role on the pseudo root Management Group ![Management subscription ID](../../media/alz-ManagementSubscription.png) ![](../../media/alz-UAMI-Management-SubscriptionID.png) -2. Changes the previous parameter objects, such as ***policyAssignmentParametersCommon***, ***policyAssignmentParametersBYON*** and ***policyAssignmentParametersNotificationAssets*** into classic parameters using the same name as before. As result, the previous sections of the parameter you'll now look like the following image: +2. Changes the previous parameter objects, such as **_policyAssignmentParametersCommon_**, **_policyAssignmentParametersBYON_** and **_policyAssignmentParametersNotificationAssets_** into classic parameters using the same name as before. As result, the previous sections of the parameter you'll now look like the following image: + + ![New parameter file sample](../../media/alz-New-ParamterFile-Structure.png) + +## Update - ![New parameter file sample](../../media/alz-New-ParamterFile-Structure.png) +Complete the activities documented in the [Steps to update to the latest release](.._index#steps-to-update-to-the-latest-release) page. diff --git a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-09-02.md b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-09-02.md index 316bc057a..2c5837293 100644 --- a/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-09-02.md +++ b/docs/content/patterns/alz/UpdateToNewReleases/Update_to_release_2024-09-02.md @@ -3,15 +3,16 @@ title: Updating to release 2024-09-02 geekdocCollapseSection: true weight: 97 --- + {{< hint type=Important >}} -***Updating to release [2024-09-02](../../Whats-New#2024-09-02) from previous releases, contains a breaking change. To perform the update, it's required to remove previously deployed policy definitions, policy set definitions, policy assignments and role assignments. As part of this release we made a script available to clean all the necessary items. ***It's strongly recommended that you test the script thoroughly before running on production environment. It isn't necessary to remove alert definitions that will continue to work in the meantime.*** +**_Updating to release [2024-09-02](../../Whats-New#2024-09-02) from previous releases, contains a breaking change. To perform the update, it's required to remove previously deployed policy definitions, policy set definitions, policy assignments and role assignments. It isn't necessary to remove alert definitions that will continue to work in the meantime._** {{< /hint >}} -# Pre update actions +## Pre update actions -Before updating to release [2024-09-02](../../Whats-New#2024-09-02), it's required to remove existing policy definitions, policy set definitions, policy assignments and role assignments. This action is required because of a breaking change caused by the redefinition of some parameters, which allows for more flexibility in disabling the policy remediation or, in some cases, the alerts. Unfortunately not all the alerts can be disabled after creation; only log-based alerts can be. Even if disabling the effect of policy was already possible in AMBA-ALZ, with this release we made sure that all the policies will honor both the ***PolicyEffect*** and the ***MonitorDisable*** parameters. +Before updating to release [2024-09-02](../../Whats-New#2024-09-02), it's required to remove existing policy definitions, policy set definitions, policy assignments and role assignments. This action is required because of a breaking change caused by the redefinition of some parameters, which allows for more flexibility in disabling the policy remediation or, in some cases, the alerts. Unfortunately not all the alerts can be disabled after creation; only log-based alerts can be. Even if disabling the effect of policy was already possible in AMBA-ALZ, with this release we made sure that all the policies will honor both the **_PolicyEffect_** and the **_MonitorDisable_** parameters. -In particular, the *MonitorDisable* feature has been redesigned to allow customer to specify they own existing tag and tag value instead of forcing a hard coded one. Given the ALZ guidance and the best practice of having a consistent tagging definition, it's only allowed to one parameter name fo r the entire deployment. Instead, parameter value can be different. You can specify an array of values assigned to the same parameter. For instance, you have the ```Environment``` tag name consistently applied to several environments, saying ```Production```, ```Test```, ```Sandbox```, and so on and you want to disable alerts for resources, which are in both ```Test``` and ```Sandbox```. Now it's possible by just configuring the parameters for tag name and tag values as reported in the sample screenshot (these are the default values) below: +In particular, the _MonitorDisable_ feature has been redesigned to allow customer to specify they own existing tag and tag value instead of forcing a hard coded one. Given the ALZ guidance and the best practice of having a consistent tagging definition, it's only allowed to one parameter name fo r the entire deployment. Instead, parameter value can be different. You can specify an array of values assigned to the same parameter. For instance, you have the `Environment` tag name consistently applied to several environments, saying `Production`, `Test`, `Sandbox`, and so on, and you want to disable alerts for resources, which are in both `Test` and `Sandbox`. Now it's possible by just configuring the parameters for tag name and tag values as reported in the sample screenshot (these are the default values) below: ![MonitorDisable* parameters](../../media/MonitorDisableParams.png) @@ -21,35 +22,48 @@ Once the policy definitions, policy set definitions, policy assignments and role To run the script, complete the following steps: - 1. Open PowerShell - 2. Install the **Az.ResourceGraph** module: `Install-Module Az.ResourceGraph` (if not present) - 3. Change directory to `patterns\alz\scripts`, there you find the **Start-AMBAPolicyInitiativesAndAssignmentsCleanup.ps1** script - 4. Configure the ***$pseudoRootManagementGroup*** variable using the following command: +1. Open PowerShell +2. Make sure the following modules are installed: + 1. **Az.Accounts**: if not installed, use the `Install-Module Az.Accounts` to install it + 2. **Az.Resources**: if not installed, use the `Install-Module Az.Resources` to install it +3. Change directory to the location of the **Start-AMBA-ALZ-Maintenance.ps1** script +4. Configure the **_$pseudoRootManagementGroup_** variable using the following command: + + ```powershell + $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" + ``` + +5. Sign in to Azure with the `Connect-AzAccount` command. The account you sign in with needs to have permissions to all the aforementioned resources (Policy Assignments, Policy Definitions, and other resources) at the desired Management Group scope. +6. Execute the script using one of the following options: + + {{% include "PowerShell-ExecutionPolicy.md" %}} + + **Get full help on script usage help:** - ```powershell - $pseudoRootManagementGroup = "The pseudo root management group id parenting the Platform and Landing Zones management groups" - ``` + ```powershell + Get-help ./Start-AMBA-ALZ-Maintenance.ps1 + ``` - 1. Sign in to the Azure with the `Connect-AzAccount` command. The account you sign in as needs to have permissions to remove policy definitions, policy set definitions, policy assignments and role assignments at the desired Management Group scope. + **Show output of what would happen if deletes executed:** - 2. Execute the script using one of the following options: + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems PolicyAssignments -WhatIf + ``` - {{% include "PowerShell-ExecutionPolicy.md" %}} + **Execute the script asking for confirmation before deleting the resources deployed by AMBA-ALZ:** - **Show output of what would happen if deletes executed:** + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems PolicyAssignments + ``` - ```powershell - ./Start-AMBAPolicyInitiativesAndAssignmentsCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -WhatIf - ``` + **Execute the script without asking for confirmation before deleting the resources deployed by AMBA-ALZ.** - **Execute the script asking for confirmation before deleting the policy definitions, policy set definitions, policy assignments and role assignments deployed by AMBA-ALZ:** + ```powershell + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems PolicyAssignments -Confirm:$false + ``` - ```powershell - ./Start-AMBAPolicyInitiativesAndAssignmentsCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup - ``` +7. Repeat the command passing the **_PolicyDefinitions_** parameter to clean up policy definitions and policy initiatives. - **Execute the script without asking for confirmation before deleting the policy definitions, policy set definitions, policy assignments and role assignments deployed by AMBA-ALZ.** +## Update - ```powershell - ./Start-AMBAPolicyInitiativesAndAssignmentsCleanup.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -Confirm:$false - ``` +Complete the activities documented in the [Steps to update to the latest release](.._index#steps-to-update-to-the-latest-release) page. diff --git a/docs/content/patterns/alz/deploy/Remediate-Policies.md b/docs/content/patterns/alz/deploy/Remediate-Policies.md index c13dbbe1b..62f0bbd92 100644 --- a/docs/content/patterns/alz/deploy/Remediate-Policies.md +++ b/docs/content/patterns/alz/deploy/Remediate-Policies.md @@ -4,7 +4,7 @@ weight: 80 --- The policies are all deploy-if-not-exists, by default, meaning that any new deployments will be influenced by them. Therefore, if you are deploying in a green field scenario and will afterwards be deploying any of the covered resource types, including subscriptions, then the policies will take effect and the relevant alert rules, action groups and alert processing rules will be created. -If you are in a brownfield scenario on the other hand, policies will be reporting non-compliance for resources in scope, but to remediate non-compliant resources you will need to initiate remediation. This can be done either through the portal, on a policy-by-policy basis or you can run the *Start-AMBARemediation.ps1* script located in the *.\patterns\alz\scripts* folder to remediate all AMBA policies in scope as defined by management group pre-fix. +If you are in a brownfield scenario on the other hand, policies will be reporting non-compliance for resources in scope, but to remediate non-compliant resources you will need to initiate remediation. This can be done either through the portal, on a policy-by-policy basis or you can run the _Start-AMBARemediation.ps1_ script located in the _.\patterns\alz\scripts_ folder to remediate all AMBA-ALZ policies in scope as defined by management group pre-fix. {{< hint type=Important >}} This script requires PowerShell 7.0 or higher and the following PowerShell modules: @@ -16,7 +16,7 @@ This script requires PowerShell 7.0 or higher and the following PowerShell modul To use the script, do the following: -- Log on to Azure PowerShell with an account with at least Resource Policy Contributor permissions at the pseudo-root management group level +- Sign in Azure PowerShell with an account with at least Resource Policy Contributor permissions at the pseudo-root management group level - Navigate to the root of the cloned repo - Set the variables - Run the remediation script @@ -36,7 +36,7 @@ To use the script, do the following: ``` - The script will return the output from the REST API calls, which should be a status code 201. If the script fails, check the error message and ensure that the management group name and policy name are correct. -- After running the script, you should be able to see a number of remediation tasks initiated at the alz-platform-management. +- After running the script, you should can see many remediation tasks started at the alz-platform-management. For convenience, assuming that the management hierarchy is fully aligned to ALZ, below are the commands required to remediate all policies assigned through the guidance provided in this repo: @@ -66,7 +66,7 @@ $LZManagementGroup="The management group id for Landing Zones" .\patterns\alz\scripts\Start-AMBARemediation.ps1 -managementGroupName $LZManagementGroup -policyName Alerting-Web ``` -Should you need to remediate just one policy definition and not the entire policy initiative, you can run the remediation script targeted at the policy reference id that can be found under [Policy Initiatives](../../Policy-Initiatives). For example, to remediate the ***Deploy AMBA Notification Assets*** policy, run the command below: +Should you need to remediate just one policy definition and not the entire policy initiative, you can run the remediation script targeted at the policy reference id that can be found under [Policy Initiatives](../../Policy-Initiatives). For example, to remediate the **_Deploy AMBA Notification Assets_** policy, run the following command: ```powershell #Run the following command to initiate remediation of a single policy definition diff --git a/patterns/alz/scripts/Start-AMBA-ALZ-Maintenance.ps1 b/patterns/alz/scripts/Start-AMBA-ALZ-Maintenance.ps1 new file mode 100644 index 000000000..b7f513d7e --- /dev/null +++ b/patterns/alz/scripts/Start-AMBA-ALZ-Maintenance.ps1 @@ -0,0 +1,570 @@ +# The below copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +<# +.DESCRIPTION + This script is intended to consolidate previous maintenance scripts. It allow customers to: + - remove ALL resources deployed by the AMBA-ALZ pattern (alerts, policy assignments, policy initiatives, policy definitions, and policy assignment role assignments) + - remove ONLY the deployment entries of AMBA-ALZ happening at the pseudo root management group level + - remove ONLY the notification assets (AGs and APRs) deployed by AMBA-ALZ + - remove ONLY alerts deployed by the AMBA-ALZ pattern + - remove ONLY policy assignments and role assignment created by the AMBA-ALZ deployment + - remove ONLY policy definitions and policy initiatives created by the AMBA-ALZ deployment + - remove ONLY orphaned alerts deployed by the AMBA-ALZ pattern + + In order for this script to function the deployed resources must have a tag _deployed_by_amba with a value of true and Policy resources must have metadata property + named _deployed_by_amba with a value of True. These tags and metadata are included in the automation, but if they are subsequently removed, there may be orphaned + resources after this script executes. + + The Role Assignments associated with Policy assignment identities and including _deployed_by_amba in the description field will also be deleted. + + This script leverages the Azure Resource Graph to find object to delete. Note that the Resource Graph lags behind ARM by a couple minutes. + +.LINK + https://github.com/Azure/azure-monitor-baseline-alerts + +.PARAMETER pseudoRootManagementGroup + Required. The pseudo root management group to start the cleanup from. This is the management group that is the parent of all the management groups that are part of the AMBA-ALZ deployment. This is the management group that the AMBA-ALZ deployment was initiated from. + +.PARAMETER cleanItems + Required. The item type we want the script to clean up. The options are: + - Amba-Alz + - Deployments + - NotificationAssets + - Alerts + - PolicyAssignments + - PolicyDefinitions + - OrphanedAlerts + +.EXAMPLE + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz -WhatIf + # show output of what would happen if deletes executed. + +.EXAMPLE + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz + # execute the script and will ask for confirmation before taking the configured action. + +.EXAMPLE + ./Start-AMBA-ALZ-Maintenance.ps1 -pseudoRootManagementGroup $pseudoRootManagementGroup -cleanItems Amba-Alz -Confirm:$false + # execute the script without asking for confirmation before taking the configured action. +#> + +[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] +param( + # the pseudo managemnt group to start from + [Parameter(Mandatory = $True, + ValueFromPipeline = $false)] + [string]$pseudoRootManagementGroup, + + # the items to be cleaned-up + [Parameter(Mandatory = $True, + ValueFromPipeline = $false)] + [ValidateSet("Amba-Alz", "Deployments", "NotificationAssets", "OrphanedAlerts", "Alerts", "PolicyAssignments", "PolicyDefinitions", IgnoreCase = $true)] + [string]$cleanItems +) + +#region general functions +Function Search-AzGraphRecursive { + # ensure query results with more than 100 resources and/or over more than 10 management groups are returned + param($query, $managementGroupNames, $skipToken) + + $optionalParams = @{} + If ($skipToken) { + $optionalParams += @{skipToken = $skipToken } + } + + # ARG will only query 10 management groups at a time--implement batching + If ($managementGroupNames.count -gt 10) { + $managementGroupBatches = @() + + For ($i = 0; $i -le $managementGroupNames.count; $i = $i + 10) { + $batchGroups = $managementGroupNames[$i..($i + 9)] + $managementGroupBatches += , @($batchGroups) + + If ($batchGroups.count -lt 10) { + continue + } + } + + $result = [System.Collections.ArrayList]::new() + ForEach ($managementGroupBatch in $managementGroupBatches) { + $batchResult = Search-AzGraph -Query $query -ManagementGroup $managementGroupBatch -Verbose:$false @optionalParams + + # resource graph returns pages of 100 resources, if there are more than 100 resources in a batch, recursively query for more + If ($batchResult.count -eq 100 -and $batchResult.SkipToken) { + [void]$result.Add($batchResult) + Search-AzGraphRecursive -query $query -managementGroupNames $managementGroupNames -skipToken $batchResult.SkipToken + } + else { + [void]$result.Add($batchResult) + } + } + } + Else { + $result = Search-AzGraph -Query $query -ManagementGroup $managementGroupNames -Verbose:$false @optionalParams + + If ($result.count -eq 100 -and $result.SkipToken) { + Search-AzGraphRecursive -query $query -managementGroupNames $managementGroupNames -skipToken $result.SkipToken + } + } + + $result +} + +Function Iterate-ManagementGroups($mg) { + + [void]$script:managementGroups.Add($mg.Name) + if ($mg.Children) { + foreach ($child in $mg.Children) { + if ($child.Type -eq 'Microsoft.Management/managementGroups') { + Iterate-ManagementGroups $child + } + } + } +} + +#endregion + +#region Get functions +Function Get-ALZ-Alerts { + # get alert resources to delete + $query = "Resources | where type in~ ('Microsoft.Insights/metricAlerts','Microsoft.Insights/activityLogAlerts', 'Microsoft.Insights/scheduledQueryRules') and tags['_deployed_by_amba'] =~ 'True' | project id" + $alertResourceIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($alertResourceIds.Count)' metric, activity log and log alerts with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $alertResourceIds +} + +Function Get-ALZ-OrphanedAlerts { + + # get AMBA-ALZ alert resources + $query = "Resources | where type in~ ('Microsoft.Insights/metricAlerts','Microsoft.Insights/activityLogAlerts', 'Microsoft.Insights/scheduledQueryRules') and tags['_deployed_by_amba'] =~ 'True' | project id, scope = tostring(properties.scopes)" + $alertResources = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups + + # get alerts without scoped resource existent + If ($alertResources.count -gt 0) { + $tempArrayList = [System.Collections.ArrayList]::new() + $orphanedAlerts = [System.Collections.ArrayList]::Synchronized($tempArrayList) + <#ForEach ($alert in $alertResources) { + $scope = $($alert.scope.replace('"]', '')).replace('["', '') + $query = "Resources | where id =~ '$scope' | project id" + $resourceId = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id + + If (-NOT $resourceId) { + $orphanedAlerts.add($alert.id) + } + }#> + + $alertResources | ForEach-Object -Parallel { + $arr = $using:orphanedAlerts + $scope = $($_.scope.replace('"]', '')).replace('["', '') + + # Filtering out alerts targeted at the subscriptions and the resource groups + if (($scope -split '/').count -gt 5) { + $resourceId = Get-AzResource -ResourceId $scope -ErrorAction SilentlyContinue + + if (-not $resourceId) { + [void]$arr.Add($_.id) + } + } + } + } + + Write-Host "- Found '$($orphanedAlerts.Count)' orphaned metric, activity log and log alerts with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $orphanedAlerts +} + +Function Get-ALZ-ResourceGroups { + # get resource group to delete + $query = "ResourceContainers | where type =~ 'microsoft.resources/subscriptions/resourcegroups' and tags['_deployed_by_amba'] =~ 'True' | project id" + $resourceGroupIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($resourceGroupIds.Count)' resource groups with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $resourceGroupIds +} + +Function Get-ALZ-PolicyAssignments { + # get policy assignments to delete + $query = "policyresources | where type =~ 'microsoft.authorization/policyAssignments' | project name,metadata=parse_json(properties.metadata),type,identity,id | where metadata._deployed_by_amba =~ 'true'" + $policyAssignmentIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($policyAssignmentIds.Count)' policy assignments with metadata '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $policyAssignmentIds +} + +Function Get-ALZ-PolicySetDefinitions { + # get policy set definitions to delete + $query = "policyresources | where type =~ 'microsoft.authorization/policysetdefinitions' | project name,metadata=parse_json(properties.metadata),type,id | where metadata._deployed_by_amba =~ 'true' | project id" + $policySetDefinitionIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($policySetDefinitionIds.Count)' policy set definitions with metadata '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $policySetDefinitionIds +} + +Function Get-ALZ-PolicyDefinitions { + # get policy definitions to delete + $query = "policyresources | where type =~ 'microsoft.authorization/policyDefinitions' | project name,metadata=parse_json(properties.metadata),type,id | where metadata._deployed_by_amba =~ 'true' | project id" + $policyDefinitionIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($policyDefinitionIds.Count)' policy definitions with metadata '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $policyDefinitionIds + +} + +Function Get-ALZ-UserAssignedManagedIdentities { + # get user assigned managed identities to delete + $query = "Resources | where type =~ 'Microsoft.ManagedIdentity/userAssignedIdentities' and tags['_deployed_by_amba'] =~ 'True' | project id, name, principalId = properties.principalId, tenantId, subscriptionId, resourceGroup" + $UamiIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Sort-Object -Property id | Get-Unique -AsString + Write-Host "- Found '$($UamiIds.Count)' user assigned managed identities with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $UamiIds +} + +Function Get-ALZ-RoleAssignments { + # get role assignments to delete + $query = "authorizationresources | where type =~ 'microsoft.authorization/roleassignments' and properties.description == '_deployed_by_amba' | project roleDefinitionId = properties.roleDefinitionId, objectId = properties.principalId, scope = properties.scope, id" + $roleAssignments = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Sort-Object -Property id | Get-Unique -AsString + Write-Host "- Found '$($roleAssignments.Count)' role assignments with description '_deployed_by_amba' to be deleted." -ForegroundColor Cyan + + # Returning items + $roleAssignments +} + +Function Get-ALZ-Deployments { + # get deployments to delete + $allDeployments = @() + ForEach ($mg in $managementGroups) { + $deployments = Get-AzManagementGroupDeployment -ManagementGroupId "$mg" -WarningAction silentlyContinue | where { $_.DeploymentName.StartsWith("amba-") } + $allDeployments += $deployments + } + Write-Host "- Found '$($allDeployments.Count)' deployments for AMBA-ALZ pattern with name starting with 'amba-' performed on the '$pseudoRootManagementGroup' Management Group hierarchy." -ForegroundColor Cyan + + # Returning items + $allDeployments +} + +Function Get-ALZ-AlertProcessingRules { + # get alert processing rules to delete + #$query = "resources | where type =~ 'Microsoft.AlertsManagement/actionRules' | where tags['_deployed_by_amba'] =~ 'True'| project id" + $query = "resources | where type =~ 'Microsoft.AlertsManagement/actionRules' | where name startswith 'apr-AMBA-' and properties.description startswith 'AMBA Notification Assets - ' and tags['_deployed_by_amba'] =~ 'True'| project id" + $alertProcessingRuleIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($alertProcessingRuleIds.Count)' alert processing rule(s) with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $alertProcessingRuleIds +} + +Function Get-ALZ-ActionGroups { + # get action groups to delete + $query = "resources | where type =~ 'Microsoft.Insights/actionGroups' | where tags['_deployed_by_amba'] =~ 'True' | project id" + $actionGroupIds = Search-AzGraphRecursive -Query $query -ManagementGroupNames $managementGroups | Select-Object -ExpandProperty Id | Sort-Object | Get-Unique + Write-Host "- Found '$($actionGroupIds.Count)' action group(s) with tag '_deployed_by_amba=True' to be deleted." -ForegroundColor Cyan + + # Returning items + $actionGroupIds +} + +#endregion + +#region Delete functions +Function Delete-ALZ-Alerts($fAlertsToBeDeleted) +{ + # delete alert resources + Write-Host "`n-- Deleting alerts ..." -foregroundcolor Yellow + $fAlertsToBeDeleted | Foreach-Object -Parallel { Remove-AzResource -ResourceId $_ -Force } | Out-Null + Write-Host "---- Done deleting alerts ..." -ForegroundColor Cyan +} + +Function Delete-ALZ-ResourceGroups($fRgToBeDeleted) +{ + # delete resource groups + Write-Host "`n-- Deleting resource groups ..." -foregroundcolor Yellow + $fRgToBeDeleted | ForEach-Object { Remove-AzResourceGroup -ResourceGroupId $_ -Confirm:$false } | Out-Null + Write-Host "---- Done deleting resource groups ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-PolicyAssignments($fPolicyAssignmentsToBeDeleted) +{ + # delete policy assignments + Write-Host "`n-- Deleting policy assignments ..." -foregroundcolor Yellow + $fPolicyAssignmentsToBeDeleted | ForEach-Object -Parallel { Remove-AzPolicyAssignment -Id $_ -Confirm:$false -ErrorAction Stop } | Out-Null + Write-Host "---- Done policy assignments ..." -foregroundcolor Cyan +} +Function Delete-ALZ-PolicySetDefinitions($fPolicySetDefinitionsToBeDeleted) +{ + # delete policy set definitions + Write-Host "`n-- Deleting policy set definitions ..." -foregroundcolor Yellow + $fPolicySetDefinitionsToBeDeleted | ForEach-Object -Parallel { Remove-AzPolicySetDefinition -Id $_ -Force } | Out-Null + Write-Host "---- Done deleting policy set definitions ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-PolicyDefinitions($fPolicyDefinitionsToBeDeleted) +{ + # delete policy definitions + Write-Host "`n-- Deleting policy definitions ..." -foregroundcolor Yellow + $fPolicyDefinitionsToBeDeleted | ForEach-Object -Parallel { Remove-AzPolicyDefinition -Id $_ -Force } | Out-Null + Write-Host "---- Done deleting policy definitions ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-RoleAssignments($fRoleAssignmentsToBeDeleted) +{ + # delete role assignments + Write-Host "`n-- Deleting role assignments ..." -foregroundcolor Yellow + $fRoleAssignmentsToBeDeleted | Select-Object -Property objectId, roleDefinitionId, scope | ForEach-Object -Parallel { Remove-AzRoleAssignment @psItem -Confirm:$false } | Out-Null + Write-Host "---- Done deleting role assignments ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-UserAssignedManagedIdentities($fUamiToBeDeleted) +{ + # delete user assigned managed identities + Write-Host "`n-- Deleting user assigned managed identities ..." -foregroundcolor Yellow + $fUamiToBeDeleted | ForEach-Object -Parallel { Remove-AzUserAssignedIdentity -ResourceGroupName $_.resourceGroup -Name $_.name -SubscriptionId $_.subscriptionId -Confirm:$false } | Out-Null + Write-Host "---- Done deleting user assigned managed identities ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-AlertProcessingRules($fAprToBeDeleted) +{ + # delete alert processing rules + Write-Host "`n-- Deleting alert processing rules ..." -foregroundcolor Yellow + $fAprToBeDeleted | Foreach-Object -Parallel { Remove-AzResource -ResourceId $_ -Force } | Out-Null + Write-Host "---- Done deleting alert processing rules ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-ActionGroups($fAgToBeDeleted) +{ + # delete action groups + Write-Host "`n-- Deleting action groups ..." -foregroundcolor Yellow + $fAgToBeDeleted | Foreach-Object -Parallel { Remove-AzResource -ResourceId $_ -Force } | Out-Null + Write-Host "---- Done deleting action groups ..." -foregroundcolor Cyan +} + +Function Delete-ALZ-Deployments($fDeploymentsToBeDeleted) +{ + # delete deployments + Write-Host "`n-- Deleting deployments ..." -foregroundcolor Yellow + $fDeploymentsToBeDeleted | ForEach-Object -Parallel { Remove-AzManagementGroupDeployment -InputObject $_ -WarningAction silentlyContinue } -throttlelimit 100 | Out-Null + Write-Host "---- Done deleting deployments ..." -foregroundcolor Cyan +} + +#endregion + +$ErrorActionPreference = 'Stop' + +If (-NOT(Get-Module -ListAvailable Az.Resources)) { + Write-Warning "This script requires the Az.Resources module." + + $response = Read-Host "Would you like to install the 'Az.Resources' module now? (y/n)" + If ($response -match '[yY]') { Install-Module Az.Resources -Scope CurrentUser } +} + +If (-NOT(Get-Module -ListAvailable Az.ResourceGraph)) { + Write-Warning "This script requires the Az.ResourceGraph module." + + $response = Read-Host "Would you like to install the 'Az.ResourceGraph' module now? (y/n)" + If ($response -match '[yY]') { Install-Module Az.ResourceGraph -Scope CurrentUser } +} + +If (-NOT(Get-Module -ListAvailable Az.ManagedServiceIdentity)) { + Write-Warning "This script requires the Az.ManagedServiceIdentity module." + + $response = Read-Host "Would you like to install the 'Az.ManagedServiceIdentity' module now? (y/n)" + If ($response -match '[yY]') { Install-Module Az.ManagedServiceIdentity -Scope CurrentUser } +} + +# get all management groups -- used in graph query scope +$managementGroups = [System.Collections.ArrayList]::new() +$allMgs = Get-AzManagementGroup -GroupName $pseudoRootManagementGroup -Expand -Recurse +foreach ($mg in $allMgs) { + Iterate-ManagementGroups $mg +} + +Write-Host "`nFound '$($managementGroups.Count)' management group(s) (including the parent one) which are part of the '$pseudoRootManagementGroup' management group hierarchy, to be queried for AMBA-ALZ resources.`n" + +If ($managementGroups.count -eq 0) { + Write-Error "The command 'Get-AzManagementGroups' returned '0' groups. This script needs to run with Owner permissions on the Azure Landing Zones intermediate root management group to effectively clean up Policies and all related resources deployed by AMBA-ALZ." +} + +Switch ($cleanItems) +{ + "Amba-Alz" + { + # Invoking function to retrieve alerts + $alertsToBeDeleted = Get-ALZ-Alerts + + # Invoking function to retrieve resource groups + $rgToBeDeleted = Get-ALZ-ResourceGroups + + # Invoking function to retrieve policy assignments + $policyAssignmentToBeDeleted = Get-ALZ-PolicyAssignments + + # Invoking function to retrieve policy set definitions + $policySetDefinitionsToBeDeleted = Get-ALZ-PolicySetDefinitions + + # Invoking function to retrieve policy definitions + $policyDefinitionsToBeDeleted = Get-ALZ-PolicyDefinitions + + # Invoking function to retrieve role assignments + $roleAssignmentsToBeDeleted = Get-ALZ-RoleAssignments + + # Invoking function to retrieve user assigned managed identities + $uamiToBeDeleted = Get-ALZ-UserAssignedManagedIdentities + + # Invoking function to retrieve alert processing rules + $aprToBeDeleted = Get-ALZ-AlertProcessingRules + + # Invoking function to retrieve action groups + $agToBeDeleted = Get-ALZ-ActionGroups + + If (($alertsToBeDeleted.count -gt 0) -or ($policyAssignmentToBeDeleted.count -gt 0) -or ($policySetDefinitionsToBeDeleted.count -gt 0) -or ($policyDefinitionsToBeDeleted.count -gt 0) -or ($roleAssignmentsToBeDeleted.count -gt 0) -or ($uamiToBeDeleted.count -gt 0) -or ($aprToBeDeleted.count -gt 0) -or ($agToBeDeleted.count -gt 0)) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete alerts, policy assignments, policy initiatives, policy definitions, policy role assignments, user assigned managed identities, alert processing rules and action groups deployed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete alerts + If ($alertsToBeDeleted.count -gt 0) { Delete-ALZ-Alerts -fAlertsToBeDeleted $alertsToBeDeleted } + + # Invoking function to delete policy assignments + If ($policyAssignmentToBeDeleted.count -gt 0) { Delete-ALZ-PolicyAssignments -fPolicyAssignmentsToBeDeleted $policyAssignmentToBeDeleted } + + # Invoking function to delete policy set definitions + If ($policySetDefinitionsToBeDeleted.count -gt 0) { Delete-ALZ-PolicySetDefinitions -fPolicySetDefinitionsToBeDeleted $policySetDefinitionsToBeDeleted } + + # Invoking function to delete policy definitions + If ($policyDefinitionsToBeDeleted.count -gt 0) { Delete-ALZ-PolicyDefinitions -fPolicyDefinitionsToBeDeleted $policyDefinitionsToBeDeleted } + + # Invoking function to delete role assignments + If ($roleAssignmentsToBeDeleted.count -gt 0) { Delete-ALZ-RoleAssignments -fRoleAssignmentsToBeDeleted $roleAssignmentsToBeDeleted } + + # Invoking function to delete user assigned managed identities + If ($uamiToBeDeleted.count -gt 0) { Delete-ALZ-UserAssignedManagedIdentities -fUamiToBeDeleted $uamiToBeDeleted } + + # Invoking function to delete alert processing rules + If ($aprToBeDeleted.count -gt 0) { Delete-ALZ-AlertProcessingRules -fAprToBeDeleted $aprToBeDeleted } + + # Invoking function to delete action groups + If ($agToBeDeleted.count -gt 0) { Delete-ALZ-ActionGroups -fAgToBeDeleted $agToBeDeleted } + + # Invoking function to delete resource groups + # If ($rgToBeDeleted -gt 0) { Delete-ALZ-ResourceGroups -fRgToBeDeleted $rgToBeDeleted } + } + } + } + + "Deployments" + { + # Invoking function to retrieve deployments + $deploymentsToBeDeleted = Get-ALZ-Deployments + + If ($deploymentsToBeDeleted.count -gt 0) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete deployments performed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete deployments + Delete-ALZ-Deployments -fDeploymentsToBeDeleted $deploymentsToBeDeleted + } + } + } + + "NotificationAssets" + { + # Invoking function to retrieve action groups + $agToBeDeleted = Get-ALZ-ActionGroups + + # Invoking function to retrieve alert processing rules + $aprToBeDeleted = Get-ALZ-AlertProcessingRules + + If (($aprToBeDeleted.count -gt 0) -or ($agToBeDeleted.count -gt 0)) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete AMBA-ALZ alert processing rules and action groups on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete alert processing rules + If ($aprToBeDeleted.count -gt 0) { Delete-ALZ-AlertProcessingRules -fAprToBeDeleted $aprToBeDeleted } + + # Invoking function to delete action groups + If ($agToBeDeleted.count -gt 0) { Delete-ALZ-ActionGroups -fAgToBeDeleted $agToBeDeleted } + } + } + } + + "Alerts" + { + # Invoking function to retrieve alerts + $alertsToBeDeleted = Get-ALZ-Alerts + + If ($alertsToBeDeleted.count -gt 0) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete alerts deployed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete alerts + Delete-ALZ-Alerts -fAlertsToBeDeleted $alertsToBeDeleted + } + } + } + + "OrphanedAlerts" + { + # Invoking function to retrieve orphaned alerts + $orphanedAlertsToDeleted = Get-ALZ-OrphanedAlerts + + If ($orphanedAlertsToDeleted.count -gt 0) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete orphaned alerts deployed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete alerts + Delete-ALZ-Alerts -fAlertsToBeDeleted $orphanedAlertsToDeleted + } + } + } + + "PolicyAssignments" + { + # Invoking function to retrieve policy assignments + $policyAssignmentsToBeDeleted = Get-ALZ-PolicyAssignments + + # Invoking function to retrieve role assignments + $roleAssignmentsToBeDeleted = Get-ALZ-RoleAssignments + + If (($policyAssignmentsToBeDeleted.count -gt 0) -or ($roleAssignmentsToBeDeleted.count -gt 0)) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete policy assignments, policy initiatives, policy definitions and policy role assignments deployed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete policy assignments + If ($policyAssignmentsToBeDeleted.count -gt 0) { Delete-ALZ-PolicyAssignments -fPolicyAssignmentsToBeDeleted $policyAssignmentsToBeDeleted } + + # Invoking function to delete role assignments + If ($roleAssignmentsToBeDeleted.count -gt 0) { Delete-ALZ-RoleAssignments -fRoleAssignmentsToBeDeleted $roleAssignmentsToBeDeleted } + } + } + } + + "PolicyDefinitions" + { + # Invoking function to retrieve policy set definitions + $policySetDefinitionsToBeDeleted = Get-ALZ-PolicySetDefinitions + + # Invoking function to retrieve policy definitions + $policyDefinitionsToBeDeleted = Get-ALZ-PolicyDefinitions + + If (($policySetDefinitionsToBeDeleted.count -gt 0) -or ($policyDefinitionsToBeDeleted.count -gt 0)) { + If ($PSCmdlet.ShouldProcess($pseudoRootManagementGroup, "Delete policy assignments, policy initiatives, policy definitions and policy role assignments deployed by AMBA-ALZ on the '$pseudoRootManagementGroup' Management Group hierarchy ..." )) { + + # Invoking function to delete policy set definitions + If ($policySetDefinitionsToBeDeleted.count -gt 0) { Delete-ALZ-PolicySetDefinitions -fPolicySetDefinitionsToBeDeleted $policySetDefinitionsToBeDeleted } + + # Invoking function to delete policy definitions + If ($policyDefinitionsToBeDeleted.count -gt 0) { Delete-ALZ-PolicyDefinitions -fPolicyDefinitionsToBeDeleted $policyDefinitionsToBeDeleted } + } + } + } +} + +Write-Host "`n=== Script execution completed. ===`n"