Get-AzureAssessResources.ps1
<#
.SYNOPSIS Gets the resources to be analysed within specified scope .EXAMPLE PS C:\Get-AzureAssessResourses -SubscriptionId 3395068f-a9b5-41a9-af54-bd362b69e19a -ResourceGroupName "rg-app-service" # Get all resource in indicated resourcegroup and subscription .EXAMPLE PS C:\Get-AzureAssessResourses -SubscriptionId 3395068f-a9b5-41a9-af54-bd362b69e19a # Get all resource for all resource groups in subscription .EXAMPLE PS C:\Get-AzureAssessResourse -MamagementGroup "myManagementGroup" # Get all ressource in all the subscriptions and resource groups under indicated management group #> $defenderforcloudchecks = @{ "VirtualMachines" = @("Microsoft.Compute/virtualMachines", "Microsoft.HybridCompute/machines") "AppServices" = @("Microsoft.Web/sites") "SqlServers" = @("Microsoft.Sql/servers", "Microsoft.Sql/sqlManagedInstances", "Microsoft.AzureArcData/sqlServers", "Microsoft.AzureArcData/sqlManagedInstances") "SqlServerVirtualMachines" = @("Microsoft.SqlVirtualMachine/sqlVirtualMachines") "OpenSourceRelationalDatabases" = @("Microsoft.DBforMySQL/servers","Microsoft.DBforPostgreSQL/servers","Microsoft.DBforMariaDB/servers","Microsoft.AzureArcData/postgresInstances") "CosmosDbs" = @("Microsoft.DocumentDB/databaseAccounts") "StorageAccounts" = @("Microsoft.Storage/storageAccounts") "ContainerRegistry" = @("Microsoft.ContainerRegistry/registries") "KubernetesService" = @("Microsoft.ContainerService/managedCluster", "Microsoft.ContainerService/connectedCluster") "Containers" = @("Microsoft.ContainerRegistry/registries", "Microsoft.ContainerService/managedCluster", "Microsoft.ContainerService/connectedCluster") "KeyVaults" = @("Microsoft.KeyVault/vaults") "DNS" = @() "Arm" = @() } function Get-AzureAssessResources() { [CmdletBinding(DefaultParameterSetName="SubnRg")] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1, ParameterSetName="SubnRg")] [string]$SubscriptionId, [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 2, ParameterSetName="SubnRg")] [string]$ResourceGroupName, [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 2, ParameterSetName="MgmtGrp")] [string[]]$ManagementGroupNames, [Parameter(Mandatory = $false)] [validateSet("Microsoft.Web/sites", "Microsoft.Web/serverFarms", "Microsoft.Network/privateEndpoints","Microsoft.Storage/storageAccounts","Microsoft.Sql/servers","Microsoft.KeyVault/vaults","Microsoft.Compute/virtualMachines")] [string[]]$ResourceTypes = ("Microsoft.Web/sites", "Microsoft.Web/serverFarms", "Microsoft.Network/privateEndpoints","Microsoft.Storage/storageAccounts","Microsoft.Sql/servers","Microsoft.KeyVault/vaults","Microsoft.Compute/virtualMachines") ) # Initialize CSV files for collected resources $privateendpointscsv = Join-Path -Path "." -ChildPath "privateendpoints.csv" $webappscsv = Join-Path -Path "." -ChildPath "webapps.csv" $appserviceplanscsv = Join-Path -Path "." -ChildPath "appserviceplans.csv" $storagecsv = Join-Path -Path "." -ChildPath "storages.csv" $sqlserverscsv = Join-Path -Path "." -ChildPath "sqlservers.csv" $keyvaultscsv = Join-Path -Path "." -ChildPath "keyvaults.csv" $virtualmachinescsv = Join-Path -Path "." -ChildPath "virtualmachines.csv" $managementgroupscsv = Join-Path -Path "." -ChildPath "managementgroups.csv" $subscriptionscsv = Join-Path -Path "." -ChildPath "subscriptions.csv" $resourcegroupscsv = Join-Path -Path "." -ChildPath "resourcegroups.csv" $securityrecommendationscsv = Join-Path -Path "." -ChildPath "securityrecommendations.csv" $roleassignmentscsv = Join-Path "." -ChildPath "roleassignments.csv" Write-Output "Initializing csv files" # Initialize CSV files with headers if ($ResourceTypes -contains "Microsoft.Network/privateEndpoints") { "Id,ResourceGroupId,Type,Name,Link,Location,ServiceSubscriptionId,ServiceResourceGroupName,ServiceProvider,ServiceName" | Out-File -FilePath $privateendpointscsv -Force } if ($ResourceTypes -contains "Microsoft.Web/sites") { "Id,ResourceGroupId,Type,Name,Link,Location,PublicNetworkAccess,HasFirewallRules,HasPrivateEndpoint,State,DefaultHostName,HttpsOnly,MinTlsVersion,FtpsState,AppServiceEnvironementInbound" | Out-File -FilePath $webappscsv -Force } if ($ResourceTypes -contains "Microsoft.Web/serverFarms") { "Id,ResourceGroupId,Type,Name,Link,Location,Sku,AppServiceEnvironementInbound" | Out-File -FilePath $appserviceplanscsv -Force } if ($ResourceTypes -contains "Microsoft.Storage/storageAccounts") { "Id,ResourceGroupId,Type,Name,Link,Location,PublicNetworkAccess,HasFirewallRules,HasPrivateEndpoint,Sku,MinimumTlsVersion,EnableHttpsTrafficOnly,AllowBlobPublicAccess,InfrastructureEncryption,ServiceEncryption" | Out-File -FilePath $storagecsv -Force } if ($ResourceTypes -contains "Microsoft.Sql/servers") { "Id,ResourceGroupId,Type,Name,Link,Location,PublicNetworkAccess,HasFirewallRules,HasPrivateEndpoint,FullyQualifiedDomainName,MinimalTlsVersion,AdministratorType,EntraOnlyAuth" | Out-File -FilePath $sqlserverscsv -Force } if ($ResourceTypes -contains "Microsoft.KeyVault/vaults") { "Id,ResourceGroupId,Type,Name,Link,Location,PublicNetworkAccess,HasFirewallRules,HasPrivateEndpoint,VaultUri,EnableSoftDelete,EnablePurgeProtection" | Out-File -FilePath $keyvaultscsv -Force } if ($ResourceTypes -contains "Microsoft.Compute/virtualMachines") { "Id,ResourceGroupId,Type,Name,Link,Location,PublicNetworkAccess,HasFirewallRules,HasPrivateEndpoint,HasOpenSSHorRDP,VmSize,PublicIp" | Out-File -FilePath $virtualmachinescsv -Force } "ResourceGroupId,ResourceId,ResourceType,ResourceName,Recommendation,Description,Severity" | Out-File -FilePath $securityrecommendationscsv -Force if ($PSCmdlet.ParameterSetName -eq "MgmtGrp") { "ManagementGroup" | Out-File -FilePath $managementgroupscsv -Force } "ManagementGroup,Id,Name,Link,DefenderForVirtualMachines,DefenderForAppServices,DefenderForSqlServers,DefenderForSqlServerVirtualMachines,DefenderForOpenSourceDBs,DefenderForCosmosDbs,DefenderForStorageAccounts,DefenderForContainerRegistry,DefenderForKubernetesService,DefenderForContainers,DefenderForKeyVaults,DefenderForDNS,DefenderForArm,HasVirtualMachines,HasAppServices,HasSqlServers,HasSqlServerVirtualMachines,HasOpenSourceDBs,HasCosmosDbs,HasStorageAccounts,HasContainerRegistry,HasKubernetesService,HasContainers,HasKeyVaults" | Out-File -FilePath $subscriptionscsv -Force "SubscriptionId,Id,Name,Link" | Out-File -FilePath $resourcegroupscsv -Force "roleId,role,principalId,principalType,scope,source,resourceType,resourceName,link" | Out-File -FilePath $roleassignmentscsv -Force Write-Output "Get subscriptions ids" $SubscriptionIds = @() $context = get-azcontext if ($PSCmdlet.ParameterSetName -eq "SubnRg") { $SubscriptionIds += "" | Select-Object @{N="ManagementGroup";E={$null}},@{N="SubscriptionId";E={$SubscriptionId}} } elseif ($PSCmdlet.ParameterSetName -eq "MgmtGrp") { foreach($ManagementGroupName in $ManagementGroupNames) { # Expand all management groups and subscriptions under the indicated management group $SubscriptionIds += Get-AzManagementGroupSubscription -GroupName $ManagementGroupName | Select-Object @{N="ManagementGroup";E={$ManagementGroupName}},@{N="SubscriptionId";E={($_.Id -split "/")[-1]}} "" | Select-Object @{N="ManagementGroup";E={$ManagementGroupName}} | Export-Csv -Path $managementgroupscsv -NoTypeInformation -Append } } # Message that collection is starting for the number of subscriptions Write-Output "Perparing collection for $($SubscriptionIds.Count) subscriptions" # Expand all subscriptions and their ressource groups $collections = @() $resourcegroupinfos = @() $subscriptionsinfos = @() foreach($CurrentSubscription in $SubscriptionIds) { $ManagementGroupName = $CurrentSubscription.ManagementGroup $SubscriptionName = (Set-AzContext -Subscription $CurrentSubscription.SubscriptionId).Subscription.Name # get defender for cloud informations $defenderforcloud = @{} $defenderforcloudres = @{} $securitypricing = @(Get-AzSecurityPricing) foreach($defenderforcloudcheck in $defenderforcloudchecks.Keys) { $defenderforcloud[$defenderforcloudcheck] = ($securitypricing | Where-Object {$_.Name -eq $defenderforcloudcheck}).PricingTier -eq "Standard" # check resources presences $defenderforcloudres[$defenderforcloudcheck] = ($defenderforcloudchecks[$defenderforcloudcheck]).Count -eq 0 if ($defenderforcloudres[$defenderforcloudcheck] -eq $false) { $jobs = @() foreach($defenderforcloudreskey in $defenderforcloudchecks[$defenderforcloudcheck]) { $jobs += invoke-azrestmethod -AsJob -method "GET" -path "/subscriptions/$($CurrentSubscription.SubscriptionId)/resources?`$filter=resourceType+eq+'$defenderforcloudreskey'&`$top=1&api-version=2023-07-01" } $res = $jobs | Wait-Job | Receive-Job | Where-Object { $_.StatusCode -eq 200 } | ForEach-Object { $_.Content | ConvertFrom-Json } | Select-Object -ExpandProperty value $defenderforcloudres[$defenderforcloudcheck] = $res.Count -gt 0 } } $subscriptionsinfos += "" | select-object ` @{N="ManagementGroup";E={$ManagementGroupName}}, ` @{N="Id";E={$CurrentSubscription.SubscriptionId}}, ` @{N="Name";E={$SubscriptionName}}, ` @{N="Link";E={"https://portal.azure.com/#@$($context.Tenant.Id)/resource/subscriptions/$($CurrentSubscription.SubscriptionId)"}}, ` @{N="DefenderForVirtualMachines";E={$defenderforcloud["VirtualMachines"]}}, ` @{N="DefenderForAppServices";E={$defenderforcloud["AppServices"]}}, ` @{N="DefenderForSqlServers";E={$defenderforcloud["SqlServers"]}}, ` @{N="DefenderForSqlServerVirtualMachines";E={$defenderforcloud["SqlServerVirtualMachines"]}}, ` @{N="DefenderForOpenSourceDBs";E={$defenderforcloud["OpenSourceRelationalDatabases"]}}, ` @{N="DefenderForCosmosDbs";E={$defenderforcloud["CosmosDbs"]}}, ` @{N="DefenderForStorageAccounts";E={$defenderforcloud["StorageAccounts"]}}, ` @{N="DefenderForContainerRegistry";E={$defenderforcloud["ContainerRegistry"]}}, ` @{N="DefenderForKubernetesService";E={$defenderforcloud["KubernetesService"]}}, ` @{N="DefenderForContainers";E={$defenderforcloud["Containers"]}}, ` @{N="DefenderForKeyVaults";E={$defenderforcloud["KeyVaults"]}}, ` @{N="DefenderForDNS";E={$defenderforcloud["DNS"]}}, ` @{N="DefenderForArm";E={$defenderforcloud["Arm"]}}, ` @{N="HasVirtualMachines";E={$defenderforcloudres["VirtualMachines"]}}, ` @{N="HasAppServices";E={$defenderforcloudres["AppServices"]}}, ` @{N="HasSqlServers";E={$defenderforcloudres["SqlServers"]}}, ` @{N="HasSqlServerVirtualMachines";E={$defenderforcloudres["SqlServerVirtualMachines"]}}, ` @{N="HasOpenSourceDBs";E={$defenderforcloudres["OpenSourceRelationalDatabases"]}}, ` @{N="HasCosmosDbs";E={$defenderforcloudres["CosmosDbs"]}}, ` @{N="HasStorageAccounts";E={$defenderforcloudres["StorageAccounts"]}}, ` @{N="HasContainerRegistry";E={$defenderforcloudres["ContainerRegistry"]}}, ` @{N="HasKubernetesService";E={$defenderforcloudres["KubernetesService"]}}, ` @{N="HasContainers";E={$defenderforcloudres["Containers"]}}, ` @{N="HasKeyVaults";E={$defenderforcloudres["KeyVaults"]}} $ResourceGroupNames = @($ResourceGroupName) if (($PSCmdlet.ParameterSetName -eq "SubnRg" -and !$ResourceGroupName) -or $PSCmdlet.ParameterSetName -eq "MgmtGrp") { $ResourceGroupNames = Invoke-RetryCommand { Get-AzResourceGroup } | foreach-object { $_.ResourceGroupName } } foreach($CurrentResourceGroupName in $ResourceGroupNames) { $resourcegroupinfos += "" | select-object @{N="SubscriptionId";E={$CurrentSubscription.SubscriptionId}},@{N="Id";E={"/subscriptions/$($CurrentSubscription.SubscriptionId)/resourceGroups/$CurrentResourceGroupName"}},@{N="Name";E={$CurrentResourceGroupName}},@{N="Link";E={"https://portal.azure.com/#@$($context.Tenant.Id)/resource/subscriptions/$($CurrentSubscription.SubscriptionId)/resourceGroups/$CurrentResourceGroupName"}} } } # save subscriptions infos $subscriptionsinfos | Export-Csv -Path $subscriptionscsv -NoTypeInformation -Append # save resourcegroup infos $resourcegroupinfos | Export-Csv -Path $resourcegroupscsv -NoTypeInformation -Append # use job queries $jobs = @() $cnt = 0 foreach($ResourceType in $ResourceTypes) { foreach($ResourceGroupInfo in $resourcegroupinfos) { $jobs += Invoke-AzRestMethod -AsJob -Method GET -Path "/subscriptions/$($ResourceGroupInfo.SubscriptionId)/resourceGroups/$($ResourceGroupInfo.Name)/resources?`$filter=resourceType+eq+'$($ResourceType)'&`$top=1&api-version=2021-04-01" if ($jobs.Count -ge 20) { $cnt += $jobs.Count $collections += $jobs | wait-job | Receive-Job | Where-Object {($_.StatusCode -eq 200 -and $_.Content -ne "{`"value`":[]}")} | ForEach-Object { ($_.Content | convertfrom-json).Value[0].id } | Select-Object @{N="SubscriptionId";E={($_ -split "/")[2]}},@{N="ResourceGroupName";E={($_ -split "/")[4]}},@{N="ResourceType";E={($_ -split "/")[6..7] -join "/"}} Write-Progress -Activity "checking resources collection" -Status "$cnt of $($ResourceTypes.Count * $ResourceGroupInfos.Count)" -PercentComplete (($cnt / ($ResourceTypes.Count * $ResourceGroupInfos.Count))*100) $jobs = @() } } } $cnt += $jobs.Count $collections += $jobs | wait-job | Receive-Job | Where-Object {($_.StatusCode -eq 200 -and $_.Content -ne "{`"value`":[]}")} | ForEach-Object { ($_.Content | convertfrom-json).Value[0].id } | Select-Object @{N="SubscriptionId";E={($_ -split "/")[2]}},@{N="ResourceGroupName";E={($_ -split "/")[4]}},@{N="ResourceType";E={($_ -split "/")[6..7] -join "/"}} Write-Progress -Activity "checking resources collection" -Status "$cnt of $($ResourceTypes.Count * $ResourceGroupInfos.Count)" -PercentComplete (($cnt / ($ResourceTypes.Count * $ResourceGroupInfos.Count))*100) # adding role assignement to the collections $collections += $resourcegroupinfos | Select-Object SubscriptionId,@{N="ResourceGroupName";E={$_.Name}},@{N="ResourceType";E={"roles"}} # sort by subscription id to limit context changes $collections = $collections | Sort-Object -Property SubscriptionId # Start the collections showing a progress bar for($colid = 0; $colid -lt $collections.Count; $colid += 1) { $SubscriptionId = $collections[$colid].SubscriptionId $ResourceGroupName = $collections[$colid].ResourceGroupName $ResourceType = $collections[$colid].ResourceType if ($ResourceType -eq "Microsoft.Network/privateEndpoints") { # Get all private endpoints job Get-AzureAssessResPrivateEndpoints -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $privateendpointscsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.Web/sites") { # Get all webapps job Get-AzureAssessResWebApps -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $webappscsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.Web/serverFarms") { # Get all app service plans job Get-AzureAssessResAppServicePlans -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $appserviceplanscsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.Storage/storageAccounts") { # Get all storage accounts job Get-AzureAssessResStorages -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $storagecsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.Sql/servers") { # Get all sql servers job Get-AzureAssessResSqlServers -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $sqlserverscsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.KeyVault/vaults") { # Get all key vaults and export to csv Get-AzureAssessResKeyVaults -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $keyvaultscsv -NoTypeInformation -Append } if ($ResourceType -eq "Microsoft.Compute/virtualMachines") { # Get all virualmachines and export to csv Get-AzureAssessResVirtualMachines -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $virtualmachinescsv -NoTypeInformation -Append } if ($ResourceType -eq "roles") { # Get all role assignements and export to csv Get-AzureAssessPrivilegedRoleAssignments -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName | Export-Csv -Path $roleassignmentscsv -NoTypeInformation -Append } # Get all Defender for cloud recommendations Get-AzureAssessResSecurityRecommendations -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName -ResourceType $ResourceType | Export-Csv -Path $securityrecommendationscsv -NoTypeInformation -Append Write-Progress -Activity "Collecting resources" -Status "$colid of $($collections.Count)" -PercentComplete ($colid / $collections.Count * 100) } # Add information about private endpoints Join-AzureAssessPrivateEndpoints # remove duplicates from role assignements $uniqueroleassignments = Get-Content $roleassignmentscsv | ConvertFrom-Csv | Sort-Object | Get-Unique -AsString -CaseInsensitive $uniqueroleassignments | Export-Csv -Path $roleassignmentscsv -NoTypeInformation -Force } # SIG # Begin signature block # MIIRWAYJKoZIhvcNAQcCoIIRSTCCEUUCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAfwOXqdDa2FpeS # 0Y7YzEJnlkIrdyaoUHb5v403pVw346CCDZIwgga5MIIEoaADAgECAhEAmaOACiZV # O2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNV # BAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBD # ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQg # TmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIxOFowVjEL # MAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEk # MCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5cTbq96y34 # vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7VS5+djSo # McbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1PH9ud0IF+ # njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOouu9Tj1yHI # ohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv8aGUsRda # CtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtMLK+Wo837 # Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9lDV2nT8m # FSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/JHuurfTI # 5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkKbWpQ5bou # fUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADaCi2JSplK # ShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAWd18Jx5n8 # 58JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFN10 # XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8+tT4HKbR # Og79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAwBgNVHR8E # KTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsG # AQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVt # LmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0 # bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6 # Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhYD+WPUCia # U58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUStJl490L9 # 4C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChDUyuQy6rG # DxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiRsWrhWM2f # 8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7bWRLDm0Cd # Y9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mATwZWwSD+B # 7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3/bFAEloM # U+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESYkOh1/w1t # VxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR+x+zPF/2 # DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C+xN4YaNj # t2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qwt4HOUBCr # W602NCmvO1nm+/80nLy5r0AZvCQxaQ4wggbRMIIEuaADAgECAhBNn7NsFkgeJAAl # SKxTsSjWMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhB # c3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNp # Z25pbmcgMjAyMSBDQTAeFw0yNDAxMTYxMjAwMzRaFw0yNTAxMTUxMjAwMzNaMHcx # CzAJBgNVBAYTAkJFMRgwFgYDVQQIDA9XYWxsb29uIEJyYWJhbnQxHjAcBgNVBAoM # FU9wZW4gU291cmNlIERldmVsb3BlcjEuMCwGA1UEAwwlT3BlbiBTb3VyY2UgRGV2 # ZWxvcGVyLCBDZWRyaWMgQmxvbWFydDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBALp1WzPLBGmSjvJ2se9K+HWIzxlPIh9vmddaj0Sc6Yz3jJizVN7WphR7 # 1kR4KFEfCFL6eleZlIkqDMkNfwBTpfVCx7MYR85YSceHo8ieEIV5MmWSZ1CR36/A # wXrUvXzlX85Rf/RuotfluSmdhTRoBbCN9aIsSm50pEZixvUOcipTNZbuY29NvjXP # JAH1RX0od6QYCGt/v+5C+hBippk+QohxmKQYLilh4+58fdZvnXaKPvEuEpbhXCeh # /HbASrvTbZXXbh8fMbHOq+xnCemK/6aqjfqgRzkXn9unjl6wj6KT7MoEp1tCn+9z # cmi/zW3KeI3Alld5B6IEvVfZVmaCrvSsRBNFnVpVg5eGQNRyan0xfblEwKLrsoNk # WhUtJY3SD53kvz8OHBKRY1quaq70UefcIDuPq4+76CVovjbpT/wnmP6PFnHtNrDj # KzMAnUWOeseIcDhp7ETzVyoh2rWofTpXUr5aEau5mkXs0MclqjimMeWf0r3NyBa5 # E3k0rG/xtpmTFB9e4w7b0VQUxNUcVdmocGL7Rj4ouWLjUDUkiE2DctxMTaPmqKJE # nx8cFsBCrDmgNYxGOZ03ykPmPbwc3SooZeS5rRmR4v2GTVrbsmbiiggtYDjhJddo # sC/TtJ+65JL48oTHDK1KVMtSjUBr/Q16Nzg0JaXfiZ4JS+MX45ylAgMBAAGjggF4 # MIIBdDAMBgNVHRMBAf8EAjAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jY3Nj # YTIwMjEuY3JsLmNlcnR1bS5wbC9jY3NjYTIwMjEuY3JsMHMGCCsGAQUFBwEBBGcw # ZTAsBggrBgEFBQcwAYYgaHR0cDovL2Njc2NhMjAyMS5vY3NwLWNlcnR1bS5jb20w # NQYIKwYBBQUHMAKGKWh0dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jY3NjYTIw # MjEuY2VyMB8GA1UdIwQYMBaAFN10XUwA23ufoHTKsW73PMAywHDNMB0GA1UdDgQW # BBQ2dBi+EnTsl++Xmrax5h7dyzC12TBLBgNVHSAERDBCMAgGBmeBDAEEATA2Bgsq # hGgBhvZ3AgUBBDAnMCUGCCsGAQUFBwIBFhlodHRwczovL3d3dy5jZXJ0dW0ucGwv # Q1BTMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG # 9w0BAQsFAAOCAgEAZm3wL05QNFh25ll601jtST553L2VVS4ugvlHmX90PSOkjmX3 # jQ2ERwdz9MHWhoOvW1EdOrBlm31YRt2GmCz4/82vq9fTTNwLSzk3csHEIgHuAbN1 # INCVgz0l7Ya7mkxFLHoZ4BJ9LluS4p2NjvU9r7OGnBCgfFaLriC+qRY8QxCeMQOl # l1BTTaUBMp0pgxh3XOOxOQfNeFCkXg0q4QULkaRuApJFZi/pY+PMA6p8bjOTP4YI # 9VNsoc7ReBYMDL588oupc1CTiDaf0e6YaN80z6WoIGuNja3VPDEG4VmWZG+Of9gO # XUNllvR8n1IXXsvWEuHRTCV9jjK89NHGaNroeXHr1C6eERnoNUPbEuIb/parUnGB # n5MKWL+2TlL9Z34lSFz6e1Efi4oJeDznUojNZKJzOMvBS+JJyr0aVuW4lDoqbqkl # 9vFLjHi1oGM7mBrlL8AHEC3iUNEOwgPcbsIYAqV85RyXYNQqLu1ik1MmmpKy/Tma # Mmi/AiXxtjC6RrnrkN6tIHR7Nky9b5jWfMxCCG2b119gr7SkJ8qVOH8I9oBxMDPR # IjBi5rEjSbDOCpRhZiqmx7K7gW2Gyp1OCIffVyiqmeZh+YLxpdP0tymxtqg/HVqV # If3xn0Sgl7HcUpcRkY3EgTPUqNaVzOSO5h8KyzA9nVtUX2XwSx9C4vb6uqcxggMc # MIIDGAIBATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBT # eXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBD # QQIQTZ+zbBZIHiQAJUisU7Eo1jANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3 # AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG # AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCC5yQ+VJJ7j # 0tBYYVKSqYLfUM4hQsMeAaI2hShopDUpfzANBgkqhkiG9w0BAQEFAASCAgAGry8Y # TU335LkDYwj1g2PfEuAbf8/FcL8OK8dXjAYfEvEZBvj/DM9iYRRuX9kok3VZdoEM # nXzrZaYcZJNcjeDGSa65tp4QteC5wu6VH3mjc0ZqkUplxyzIZ7Wn+ZynrMJK9h30 # ZpC7vtOtQ93TARYSGLevqCFFwQX6WWqIqwJ+dAtpzBrNta4IRbiQXYb0gEWLAQQ2 # gsKyyU5btpTdrnbVDjcaj2mb8IdqTCJIW656PuZxLxjb9u5Sqq4hX+O3CPlm+3kA # 9FPyr7LEseDcOkFXzUSluDIzM1FJHFexQgBTvF8gfjhEzXDzGA3x5umFYyU+A3IG # DYKgSGKDYXdgDY4TesfBddLTWAE3P2Bgio1fePZmsHHjdacwyt/3U1sUeBNAYcmZ # GBI/oXVH/ZDpH5IAMK9+PtYPHqaBhZ/xFHusANBERS7VDCE4O2rKQ2xySdHkqTGa # l6k/lI5WGrh4b7coV9xt2E7/qmdkR3eQU+o2IErI0h0siNf5XiVATcR3riBcO2dO # K8jxT0ZO874sb6VRtPoXsuQxa32Wqzm4MQfApL+LW2WkcTfqkZMxsL/G9Z0MB81Z # /Bxcbx1ZV/Lg7lg4GNmss3CPD1UcZ4VbIn8JJlY4Q+qFV8fNPAw6qvNuZWnG7gVR # BpGHmneFn2oK8Aeykkp02p8RJPLMxxl2ytGEaQ== # SIG # End signature block |