Private/Trees/New-OwnerLensAzureRbacTree.ps1

function Test-OwnerLensResourceUnderScope {
  param(
    [string]$ResourceId,
    [string]$Scope
  )

  if ([string]::IsNullOrWhiteSpace($ResourceId) -or [string]::IsNullOrWhiteSpace($Scope)) {
    return $false
  }

  $normalizedResourceId = $ResourceId.TrimEnd("/")
  $normalizedScope = $Scope.TrimEnd("/")

  return (
    $normalizedResourceId.Equals($normalizedScope, [System.StringComparison]::OrdinalIgnoreCase) -or
    $normalizedResourceId.StartsWith("$normalizedScope/", [System.StringComparison]::OrdinalIgnoreCase)
  )
}

function Get-OwnerLensResourceLabel {
  param(
    [object]$Dependency,
    [object]$Assignment
  )

  if ($Dependency) {
    $resourceName = Get-OwnerLensDisplayValue -Value $Dependency.resourceName -Fallback ([string]$Dependency.resourceId)
    $dependencyType = Get-OwnerLensDisplayValue -Value $Dependency.dependencyType -Fallback "Scope"
    $resourceType = Get-OwnerLensDisplayValue -Value $Dependency.resourceType
    $resourceGroup = Get-OwnerLensDisplayValue -Value $Dependency.resourceGroup
    $resourceId = [string]$Dependency.resourceId
    $resourceLabel = Format-OwnerLensRichLink `
      -Text $resourceName `
      -Uri (ConvertTo-OwnerLensAzurePortalResourceUri -ResourceId $resourceId)
    $scopeDetails = @()

    if (-not [string]::IsNullOrWhiteSpace($resourceType)) {
      $scopeDetails += $resourceType
    }

    if (-not [string]::IsNullOrWhiteSpace($resourceGroup)) {
      $scopeDetails += "rg=$resourceGroup"
    }

    if ($scopeDetails.Count -gt 0) {
      return "[blue]$dependencyType`: $resourceLabel ($($scopeDetails -join ", "))[/]"
    }

    return "[blue]$dependencyType`: $resourceLabel[/]"
  }

  $scope = Get-OwnerLensDisplayValue -Value $Assignment.scope -Fallback "unknown scope"
  return "[blue]Scope: $(Format-OwnerLensAzureResourceId -ResourceId $scope)[/]"
}

function Get-OwnerLensDefaultAzureOwnerTagNames {
  @("userOwner", "technicalOwner", "businessOwner", "groupOwner", "ownerGroup", "teamOwner", "team", "owner", "serviceOwner", "appOwner", "applicationOwner", "productOwner", "managedBy", "ownedBy", "costCenter", "costCentre", "cost-center", "cost_center")
}

function Add-OwnerLensTagNodes {
  param(
    [object]$Tree,
    [object]$Tags,
    [string[]]$OwnerTagNames = @()
  )

  if (-not $Tags) {
    return
  }

  $tagRows = @()
  if ($Tags -is [hashtable] -or $Tags -is [System.Collections.IDictionary]) {
    foreach ($key in $Tags.Keys) {
      $tagRows += [pscustomobject]@{ key = [string]$key; value = [string]$Tags[$key] }
    }
  }
  else {
    foreach ($property in $Tags.PSObject.Properties) {
      $tagRows += [pscustomobject]@{ key = [string]$property.Name; value = [string]$property.Value }
    }
  }

  $tagRows = @($tagRows | Where-Object { -not [string]::IsNullOrWhiteSpace($_.key) } | Sort-Object key)
  if ($tagRows.Count -eq 0) {
    return
  }

  $ownerTagNameSet = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
  foreach ($ownerTagName in @($OwnerTagNames)) {
    if (-not [string]::IsNullOrWhiteSpace($ownerTagName)) {
      $ownerTagNameSet.Add([string]$ownerTagName) | Out-Null
    }
  }

  $tagsNode = Add-RichTreeNode $Tree "tags ($($tagRows.Count))" -PassThru
  foreach ($tag in $tagRows) {
    $tagText = "$($tag.key)=$($tag.value)"
    if ($ownerTagNameSet.Contains([string]$tag.key)) {
      $tagText = "[green]$tagText[/]"
    }

    Add-RichTreeNode $tagsNode $tagText
  }
}

function Format-OwnerLensStorageDiagnosticStatus {
  param([object]$StorageAccount)

  $diagnosticServices = @($StorageAccount.diagnosticSettings | Sort-Object service)
  $configuredServices = @($diagnosticServices | Where-Object dataAccessLogEnabled)
  if ($configuredServices.Count -eq 0) {
    return "[yellow]No diagnostic settings detected; not possible to detect data access based on logs to increase accuracy.[/]"
  }

  $serviceSummaries = @($configuredServices | ForEach-Object {
      $settingNames = @($_.diagnosticSettingNames | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) -join ","
      $workspaceIds = @($_.workspaceIds | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) } | ForEach-Object {
          Format-OwnerLensShortAzureResourceLink -ResourceId ([string]$_)
        }) -join ","
      $details = @("status=$($_.status)")

      if (-not [string]::IsNullOrWhiteSpace($settingNames)) {
        $details += "settings=$settingNames"
      }

      if (-not [string]::IsNullOrWhiteSpace($workspaceIds)) {
        $details += "workspaces=$workspaceIds"
      }

      "$($_.service) ($($details -join ", "))"
    })

  return "[dim]Configured: $($serviceSummaries -join "; ")[/]"
}

