public/GrantAppConsentAndManagementPermissionToAiAdmin.ps1
<#
.SYNOPSIS Grants app consent and management permissions to users assigned the AI Admin role. .DESCRIPTION The GrantAppConsentAndManagementPermissionToAiAdmin function is used to assign Microsoft Graph application permissions and create a custom role for users holding the AI Admin role. It ensures necessary modules are installed, collects AI Admin users, creates or reuses a custom permission grant policy, assigns specific permissions, and finally assigns a custom role for managing app and connector permissions. This function is particularly useful for administrators configuring Microsoft Graph Connectors or enabling custom connector management capabilities for Copilot scenarios. .FUNCTION GrantAppConsentAndManagementPermissionToAiAdmin Automates the assignment of Graph API permissions and custom roles to AI Admins to enable them to manage external connectors and consent to applications. .PARAMETER AiAdminRoleDefinitionId Optional. Role Definition ID for the AI Admin role. Default is "d2562ede-74db-457e-a7b6-544e236ebb61". .PARAMETER PolicyName Optional. Name of the permission grant policy to create or reuse. Default is "Grant-Consent-Permissions-To-AIAdmins". .PARAMETER UnifiedRoleName Optional. Name of the custom role to assign to AI Admins. Default is "Custom Connector Management for Copilot". .NOTES - Requires Microsoft Graph PowerShell SDK modules. - Prompts for user confirmation before proceeding with changes. - Requires the following Microsoft Graph permissions: RoleManagement.ReadWrite.Directory, Policy.ReadWrite.PermissionGrant, User.Read.All. - Creates or updates permission grant policies and assigns required permissions. - Automatically assigns the created role to users with the AI Admin role. #> function GrantAppConsentAndManagementPermissionToAiAdmin { param( [string]$AiAdminRoleDefinitionId = "d2562ede-74db-457e-a7b6-544e236ebb61", [string]$PolicyName = "Grant-Consent-Permissions-To-AIAdmins", [string]$UnifiedRoleName = "Custom Connector Management for Copilot" ) # === Required Modules === $requiredModules = @( "Microsoft.Graph.Authentication", "Microsoft.Graph.Identity.DirectoryManagement", "Microsoft.Graph.Users", "Microsoft.Graph.Identity.Governance", "Microsoft.Graph.Identity.SignIns" ) Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "Grant App registration and consent permissions for Copilot connectors" -ForegroundColor Cyan Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "" Write-Host "This script performs the following actions:" -ForegroundColor Yellow Write-Host "- Grants application registration permissions to users who are currently assigned with an AI Administrator role." Write-Host "- Grants permissions to consent to Graph Connector-related API permissions by doing the following:" Write-Host " - Creates a custom consent policy named 'Grant Consent Permissions To AIAdmins' to allow consent to ExternalItem.* and ExternalConnection.*." Write-Host " - Creates a custom role named 'Custom Connector Management for Copilot' and assigns the consent policy to this role." Write-Host " - Assigns the custom role to existing AI Administrators." Write-Host "" Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "Installing Required Modules (This may take a few minutes)" -ForegroundColor Cyan Write-Host "=======================================================================" -ForegroundColor Cyan foreach ($module in $requiredModules) { Write-Host "Checking for $module module..." if (-not (Get-Module -ListAvailable -Name $module)) { Write-Host "$module module not found. Installing..." try { Install-Module -Name $module -Scope CurrentUser -Force -AllowClobber Write-Host "$module module installed successfully." -ForegroundColor Green } catch { Write-Error "Failed to install $module module. Error: $_" return } } else { Write-Host "$module module is already installed." -ForegroundColor Green } Write-Host "Importing $module module..." Import-Module $module -Force } Write-Host "`nAll required modules have been installed and imported successfully!" -ForegroundColor Green Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "Login With Admin Account" -ForegroundColor Cyan Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "" Write-Host "- Please log in with an administrator account and grant the necessary permissions for the cmdlet to execute:" -ForegroundColor Yellow Write-Host "- After logging in, return to this window." -ForegroundColor Yellow Write-Host "- You will be able to review the users who will be granted permissions before the cmdlet proceeds further." -ForegroundColor Yellow Write-Host "" $initialConsent = Read-Host "Do you want to proceed to login with your admin account? (yes/no)" if ($initialConsent -ne "yes" -and $initialConsent -ne "y") { Write-Warning "Operation cancelled by user." return } Connect-MgGraph -Scopes RoleManagement.ReadWrite.Directory, Policy.ReadWrite.PermissionGrant, User.Read.All -NoWelcome $assignments = Get-MgRoleManagementDirectoryRoleAssignment -Filter "roleDefinitionId eq '$AiAdminRoleDefinitionId'" $userPrincipalInfos = @() foreach ($assignment in $assignments) { try { $user = Get-MgUser -UserId $assignment.PrincipalId -ErrorAction SilentlyContinue if ($user) { $userPrincipalInfos += @{ Id = $user.Id Email = $user.UserPrincipalName } } } catch {} } if (-not $userPrincipalInfos) { Write-Warning "No users with AI Admin role found. Exiting." return } Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "Review Users And Permissions" -ForegroundColor Cyan Write-Host "=======================================================================" -ForegroundColor Cyan Write-Host "Users who will be granted the permissions:" -ForegroundColor Green for ($i = 0; $i -lt $userPrincipalInfos.Count; $i++) { Write-Host "$($i + 1). $($userPrincipalInfos[$i].Email)" -ForegroundColor Green } Write-Host "" Write-Host "Permissions that will be granted:" -ForegroundColor Yellow Write-Host "- Ability to consent to ExternalConnection.* and ExternalItem.*(ReadWrite.OwnedBy, ReadWrite.All, Read.All)" -ForegroundColor Yellow Write-Host "- Register application and manage permissions for apps owned" -ForegroundColor Yellow Write-Host "" $continueWithGraphConnector = Read-Host "Do you want to continue with assigning these permissions to these users? (yes/no)" if ($continueWithGraphConnector -ne "yes" -and $continueWithGraphConnector -ne "y") { Write-Warning "Operation cancelled by user." return } Write-Host "`nCreating custom consent policy -'$PolicyName'..." -ForegroundColor Green $permissions = @{ "f431331c-49a6-499f-be1c-62af19c34a9d" = "ExternalConnection.ReadWrite.OwnedBy" "1914711b-a1cb-4793-b019-c2ce0ed21b8c" = "ExternalConnection.Read.All" "8116ae0f-55c2-452d-9944-d18420f5b2c8" = "ExternalItem.ReadWrite.OwnedBy" "34c37bc0-2b40-4d5e-85e1-2365cd256d79" = "ExternalConnection.ReadWrite.All" "7a7cffad-37d2-4f48-afa4-c6ab129adcc2" = "ExternalItem.Read.All" "38c3d6ee-69ee-422f-b954-e17819665354" = "ExternalItem.ReadWrite.All" } $permissionIds = $permissions.Keys $appManagementPermissions = @( "microsoft.directory/applications/create", "microsoft.directory/applications/permissions/update" ) $policy = Get-MgPolicyPermissionGrantPolicy -Filter "id eq '$PolicyName'" -ErrorAction SilentlyContinue if (-not $policy) { $policy = New-MgPolicyPermissionGrantPolicy -Id $PolicyName ` -DisplayName $PolicyName ` -Description "App registration and consent permissions for Copilot connectors" Write-Host "Policy created." }else { Write-Host "Policy already exists." } # Microsoft Graph app resource id $resourceAppId = "00000003-0000-0000-c000-000000000000" $existingIncludes = Get-MgPolicyPermissionGrantPolicyInclude -PermissionGrantPolicyId $policy.Id -ErrorAction SilentlyContinue foreach ($permId in $permissionIds) { $exists = $existingIncludes | Where-Object { $_.PermissionType -eq "Application" -and $_.ResourceApplication -eq $resourceAppId -and $_.Permissions -contains $permId } if (-not $exists) { New-MgPolicyPermissionGrantPolicyInclude -PermissionGrantPolicyId $policy.Id ` -PermissionType "Application" ` -ResourceApplication $resourceAppId ` -Permissions $permId > $null } } Write-Host "`nCreating custom role - '$UnifiedRoleName'..." -ForegroundColor Green $existingRole = Get-MgRoleManagementDirectoryRoleDefinition | Where-Object { $_.DisplayName -eq $UnifiedRoleName } if (-not $existingRole) { $unifiedRoleDefinition = @{ displayName = $UnifiedRoleName description = "App registration and consent permissions for Copilot connectors" isEnabled = $true assignableScopes = @("/") rolePermissions = @( @{ allowedResourceActions = @( "microsoft.directory/servicePrincipals/managePermissionGrantsForAll.$($policy.Id)" ) + $appManagementPermissions } ) } $unifiedRole = New-MgRoleManagementDirectoryRoleDefinition -BodyParameter $unifiedRoleDefinition Write-Host "Role created." } else { $unifiedRole = $existingRole Write-Host "Role already exists." } Write-Host "`nAssigning custom role to the users..." -ForegroundColor Green [int]$failureCount = 0 $totalUsers = $userPrincipalInfos.Count foreach ($info in $userPrincipalInfos) { $userId = $info.Id $email = $info.Email try { $existingAssignment = Get-MgRoleManagementDirectoryRoleAssignment -Filter "principalId eq '$userId' and roleDefinitionId eq '$($unifiedRole.Id)'" -ErrorAction Stop if (-not $existingAssignment) { Write-Host "- $email" New-MgRoleManagementDirectoryRoleAssignment -PrincipalId $userId ` -RoleDefinitionId $unifiedRole.Id ` -DirectoryScopeId "/" > $null } else { Write-Host "User $email already has role assigned. Skipping." } } catch { Write-Warning "Failed to assign role to user $email. Error: $_" $failureCount++ } } # === Final Summary Output === Write-Host "`nSummary:" -ForegroundColor Cyan if ($failureCount -eq $totalUsers) { Write-Host "Failed to grant permission." -ForegroundColor Red Write-Host "Please retry." -ForegroundColor Red } elseif ($failureCount -gt 0) { Write-Host "Failed to grant permission for $failureCount out of $totalUsers users." -ForegroundColor Red Write-Host "Please retry." -ForegroundColor Red } else { Write-Host "Successfully granted permissions to all $totalUsers users." -ForegroundColor Green } } # SIG # Begin signature block # MIIoewYJKoZIhvcNAQcCoIIobDCCKGgCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAX+riIfwQlQfWA # d0E6p64dSO32ZTJXUPLdRBRJ+jlJWKCCDXYwggX0MIID3KADAgECAhMzAAAEBGx0 # Bv9XKydyAAAAAAQEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjQwOTEyMjAxMTE0WhcNMjUwOTExMjAxMTE0WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC0KDfaY50MDqsEGdlIzDHBd6CqIMRQWW9Af1LHDDTuFjfDsvna0nEuDSYJmNyz # NB10jpbg0lhvkT1AzfX2TLITSXwS8D+mBzGCWMM/wTpciWBV/pbjSazbzoKvRrNo # DV/u9omOM2Eawyo5JJJdNkM2d8qzkQ0bRuRd4HarmGunSouyb9NY7egWN5E5lUc3 # a2AROzAdHdYpObpCOdeAY2P5XqtJkk79aROpzw16wCjdSn8qMzCBzR7rvH2WVkvF # HLIxZQET1yhPb6lRmpgBQNnzidHV2Ocxjc8wNiIDzgbDkmlx54QPfw7RwQi8p1fy # 4byhBrTjv568x8NGv3gwb0RbAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU8huhNbETDU+ZWllL4DNMPCijEU4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMjkyMzAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIjmD9IpQVvfB1QehvpC # Ge7QeTQkKQ7j3bmDMjwSqFL4ri6ae9IFTdpywn5smmtSIyKYDn3/nHtaEn0X1NBj # L5oP0BjAy1sqxD+uy35B+V8wv5GrxhMDJP8l2QjLtH/UglSTIhLqyt8bUAqVfyfp # h4COMRvwwjTvChtCnUXXACuCXYHWalOoc0OU2oGN+mPJIJJxaNQc1sjBsMbGIWv3 # cmgSHkCEmrMv7yaidpePt6V+yPMik+eXw3IfZ5eNOiNgL1rZzgSJfTnvUqiaEQ0X # dG1HbkDv9fv6CTq6m4Ty3IzLiwGSXYxRIXTxT4TYs5VxHy2uFjFXWVSL0J2ARTYL # E4Oyl1wXDF1PX4bxg1yDMfKPHcE1Ijic5lx1KdK1SkaEJdto4hd++05J9Bf9TAmi # u6EK6C9Oe5vRadroJCK26uCUI4zIjL/qG7mswW+qT0CW0gnR9JHkXCWNbo8ccMk1 # sJatmRoSAifbgzaYbUz8+lv+IXy5GFuAmLnNbGjacB3IMGpa+lbFgih57/fIhamq # 5VhxgaEmn/UjWyr+cPiAFWuTVIpfsOjbEAww75wURNM1Imp9NJKye1O24EspEHmb # DmqCUcq7NqkOKIG4PVm3hDDED/WQpzJDkvu4FrIbvyTGVU01vKsg4UfcdiZ0fQ+/ # V0hf8yrtq9CkB8iIuk5bBxuPMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGlswghpXAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAQEbHQG/1crJ3IAAAAABAQwDQYJYIZIAWUDBAIB # BQCggeYwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIJwwXxSfbbMC1Qw0odu35epR # tDcwRTStfVjGxwJar5BMMHoGCisGAQQBgjcCAQwxbDBqoEyASgBNAGkAYwByAG8A # cwBvAGYAdAAuAEcAcgBhAHAAaAAuAEMAbwBuAG4AZQBjAHQAbwByAHMALgBDAG0A # ZABsAGUAdAAuAGQAbABsoRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTANBgkq # hkiG9w0BAQEFAASCAQBg6o99BTKt1MfHHi81hGptRBDPd6oHGMC315XC1I1oZ85C # 8PpfZqf675E4B1amp+GpHNN1RDp4K4040qxdu4yjvRXjYKA1b0M/EMtrG2haLrRf # pVbv17iOMqvzHwih6oeHMjz8RbAksC+rifRHa7WekqLkh1WVMDmhRvSd5a//wUPY # eCMyFiOcFkWYwN3k8/gfPrgPGo70rJFzhvvRSMy/+TF8I6dCo2wctZ1QsgwBPZpj # /vKFg26TlMPwZxKykkqUo4E2F7fvFh/8xNhMvnhDW/GTOMBmQRVyz5rOj56duPxJ # 2nkuNbVZemS4n4cGGsB8eMKqMLWCkmuy08GmCCXmoYIXrTCCF6kGCisGAQQBgjcD # AwExgheZMIIXlQYJKoZIhvcNAQcCoIIXhjCCF4ICAQMxDzANBglghkgBZQMEAgEF # ADCCAVoGCyqGSIb3DQEJEAEEoIIBSQSCAUUwggFBAgEBBgorBgEEAYRZCgMBMDEw # DQYJYIZIAWUDBAIBBQAEILyCfRpClnVcvvIi+p+KCRrzgpFLv82+OMZ6dahNkA1D # AgZoUxm/stMYEzIwMjUwNzA3MTIzMDQ1LjM2NlowBIACAfSggdmkgdYwgdMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjU1MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNloIIR+zCCBygwggUQoAMCAQICEzMAAAIB0UVZmBDMQk8A # AQAAAgEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTAwHhcNMjQwNzI1MTgzMTIyWhcNMjUxMDIyMTgzMTIyWjCB0zELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IEly # ZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBF # U046NTUxQS0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w # IFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC1at/4fMO7 # uyTnTLlgeF4IgkbS7FFIUVwc16T5N31mbImPbQQSNpTwkMm7mlZzik8CwEjfw0QA # nVv4oGeVK2pTy69cXiqcRKEN2Lyc+xllCxNkMpYCBQzaJlM6JYi5lwWzlkLz/4aW # tUszmHVj2d8yHkHgOdRA5cyt6YBP0yS9SGDe5piCaouWZjI4OZtriVdkG7XThIsA # Wxc5+X9MuGlOhPjrLuUj2xsj26rf8B6uHdo+LaSce8QRrOKVd6ihc0sLB274izqj # yRAui5SfcrBRCbRvtpS2y/Vf86A+aw4mLrI3cthbIchK+s24isniJg2Ad0EG6ZBg # rwuNmZBpMoVpzGGZcnSraDNoh/EXbIjAz5X2xCqQeSD9D6JIM2kyvqav87CSc4Qi # MjSDpkw7KaK+kKHMM2g/P2GQreBUdkpbs1Xz5QFc3gbRoFfr18pRvEEEvKTZwL4+ # E6hSOSXpQLz9zSG6qPnFfyb5hUiTzV7u3oj5X8TjJdF55mCvQWFio2m9OMZxo7Za # uQ/leaxhLsi8w8h/gMLIglRlqqgExOgAkkcZF74M+oIeDpuYY+b3sys5a/Xr8Kjp # L1xAORen28xJJFBZfLgq0mFl+a4PPa+vWPDg16LHC4gMbDWa1X9N1Ij6+ksl9SIu # X9v3D+0kH3YEAtBPx7Vgfw2mF06jXELCRwIDAQABo4IBSTCCAUUwHQYDVR0OBBYE # FLByr1uWoug8+JWvKb2YWYVZvLJSMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWn # G1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEw # KDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFt # cCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAww # CgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQA6 # NADLPRxXO1MUapdfkktHEUr87+gx7nm4OoQLxV3WBtwzbwoFQ+C9Qg9eb+90M3Yh # UGRYebAKngAhzLh1m2S5SZ3R+e7ppP0y+jWd2wunZglwygUsS3dO2uIto76Lgau/ # RlQu1ZdQ8Bb8yflJyOCfTFl24Y8EP9ezcnv6B6337xm8GKmyD83umiKZg5WwfEtx # 6btXld0w2zK1Ob+4KiaEz/CBHkqUNhNU0BcHFxIox4lqIPdXX4eE2RWWIyXlU4/6 # fDnFYXnm72Hp4XYbt4E+pP6pIVD6tAJB0is3TIbVA308muiC4r4UlAl1DN18PdFZ # WxyIHKBthpmVPVwYkjUjJDvgNDRQF1Ol94azKsRD08jxDKpUupvarsu0joMkw2mF # i76Ov//SymvVRW/IM+25GdsZBE2LUI7AlyP05iaWQWAo14J9sNPtTe4Q69aiZ6Rf # rRj+bm61FxQ9V4A92GQH4PENp6/cnXLAM13K73XWcBU+BGTIqAwrdRIsbfsR2Vq0 # OTwXK4KvHi2IfKoc7fATrE/DfZDx7++a5A+gFm5fepR6gUizJkR6cerZJwy6eFyp # bfZJRUCLmhnhned/t0CA1q7bU0Q/CBb7bCSs2oODsenzIfKg4puAQG7pERBu9J9n # kqHg9X5LaDF/a6roahgOeWoAE4xjDPfT0hKLRs8yHzCCB3EwggVZoAMCAQICEzMA # AAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290 # IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMw # MDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0G # CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3u # nAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1 # jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZT # fDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+ # jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c # +gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+ # cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C6 # 26p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV # 2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoS # CtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxS # UV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJp # xq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkr # BgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0A # XmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYI # KwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9S # ZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIE # DB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNV # HSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVo # dHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29D # ZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAC # hj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1 # dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwEx # JFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts # 0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9I # dQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYS # EhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMu # LGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT9 # 9kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2z # AVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6Ile # T53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6l # MVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbh # IurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3u # gm2lBRDBcQZqELQdVTNYs6FwZvKhggNWMIICPgIBATCCAQGhgdmkgdYwgdMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjU1MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDX7bpxH/IfXTQOI0UZaG4C # /atgGqCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqG # SIb3DQEBCwUAAgUA7BX6wDAiGA8yMDI1MDcwNzA3NTAyNFoYDzIwMjUwNzA4MDc1 # MDI0WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDsFfrAAgEAMAcCAQACAghUMAcC # AQACAhOrMAoCBQDsF0xAAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkK # AwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAANF # Mqd8Bk+/9T6fOL95v0FCre1YZmcOUVfV/pD5AEHoDad9zUUzHtP7PPjw/bFeiBNF # oHB8By4GdZnbGPdlxGnukXN+EmSm0w4pkTjWrphL01w8XH5vQmPS+Q16jKBEM867 # z9RHKdtTY3rFig8wgCLRVKgYICL1rJzMQLtE1WK4ceEy3RFpfn0wwTaCmNqzH7e6 # gdywLqwKP/UbhQRzjgM3zu2BetQZn3VdYerq6yHZosY4MRnMUNVw6mMTobCOzWQU # AXthb/PC1+wz+H66hvw5SGp7A5gfWvMlKZB0Yjs+KJkWxj79QPPEolT0cnREtnAi # +r/BWMgMm/faxiPLqDUxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFt # cCBQQ0EgMjAxMAITMwAAAgHRRVmYEMxCTwABAAACATANBglghkgBZQMEAgEFAKCC # AUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCC3 # pp6nH2SoKDpHP0GIcsfNgAexe40rrwl08FIUIiL2+zCB+gYLKoZIhvcNAQkQAi8x # geowgecwgeQwgb0EIFhrsjpMlBFybHQdpJNZl0mCjB2uX35muvSkh2oe1zgjMIGY # MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIB0UVZmBDM # Qk8AAQAAAgEwIgQgjao2isP13XB0uZOnYtp//Z8YXc0MiNAFra3+Uj+C54IwDQYJ # KoZIhvcNAQELBQAEggIAVApDirTQd+suFvKa2lFvcqBpoKjfPjtmAUovBoNntRYK # pMNnVtEs8sZZsxSEAgaKz7w0R9Kcd2DY/lflNCswoKPvXzZ8DV5w9N3HPScmwCJY # cptFYJQt83FUVFJP8AEU94l0vnxy6bGWMSLu99YYU3ZvkQ/8iGzfGdghJ5Bfh7Zr # w6hdbGcT9BXdXhNPoeLLozq547RD5RW96+qz0BdmjEutRZFJJKNWqOKMXDcema2i # QOF7fD8uRxQwqXBoSCTdS7wLb+x7PJBAQv73JJvwoDHaIwpMJplNm5MXHlywoowJ # AisQyIUc8E2WO23078qWMF6k8mvNgoDsOrfzGjVzF6wXNDkG/68s+MgiP/p5jqEl # hwUkAHELNnRhk76e2bQWy5hhzC/vjjiXVx3I51Xg3HsGXk7mh8+0Pzj4QD2d8rsZ # DT0PodR145MVhXhBs1x9Ob7ySRGCqEy2NdVvFwX7tpUHDryAmsN+hs3RNEJKDDsV # Xo9ZzSnx9/gSL7O8+igqOj1RRzRbaey4Bke76QVSOLIwpG3z9wR4Bv7b6fDHWS49 # Et1T4ghDTSkKX2LYd+uEw98xZ0SyKJIaDVmdfJMArAo2ri8ZrwZ7nBU75sTN8ro/ # E1C23QloTIdDxiXorwylEV1HgcrJYYLjdt5QPPr6lHcoYsb9M1eEjSyot2BnvVs= # SIG # End signature block |