Private/Get-OwnerCandidate.ps1

$OwnerCandidatePolicy = @{
  ExplicitOwner = @{
    Enabled = $true
    Score = 95
    Signal = "OWNER"
  }

  ExplicitOwnerTag = @{
    Enabled = $true
    Score = 80
    Signal = "TAG"
  }

  DirectoryRelationship = @{
    Enabled = $true
    Score = 30
    Signal = "MEMBERSHIP"
  }

  SharedRbacScope = @{
    Enabled = $true
    ScoreByCandidateType = @{
      User = 35
      Group = 30
      Default = 30
    }
    Signal = "RBAC"
  }

  OperationalActivity = @{
    Enabled = $true
    Score = 25
    Signal = "LOG"
  }

  CredentialGenerator = @{
    Enabled = $true
    Score = 40
    Signal = "SAS"
  }
}

function New-OwnerCandidate {
  param(
    [Parameter(Mandatory = $true)]
    [string]$Candidate,

    [Parameter(Mandatory = $true)]
    [string]$CandidateType,

    [Parameter(Mandatory = $true)]
    [string]$Confidence,

    [Parameter(Mandatory = $true)]
    [string]$Relationship,

    [Parameter(Mandatory = $true)]
    [string]$Signal,

    [Parameter(Mandatory = $true)]
    [string]$EvidenceId,

    [Parameter(Mandatory = $true)]
    [string]$EvidenceSource,

    [string]$EvidenceValue = "",

    [string]$Reason = ""
  )

  return [pscustomobject]@{
    candidate = $Candidate
    candidateType = $CandidateType
    confidence = $Confidence
    relationship = $Relationship
    signal = $Signal
    evidenceId = $EvidenceId
    evidenceSource = $EvidenceSource
    evidenceValue = $EvidenceValue
    reason = $Reason
  }
}

function Test-OwnerCandidatePolicyEnabled {
  param([hashtable]$Rule)

  return ($Rule -and [bool]$Rule.Enabled)
}

function Get-OwnerCandidatePolicyScore {
  param(
    [Parameter(Mandatory = $true)]
    [hashtable]$Rule,

    [string]$CandidateType = ""
  )

  if ($Rule.ScoreByCandidateType) {
    if (-not [string]::IsNullOrWhiteSpace($CandidateType) -and $Rule.ScoreByCandidateType.ContainsKey($CandidateType)) {
      return [int]$Rule.ScoreByCandidateType[$CandidateType]
    }

    if ($Rule.ScoreByCandidateType.ContainsKey("Default")) {
      return [int]$Rule.ScoreByCandidateType.Default
    }
  }

  return [int]$Rule.Score
}

function Get-OwnerCandidateTextValue {
  param(
    [AllowNull()]
    [object]$Value,

    [string]$Fallback = ""
  )

  $text = [string]$Value
  if ([string]::IsNullOrWhiteSpace($text)) {
    return $Fallback
  }

  return $text
}

function ConvertTo-OwnerConfidence {
  param([int]$Score)

  if ($Score -ge 80) {
    return "HIGH"
  }

  if ($Score -ge 50) {
    return "MED"
  }

  return "LOW"
}

function Get-OwnerConfidenceRank {
  param([string]$Confidence)

  switch ($Confidence) {
    "HIGH" { return 3 }
    "MED" { return 2 }
    default { return 1 }
  }
}

function ConvertTo-OwnerCandidateType {
  param([string]$ObjectType)

  switch -Regex ($ObjectType) {
    "user|#microsoft\.graph\.user" { return "User" }
    "group|#microsoft\.graph\.group" { return "Group" }
    default {
      if ([string]::IsNullOrWhiteSpace($ObjectType)) {
        return "Unknown"
      }

      return $ObjectType
    }
  }
}

function ConvertTo-OwnerTagNameSet {
  param([string[]]$TagNames)

  $tagNameSet = @{}
  foreach ($tagName in @($TagNames)) {
    if ([string]::IsNullOrWhiteSpace($tagName)) {
      continue
    }

    $tagNameSet[[string]$tagName] = $true
  }

  return $tagNameSet
}

function Test-OwnerTagNameMatch {
  param(
    [string]$TagName,
    [hashtable]$TagNameSet
  )

  if ([string]::IsNullOrWhiteSpace($TagName) -or -not $TagNameSet) {
    return $false
  }

  return $TagNameSet.ContainsKey($TagName)
}