function Get-OwnerLensPrincipalDisplayText {
  param(
    [string]$Label,
    [string]$PrincipalType,
    [string]$PrincipalId,
    [string]$PrincipalUpn
  )

  $displayLabel = Get-OwnerLensDisplayValue -Value $Label -Fallback "unknown principal"
  $displayType = Get-OwnerLensDisplayValue -Value $PrincipalType -Fallback "Principal"
  $displayId = Get-OwnerLensDisplayValue -Value $PrincipalId -Fallback "unknown id"
  $displayUpn = Get-OwnerLensDisplayValue -Value $PrincipalUpn -Fallback "unknown upn"

  return "$displayLabel ($displayType, id=$displayId, upn=$displayUpn)"
}

function Get-OwnerLensActivityCallerPrincipalType {
  param([object]$Caller)

  return Get-OwnerLensPrincipalType `
    -Caller ([string]$Caller.caller) `
    -AppId ([string]$Caller.callerAppId)
}

function New-OwnerLensAzureRbacTree {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory = $true)]
    [object]$Report
  )

  $sp = Get-OwnerLensReportValue -Report $Report -Path "enterpriseApplication"
  $displayName = Get-OwnerLensDisplayValue -Value $sp.displayName -Fallback "service principal"
  $root = New-RichTree "[magenta]Service Principal: $displayName (objectId=$($sp.objectId), appId=$($sp.appId))[/]"
  $roleAssignments = Get-OwnerLensReportArray -Report $Report -Path "azure.roleAssignments"
  $resourceDependencies = Get-OwnerLensReportArray -Report $Report -Path "azure.resourceDependencies"
  $coAssignedRoleCandidates = Get-OwnerLensReportArray -Report $Report -Path "azure.coAssignedRoleCandidates"
  $rbacScopeActivityCallers = Get-OwnerLensReportArray -Report $Report -Path "azure.rbacScopeActivityCallers"
  $storageAccountsWithRbac = Get-OwnerLensReportArray -Report $Report -Path "azure.storageAccountsWithRbac"
  $blobReadCallers = Get-OwnerLensReportArray -Report $Report -Path "azure.blobReadCallers"
  $ownerTagConfiguration = Get-OwnerLensReportValue -Report $Report -Path "meta.ownerTagConfiguration"
  $ownerTagNames = @($ownerTagConfiguration.userOwnerTagNames) +
    @($ownerTagConfiguration.groupOwnerTagNames) +
    @($ownerTagConfiguration.tagOwnerTagNames)
  if ($ownerTagNames.Count -eq 0) {
    $ownerTagNames = @(Get-OwnerLensDefaultAzureOwnerTagNames)
  }

  if ($roleAssignments.Count -eq 0) {
    Add-RichTreeNode $root "no Azure RBAC role assignments found for this service principal"
    return $root
  }

  foreach ($scopeGroup in @($roleAssignments | Group-Object scope | Sort-Object Name)) {
    $scope = [string]$scopeGroup.Name
    $assignments = @($scopeGroup.Group | Sort-Object subscriptionName, roleDefinitionName)
    $firstAssignment = $assignments | Select-Object -First 1
    $dependency = @($resourceDependencies | Where-Object {
        ([string]$_.resourceId).Equals($scope, [System.StringComparison]::OrdinalIgnoreCase)
      } | Select-Object -First 1)

    $resourceNode = Add-RichTreeNode $root (Get-OwnerLensResourceLabel -Dependency $dependency -Assignment $firstAssignment) -PassThru
    Add-RichTreeNode $resourceNode "scope: $(Format-OwnerLensAzureResourceId -ResourceId $scope)"

    $rolesNode = Add-RichTreeNode $resourceNode "roles for inspected SP ($($assignments.Count))" -PassThru
    foreach ($assignment in $assignments) {
      $roleLabel = Get-OwnerLensDisplayValue -Value $assignment.roleDefinitionName -Fallback "unknown role"
      $subscriptionName = Get-OwnerLensDisplayValue -Value $assignment.subscriptionName
      if (-not [string]::IsNullOrWhiteSpace($subscriptionName)) {
        $roleLabel = "$roleLabel (subscription=$subscriptionName)"
      }

      Add-RichTreeNode $rolesNode $roleLabel
    }

    Add-OwnerLensTagNodes -Tree $resourceNode -Tags $dependency.tags -OwnerTagNames $ownerTagNames

    $coAssignedPrincipals = @($coAssignedRoleCandidates | Where-Object {
        ([string]$_.scope).Equals($scope, [System.StringComparison]::OrdinalIgnoreCase)
      } | Sort-Object principalDisplayName, principalName, roleDefinitionName)
    if ($coAssignedPrincipals.Count -gt 0) {
      $principalGroups = @($coAssignedPrincipals | Group-Object {
          $principalId = Get-OwnerLensDisplayValue -Value $_.principalId
          if (-not [string]::IsNullOrWhiteSpace($principalId)) {
            return "id:$principalId"
          }

          $principalName = Get-OwnerLensDisplayValue -Value $_.principalName
          if (-not [string]::IsNullOrWhiteSpace($principalName)) {
            return "upn:$principalName"
          }

          return "display:$($_.principalDisplayName)"
        } | Sort-Object {
          $firstPrincipal = $_.Group | Select-Object -First 1
          Get-OwnerLensDisplayValue -Value $firstPrincipal.principalDisplayName -Fallback (Get-OwnerLensDisplayValue -Value $firstPrincipal.principalName -Fallback $firstPrincipal.principalId)
        })
      $coAssignedCount = Format-OwnerLensRichLink `
        -Text ([string]$principalGroups.Count) `
        -Uri (ConvertTo-OwnerLensAzurePortalIamUri -Scope $scope)
      $coAssignedNode = Add-RichTreeNode $resourceNode "other principals on same scope ($coAssignedCount)" -PassThru
      foreach ($principalGroup in $principalGroups) {
        $principal = $principalGroup.Group | Select-Object -First 1
        $principalLabel = Get-OwnerLensDisplayValue -Value $principal.principalDisplayName -Fallback (Get-OwnerLensDisplayValue -Value $principal.principalName -Fallback $principal.principalId)
        $principalType = Get-OwnerLensDisplayValue -Value $principal.principalType -Fallback "Principal"
        $principalId = Get-OwnerLensDisplayValue -Value $principal.principalId -Fallback "unknown id"
        $principalUpn = Get-OwnerLensDisplayValue -Value $principal.principalName -Fallback "unknown upn"
        $hasDataAccess = [bool](@($principalGroup.Group | Where-Object {
              [bool]$_.isStorageDataReadRole
            }).Count -gt 0)
        $principalText = Format-OwnerLensPrincipalLabel `
          -Text (Get-OwnerLensPrincipalDisplayText -Label $principalLabel -PrincipalType $principalType -PrincipalId $principalId -PrincipalUpn $principalUpn) `
          -PrincipalType $principalType `
          -HasDataAccess $hasDataAccess
        $principalNode = Add-RichTreeNode $coAssignedNode $principalText -PassThru
        $principalRoles = @($principalGroup.Group | Sort-Object roleDefinitionName, subscriptionName | ForEach-Object {
            Get-OwnerLensDisplayValue -Value $_.roleDefinitionName -Fallback "unknown role"
          } | Sort-Object -Unique)
        foreach ($roleName in $principalRoles) {
          Add-RichTreeNode $principalNode $roleName
        }
      }
    }

    $activityCallers = @($rbacScopeActivityCallers | Where-Object {
        @($_.rbacScopes) -contains $scope
      } | Sort-Object @{ Expression = "eventCount"; Descending = $true }, callerName, caller)
    if ($activityCallers.Count -gt 0) {
      $activityNode = Add-RichTreeNode $resourceNode "recent activity callers ($($activityCallers.Count))" -PassThru
      foreach ($caller in $activityCallers) {
        $callerLabel = Get-OwnerLensDisplayValue -Value $caller.callerName -Fallback (Get-OwnerLensDisplayValue -Value $caller.caller -Fallback $caller.callerKey)
        $callerType = Get-OwnerLensActivityCallerPrincipalType -Caller $caller
        $callerId = Get-OwnerLensDisplayValue -Value $caller.callerObjectId -Fallback $caller.callerAppId
        $highlightCaller = [bool]$caller.matchesInspectedServicePrincipal -or
          ([string]$callerType).Equals("User", [System.StringComparison]::OrdinalIgnoreCase)
        $callerText = Format-OwnerLensPrincipalLabel `
          -Text (Get-OwnerLensPrincipalDisplayText -Label $callerLabel -PrincipalType $callerType -PrincipalId $callerId -PrincipalUpn ([string]$caller.caller)) `
          -PrincipalType $callerType `
          -HasDataAccess $highlightCaller
        Add-RichTreeNode $activityNode "$callerText (events=$($caller.eventCount), lastSeen=$($caller.lastSeen), inspectedSP=$($caller.matchesInspectedServicePrincipal))"
      }
    }

    $storageAccounts = @($storageAccountsWithRbac | Where-Object {
        Test-OwnerLensResourceUnderScope -ResourceId ([string]$_.resourceId) -Scope $scope
      } | Sort-Object name)
    if ($storageAccounts.Count -gt 0) {
      $storageNode = Add-RichTreeNode $resourceNode "storage accounts with data-plane read ($($storageAccounts.Count))" -PassThru
      foreach ($storageAccount in $storageAccounts) {
        $readServices = @($storageAccount.dataPlaneReadServices) -join ","
        $verificationStatus = Get-OwnerLensDisplayValue -Value $storageAccount.dataAccessVerificationStatus -Fallback "Unknown"
        $storageAccountNode = Add-RichTreeNode $storageNode "$(Format-OwnerLensRichLink -Text ([string]$storageAccount.name) -Uri (ConvertTo-OwnerLensAzurePortalResourceUri -ResourceId ([string]$storageAccount.resourceId))) (rg=$($storageAccount.resourceGroup), location=$($storageAccount.location), read=$readServices, diagnostics=$verificationStatus)" -PassThru
        Add-RichTreeNode $storageAccountNode (Format-OwnerLensStorageDiagnosticStatus -StorageAccount $storageAccount)

        $blobParticipants = @($blobReadCallers | Where-Object {
            @($_.storageAccounts) -contains [string]$storageAccount.name
          } | Sort-Object @{ Expression = "blobAccessCount"; Descending = $true }, requesterUpn, requesterAppId)
        if ($blobParticipants.Count -gt 0) {
          $participantsNode = Add-RichTreeNode $storageAccountNode "blob data-plane participants ($($blobParticipants.Count))" -PassThru
          foreach ($participant in $blobParticipants) {
            $participantLabel = Get-OwnerLensDisplayValue -Value $participant.requesterUpn -Fallback (Get-OwnerLensDisplayValue -Value $participant.requesterAppId -Fallback $participant.requesterKey)
            Add-RichTreeNode $participantsNode "$participantLabel ($($participant.requesterType), reads=$($participant.blobReadCount), publishes=$($participant.blobPublishCount), inspectedSP=$($participant.matchesInspectedServicePrincipal))"
          }
        }
      }
    }
  }

  return $root
}

