Public/ServiceEM/New-EntraOpsServiceEMAssignment.ps1

<#
.SYNOPSIS
    Assigns service members and the service owner to their initial access packages.

.DESCRIPTION
    Submits adminAdd assignment requests to place service members into the
    WorkloadPlane-Members access package and the service owner into the
    WorkloadPlane-Members package (unless already assigned). Uses the
    "Initial Workload Membership Policy" assignment policy. Skipped gracefully
    when no WorkloadPlane-Members package or policy exists (e.g. Sub-only
    landing zones).

    Idempotent: existing delivered assignments are detected and skipped.
    Waits up to five minutes for newly submitted requests. A returned assignment list contains only
    delivered assignments; a warning identifies requests whose access is not ready yet.

.PARAMETER ServiceCatalogId
    Object ID of the Entitlement Management catalog. Used to scope assignment
    lookups so only assignments from this catalog are considered.

.PARAMETER ServiceMembers
    Graph User objects to assign to the WorkloadPlane-Members access package.
    Typically the output of Get-MgUser for each service member UPN.

.PARAMETER WorkloadPlaneAdmin
    Graph User object for the workload plane admin. Added to WorkloadPlane-Members
    unless already present via ServiceMembers. Also added to CatalogPlane-Members.

.PARAMETER CatalogPlaneMembers
    Graph User objects added to the CatalogPlane-Members access package through the
    admin-only "Initial Catalog Members Policy" (PerService model only).

.PARAMETER ServiceAssignmentPolicies
    Assignment policy objects returned by New-EntraOpsServiceEMAssignmentPolicy.

.PARAMETER ServicePackages
    Access package objects returned by New-EntraOpsServiceEMAccessPackage.

.PARAMETER AssignmentRequestStatuses
    Optional collection populated with the last observed ID, state, status, target ID and access package ID
    of requests submitted or found open in this run. Used by the bootstrap report to expose unfinished access provisioning.

.PARAMETER logPrefix
    Text prepended to verbose messages. Defaults to the function name.

.EXAMPLE
    New-EntraOpsServiceEMAssignment `
        -ServiceCatalogId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
        -ServiceMembers $graphMembers `
        -WorkloadPlaneAdmin $graphOwner `
        -ServiceAssignmentPolicies $policies `
        -ServicePackages $packages

    Assigns every user in $graphMembers (plus the workload plane admin) to the
    AP-<ServiceName>-WorkloadPlane-Members access package via adminAdd.

#>