function Resolve-OwnerTagCandidateType {
  param(
    [string]$TagName,
    [hashtable]$UserOwnerTagNameSet,
    [hashtable]$GroupOwnerTagNameSet,
    [hashtable]$TagOwnerTagNameSet
  )

  if (Test-OwnerTagNameMatch -TagName $TagName -TagNameSet $UserOwnerTagNameSet) {
    return "User"
  }

  if (Test-OwnerTagNameMatch -TagName $TagName -TagNameSet $GroupOwnerTagNameSet) {
    return "Group"
  }

  if (Test-OwnerTagNameMatch -TagName $TagName -TagNameSet $TagOwnerTagNameSet) {
    return "Tag"
  }

  return ""
}

function Format-OwnerTagCandidateValue {
  param(
    [string]$TagName,
    [string]$TagValue,
    [string]$CandidateType
  )

  if ($CandidateType -eq "User" -or $CandidateType -eq "Group") {
    return $TagValue
  }

  return ("{0}={1}" -f $TagName, $TagValue)
}

function Get-OwnerCandidateTagEntries {
  param([object]$Tags)

  if (-not $Tags) {
    return @()
  }

  if ($Tags -is [System.Collections.IDictionary]) {
    return @($Tags.Keys | ForEach-Object {
      [pscustomobject]@{
        Name = [string]$_
        Value = [string]$Tags[$_]
      }
    })
  }

  return @($Tags.PSObject.Properties | ForEach-Object {
    [pscustomobject]@{
      Name = [string]$_.Name
      Value = [string]$_.Value
    }
  })
}

function Get-EnterpriseApplicationOwnerTagEntries {
  param([object]$Tags)

  if (-not $Tags) {
    return @()
  }

  if ($Tags -is [System.Collections.IDictionary]) {
    return @(Get-OwnerCandidateTagEntries -Tags $Tags)
  }

  return @($Tags | ForEach-Object {
    $tagText = [string]$_
    if ([string]::IsNullOrWhiteSpace($tagText)) {
      return
    }

    if ($tagText -match "^\s*([^=:]+)\s*[=:]\s*(.+?)\s*$") {
      [pscustomobject]@{
        Name = [string]$Matches[1]
        Value = [string]$Matches[2]
      }
    }
  })
}

function ConvertTo-OwnerCandidateTsvField {
  param([object]$Value)

  if ($null -eq $Value) {
    return ""
  }

  return ([string]$Value) -replace "[`t`r`n]+", " "
}

function Format-OwnerCandidateTable {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory = $true)]
    [object[]]$Candidates
  )

  $rows = @($Candidates |
    Group-Object candidate, candidateType |
    ForEach-Object {
      $groupRows = @($_.Group | Sort-Object @{ Expression = { Get-OwnerConfidenceRank -Confidence ([string]$_.confidence) }; Descending = $true }, evidenceId)
      $bestConfidence = [string]$groupRows[0].confidence
      [pscustomobject]@{
        candidate = [string]$groupRows[0].candidate
        type = [string]$groupRows[0].candidateType
        confidence = $bestConfidence
        relationship = [string](($groupRows | Select-Object -ExpandProperty relationship -Unique) -join ",")
        signal = [string](($groupRows | Select-Object -ExpandProperty signal -Unique) -join ",")
        evidenceId = [string](($groupRows | Select-Object -ExpandProperty evidenceId -First 4) -join ",")
      }
    } |
    Sort-Object @{ Expression = { Get-OwnerConfidenceRank -Confidence ([string]$_.confidence) }; Descending = $true }, candidate)

  $columns = @("candidate", "type", "confidence", "relationship", "signal", "evidenceId")
  $lines = @(
    ($columns -join "`t")
    $rows | ForEach-Object {
      $row = $_
      (($columns | ForEach-Object { ConvertTo-OwnerCandidateTsvField -Value $row.$_ }) -join "`t")
    }
  )

  return ($lines -join [Environment]::NewLine)
}

function Get-OwnerCandidateSasGeneratorKey {
  param([object]$BlobRead)

  $sasGeneratorUpn = [string]$BlobRead.sasGeneratorUpn
  if (-not [string]::IsNullOrWhiteSpace($sasGeneratorUpn)) {
    return "upn:$sasGeneratorUpn"
  }

  $sasGeneratorObjectId = [string]$BlobRead.sasGeneratorObjectId
  if (-not [string]::IsNullOrWhiteSpace($sasGeneratorObjectId)) {
    return "object:$sasGeneratorObjectId"
  }

  $sasGeneratorAppId = [string]$BlobRead.sasGeneratorAppId
  if (-not [string]::IsNullOrWhiteSpace($sasGeneratorAppId)) {
    return "app:$sasGeneratorAppId"
  }

  return ""
}

