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 # MIIoPAYJKoZIhvcNAQcCoIIoLTCCKCkCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCACVRS7JCIH0NNP # csS4VqT/yBsiSawe+AKZQNmeUHk+BaCCDYUwggYDMIID66ADAgECAhMzAAADri01 # UchTj1UdAAAAAAOuMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwODU5WhcNMjQxMTE0MTkwODU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQD0IPymNjfDEKg+YyE6SjDvJwKW1+pieqTjAY0CnOHZ1Nj5irGjNZPMlQ4HfxXG # yAVCZcEWE4x2sZgam872R1s0+TAelOtbqFmoW4suJHAYoTHhkznNVKpscm5fZ899 # QnReZv5WtWwbD8HAFXbPPStW2JKCqPcZ54Y6wbuWV9bKtKPImqbkMcTejTgEAj82 # 6GQc6/Th66Koka8cUIvz59e/IP04DGrh9wkq2jIFvQ8EDegw1B4KyJTIs76+hmpV # M5SwBZjRs3liOQrierkNVo11WuujB3kBf2CbPoP9MlOyyezqkMIbTRj4OHeKlamd # WaSFhwHLJRIQpfc8sLwOSIBBAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhx/vdKmXhwc4WiWXbsf0I53h8T8w # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMTgzNjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGrJYDUS7s8o0yNprGXRXuAnRcHKxSjFmW4wclcUTYsQZkhnbMwthWM6cAYb/h2W # 5GNKtlmj/y/CThe3y/o0EH2h+jwfU/9eJ0fK1ZO/2WD0xi777qU+a7l8KjMPdwjY # 0tk9bYEGEZfYPRHy1AGPQVuZlG4i5ymJDsMrcIcqV8pxzsw/yk/O4y/nlOjHz4oV # APU0br5t9tgD8E08GSDi3I6H57Ftod9w26h0MlQiOr10Xqhr5iPLS7SlQwj8HW37 # ybqsmjQpKhmWul6xiXSNGGm36GarHy4Q1egYlxhlUnk3ZKSr3QtWIo1GGL03hT57 # xzjL25fKiZQX/q+II8nuG5M0Qmjvl6Egltr4hZ3e3FQRzRHfLoNPq3ELpxbWdH8t # Nuj0j/x9Crnfwbki8n57mJKI5JVWRWTSLmbTcDDLkTZlJLg9V1BIJwXGY3i2kR9i # 5HsADL8YlW0gMWVSlKB1eiSlK6LmFi0rVH16dde+j5T/EaQtFz6qngN7d1lvO7uk # 6rtX+MLKG4LDRsQgBTi6sIYiKntMjoYFHMPvI/OMUip5ljtLitVbkFGfagSqmbxK # 7rJMhC8wiTzHanBg1Rrbff1niBbnFbbV4UDmYumjs1FIpFCazk6AADXxoKCo5TsO # zSHqr9gHgGYQC2hMyX9MGLIpowYCURx3L7kUiGbOiMwaMIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGg0wghoJAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAOuLTVRyFOPVR0AAAAA # A64wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFcn # MryRoaNB8bRKPhnbp2bnX8nB/xb3mIfuxPe/+B5mMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAT9pB3J+YcVuOSxFCUbiLGevLq/vsgzR4KEz8 # I8rsTHiO6fdyNWHPPWLfYovi1y4vuwodNnpDGaQ7uk9t/gBHkzh7B76mX0Zi7NV6 # PWsmMHSqyhhkBbrMzri2Fcsg8FaROigQnSx52Wij0QJCHg9p0m3bWqVynA46WwaU # sThMthZ7LI5YeDCDScUuoLmJMkrpC+1VOQnACD0WdMw+Q0y3u0OYTp861tPsrQfa # HnAi5dCIGuxc2WQk+0iwsA1fpypw4EWP9x8uhFR5kA8XkTvX0sSTp807GlPlM2fd # HsUxc4XN5sOSwNTJMpGZSmDnH1i56QdmQWnZQFpj62NwOzSgAqGCF5cwgheTBgor # BgEEAYI3AwMBMYIXgzCCF38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCAdAiILy7kynzrDrXtsbrzN+nt+lMh9n51b # Qk4e47dc+gIGZeen48qEGBMyMDI0MDMxMTEwNDM0NC42NzhaMASAAgH0oIHRpIHO # MIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL # ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk # IFRTUyBFU046ODYwMy0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1l # LVN0YW1wIFNlcnZpY2WgghHtMIIHIDCCBQigAwIBAgITMwAAAfGzRfUn6MAW1gAB # AAAB8TANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MDAeFw0yMzEyMDYxODQ1NTVaFw0yNTAzMDUxODQ1NTVaMIHLMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l # cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046ODYwMy0w # NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCxulCZttIf8X97rW9/J+Q4 # Vg9PiugB1ya1/DRxxLW2hwy4QgtU3j5fV75ZKa6XTTQhW5ClkGl6gp1nd5VBsx4J # b+oU4PsMA2foe8gP9bQNPVxIHMJu6TYcrrn39Hddet2xkdqUhzzySXaPFqFMk2Vi # fEfj+HR6JheNs2LLzm8FDJm+pBddPDLag/R+APIWHyftq9itwM0WP5Z0dfQyI4Wl # VeUS+votsPbWm+RKsH4FQNhzb0t/D4iutcfCK3/LK+xLmS6dmAh7AMKuEUl8i2kd # WBDRcc+JWa21SCefx5SPhJEFgYhdGPAop3G1l8T33cqrbLtcFJqww4TQiYiCkdys # CcnIF0ZqSNAHcfI9SAv3gfkyxqQNJJ3sTsg5GPRF95mqgbfQbkFnU17iYbRIPJqw # gSLhyB833ZDgmzxbKmJmdDabbzS0yGhngHa6+gwVaOUqcHf9w6kwxMo+OqG3QZIc # wd5wHECs5rAJZ6PIyFM7Ad2hRUFHRTi353I7V4xEgYGuZb6qFx6Pf44i7AjXbptU # olDcVzYEdgLQSWiuFajS6Xg3k7Cy8TiM5HPUK9LZInloTxuULSxJmJ7nTjUjOj5x # wRmC7x2S/mxql8nvHSCN1OED2/wECOot6MEe9bL3nzoKwO8TNlEStq5scd25GA0g # MQO+qNXV/xTDOBTJ8zBcGQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFLy2xe59sCE0 # SjycqE5Erb4YrS1gMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8G # A1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBs # BggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy # MDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH # AwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQDhSEjSBFSCbJyl # 3U/QmFMW2eLPBknnlsfID/7gTMvANEnhq08I9HHbbqiwqDEHSvARvKtL7j0znICY # BbMrVSmvgDxU8jAGqMyiLoM80788So3+T6IZV//UZRJqBl4oM3bCIQgFGo0VTeQ6 # RzYL+t1zCUXmmpPmM4xcScVFATXj5Tx7By4ShWUC7Vhm7picDiU5igGjuivRhxPv # bpflbh/bsiE5tx5cuOJEJSG+uWcqByR7TC4cGvuavHSjk1iRXT/QjaOEeJoOnfes # bOdvJrJdbm+leYLRI67N3cd8B/suU21tRdgwOnTk2hOuZKs/kLwaX6NsAbUy9pKs # DmTyoWnGmyTWBPiTb2rp5ogo8Y8hMU1YQs7rHR5hqilEq88jF+9H8Kccb/1ismJT # GnBnRMv68Ud2l5LFhOZ4nRtl4lHri+N1L8EBg7aE8EvPe8Ca9gz8sh2F4COTYd1P # Hce1ugLvvWW1+aOSpd8NnwEid4zgD79ZQxisJqyO4lMWMzAgEeFhUm40FshtzXud # AsX5LoCil4rLbHfwYtGOpw9DVX3jXAV90tG9iRbcqjtt3vhW9T+L3fAZlMeraWfh # 7eUmPltMU8lEQOMelo/1ehkIGO7YZOHxUqeKpmF9QaW8LXTT090AHZ4k6g+tdpZF # fCMotyG+E4XqN6ZWtKEBQiE3xL27BDCCB3EwggVZoAMCAQICEzMAAAAVxedrngKb # SZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIy # NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXI # yjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjo # YH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1y # aa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v # 3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pG # ve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viS # kR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYr # bqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlM # jgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSL # W6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF # emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIu # rQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIE # FgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWn # G1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEW # M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5 # Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi # AEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV # 9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js # Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAx # MC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2 # LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv # 6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZn # OlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1 # bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4 # rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU # 6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDF # NLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/ # HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdU # CbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKi # excdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTm # dHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq # ELQdVTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJp # Y2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjg2MDMtMDVF # MC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMK # AQEwBwYFKw4DAhoDFQD7n7Bk4gsM2tbU/i+M3BtRnLj096CBgzCBgKR+MHwxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6Zi9kjAi # GA8yMDI0MDMxMDIzMTUzMFoYDzIwMjQwMzExMjMxNTMwWjB3MD0GCisGAQQBhFkK # BAExLzAtMAoCBQDpmL2SAgEAMAoCAQACAgFhAgH/MAcCAQACAhPUMAoCBQDpmg8S # AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSCh # CjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAKN0izJfoirEYNWYXRGJxyir # Mz6un9L/+V92qQLw0T6BSktfkjNqWDIFnIKYs17kvpYVBOfRAAxi3EouBTQr3sUl # gLsX7XcCUahof/oEYtaVGvjq8xm7gG9UE+hw+m4HxBTXdHQdppKnzyk2NgN12goI # BFcguOcmwXb/2of2vagY/z3/6watnCTMp28/CzazM6nQ6SFMyvxbrtt3s4geSPC+ # X8HB1wfYBSHPcRwbWQvBz953pALLihNrXYg7W8PR9osmBbCx3lMqNZgNjs8s+TcU # i2b3hbM7grixV7aWbgCCp2UQCmarbBKFJ8mrYuu6Zhluz1CtKz4E+ZAQCelQ5aox # ggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAA # AfGzRfUn6MAW1gABAAAB8TANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkD # MQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCC36IFZO/nHH9NotVdMo4dn # coANEj+euP1SnK7DZCS/azCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EINV3 # /T5hS7ijwao466RosB7wwEibt0a1P5EqIwEj9hF4MIGYMIGApH4wfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHxs0X1J+jAFtYAAQAAAfEwIgQgu3md # xFa7KM5DsHeHnJ8zOmyU+DjbDIesJ5H4D1mARiYwDQYJKoZIhvcNAQELBQAEggIA # he26xLCgewxUnm6z/bMFUIUDdMZKTluH0Bp7En5hiPod/+cdV5QXX6q7dqsaIG4t # IdVw66PfOn692d0SQKMP+IkrCCUOIp0cpsnIuseBfvtg8fM+WVODugX+bFnZ3qcf # nVvfPpQfvOwoCyojsEUyy3eRotzYlY2zQKa1XC8ULU8MgqSUsnMruul0xMuU5ehy # TBLK2swlHyUnQ2yquey4ki+Mlrt0fShY6BtAiOJ+ckeI8+YVACFrBEDsFt7lH6xb # HVnwGtZKFMo5+dsW9wVzleYTzP1dgtQTzpmdYPbQ2U2TdVboT3Kyeg5JZzdRSn5/ # noM4dWn4c8O0FvaxCBcw5CCsXB93IlFZvE7Yd/rmb0+xC9F7rVuhxztyf06Aw8CD # AyeKITqjYznxAff1H35MqSoK5AfFXEiZ5u2YbDN2Z5zk0/uPfxtLG8n12dJf40u/ # gjScq+Q6KCjOorKJNrCi0WlNQ7Gr4HfPtSpe0qAgEEXAG/DEtJ+yNC80ordugEpE # B2cflck++P8H3ux0I5N7w4//zlSoWQWqT0AyAcwliW61cDOxwAqfmcbzdYOLCYa5 # TfVjxzTXCa4Hras1EksHtJmUxW1P5hg8rXIu7wySbDTEHVVB/ole96SE8Wcfx6ua # LiYHyWGqBxk6MWVrodcbFaGWeRTaMVdPDHhiz5wlRKk= # SIG # End signature block |