public/Convert-SentinelARArmToYaml.ps1
<#
.SYNOPSIS Converts an Azure Sentinel Analytics Rule ARM template to YAML .DESCRIPTION Converts an Azure Sentinel Analytics Rule ARM template to YAML. The ARM template can be provided as a file or as a string. The YAML file can be saved to the same directory as the ARM template file. .PARAMETER Filename The path to the Analytics Rule ARM template file .PARAMETER Data The ARM template data as a string .PARAMETER OutFile The path to the output YAML file .PARAMETER UseOriginalFilename If set, the output file will be saved with the original filename of the ARM template file The extension will be replaced with .yaml .PARAMETER UseDisplayNameAsFilename If set, the output file will be saved with the display name of the Analytics Rule as filename The extension will be replaced with .yaml .PARAMETER UseIdAsFilename If set, the output file will be saved with the id of the Analytics Rule as filename The extension will be replaced with .yaml .EXAMPLE Convert-SentinelARArmToYaml -Filename "C:\Temp\MyRule.json" -OutFile "C:\Temp\MyRule.yaml" .NOTES Author: Fabian Bader (https://cloudbrothers.info/) #> function Convert-SentinelARArmToYaml { [CmdletBinding(DefaultParameterSetName = 'StdOut')] param ( [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Path')] [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'UseOriginalFilename')] [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'UseDisplayNameAsFilename')] [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'UseIdAsFilename')] [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'StdOut')] [string]$Filename, [Alias('Yaml')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Pipeline', Position = 0)] [array]$Data, [Parameter(Mandatory = $false, ParameterSetName = 'Path')] [Parameter(Mandatory = $false, ParameterSetName = 'Pipeline')] [string]$OutFile, [Parameter(ParameterSetName = 'UseOriginalFilename')] [switch]$UseOriginalFilename, [Parameter(ParameterSetName = 'UseDisplayNameAsFilename')] [switch]$UseDisplayNameAsFilename, [Parameter(ParameterSetName = 'UseIdAsFilename')] [switch]$UseIdAsFilename ) begin { if ($PsCmdlet.ParameterSetName -ne "Pipeline" ) { if (-not (Test-Path $Filename) ) { throw "File not found" } } } process { # Use pipeline data and create a variable containing all parsed strings if ($PsCmdlet.ParameterSetName -eq "Pipeline") { $FullARM += $Data } } end { # Mapping of Arm property names to YAML when different $ValueNameMappingArm2Yaml = [ordered]@{ "displayName" = "name" "alertRuleTemplateName" = "id" "templateVersion" = "version" "techniques" = "relevantTechniques" } # Mapping of Arm operator names to YAML when different $CompareOperatorArm2Yaml = @{ "Equals" = "eq" "GreaterThan" = "gt" "GreaterThanOrEqual" = "ge" "LessThan" = "lt" "LessThanOrEqual" = "le" } # List of values to always remove $RemoveArmValues = @( "enabled" ) $DefaultSortOrderInYAML = @( "id", "name", "version", "kind", "description", "severity", "requiredDataConnectors", "queryFrequency", "queryPeriod", "triggerOperator", "triggerThreshold", "tactics", "relevantTechniques", "query" ) # Use parsed pipeline data if no file was specified (default) try { if ($PsCmdlet.ParameterSetName -eq "Pipeline") { $AnalyticsRuleTemplate = $FullARM | ConvertFrom-Json -Verbose } else { Write-Verbose "Read file `"$Filename`"" $AnalyticsRuleTemplate = Get-Content $Filename | ConvertFrom-Json -Verbose } } catch { throw "Could not convert source file. JSON might be corrupted" } if ($AnalyticsRuleTemplate.resources.Count -ne 1) { throw "ARM template must contain exactly one resource" } # Get the id of the analytic rule if ($AnalyticsRuleTemplate.resources.id -match "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") { $Id = $Matches[0] } else { Write-Warning "Error reading current Id. Generating new Id." $Id = (New-Guid).Guid } Write-Verbose "Convert Analytics Rule $($AnalyticsRuleTemplate.resources.properties.displayName) ($($Id)) to YAML file" #region Set output filename to defined value if not specified by user if ($PsCmdlet.ParameterSetName -in ("UseOriginalFilename", "UseDisplayNameAsFilename", "UseIdAsFilename") ) { $FileObject = Get-ChildItem $Filename if ($UseOriginalFilename) { # Use original filename as new filename $NewFileName = $FileObject.Name -replace $FileObject.Extension, ".yaml" } if ($UseDisplayNameAsFilename) { # Use the display name of the Analytics Rule as filename $NewFileName = $AnalyticsRuleTemplate.resources.properties.displayName -Replace '[^0-9A-Z]', ' ' # Convert To CamelCase $NewFileName = ((Get-Culture).TextInfo.ToTitleCase($NewFileName) -Replace ' ') + '.yaml' } if ($UseIdAsFilename) { # Use id as of the Analytics Rule filename $NewFileName = $Id + '.yaml' } $OutFile = Join-Path $FileObject.Directory $NewFileName } #endregion # Get the properties of the analytic rule $AnalyticsRule = $AnalyticsRuleTemplate.resources | Select-Object -ExpandProperty properties # Add the id and kind from the ARM template $AnalyticsRule = $AnalyticsRule | Add-Member -MemberType NoteProperty -Name "id" -Value $Id -PassThru -Force $AnalyticsRule = $AnalyticsRule | Add-Member -MemberType NoteProperty -Name "kind" -Value $AnalyticsRuleTemplate.resources.kind -PassThru -Force # Remove values that are not needed foreach ($RemoveArmValue in $RemoveArmValues) { $AnalyticsRule.PSObject.Properties.Remove($RemoveArmValue) | Out-Null } $JSON = $AnalyticsRule | ConvertTo-Json -Depth 100 # Use ISO8601 format for timespan values $JSON = $JSON -replace '"PT([0-9]+)M"', '"$1m"' -replace '"PT([0-9]+)H"', '"$1h"' -replace '"P([0-9]+)D"', '"$1d"' # Convert the names of the properties to the names used in the YAML foreach ($Arm2Yaml in $ValueNameMappingArm2Yaml.Keys) { $JSON = $JSON -replace $Arm2Yaml, $ValueNameMappingArm2Yaml[$Arm2Yaml] } # Convert the compare operators to the names used in the YAML foreach ($Arm2Yaml in $CompareOperatorArm2Yaml.Keys) { $JSON = $JSON -replace $Arm2Yaml, $CompareOperatorArm2Yaml[$Arm2Yaml] } # Convert the JSON to a PowerShell object $AnalyticsRule = $JSON | ConvertFrom-Json # Use custom sort order of YAML $ErrorActionPreference = "SilentlyContinue" $AnalyticsRuleKeys = $AnalyticsRule.PSObject.Properties.Name | Sort-Object { $i = $DefaultSortOrderInYAML.IndexOf($_) ; if ( $i -eq -1 ) { 100 } else { $i } } $ErrorActionPreference = "Continue" # Create ordered hashtable $AnalyticsRuleCleaned = [ordered]@{} foreach ($PropertyName in $AnalyticsRuleKeys) { # Remove empty properties if ( -not [string]::IsNullOrWhiteSpace($AnalyticsRule.$PropertyName) -or ( $AnalyticsRule.$PropertyName -is [array] -and ($AnalyticsRule.$PropertyName.Count -gt 0) ) ) { $AnalyticsRuleCleaned.Add($PropertyName, $AnalyticsRule.$PropertyName) } } # Convert the PowerShell object to YAML $AnalyticsRuleYAML = $AnalyticsRuleCleaned | ConvertTo-Yaml # Write the YAML to a file or return the YAML if ($OutFile) { $AnalyticsRuleYAML | Out-File $OutFile -Force -Encoding utf8 Write-Verbose "Output written to file: `"$OutFile`"" } else { return $AnalyticsRuleYAML } } } # SIG # Begin signature block # MIIn3wYJKoZIhvcNAQcCoIIn0DCCJ8wCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUPvxoNnTlLUcUyYVQaRj5/vRb # zPiggiEHMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGrjCCBJag # AwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIw # MzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQg # UlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCw # zIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFz # sbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ # 7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7 # QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/teP # c5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCY # OjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9K # oRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6 # dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM # 1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbC # dLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbEC # AwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1N # hS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcB # AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr # BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAI # BgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7Zv # mKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI # 2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/ty # dBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVP # ulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmB # o1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc # 6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3c # HXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0d # KNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZP # J/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLe # Mt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDy # Divl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBrAwggSYoAMCAQICEAitQLJg0pxM # n17Nqb2TrtkwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE # AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIxMDQyOTAwMDAwMFoXDTM2 # MDQyODIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS # U0E0MDk2IFNIQTM4NCAyMDIxIENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBANW0L0LQKK14t13VOVkbsYhC9TOM6z2Bl3DFu8SFJjCfpI5o2Fz16zQk # B+FLT9N4Q/QX1x7a+dLVZxpSTw6hV/yImcGRzIEDPk1wJGSzjeIIfTR9TIBXEmtD # mpnyxTsf8u/LR1oTpkyzASAl8xDTi7L7CPCK4J0JwGWn+piASTWHPVEZ6JAheEUu # oZ8s4RjCGszF7pNJcEIyj/vG6hzzZWiRok1MghFIUmjeEL0UV13oGBNlxX+yT4Us # SKRWhDXW+S6cqgAV0Tf+GgaUwnzI6hsy5srC9KejAw50pa85tqtgEuPo1rn3MeHc # reQYoNjBI0dHs6EPbqOrbZgGgxu3amct0r1EGpIQgY+wOwnXx5syWsL/amBUi0nB # k+3htFzgb+sm+YzVsvk4EObqzpH1vtP7b5NhNFy8k0UogzYqZihfsHPOiyYlBrKD # 1Fz2FRlM7WLgXjPy6OjsCqewAyuRsjZ5vvetCB51pmXMu+NIUPN3kRr+21CiRshh # WJj1fAIWPIMorTmG7NS3DVPQ+EfmdTCN7DCTdhSmW0tddGFNPxKRdt6/WMtyEClB # 8NXFbSZ2aBFBE1ia3CYrAfSJTVnbeM+BSj5AR1/JgVBzhRAjIVlgimRUwcwhGug4 # GXxmHM14OEUwmU//Y09Mu6oNCFNBfFg9R7P6tuyMMgkCzGw8DFYRAgMBAAGjggFZ # MIIBVTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRoN+Drtjv4XxGG+/5h # ewiIZfROQjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8B # Af8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYIKwYBBQUHAQEEazBpMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKG # NWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290 # RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMBwGA1UdIAQVMBMwBwYFZ4EMAQMw # CAYGZ4EMAQQBMA0GCSqGSIb3DQEBDAUAA4ICAQA6I0Q9jQh27o+8OpnTVuACGqX4 # SDTzLLbmdGb3lHKxAMqvbDAnExKekESfS/2eo3wm1Te8Ol1IbZXVP0n0J7sWgUVQ # /Zy9toXgdn43ccsi91qqkM/1k2rj6yDR1VB5iJqKisG2vaFIGH7c2IAaERkYzWGZ # gVb2yeN258TkG19D+D6U/3Y5PZ7Umc9K3SjrXyahlVhI1Rr+1yc//ZDRdobdHLBg # XPMNqO7giaG9OeE4Ttpuuzad++UhU1rDyulq8aI+20O4M8hPOBSSmfXdzlRt2V0C # FB9AM3wD4pWywiF1c1LLRtjENByipUuNzW92NyyFPxrOJukYvpAHsEN/lYgggnDw # zMrv/Sk1XB+JOFX3N4qLCaHLC+kxGv8uGVw5ceG+nKcKBtYmZ7eS5k5f3nqsSc8u # pHSSrds8pJyGH+PBVhsrI/+PteqIe3Br5qC6/To/RabE6BaRUotBwEiES5ZNq0RA # 443wFSjO7fEYVgcqLxDEDAhkPDOPriiMPMuPiAsNvzv0zh57ju+168u38HcT5uco # P6wSrqUvImxB+YJcFWbMbA7KxYbD9iYzDAdLoNMHAmpqQDBISzSoUSC7rRuFCOJZ # DW3KBVAr6kocnqX9oKcfBnTn8tZSkP2vhUgh+Vc7tJwD7YZF9LRhbr9o4iZghurI # r6n+lB3nYxs6hlZ4TjCCBsAwggSooAMCAQICEAxNaXJLlPo8Kko9KQeAPVowDQYJ # KoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2 # IFRpbWVTdGFtcGluZyBDQTAeFw0yMjA5MjEwMDAwMDBaFw0zMzExMjEyMzU5NTla # MEYxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDEkMCIGA1UEAxMbRGln # aUNlcnQgVGltZXN0YW1wIDIwMjIgLSAyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEAz+ylJjrGqfJru43BDZrboegUhXQzGias0BxVHh42bbySVQxh9J0J # dz0Vlggva2Sk/QaDFteRkjgcMQKW+3KxlzpVrzPsYYrppijbkGNcvYlT4DotjIdC # riak5Lt4eLl6FuFWxsC6ZFO7KhbnUEi7iGkMiMbxvuAvfTuxylONQIMe58tySSge # TIAehVbnhe3yYbyqOgd99qtu5Wbd4lz1L+2N1E2VhGjjgMtqedHSEJFGKes+JvK0 # jM1MuWbIu6pQOA3ljJRdGVq/9XtAbm8WqJqclUeGhXk+DF5mjBoKJL6cqtKctvdP # bnjEKD+jHA9QBje6CNk1prUe2nhYHTno+EyREJZ+TeHdwq2lfvgtGx/sK0YYoxn2 # Off1wU9xLokDEaJLu5i/+k/kezbvBkTkVf826uV8MefzwlLE5hZ7Wn6lJXPbwGqZ # IS1j5Vn1TS+QHye30qsU5Thmh1EIa/tTQznQZPpWz+D0CuYUbWR4u5j9lMNzIfMv # wi4g14Gs0/EH1OG92V1LbjGUKYvmQaRllMBY5eUuKZCmt2Fk+tkgbBhRYLqmgQ8J # JVPxvzvpqwcOagc5YhnJ1oV/E9mNec9ixezhe7nMZxMHmsF47caIyLBuMnnHC1mD # jcbu9Sx8e47LZInxscS451NeX1XSfRkpWQNO+l3qRXMchH7XzuLUOncCAwEAAaOC # AYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATAf # BgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4EFgQUYore0GH8 # jzEU7ZcLzT0qlBTfUpwwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFt # cGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVT # dGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAVaoqGvNG83hXNzD8deNP # 1oUj8fz5lTmbJeb3coqYw3fUZPwV+zbCSVEseIhjVQlGOQD8adTKmyn7oz/AyQCb # Ex2wmIncePLNfIXNU52vYuJhZqMUKkWHSphCK1D8G7WeCDAJ+uQt1wmJefkJ5ojO # fRu4aqKbwVNgCeijuJ3XrR8cuOyYQfD2DoD75P/fnRCn6wC6X0qPGjpStOq/CUkV # NTZZmg9U0rIbf35eCa12VIp0bcrSBWcrduv/mLImlTgZiEQU5QpZomvnIj5EIdI/ # HMCb7XxIstiSDJFPPGaUr10CU+ue4p7k0x+GAWScAMLpWnR1DT3heYi/HAGXyRkj # gNc2Wl+WFrFjDMZGQDvOXTXUWT5Dmhiuw8nLw/ubE19qtcfg8wXDWd8nYiveQclT # uf80EGf2JjKYe/5cQpSBlIKdrAqLxksVStOYkEVgM4DgI974A6T2RUflzrgDQkfo # QTZxd639ouiXdE4u2h4djFrIHprVwvDGIqhPm73YHJpRxC+a9l+nJ5e6li6FV8Bg # 53hWf2rvwpWaSxECyIKcyRoFfLpxtU56mWz06J7UWpjIn7+NuxhcQ/XQKujiYu54 # BNu90ftbCqhwfvCXhHjjCANdRyxjqCU4lwHSPzra5eX25pvcfizM/xdMTQCi2NYB # DriL7ubgclWJLCcZYfZ3AYwwggdIMIIFMKADAgECAhAKgjCQR6s2I8rDH7I9rOua # MA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2Vy # dCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25p # bmcgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjIwNTE4MDAwMDAwWhcNMjUw # NTE3MjM1OTU5WjBNMQswCQYDVQQGEwJERTEQMA4GA1UEBxMHSGFtYnVyZzEVMBMG # A1UEChMMRmFiaWFuIEJhZGVyMRUwEwYDVQQDEwxGYWJpYW4gQmFkZXIwggIiMA0G # CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDBI8VJts4gUJjzaL//82nAioe/sYkI # OqO74ImDtMCiMNXYINLPvao3Y9iNXlqd+H+N4lUa0DsGsJ4paQvNUf0/ilbnaO4S # HBF7t9u/uz4+SlOEsF3BBeH8kcReki/2MuQ4YfdjGvGghLlt2fMp+7JSvyon8n5T # pr1KCQ6QU0zqkYcUZjZOxEDzAyNN2mFgZMp/nzmEfiYPv8arV1vvYhAOmigpdg9m # htD4sC4u0X9GBNUfVi2D/rWZ3bylXflDJm6MBxyhgmOANbN5zHs7tx1i7ACWw9+H # ov5gVU7H0vK5pUVCDrDrd7UM1gSC4iY+Xq1a0Aw4eaBfF3hrjD8fS29SSqM4fkrh # 1TgJaZwhKeR2Hax0c3DHyCN9h7dPClbGUU5TUcRp7ocA0Xq1W0jJWFBHBLsnUM0k # 7Uog4ZkMGEqGI+SWvXtYydHl5gQI51xpyQcNP3JkndAeRPQYxrcqdlJHnpGE5vPs # 0fyWUlFJn/bLMM48CGIU6sqNk9hgvxHnbjxmTE7FtMlalOFbnd0o8zpv02i2qIlb # mu7h45WrTKNIx208u21AC7ocS00ojX3QCK/lc89BgzIjU8dUtjmxXumbfqEiljkR # bbcecmzfTbgCIXjkU3WbEeVSSbtz4Jiw0BufJEmUhxTIXXbVqQU1W4ZBTBshCe2Z # Chr+TF3++ljakQIDAQABo4ICBjCCAgIwHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHQYDVR0OBBYEFPUKlMJ9lsMeVu5KQOaYqYXKAg45MA4GA1UdDwEB # /wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBP # hk1odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2Rl # U2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2Ny # bDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0 # MDk2U0hBMzg0MjAyMUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggr # BgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcB # AQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwG # CCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAMBgNV # HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQAJwchVKGCBGuhUPGL5IN8k6pUz # Zn3ZPbli/zHJYYxSbXhsYQ4GCd8eIhQmYr0GmbST+GdgSlXkiWXz9F/bSX7K+XBO # PWbiy3ZGvhzzhFIaatbzeaRjEyGDlgu0uJl1p80JyS737bp2BnnfsrtgOEa4h5aD # vTxVyECcMRvwKWKpYxgvDoni9qBD3UTl6Y+mrsWEOzao0wSWeuNZQuNCRhEaUN/D # bYBymy0KsQGRz7XxZmXoEPY7DUPXCExXo/XjvZmBNyjo9ynwEqGuqihRerYIPBhc # lv+IU3BGe7sKzvy752Uu76xc3Gxsa49P0iD7k68LUWIcx45rhpLwdlKlNu7jDxxy # Uv0R1eqWBVcULY+UOKv/Zb1WP2zq2JKneF2Uft0g7kURCHwkut08XApdnx2uC8/b # ox/XWMK/KQz5BCb2OEH9WECfCKySBSh0iR+jHRGMm0JCQ1PWheolUSvAGqX8hVBQ # 1AJHtDt8DxTaNTwUFORivJRABBogSrFq/dz4aoz3hOHcLkW+s67gJTbz8dm5ONlk # IE/uzYRb//htFRBKdcHiZqzNRH7/xH5tf77J8f867UdAvloaj2rYvfqhpUWNozbz # bDWnMUARR/SOClSQF4k4VR4W+KthbKp7H6grDLxXOCz4Ep3sU5KEtrvAJqLV+N9i # +k7sbFul1gmpqc0yYDGCBkIwggY+AgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNV # BAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0 # IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQCoIwkEerNiPK # wx+yPazrmjAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZ # BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB # BAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU6ClPZMz8KIB+ljgcRKnyV9DSk4wwDQYJ # KoZIhvcNAQEBBQAEggIAKbmfMeWRTZKOgbnJrUCNstWwSgL8+119e91TLn0SuLvh # ef0qxVVrLvzaVzx5oInxu9PHcn51m/KL55QQc0r6uRy9O701847A5Yjfhjh+DD3T # lHUKoK/nOrPHVXHW10nvewa5acNZFuD1CeZctbD/Mn11J1OJcziwG3Rk1Q7DnMPu # P26Vet+7SyTsR9HIms7jJJxdRqrH27/EvxFEm/4bNscOwrwHZToAtQiBfm/gjgLt # 7kGXLOUln+3pYK3z6CXJT74Pr9LZb2c25svOQu9oe3l5XG5A4RC/jtj1Rctdo+yh # 3vItt/xxLgq2lUrdWAVGFvn5Ak7tf0vGj8vx5cjM2FissZH06u80RVq7IaCC4QD3 # 2E4N2A5d+0rFLC0KT8Qr7oK7mAobZYJJa80tjMaBZ5jKClq5Br0Jx679Vyui48TX # sm3xgPCJ3H4LzFvUptrl4geewsbTFgT7e0k8ioQ7ycrCKU6MchfG3X4Lr6G9m8sP # Q9Kt4xkKGSCIgTayIZYXo8YQ73Z3GyWF8I9ZUqusSrBOzxefY/OoOniT0fo58wGS # RjcpXz7JY9VOCDt/o8l6o/Fo6Fv73bqRbbCN5D60ZQ2aqE2K4XAq0a3PCc2h/9yM # XgqXdeA/AZwJ9Dzy65Z1HHavpl0NfaHIam2bGec/uYarAQ0i7jQ6BaCoRqmtAlWh # ggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0 # ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAMTWlyS5T6PCpK # PSkHgD1aMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEH # ATAcBgkqhkiG9w0BCQUxDxcNMjMwMzAyMjA1NTUxWjAvBgkqhkiG9w0BCQQxIgQg # sQzq5l6hbUd1wcSb47Y9nNGuHXu7QqhyqUgXbRr+E1kwDQYJKoZIhvcNAQEBBQAE # ggIAHtj1Bn4OncTM+dMOzjiBHMO1FxC47+/PyTxEXmJSgKwhNxWRcTZP31HT+GOW # CxYJOwMgozEOS6e6ReZNe7vUdjuPN4eh2+YEKaO/V4LW8MdJxVR/wbfBXGWZW3FR # jVxOjjokZjh8jIxe9bqbi011EwI1NntJG9gEOGuqXM7nBNmLITxSyoTtfd40BT96 # 9Bbz8P7yfGOpxFAhvDr5UmJpJGZ7u+rcJRQ2FX065T581PK6EJCiAzj8nXOc9WIt # QnGIpaPi+H13kaffJ0HHipwD+xxQqujPTzZ+9EC4xXBfdP4EHTe6yr3D4E6PM2L4 # MwzdCYRPuP7UNNwOUF3PYy2Ucr2RHkmsZICvN0RziPmMgH1m2vNsOpY7uAAsfgcR # 6zny7aUk6m1Ld8fP58cNVe5XuFNxtjS9mvUIsJq5A82+ieFQwi+39dkChdYQ+zA0 # I646sBgRjjcoe+uUmHuSGa1vEwMzD1u33WoEIAWUiC3Y1XkYJIunatujQ9Dt+5xz # Sy3rgx41XbyZAhqvNAqelBTBl8Jri+7EbA2U3+6egU2OHw4Q+8MVD8JWOwzx/WR0 # 5OxieXw888j06uqyCn4CvszITvQeg3Z1+3iV6ZktQYRLmmmF4XkVmesZOFMZANma # KKcAR7J9w8kVQA2agvK175RWR9Ycv6OnOBaqFzyXjTMYHLw= # SIG # End signature block |