Private/appregistrations.ps1
|
function RegisterAzureADApp($name, $appRoleAssignments, $replyUrls = $null, $homepage = $null, $EnableIdToken = $false, $createIfNotExists = $true) { $azureAdAppReg = Convert-LinesToObject -lines $(az ad app list --filter "displayname eq '$name'" --query "[0]" --only-show-errors) if($null -eq $azureAdAppReg) { if ($createIfNotExists) { Write-Information "Creating app registration $name, as it does not exist yet" $appRoleManifestJson = HashTable2AzJson -psHashTable $appRoleAssignments $azAppRegistrationCommand = "az ad app create --display-name '$name' --app-roles '$appRoleManifestJson'" if ($null -ne $replyUrls) { if (AzUsesAADGraph) { $azAppRegistrationCommand += " --reply-urls '$replyUrls'" } else { $azAppRegistrationCommand += " --web-redirect-uris '$replyUrls'" } } if ($null -ne $homepage) { if (AzUsesAADGraph) { $azAppRegistrationCommand += " --homepage '$homepage'" } else { $azAppRegistrationCommand += " --web-home-page-url '$homepage'" } } if (-not (AzUsesAADGraph)) { $azAppRegistrationCommand += " --sign-in-audience AzureADMyOrg" if ($EnableIdToken) { $azAppRegistrationCommand += " --enable-id-token-issuance" } } $azureAdAppReg = Convert-LinesToObject -lines $(ExecuteAzCommandRobustly -azCommand $azAppRegistrationCommand) Write-Verbose "Created app registration $name (App ID $($azureAdAppReg.appId))" # Check whether the AppRoles were added correctly if ($azureAdAppReg.appRoles.Count -le 0) { Write-Error "The app registration $name (App ID $($azureAdAppReg.appId) has no app roles. This is likely an error that must be fixed." } # REVISIT: Once there is a solution for https://github.com/Azure/azure-cli/issues/22810, we can upload the logo # $graphEndpointForAppLogo = "https://graph.microsoft.com/v1.0/applications/$($azureAdAppReg.id)/logo" # az rest --method put --url $graphEndpointForAppLogo --body '@testlogo.png' --headers Content-Type=image/png } else { throw "App registration $name does not exist yet. Please run Complete-SCEPmanInstallation first." } } else { Write-Information "Existing app registration $name found (App ID $($azureAdAppReg.appId))" # check whether we need to update the roles $anything2Update = $false $updatedAppRoles = $azureAdAppReg.appRoles foreach ($requiredAppRole in $appRoleAssignments) { $role2Update = $updatedAppRoles.Where({ $_.value -eq $requiredAppRole.value}, "First") if ($role2Update.Count -eq 0) { $anything2Update = $true Write-Verbose "Required role $($requiredAppRole.displayName) will be added to existing app registration" $updatedAppRoles += ,$requiredAppRole } } if ($anything2Update) { Write-Information "Adding new roles to app registration $name" $appRolesJson = HashTable2AzJson -psHashTable $updatedAppRoles ExecuteAzCommandRobustly "az ad app update --id $($azureAdAppReg.appId) --app-roles '$appRolesJson'" # Reload app registration with new roles $azureAdAppReg = Invoke-Az -azCommand $('ad', 'app', 'show', '--id', $azureAdAppReg.id) | Convert-LinesToObject } if ($null -ne $replyUrls) { $existingReplyUrls = $azureAdAppReg.web.redirectUris $newReplyUrls = $replyUrls -split " " $replyUrlsToAdd = $newReplyUrls | Where-Object { $existingReplyUrls -notcontains $_ } if ($replyUrlsToAdd.Count -gt 0) { Write-Information "Adding reply URLs to app registration $name" $azCommandToAddReplyUrls = @("ad", "app", "update", "--id", $azureAdAppReg.appId) if (AzUsesAADGraph) { $azCommandToAddReplyUrls += "--reply-urls" } else { $azCommandToAddReplyUrls += "--web-redirect-uris" # ExecuteAzCommandRobustly -callAzNatively -azCommand @("ad", "app", "update", "--id", $azureAdAppReg.appId, "--web-home-page-url", $homepage, "--web-redirect-uris", $allReplyUrls) } $azCommandToAddReplyUrls += $existingReplyUrls + $replyUrlsToAdd ExecuteAzCommandRobustly -callAzNatively -azCommand $azCommandToAddReplyUrls } } $azureAdAppReg.web.redirectUris } return $azureAdAppReg } function CreateSCEPmanAppRegistration ($AzureADAppNameForSCEPman, $CertMasterServicePrincipalId, $GraphBaseUri) { Write-Information "Getting Azure AD app registration for SCEPman" # Register SCEPman App $appregsc = RegisterAzureADApp -name $AzureADAppNameForSCEPman -appRoleAssignments $ScepmanManifest -hideApp $true $servicePrincipalScepmanId = CreateServicePrincipal -appId $($appregsc.appId) # Expose SCEPman API ExecuteAzCommandRobustly -azCommand "az ad app update --id $($appregsc.appId) --identifier-uris `"api://$($appregsc.appId)`"" Write-Information "Allowing CertMaster to submit CSR requests to SCEPman API" $ScepManSubmitCSRPermission = $appregsc.appRoles.Where({ $_.value -eq "CSR.Request"}, "First") if ($ScepManSubmitCSRPermission.count -eq 0) { throw "SCEPman has no role CSR.Request in its $($appregsc.appRoles.Count) app roles. Certificate Master needs to be assigned this role." } $resourcePermissionsForCertMaster = @([pscustomobject]@{'resourceId'=$servicePrincipalScepmanId;'appRoleId'=$($ScepManSubmitCSRPermission.id);'permissionLevel'=0}) $null = SetManagedIdentityPermissions -principalId $CertMasterServicePrincipalId -resourcePermissions $resourcePermissionsForCertMaster -GraphBaseUri $GraphBaseUri return $appregsc } function CreateCertMasterAppRegistration ($AzureADAppNameForCertMaster, $CertMasterBaseURLs, $SkipAutoGrant = $false, $AddAdditionalAppRoles = $false) { Write-Information "Getting Azure AD app registration for CertMaster" ### CertMaster App Registration if ($AddAdditionalAppRoles) { Write-Verbose "Adding additional app roles to CertMaster App Registration" $AppRoleAssignments = $CertmasterManifest + $CertmasterAdditionalManifest } else { $AppRoleAssignments = $CertmasterManifest } $signInUrlArray = $CertMasterBaseURLs | ForEach-Object { "$_/signin-oidc" } $spaceSeparatedSignInUrls = $signInUrlArray -join " " # Register CertMaster App $appregcm = RegisterAzureADApp -name $AzureADAppNameForCertMaster -appRoleAssignments $AppRoleAssignments -replyUrls $spaceSeparatedSignInUrls -hideApp $false -homepage $CertMasterBaseURLs[0] -EnableIdToken $true $null = CreateServicePrincipal -appId $($appregcm.appId) # Expose CertMaster API ExecuteAzCommandRobustly -azCommand "az ad app update --id $($appregcm.appId) --identifier-uris `"api://$($appregcm.appId)`"" Write-Verbose "Adding Delegated permission to CertMaster App Registration" # Add Microsoft Graph's User.Read as delegated permission for CertMaster AddDelegatedPermissionToCertMasterApp -appId $appregcm.appId -SkipAutoGrant $SkipAutoGrant return $appregcm } <# .SYNOPSIS .DESCRIPTION Adds az as an Authorized Client Application to an existing App Registration. Returns $true if the authorization was added, $false if it already existed. #> function Add-AzAsTrustedClientApplication { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$true)]$AppId ) $AppJson = ExecuteAzCommandRobustly -callAzNatively -azCommand @('ad', 'app', 'show', '--id', $AppId) $AppObject = Convert-LinesToObject -Lines $AppJson $existingAzAuthorization = $AppObject.api.preAuthorizedApplications | Where-Object { $_.appId -eq $AzAppId } if ($null -eq $existingAzAuthorization) { Write-Information "Adding az as authorized application" $AccessApplicationPermissionId = $AppObject.api.oauth2PermissionScopes | Where-Object { $_.value -eq 'user_impersonation' } | Select-Object -ExpandProperty id if ($existingAzAuthorization.Count -eq 0) { $existingAzAuthorization = [System.Collections.ArrayList]@() } $null = $existingAzAuthorization.Add(@{ 'appId' = $AzAppId; 'permissionIds' = @($AccessApplicationPermissionId) }) $preAuthorizationsInner = ConvertTo-Json -InputObject $existingAzAuthorization -Compress $preAuthorizationsBody = "{'api':{'preAuthorizedApplications':$($preAuthorizationsInner.Replace("delegatedPermissionIds", "permissionIds").Replace('"', "'"))}}" if ($PSCmdlet.ShouldProcess("Application with id $($AppObject.id)", "Add az (App Id: $AzAppId) as authorized application")) { $null = ExecuteAzCommandRobustly -callAzNatively -azCommand @('rest', '--method', 'patch', '--uri', "https://graph.microsoft.com/beta/applications/$($AppObject.id)", '--body', $preAuthorizationsBody, '--headers', 'Content-Type=application/json') } return $true } else { return $false } } function Remove-AzAsTrustedClientApplication { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)]$AppId ) $AppJson = Invoke-Az -azCommand @('ad', 'app', 'show', '--id', $AppId) $AppObject = Convert-LinesToObject -Lines $AppJson $authorizationsWithoutAz = $AppObject.api.preAuthorizedApplications | Where-Object { $_.appId -ne $AzAppId } if ($null -eq $authorizationsWithoutAz) { $authorizationsWithoutAz = @() } $previousPreAuthorizationsInner = ConvertTo-Json -InputObject $authorizationsWithoutAz -Compress $previousPreAuthorizationsBody = "{'api':{'preAuthorizedApplications':$($previousPreAuthorizationsInner.Replace("delegatedPermissionIds", "permissionIds").Replace('"', "'"))}}" if ($PSCmdlet.ShouldProcess("Application with id $($AppObject.id)", "Remove az (App Id: $AzAppId) as authorized application")) { $null = ExecuteAzCommandRobustly -callAzNatively -azCommand @('rest', '--method', 'patch', '--uri', "https://graph.microsoft.com/beta/applications/$($AppObject.id)", '--body', $previousPreAuthorizationsBody, '--headers', 'Content-Type=application/json') } } # SIG # Begin signature block # MIIv6wYJKoZIhvcNAQcCoIIv3DCCL9gCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAiiWN6lziIQ6e/ # bQXMOW9mLIcK+tFPv5roeDPpr0/avKCCFA4wggVyMIIDWqADAgECAhB2U/6sdUZI # k/Xl10pIOk74MA0GCSqGSIb3DQEBDAUAMFMxCzAJBgNVBAYTAkJFMRkwFwYDVQQK # ExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENvZGUgU2ln # bmluZyBSb290IFI0NTAeFw0yMDAzMTgwMDAwMDBaFw00NTAzMTgwMDAwMDBaMFMx # CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQD # EyBHbG9iYWxTaWduIENvZGUgU2lnbmluZyBSb290IFI0NTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBALYtxTDdeuirkD0DcrA6S5kWYbLl/6VnHTcc5X7s # k4OqhPWjQ5uYRYq4Y1ddmwCIBCXp+GiSS4LYS8lKA/Oof2qPimEnvaFE0P31PyLC # o0+RjbMFsiiCkV37WYgFC5cGwpj4LKczJO5QOkHM8KCwex1N0qhYOJbp3/kbkbuL # ECzSx0Mdogl0oYCve+YzCgxZa4689Ktal3t/rlX7hPCA/oRM1+K6vcR1oW+9YRB0 # RLKYB+J0q/9o3GwmPukf5eAEh60w0wyNA3xVuBZwXCR4ICXrZ2eIq7pONJhrcBHe # OMrUvqHAnOHfHgIB2DvhZ0OEts/8dLcvhKO/ugk3PWdssUVcGWGrQYP1rB3rdw1G # R3POv72Vle2dK4gQ/vpY6KdX4bPPqFrpByWbEsSegHI9k9yMlN87ROYmgPzSwwPw # jAzSRdYu54+YnuYE7kJuZ35CFnFi5wT5YMZkobacgSFOK8ZtaJSGxpl0c2cxepHy # 1Ix5bnymu35Gb03FhRIrz5oiRAiohTfOB2FXBhcSJMDEMXOhmDVXR34QOkXZLaRR # kJipoAc3xGUaqhxrFnf3p5fsPxkwmW8x++pAsufSxPrJ0PBQdnRZ+o1tFzK++Ol+ # A/Tnh3Wa1EqRLIUDEwIrQoDyiWo2z8hMoM6e+MuNrRan097VmxinxpI68YJj8S4O # JGTfAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G # A1UdDgQWBBQfAL9GgAr8eDm3pbRD2VZQu86WOzANBgkqhkiG9w0BAQwFAAOCAgEA # Xiu6dJc0RF92SChAhJPuAW7pobPWgCXme+S8CZE9D/x2rdfUMCC7j2DQkdYc8pzv # eBorlDICwSSWUlIC0PPR/PKbOW6Z4R+OQ0F9mh5byV2ahPwm5ofzdHImraQb2T07 # alKgPAkeLx57szO0Rcf3rLGvk2Ctdq64shV464Nq6//bRqsk5e4C+pAfWcAvXda3 # XaRcELdyU/hBTsz6eBolSsr+hWJDYcO0N6qB0vTWOg+9jVl+MEfeK2vnIVAzX9Rn # m9S4Z588J5kD/4VDjnMSyiDN6GHVsWbcF9Y5bQ/bzyM3oYKJThxrP9agzaoHnT5C # JqrXDO76R78aUn7RdYHTyYpiF21PiKAhoCY+r23ZYjAf6Zgorm6N1Y5McmaTgI0q # 41XHYGeQQlZcIlEPs9xOOe5N3dkdeBBUO27Ql28DtR6yI3PGErKaZND8lYUkqP/f # obDckUCu3wkzq7ndkrfxzJF0O2nrZ5cbkL/nx6BvcbtXv7ePWu16QGoWzYCELS/h # AtQklEOzFfwMKxv9cW/8y7x1Fzpeg9LJsy8b1ZyNf1T+fn7kVqOHp53hWVKUQY9t # W76GlZr/GnbdQNJRSnC0HzNjI3c/7CceWeQIh+00gkoPP/6gHcH1Z3NFhnj0qinp # J4fGGdvGExTDOUmHTaCX4GUT9Z13Vunas1jHOvLAzYIwggboMIIE0KADAgECAhB3 # vQ4Ft1kLth1HYVMeP3XtMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAkJFMRkw # FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIENv # ZGUgU2lnbmluZyBSb290IFI0NTAeFw0yMDA3MjgwMDAwMDBaFw0zMDA3MjgwMDAw # MDBaMFwxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTIw # MAYDVQQDEylHbG9iYWxTaWduIEdDQyBSNDUgRVYgQ29kZVNpZ25pbmcgQ0EgMjAy # MDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMsg75ceuQEyQ6BbqYoj # /SBerjgSi8os1P9B2BpV1BlTt/2jF+d6OVzA984Ro/ml7QH6tbqT76+T3PjisxlM # g7BKRFAEeIQQaqTWlpCOgfh8qy+1o1cz0lh7lA5tD6WRJiqzg09ysYp7ZJLQ8LRV # X5YLEeWatSyyEc8lG31RK5gfSaNf+BOeNbgDAtqkEy+FSu/EL3AOwdTMMxLsvUCV # 0xHK5s2zBZzIU+tS13hMUQGSgt4T8weOdLqEgJ/SpBUO6K/r94n233Hw0b6nskEz # IHXMsdXtHQcZxOsmd/KrbReTSam35sOQnMa47MzJe5pexcUkk2NvfhCLYc+YVaMk # oog28vmfvpMusgafJsAMAVYS4bKKnw4e3JiLLs/a4ok0ph8moKiueG3soYgVPMLq # 7rfYrWGlr3A2onmO3A1zwPHkLKuU7FgGOTZI1jta6CLOdA6vLPEV2tG0leis1Ult # 5a/dm2tjIF2OfjuyQ9hiOpTlzbSYszcZJBJyc6sEsAnchebUIgTvQCodLm3HadNu # twFsDeCXpxbmJouI9wNEhl9iZ0y1pzeoVdwDNoxuz202JvEOj7A9ccDhMqeC5LYy # AjIwfLWTyCH9PIjmaWP47nXJi8Kr77o6/elev7YR8b7wPcoyPm593g9+m5XEEofn # GrhO7izB36Fl6CSDySrC/blTAgMBAAGjggGtMIIBqTAOBgNVHQ8BAf8EBAMCAYYw # EwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E # FgQUJZ3Q/FkJhmPF7POxEztXHAOSNhEwHwYDVR0jBBgwFoAUHwC/RoAK/Hg5t6W0 # Q9lWULvOljswgZMGCCsGAQUFBwEBBIGGMIGDMDkGCCsGAQUFBzABhi1odHRwOi8v # b2NzcC5nbG9iYWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUwRgYIKwYBBQUH # MAKGOmh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2NvZGVzaWdu # aW5ncm9vdHI0NS5jcnQwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2NybC5nbG9i # YWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUuY3JsMFUGA1UdIAROMEwwQQYJ # KwYBBAGgMgECMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24u # Y29tL3JlcG9zaXRvcnkvMAcGBWeBDAEDMA0GCSqGSIb3DQEBCwUAA4ICAQAldaAJ # yTm6t6E5iS8Yn6vW6x1L6JR8DQdomxyd73G2F2prAk+zP4ZFh8xlm0zjWAYCImbV # YQLFY4/UovG2XiULd5bpzXFAM4gp7O7zom28TbU+BkvJczPKCBQtPUzosLp1pnQt # pFg6bBNJ+KUVChSWhbFqaDQlQq+WVvQQ+iR98StywRbha+vmqZjHPlr00Bid/XSX # hndGKj0jfShziq7vKxuav2xTpxSePIdxwF6OyPvTKpIz6ldNXgdeysEYrIEtGiH6 # bs+XYXvfcXo6ymP31TBENzL+u0OF3Lr8psozGSt3bdvLBfB+X3Uuora/Nao2Y8nO # ZNm9/Lws80lWAMgSK8YnuzevV+/Ezx4pxPTiLc4qYc9X7fUKQOL1GNYe6ZAvytOH # X5OKSBoRHeU3hZ8uZmKaXoFOlaxVV0PcU4slfjxhD4oLuvU/pteO9wRWXiG7n9dq # cYC/lt5yA9jYIivzJxZPOOhRQAyuku++PX33gMZMNleElaeEFUgwDlInCI2Oor0i # xxnJpsoOqHo222q6YV8RJJWk4o5o7hmpSZle0LQ0vdb5QMcQlzFSOTUpEYck08T7 # qWPLd0jV+mL8JOAEek7Q5G7ezp44UCb0IXFl1wkl1MkHAHq4x/N36MXU4lXQ0x72 # f1LiSY25EXIMiEQmM2YBRN/kMw4h3mKJSAfa9TCCB6gwggWQoAMCAQICDF3VjaKN # us83AvC1UTANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQ # R2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFsU2lnbiBHQ0MgUjQ1IEVW # IENvZGVTaWduaW5nIENBIDIwMjAwHhcNMjUxMTI3MTcwNDI2WhcNMjcxMTI4MTcw # NDI2WjCCAQwxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRIwEAYDVQQF # EwlIUkIgMTIzODExEzARBgsrBgEEAYI3PAIBAxMCREUxFzAVBgsrBgEEAYI3PAIB # AhMGSGVzc2VuMSIwIAYLKwYBBAGCNzwCAQETEU9mZmVuYmFjaCBhbSBNYWluMQsw # CQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMRowGAYDVQQHExFPZmZlbmJhY2gg # YW0gTWFpbjEZMBcGA1UECQwQS2Fpc2Vyc3RyYcOfZSAzOTEXMBUGA1UEChMOZ2x1 # ZWNra2FuamEgQUcxFzAVBgNVBAMTDmdsdWVja2thbmphIEFHMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAkQoXi0dUFVttodx+Ydj1O6EZZqgDdlSGDA/6 # x1UCkMrWNVEW+LdbUGU8KW7fUcKPCAcDJNrXfXxZeBht2G4pPvhaMz/kBdSK6bI1 # sqo1WSN//beapdUefQpq/wgnUneq13tEJQAke6EWdLyidObcogBSp9wCXBbMWsTO # utgCONjyu8AilmzRY+94lO7VwUA2LGGPX8FRAEt5AMzifsEo2lIEKiDou2H8HUUC # PibiChiuT3oGIDYYnCA/RzS44E0cAuAzlD3NQNCeIDzfoFiUD8mAC1gYU6i8yIej # jUGl8+kpbpBYjgzwbsiCBn0rDhrlpJ3MHkZCrp82kzWK0l7c3ukNvdlGcU4tKdXk # AHgpJecdYUDvz9iaYFvYEivF+Jg+Tc8ZnzsP5/q3KKw4g0QiJ+MXgvwJx8OSvAKW # tkwkLxgE9oxufs3Y8xsmwyWqxWDBcyzzvs6yISnUaeTtGmyB8BsEbahDFrxHhV6U # nwxNpJ+iM+j08J1tNIW0AXjY6ojGOIC8IIL+EiK34MXJ6Jxy22mntMnc6ztK6c7H # IKiRHIPX4jXtg7IYRS/k5muuIt/xKzN7qtF9xJbaZi8jRE6fgWDwszLJUMHSLthh # yKTsUEvuqZ79WnSHErg26EPQYirAY/IFt7Z7+3SDW2WI8uG2qY6hkpE0hm+/F3uS # M+s98jUCAwEAAaOCAbYwggGyMA4GA1UdDwEB/wQEAwIHgDCBnwYIKwYBBQUHAQEE # gZIwgY8wTAYIKwYBBQUHMAKGQGh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20v # Y2FjZXJ0L2dzZ2NjcjQ1ZXZjb2Rlc2lnbmNhMjAyMC5jcnQwPwYIKwYBBQUHMAGG # M2h0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjQ1ZXZjb2Rlc2lnbmNh # MjAyMDBVBgNVHSAETjBMMEEGCSsGAQQBoDIBAjA0MDIGCCsGAQUFBwIBFiZodHRw # czovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAHBgVngQwBAzAJBgNV # HRMEAjAAMEcGA1UdHwRAMD4wPKA6oDiGNmh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5j # b20vZ3NnY2NyNDVldmNvZGVzaWduY2EyMDIwLmNybDATBgNVHSUEDDAKBggrBgEF # BQcDAzAfBgNVHSMEGDAWgBQlndD8WQmGY8Xs87ETO1ccA5I2ETAdBgNVHQ4EFgQU # q/cn5ijjtp0mG1yoiF02hg4dx4IwDQYJKoZIhvcNAQELBQADggIBAJ1TZv/rvy2w # jANcL/kb6rTk+/6L7l49UghLghUKFVfrdEEc+21iexA7zlkvhM0TrhdiFU7TjDky # InPctzsDlqwUhawEx4PT8ZkZkZzm25YWaqtZH44st/Fz59KiG+85NUdRd+0cL3Y8 # NR66z3xfI6K3W/nrIcE6RHm/opOM+L02Hd2MBligLnoFYcTvR3NPCA21A6+IOaYM # n5YZzNKFXWry8ZHpWjnE4u9mxHYpS1zu2aIkwL8mfYM5moYoh0PAcp9XA5Sm4KrV # LeIzZ3HIy4EzLCbFBP+OGFpkqq8pTtmYItG+g1rYEg5a8egrY83zJMHazaTFBgRI # MNXCgeMZhC8O6NsAtbj3FSbiYKg1hNwZzHYL+uL3jcPZjuUoOpmvXu67xWs4ZfdT # Mluy5E7FyWwtnOjr/04EXWyKATYMDIkd47Wqam/ZB7umF5T5YPnmTlv18ArEXuVQ # EEpS/cN90DtRz2OGruu+V9bg3fk6NKDJLve8detDOTTBN0C/bFGxI5YLHmwVAdaq # pz3t14ShRjVcxP7aN0bEL3YOuQvjnjQGe29H6n/MPf8UG4WYMd+a8qIP4HROLJq0 # YJylzYBglqoQeQC/OG+PtWTvL9oByPVYNc+llAuap/xmWSLZgAqPbi+PAfow69Lg # bppHUCnJhNkXD/mJ4qB0KvPG+bzL19dEMYIbMzCCGy8CAQEwbDBcMQswCQYDVQQG # EwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFs # U2lnbiBHQ0MgUjQ1IEVWIENvZGVTaWduaW5nIENBIDIwMjACDF3VjaKNus83AvC1 # UTANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkG # CSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE # AYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBoakZGbn3wuubdq99rI9Fv45eyYBpuk3Yz # f951sm5i9DANBgkqhkiG9w0BAQEFAASCAgBYmck2Y64KxkQ12QqjyubAkdUDCLQa # 8ZWqY/5gH7YEOvjOSRs0IKOxlVoVCS/n4ZJen06I8uib0rpMoxJ6G6nrxTxHK7Ab # izheoQDWim1DWlZ2/gjmHHgY8CmdeWD99s/F6jG4NDiwlCioBaPVymuQ/WpyikRq # Wrtghsx3VQzulAjSAdGoWuRtYq/CvaGY8iekCQ8VcOZu8xxYQTVACN1FQz69D97y # 1iXT8sAFFjNCxw4dWsOYGpjmaeLH/ffNBt9nXTKTesjTIc1wqTWTp50/AoCuG4j6 # jUYaHiHicFkFkSUE7ov493kuQT7lvDMpsYFN+LNFH7XTC5ijkoIsv4rOfBruH/tr # B+ql5GF0Ma8b3AsswmM0wAOAkoKualtCO6Nfm2KSCXLfRFbtVXKsefVuwc2MnOZk # +sORr69uFGv+CYPlHK6m5K9SNOgdDuyFN6iBOsA+Mn4fiUNP4jGe9x5qlIkY62Cf # tLyUd/0SsCzt0NrK+Dhypy/NB1d52+FFqlLgvH33+8K0RYt0N9R5PNoTZJVnOKVr # 3TtqVuxJ16aAMCIFNPCLYwYhSC/8SfszarS+5W3+TyO4N+VkJypsaCqEYf4F45Xm # XfwX6KXFX8Ynimz4RVNOzQ4aJvMUV7tofwOGtSy1IG6M7Ar/qKrGC+VBkvM/Bd8j # fsYm075NxI/JOqGCGBEwghgNBgorBgEEAYI3AwMBMYIX/TCCF/kGCSqGSIb3DQEH # AqCCF+owghfmAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFiBgsqhkiG9w0BCRABBKCC # AVEEggFNMIIBSQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCC2zV87 # 5PyqskJCkkerVp7MOHgiy59U65NH8fQ9WVY3tQIGaR9SpxoKGBMyMDI1MTIwMjEz # MjkwOC40MDNaMASAAgH0oIHhpIHeMIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRp # b25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0QwMC0wNUUwLUQ5NDcxNTAz # BgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9y # aXR5oIIPITCCB4IwggVqoAMCAQICEzMAAAAF5c8P/2YuyYcAAAAAAAUwDQYJKoZI # hvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlv # biBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIwMTExOTIwMzIz # MVoXDTM1MTExOTIwNDIzMVowYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0Eg # VGltZXN0YW1waW5nIENBIDIwMjAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK # AoICAQCefOdSY/3gxZ8FfWO1BiKjHB7X55cz0RMFvWVGR3eRwV1wb3+yq0OXDEqh # UhxqoNv6iYWKjkMcLhEFxvJAeNcLAyT+XdM5i2CgGPGcb95WJLiw7HzLiBKrxmDj # 1EQB/mG5eEiRBEp7dDGzxKCnTYocDOcRr9KxqHydajmEkzXHOeRGwU+7qt8Md5l4 # bVZrXAhK+WSk5CihNQsWbzT1nRliVDwunuLkX1hyIWXIArCfrKM3+RHh+Sq5RZ8a # Yyik2r8HxT+l2hmRllBvE2Wok6IEaAJanHr24qoqFM9WLeBUSudz+qL51HwDYyID # PSQ3SeHtKog0ZubDk4hELQSxnfVYXdTGncaBnB60QrEuazvcob9n4yR65pUNBCF5 # qeA4QwYnilBkfnmeAjRN3LVuLr0g0FXkqfYdUmj1fFFhH8k8YBozrEaXnsSL3kdT # D01X+4LfIWOuFzTzuoslBrBILfHNj8RfOxPgjuwNvE6YzauXi4orp4Sm6tF245Da # FOSYbWFK5ZgG6cUY2/bUq3g3bQAqZt65KcaewEJ3ZyNEobv35Nf6xN6FrA6jF944 # 7+NHvCjeWLCQZ3M8lgeCcnnhTFtyQX3XgCoc6IRXvFOcPVrr3D9RPHCMS6Ckg8wg # gTrtIVnY8yjbvGOUsAdZbeXUIQAWMs0d3cRDv09SvwVRd61evQIDAQABo4ICGzCC # AhcwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRr # aSg6NS9IY0DPe9ivSek+2T3bITBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9z # aXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoA # UwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZ # mAQHJ89QEE9oqKIwgYQGA1UdHwR9MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZp # Y2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5j # cmwwgZQGCCsGAQUFBwEBBIGHMIGEMIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5t # aWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUy # MFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUy # MDIwMjAuY3J0MA0GCSqGSIb3DQEBDAUAA4ICAQBfiHbHfm21WhV150x4aPpO4dhE # mSUVpbixNDmv6TvuIHv1xIs174bNGO/ilWMm+Jx5boAXrJxagRhHQtiFprSjMktT # liL4sKZyt2i+SXncM23gRezzsoOiBhv14YSd1Klnlkzvgs29XNjT+c8hIfPRe9rv # VCMPiH7zPZcw5nNjthDQ+zD563I1nUJ6y59TbXWsuyUsqw7wXZoGzZwijWT5oc6G # vD3HDokJY401uhnj3ubBhbkR83RbfMvmzdp3he2bvIUztSOuFzRqrLfEvsPkVHYn # vH1wtYyrt5vShiKheGpXa2AWpsod4OJyT4/y0dggWi8g/tgbhmQlZqDUf3UqUQsZ # aLdIu/XSjgoZqDjamzCPJtOLi2hBwL+KsCh0Nbwc21f5xvPSwym0Ukr4o5sCcMUc # Sy6TEP7uMV8RX0eH/4JLEpGyae6Ki8JYg5v4fsNGif1OXHJ2IWG+7zyjTDfkmQ1s # nFOTgyEX8qBpefQbF0fx6URrYiarjmBprwP6ZObwtZXJ23jK3Fg/9uqM3j0P01nz # VygTppBabzxPAh/hHhhls6kwo3QLJ6No803jUsZcd4JQxiYHHc+Q/wAMcPUnYKv/ # q2O444LO1+n6j01z5mggCSlRwD9faBIySAcA9S8h22hIAcRQqIGEjolCK9F6nK9Z # yX4lhthsGHumaABdWzCCB5cwggV/oAMCAQICEzMAAABV2d1pJij5+OIAAAAAAFUw # DQYJKoZIhvcNAQEMBQAwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGlt # ZXN0YW1waW5nIENBIDIwMjAwHhcNMjUxMDIzMjA0NjQ5WhcNMjYxMDIyMjA0NjQ5 # WjCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UE # CxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjdEMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVi # bGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBAL25H5IeWUiz9DAlFmn2sPymaFWbvYkMfK+ScIWb3a1I # vOlIwghUDjY0Gp6yMRhfYURiGS0GedIB6ywvuH6VBCX3+bdOFcAclgtv21jrpOjZ # mk4fSaT2Q3BszUfeUJa8o3xI7ZfoMY9dszTxHQAz6ZVX87fHGEVhQcfxW33IdPJO # j/ae419qtYxT21MVmCfsTshgtWioQxmOW/vMC9/b+qgtBxSMf798vm3qfmhF6KCv # FaHlivrM32hY16PGE3L0PFC+LM7vRxU7mTb+r76CeybvqOWk4+dbKYftPhV1t/E5 # S/6wwXeYmu/Y7JC7Tnh2w45G5Y4pcM3oHMb/YuPRdOWa0v+RC2QgmNVWqjuxDiyl # WscXQDuaMtb29AcdGUVV9ZsRY2M2sthAtOdZOshiR5ufMtaHtiCkWv0jNfgUxrHu # rxzYuUNneWZ6EfQDgFAw8CSCKkSOK2c9jEop4ddVq10xvbqxdrqMneVXvvIcXrPQ # AXj9j2ECpV2EwMb3Wnmpw00P78JpzPsk3Fs61ZvOGd/F1RcOBu6f2TWdp7HL7+rq # 7tgHr13MldbfIWu4lpoYYE1gTQa1Yrg5XN4j7zs9klT2z3qocmPzV8DWQgIHNh+a # Ts7bujMEMQyI7Xt1zPxZCgcR6H0tmmzU/9BxvsWbRalCQ2sYGyWupTdc4e7KY7kP # AgMBAAGjggHLMIIBxzAdBgNVHQ4EFgQUVgRfEG3cCAPwyL+pyRbKwdesZbYwHwYD # VR0jBBgwFoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZb # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw # UHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5Bggr # BgEFBQcBAQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0 # YW1waW5nJTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQB # gjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # cGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEB # DAUAA4ICAQBSHuGSVHvalCnFnlsqXIQefH1xP2SFr9g+Vz+f5P7QeywjfQb5jUlS # md1XnJUDPe/MHxL7r3TEElL+mNtG6CDPAytStSFPXD9tTBtBMYh8Wqo64pH9qm36 # 1yIqeBH979mzWCkMQsTd0nM6dUl9B+7qiti+ToXwxIl39eYqLuYYfhD2mqqePXMz # UKSQzkf73yYIVHP6nLJQz4aAmaWcfG9jg78sBkDV8KpW7JgktuLhphJEN1B+SVHj # enPdcmrFXIUu/K4jK5ukfWaQIjuaXzSjBlNjC5tQN6adPfA3GxUwHPeR4ekL5If/ # 9vBf13tmzBW+gy+0sNGTveb9IL9GU8iX8UvywsX62nhCCPRUhTigDBKdczRUrNrn # tBhowbfchBDFML8avRMRc9Gmc2JvIryX336SFQ51//q1UU2HMSJEMhWLJSIWJVhf # UowsOa+PampIzETYfFvTu2mqKJUlWZXkGYxrdCvCczJcqeoadpW1ul6kcdnDh228 # SQ8ZhDc6IRlM4iNd5SNoNgX+aom3wuGyjUaSaPZWxPB1G2NKiYhPLt0lPHg0Gskj # 1zhISY8UQkMMDr3o2JgRuT+wnJEDQUp55ddvhSkSoD6I9DL/s+TjIY/c9jLaW5xy # wJHqdKHUApRMsghv7kebSua1upmR+TquelFktDSOjVdSRkuya4uoxTGCB0Mwggc/ # AgEBMHgwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5n # IENBIDIwMjACEzMAAABV2d1pJij5+OIAAAAAAFUwDQYJYIZIAWUDBAIBBQCgggSc # MBEGCyqGSIb3DQEJEAIPMQIFADAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQw # HAYJKoZIhvcNAQkFMQ8XDTI1MTIwMjEzMjkwOFowLwYJKoZIhvcNAQkEMSIEIGto # OsuRe4NLvZ0/EPb10fgQ/wf7t2PAMyyd/m4Ol+NMMIG5BgsqhkiG9w0BCRACLzGB # qTCBpjCBozCBoAQg2Lk8l2SGYru/ff7+D2qrJnkswcYdK6pGKu7GGGr4/s0wfDBl # pGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENB # IDIwMjACEzMAAABV2d1pJij5+OIAAAAAAFUwggNeBgsqhkiG9w0BCRACEjGCA00w # ggNJoYIDRTCCA0EwggIpAgEBMIIBCaGB4aSB3jCB2zELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdEMDAtMDVFMC1E # OTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5n # IEF1dGhvcml0eaIjCgEBMAcGBSsOAwIaAxUAHTtUAYJlv7bgWVeRBo4X7FeHDeqg # ZzBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5n # IENBIDIwMjAwDQYJKoZIhvcNAQELBQACBQDs2PojMCIYDzIwMjUxMjAyMDUzOTQ3 # WhgPMjAyNTEyMDMwNTM5NDdaMHQwOgYKKwYBBAGEWQoEATEsMCowCgIFAOzY+iMC # AQAwBwIBAAICGIkwBwIBAAICEncwCgIFAOzaS6MCAQAwNgYKKwYBBAGEWQoEAjEo # MCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG # 9w0BAQsFAAOCAQEAZVgJ7uDBWC6P8VlYQG6GQYR8+R06vJs0CIDBrJgaaK5H/AeH # Gp7bZxU3V7k9KtszyJG3rCV96f9ax5+6WyKI0pN3CAhhng6ZeLU9dY5s1TAumi90 # 4IJ6xrMLY/xm42P/MzJ1kfxaHv/+BMljk03xcD1x5DmnVmooK0DRjTmMkgCkPdsK # V+wMT6fWsdJr/o7FsTVunlxTvlR/KVG9SglkKwmphXYSZF6Y3xnfGO4FIAox8x6Y # KZsiNipKSGc1tXOVHTknk3yQoFGkvGoBxYSA+9IEfCBz1roxzpVXNYKrCo/cNqhA # v9x3YmomsSVD49s2FHcuZ4KfApCDu3pQ+gepYTANBgkqhkiG9w0BAQEFAASCAgA/ # 38GNCifPIDCqxBg3UNXDA8V1bIiXCfABmW53lEE4Emcj2vTCDQnhnRMhjehNn7VW # gXhpfg/tA9RTTx9kx0LoEsJD1gvs+diR2fsTlj05EaV0TGjbYXNdLL/3qMyfr4/R # VYW58E8NESz40+abHput9/3VPBH4SK6lBiL6DT26ZoJAGZ4t601tawKIsmeIBc8A # G0DegyImI5CWq2wCNMFv/x5GCewroIfgLp4hsLO3K3R1Dulh5YJkrDHgo9tmZQ1L # 0uHy3NQPeZIwV0g78IfKh5KO+/g9TuXk2cFbAWCbqIcTwHLG3zkGm4MBOC96AtrR # zptCvwDfB6zeo3kJrRnpDusvKeh3eISmPPy2O9FOQ8vrG/FnaF7u1nX/2HuJD0aF # moPKhR6BIlSQLtT9Oe/qfnNWkKBJfv9bdkoVgtsXTstpxpSxEN/xAlpPNtWa5TjD # iV5rbd5RF5sjSbC6sHZMpv8KQZRiW3w03KtskTNHWa5iMnn/nZzN/ntnllf39I0a # deEwjLrb2axpW4bQ45MU1WF3zotElthVT64A5sq8FYl4Pvk1wZj58/8xEIaIXn5X # VY0SYFjXgM8k/flT99Ze5cvlIhVEOtqA1xK6KCn/bFfshd4hA+rVRkmEP8nghAgi # k+ZOletVO5lJZCjR/5x3Nfqrd3D3xDDIg1MJIn5CdQ== # SIG # End signature block |