function New-EntraOpsServiceEMAssignment {
    [OutputType([psobject[]])]
    [cmdletbinding()]
    param(
        [Parameter(Mandatory)]
        [string]$ServiceCatalogId,

        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [psobject[]]$ServiceMembers,

        [psobject]$WorkloadPlaneAdmin,

        [AllowEmptyCollection()]
        [psobject[]]$CatalogPlaneMembers = @(),

        [Parameter(Mandatory)]
        [psobject[]]$ServiceAssignmentPolicies,
        
        [Parameter(Mandatory)]
        [psobject[]]$ServicePackages,

        [Parameter(DontShow)]
        [AllowEmptyCollection()]
        [System.Collections.Generic.List[object]]$AssignmentRequestStatuses,

        [string]$logPrefix = "[$($MyInvocation.MyCommand)]"
    )

    begin {
        $assignmentRequests = @()
        $assignments = @()

        # Open requests of the catalog's access packages; filtering by package avoids reading all requests of the tenant
        $openStates = @('submitted', 'pendingApproval', 'delivering', 'scheduled')
        foreach ($package in @($ServicePackages | Where-Object { $_.Id })) {
            $assignmentRequestsUri = "/v1.0/identityGovernance/entitlementManagement/assignmentRequests?`$expand=assignment(`$expand=target),accessPackage&`$filter=accessPackage/id eq '$($package.Id)'"
            try{
                Write-Verbose "$logPrefix Looking up open assignment requests of $($package.DisplayName)"
                # -ThrowOnFailure: a failed lookup must not look like "no open requests" and submit duplicate requests
                $assignmentRequests += @(Invoke-EntraOpsMsGraphQuery -Method GET -Uri $assignmentRequestsUri -OutputType PSObject -DisableCache -ThrowOnFailure) | Where-Object { $_ -and "$($_.State)" -in $openStates }
            }catch{
                throw "$logPrefix Failed to look up the open assignment requests of $($package.DisplayName); no assignment request was submitted: $($_.Exception.Message)"
            }
        }

        if ($null -ne $AssignmentRequestStatuses) {
            foreach ($request in $assignmentRequests) {
                $AssignmentRequestStatuses.Add([pscustomobject]@{
                    Id = $request.Id; State = $request.State; Status = $request.Status
                    TargetId = $request.Assignment.Target.ObjectId; AccessPackageId = $request.AccessPackage.Id
                })
            }
        }

        $encodedServiceCatalogId = ConvertTo-EntraOpsODataStringLiteral -Value $ServiceCatalogId
        $assignmentsSplat = "/v1.0/identityGovernance/entitlementManagement/assignments?`$filter=accessPackage/catalog/id eq '$encodedServiceCatalogId' and state eq 'delivered'&`$expand=accessPackage(`$expand=catalog),accessPackage,target"
        Write-Verbose "$logPrefix $($assignmentsSplat)"
        try{
            $assignments += Invoke-EntraOpsMsGraphQuery -Method GET -Uri $assignmentsSplat -OutputType PSObject -DisableCache -ThrowOnFailure
            if(($assignments|Measure-Object).Count -gt 0){
                Write-Verbose "$logPrefix Found Access Package Assignment IDs: $($assignments.Id|ConvertTo-Json -Compress)"
            }
        }catch{
            # A failed lookup must not look like "no assignments" and submit duplicate requests
            throw "$logPrefix Failed to look up the access package assignments of catalog ${ServiceCatalogId}; no assignment request was submitted: $($_.Exception.Message)"
        }

        # A user may hold one package and still need another, so existing access is keyed per target and package
        $existingAccess = @{}
        foreach ($assignment in @($assignments | Where-Object { $_ })) {
            $existingAccess["$($assignment.Target.ObjectId)|$($assignment.AccessPackage.Id)"] = 'delivered'
        }
        foreach ($request in @($assignmentRequests | Where-Object { $_ })) {
            $existingAccess["$($request.Assignment.Target.ObjectId)|$($request.AccessPackage.Id)"] = "request $($request.State)"
        }
        $getExistingAccess = { param($TargetId, $AccessPackageId) $existingAccess["$TargetId|$AccessPackageId"] }

        $wlMembersPackage = $ServicePackages|Where-Object{$_.DisplayName -like "*WorkloadPlane-Members"}
        $wlMembersPolicy  = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Initial Workload Membership Policy"}
        # Rg scope fallback: no WorkloadPlane-Members access package - use WorkloadPlane-Users
        if(-not $wlMembersPackage){
            $wlMembersPackage = $ServicePackages|Where-Object{$_.DisplayName -like "*WorkloadPlane-Users"}
            # Admin-only direct policy without approval; the request policy is the fallback for older landing zones
            $wlMembersPolicy  = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Initial Workload Users Policy"}
            if(-not $wlMembersPolicy){
                $wlMembersPolicy = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Workload Plane Users Policy"}
            }
        }
        $assignmentParams = @{
            requestType = "adminAdd"
            assignment = @{
                targetId = ""
                assignmentPolicyId = $wlMembersPolicy.Id
                accessPackageId    = $wlMembersPackage.Id
            }
        }
        # Requests accepted by Graph in this run; only these are awaited in the end block.
        $submittedRequests = [System.Collections.Generic.List[psobject]]::new()

        $assignmentRequestUri = "/v1.0/identityGovernance/entitlementManagement/assignmentRequests"
        $adminOnlyPolicyNames = @('Initial Workload Users Policy', 'Initial Workload Admin Policy', 'Initial Management Admin Policy', 'Initial Catalog Members Policy')
        $addTargetToPolicy = {
            param($Policy, [string]$TargetId)
            $policyUri = "/v1.0/identityGovernance/entitlementManagement/assignmentPolicies/$($Policy.Id)"
            $current = Invoke-EntraOpsMsGraphQuery -Method GET -Uri "$($policyUri)?`$expand=accessPackage" -OutputType PSObject -DisableCache -ThrowOnFailure
            if (-not $current -or -not $current.Id) { return $false }
            $targets = @(if ($current.AllowedTargetScope -eq 'specificDirectoryUsers') { $current.SpecificAllowedTargets | Where-Object { $_ } })
            if ($targets | Where-Object { $_.UserId -eq $TargetId }) { return $false }
            $policyBody = [ordered]@{
                displayName             = $current.DisplayName
                description             = $current.Description
                allowedTargetScope      = 'specificDirectoryUsers'
                specificAllowedTargets  = @($targets) + @(@{ '@odata.type' = '#microsoft.graph.singleUser'; userId = $TargetId })
                expiration              = $current.Expiration
                requestorSettings       = $current.RequestorSettings
                requestApprovalSettings = $current.RequestApprovalSettings
                accessPackage           = @{ id = $current.AccessPackage.Id }
            }
            if ($current.ReviewSettings) { $policyBody.reviewSettings = $current.ReviewSettings }
            try {
                Invoke-EntraOpsMsGraphQuery -Method PUT -Uri $policyUri -Body ($policyBody | ConvertTo-Json -Depth 20) -OutputType PSObject -ThrowOnFailure | Out-Null
            } catch {
                Write-Warning "$logPrefix Failed to add $TargetId to the scope of policy '$($current.DisplayName)': $($_.Exception.Message)"
                return $false
            }
            Write-Verbose "$logPrefix Added $TargetId as specific user to policy '$($current.DisplayName)'"
            return $true
        }
        # Entra ID ignores "all members" policies for users in scope of a policy for specific users of the
        # same access package (e.g. the Workload Plane Policy), so the target is added to the admin-only policy
        $submitAssignment = {
            param($Policy, [string]$TargetId)
            $requestBody = $assignmentParams | ConvertTo-Json -Depth 10
            if ($Policy.DisplayName -notin $adminOnlyPolicyNames) {
                return Invoke-EntraOpsMsGraphQuery -Method POST -Uri $assignmentRequestUri -Body $requestBody -OutputType PSObject -ThrowOnFailure
            }
            try {
                return Invoke-EntraOpsMsGraphQuery -Method POST -Uri $assignmentRequestUri -Body $requestBody -OutputType PSObject -ThrowOnFailure -SuppressBadRequestWarning
            } catch {
                if ($_.Exception.Data['StatusCode'] -ne 400) { throw }
                $rejectionCode = $_.Exception.Data['ErrorCode']
            }
            Write-Verbose "$logPrefix $TargetId isn't accepted by policy '$($Policy.DisplayName)' ($rejectionCode), adding the user to its scope"
            if (-not (& $addTargetToPolicy $Policy $TargetId)) {
                return Invoke-EntraOpsMsGraphQuery -Method POST -Uri $assignmentRequestUri -Body $requestBody -OutputType PSObject -ThrowOnFailure
            }
            $retry = @{}
            $accepted = Wait-EntraOpsServiceEMCondition -Activity "Updated scope of policy '$($Policy.DisplayName)'" -MaxWaitSeconds 60 -logPrefix $logPrefix -Condition {
                try {
                    $retry.Result = Invoke-EntraOpsMsGraphQuery -Method POST -Uri $assignmentRequestUri -Body $requestBody -OutputType PSObject -ThrowOnFailure -SuppressBadRequestWarning
                    $null -ne $retry.Result
                } catch { $false }
            }
            if ($accepted) { return $retry.Result }
            return Invoke-EntraOpsMsGraphQuery -Method POST -Uri $assignmentRequestUri -Body $requestBody -OutputType PSObject -ThrowOnFailure
        }
        # Failed requests don't stop the other assignments; they are reported together at the end
        $assignmentFailures = [System.Collections.Generic.List[string]]::new()
    }

    process {
        Write-Verbose "$logPrefix Beginning EM Assignment"

        if(-not $wlMembersPackage -or -not $wlMembersPolicy){
            Write-Verbose "$logPrefix WorkloadPlane-Members access package or policy not found (Sub-only landing zone?), skipping member assignments"
        } else {
            foreach($member in $ServiceMembers){
                Write-Verbose "$logPrefix Processing Service Member ID: $($member.Id)"
                $assignmentParams.assignment.targetId = $member.Id
                $existingMemberAccess = & $getExistingAccess $member.Id $wlMembersPackage.Id
                if($existingMemberAccess){
                    Write-Verbose "$logPrefix Member $($member.Id) already has access package $($wlMembersPackage.DisplayName) ($existingMemberAccess), skipping"
                } else {
                    try{
                        Write-Verbose "$logPrefix Creating Assignment Request"
                        $postResult = & $submitAssignment $wlMembersPolicy $member.Id
                        if($null -ne $postResult){
                            $assignmentRequests += $postResult
                            $existingAccess["$($member.Id)|$($wlMembersPackage.Id)"] = "request $($postResult.State)"
                            $submittedRequests.Add([pscustomobject]@{ Id = $postResult.Id; State = $postResult.State; Status = $postResult.Status; TargetId = $member.Id; AccessPackageId = $wlMembersPackage.Id })
                        } else {
                            Write-Warning "$logPrefix Assignment request for member $($member.Id) was rejected. Check that the user is in the allowed target scope of policy '$($wlMembersPolicy.DisplayName)'."
                        }
                    }catch{
                        Write-Verbose "$logPrefix Failed to create Assignment Request"
                        $assignmentFailures.Add("member $($member.Id) to $($wlMembersPackage.DisplayName): $($_.Exception.Message)")
                    }
                }
            }
        }

        # Enroll the workload plane admin: prefer ManagementPlane-Admins; fall back to WorkloadPlane-Admins
        # (Centralized governance - ManagementPlane-Admins is delegated to tenant-wide group).
        $mgmtAdminsPackage = $ServicePackages|Where-Object{$_.DisplayName -like "*ManagementPlane-Admins"}
        $mgmtAdminsPolicy  = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Initial Management Admin Policy"}
        if(-not $mgmtAdminsPackage){
            $mgmtAdminsPackage = $ServicePackages|Where-Object{$_.DisplayName -like "*WorkloadPlane-Admins"}
            $mgmtAdminsPolicy  = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Initial Workload Admin Policy"}
            if(-not $mgmtAdminsPolicy){
                $mgmtAdminsPolicy = $ServiceAssignmentPolicies|Where-Object{$_.DisplayName -eq "Workload Plane Policy"}
            }
        }
        if($mgmtAdminsPackage -and $mgmtAdminsPolicy -and $WorkloadPlaneAdmin){
            $existingAdminAccess = & $getExistingAccess $WorkloadPlaneAdmin.Id $mgmtAdminsPackage.Id
            if($existingAdminAccess){
                Write-Verbose "$logPrefix Workload plane admin $($WorkloadPlaneAdmin.Id) already has access package $($mgmtAdminsPackage.DisplayName) ($existingAdminAccess), skipping"
            } else {
                try{
                    $assignmentParams.assignment.targetId = $WorkloadPlaneAdmin.Id
                    $assignmentParams.assignment.assignmentPolicyId = $mgmtAdminsPolicy.Id
                    $assignmentParams.assignment.accessPackageId = $mgmtAdminsPackage.Id
                    Write-Verbose "$logPrefix Creating Assignment Request for Workload Plane Admin - $($assignmentParams|ConvertTo-Json -Compress)"
                    $postResult = & $submitAssignment $mgmtAdminsPolicy $WorkloadPlaneAdmin.Id
                    if($null -ne $postResult){
                        $assignmentRequests += $postResult
                        $submittedRequests.Add([pscustomobject]@{ Id = $postResult.Id; State = $postResult.State; Status = $postResult.Status; TargetId = $WorkloadPlaneAdmin.Id; AccessPackageId = $mgmtAdminsPackage.Id })
                    } else {
                        Write-Warning "$logPrefix Assignment request for workload plane admin $($WorkloadPlaneAdmin.Id) was rejected. Check that the user is in the allowed target scope of policy '$($mgmtAdminsPolicy.DisplayName)'."
                    }
                }catch{
                    Write-Verbose "$logPrefix Failed to create Assignment Request for Workload Plane Admin"
                    $assignmentFailures.Add("workload plane admin $($WorkloadPlaneAdmin.Id) to $($mgmtAdminsPackage.DisplayName): $($_.Exception.Message)")
                }
            }
        } else {
            Write-Verbose "$logPrefix No suitable workload plane admin assignment conditions met, skipping workload plane admin assignment"
        }

        # CatalogPlane-Members is the requestor group of the catalog and can't be requested by non-members
        $catalogMembersPackage = $ServicePackages | Where-Object { $_.DisplayName -like "*CatalogPlane-Members" } | Select-Object -First 1
        $catalogMembersPolicy  = $ServiceAssignmentPolicies | Where-Object { $_.DisplayName -eq "Initial Catalog Members Policy" } | Select-Object -First 1
        $catalogTargets = @(@($CatalogPlaneMembers) + @($WorkloadPlaneAdmin) | Where-Object { $_ -and $_.Id } | Sort-Object -Property Id -Unique)
        if ($catalogTargets.Count -gt 0 -and (-not $catalogMembersPackage -or -not $catalogMembersPolicy)) {
            Write-Verbose "$logPrefix CatalogPlane-Members access package or Initial Catalog Members Policy not found (delegated administrator group?), skipping CatalogPlane-Members assignments"
        } elseif ($catalogTargets.Count -gt 0) {
            foreach ($catalogTarget in $catalogTargets) {
                if (& $getExistingAccess $catalogTarget.Id $catalogMembersPackage.Id) {
                    Write-Verbose "$logPrefix $($catalogTarget.Id) already has access package $($catalogMembersPackage.DisplayName), skipping"
                    continue
                }
                $assignmentParams.assignment.targetId = $catalogTarget.Id
                $assignmentParams.assignment.assignmentPolicyId = $catalogMembersPolicy.Id
                $assignmentParams.assignment.accessPackageId = $catalogMembersPackage.Id
                try {
                    Write-Verbose "$logPrefix Creating CatalogPlane-Members Assignment Request for $($catalogTarget.Id)"
                    $postResult = & $submitAssignment $catalogMembersPolicy $catalogTarget.Id
                    if ($null -ne $postResult) {
                        $assignmentRequests += $postResult
                        $existingAccess["$($catalogTarget.Id)|$($catalogMembersPackage.Id)"] = "request $($postResult.State)"
                        $submittedRequests.Add([pscustomobject]@{ Id = $postResult.Id; State = $postResult.State; Status = $postResult.Status; TargetId = $catalogTarget.Id; AccessPackageId = $catalogMembersPackage.Id })
                    } else {
                        Write-Warning "$logPrefix Assignment request of CatalogPlane-Members for $($catalogTarget.Id) was rejected. Check that the user is in the allowed target scope of policy '$($catalogMembersPolicy.DisplayName)'."
                    }
                } catch {
                    Write-Verbose "$logPrefix Failed to create CatalogPlane-Members Assignment Request"
                    $assignmentFailures.Add("$($catalogTarget.Id) to $($catalogMembersPackage.DisplayName): $($_.Exception.Message)")
                }
            }
        }
    }

    end {
        $throwAssignmentFailures = {
            if ($assignmentFailures.Count -gt 0) {
                throw "$logPrefix Failed to create $($assignmentFailures.Count) access package assignment request(s); re-run the deployment after resolving: $($assignmentFailures -join '; ')"
            }
        }
        # Nothing was submitted in this run — no point waiting for fulfillment.
        if($submittedRequests.Count -eq 0){
            & $throwAssignmentFailures
            Write-Verbose "$logPrefix No new assignment requests submitted, skipping consistency check"
            return [psobject[]]@()
        }

        if ($null -ne $AssignmentRequestStatuses) {
            foreach ($request in $submittedRequests) { $AssignmentRequestStatuses.Add($request) }
        }
        $check = @{ Pending = @($submittedRequests); Checks = 0 }
        $completed = Wait-EntraOpsServiceEMCondition -Activity "Assignment request fulfillment" -logPrefix $logPrefix -ProgressStatus { "$($check.Pending.Count) of $($submittedRequests.Count) access request(s) pending" } -Condition {
            $stillPending = @()
            foreach($request in $check.Pending){
                $current = Invoke-EntraOpsMsGraphQuery -Method GET -Uri "/v1.0/identityGovernance/entitlementManagement/assignmentRequests/$($request.Id)" -OutputType PSObject -DisableCache -ThrowOnFailure
                $state = if($current -and $current.State){ $current.State } else { $request.State }
                $request.State = $state
                $request.Status = $current.Status
                $requestLabel = "Assignment request $($request.Id) (target $($request.TargetId), access package $($request.AccessPackageId))"
                if($state -in @('delivered','partiallyDelivered')){
                    Write-Verbose "$logPrefix $requestLabel is $state"
                } elseif($state -in @('deliveryFailed','denied','canceled')){
                    Write-Warning "$logPrefix $requestLabel ended in state '$state' (status: $($current.Status))"
                } elseif($state -eq 'pendingApproval'){
                    Write-Warning "$logPrefix $requestLabel is waiting for approval and is not awaited"
                } else {
                    $stillPending += $request
                }
            }
            $check.Pending = $stillPending
            $check.Checks++
            if($check.Pending.Count -gt 0){
                Write-Verbose "$logPrefix $($check.Pending.Count) of $($submittedRequests.Count) assignment request(s) pending: $(($check.Pending | ForEach-Object { "$($_.Id)=$($_.State) (status '$($_.Status)', target $($_.TargetId), access package $($_.AccessPackageId))" }) -join ', ')"
                if($check.Checks -eq 5){
                    Write-Warning "$logPrefix Fulfillment can take 5+ minutes to complete"
                }
            }
            $check.Pending.Count -eq 0
        }
        if(-not $completed){
            Write-Warning "$logPrefix Assignment requests not fulfilled within the 300-second wait budget, continuing without waiting; access for these requests is not ready: $(($check.Pending | ForEach-Object { "$($_.Id)=$($_.State) (status '$($_.Status)', target $($_.TargetId), access package $($_.AccessPackageId))" }) -join ', ')"
        }

        # Requests that were submitted are awaited first, so a re-run finds them as existing access
        & $throwAssignmentFailures

        $checkAssignments = @()
        $checkAssignments += Invoke-EntraOpsMsGraphQuery -Method GET -Uri $assignmentsSplat -OutputType PSObject -DisableCache -ThrowOnFailure
        return [psobject[]]$checkAssignments
    }
}
# SIG # Begin signature block
# MIIniAYJKoZIhvcNAQcCoIIneTCCJ3UCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAo9etvctP9wIS2
# WWmyYJFz3G5OMO+UZHZ4sufjWttt+qCCIDwwggXJMIIEsaADAgECAhAbtY8lKt8j
# AEkoya49fu0nMA0GCSqGSIb3DQEBDAUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
# ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
# dGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5l
# dHdvcmsgQ0EwHhcNMjEwNTMxMDY0MzA2WhcNMjkwOTE3MDY0MzA2WjCBgDELMAkG
# A1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAl
# BgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMb
# Q2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEAvfl4+ObVgAxknYYblmRnPyI6HnUBfe/7XGeMycxca6mR5rlC
# 5SBLm9qbe7mZXdmbgEvXhEArJ9PoujC7Pgkap0mV7ytAJMKXx6fumyXvqAoAl4Va
# qp3cKcniNQfrcE1K1sGzVrihQTib0fsxf4/gX+GxPw+OFklg1waNGPmqJhCrKtPQ
# 0WeNG0a+RzDVLnLRxWPa52N5RH5LYySJhi40PylMUosqp8DikSiJucBb+R3Z5yet
# /5oCl8HGUJKbAiy9qbk0WQq/hEr/3/6zn+vZnuCYI+yma3cWKtvMrTscpIfcRnNe
# GWJoRVfkkIJCu0LW8GHgwaM9ZqNd9BjuiMmNF0UpmTJ1AjHuKSbIawLmtWJFfzcV
# WiNoidQ+3k4nsPBADLxNF8tNorMe0AZa3faTz1d1mfX6hhpneLO/lv403L3nUlbl
# s+V1e9dBkQXcXWnjlQ1DufyDljmVe2yAWk8TcsbXfSl6RLpSpCrVQUYJIP4ioLZb
# MI28iQzV13D4h1L92u+sUS4Hs07+0AnacO+Y+lbmbdu1V0vc5SwlFcieLnhO+Nqc
# noYsylfzGuXIkosagpZ6w7xQEmnYDlpGizrrJvojybawgb5CAKT41v4wLsfSRvbl
# jnX98sy50IdbzAYQYLuDNbdeZ95H7JlI8aShFf6tjGKOOVVPORa5sWOd/7cCAwEA
# AaOCAT4wggE6MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLahVDkCw6A/joq8
# +tT4HKbROg79MB8GA1UdIwQYMBaAFAh2zcsH/yT2xc3tu5C84oQ3RnX3MA4GA1Ud
# DwEB/wQEAwIBBjAvBgNVHR8EKDAmMCSgIqAghh5odHRwOi8vY3JsLmNlcnR1bS5w
# bC9jdG5jYS5jcmwwawYIKwYBBQUHAQEEXzBdMCgGCCsGAQUFBzABhhxodHRwOi8v
# c3ViY2Eub2NzcC1jZXJ0dW0uY29tMDEGCCsGAQUFBzAChiVodHRwOi8vcmVwb3Np
# dG9yeS5jZXJ0dW0ucGwvY3RuY2EuY2VyMDkGA1UdIAQyMDAwLgYEVR0gADAmMCQG
# CCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMwDQYJKoZIhvcNAQEM
# BQADggEBAFHCoVgWIhCL/IYx1MIy01z4S6Ivaj5N+KsIHu3V6PrnCA3st8YeDrJ1
# BXqxC/rXdGoABh+kzqrya33YEcARCNQOTWHFOqj6seHjmOriY/1B9ZN9DbxdkjuR
# mmW60F9MvkyNaAMQFtXx0ASKhTP5N+dbLiZpQjy6zbzUeulNndrnQ/tjUoCFBMQl
# lVXwfqefAcVbKPjgzoZwpic7Ofs4LphTZSJ1Ldf23SIikZbr3WjtP6MZl9M7JYjs
# NhI9qX7OAo0FmpKnJ25FspxihjcNpDOO16hO0EoXQ0zF8ads0h5YbBRRfopUofbv
# n3l6XYGaFpAP4bvxSgD5+d2+7arszgowggZrMIIEU6ADAgECAhBX5gfP8LabvnxC
# XoItEBa/MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhB
# c3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNp
# Z25pbmcgMjAyMSBDQTAeFw0yNjEwMDYwODI4MjNaFw0yNzEwMDYwODI4MjJaMIGQ
# MQswCQYDVQQGEwJERTEdMBsGA1UECAwUUmhpbmVsYW5kLVBhbGF0aW5hdGUxEjAQ
# BgNVBAcMCUxhaG5zdGVpbjEeMBwGA1UECgwVT3BlbiBTb3VyY2UgRGV2ZWxvcGVy
# MS4wLAYDVQQDDCVPcGVuIFNvdXJjZSBEZXZlbG9wZXIgVGhvbWFzIE5hdW5oZWlt
# MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAphp2ljSmVsRB6gvkEq7A
# DUMENpKZiDFoAfF1ktD1nCwaVyI+bJ0ROjHwAn4iJgS+vlBDPOUIw2GLHkiqUhOg
# HSwzg6gj45GNmt6zxsKP0zPlhMB/fb0zmz7/F7e3yfKCXLfhbHuk0Es9gJ+8Wmet
# 9StVwwSE/K0MpW06GKA9nPWyE4N/ADwigDIj9rsTKJR4cve9w8G1b3zohpUc/qMr
# onab+HVw5r9b3sOBnnaXC6zvrX4fovRz1ztwfWjRjILLoFG6mW/TuK5F2ICD3Rhl
# 9R2rJWWWhzTDMsQlzvX+/SaM74q3OFpIVNdhvtmWU9pKUBRAyYMijcDqKEFGSzrc
# 8JFmGMpP5TuroWF+N21d3px2eARvW1mV0DCfFAH+Og20SH/gVW6/ltQQEkH/z/Zt
# 49ARyJrgESLOQtlMCIYSoKISdkk4ml4VUS1E/PcbzXEYj3a7m6DOxcd3WuY03UT9
# cnk3p0LMN6LeLYAZgVY+HRloZlH+kW2SkOHNuWgtXvZhAgMBAAGjggF4MIIBdDAM
# BgNVHRMBAf8EAjAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jY3NjYTIwMjEu
# Y3JsLmNlcnR1bS5wbC9jY3NjYTIwMjEuY3JsMHMGCCsGAQUFBwEBBGcwZTAsBggr
# BgEFBQcwAYYgaHR0cDovL2Njc2NhMjAyMS5vY3NwLWNlcnR1bS5jb20wNQYIKwYB
# BQUHMAKGKWh0dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jY3NjYTIwMjEuY2Vy
# MB8GA1UdIwQYMBaAFN10XUwA23ufoHTKsW73PMAywHDNMB0GA1UdDgQWBBTBvGyH
# MXj1dMbVnxuof9oP4PY7cDBLBgNVHSAERDBCMAgGBmeBDAEEATA2BgsqhGgBhvZ3
# AgUBBDAnMCUGCCsGAQUFBwIBFhlodHRwczovL3d3dy5jZXJ0dW0ucGwvQ1BTMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF
# AAOCAgEAkC165c7/r6y3VeEEpNXas9bQs6ZpKPdJffHkf9xoPi4kWvAIWGc4ocG1
# DJLb18RXiDYShDmT5sb/6I08FeipKi2DNJkuOq6yOTJ3S7+hNFIZCyd6i7WKO8ea
# P5I+FAbyJP4+5coZoMg45bUa9JoocaJCm+5n7WiCfN7/EQpClW5Trm4+ZMbp7EMN
# F1uLJgGCMnN0SsoUarp7PHlqupMxMC4Uhhe+lAP2ytcSIU81L97/qjrADbLWqICk
# 9il5iGM+aZndguq/cmfH9rJj4GRZHWnG6WwnzYD9+KgYlRI6em+/9dq+IRiXe2Bs
# thUuIaFW7U2gWw8tBTEYm1UBLHdJx+L1gjJCLs5KT/wy5wU32wZxNDqPUQejUC1x
# GvU3cKqmLgRq+yNf3gFVfzqIoggyM3U9wQvnk7nBtCkpjXS2hdx4yxzcmrlWsDHr
# z6+6/jeyQySzbYUlFmKnc4n9Mw2soHOajEua5poFARVRS5KgUBuiiQ21YFNYzWBo
# qGuECaaAI/C5rGxapMJ3dAOBnHw6NLqBet+ZXBJEccX5y89MLlOQu+jDmJP8HieR
# qDLlwfhVZnw4RY8Rus43NZBwhNlVuOUXqocHKmJhKNlekda3qsJj93eQBQOxKJcc
# w5O08q9jukpH2+yzFAj+7ll33DuNUgWptogc4Awtbx3glzcEvJQwggaCMIIEaqAD
# AgECAhAo8HfBHDa9/l90MkdwJy4DMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYT
# AlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMT
# G0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQTAeFw0yNjAzMTEwNzM0NTRaFw0z
# NjAyMjcwNzM0NTRaMFAxCzAJBgNVBAYTAlBMMSEwHwYDVQQKDBhBc3NlY28gRGF0
# YSBTeXN0ZW1zIFMuQS4xHjAcBgNVBAMMFUNlcnR1bSBUaW1lc3RhbXAgMjAyNjCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALi9zfBw+xI12hi2F9uNQBNO
# STkTIi13fuh3DiWybI5392bBfJw6tO7zDs7UqP/rejVf4xFTU3XNOPsuOFkP5SPF
# snWwn3VJL+NhNhsuujvYsQtaQnvNo1wk46reTgws1L8OFEdKaxgyqT4zOQx81mLw
# NZSqXNU9Rrb9oAJWJF4Mydz+C1ebu0D0+vgM3tqAQ8TU203fqgKCPqIdHloaFqH9
# eyR+8tnpmy2hnnN59ZOtmsuHeRwf5iTOhlhf0d/qqquLOSIGPgGVL1Hj5XBUox2O
# E7tQRr+l/xxNbL6OuwBO4Aa2EbuxYg37cpXv5i2/lTL4NASB/duf9W4fjA3Ro+GP
# +bC54n2OYiM3Cq8z92ejx8F5HWO2e4/75eC95B9tMw/eq7109GDyW2+2ut5Bn0o8
# MXJTERkyystWbqcnUkomA97qfiDCwvpWuOMdfTOksXe9S+xDxOJaCbiyTivgPulx
# cT+tfQTRXBr5UwtPvc+INnafOEilzVHA11tv+pHcylryxBc08cUihf/ttqkZS0bm
# x3VxQay8uohaTp0//ECA9vYGW51SKdJMJhXvKyIdBLy8WYNchTt8yRITv9Adxg9J
# qGujh+TnP1bW3aQjFtlEl7SzgNeI8OVA/CJAWWUuRT3Au9ToOpHy/flrrknhN4he
# Ew7/6ILMv4HSsj0YZ4otAgMBAAGjggFQMIIBTDB1BggrBgEFBQcBAQRpMGcwOwYI
# KwYBBQUHMAKGL2h0dHA6Ly9zdWJjYS5yZXBvc2l0b3J5LmNlcnR1bS5wbC9jdHNj
# YTIwMjEuY2VyMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0dW0u
# Y29tMB8GA1UdIwQYMBaAFL5UAi+/QGxzQ86sCSVOnkNEGu7gMAwGA1UdEwEB/wQC
# MAAwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL3N1YmNhLmNybC5jZXJ0dW0ucGwv
# Y3RzY2EyMDIxLmNybDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8E
# BAMCB4AwIgYDVR0gBBswGTAIBgZngQwBBAIwDQYLKoRoAYb2dwIFAQswHQYDVR0O
# BBYEFCM5aiirmhKnpKfyH/lFmr+N/oIDMA0GCSqGSIb3DQEBDAUAA4ICAQBm/pOb
# rAveTqYFPCSthxNVwBHTW4TfuBQY2KGCdMlH6ALjVPYf2XARNGMTXScR0JQ2/c2L
# xLpoHHhRwxFf3d933DhFS165rYj6iPSQKm41rc9AMpTCjMdmai1aK9o870pOzTzL
# RhWFVIxm+5Qf+t4V5z14tPoUsAWdfRKD1Zzvzfe5AHlE9rxOZcGROiULxs3Edf7Z
# J8RZI0jzD9juj2oEX2XS7BVKuNCK1W0h1mjapv028yqo8UtZh5/1Ib48Yyp88BDY
# Shh5PSGUUuS5tYXVfcduIPBe3PdNTYRYdT5VNxkwLgjMzIcr/6SH2fejFJDjnCxj
# vXLuarErJg/IdI+hXdGIBDVOGv1zrkF4ktoQvFZIp5DIAYh0GwyUhc87qqn5UaYT
# j2+iyiBDSNh7aGCrkuAnqg7Qh7frhX+QhMGeJ9SpLpnG76qN85hLyjvYR6gRYiLT
# j8G4fxjqV400/buPw0rBo9yJZyq/8cGdCOLPOYf9qpefTcrZKeO9pg+UJHx8UABb
# aTqizRxm8sUSEycccCCFhIit3AI/3wGuSOADeiA676NcQ7+dsP04YvzvdN7pTZNy
# g672WpBDJdg0eItHl4yomvNeIOWh1qs4QqOW6TI8Ocsi4uSDTLorxLUDnBTwKQzz
# pxd1YUctEgRh32R0J9FkFkeEruJU94RljFr1uDCCBrkwggShoAMCAQICEQCZo4AK
# JlU7ZavcboSms+o5MA0GCSqGSIb3DQEBDAUAMIGAMQswCQYDVQQGEwJQTDEiMCAG
# A1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVt
# IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3Rl
# ZCBOZXR3b3JrIENBIDIwHhcNMjEwNTE5MDUzMjE4WhcNMzYwNTE4MDUzMjE4WjBW
# MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
# MSQwIgYDVQQDExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwggIiMA0GCSqG
# SIb3DQEBAQUAA4ICDwAwggIKAoICAQCdI88EMCM7wUYs5zNzPmNdenW6vlxNur3r
# Lfi+5OZ+U3iZIB+AspO+CC/bj+taJUbMbFP1gQBJUzDUCPx7BNLgid1TyztVLn52
# NKgxxu8gpyTr6EjWyGzKU/gnIu+bHAse1LCitX3CaOE13rbuHbtrxF2tPU8f253Q
# gX6eO8yTbGps1Mg+yda3DcTsOYOhSYNCJiL+5wnjZ9weoGRtvFgMHtJg6i671OPX
# IciiHO4Lwo2p9xh/tnj+JmCQEn5QU0NxzrOiRna4kjFaA9ZcwSaG7WAxeC/xoZSx
# F1oK1UPZtKVt+yrsGKqWONoK6f5EmBOAVEK2y4ATDSkb34UD7JA32f+Rm0wsr5aj
# zftDhA5mBipVZDjHpwzv8bTKzCDUSUuUmPo1govD0RwFcTtMXcfJtm1i+P2UNXad
# PyYVKRxKQATHN3imsfBiNRdN5kiVVeqP55piqgxOkyt+HkwIA4gbmSc3hD8ke66t
# 9MjlcNg73rZZlrLHsAIV/nJ0mmgSjBI/TthoGJDydekOQ2tQD2Dup/+sKQptalDl
# ui59SerVSJg8gAeV7N/ia4mrGoiez+SqV3olVfxyLFt3o/OQOnBmjhKUANoKLYlK
# mUpKEFI0PfoT8Q1W/y6s9LTI6ekbi0igEbFUIBE8KDUGfIwnisEkBw5KcBZ3XwnH
# mfznwlKo8QIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
# 3XRdTADbe5+gdMqxbvc8wDLAcM0wHwYDVR0jBBgwFoAUtqFUOQLDoD+Oirz61Pgc
# ptE6Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDAGA1Ud
# HwQpMCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5jcmwwbAYI
# KwYBBQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0
# dW0uY29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwv
# Y3RuY2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYYaHR0
# cDovL3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQB1iFgP5Y9Q
# KJpTnxDsQ/z0O23JmoZifZdEOEmQvo/79PQg9nLF/GJe6ZiUBEyDBHMtFRK0mXj3
# Qv3gL0sYXe+PPMfwmreJHvgFGWQ7XwnfMh2YIpBrkvJnjwh8gIlNlUl4KENTK5DL
# qsYPEtRQCw7R6p4s2EtWyDDr/M58iY2UBEqfUU/ujR9NuPyKk0bEcEi62JGxauFY
# zZ/yld13fHaZskIoq2XazjaD0pQkcQiIueL0HKiohS6XgZuUtCKA7S6CHttZEsOb
# QJ1j2s0urIDdqF7xaXFVaTHKtAuMfwi0jXtF3JJphrJfc+FFILgCbX/uYBPBlbBI
# P4Ht4xxk2GmfzMn7oxPITpigQFJFWuzTMUUgdRHTxaTSKRJ/6Uh7ki/pFjf9sUAS
# WgxT69QF9Ki4JF5nBIujxZ2sOU9e1HSCJwOfK07t5nnzbs1LbHuAIGJsRJiQ6HX/
# DW1XFOlXY1rc9HufFhWU+7Uk+hFkJsfzqBz3pRO+5aI6u5abI4Qws4YaeJH7H7M8
# X/YNoaArZbV4Ql+jarKsE0+8XvC4DJB+IVcvC9Ydqahi09mjQse4fxfef0L7E3hh
# o2O3bLDM6v60rIRUCi2fJT2/IRU5ohgyTch4GuYWefSBsp5NPJh4QRTP9DC3gc5Q
# EKtbrTY0Ka87Web7/zScvLmvQBm8JDFpDjCCBrkwggShoAMCAQICEQDn/2nHOzXO
# S5Em2HR8aKWHMA0GCSqGSIb3DQEBDAUAMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UE
# ChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
# cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBO
# ZXR3b3JrIENBIDIwHhcNMjEwNTE5MDUzMjA3WhcNMzYwNTE4MDUzMjA3WjBWMQsw
# CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQw
# IgYDVQQDExtDZXJ0dW0gVGltZXN0YW1waW5nIDIwMjEgQ0EwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQDpEh8ENe25XXrFppVBvoplf0530W0lddNmjtv4
# YSh/f7eDQKFaIqc7tHj7ox+u8vIsJZlroakUeMS3i3T8aJRC+eQs4FF0GqvkM6+W
# ZO8kmzZfxmZaBYmMLs8FktgFYCzywmXeQ1fEExflee2OpbHVk665eXRHjH7MYZIz
# Nnjl2m8Hy8ulB9mR8wL/W0v0pjKNT6G0sfrx1kk+3OGosFUb7yWNnVkWKU4qSxLv
# 16kJ6oVJ4BSbZ4xMak6JLeB8szrK9vwGDpvGDnKCUMYL3NuviwH1x4gZG0JAXU3x
# 2pOAz91JWKJSAmRy/l0s0l5bEYKolg+DMqVhlOANd8Yh5mkQWaMEvBRE/kAGzIqg
# WhwzN2OsKIVtO8mf5sPWSrvyplSABAYa13rMYnzwfg08nljZHghquCJYCa/xHK9a
# cev9UD7Y+usr15d7mrszzxhF1JOr1Mpup2chNSBlyOObhlSO16rwrffVrg/SzaKf
# SndS5swRhr8bnDqNJY9TNyEYvBYpgF95K7p0g4LguR4A++Z1nFIHWVY5v0fNVZmg
# zxD9uVo/gta3onGOQj3JCxgYx0KrCXu4yc9QiVwTFLWbNdHFSjBCt5/8Q9pLuRhV
# ocdCunhcHudMS1CGQ/Rn0+7P+fzMgWdRKfEOh/hjLrnQ8BdJiYrZNxvIOhM2aa3z
# EDHNwwIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUvlQC
# L79AbHNDzqwJJU6eQ0Qa7uAwHwYDVR0jBBgwFoAUtqFUOQLDoD+Oirz61PgcptE6
# Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMDAGA1UdHwQp
# MCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5jcmwwbAYIKwYB
# BQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0dW0u
# Y29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY3Ru
# Y2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYYaHR0cDov
# L3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQC4k1l3yUwV/ZQH
# CKCneqAs8EGTnwEUJLdDpokN/dMhKjK0rR5qX8nIIHzxpQR3TAw2IRw1Uxsr2Pli
# G3bCFqSdQTUbfaTq6V3vBzEebDru9QFjqlKnxCF2h1jhLNFFplbPJiW+JSnJTh1f
# KEqEdKdxgl9rVTvlxfEJ7exOn25MGbd/wGPwuSmMxRJVO0wnqgS7kmoJjNF9zqee
# hFSDDP8ZVkWg4EZ2tIS0M3uZmByRr+1Lkwjjt8AtW83mVnZTyTsOb+FNfwJY7DS4
# FmWhkRbgcHRetreoTirPOr/ozyDKhT8MTSTf6Lttg6s6T/u08mDWw6HK04ZRDfQ9
# sb77QV8mKgO44WGP31vXnVKoWVJpFBjPvjL8/Zck/5wXX2iqjOaLStFOR/IQki+E
# hn4zlcgVm22ZVCBPF+l8nAwUUShCtKuSU7GmZLKCmmxQMkSiWILTm8EtVD6AxnJh
# oq8EnhjEEyUoflkeRF2WhFiVQOmWTwZRr44IxWGkNJC6tTorW5rl2Zl+2e9JLPYf
# 3pStAPMDoPKIjVXd6NW2+fZrNUBeDo2eOa5Fn7Brs/HLQff5Xgris5MeUbdVgDrF
# 8uxO6cLPvZPo63j62SsNg55pTWk9fUIF9iPoRbb4QurjoY/woI1RAOKtYtTic6aA
# Jq3u83RIPpGXBSJKwx4KJAOZnCDCtTGCBqIwggaeAgEBMGowVjELMAkGA1UEBhMC
# UEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMb
# Q2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBAhBX5gfP8LabvnxCXoItEBa/MA0G
# CWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZI
# hvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcC
# ARUwLwYJKoZIhvcNAQkEMSIEIKsfIhXgY2yxQqY8QCm5dTmsMihFkwny0Hz4dEwo
# ASemMA0GCSqGSIb3DQEBAQUABIIBgItOCIXq6HUW3SfKV346as3CzRvIQ2tKv232
# Nq5zYWbucuHjFQjmMoJCAfiK//VYRzvIFQOgrs1eXfYxzkI6dryFIHQhg+/DyJdN
# DS43i3un3OqLPtcKNJtpYAoOlc4H2RhqiL4OC1tF1RjG8YS+BPU4L5F3VM3fHGP4
# Ovrffj65nrNtxHcSzsJP42e1BYAIPGRUwMP4fHDuCOgELb1NbbQlJrDc6S3GSN8v
# 9sMYFd8kXTFThAdoZTKPyxoow2k1cXt7mZP0TSU9AuZGRwAqYiEpgHQ63ad6B6w/
# ybD/PxW7fPtihH/bGLGbxse3lDB2mBY8uoXTlcfctEsCswmN57JQ0bP/zld1arg+
# L/Lue6C7OQOJXr4E+Ua3GdmWeY2g8R8hSBBAMQm7scsHBS+MExYk7fpU7WOB1U0q
# 3AmL6/pchqQJkJX0jlDVhSdlymLsz3NjR8ik/MEndAD5e/6zKjDRMaXKVVdOu47f
# Tv86kLvcsNt1QBiz218qbrYlz848/qGCBAIwggP+BgkqhkiG9w0BCQYxggPvMIID
# 6wIBATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0
# ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQQIQ
# KPB3wRw2vf5fdDJHcCcuAzANBglghkgBZQMEAgIFAKCCAVYwGgYJKoZIhvcNAQkD
# MQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjEwMjcwNTQxMDdaMDcG
# CyqGSIb3DQEJEAIvMSgwJjAkMCIEIIW+kOEK0kONfMkotq9IsJqyCBd87PiwEmxY
# 05EFJcQ8MD8GCSqGSIb3DQEJBDEyBDDbXl1zcuQnoJkEgoHoSzrD5UrOZISpu+Th
# KSxSDjrxgTEcbX2HcxzxNv+hBTnj6TcwgZ8GCyqGSIb3DQEJEAIMMYGPMIGMMIGJ
# MIGGBBRXFGhBDKha80JO+RZKUTYQ9NONmDBuMFqkWDBWMQswCQYDVQQGEwJQTDEh
# MB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQDExtDZXJ0
# dW0gVGltZXN0YW1waW5nIDIwMjEgQ0ECECjwd8EcNr3+X3QyR3AnLgMwDQYJKoZI
# hvcNAQEBBQAEggIAobAzFR0c83Vk46XGUmJFtHHbP22GcrjxLgH+Vz85Y5+FTqXn
# jeToRgfoYv8TzEjgo6nzgqTLj/TUUOBIXMK4qJAemNeNUD7UUj2d68z1TMka7qQC
# rMKMnPFZgHr4DBBjrBMPeUr4HIeYsNAGkRAyLaHRS0KJxF5/fG3OG8KtEAv9lQy7
# OvBnTRmusNn/LOLvqnsy1EFZZW3kZ7ngfEopL3ZDUiyV1LnI4ysYedk+RovoTrGf
# GLDee2sUrvB3wvz1fvT+6LCIGlZGGY3LVRkrbeNFjsxqHLloLwRCTjZN+2kTr6Yh
# IIH1UMrfjSr8kwtQdgQ32l/6CEzrYj4skjNFJ2uDMrM2LWjtNwBhtSkwfANfusj7
# WZxDmn3Erh9uyFbu1suDf6rGhWQHFRyejqi8IkGIrB8XkLc34agUiaX1zkNlwJGb
# XoY/y8aZ04g2aq31vPr+9WLfNAK/804W6oYVIWVak4FubyvYLNgikDGpJwJ6co+D
# MyOXQ74KLiVLJaYLjsEY0kn28UCvFV3Z9MyEHpxaK8+yJou/0Fx98oi/ffjnqM8H
# afe0/uu0poxnOSfWHDidCJtxKWGkHdn7FqZVxDN/+nIXNfXD03FhKVMWyGdcR1kU
# Kh4fUfLeok7GYZ3LAinFHRHjIFTipfOfg/SheUUyaLFqNZ2m5DgJ6zH5MVc=
# SIG # End signature block