function Get-OwnerCandidateSasGeneratorName {
  param([object]$BlobRead)

  $sasGeneratorUpn = [string]$BlobRead.sasGeneratorUpn
  if (-not [string]::IsNullOrWhiteSpace($sasGeneratorUpn)) {
    return $sasGeneratorUpn
  }

  $sasGeneratorObjectId = [string]$BlobRead.sasGeneratorObjectId
  if (-not [string]::IsNullOrWhiteSpace($sasGeneratorObjectId)) {
    return $sasGeneratorObjectId
  }

  return [string]$BlobRead.sasGeneratorAppId
}

function Get-OwnerCandidateSasGeneratorType {
  param([object]$BlobRead)

  if (-not [string]::IsNullOrWhiteSpace([string]$BlobRead.sasGeneratorUpn)) {
    return "User"
  }

  if (-not [string]::IsNullOrWhiteSpace([string]$BlobRead.sasGeneratorAppId)) {
    return "ServicePrincipal"
  }

  return "SasGenerator"
}

function Get-OwnerCandidateRbacScopeActivityCallerName {
  param([object]$ActivityCaller)

  $caller = [string]$ActivityCaller.caller
  if ($caller -match "@") {
    return $caller
  }

  $callerName = [string]$ActivityCaller.callerName
  if (-not [string]::IsNullOrWhiteSpace($callerName)) {
    return $callerName
  }

  if (-not [string]::IsNullOrWhiteSpace($caller)) {
    return $caller
  }

  $callerObjectId = [string]$ActivityCaller.callerObjectId
  if (-not [string]::IsNullOrWhiteSpace($callerObjectId)) {
    return $callerObjectId
  }

  $callerAppId = [string]$ActivityCaller.callerAppId
  if (-not [string]::IsNullOrWhiteSpace($callerAppId)) {
    return $callerAppId
  }

  return [string]$ActivityCaller.callerKey
}

