diff --git a/arm/Microsoft.Automation/automationAccounts/.parameters/parameters.json b/arm/Microsoft.Automation/automationAccounts/.parameters/parameters.json index 8eb92bdbc8..4284a511cc 100644 --- a/arm/Microsoft.Automation/automationAccounts/.parameters/parameters.json +++ b/arm/Microsoft.Automation/automationAccounts/.parameters/parameters.json @@ -76,85 +76,85 @@ } ] }, - // "linkedWorkspaceId": { - // "value": "/subscriptions/<>/resourcegroups/test-rg/providers/Microsoft.OperationalInsights/workspaces/test-law" - // }, - // "gallerySolutions": { - // "value": [ - // "Updates" - // ] - // }, - // "softwareUpdateConfigurations": { - // "value": [ - // { - // "name": "Windows_ZeroDay", - // "frequency": "Month", - // "operatingSystem": "Windows", - // "rebootSetting": "IfRequired", - // "scopeByTags": { - // "Update": [ - // "Automatic-Wave1" - // ] - // }, - // "maintenanceWindow": "PT4H", - // "updateClassifications": [ - // "Critical", - // "Security", - // "UpdateRollup", - // "FeaturePack", - // "ServicePack", - // "Definition", - // "Tools", - // "Updates" - // ], - // "includeUpdates": [ - // "654321" - // ], - // "excludeUpdates": [ - // "123456" - // ], - // "interval": 1, - // "monthlyOccurrences": [ - // { - // "occurrence": 3, - // "day": "Friday" - // } - // ], - // "startTime": "22:00" - // }, - // { - // "name": "Linux_ZeroDay", - // "frequency": "OneTime", - // "operatingSystem": "Linux", - // "rebootSetting": "IfRequired", - // "maintenanceWindow": "PT4H", - // "updateClassifications": [ - // "Critical", - // "Security", - // "Other" - // ], - // "includeUpdates": [ - // "kernel" - // ], - // "excludeUpdates": [ - // "icacls" - // ], - // "startTime": "2021-12-31T06:00" - // } - // ] - // }, - // "privateEndpoints": { - // "value": [ - // { - // "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-005-privateEndpoints", - // "service": "Webhook" - // }, - // { - // "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-005-privateEndpoints", - // "service": "DSCAndHybridWorker" - // } - // ] - // }, + "linkedWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-sxx-az-law-x-001" + }, + "gallerySolutions": { + "value": [ + "Updates" + ] + }, + "softwareUpdateConfigurations": { + "value": [ + { + "name": "Windows_ZeroDay", + "frequency": "Month", + "operatingSystem": "Windows", + "rebootSetting": "IfRequired", + "scopeByTags": { + "Update": [ + "Automatic-Wave1" + ] + }, + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "UpdateRollup", + "FeaturePack", + "ServicePack", + "Definition", + "Tools", + "Updates" + ], + "includeUpdates": [ + "654321" + ], + "excludeUpdates": [ + "123456" + ], + "interval": 1, + "monthlyOccurrences": [ + { + "occurrence": 3, + "day": "Friday" + } + ], + "startTime": "22:00" + }, + { + "name": "Linux_ZeroDay", + "frequency": "OneTime", + "operatingSystem": "Linux", + "rebootSetting": "IfRequired", + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "Other" + ], + "includeUpdates": [ + "kernel" + ], + "excludeUpdates": [ + "icacls" + ], + "startTime": "2021-12-31T06:00" + } + ] + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-005-privateEndpoints", + "service": "Webhook" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-005-privateEndpoints", + "service": "DSCAndHybridWorker" + } + ] + }, "systemAssignedIdentity": { "value": true }, diff --git a/utilities/pipelines/resourceRemoval/Remove-DeployedModule.ps1 b/utilities/pipelines/resourceRemoval/Remove-DeployedModule.ps1 index 3c288be8e8..8398641a2d 100644 --- a/utilities/pipelines/resourceRemoval/Remove-DeployedModule.ps1 +++ b/utilities/pipelines/resourceRemoval/Remove-DeployedModule.ps1 @@ -39,6 +39,18 @@ } Remove-VirtualMachine @inputObject -Verbose } + 'automationAccounts' { + Write-Verbose 'Run automation account removal script' -Verbose + # Load function + . (Join-Path $PSScriptRoot 'helper' 'Remove-AutomationAccount.ps1') + + # Invoke removal + $inputObject = @{ + deploymentName = $deploymentName + ResourceGroupName = $ResourceGroupName + } + Remove-AutomationAccount @inputObject -Verbose + } default { Write-Verbose 'Run default removal script' -Verbose # Load function diff --git a/utilities/pipelines/resourceRemoval/helper/Remove-AutomationAccount.ps1 b/utilities/pipelines/resourceRemoval/helper/Remove-AutomationAccount.ps1 new file mode 100644 index 0000000000..8867a18695 --- /dev/null +++ b/utilities/pipelines/resourceRemoval/helper/Remove-AutomationAccount.ps1 @@ -0,0 +1,124 @@ +<# +.SYNOPSIS +Remove Automation account, Log analytics link and Update solution deployed with a given deployment name. Resources will be removed even if Log Analytics is in a different resource group than the Automation Account + +.DESCRIPTION +Remove Automation account, Log analytics link and Update solution deployed with a given deployment name. Resources will be removed even if Log Analytics is in a different resource group than the Automation Account + +.PARAMETER deploymentName +Mandatory. The deployment name to use and find resources to remove + +.PARAMETER searchRetryLimit +Optional. The maximum times to retry the search for resources via their removal tag + +.PARAMETER searchRetryInterval +Optional. The time to wait in between the search for resources via their remove tags + +.EXAMPLE +Remove-AutomationAccount -deploymentname 'aa-12345' + +Remove Automation account, Log analytics link and Update solution deployed starting with the deployment name 'aa-12345'. +#> +function Remove-AutomationAccount { + + [Cmdletbinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory = $true)] + [string] $deploymentName, + + [Parameter(Mandatory = $false)] + [string] $ResourceGroupName = 'validation-rg', + + [Parameter(Mandatory = $false)] + [int] $searchRetryLimit = 40, + + [Parameter(Mandatory = $false)] + [int] $searchRetryInterval = 60 + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + + # Load helper + . (Join-Path $PSScriptRoot 'Remove-Resource.ps1') + } + + process { + + # Identify resources + # ------------------ + $searchRetryCount = 1 + do { + $deployments = Get-AzResourceGroupDeploymentOperation -DeploymentName $deploymentName -ResourceGroupName $resourceGroupName -ErrorAction 'SilentlyContinue' + if ($deployments) { + break + } + Write-Verbose ('[Failure] not to find Automation Account deployment resources by name [{0}] in scope [{1}]. Retrying in [{2}] seconds [{3}/{4}]' -f $deploymentName, $deploymentScope, $searchRetryInterval, $searchRetryCount, $searchRetryLimit) -Verbose + Start-Sleep $searchRetryInterval + $searchRetryCount++ + } while ($searchRetryCount -le $searchRetryLimit) + + if (-not $deployments) { + throw "No deployment found for [$deploymentName]" + } + + $resourcesToRemove = @() + $unorderedResourceIds = $deployments.TargetResource | Where-Object { $_ -and $_ -notmatch '/deployments/' } + $childDeploymentsIds = $deployments.TargetResource | Where-Object { $_ -and $_ -match '/deployments/' } + + foreach ($childDeploymentId in $childDeploymentsIds) { + $searchRetryCount = 1 + $childDeploymentTokens = $childDeploymentId.Split('/') + $childDeploymentName = $childDeploymentTokens[8] + $childDeploymentResourceGroup = $childDeploymentTokens[4] + do { + Write-Verbose ('Searching child deployment named [{0}] in resource group [{1}]. Attempt [{2}/{3}]' -f $childDeploymentName, $childDeploymentResourceGroup, $searchRetryCount, $searchRetryLimit) -Verbose + $childDeployment = Get-AzResourceGroupDeploymentOperation -DeploymentName $childDeploymentName -ResourceGroupName $childDeploymentResourceGroup -ErrorAction 'SilentlyContinue' + if ($childDeployment) { + Write-Verbose ('[Success] Child deployment named [{0}] in resource group [{1}] found' -f $childDeploymentName, $childDeploymentResourceGroup) -Verbose + $unorderedResourceIds += $childDeployment.TargetResource + break + } + Write-Verbose ('[Failure] Did not to find child deployment named [{0}] in resource group [{1}]. Retrying in [{2}] seconds [{3}/{4}]' -f $childDeploymentName, $childDeploymentResourceGroup, $searchRetryInterval, $searchRetryCount, $searchRetryLimit) -Verbose + Start-Sleep $searchRetryInterval + $searchRetryCount++ + } while ($searchRetryCount -le $searchRetryLimit) + } + + $unorderedResourceIds = $unorderedResourceIds | Where-Object { $_ ` + -and ($_ -notmatch '/Microsoft.Insights/diagnosticSettings/') ` + -and ($_ -notmatch '/variables/') ` + -and ($_ -notmatch '/softwareUpdateConfigurations/') ` + -and ($_ -notmatch '/jobSchedules/') ` + -and ($_ -notmatch '/schedules/') ` + -and ($_ -notmatch '/runbooks/') ` + -and ($_ -notmatch '/modules/') ` + -and ($_ -notmatch '/Microsoft.Authorization/roleAssignments/') ` + } | Select-Object -Unique + + $orderedResourceIds = @( + $unorderedResourceIds | Where-Object { $_ -match 'Microsoft.OperationsManagement/solutions/Updates' } + $unorderedResourceIds | Where-Object { $_ -match 'linkedServices/automation' } + $unorderedResourceIds | Where-Object { $_ -match 'Microsoft.Insights/diagnosticSettings' } + $unorderedResourceIds | Where-Object { $_ -match 'Microsoft.Automation/automationAccounts' } + ) + + $resourcesToRemove = $orderedResourceIds | ForEach-Object { + @{ + resourceId = $_ + name = $_.Split('/')[-1] + type = $_.Split('/')[6..7] -join '/' + } + } + + # Remove resources + # ---------------- + if ($PSCmdlet.ShouldProcess(('[{0}] resources' -f $resourcesToRemove.Count), 'Remove')) { + Remove-Resource -resourceToRemove $resourcesToRemove -Verbose + } + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +}