Invoke-MSGovernanceDataCollection.ps1
<#
.SYNOPSIS Collect Data for Azure AD Governance Workshop .DESCRIPTION Collect Data for Azure AD Governance Workshop .EXAMPLE PS C:\>Invoke-WorkshopDataCollection Collect Data for Azure AD Governance Workshop #> function Invoke-MSGovernanceDataCollection { [CmdletBinding(SupportsShouldProcess = $true)] param ( # Output Directory [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $OutputDirectory, # Tenant name for connecting to SharePoint Online. For example, "https://<TenantName>-admin.sharepoint.com/" [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $TenantName, # Tenant identifier to use when connecting to MS Graph. [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $TenantId = 'organizations', # Skip Report Output [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $SkipReportOutput, # Prompt for user confirmation before collecting optional data. [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $Prompt ) begin { New-Variable -Name stackProgressId -Scope Script -Value (New-Object System.Collections.Generic.Stack[int]) -ErrorAction SilentlyContinue $stackProgressId.Clear() $stackProgressId.Push(0) $PromptChoices = @( New-Object System.Management.Automation.Host.ChoiceDescription -ArgumentList "&Yes", "Yes, collect the data." New-Object System.Management.Automation.Host.ChoiceDescription -ArgumentList "&No", "No, skip this." ) } process { Write-Output 'Connecting to Microsoft Graph...' #Connect-MgGraph -TenantId $TenantId -Scopes 'Directory.AccessAsUser.All' Connect-MgGraph -TenantId $TenantId -Scopes 'Organization.Read.All', 'User.Read.All', 'Application.Read.All', 'RoleManagement.Read.All', 'AppRoleAssignment.ReadWrite.All', 'Policy.Read.All', 'AuditLog.Read.All', 'EntitlementManagement.Read.All' | Out-Null ## Get Tenant Settings $MsGraphContextData = Get-MgContext Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $MsGraphContextData.TenantId) -Status 'Tenant Domains' -PercentComplete 0 $OrganizationData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri 'organization' -QueryParameters @{ #'$select' = ('id', 'verifiedDomains') -join ',' } $OrganizationData = $OrganizationData | ForEach-Object { [pscustomobject]$_ } $InitialTenantDomain = $OrganizationData.verifiedDomains | ForEach-Object { [pscustomobject]$_ } | Where-Object isInitial -EQ $true | Select-Object -ExpandProperty name -First 1 if (!$TenantName) { $TenantName = $InitialTenantDomain.Replace('.onmicrosoft.com', '') } ## Create Output Directory $OutputDirectory = Join-Path $OutputDirectory $InitialTenantDomain Assert-DirectoryExists $OutputDirectory | Out-Null ## Output Tenant Context and Domain Data $OutputPath = Join-Path $OutputDirectory 'MsGraphContext.xml' $MsGraphContextData | Export-Clixml -Path $OutputPath -Force $OutputPath = Join-Path $OutputDirectory 'Organization.xml' $OrganizationData | Export-Clixml -Path $OutputPath -Force #$OutputPath = Join-Path $OutputDirectory 'TenantDomains.xml' #$TenantDomainData | Export-Clixml -Path $OutputPath -Force ## Get SharePoint Settings Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'SharePoint Online Settings' -PercentComplete 5 Write-Output 'Connecting to SharePoint Online Admin PowerShell...' Connect-SPOService -Url ('https://{0}-admin.sharepoint.com/' -f $TenantName) $OutputPath = Join-Path $OutputDirectory 'SpoSettings.xml' $SpoSettingsData = Get-SPOTenant $SpoSettingsData | Export-Clixml -Path $OutputPath -Force ## Get Teams Settings Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Microsoft Teams Settings' -PercentComplete 10 $OutputPath = Join-Path $OutputDirectory 'TeamsSettings.xml' try { Write-Output 'Connecting to Microsoft Teams Admin PowerShell...' Connect-MicrosoftTeams #$CsSession = New-CsOnlineSession -OverrideAdminDomain $InitialTenantDomain $TeamsSettingsData = Get-CsTeamsClientConfiguration #$TeamsSettingsData = Invoke-Command -Session $CsSession -ScriptBlock { Get-CsTeamsClientConfiguration } } finally { Disconnect-MicrosoftTeams #Remove-PSSession $CsSession } $TeamsSettingsData | Export-Clixml -Path $OutputPath -Force ## Get Entitlement Management Settings Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Entitlement Management Settings' -PercentComplete 15 $OutputPath = Join-Path $OutputDirectory 'ElmSettings.xml' $ElmSettingsData = Get-MsgraphResult -ApiVersion beta -RelativeUri 'identityGovernance/entitlementManagement/settings' -Select (('externalUserLifecycleAction', 'daysUntilExternalUserDeletedAfterBlocked') -join ',') $ElmSettingsData | Export-Clixml -Path $OutputPath -Force ## Get User Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Users' -PercentComplete 20 $OutputPath = Join-Path $OutputDirectory 'Users.xml' [string[]] $SourceAttributes = 'id', 'userPrincipalName', 'userType', 'accountEnabled', 'displayName', 'givenName', 'surname', 'mail', 'jobTitle', 'companyName', 'country', 'creationType', 'externalUserState', 'externalUserStateChangeDateTime', 'createdDateTime', 'deletedDateTime', 'refreshTokensValidFromDateTime', 'signInSessionsValidFromDateTime', 'signInActivity' $UserData = Get-MsgraphResult -ApiVersion beta -RelativeUri 'users' -Select ($SourceAttributes -join ',') -QueryParameters @{ '$count' = 'true' '$filter' = 'userType eq ''Guest'' or endsWith(userPrincipalName, ''#EXT#@{0}'')' -f $InitialTenantDomain } $UserData = $UserData | ForEach-Object { [pscustomobject]$_ } $UserData | Export-Clixml -Path $OutputPath -Force ## Get Applications/Service Principals Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Service Principals' -PercentComplete 30 $OutputPath = Join-Path $OutputDirectory 'ServicePrincipals.xml' [string[]] $SourceAttributes = 'id', 'appId', 'servicePrincipalType', 'accountEnabled', 'displayName', 'appRoles', 'appRoleAssignmentRequired', 'appOwnerOrganizationId', 'tags', 'createdDateTime', 'deletedDateTime' $ServicePrincipalData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri 'servicePrincipals' -Select ($SourceAttributes -join ',') -QueryParameters @{ #'$count' = 'true' #'$filter' = 'appOwnerOrganizationId ne ''f8cdef31-a31e-4b4a-93e4-5f571e91255a''' } $ServicePrincipalData = $ServicePrincipalData | ForEach-Object { [pscustomobject]$_ } $ServicePrincipalData | Export-Clixml -Path $OutputPath -Force ## Get User Directory Role Assignments Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Directory Role Assignments' -PercentComplete 40 if (!$Prompt -or (Write-HostPrompt "Confirm" "Do you want to collect user directory role assignment data?" -DefaultChoice 0 -Choices $PromptChoices) -eq 0) { $OutputPath = Join-Path $OutputDirectory 'DirectoryRoleAssignments.xml' [string[]] $SourceAttributes = 'id', 'displayName', 'description', 'roleTemplateId', 'createdDateTime', 'deletedDateTime' $listDirectoryRoleAssignmentData = New-Object System.Collections.Generic.List[hashtable] Use-Progress -InputObjects $UserData -Activity "User Processing" -Property userPrincipalName -ScriptBlock { $User = $args[0] [hashtable[]] $DirectoryRoleAssignmentData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri ('users/{0}/memberOf' -f $User.id) -Select ($SourceAttributes -join ',') foreach ($DirectoryRoleAssignment in $DirectoryRoleAssignmentData) { $DirectoryRoleAssignment.Add('userId', $User.id) $DirectoryRoleAssignment.Add('userPrincipalName', $User.userPrincipalName) $DirectoryRoleAssignment.Add('userDisplayName', $User.displayName) $DirectoryRoleAssignment.Add('userType', $User.userType) } if ($DirectoryRoleAssignmentData) { $listDirectoryRoleAssignmentData.AddRange($DirectoryRoleAssignmentData) } } $DirectoryRoleAssignmentData = $listDirectoryRoleAssignmentData | ForEach-Object { [pscustomobject]$_ } $DirectoryRoleAssignmentData | Where-Object '@odata.type' -EQ '#microsoft.graph.directoryRole' | Export-Clixml -Path $OutputPath -Force } ## Get User App Role Assignments Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'App Role Assignments' -PercentComplete 50 if (!$Prompt -or (Write-HostPrompt "Confirm" "Do you want to collect user application role assignment data?" -DefaultChoice 0 -Choices $PromptChoices) -eq 0) { $OutputPath = Join-Path $OutputDirectory 'AppRoleAssignments.xml' #[string[]] $SourceAttributes = 'id', 'principalType', 'principalId', 'principalDisplayName', 'resourceId', 'resourceDisplayName', 'appRoleId', 'createdDateTime', 'deletedDateTime' $listAppRoleAssignmentData = New-Object System.Collections.Generic.List[hashtable] Use-Progress -InputObjects $UserData -Activity "User Processing" -Property userPrincipalName -ScriptBlock { $User = $args[0] [hashtable[]] $AppRoleAssignmentData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri ('users/{0}/appRoleAssignments' -f $User.id) foreach ($AppRoleAssignment in $AppRoleAssignmentData) { $AppRoleAssignment.Add('userId', $User.id) $AppRoleAssignment.Add('userPrincipalName', $User.userPrincipalName) $AppRoleAssignment.Add('userDisplayName', $User.displayName) $AppRoleAssignment.Add('userType', $User.userType) } if ($AppRoleAssignmentData) { $listAppRoleAssignmentData.AddRange($AppRoleAssignmentData) } } $AppRoleAssignmentData = $listAppRoleAssignmentData | ForEach-Object { [pscustomobject]$_ } $AppRoleAssignmentData | Export-Clixml -Path $OutputPath -Force } ## Get User Team Membership Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Team Memberships' -PercentComplete 60 if (!$Prompt -or (Write-HostPrompt "Confirm" "Do you want to collect user Teams access data?" -DefaultChoice 0 -Choices $PromptChoices) -eq 0) { $OutputPath = Join-Path $OutputDirectory 'TeamMemberships.xml' [string[]] $SourceAttributes = 'id', 'displayName', 'description', 'classification', 'guestSettings', 'createdDateTime', 'deletedDateTime' $listTeamMembershipData = New-Object System.Collections.Generic.List[hashtable] Use-Progress -InputObjects $UserData -Activity "User Processing" -Property userPrincipalName -ScriptBlock { $User = $args[0] [hashtable[]] $TeamMembershipData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri ('users/{0}/joinedTeams' -f $User.id) -Select ($SourceAttributes -join ',') foreach ($Team in $TeamMembershipData) { $Team.Add('userId', $User.id) $Team.Add('userPrincipalName', $User.userPrincipalName) $Team.Add('userDisplayName', $User.displayName) $Team.Add('userType', $User.userType) } if ($TeamMembershipData) { $listTeamMembershipData.AddRange($TeamMembershipData) } } $TeamMembershipData = $listTeamMembershipData | ForEach-Object { [pscustomobject]$_ } $TeamMembershipData | Export-Clixml -Path $OutputPath -Force } ## Get Conditional Access Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'Conditional Access Policies' -PercentComplete 70 $OutputPath = Join-Path $OutputDirectory 'ConditionalAccessPolicies.xml' $ConditionalAccessPolicyData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri 'identity/conditionalAccess/policies' $ConditionalAccessPolicyData = $ConditionalAccessPolicyData | ForEach-Object { [pscustomobject]$_ } $ConditionalAccessPolicyData | Export-Clixml -Path $OutputPath -Force ## Get User Signin Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'User Sign-in Logs' -PercentComplete 80 if (!$Prompt -or (Write-HostPrompt "Confirm" "Do you want to collect user sign-in log data?" -DefaultChoice 0 -Choices $PromptChoices) -eq 0) { $OutputPath = Join-Path $OutputDirectory 'SignInLogs.xml' $listSignInData = New-Object System.Collections.Generic.List[hashtable] Use-Progress -InputObjects $UserData -Activity "User Processing" -Property userPrincipalName -ScriptBlock { $User = $args[0] [hashtable[]] $SignInData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri 'auditLogs/signIns' -Filter ("userId eq '{0}'" -f $User.id) if ($SignInData) { $listSignInData.AddRange($SignInData) } } $SignInData = $listSignInData | ForEach-Object { [pscustomobject]$_ } $SignInData | Export-Clixml -Path $OutputPath -Force } ## Get User Audit Data Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Status 'User Audit Logs' -PercentComplete 90 if (!$Prompt -or (Write-HostPrompt "Confirm" "Do you want to collect user audit log data?" -DefaultChoice 0 -Choices $PromptChoices) -eq 0) { $OutputPath = Join-Path $OutputDirectory 'AuditLogs.xml' $listAuditData = New-Object System.Collections.Generic.List[hashtable] Use-Progress -InputObjects $UserData -Activity "User Processing" -Property userPrincipalName -ScriptBlock { $User = $args[0] [hashtable[]] $AuditData = Get-MsgraphResult -ApiVersion 'v1.0' -RelativeUri 'auditLogs/directoryaudits' -Filter ("initiatedBy/user/id eq '{0}'" -f $User.id) if ($AuditData) { $listAuditData.AddRange($AuditData) } } $AuditData = $listAuditData | ForEach-Object { [pscustomobject]$_ } $AuditData | Export-Clixml -Path $OutputPath -Force } ## Complete Write-Progress -Id 0 -Activity ('Microsoft Governance Workshop Data Collection - {0}' -f $InitialTenantDomain) -Completed ## Package Output Compress-Archive (Join-Path $OutputDirectory '\*') -DestinationPath "$OutputDirectory.zip" -Force ## Generate Reports if (!$SkipReportOutput) { Export-WorkshopReports -DataDirectory $OutputDirectory } } end { Disconnect-MgGraph Disconnect-SPOService Disconnect-MicrosoftTeams } } # SIG # Begin signature block # MIInlQYJKoZIhvcNAQcCoIInhjCCJ4ICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAf37Hqx8i35HWa # W+3FMsaXGdHCKnFYLBPfJc7sGbfEw6CCDXYwggX0MIID3KADAgECAhMzAAACy7d1 # OfsCcUI2AAAAAALLMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NTU5WhcNMjMwNTExMjA0NTU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC3sN0WcdGpGXPZIb5iNfFB0xZ8rnJvYnxD6Uf2BHXglpbTEfoe+mO//oLWkRxA # wppditsSVOD0oglKbtnh9Wp2DARLcxbGaW4YanOWSB1LyLRpHnnQ5POlh2U5trg4 # 3gQjvlNZlQB3lL+zrPtbNvMA7E0Wkmo+Z6YFnsf7aek+KGzaGboAeFO4uKZjQXY5 # RmMzE70Bwaz7hvA05jDURdRKH0i/1yK96TDuP7JyRFLOvA3UXNWz00R9w7ppMDcN # lXtrmbPigv3xE9FfpfmJRtiOZQKd73K72Wujmj6/Su3+DBTpOq7NgdntW2lJfX3X # a6oe4F9Pk9xRhkwHsk7Ju9E/AgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUrg/nt/gj+BBLd1jZWYhok7v5/w4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzQ3MDUyODAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJL5t6pVjIRlQ8j4dAFJ # ZnMke3rRHeQDOPFxswM47HRvgQa2E1jea2aYiMk1WmdqWnYw1bal4IzRlSVf4czf # zx2vjOIOiaGllW2ByHkfKApngOzJmAQ8F15xSHPRvNMmvpC3PFLvKMf3y5SyPJxh # 922TTq0q5epJv1SgZDWlUlHL/Ex1nX8kzBRhHvc6D6F5la+oAO4A3o/ZC05OOgm4 # EJxZP9MqUi5iid2dw4Jg/HvtDpCcLj1GLIhCDaebKegajCJlMhhxnDXrGFLJfX8j # 7k7LUvrZDsQniJZ3D66K+3SZTLhvwK7dMGVFuUUJUfDifrlCTjKG9mxsPDllfyck # 4zGnRZv8Jw9RgE1zAghnU14L0vVUNOzi/4bE7wIsiRyIcCcVoXRneBA3n/frLXvd # jDsbb2lpGu78+s1zbO5N0bhHWq4j5WMutrspBxEhqG2PSBjC5Ypi+jhtfu3+x76N # mBvsyKuxx9+Hm/ALnlzKxr4KyMR3/z4IRMzA1QyppNk65Ui+jB14g+w4vole33M1 # pVqVckrmSebUkmjnCshCiH12IFgHZF7gRwE4YZrJ7QjxZeoZqHaKsQLRMp653beB # fHfeva9zJPhBSdVcCW7x9q0c2HVPLJHX9YCUU714I+qtLpDGrdbZxD9mikPqL/To # /1lDZ0ch8FtePhME7houuoPcMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGXUwghlxAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAALLt3U5+wJxQjYAAAAAAsswDQYJYIZIAWUDBAIB # BQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMFSe89CtGpGZeIG/Wo7SCHj # T4zAdZ7Q1m/CYuy+7iiiMEQGCisGAQQBgjcCAQwxNjA0oBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQuY29tIDANBgkqhkiG9w0B # AQEFAASCAQAV0pTZoN6xnDBtG5pLnJnrmm1nKjCS94qd+M2M0dYhL7r7TbxgoNhG # D43Mz1PaSN+z3gsCfY2WKS6vd4BEe/pZbB/OoKduKyqgL53zBX4yWCcA3BY0uF1O # TEovAvA6PaG9hBOiFTm8y/SahgaxZXKzblEtKeOfzVyLcIwv4ZSiCH2N8KAGoXgN # 6uN0IL28O901j50T9UNm9AJOVC7yXYVulj6u/RclA9yeCyS/GY3hpSG7+8+zAWlh # jjSSZhI6jP0A7wqFp83yhjxz60slT5IuxULh0vJW7063fipFNcRpi2e9+m1t98r0 # A1l6qLUm1NDam0aAAeiA8/TCniDY5dDgoYIW/TCCFvkGCisGAQQBgjcDAwExghbp # MIIW5QYJKoZIhvcNAQcCoIIW1jCCFtICAQMxDzANBglghkgBZQMEAgEFADCCAVEG # CyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZI # AWUDBAIBBQAEID3zDv97iwEHy7S0aHNzkDxfvZhnpCOEkjtC1YFlMZbRAgZj7hU9 # CaEYEzIwMjMwMjIxMDExNTE4Ljc4M1owBIACAfSggdCkgc0wgcoxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBB # bWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkREOEMt # RTMzNy0yRkFFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # oIIRVDCCBwwwggT0oAMCAQICEzMAAAHFA83NIaH07zkAAQAAAcUwDQYJKoZIhvcN # AQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIxMTA0MTkw # MTMyWhcNMjQwMjAyMTkwMTMyWjCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9u # czEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046REQ4Qy1FMzM3LTJGQUUxJTAjBgNV # BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCrSF2zvR5fbcnulqmlopdGHP5NPsknc69V/f43x82n # FGzmNjiES/cFX/DkRZdtl07ibfGPTWVMj/EOSr7K2O6I97zEZexnEOe2/svUTMx3 # mMhKon55i7ySBXTnqaqzx0GjnnFk889zF/m7X3OfThoxAXk9dX8LhktKMVr0gU1y # uJt06beUZbWtBEVraNSy6nqC/rfirlTAfT1YYa7TPz1Fu1vIznm+YGBZXx53ptkJ # mtyhgiMwvwVFO8aXOeqboe3Bl1czAodPdr+QtRI+IYCysiATPPs2kGl46yCz1OvD # JZNkE1sHDIgAKZDfiP65Hh63aFmT40fj0qEQnJgPb504hoMYHYRQ0VJhzLUySC1m # 3V5GoEHSb5g9jPseOhw/KQpg1BntO/7OCU598KJrHWM5vS7ohgLlfUmvwDBNyxoP # K7eoCHHxwVA30MOCJVnD5REVnyjKgOTqwhXWfHnNkvL6E21qR49f1LtjyfWpZ8CO # hc8TorT91tPDzsQ4kv8GUkZwqgVPK2vTM+D8w0lJvp/Zr/AORegYIZYmJCsZPGM4 # /5H3r+cggbTl4TUumTLYU51gw8HgOFbu0F1lq616lNO5KGaCf4YoRHwCgDWBJKTU # QLllfhymlWeAmluUwG7yv+0KF8dV1e+JjqENKEfBAKZmpl5uBJgeceXi6sT7grpk # LwIDAQABo4IBNjCCATIwHQYDVR0OBBYEFFTquzi/WbE1gb+u2kvCtXB6TQVrMB8G # A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG # Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy # MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w # XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy # dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG # A1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcNAQELBQAD # ggIBAIyo3nx+swc5JxyIr4J2evp0rx9OyBAN5n1u9CMK7E0glkn3b7Gl4pEJ/der # jup1HKSQpSdkLp0eEvC3V+HDKLL8t91VD3J/WFhn9GlNL7PSGdqgr4/8gMCJQ2bf # Y1cuEMG7Q/hJv+4JXiM641RyYmGmkFCBBWEXH/nsliTUsJ2Mh57/8atx9uRC2Jih # v05r3cNKNuwPWOpqJwSeRyVQ3+YSb1mycKcDX785AOn/xDhw98f3gszgnpfQ200F # 5XLC9YfTC4xo4nMeAMsJ4lSQUT0cTywENV52aPrM8kAj7ujMuNirDuLhEVuJK19Z # lIaPC36UslBlFZQJxPdodi9OjVhYNmySiFaDvvD18XZBuI70N+eqhntCjMeLtGI+ # luOCQkwCGuGl5N/9q3Z734diQo5tSaA8CsfVaOK/CbV3s9haxqsvu7mpm6TfoZvW # YRNLWgDZdff4LeuC3NGiE/z2plV/v2VW+OaDfg20gIr+kyT31IG62CG2KkVIxB1t # dSdLah4u31wq6/Uwm76AnzepdM2RDZCqHG01G9sT1CqaolDDlVb/hJnN7Wk9fHI5 # M7nIOr6JEhS5up5DOZRwKSLI24IsdaHw4sIjmYg4LWIu1UN/aXD15auinC7lIMm1 # P9nCohTWpvZT42OQ1yPWFs4MFEQtpNNZ33VEmJQj2dwmQaD+MIIHcTCCBVmgAwIB # AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 # IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1 # WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O # 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn # hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t # 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq # D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP # frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW # rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv # 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb # r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten # IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc # xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a # j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB # MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU # n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw # QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E # b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/ # MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ # oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p # Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB # BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v # Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h # LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x # 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p # y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A # oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC # HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB # 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt # yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3 # rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV # v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24 # 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw # Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAsswggI0AgEBMIH4oYHQpIHNMIHK # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxN # aWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNT # IEVTTjpERDhDLUUzMzctMkZBRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAIQAa9hdkkrtxSjrb4u8RhATHv+eg # gYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYw # JAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0B # AQUFAAIFAOeegi8wIhgPMjAyMzAyMjEwNzM1MTFaGA8yMDIzMDIyMjA3MzUxMVow # dDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA556CLwIBADAHAgEAAgIUKjAHAgEAAgIR # XzAKAgUA55/TrwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAow # CAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAIbvoWlSYDdT # uJmL7RzB5d2oJC6NzVP+9ThTBhK9W8cdjpeb7OSJTZ0VrLTy8D620Jv2TpsM1pc2 # gE7FKmKyEr4UsaniU7ibKKDwWK3BvIoOd2Bl3Sf94S+DMrQ3a3ScA3QflMaLkNLo # 29fGeccOeOWQuLu8HV1TJr4tnTzYQr9kMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHFA83NIaH07zkAAQAAAcUwDQYJYIZI # AWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG # 9w0BCQQxIgQgWYNamvp3S9yJdXcgiU62HsTcbjD27zMdD1ShClYpk6owgfoGCyqG # SIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAZAbGR9iR3TAr5XT3A7Sw76ybyAAzKPkS4 # o+q81D98sTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n # dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMz # AAABxQPNzSGh9O85AAEAAAHFMCIEIEd5+/1zEBb4HmUZ+MC0P9kQt0gHDFQZwJam # 3u3PqwYzMA0GCSqGSIb3DQEBCwUABIICACqHiDUCGp26NrrUJKdRX/JF5s8GU0VM # tDhxgqUDbNIJXYBcu1ZbAyPkwSB24uelQ+TWgPqElIqEWHCLkE1V1MdTOMMyQ7Tn # bo8boOaQii7r4rzeGQ0CnpdUv6/qKjCyAX3k0AqKP0qvGEi97c+GlDHm5oSQcfYW # fMhnm1vp+wYtV41jupcV6+m+b3QpeJ8eX0TicBU4HxshrH5K+iEx1wB8MHM8x0Xu # P61NEY1WPeMbZdJ1raaFklvrbTf6ZPs1F4WABUlafkN0kJoC9shWzUXPqXf357rl # FzirVSbYHxMF+A5Xhwv+NUuZSye0dqF9f/btNKTCEKXHCoDOIirXweopHxTAhAhu # ah8Ou8oWeQPEGUEPv3v3Oo84gQV3bSyhxMX6DkTNYvyDJOw2ZAuFn0+aItHe5TnR # 9mS0Ud3P7EwkEQr/VsBi4Mt31UMmMw+GVWwjUXjJM7YEdbifiJksnn5DEJ+SF1kU # Iq9GCFTb6R9hL+jTPz5lzPjuW/g/wSxGnn4N9ezE7gkPxjMz4vzMi6EzPM9FCCpZ # XehiTK22Dvfbng3Iwc/uJfDj0/fhQqankEdNNTXHn3tb+6iB8r3AWcn8hmkEA5W7 # rddO6l4lf3KzpsFsyn4o7jnidLiQyJUc7HQPMVZfBbaDbgXaxtNRaULItt9czNkh # p7h4+KMRDyOg # SIG # End signature block |