function Get-OwnerCandidateRbacScopeActivityCallerType {
  param([object]$ActivityCaller)

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

function Add-OwnerCandidatesFromTags {
  param(
    [object[]]$Tags,
    [string]$Relationship,
    [hashtable]$Rule,
    [string]$EvidenceId,
    [string]$EvidenceSource,
    [string]$Reason,
    [hashtable]$UserOwnerTagNameSet,
    [hashtable]$GroupOwnerTagNameSet,
    [hashtable]$TagOwnerTagNameSet
  )

  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $Rule)) {
    return @()
  }

  foreach ($tag in @($Tags)) {
    if ([string]::IsNullOrWhiteSpace([string]$tag.Value)) {
      continue
    }

    $candidateType = Resolve-OwnerTagCandidateType `
      -TagName ([string]$tag.Name) `
      -UserOwnerTagNameSet $UserOwnerTagNameSet `
      -GroupOwnerTagNameSet $GroupOwnerTagNameSet `
      -TagOwnerTagNameSet $TagOwnerTagNameSet

    if ([string]::IsNullOrWhiteSpace($candidateType)) {
      continue
    }

    New-OwnerCandidate `
      -Candidate (Format-OwnerTagCandidateValue -TagName ([string]$tag.Name) -TagValue ([string]$tag.Value) -CandidateType $candidateType) `
      -CandidateType $candidateType `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $Rule -CandidateType $candidateType)) `
      -Relationship $Relationship `
      -Signal ([string]$Rule.Signal) `
      -EvidenceId $EvidenceId `
      -EvidenceSource $EvidenceSource `
      -EvidenceValue ("{0}={1}" -f $tag.Name, [string]$tag.Value) `
      -Reason $Reason
  }
}

function Get-OwnerCandidates {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory = $true)]
    [object]$Report,

    [string[]]$UserOwnerTagNames = @("userOwner", "technicalOwner", "businessOwner"),

    [string[]]$GroupOwnerTagNames = @("groupOwner", "ownerGroup", "teamOwner", "team"),

    [string[]]$TagOwnerTagNames = @("owner", "serviceOwner", "appOwner", "applicationOwner", "productOwner", "ownedBy", "costCenter", "costCentre", "cost-center", "cost_center")
  )

  $userOwnerTagNameSet = ConvertTo-OwnerTagNameSet -TagNames $UserOwnerTagNames
  $groupOwnerTagNameSet = ConvertTo-OwnerTagNameSet -TagNames $GroupOwnerTagNames
  $tagOwnerTagNameSet = ConvertTo-OwnerTagNameSet -TagNames $TagOwnerTagNames
  $candidates = @()
  $enterpriseApplication = Get-OwnerLensReportValue -Report $Report -Path "enterpriseApplication"
  $graphOwners = Get-OwnerLensReportArray -Report $Report -Path "graph.owners"
  $graphMemberships = Get-OwnerLensReportArray -Report $Report -Path "graph.memberOf"
  $coAssignedRoleCandidates = Get-OwnerLensReportArray -Report $Report -Path "azure.coAssignedRoleCandidates"
  $resourceDependencies = Get-OwnerLensReportArray -Report $Report -Path "azure.resourceDependencies"
  $azureActivityEvidence = Get-OwnerLensReportArray -Report $Report -Path "azure.activityEvidence"
  $rbacScopeActivityCallers = Get-OwnerLensReportArray -Report $Report -Path "azure.rbacScopeActivityCallers"
  $blobReadEvidence = Get-OwnerLensReportArray -Report $Report -Path "azure.blobReadEvidence"

  $rule = $OwnerCandidatePolicy.ExplicitOwner
  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $rule)) {
    $graphOwners = @()
  }

  foreach ($owner in @($graphOwners)) {
    $candidateType = ConvertTo-OwnerCandidateType -ObjectType ([string]$owner.objectType)
    if ($candidateType -eq "User") {
      $candidateName = [string]$owner.userPrincipalName
      if ([string]::IsNullOrWhiteSpace($candidateName)) {
        $candidateName = [string]$owner.mail
      }
      if ([string]::IsNullOrWhiteSpace($candidateName)) {
        $candidateName = [string]$owner.displayName
      }
    } else {
      $candidateName = [string]$owner.displayName
    }

    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      $candidateName = [string]$owner.objectId
    }

    $ownerSource = [string]$owner.ownerSource
    if ([string]::IsNullOrWhiteSpace($ownerSource)) {
      $ownerSource = "ServicePrincipal"
    }

    $ownerEvidenceBase = "/servicePrincipals/$($enterpriseApplication.objectId)"
    $ownerReason = "Direct Microsoft Graph owner on the service principal."
    if ($ownerSource -eq "Application" -and -not [string]::IsNullOrWhiteSpace([string]$enterpriseApplication.applicationObjectId)) {
      $ownerEvidenceBase = "/applications/$($enterpriseApplication.applicationObjectId)"
      $ownerReason = "Direct Microsoft Graph owner on the application registration."
    }

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType $candidateType `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType $candidateType)) `
      -Relationship "Direct" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId ("{0}/owners/{1}" -f $ownerEvidenceBase, [string]$owner.objectId) `
      -EvidenceSource "$ownerEvidenceBase/owners" `
      -EvidenceValue ([string]$owner.objectId) `
      -Reason $ownerReason
  }

  $candidates += Add-OwnerCandidatesFromTags `
    -Tags (Get-EnterpriseApplicationOwnerTagEntries -Tags $enterpriseApplication.tags) `
    -Relationship "Direct" `
    -Rule $OwnerCandidatePolicy.ExplicitOwnerTag `
    -EvidenceId ([string]$enterpriseApplication.objectId) `
    -EvidenceSource "/servicePrincipals/$($enterpriseApplication.objectId)/tags" `
    -Reason "Owner-like tag found directly on the inspected service principal." `
    -UserOwnerTagNameSet $userOwnerTagNameSet `
    -GroupOwnerTagNameSet $groupOwnerTagNameSet `
    -TagOwnerTagNameSet $tagOwnerTagNameSet

  $rule = $OwnerCandidatePolicy.DirectoryRelationship
  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $rule)) {
    $graphMemberships = @()
  }

  foreach ($memberOf in @($graphMemberships)) {
    $candidateType = ConvertTo-OwnerCandidateType -ObjectType ([string]$memberOf.objectType)
    $candidateName = [string]$memberOf.displayName
    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      $candidateName = [string]$memberOf.objectId
    }

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType $candidateType `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType $candidateType)) `
      -Relationship "Indirect" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId ("/servicePrincipals/{0}/memberOf/{1}" -f $enterpriseApplication.objectId, [string]$memberOf.objectId) `
      -EvidenceSource "/servicePrincipals/$($enterpriseApplication.objectId)/memberOf" `
      -EvidenceValue ([string]$memberOf.objectId) `
      -Reason "The service principal is a member of this directory object."
  }

  $rule = $OwnerCandidatePolicy.SharedRbacScope
  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $rule)) {
    $coAssignedRoleCandidates = @()
  }

  foreach ($coAssignee in @($coAssignedRoleCandidates)) {
    $candidateType = ConvertTo-OwnerCandidateType -ObjectType ([string]$coAssignee.principalType)
    if ($candidateType -eq "Unknown") {
      continue
    }

    if ($candidateType -eq "User") {
      $candidateName = [string]$coAssignee.principalName
      if ([string]::IsNullOrWhiteSpace($candidateName)) {
        $candidateName = [string]$coAssignee.principalDisplayName
      }
    } else {
      $candidateName = [string]$coAssignee.principalDisplayName
    }

    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      $candidateName = [string]$coAssignee.principalId
    }

    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      continue
    }

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType $candidateType `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType $candidateType)) `
      -Relationship "Indirect" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId ([string]$coAssignee.scope) `
      -EvidenceSource ([string]$coAssignee.scope) `
      -EvidenceValue ([string]$coAssignee.roleDefinitionName) `
      -Reason "This principal has Azure RBAC on the same scope as the inspected service principal."
  }

  foreach ($resource in @($resourceDependencies)) {
    if (-not $resource.tags) {
      continue
    }

    $candidates += Add-OwnerCandidatesFromTags `
      -Tags (Get-OwnerCandidateTagEntries -Tags $resource.tags) `
      -Relationship "Indirect" `
      -Rule $OwnerCandidatePolicy.SharedRbacScope `
      -EvidenceId ([string]$resource.resourceId) `
      -EvidenceSource ([string]$resource.resourceId) `
      -Reason "Azure resource tag found on a resource reached through RBAC assigned to the inspected service principal." `
      -UserOwnerTagNameSet $userOwnerTagNameSet `
      -GroupOwnerTagNameSet $groupOwnerTagNameSet `
      -TagOwnerTagNameSet $tagOwnerTagNameSet
  }

  $rule = $OwnerCandidatePolicy.OperationalActivity
  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $rule)) {
    $azureActivityEvidence = @()
    $rbacScopeActivityCallers = @()
  }

  foreach ($activity in @($azureActivityEvidence)) {
    $candidateName = [string]$activity.callerName
    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      $candidateName = [string]$activity.caller
    }
    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      continue
    }

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType "ActivityCaller" `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType "ActivityCaller")) `
      -Relationship "Indirect" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId ([string]$activity.resourceId) `
      -EvidenceSource ([string]$activity.resourceId) `
      -EvidenceValue ([string]$activity.operationNameValue) `
      -Reason "Recent Azure activity matched the inspected service principal; this is weak ownership evidence."
  }

  foreach ($activityCaller in @($rbacScopeActivityCallers | Where-Object {
        -not [bool]$_.matchesInspectedServicePrincipal
      })) {
    $candidateName = Get-OwnerCandidateRbacScopeActivityCallerName -ActivityCaller $activityCaller
    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      continue
    }

    $evidenceId = [string](@($activityCaller.rbacScopes) | Where-Object {
        -not [string]::IsNullOrWhiteSpace([string]$_)
      } | Select-Object -First 1)
    if ([string]::IsNullOrWhiteSpace($evidenceId)) {
      $evidenceId = [string]$activityCaller.callerKey
    }

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType (Get-OwnerCandidateRbacScopeActivityCallerType -ActivityCaller $activityCaller) `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType (Get-OwnerCandidateRbacScopeActivityCallerType -ActivityCaller $activityCaller))) `
      -Relationship "Indirect" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId $evidenceId `
      -EvidenceSource "AzureActivity" `
      -EvidenceValue ("events={0},lastSeen={1}" -f [string]$activityCaller.eventCount, [string]$activityCaller.lastSeen) `
      -Reason "Recent Azure RBAC scope activity was performed by this principal under a scope where the inspected service principal has RBAC."
  }

  $sasGeneratorGroups = @($blobReadEvidence | Where-Object {
      ([string]$_.authenticationType).Equals("SAS", [System.StringComparison]::OrdinalIgnoreCase) -and
      -not [string]::IsNullOrWhiteSpace((Get-OwnerCandidateSasGeneratorKey -BlobRead $_))
    } | Group-Object { Get-OwnerCandidateSasGeneratorKey -BlobRead $_ })

  $rule = $OwnerCandidatePolicy.CredentialGenerator
  if (-not (Test-OwnerCandidatePolicyEnabled -Rule $rule)) {
    $sasGeneratorGroups = @()
  }

  foreach ($sasGeneratorGroup in $sasGeneratorGroups) {
    $sasEvents = @($sasGeneratorGroup.Group | Sort-Object eventTimestamp)
    $firstSasEvent = $sasEvents | Select-Object -First 1
    $candidateName = Get-OwnerCandidateSasGeneratorName -BlobRead $firstSasEvent
    if ([string]::IsNullOrWhiteSpace($candidateName)) {
      continue
    }

    $evidenceId = [string]$firstSasEvent.storageAccountResourceId
    if ([string]::IsNullOrWhiteSpace($evidenceId)) {
      $evidenceId = [string]$firstSasEvent.uri
    }

    $evidenceValues = @($sasEvents | ForEach-Object {
        Get-OwnerCandidateTextValue -Value $_.operationName -Fallback $_.sasSignedPermissions
      } | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) } | Sort-Object -Unique)

    $candidates += New-OwnerCandidate `
      -Candidate $candidateName `
      -CandidateType (Get-OwnerCandidateSasGeneratorType -BlobRead $firstSasEvent) `
      -Confidence (ConvertTo-OwnerConfidence -Score (Get-OwnerCandidatePolicyScore -Rule $rule -CandidateType (Get-OwnerCandidateSasGeneratorType -BlobRead $firstSasEvent))) `
      -Relationship "Indirect" `
      -Signal ([string]$rule.Signal) `
      -EvidenceId $evidenceId `
      -EvidenceSource "StorageBlobLogs" `
      -EvidenceValue ([string]($evidenceValues -join ",")) `
      -Reason "StorageBlobLogs identify this principal as the generator of a user delegation SAS used for blob data-plane access."
  }

  $rankedCandidates = @($candidates |
    Sort-Object @{ Expression = { Get-OwnerConfidenceRank -Confidence ([string]$_.confidence) }; Descending = $true }, candidate, evidenceId)

  if ($rankedCandidates.Count -eq 0) {
    return @(
      New-OwnerCandidate `
        -Candidate "No owner candidate found" `
        -CandidateType "NotFound" `
        -Confidence "LOW" `
        -Relationship "None" `
        -Signal "NONE" `
        -EvidenceId "not-found" `
        -EvidenceSource "ownerCandidates" `
        -EvidenceValue "" `
        -Reason "No Graph owners, memberships, Azure RBAC co-assignments, resource owner tags, or activity evidence were found."
    )
  }

  return $rankedCandidates
}

