Framework/Helpers/ControlHelper.ps1
# This class should contains method that would be required to filter/targer controls class ControlHelper: EventBase{ static [psobject] $ControlFixBackup = @() static $GroupMembersResolutionObj = @{} #Caching group resolution static $ResolvedBroaderGroups = @{} # Caching expanded broader groups static $GroupsWithNumerousMembers = @() # Groups which contains very large groups static $VeryLargeGroups = @() # Very large groups (fetched from controlsettings) static $IsGroupDetailsFetchedFromPolicy = $false static $AllowedMemberCountPerBroadGroup = @() # Allowed member count (fetched from controlsettings) static $GroupsToExpand = @() # Groups for which meber counts need to check (fetched from controlsettings) static $GroupsWithDescriptor = @{} # All broder groups with descriptors static [string] $parentGroup = $null #used to store current broader group static $CurrentGroupResolutionLevel = -1 # used to define the current level of group which is expanding. Negative value indicates all level. static $GroupResolutionLevel = 1 # used to define the level of group expansion. Negative value indicates all level. static $UseSIPFeedForAADGroupExpansion = $false static $AADGroupsObjFromPolicy = $null static [CloudmineDataHelper] $CloudmineDataHelperObj; static $InactiveResources = @() #Checks if the severities passed by user are valid and filter out invalid ones hidden static [string []] CheckValidSeverities([string []] $ParamSeverities) { $ValidSeverities = @(); $ValidSeverityValues = @(); $InvalidSeverities = @(); $ControlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); if([Helpers]::CheckMember($ControlSettings, 'ControlSeverity')) { $severityMapping = $ControlSettings.ControlSeverity #Discard the severity values passed in parameter that do not have mapping in Org settings. foreach($sev in $severityMapping.psobject.properties) { $ValidSeverities += $sev.value } $ValidSeverityValues += $ParamSeverities | Where-Object { $_ -in $ValidSeverities} $InvalidSeverities += $ParamSeverities | Where-Object { $_ -notin $ValidSeverities } } else { $ValidEnumSeverities = [Enum]::GetNames('ControlSeverity') $ValidSeverityValues += $ParamSeverities | Where-Object { $_ -in $ValidEnumSeverities} $InvalidSeverities += $ParamSeverities | Where-Object { $_ -notin $ValidEnumSeverities } } if($InvalidSeverities) { [EventBase]:: PublishGenericCustomMessage("WARNING: No control severity corresponds to `"$($InvalidSeverities -join ', ')`" for your org.",[MessageType]::Warning) } return $ValidSeverityValues } static [object] GetIdentitiesFromAADGroup([string] $OrgName, [String] $EntityId, [String] $groupName) { $members = @() $AllUsers = @() $rmContext = [ContextHelper]::GetCurrentContext(); $user = ""; $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $rmContext.AccessToken))) try { $apiUrl = 'https://dev.azure.com/{0}/_apis/IdentityPicker/Identities/{1}/connections?identityTypes=user&identityTypes=group&operationScopes=ims&operationScopes=source&connectionTypes=successors&depth=1&properties=DisplayName&properties=SubjectDescriptor&properties=SignInAddress' -f $($OrgName), $($EntityId) $responseObj = @(Invoke-RestMethod -Method Get -Uri $apiURL -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) } -UseBasicParsing) # successors property will not be available if there are no users added to group. if ([Helpers]::CheckMember($responseObj[0], "successors")) { $members = @($responseObj.successors | Select-Object originId, displayName, @{Name = "subjectKind"; Expression = { $_.entityType } }, @{Name = "mailAddress"; Expression = { $_.signInAddress } }, @{Name = "descriptor"; Expression = { $_.subjectDescriptor } }, @{Name = "groupName"; Expression = { $groupName } }) } $members | ForEach-Object { if ($_.subjectKind -eq 'User') { $AllUsers += $_ } } return $AllUsers } catch { Write-Host $_ return $AllUsers } } static [void] ResolveNestedGroupMembers([string]$descriptor,[string] $orgName,[string] $projName){ [ControlHelper]::groupMembersResolutionObj[$descriptor] = @() $url="https://dev.azure.com/{0}/_apis/Contribution/HierarchyQuery?api-version=5.1-preview" -f $($orgName); if ([string]::IsNullOrEmpty($projName)){ $postbody=@' {"contributionIds":["ms.vss-admin-web.org-admin-group-members-data-provider"],"dataProviderContext":{"properties":{"subjectDescriptor":"{0}","sourcePage":{"url":"https://dev.azure.com/{2}/_settings/groups?subjectDescriptor={0}","routeId":"ms.vss-admin-web.collection-admin-hub-route","routeValues":{"adminPivot":"groups","controller":"ContributedPage","action":"Execute"}}}}} '@ $postbody=$postbody.Replace("{0}",$descriptor) $postbody=$postbody.Replace("{1}",$orgName) } else { $postbody=@' {"contributionIds":["ms.vss-admin-web.org-admin-group-members-data-provider"],"dataProviderContext":{"properties":{"subjectDescriptor":"{0}","sourcePage":{"url":"https://dev.azure.com/{1}/{2}/_settings/permissions?subjectDescriptor={0}","routeId":"ms.vss-admin-web.collection-admin-hub-route","routeValues":{"adminPivot":"groups","controller":"ContributedPage","action":"Execute"}}}}} '@ $postbody=$postbody.Replace("{0}",$descriptor) $postbody=$postbody.Replace("{1}",$orgName) $postbody=$postbody.Replace("{2}",$projName) } $rmContext = [ContextHelper]::GetCurrentContext(); $user = ""; $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$rmContext.AccessToken))) try { $response = Invoke-RestMethod -Uri $url -Method Post -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $postbody if([Helpers]::CheckMember($response.dataProviders.'ms.vss-admin-web.org-admin-group-members-data-provider', "identities")) { $data=$response.dataProviders.'ms.vss-admin-web.org-admin-group-members-data-provider'.identities $data | ForEach-Object{ if($_.subjectKind -eq "group") { if ([ControlHelper]::UseSIPFeedForAADGroupExpansion -and [Helpers]::CheckMember($_,"isAadGroup") -and $_.isAadGroup -eq $true) { $members = [ControlHelper]::ResolveGroupUsingSIPData($orgName, $_) [ControlHelper]::groupMembersResolutionObj[$descriptor] += $members } else { if ([string]::IsNullOrWhiteSpace($_.descriptor) -and (-not [string]::IsNullOrWhiteSpace($_.entityId))) { $identities = @([ControlHelper]::GetIdentitiesFromAADGroup($orgName, $_.entityId, $_.displayName)) if ($identities.Count -gt 0) { #add the descriptor of group to denote the user is a direct member of this group and is not a part of the group due to nesting, to be used in auto fix $identities | Add-Member -NotePropertyName "DirectMemberOfGroup" -NotePropertyValue $descriptor [ControlHelper]::groupMembersResolutionObj[$descriptor] += $identities } } else { [ControlHelper]::ResolveNestedGroupMembers($_.descriptor,$orgName,$projName) [ControlHelper]::groupMembersResolutionObj[$descriptor] += [ControlHelper]::groupMembersResolutionObj[$_.descriptor] } } } else { #add the descriptor of group to denote the user is a direct member of this group and is not a part of the group due to nesting, to be used in auto fix $_ | Add-Member -NotePropertyName "DirectMemberOfGroup" -NotePropertyValue $descriptor [ControlHelper]::groupMembersResolutionObj[$descriptor] += $_ } } } } catch { Write-Host $_ } } static [void] FindGroupMembers([string]$descriptor,[string] $orgName,[string] $projName){ if (-not [ControlHelper]::GroupMembersResolutionObj.ContainsKey("OrgName")) { [ControlHelper]::GroupMembersResolutionObj["OrgName"] = $orgName } if ([ControlHelper]::IsGroupDetailsFetchedFromPolicy -eq $false) { [ControlHelper]::FetchControlSettingDetails() } if ([ControlHelper]::UseSIPFeedForAADGroupExpansion) { if (-not [IdentityHelpers]::hasSIPAccess) { [ControlHelper]::UseSIPFeedForAADGroupExpansion = $false } } [ControlHelper]::ResolveNestedGroupMembers($descriptor, $orgName, $projName) } static [PSObject] ResolveGroupUsingSIPData([string] $OrgName, $group) { $users = @() try { #check if group object id is present in the policy file if ($null -eq [ControlHelper]::AADGroupsObjFromPolicy) { [ControlHelper]::AADGroupsObjFromPolicy = [ConfigurationHelper]::LoadServerFileRaw("AAD_Groups.csv", [ConfigurationManager]::GetAzSKSettings().UseOnlinePolicyStore, [ConfigurationManager]::GetAzSKSettings().OnlinePolicyStoreUrl, [ConfigurationManager]::GetAzSKSettings().EnableAADAuthForOnlinePolicyStore) | ConvertFrom-Csv } if ([ControlHelper]::AADGroupsObjFromPolicy.displayName -contains $group.displayName) { $groupObj = [ControlHelper]::AADGroupsObjFromPolicy | where-object {$_.displayName -eq $group.displayName} } else { #Get the object id of the group which will then be used to create mapping with SIP database $groupObj = @() $rmContext = [ContextHelper]::GetCurrentContext(); $user = ""; $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$rmContext.AccessToken))) $url=" https://vssps.dev.azure.com/{0}/_apis/Graph/SubjectQuery?api-version=5.2-preview.1" -f $($orgName); $postbody='{"query":"' + $($group.displayName) + '","subjectKind":["Group"]}' $responseObj = Invoke-RestMethod -Uri $url -Method Post -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $postbody if ([Helpers]::CheckMember($responseObj,"value") -and $group.descriptor -eq $responseObj.value[0].descriptor) { $groupObj = $responseObj.value[0] } } #Get the members of the group from the SIP database $accessToken = [IdentityHelpers]::dataExplorerAccessToken $apiURL = "https://dsresip.kusto.windows.net/v2/rest/query" $inputbody = "{`"db`": `"AADUsersData`",`"csl`": `"let GroupObjectIds = dynamic(['$($groupObj.originId)']); let LatestGroupEtlDate = toscalar ( cluster('dsresip.kusto.windows.net').database('AADGroupsData').GroupMembers | summarize arg_max(etldate,*) | project etldate); let LatestUserEtlDate = toscalar ( UsersInfo | summarize arg_max(etldate,*) | project etldate); cluster('dsresip.kusto.windows.net').database('AADGroupsData').GroupMembers | where etldate == LatestGroupEtlDate and GroupId in~ (GroupObjectIds) | project GroupId,GroupDisplayName, GroupPrincipalName, objectId= UserId | join kind=inner (UsersInfo | where etldate == LatestUserEtlDate | project objectId = UserId, providerDisplayName = UserDisplayName, mail = UserPrincipalName,extensionAttribute2) on objectId | project GroupId,GroupDisplayName,GroupPrincipalName, objectId , providerDisplayName , mail ,extensionAttribute2`"}" $header = @{ "Authorization" = "Bearer " + $accessToken } $kustoResponse = Invoke-RestMethod -Uri $apiURL -Method Post -ContentType "application/json; charset=utf-8" -Headers $header -Body $inputbody; $kustoResponse = $kustoResponse | Where-Object {$_.FrameType -eq "DataTable" -and $_.TableKind -eq 'PrimaryResult'} $kustoResponse.rows | Where-Object {$_[0] -eq $groupObj.originId} | ForEach-Object {$user = "" | select-object identityId, originId, subjectKind, displayName, mailAddress, descriptor, DirectMemberOfGroup; $user.identityId = $_[3]; $user.originId = $_[3]; $user.subjectKind = 'user'; $user.displayName = $_[4]; $user.mailAddress = $_[5]; $user.DirectMemberOfGroup = $_[1]; $users += $user} } catch { #eat exception } return $users } static [PSObject] ResolveNestedBroaderGroupMembers([PSObject]$groupObj,[string] $orgName,[string] $projName) { $groupPrincipalName = $groupObj.principalName $members = @() #increasing the level of group which is currently expanding and comparing it with defined expansion limit on each recursion. [ControlHelper]::CurrentGroupResolutionLevel += 1 if ([ControlHelper]::CurrentGroupResolutionLevel -le [ControlHelper]::GroupResolutionLevel) { if ([ControlHelper]::ResolvedBroaderGroups.ContainsKey($groupPrincipalName)) { $members += [ControlHelper]::ResolvedBroaderGroups[$_.principalName]; } else { [ControlHelper]::ResolvedBroaderGroups[$groupPrincipalName] = @() $rmContext = [ContextHelper]::GetCurrentContext(); $user = ""; $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$rmContext.AccessToken))) $memberslist = @() if ([string]::IsNullOrWhiteSpace($groupObj.descriptor) -and (-not [string]::IsNullOrWhiteSpace($groupObj.entityId))) { $apiUrl = 'https://dev.azure.com/{0}/_apis/IdentityPicker/Identities/{1}/connections?identityTypes=user&identityTypes=group&operationScopes=ims&operationScopes=source&connectionTypes=successors&depth=1&properties=DisplayName&properties=SubjectDescriptor&properties=SignInAddress' -f $($OrgName), $($groupObj.entityId) $responseObj = @(Invoke-RestMethod -Method Get -Uri $apiURL -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) } -UseBasicParsing) # successors property will not be available if there are no users added to group. if ([Helpers]::CheckMember($responseObj[0], "successors")) { $memberslist = @($responseObj.successors | Select-Object entityId, originId, descriptor, @{Name = "principalName"; Expression = { $_.displayName } }, @{Name = "mailAddress"; Expression = { $_.signInAddress } }, @{Name = "subjectKind"; Expression = { $_.entityType } }) } $members += [ControlHelper]::NestedGroupResolverHelper($memberslist) } else { $descriptor = $groupObj.descriptor $url="https://dev.azure.com/{0}/_apis/Contribution/HierarchyQuery?api-version=5.1-preview" -f $($orgName); $postbody=@' {"contributionIds":["ms.vss-admin-web.org-admin-group-members-data-provider"],"dataProviderContext":{"properties":{"subjectDescriptor":"{0}","sourcePage":{"url":"https://dev.azure.com/{1}/{2}/_settings/permissions?subjectDescriptor={0}","routeId":"ms.vss-admin-web.collection-admin-hub-route","routeValues":{"adminPivot":"groups","controller":"ContributedPage","action":"Execute"}}}}} '@ $postbody=$postbody.Replace("{0}",$descriptor) $postbody=$postbody.Replace("{1}",$orgName) $postbody=$postbody.Replace("{2}",$projName) $response = Invoke-RestMethod -Uri $url -Method Post -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $postbody if([Helpers]::CheckMember($response.dataProviders.'ms.vss-admin-web.org-admin-group-members-data-provider', "identities")) { $memberslist = @($response.dataProviders.'ms.vss-admin-web.org-admin-group-members-data-provider'.identities) } $members += [ControlHelper]::NestedGroupResolverHelper($memberslist) } [ControlHelper]::ResolvedBroaderGroups[$groupPrincipalName] = $members } } return $members } static [PSObject] NestedGroupResolverHelper($memberslist) { $members = @() if ($memberslist.Count -gt 0) { $memberslist | ForEach-Object { if($_.subjectKind -eq "Group") { if ([ControlHelper]::VeryLargeGroups -contains $_.principalName) { [ControlHelper]::GroupsWithNumerousMembers += [ControlHelper]::parentGroup } else { $members += [ControlHelper]::ResolveNestedBroaderGroupMembers($_, $orgName, $projName) #decreasing the current level of resolution, so that other groups present at the same level can also be expanded. [ControlHelper]::CurrentGroupResolutionLevel -= 1 # Uncomment the below code if member count needs to be displayed on console. # Write-Host "Group: [$($_.principalName)]; MemberCount: $(@([ControlHelper]::ResolvedBroaderGroups[$_.principalName]).Count)" -ForegroundColor Cyan } } else { $members += $_ } } } return $members } static [PSObject] GetBroaderGroupDescriptorObj([string] $OrgName,[string] $groupName) { $groupObj = @() $projName = $groupName.Split("\")[0] -replace '[\[\]]' $rmContext = [ContextHelper]::GetCurrentContext(); $user = ""; $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$rmContext.AccessToken))) $url= "https://dev.azure.com/{0}/_apis/Contribution/HierarchyQuery?api-version=5.1-preview.1" -f $($OrgName); if ($projName -eq $OrgName) { $body=@' {"contributionIds":["ms.vss-admin-web.org-admin-groups-data-provider"],"dataProviderContext":{"properties":{"sourcePage":{"url":"https://dev.azure.com/{0}/_settings/groups","routeId":"ms.vss-admin-web.collection-admin-hub-route","routeValues":{"adminPivot":"groups","controller":"ContributedPage","action":"Execute"}}}}} '@ $body=$body.Replace("{0}",$OrgName) } else { $body=@' {"contributionIds":["ms.vss-admin-web.org-admin-groups-data-provider"],"dataProviderContext":{"properties":{"sourcePage":{"url":"https://dev.azure.com/{0}/{1}/_settings/permissions","routeId":"ms.vss-admin-web.project-admin-hub-route","routeValues":{"project":"{1}","adminPivot":"permissions","controller":"ContributedPage","action":"Execute"}}}}} '@ $body=$body.Replace("{0}",$OrgName) $body=$body.Replace("{1}",$projName) } try{ $responseObj = Invoke-RestMethod -Uri $url -Method Post -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body $groupObj = $responseObj.dataProviders.'ms.vss-admin-web.org-admin-groups-data-provider'.identities | Where-Object {$_.principalName -eq $groupName} } catch { Write-Host $_ } return $groupObj } hidden static FetchControlSettingDetails() { $ControlSettingsObj = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); [ControlHelper]::VeryLargeGroups = @($ControlSettingsObj.VeryLargeGroups) [ControlHelper]::AllowedMemberCountPerBroadGroup = @($ControlSettingsObj.AllowedMemberCountPerBroadGroup) [ControlHelper]::GroupsToExpand = @($ControlSettingsObj.BroaderGroupsToExpand) [ControlHelper]::IsGroupDetailsFetchedFromPolicy = $true [ControlHelper]::GroupResolutionLevel = $ControlSettingsObj.GroupResolution.GroupResolutionLevel [ControlHelper]::UseSIPFeedForAADGroupExpansion = $ControlSettingsObj.GroupResolution.UseSIPFeedForAADGroupExpansion } static [PSObject] FilterBroadGroupMembers([PSObject] $groupList, [bool] $fetchDescriptor) { $broaderGroupsWithExcessiveMembers = @() if ([ControlHelper]::IsGroupDetailsFetchedFromPolicy -eq $false) { [ControlHelper]::FetchControlSettingDetails() } # if the value is set to -1, it means all level of the groups needs be expaned. if ([ControlHelper]::GroupResolutionLevel -eq -1) { [ControlHelper]::GroupResolutionLevel = 1000 } # if environment variable is provided, it will override the policy configuration. if ($null -ne $env:GroupResolutionLevel) { [ControlHelper]::GroupResolutionLevel = $env:GroupResolutionLevel } [ControlHelper]::CurrentGroupResolutionLevel = 0 $groupList | Foreach-Object { # In some cases, group object doesn't contains descriptor key which requires to expand the groups. if ($fetchDescriptor) { $groupName = $_.Name.split('\')[-1] } else { $groupName = $_.principalName.split('\')[-1] } if ([ControlHelper]::GroupsToExpand -contains $groupName) { if ($fetchDescriptor) { if (-not ([ControlHelper]::GroupsWithDescriptor.keys -contains $_.Name)) { [ControlHelper]::GroupsWithDescriptor[$_.Name] += [ControlHelper]::GetBroaderGroupDescriptorObj($this.OrganizationContext.OrganizationName, $_.Name) } $groupObj = [ControlHelper]::GroupsWithDescriptor[$_.Name] } else { $groupObj = $_ } [ControlHelper]::parentGroup = $groupObj.principalName #Checking if group is prenet in the dictionary, if not then expand it, else fetch from dictionary if ([ControlHelper]::GroupMembersResolutionObj.ContainsKey($groupObj.descriptor)) { $groupMembers = @([ControlHelper]::GroupMembersResolutionObj[$groupObj.descriptor]) } elseif (-not [ControlHelper]::ResolvedBroaderGroups.ContainsKey($groupObj.principalName)) { $groupMembers = @([ControlHelper]::ResolveNestedBroaderGroupMembers($groupObj, $this.OrganizationContext.OrganizationName, $this.ResourceContext.ResourceGroupName)) } else { $groupMembers = @([ControlHelper]::ResolvedBroaderGroups[$groupObj.principalName]) } $groupMembersCount = @($groupMembers | Select-Object -property mailAddress -Unique).Count # Checking the allowed member count for broader group # Fail only if member count is greater then allowed limit. if ([Helpers]::CheckMember([ControlHelper]::AllowedMemberCountPerBroadGroup, $groupName)) { $allowedMemberCount = [ControlHelper]::AllowedMemberCountPerBroadGroup.$groupName if (($groupMembersCount -gt $allowedMemberCount) -or ([ControlHelper]::GroupsWithNumerousMembers -contains $groupObj.principalName)) { $broaderGroupsWithExcessiveMembers += $groupObj.principalName } } else { $broaderGroupsWithExcessiveMembers += $groupObj.principalName } } else { if ($fetchDescriptor) { $broaderGroupsWithExcessiveMembers += $_.Name } else { $broaderGroupsWithExcessiveMembers += $_.principalName } } } return $broaderGroupsWithExcessiveMembers } static [PSObject] GetInactiveControlDataFromCloudMine($organizationName,$projectId,$resourceId,$resourceType){ $resourceDetails = @() [ControlHelper]::CloudmineDataHelperObj = [CloudmineDataHelper]::CloudmineDataHelperInstance if (![ControlHelper]::CloudmineDataHelperObj) { [ControlHelper]::CloudmineDataHelperObj = [CloudmineDataHelper]::GetInstance($organizationName); [ControlHelper]::InactiveResources = [ControlHelper]::CloudmineDataHelperObj.GetCloudMineData($projectId) } if(-not [Helpers]::CheckMember([ControlHelper]::InactiveResources[0],"ResourceID")){ return @([Constants]::CMErrorMessage); } $resourceDetails = @([ControlHelper]::InactiveResources | where {$_.ResourceType -eq $resourceType -and $_.ResourceID -eq $resourceId -and $_.ProjectID -eq $projectId}) return $resourceDetails } } # SIG # Begin signature block # MIInvwYJKoZIhvcNAQcCoIInsDCCJ6wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCACVRS7JCIH0NNP # csS4VqT/yBsiSawe+AKZQNmeUHk+BaCCDXYwggX0MIID3KADAgECAhMzAAADTrU8 # esGEb+srAAAAAANOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI5WhcNMjQwMzE0MTg0MzI5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDdCKiNI6IBFWuvJUmf6WdOJqZmIwYs5G7AJD5UbcL6tsC+EBPDbr36pFGo1bsU # p53nRyFYnncoMg8FK0d8jLlw0lgexDDr7gicf2zOBFWqfv/nSLwzJFNP5W03DF/1 # 1oZ12rSFqGlm+O46cRjTDFBpMRCZZGddZlRBjivby0eI1VgTD1TvAdfBYQe82fhm # WQkYR/lWmAK+vW/1+bO7jHaxXTNCxLIBW07F8PBjUcwFxxyfbe2mHB4h1L4U0Ofa # +HX/aREQ7SqYZz59sXM2ySOfvYyIjnqSO80NGBaz5DvzIG88J0+BNhOu2jl6Dfcq # jYQs1H/PMSQIK6E7lXDXSpXzAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUnMc7Zn/ukKBsBiWkwdNfsN5pdwAw # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMDUxNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAD21v9pHoLdBSNlFAjmk # mx4XxOZAPsVxxXbDyQv1+kGDe9XpgBnT1lXnx7JDpFMKBwAyIwdInmvhK9pGBa31 # TyeL3p7R2s0L8SABPPRJHAEk4NHpBXxHjm4TKjezAbSqqbgsy10Y7KApy+9UrKa2 # kGmsuASsk95PVm5vem7OmTs42vm0BJUU+JPQLg8Y/sdj3TtSfLYYZAaJwTAIgi7d # hzn5hatLo7Dhz+4T+MrFd+6LUa2U3zr97QwzDthx+RP9/RZnur4inzSQsG5DCVIM # pA1l2NWEA3KAca0tI2l6hQNYsaKL1kefdfHCrPxEry8onJjyGGv9YKoLv6AOO7Oh # JEmbQlz/xksYG2N/JSOJ+QqYpGTEuYFYVWain7He6jgb41JbpOGKDdE/b+V2q/gX # UgFe2gdwTpCDsvh8SMRoq1/BNXcr7iTAU38Vgr83iVtPYmFhZOVM0ULp/kKTVoir # IpP2KCxT4OekOctt8grYnhJ16QMjmMv5o53hjNFXOxigkQWYzUO+6w50g0FAeFa8 # 5ugCCB6lXEk21FFB1FdIHpjSQf+LP/W2OV/HfhC3uTPgKbRtXo83TZYEudooyZ/A # Vu08sibZ3MkGOJORLERNwKm2G7oqdOv4Qj8Z0JrGgMzj46NFKAxkLSpE5oHQYP1H # tPx1lPfD7iNSbJsP6LiUHXH1MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAANOtTx6wYRv6ysAAAAAA04wDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFcnMryRoaNB8bRKPhnbp2bn # X8nB/xb3mIfuxPe/+B5mMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAUf8yON7z4CcY+Kzh/WumE7Qnh5XNdeRbM8Q18qji+9WaBOTlw6Ytk22b # kT5PA54R1mQaSdiDZEdFBh2k1l/AdYwbL0PZSgwfaiX+sBExBZgAKQpzcQkbYF1a # qg2TsnRZXFeV+j3AyM3o7W2Ml3LHAcqhNMdv6CgmXkmho4kkkvyyDKtxIEEUK+jJ # B6hADDzLAMSY5INcGyElLgqFFfW9KA5dz4p8umAfXpuQv2RtQytciAUTivhfTkTo # gMXx+02UQ921Td4JlYhv0uSUXfdZChKXk9hyB2QbSi/GmT1ji2gqrwSkavAZcETI # STYcynzJD8IUNz9k5zJhlyAl8GyV6KGCFykwghclBgorBgEEAYI3AwMBMYIXFTCC # FxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsq # hkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCC/ntkEH77v2p6HaZUVCzBWfQZ8Ix15JfYDMZw5HWQ6pgIGZLgfYF77 # GBMyMDIzMDcyNDExMDc0OC4yNjhaMASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO # Ojg2REYtNEJCQy05MzM1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAG3IScaB6IqhkYAAQAAAbcwDQYJ # KoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjIw # OTIwMjAyMjE0WhcNMjMxMjE0MjAyMjE0WjCB0jELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3Bl # cmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4NkRGLTRC # QkMtOTMzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMf9z1dQNBNkTBq3HJclypjQ # cJIlDAgpvsw4vHJe06n532RKGkcn0V7p65OeA1wOoO+8NsopnjPpVZ8+4s/RhdMC # MNPQJXoWdkWOp/3puIEs1fzPBgTJrdmzdyUYzrAloICYx722gmdpbNf3P0y5Z2gR # O48sWIYyYeNJYch+ZfJzXqqvuvq7G8Nm8IMQi8Zayvx+5dSGBM5VYHBxCEjXF9EN # 6Qw7A60SaXjKjojSpUmpaM4FmVec985PNdSh8hOeP2tL781SBan92DT19tfNHv9H # 0FAmE2HGRwizHkJ//mAZdS0s6bi/UwPMksAia5bpnIDBOoaYdWkV0lVG5rN0+ltR # z9zjlaH9uhdGTJ+WiNKOr7mRnlzYQA53ftSSJBqsEpTzCv7c673fdvltx3y48Per # 6vc6UR5e4kSZsH141IhxhmRR2SmEabuYKOTdO7Q/vlvAfQxuEnJ93NL4LYV1IWw8 # O+xNO6gljrBpCOfOOTQgWJF+M6/IPyuYrcv79Lu7lc67S+U9MEu2dog0MuJIoYCM # iuVaXS5+FmOJiyfiCZm0VJsJ570y9k/tEQe6aQR9MxDW1p2F3HWebolXj9su7zrr # ElNlHAEvpFhcgoMniylNTiTZzLwUj7TH83gnugw1FCEVVh5U9lwNMPL1IGuz/3U+ # RT9wZCBJYIrFJPd6k8UtAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUs/I5Pgw0JAVh # DdYB2yPII8l4tOwwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYD # VR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # cmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwG # CCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIw # MjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD # CDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAA2dZMybhVxSXTbJ # zFgvNiMCV5/Ayn5UuzJU495YDtcefold0ehR9QBGBhHmAMt10WYCHz2WQUyM3mQD # 4IsHfEL1JEwgG9tGq71ucn9dknLBHD30JvbQRhIKcvFSnvRCCpVpilM8F/YaWXC9 # VibSef/PU2GWA+1zs64VFxJqHeuy8KqrQyfF20SCnd8zRZl4YYBcjh9G0GjhJHUP # AYEx0r8jSWjyi2o2WAHD6CppBtkwnZSf7A68DL4OwwBpmFB3+vubjgNwaICS+fkG # VvRnP2ZgmlfnaAas8Mx7igJqciqq0Q6An+0rHj1kxisNdIiTzFlu5Gw2ehXpLrl5 # 9kvsmONVAJHhndpx3n/0r76TH+3WNS9UT9jbxQkE+t2thif6MK5krFMnkBICCR/D # VcV1qw9sg6sMEo0wWSXlQYXvcQWA65eVzSkosylhIlIZZLL3GHZD1LQtAjp2A5F7 # C3Iw4Nt7C7aDCfpFxom3ZulRnFJollPHb3unj9hA9xvRiKnWMAMpS4MZAoiV4O29 # zWKZdUzygp7gD4WjKK115KCJ0ovEcf92AnwMAXMnNs1o0LCszg+uDmiQZs5eR7jz # dKzVfF1z7bfDYNPAJvm5pSQdby3wIOsN/stYjM+EkaPtUzr8OyMwrG+jpFMbsB4c # fN6tvIeGtrtklMJFtnF68CcZZ5IAMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJ # mQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1 # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEB # BQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjK # NVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhg # fWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJp # rx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/d # vI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka9 # 7aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKR # Hh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9itu # qBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyO # ArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItb # oKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6 # bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6t # AgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQW # BBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacb # UzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYz # aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku # aHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA # QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2 # VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu # bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw # LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 # d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt # MjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/q # XBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6 # U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVt # I1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis # 9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTp # kbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0 # sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138e # W0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJ # sWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7 # Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0 # dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQ # tB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB0jELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxh # bmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4 # NkRGLTRCQkMtOTMzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy # dmljZaIjCgEBMAcGBSsOAwIaAxUAyGdBGMObODlsGBZmSUX2oWgfqcaggYMwgYCk # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF # AOhojDwwIhgPMjAyMzA3MjQxMzM1NTZaGA8yMDIzMDcyNTEzMzU1NlowdDA6Bgor # BgEEAYRZCgQBMSwwKjAKAgUA6GiMPAIBADAHAgEAAgIQtTAHAgEAAgISSzAKAgUA # 6GndvAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAID # B6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAG/+YhGv0f9Jf3S8LzVS # Wy2PVmMMSmPZjCMmy1Yx2ENMd57y9G9PrjOnu3baw/v13nEzZSns0kAfTM8hQKz0 # MJfBUDWz3cerLQNz34ES7kn3USciYdRpGKYV8GE6U7AcMrNF8bjW4f7/swe7F4Id # +B7/yWGR5wjPYmaFN1G5a+W4MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBIDIwMTACEzMAAAG3IScaB6IqhkYAAQAAAbcwDQYJYIZIAWUDBAIB # BQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQx # IgQg51cPYFKn1JAi8xyTNv/5CA40rfCnbUyuDg04a45N5HQwgfoGCyqGSIb3DQEJ # EAIvMYHqMIHnMIHkMIG9BCBsJ3jTsh7aL8hNeiYGL5/8IBn8zUfr7/Q7rkM8ic1w # QTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABtyEn # GgeiKoZGAAEAAAG3MCIEILKZD0c2HShmS2x0dFWYyh5h7TYI+J05Rf6FYdAk0KWf # MA0GCSqGSIb3DQEBCwUABIICAKw1msaGxGJdhPrIrQHOOatL2oZRqjrieiMvA0iA # JfjX08H+CvSCENds1jd6jBUO29VqMrg16QXbXm7AYwm2Fw5YqlnahOvxFyoo/1iv # PIV+pDhuejhbC+cgDCBBqz5GPqIVcy7h3G/BcKl0EOcjDyZgtbvgGK7hWq+ifTx3 # srATL3ieueTbRp1MlJS/slxHuc/rPiuhGz6YAXb56fzqN43kvS9PBovCvXfSTNZB # 8k0XY8I/GixoJ7zElyvS7905Fo0VLAQEMYDDEG+WdKPF2Ccl7ixLGtuP6Y49YWV9 # 5JMvY6t05VFYbTE/O/BfbXzVLoW1pQHRJPhVSx2VT57wM7CHhfAyFwW0iYrHfAtS # hpbY4IT2hHuV2qB477gzrYFZ3NW8FoCqtVZXv7sbOJcxfno3P6JG54LcQXasJtR5 # H7fsrfJfojgQdhIxndr95vSfaTC9As3QVAu2We4kkwTtZ7ld97PrWo+iqlVNGgMC # kfOUGSC0LPVLWcMBK8qFuN2DgIf21T57nYvcOi5Ju8n54l7pnrIwWhZLEUZ1bh+d # MrZJfGgj0FWUUk77PWSrMpHhJTkadb82ezgIpc7lR/cBDz3CAcTsI/i5mwQVw1Ei # upXn5/2sfJ6lbGFASmgFWqQqujagPKUGRxVOkN93T0ObffdSs4E05JCOISi70KCb # V/xp # SIG # End signature block |