# SIG # Begin signature block
# MII9NAYJKoZIhvcNAQcCoII9JTCCPSECAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCClnOwHvslizpQU
# sCXsSNydQR5G+Ao7ZEVpYEg3tyawt6CCIfYwggXMMIIDtKADAgECAhBUmNLR1FsZ
# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggaoMIIEkKADAgECAhMzAATfN8Fd
# CkCAOd/lAAAABN83MA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYwODI0MDgwNzU1WhcNMjYwODI3
# MDgwNzU1WjBpMQswCQYDVQQGEwJQTDEXMBUGA1UECB4OAUEA8wBkAHoAawBpAGUx
# DzANBgNVBAcTBldpZWx1bjEXMBUGA1UEChMOc29mdDRwbSBzcCB6b28xFzAVBgNV
# BAMTDnNvZnQ0cG0gc3Agem9vMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKC
# AYEAsUB/A4IgTtKleM7nBJSDDNsBT3BEKv/mr4dnsVBvBZkNkBifW3Ofxb4609Vg
# fPIXAJpmhke5LoS085d62kfncFq3L5lyEk+UZyKlU0XGOToUkyIwXJ9ZMRcZzHUq
# VuzSEgf2niOdtZLGbAJA3j27caB15YiJXNXmcdpFtNOTdpFkNnlVnBq+IzAWHD43
# XXp/E/NuEP+yQbtANzSHY0QOeOaSQEzPIm/JGmbXtYSrStuGTKJg6WM5VIESIhZe
# jfpiuTgde/pKVy7tPktOoqzyhALoiplucnn32fGJxHWYX3AvApukJViJobPPHUrh
# mQOIK5Vvcq0ED3eNR2L3oOTzJdZcM6K1LhEadLpniex5z6xi4ff7NTisGdyJa3RA
# 0xxCxwXjreDHnFsEPExMdQjX625GOj9M5KbbxaPGWnRps4cLrU2gtqH8wcF3PxSE
# gab5oKyXlwE5ymXwh0OeIqgH4ahmVts+Q6EnSzUOhh/Y33Q0voBDrJH4iSzKZiAO
# MMcbAgMBAAGjggHWMIIB0jAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA9
# BgNVHSUENjA0BgorBgEEAYI3YQEABggrBgEFBQcDAwYcKwYBBAGCN2GCycz3dYGA
# 0Y0Tg469piSB0sq0aDAdBgNVHQ4EFgQUad/TRiMm/CKCInTGHVoP2MIOwzAwHwYD
# VR0jBBgwFoAUmvFUd3UMhxY3RqCs3nn59H/BeOkwZwYDVR0fBGAwXjBcoFqgWIZW
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw
# SUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwNC5jcmwwdAYIKwYBBQUH
# AQEEaDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUy
# MENBJTIwMDQuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5o
# dG0wDQYJKoZIhvcNAQEMBQADggIBAF8p+KjsdCBVGNRuYw0+ZJbOhVz3n1vXUnbE
# CHXjQOq8+j4p2dvA+5NdPKwbSiIcnwzQ26B1TOLqIT5lIwlsoFnXpopgIduf5Tc5
# P49mv+hNL2F1Wg3yJPPo59SMvUa08uX3k2KItoOiUpmpo1/BoPfasb6MJgTu235m
# Z3MHCp1gXSqTgNSIyJR0U1Lf1+6IGlvmOHyRHFAz3y1ttrQe/BUGEF6WHFXsEbkU
# KVhnYTk+e/G6wpiEHcGyYyZ+HW67jM9Eb9J7EeHt/NptwoHAL9tAEfP0xDlbWgMe
# 6U9DyBeYqeGSCqoUHi2MD77y1g2yoG44SnzQCWHmrQVViBcdVyjU2TpmVI/9+hhk
# X6wnlaSd8qU2ha/cmUmKevNr9wspd1H0yYeBwj+3oMSol8rcsa5p0w3rb1iHmzG/
# aSrA/E+ghWy4wXGayJ3jdpxjO+mCk6Qd7jEmUsh+pRd6w0zbE7CgznlYyLV5qfPa
# eCtD1yXjpQIpa3E7srlMhZd8MFcLCmdKajZNMO83tTXMqnhOEnxxB6dHJ+diDdrG
# 3egnxVUSLJRezkNLBzYwpw3FvJa7E7WpM/lSzi7MGp/Nr+KIsGwQ3M04gJIc6pU1
# n8wj85D9ACJnWKwkiPl647BeI94Ttu5SUXi+G+9588W8rlTvSyq0df0GeGdrsuZT
# Y/mNoLE+MIIGqDCCBJCgAwIBAgITMwAE3zfBXQpAgDnf5QAAAATfNzANBgkqhkiG
# 9w0BAQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENB
# IDA0MB4XDTI2MDgyNDA4MDc1NVoXDTI2MDgyNzA4MDc1NVowaTELMAkGA1UEBhMC
# UEwxFzAVBgNVBAgeDgFBAPMAZAB6AGsAaQBlMQ8wDQYDVQQHEwZXaWVsdW4xFzAV
# BgNVBAoTDnNvZnQ0cG0gc3Agem9vMRcwFQYDVQQDEw5zb2Z0NHBtIHNwIHpvbzCC
# AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALFAfwOCIE7SpXjO5wSUgwzb
# AU9wRCr/5q+HZ7FQbwWZDZAYn1tzn8W+OtPVYHzyFwCaZoZHuS6EtPOXetpH53Ba
# ty+ZchJPlGcipVNFxjk6FJMiMFyfWTEXGcx1Klbs0hIH9p4jnbWSxmwCQN49u3Gg
# deWIiVzV5nHaRbTTk3aRZDZ5VZwaviMwFhw+N116fxPzbhD/skG7QDc0h2NEDnjm
# kkBMzyJvyRpm17WEq0rbhkyiYOljOVSBEiIWXo36Yrk4HXv6Slcu7T5LTqKs8oQC
# 6IqZbnJ599nxicR1mF9wLwKbpCVYiaGzzx1K4ZkDiCuVb3KtBA93jUdi96Dk8yXW
# XDOitS4RGnS6Z4nsec+sYuH3+zU4rBnciWt0QNMcQscF463gx5xbBDxMTHUI1+tu
# Rjo/TOSm28Wjxlp0abOHC61NoLah/MHBdz8UhIGm+aCsl5cBOcpl8IdDniKoB+Go
# ZlbbPkOhJ0s1DoYf2N90NL6AQ6yR+IksymYgDjDHGwIDAQABo4IB1jCCAdIwDAYD
# VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwPQYDVR0lBDYwNAYKKwYBBAGCN2EB
# AAYIKwYBBQUHAwMGHCsGAQQBgjdhgsnM93WBgNGNE4OOvaYkgdLKtGgwHQYDVR0O
# BBYEFGnf00YjJvwigiJ0xh1aD9jCDsMwMB8GA1UdIwQYMBaAFJrxVHd1DIcWN0ag
# rN55+fR/wXjpMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUy
# MEVPQyUyMENBJTIwMDQuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZY
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQl
# MjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDA0LmNydDBUBgNVHSAE
# TTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4IC
# AQBfKfio7HQgVRjUbmMNPmSWzoVc959b11J2xAh140DqvPo+KdnbwPuTXTysG0oi
# HJ8M0NugdUzi6iE+ZSMJbKBZ16aKYCHbn+U3OT+PZr/oTS9hdVoN8iTz6OfUjL1G
# tPLl95NiiLaDolKZqaNfwaD32rG+jCYE7tt+ZmdzBwqdYF0qk4DUiMiUdFNS39fu
# iBpb5jh8kRxQM98tbba0HvwVBhBelhxV7BG5FClYZ2E5PnvxusKYhB3BsmMmfh1u
# u4zPRG/SexHh7fzabcKBwC/bQBHz9MQ5W1oDHulPQ8gXmKnhkgqqFB4tjA++8tYN
# sqBuOEp80Alh5q0FVYgXHVco1Nk6ZlSP/foYZF+sJ5WknfKlNoWv3JlJinrza/cL
# KXdR9MmHgcI/t6DEqJfK3LGuadMN629Yh5sxv2kqwPxPoIVsuMFxmsid43acYzvp
# gpOkHe4xJlLIfqUXesNM2xOwoM55WMi1eanz2ngrQ9cl46UCKWtxO7K5TIWXfDBX
# CwpnSmo2TTDvN7U1zKp4ThJ8cQenRyfnYg3axt3oJ8VVEiyUXs5DSwc2MKcNxbyW
# uxO1qTP5Us4uzBqfza/iiLBsENzNOICSHOqVNZ/MI/OQ/QAiZ1isJIj5euOwXiPe
# E7buUlF4vhvvefPFvK5U70sqtHX9Bnhna7LmU2P5jaCxPjCCBygwggUQoAMCAQIC
# EzMAAAAXJ0UJC4uHr8YAAAAAABcwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMC
# VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWlj
# cm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAz
# MjYxODExMzFaFw0zMTAzMjYxODExMzFaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBW
# ZXJpZmllZCBDUyBFT0MgQ0EgMDQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
# AoICAQCCx2T+Aw9mKgGVzJ+Tq0PMn49G3itIsYpbx7ClLSRHFe1RELdPcZ1sIqWO
# hsSfy6yyqEapClGH9Je9FXA1cQgZvvpQbkg+QInVLr/0EPrVBCwrM96lbRI2PxNe
# CwXG9LsyW2hG6KQgintDmNCBo4zpDIr377plVdSliZm6UB7rHwmvBnR02QT6tnrq
# Wq2ihzB6lRJVTEzuh0OafzIMeMnYM0+x+ve5EOLHdfiq+HXiMf9Jb7YLHtYgyHIi
# JA7bTWLqFSLGaTh7ZlbxbsLXA91OOroEpv7OjzFuu3tkpC9FflA4Dp2Euq4+qPmx
# UqfGp+TX0gLRJp9NJOzzILjcTD3rkFFFbxUv1xyg6avivFDLtoKBhM2Td138umE1
# pNOacanuSYtPHIeQHmB6haFi64avLBLwTTAm/Rbit860cFXR72wq+5Qh4hSmezHq
# KXERWPpVBe+APrJ4Iqc+aPeMmIkoCWZQO22HnLNFUFSXjiwyIbgvlH/LIAJEqTaf
# TzxDZgKhlLU7zr6gwsq3WNpcYQI6NuxWnwh3VVDDyF7onQqKs5Ll7bleVN0Y8Vvq
# gE45ppyBbvwqN/Run5fMCCRz3aYMY0kZhKO92eP7t4zHqZ5bQMAgZ0tE2Pz/jb0w
# iykUF/PcoOqqk3vVLiRDYst6vd3GEMNzMpUUvQcvBG46+COIbwIDAQABo4IB3DCC
# AdgwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSa
# 8VR3dQyHFjdGoKzeefn0f8F46TBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9z
# aXRvcnkuaHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQI
# MAYBAf8CAQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0f
# BGkwZzBloGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwv
# TWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENB
# JTIwMjAyMS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw
# VmVyaWZpZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqG
# SIb3DQEBDAUAA4ICAQCQdVoZ/U0m38l2iKaZFlsxavptpoOLyaR1a9ZK2TSF1kOn
# FJhMDse6KkCgsveoiEjXTVc6Xt86IKHn76Nk5qZB0BXv2iMRQ2giAJmYvZcmstoZ
# qfB2M3Kd5wnJhUJOtF/b6HsqSelY6nhrF06zor1lDmDQixBZcLB9zR1+RKQso1je
# kNxYuUk+HaN3k1S57qk0O//YbkwU0mELCW04N5vICMZx5T5c7Nq/7uLvbVhCdD7f
# 2bZpA4U7vOkB1ooB4AaER3pjoJ0Mad5LFyi6Na9p9Zu/hrLeOjU5FItS5Yxsqvlf
# XxAThJ176CmkYstKRmytSHZ7JhKRfV6e9Zftk/ODb/CK4pGVAVqsOf4337bQGrOH
# HCQ3IvN9gmnUuDh8JdvbheoWPHxIN1GB5sUiY584tXN7xdD8LCSsRqJvQ8e7a3gZ
# WTgViugRs1QWq+N0G9Nje6JHlN1CjJehge+H5PGktJja+juGEr0P+ukSkcL6qaZx
# FQTh3SDI71lvW++3bl/Ezd6SO8N9Udw+reoyvRHCyTiSsplZQSBTVJdPmo3qCpGu
# yHFtPo5CBn3/FPTiqJd3M9BHoqKd0G9Kmg6fGcAvFwnLNXA2kov727wRljL3ypfq
# L7iAT/Ynpxul6RwHRlcOf9dDGg1RRvr92NP/CWVXIb68geR2rvU/NsfmtjF1wDCC
# B54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJKoZIhvcNAQEMBQAw
# dzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFI
# MEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENl
# cnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIwMDUyMFoXDTM2MDQw
# MTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2ln
# bmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALLw
# wK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3qrZilYKJNqztA9OQ
# acr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrweLoQ71lzCHkD7A4A
# s1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9rGQ//h890Q8JdjLL
# w0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8sZU6ZE7iRrRZywRmr
# KDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfWo5tTgkoSMoayqoDp
# HOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC69oKpRQXY9bGH6jn9
# NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjkVd6CGUAf0K+Jw+GE
# /5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHgYYjHs1NbOc6brH+e
# KpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu0t+gCwLdN0A6cFtS
# RtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeLzdpt32cdYKp+dhr2
# ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGjggI1MIICMTAOBgNV
# HQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNlBKbAPD2Ns
# 72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5o
# dG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAf
# BgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHeg
# dYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0
# JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUl
# MjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEEgbYwgbMwgYEGCCsG
# AQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p
# Y3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRp
# ZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6
# Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG9w0BAQwFAAOCAgEA
# fyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdPQ4H55v7VOInnmezQ
# EeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVIE1CRFfNF4XKO8XYE
# a3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T8FG7/VEURIVWArbA
# zPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4e0ejRA7mB2IoX5hN
# h3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaBjhWmirYyANb0RJSL
# WjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/tuLjAsKP6SzYZ+1Ry
# 358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQwK8VtsBdekBmdTbQV
# oCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX3mccFgx6UsQeRSdV
# VVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQLUz6ZTl65yPUiOh3k
# 7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i3IpaDcR+iuGjH2Td
# aC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghqUMIIakAIBATBxMFox
# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzAp
# BgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQCEzMABN83
# wV0KQIA53+UAAAAE3zcwDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIw
# ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgWZsv
# 0/khzygtYNL/De+pvnAaEuee2OqFJPZPeCmnFukwDQYJKoZIhvcNAQEBBQAEggGA
# sE6pXJ/GqsNdGbo7zwFGUQypiuKmd/T6rpKE8C4vzswDsUgkguouisDsmzoHl7OK
# 1QAN9qh3kwtfRYfNOujT7wnNxVMNPMYn8sa0+9B5+Os1Y9Rqx+YUzf7W9VoUgd5Q
# bH9UQciNNfOvJSnx+yxsm64XjjIw/StE1zo1LRXCz9RDmBm5hc66GNFc26cxwu10
# pJlOnRF3hbuoOtbFZ2GfHwrl/53WTEaRVxaiAyM5J0034vLf8IYyJ+ToNwzKsy7d
# BVU43G+ETbkH8TC53Zdc+sMFvh//IenSgPwe9W/dPNh4INuphBM43a3qaMlvWeQ9
# BUooIyX7YrcJTHz3l79xtRNcvsmbGEAYAkUx6vfvxuSzWyKoZ+jBaQH04f0AorJ+
# 4uNe6GON2rHoiJZJRGgqWVXdegzyTHBJSmMvqjdSnQVAVdHXPrbmfeG1ZNCVORrX
# 257r+agj1aQIZsyhVNDPNRuP7S249A1POv622Ngr+UusYC0BdWnyrMiDMS3JhEvj
# oYIYFDCCGBAGCisGAQQBgjcDAwExghgAMIIX/AYJKoZIhvcNAQcCoIIX7TCCF+kC
# AQMxDzANBglghkgBZQMEAgEFADCCAWIGCyqGSIb3DQEJEAEEoIIBUQSCAU0wggFJ
# AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIFyrVs3SPZpN8gtA6hbU
# Wkqc1bVy1Kz1TAluf2hNpa7+AgZqhEjmF08YEzIwMjYwODI1MTIxNjMyLjA1NVow
# BIACAfSggeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNV
# BAsTHm5TaGllbGQgVFNTIEVTTjpBNTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWlj
# cm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHmggg8hMIIH
# gjCCBWqgAwIBAgITMwAAAAXlzw//Zi7JhwAAAAAABTANBgkqhkiG9w0BAQwFADB3
# MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgw
# RgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2Vy
# dGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAwHhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5
# MjA0MjMxWjBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBp
# bmcgQ0EgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5851Jj
# /eDFnwV9Y7UGIqMcHtfnlzPREwW9ZUZHd5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqO
# QxwuEQXG8kB41wsDJP5d0zmLYKAY8Zxv3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEE
# Snt0MbPEoKdNihwM5xGv0rGofJ1qOYSTNcc55EbBT7uq3wx3mXhtVmtcCEr5ZKTk
# KKE1CxZvNPWdGWJUPC6e4uRfWHIhZcgCsJ+sozf5EeH5KrlFnxpjKKTavwfFP6Xa
# GZGWUG8TZaiTogRoAlqcevbiqioUz1Yt4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm
# 5sOTiEQtBLGd9Vhd1MadxoGcHrRCsS5rO9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+
# eZ4CNE3ctW4uvSDQVeSp9h1SaPV8UWEfyTxgGjOsRpeexIveR1MPTVf7gt8hY64X
# NPO6iyUGsEgt8c2PxF87E+CO7A28TpjNq5eLiiunhKbq0XbjkNoU5JhtYUrlmAbp
# xRjb9tSreDdtACpm3rkpxp7AQndnI0Shu/fk1/rE3oWsDqMX3jjv40e8KN5YsJBn
# czyWB4JyeeFMW3JBfdeAKhzohFe8U5w9WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8
# Y5SwB1lt5dQhABYyzR3dxEO/T1K/BVF3rV69AgMBAAGjggIbMIICFzAOBgNVHQ8B
# Af8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFGtpKDo1L0hjQM97
# 2K9J6T7ZPdshMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEw
# DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2io
# ojCBhAYDVR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBS
# b290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBlAYIKwYB
# BQUHAQEEgYcwgYQwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0
# aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQw
# DQYJKoZIhvcNAQEMBQADggIBAF+Idsd+bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/p
# O+4ge/XEizXvhs0Y7+KVYyb4nHlugBesnFqBGEdC2IWmtKMyS1OWIviwpnK3aL5J
# edwzbeBF7POyg6IGG/XhhJ3UqWeWTO+Czb1c2NP5zyEh89F72u9UIw+IfvM9lzDm
# c2O2END7MPnrcjWdQnrLn1Ntday7JSyrDvBdmgbNnCKNZPmhzoa8PccOiQljjTW6
# GePe5sGFuRHzdFt8y+bN2neF7Zu8hTO1I64XNGqst8S+w+RUdie8fXC1jKu3m9KG
# IqF4aldrYBamyh3g4nJPj/LR2CBaLyD+2BuGZCVmoNR/dSpRCxlot0i79dKOChmo
# ONqbMI8m04uLaEHAv4qwKHQ1vBzbV/nG89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFf
# R4f/gksSkbJp7oqLwliDm/h+w0aJ/U5ccnYhYb7vPKNMN+SZDWycU5ODIRfyoGl5
# 9BsXR/HpRGtiJquOYGmvA/pk5vC1lcnbeMrcWD/26ozePQ/TWfNXKBOmkFpvPE8C
# H+EeGGWzqTCjdAsno2jzTeNSxlx3glDGJgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqP
# TXPmaCAJKVHAP19oEjJIBwD1LyHbaEgBxFCogYSOiUIr0Xqcr1nJfiWG2GwYe6Zo
# AF1bMIIHlzCCBX+gAwIBAgITMwAAAFZ+j51YCI7pYAAAAAAAVjANBgkqhkiG9w0B
# AQwFADBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcg
# Q0EgMjAyMDAeFw0yNTEwMjMyMDQ2NTFaFw0yNjEwMjIyMDQ2NTFaMIHbMQswCQYD
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3Nv
# ZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046
# QTUwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRp
# bWUgU3RhbXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAtKWfm/ul027/d8Rlb8Mn/g0QUvvLqY2Vsy3tI8U2tFSspTZomZOD3BHT
# 8LkR+RrhMJgb1VjAKFNysaK9cLSXifPGSIBrPCgs9P4y24lrJEmrV6Q5z4BmqMhI
# PrZhEvZnWpCS4HO7jYSei/nxmC7/1Er+l5Lg3PmSxb8d2IVcARxSw1B4mxB6XI0n
# kel9wa1dYb2wfGpofraFmxZOxT9eNht4LH0RBSVueba6ZNpjS/0gtfm7qiIiyP6p
# 6PRzTTbMnVqsHnV/d/rW0zHx+Q+QNZ5wUqKmTZJB9hU853+2pX5rDfK32uNY9/WB
# OAmzbqgpEdQkbiMavUMyUDShmycIvgHdQnS207sTj8M+kJL3tOdahPuPqMwsaCCg
# dfwwQx0O9TKe7FSvbAEYs1AnldCl/KHGZCOVvUNqjyL10JLe0/+GD9/ynqXGWFpX
# OjaunvZ/cKROhjN4M5e6xx0b2miqcPii4/ii2ZheKallJET7CKlpFShs3wyg6F/f
# ojQxQvPnbWD4Nyx6lhjWjwmoLcx6w1FSCtavLCly33BLRSlTU4qKUxaa8d7YN7Eq
# pn9XO0SY0umOvKFXrWH7rxl+9iaicitdnTTksAnRjvekdKT3lg7lRMfmfZU8vXNi
# N0UYJzT9EjqjRm0uN/h0oXxPhNfPYqeFbyPXGGxzaYUz6zx3qTcCAwEAAaOCAcsw
# ggHHMB0GA1UdDgQWBBS+tjPyu6tZ/h5GsyLvyz1H+FNIWjAfBgNVHSMEGDAWgBRr
# aSg6NS9IY0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQdWJsaWMlMjBS
# U0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsGAQUFBwEBBG0w
# azBpBggrBgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmclMjBD
# QSUyMDIwMjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGCN0yDfQEBMEEw
# PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j
# cy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEMBQADggIBAA4D
# qAXEsO26j/La7Fgn/Qifit8xuZekqZ57+Ye+sH/hRTbEEjGYrZgsqwR/lUUfKCFp
# bZF8msaZPQJOR4YYUEU8XyjLrn8Y1jCSmoxh9l7tWiSoc/JFBw356JAmzGGxeBA2
# EWSxRuTr1AuZe6nYaN8/wtFkiHcs8gMadxXBs6DxVhyu5YnhLPQkfumKm3lFftwE
# 7pieV7f1lskmlgsC6AeSGCzGPZUgCvcH5Tv/Qe9z7bIImSD3SuzhOIwaP+eKQTYf
# 67TifyJKkWQSdGfTA6Kcu41k8LB6oPK+MLk1jbxxK5wPqLSL62xjK04SBXHEJSEn
# sFt0zxWkxP/lgej1DxqUnmrYEdkxvzKSHIAqFWSZul/5hI+vJxvFPhsNQBEk4cSu
# lDkJQpcdVi/gmf/mHFOYhDBjsa15s4L+2sBil3XV/T8RiR66Q8xYvTLRWxd2dVsr
# OoCwnsU4WIeiC0JinCv1WLHEh7Qyzr9RSr4kKJLWdpNYLhgjkojTmEkAjFO774t3
# xB7enbvIF0GOsV19xnCUzq9EGKyt0gMuaphKlNjJ+aTpjWMZDGo+GOKsnp93Hmft
# ml0Syp3F9+M3y+y6WJGUZoIZJq227jDjjEndtpUrh9BdPdVIfVJD/Au81Rzh05UH
# AivorQ3Os8PELHIgiOd9TWzbdgmGzcILt/ddVQERMYIHRjCCB0ICAQEweDBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAIT
# MwAAAFZ+j51YCI7pYAAAAAAAVjANBglghkgBZQMEAgEFAKCCBJ8wEQYLKoZIhvcN
# AQkQAg8xAgUAMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0B
# CQUxDxcNMjYwODI1MTIxNjMyWjAvBgkqhkiG9w0BCQQxIgQgmIT35y+OY0sF5Xwd
# JCQ9XPlGcPQ9XhdE3Rd1UJKSov4wgbkGCyqGSIb3DQEJEAIvMYGpMIGmMIGjMIGg
# BCC2DDMlTaTj8JV3iTg5Xnpe4CSH60143Z+X9o5NBgMMqDB8MGWkYzBhMQswCQYD
# VQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQD
# EylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAITMwAA
# AFZ+j51YCI7pYAAAAAAAVjCCA2EGCyqGSIb3DQEJEAISMYIDUDCCA0yhggNIMIID
# RDCCAiwCAQEwggEJoYHhpIHeMIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTUwMC0wNUUwLUQ5NDcxNTAzBgNV
# BAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5
# oiMKAQEwBwYFKw4DAhoDFQD/c/cpFSqQWYBeXggyRJ2ZbvYEEaBnMGWkYzBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAN
# BgkqhkiG9w0BAQsFAAIFAO44Ad0wIhgPMjAyNjA4MjUxMTU4MjFaGA8yMDI2MDgy
# NjExNTgyMVowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA7jgB3QIBADAKAgEAAgIV
# uQIB/zAHAgEAAgIS2zAKAgUA7jlTXQIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor
# BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUA
# A4IBAQBbnO48VKdo3LMJk4+kcoLAscYZ7aF+3y1VcccLGW8kGqz/p330Y+lQ1J0X
# Z3GzaKA/LvHNgYcsmd2ZBRKuVmqYFi9juRgz7tX5RSYRyXqZ+8KFu8g4xScjl2Ot
# PDk2S6uKjuVhTdcSd3/cPk6gOWg+lXqU3N8kt/lnoP6OKTa44RsQl7GU5oTeCSph
# 6dpZF5WvgYkPARAxmdXHmgj1/cvfYEFjvHEyLC+QyVyT0q/KXjFXDUrRM8qd3225
# L4ov8dCZ9q/36NIsc4e8eyKIF+IySjp3ddR9UrGGuRb98PSVRNd3x08CyHoWMCqJ
# jhDDranmPbioHG8o0AGQ0/p7K5HgMA0GCSqGSIb3DQEBAQUABIICAKZF/SPaI5eI
# Sv1Bw5C83sTP6g8KpRPibvNHmXajrbqNkIQsS2K6/JkOn8vyT34O1YYWdYzgGIu5
# toKdsTbLKRFXqJlso9KXuQHABQRMWVLWBXqTaZ2osXuk8m/fmoEIjhyINVbxLUov
# BJY9p5LFIXntk+TYt+L/vS7pU4kYWsl/J0KDwl8E5aWl8Y+X/Tu8vnPzHvfQRAXu
# kIDZ3K+KRIaEHzsVfRyWlTKr9bs1vhn0c5sUPcm3dAX3NthkD5h3BPm17q1ZzWjv
# 4NurDm8a4duR4ybEgxVFhW+prMkHz58D+tncR8y0DfWCfvFmfCdGC/C7qQ3x4o72
# UqBUG/ILymNA/dLws4MSa214yCEVHmb0F51DmPu10BKbkkzW8VqYsQvx6v5M7jFT
# qTdNa5X+A3B2UnIJWxtxNwv6zJ6ZwV/0HZ1l5BeeYwoW5IbELgxYBbHp4NPMV9bF
# MaMP8zLcrxaZYzdNjQdGVLul8z9Y4qpiGFN+2uDnP0NVXFUpIho/K9fcLQ+dPdBg
# 255fOT11tHSNID+UQQGQPvIxMrizFNYc1hlYvsy+MnSq+/L+5QzVT/i1VzyBQ4lI
# FzRKMEZBTVM9kC/5atQf2DXLjLr9x1qlz64OIJUG5PFbAyjsv5rNPsenY62bTmO0
# xNshn91yg2zxneYLdDZ92xgbnJblOHcV
# SIG # End signature block