# SIG # Begin signature block
# MII9MQYJKoZIhvcNAQcCoII9IjCCPR4CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAU1yan7WH+jYKd
# ASfVgZlKmRhuvlftYDrMv5hUurLwgKCCIfYwggXMMIIDtKADAgECAhBUmNLR1FsZ
# 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+tHD6n58vhavFIrmcxghqRMIIajQIBATBxMFox
# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzAp
# BgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQCEzMABN83
# wV0KQIA53+UAAAAE3zcwDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIw
# ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgnJAT
# rU0lCGvVDwNkxClt5gjLWeDKi/UPet3n8ncOBR8wDQYJKoZIhvcNAQEBBQAEggGA
# TnLc00qsdGcRbfufcJOwIiNAdP1keby8hxoH7WATYbvCM6n1ucNsaODaQumTqkSN
# gzSov/w4lYssHpWR4m1CY+5z4Y1SbavKx9Omw45C1nIpi8Qatm9O2BRa8ARGhk69
# WdReqElJhZh0978zuw3N22YWVCbfLByPqD0866VKEF2xuwYXnXH17zB3i3XyHbw6
# OKEAh8RDuawepa1QpA8bWc6UiXM4XRMM/4g++nL6wjMW61sOEakGN65VWO9ol3Vr
# sX4QnBYu54+pwQOq9/1yWfX6PA+4DCDT1n/G8mac/Ew34PTsc6RNi9sBLLT1NN9j
# FwOFq3wwbi2eQ2GdEgq9t5Q+UwmuypZYQbVy1ySbBk3z5jvb0A3ASALozpV8G+ID
# 6+EfBRsb4KD5EQMkThDXzP2TP1sBdTk9MnAnmZNd2g1+AyIWhBhVTZ9NhephviyP
# ux/ZQ7S5PdULOhTAErXhVoB9xGv7lDAo+TmP3X4e8gsSs4w4b+2Dlr9zvo89D4gy
# oYIYETCCGA0GCisGAQQBgjcDAwExghf9MIIX+QYJKoZIhvcNAQcCoIIX6jCCF+YC
# AQMxDzANBglghkgBZQMEAgEFADCCAWIGCyqGSIb3DQEJEAEEoIIBUQSCAU0wggFJ
# AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIHuR7NNufZk6CUQ9Av/U
# GdvLPRGFZnQBdfiEPb33turKAgZqhILMZL8YEzIwMjYwODI1MTIxNTE2Ljk2NVow
# BIACAfSggeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNV
# BAsTHm5TaGllbGQgVFNTIEVTTjo3RDAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWlj
# 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+gAwIBAgITMwAAAFXZ3WkmKPn44gAAAAAAVTANBgkqhkiG9w0B
# AQwFADBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcg
# Q0EgMjAyMDAeFw0yNTEwMjMyMDQ2NDlaFw0yNjEwMjIyMDQ2NDlaMIHbMQswCQYD
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3Nv
# ZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046
# N0QwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRp
# bWUgU3RhbXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAvbkfkh5ZSLP0MCUWafaw/KZoVZu9iQx8r5JwhZvdrUi86UjCCFQONjQa
# nrIxGF9hRGIZLQZ50gHrLC+4fpUEJff5t04VwByWC2/bWOuk6NmaTh9JpPZDcGzN
# R95QlryjfEjtl+gxj12zNPEdADPplVfzt8cYRWFBx/Fbfch08k6P9p7jX2q1jFPb
# UxWYJ+xOyGC1aKhDGY5b+8wL39v6qC0HFIx/v3y+bep+aEXooK8VoeWK+szfaFjX
# o8YTcvQ8UL4szu9HFTuZNv6vvoJ7Ju+o5aTj51sph+0+FXW38TlL/rDBd5ia79js
# kLtOeHbDjkbljilwzegcxv9i49F05ZrS/5ELZCCY1VaqO7EOLKVaxxdAO5oy1vb0
# Bx0ZRVX1mxFjYzay2EC051k6yGJHm58y1oe2IKRa/SM1+BTGse6vHNi5Q2d5ZnoR
# 9AOAUDDwJIIqRI4rZz2MSinh11WrXTG9urF2uoyd5Ve+8hxes9ABeP2PYQKlXYTA
# xvdaeanDTQ/vwmnM+yTcWzrVm84Z38XVFw4G7p/ZNZ2nscvv6uru2AevXcyV1t8h
# a7iWmhhgTWBNBrViuDlc3iPvOz2SVPbPeqhyY/NXwNZCAgc2H5pOztu6MwQxDIjt
# e3XM/FkKBxHofS2abNT/0HG+xZtFqUJDaxgbJa6lN1zh7spjuQ8CAwEAAaOCAcsw
# ggHHMB0GA1UdDgQWBBRWBF8QbdwIA/DIv6nJFsrB16xltjAfBgNVHSMEGDAWgBRr
# aSg6NS9IY0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQdWJsaWMlMjBS
# U0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsGAQUFBwEBBG0w
# azBpBggrBgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmclMjBD
# QSUyMDIwMjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGCN0yDfQEBMEEw
# PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j
# cy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEMBQADggIBAFIe
# 4ZJUe9qUKcWeWypchB58fXE/ZIWv2D5XP5/k/tB7LCN9BvmNSVKZ3VeclQM978wf
# EvuvdMQSUv6Y20boIM8DK1K1IU9cP21MG0ExiHxaqjrikf2qbfrXIip4Ef3v2bNY
# KQxCxN3Sczp1SX0H7uqK2L5OhfDEiXf15iou5hh+EPaaqp49czNQpJDOR/vfJghU
# c/qcslDPhoCZpZx8b2ODvywGQNXwqlbsmCS24uGmEkQ3UH5JUeN6c91yasVchS78
# riMrm6R9ZpAiO5pfNKMGU2MLm1A3pp098DcbFTAc95Hh6Qvkh//28F/Xe2bMFb6D
# L7Sw0ZO95v0gv0ZTyJfxS/LCxfraeEII9FSFOKAMEp1zNFSs2ue0GGjBt9yEEMUw
# vxq9ExFz0aZzYm8ivJfffpIVDnX/+rVRTYcxIkQyFYslIhYlWF9SjCw5r49qakjM
# RNh8W9O7aaoolSVZleQZjGt0K8JzMlyp6hp2lbW6XqRx2cOHbbxJDxmENzohGUzi
# I13lI2g2Bf5qibfC4bKNRpJo9lbE8HUbY0qJiE8u3SU8eDQaySPXOEhJjxRCQwwO
# vejYmBG5P7CckQNBSnnl12+FKRKgPoj0Mv+z5OMhj9z2MtpbnHLAkep0odQClEyy
# CG/uR5tK5rW6mZH5Oq56UWS0NI6NV1JGS7Jri6jFMYIHQzCCBz8CAQEweDBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAIT
# MwAAAFXZ3WkmKPn44gAAAAAAVTANBglghkgBZQMEAgEFAKCCBJwwEQYLKoZIhvcN
# AQkQAg8xAgUAMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0B
# CQUxDxcNMjYwODI1MTIxNTE2WjAvBgkqhkiG9w0BCQQxIgQgb+JjaUHeFttJpKWO
# 0DjfeKt1GyKc3C8GZVHyQRY3rwowgbkGCyqGSIb3DQEJEAIvMYGpMIGmMIGjMIGg
# BCDYuTyXZIZiu799/v4PaqsmeSzBxh0rqkYq7sYYavj+zTB8MGWkYzBhMQswCQYD
# VQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQD
# EylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAITMwAA
# AFXZ3WkmKPn44gAAAAAAVTCCA14GCyqGSIb3DQEJEAISMYIDTTCCA0mhggNFMIID
# QTCCAikCAQEwggEJoYHhpIHeMIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0QwMC0wNUUwLUQ5NDcxNTAzBgNV
# BAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5
# oiMKAQEwBwYFKw4DAhoDFQAdO1QBgmW/tuBZV5EGjhfsV4cN6qBnMGWkYzBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAN
# BgkqhkiG9w0BAQsFAAIFAO43kwMwIhgPMjAyNjA4MjUwNDA1MjNaGA8yMDI2MDgy
# NjA0MDUyM1owdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7jeTAwIBADAHAgEAAgIX
# 9jAHAgEAAgISdjAKAgUA7jjkgwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE
# AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IB
# AQB9Emto9c7RJDvCWisDZ1YOE+UhSKfZb0Sg9ruor4Yaaf/3O5I/Zii9v8Z/QqxD
# B+jI69mRT4jimiF50/dh3R/rv3+01+Hj4VUwFHGISkuG5Hb/dz/BC6jwO7VEQp+7
# PILFnqNgOGRyL6/vBlajuMOZ/PPjejwLq8VVYojlH3gWTwECNU9bh0/5h/80m0az
# 4lL5bV0detoCRSwueBYVAH71iA2RV42jlkxgq8Lp4JWc8/ZzDBsFcGSVVngD2TE4
# pTVpVpDpetcUBC5MN7JCtceZOLHN/c6Vm9t9Hzq6GOFWtShI0J2pFZt07YVvbI+J
# GULWGJcscW/hpPeyhXav1Dp5MA0GCSqGSIb3DQEBAQUABIICAJNyUtnxXNwV68yv
# lP5zPguHHfF9R7AuT/zmW/ZRO2HT6l63iw2FbSUWjoxhE5caUVhG3ThDsh5Z2+te
# WBcW8rEvLG9ZYOck/vN3Pv/JpAepJjWveOjqBeWt6l80F4eg+Rht9j1TMoTJLMOp
# nxSTTp26zfPVJZkqMNpu6aWTPXLev736meYF476suNq9Q7YidmazpHHihIkuQBJu
# nYmnI9UezlSWZ3tvpwLdDhh8OYyZWkqXdVej3R961nvGRD9K1m9ufmvqp5MUC6m4
# T+1OEdyougg2DoFAAaQWT9zxgA5xzJOQENYKJ+ihi2r93mpNpkVT912BuqwnHhFw
# Ikji6X/A3MpK1c0RbYaoKHiSF5pHz9rupLAz6EL0pR8+NFd04i2UwvjEZj+8H4m7
# IKl8DUgj0gEX6eWJE+ZRwv6pAl/rOCrDus7md7FhgdpT24XkNAk9dDxbWoxBAzxx
# elrWiqxrgF26I5a8StA/aS9QE/I3wBFDmw/E2qhEXluES5aeS4VCabiPE444MvfM
# 8b+1dGTXjGhFBED5HeLC8Vk0qFG0JaHaoFbTaWuTL6ujFioZjR/3blLprwzNYtUC
# D+m9oGzRS8TSbHldv0tXOFscGt+/p3jv8KPjG/zLwv2MM0HKIUnF4ovMgMiUFuXx
# 3hWNmcgwTYGV0Rz9zA9EtFpJeijR
# SIG # End signature block