functions/Invoke-AzOpsPull.ps1
function Invoke-AzOpsPull { <# .SYNOPSIS Setup a repository for the AzOps workflow, based off templates and an existing Azure deployment. .DESCRIPTION Setup a repository for the AzOps workflow, based off templates and an existing Azure deployment. .PARAMETER IncludeResourcesInResourceGroup Discover only resources in these resource groups. .PARAMETER IncludeResourceType Discover only specific resource types. .PARAMETER SkipChildResource Skip childResource discovery. .PARAMETER SkipPim Skip discovery of Privileged Identity Management resources. .PARAMETER SkipLock Skip discovery of resource lock resources. .PARAMETER SkipPolicy Skip discovery of policies. .PARAMETER SkipRole Skip discovery of role. .PARAMETER SkipResourceGroup Skip discovery of resource groups .PARAMETER SkipResource Skip discovery of resources inside resource groups. .PARAMETER Rebuild Delete all AutoGeneratedTemplateFolderPath folders inside AzOpsState directory. .PARAMETER Force Delete $script:AzOpsState directory. .PARAMETER StatePath The root folder under which to write the resource json. .EXAMPLE > Invoke-AzOpsPull Setup a repository for the AzOps workflow, based off templates and an existing Azure deployment. #> [CmdletBinding()] [Alias("Initialize-AzOpsRepository")] param ( [string[]] $IncludeResourcesInResourceGroup = (Get-PSFConfigValue -FullName 'AzOps.Core.IncludeResourcesInResourceGroup'), [string[]] $IncludeResourceType = (Get-PSFConfigValue -FullName 'AzOps.Core.IncludeResourceType'), [switch] $SkipChildResource = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipChildResource'), [switch] $SkipPim = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipPim'), [switch] $SkipLock = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipLock'), [switch] $SkipPolicy = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipPolicy'), [switch] $SkipResource = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipResource'), [switch] $SkipResourceGroup = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipResourceGroup'), [string[]] $SkipResourceType = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipResourceType'), [switch] $SkipRole = (Get-PSFConfigValue -FullName 'AzOps.Core.SkipRole'), [switch] $Rebuild, [switch] $Force, [string] $StatePath = (Get-PSFConfigValue -FullName 'AzOps.Core.State'), [string] $TemplateParameterFileSuffix = (Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix') ) begin { #region Prepare if (-not $SkipPim) { try { Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.UserRole' $null = Get-AzADUser -First 1 -ErrorAction Stop Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.UserRole.Success' Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.AADP2' $servicePlanName = "AAD_PREMIUM_P2" $subscribedSkus = Invoke-AzRestMethod -Uri https://graph.microsoft.com/v1.0/subscribedSkus -ErrorAction Stop $subscribedSkusValue = $subscribedSkus.Content | ConvertFrom-Json -Depth 100 | Select-Object value if ($servicePlanName -in $subscribedSkusValue.value.servicePlans.servicePlanName) { Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.Validating.AADP2.Success' } else { Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.AADP2.Failed' $SkipPim = $true } } catch { Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.UserRole.Failed' $SkipPim = $true } } if ($false -eq $SkipChildResource -or $false -eq $SkipResource -and $true -eq $SkipResourceGroup) { Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.Validating.ResourceGroupDiscovery.Failed' -LogStringValues "`n" } $resourceTypeDiff = Compare-Object -ReferenceObject $SkipResourceType -DifferenceObject $IncludeResourceType -ExcludeDifferent if ($resourceTypeDiff) { Write-AzOpsMessage -LogLevel Warning -LogString 'Invoke-AzOpsPull.SkipResourceType.Failed' -LogStringValues $($resourceTypeDiff.InputObject) $IncludeResourceType = $IncludeResourceType | Where-Object { $_ -notin $resourceTypeDiff.InputObject } } Assert-AzOpsInitialization -Cmdlet $PSCmdlet -StatePath $StatePath $tenantId = (Get-AzContext).Tenant.Id Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Tenant' -LogStringValues $tenantId Write-AzOpsMessage -LogLevel Verbose -LogString 'Invoke-AzOpsPull.TemplateParameterFileSuffix' -LogStringValues (Get-PSFConfigValue -FullName 'AzOps.Core.TemplateParameterFileSuffix') Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Initialization.Completed' $stopWatch = [System.Diagnostics.Stopwatch]::StartNew() #endregion Initialize & Prepare } process { #region Existing Content if (Test-Path $StatePath) { $migrationRequired = (Get-ChildItem -Recurse -Force -Path $StatePath -File | Where-Object { $_.Name -like $("Microsoft.Management_managementGroups-" + $tenantId + $TemplateParameterFileSuffix) } | Select-Object -ExpandProperty FullName -First 1) -notmatch '\((.*)\)' if ($migrationRequired) { Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Migration.Required' } if ($Force -or $migrationRequired) { Invoke-PSFProtectedCommand -ActionString 'Invoke-AzOpsPull.Deleting.State' -ActionStringValues $StatePath -Target $StatePath -ScriptBlock { Remove-Item -Path $StatePath -Recurse -Force -Confirm:$false -ErrorAction Stop } -EnableException $true -PSCmdlet $PSCmdlet } if ($Rebuild) { Invoke-PSFProtectedCommand -ActionString 'Invoke-AzOpsPull.Rebuilding.State' -ActionStringValues $StatePath -Target $StatePath -ScriptBlock { Get-ChildItem -Path $StatePath -File -Recurse -Force -Filter 'Microsoft.*_*.json' | Remove-Item -Force -Recurse -Confirm:$false -ErrorAction Stop } -EnableException $true -PSCmdlet $PSCmdlet } } #endregion Existing Content #region Root Scopes $rootScope = '/providers/Microsoft.Management/managementGroups/{0}' -f $tenantId if ($script:AzOpsPartialRoot.id) { $rootScope = $script:AzOpsPartialRoot.id | Sort-Object -Unique } # Parameters $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Inherit -Include IncludeResourcesInResourceGroup, IncludeResourceType, SkipPim, SkipLock, SkipPolicy, SkipRole, SkipResourceGroup, SkipChildResource, SkipResource, SkipResourceType, StatePath Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Building.State' -LogStringValues $StatePath if ($rootScope -and $script:AzOpsAzManagementGroup) { foreach ($root in $rootScope) { # Create AzOpsState structure recursively Save-AzOpsManagementGroupChild -Scope $root -StatePath $StatePath Get-AzOpsResourceDefinition -Scope $root @parameters } } else { # If no management groups are found, iterate through each subscription foreach ($subscription in $script:AzOpsSubscriptions) { ConvertTo-AzOpsState -Resource (Get-AzSubscription -SubscriptionId $subscription.subscriptionId) -StatePath $StatePath Get-AzOpsResourceDefinition -Scope $subscription.id @parameters } } #endregion Root Scopes } end { $stopWatch.Stop() Write-AzOpsMessage -LogLevel Important -LogString 'Invoke-AzOpsPull.Duration' -LogStringValues $stopWatch.Elapsed -Metric $stopWatch.Elapsed.TotalSeconds -MetricName 'AzOpsPull Time' Clear-PSFMessage } } |