public/Convert-SentinelARYamlToArm.ps1
<#
.SYNOPSIS Converts an Azure Sentinel Analytics Rule YAML file to ARM template .DESCRIPTION Converts an Azure Sentinel Analytics Rule YAML file to ARM template. The YAML file can be provided as a file or as a string. The ARM template file can be saved to the same directory as the YAML file. .PARAMETER Filename The path to the Analytics Rule YAML file .PARAMETER Data The YAML data as a string .PARAMETER OutFile The path to the output ARM template 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 .json .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 .json .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 .json .PARAMETER APIVersion Set API version of the ARM template. Default is "2022-11-01-preview" .EXAMPLE Convert-SentinelARYamlToArm -Filename "C:\Temp\MyRule.yaml" -OutFile "C:\Temp\MyRule.json" .NOTES Author: Fabian Bader (https://cloudbrothers.info/) #> function Convert-SentinelARYamlToArm { [CmdletBinding(DefaultParameterSetName = 'StdOut')] param ( [Parameter(Mandatory, Position = 0, ParameterSetName = 'Path')] [Parameter(Mandatory, Position = 0, ParameterSetName = 'UseOriginalFilename')] [Parameter(Mandatory, Position = 0, ParameterSetName = 'UseDisplayNameAsFilename')] [Parameter(Mandatory, Position = 0, ParameterSetName = 'UseIdAsFilename')] [Parameter(Mandatory, Position = 0, ParameterSetName = 'StdOut')] [string]$Filename, [Alias('Json')] [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Pipeline', Position = 0)] [array]$Data, [Parameter(ParameterSetName = 'Path')] [Parameter(ParameterSetName = 'Pipeline')] [string]$OutFile, [Parameter(ParameterSetName = 'UseOriginalFilename')] [switch]$UseOriginalFilename, [Parameter(ParameterSetName = 'UseDisplayNameAsFilename')] [switch]$UseDisplayNameAsFilename, [Parameter(ParameterSetName = 'UseIdAsFilename')] [switch]$UseIdAsFilename, [ValidatePattern('^\d{4}-\d{2}-\d{2}(-preview)?$')] [Parameter()] [string]$APIVersion = "2022-11-01-preview" ) begin { if ($PsCmdlet.ParameterSetName -ne "Pipeline" ) { try { if (-not (Test-Path $Filename)) { Write-Error -Exception } } catch { throw "File not found" } } } process { # Use pipeline data and create a variable containing all parsed strings if ($PsCmdlet.ParameterSetName -eq "Pipeline") { $FullYaml += $Data } } end { try { # Use parsed pipeline data if no file was specified (default) if ($PsCmdlet.ParameterSetName -eq "Pipeline") { $analyticRule = $FullYaml | ConvertFrom-Yaml } else { Write-Verbose "Read file `"$Filename`"" $analyticRule = Get-Content $Filename | ConvertFrom-Yaml } } catch { throw "Could not convert source file. YAML might be corrupted" } if ( [string]::IsNullOrWhiteSpace($analyticRule.name) -or [string]::IsNullOrWhiteSpace($analyticRule.id) ) { throw "Analytics Rule name or id is empty. YAML might be corrupted" } Write-Verbose "Convert Analytics Rule $($analyticRule.name) ($($analyticRule.id)) to ARM template" #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, ".json" } if ($UseDisplayNameAsFilename) { # Use the display name of the Analytics Rule as filename $NewFileName = $analyticRule.name -Replace '[^0-9A-Z]', ' ' # Convert To CamelCase $NewFileName = ((Get-Culture).TextInfo.ToTitleCase($NewFileName) -Replace ' ') + '.json' } if ($UseIdAsFilename) { # Use id as of the Analytics Rule filename $NewFileName = $analyticRule.id + '.json' } $OutFile = Join-Path $FileObject.Directory $NewFileName } #endregion $Template = @' { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "workspace": { "type": "String" } }, "resources": [ { "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/<TEMPLATEID>')]", "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/<TEMPLATEID>')]", "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules", "kind": "<RULEKIND>", "apiVersion": "<APIVERSION>", "properties": <PROPERTIES> } ] } '@ # Replace API version with specified version $Template = $Template.Replace('<APIVERSION>', $APIVersion) # Only include the following keys in ARM template $DefaultSortOrderInArmTemplate = @( "displayName", "description", "severity", "enabled", "query", "queryFrequency", "queryPeriod", "triggerOperator", "triggerThreshold", "suppressionDuration", "suppressionEnabled", "tactics", "techniques", "alertRuleTemplateName", "incidentConfiguration", "eventGroupingSettings", "alertDetailsOverride", "customDetails", "entityMappings", "sentinelEntitiesMappings" ) $SkipYamlValues = @( "metadata", "kind", "requiredDataConnectors" ) # Mapping of Arm template names to YAML name when different $ValueNameMappingYaml2Arm = [ordered]@{ "name" = "displayName" "id" = "alertRuleTemplateName" "version" = "templateVersion" "relevantTechniques" = "techniques" } $CompareOperatorYaml2Arm = @{ "eq" = "Equals" "gt" = "GreaterThan" "ge" = "GreaterThanOrEqual" "lt" = "LessThan" "le" = "LessThanOrEqual" } $ARMTemplate = [ordered]@{} foreach ($Item in $analyticRule.Keys) { # Skip certain values, because they are not needed in the ARM template if ( $Item -notin $SkipYamlValues ) { # Change the name of the value if needed $KeyName = $ValueNameMappingYaml2Arm[$Item] # If the name is not in the mapping, use the original name if ([string]::IsNullOrWhiteSpace($KeyName)) { $KeyName = $Item } # Change values of compare operators if ( $analyticRule[$Item] -in $CompareOperatorYaml2Arm.Keys ) { $Value = $CompareOperatorYaml2Arm[$analyticRule[$Item]] } else { $Value = $analyticRule[$Item] } # Add value to hashtable if ($KeyName -notin $ARMTemplate.keys) { $ARMTemplate.Add($KeyName, $Value) } } } # Add required parameters if missing with default values $RequiredParameters = @{ "suppressionDuration" = "PT1H" "suppressionEnabled" = $false "enabled" = $true "customDetails" = $null "entityMappings" = $null "templateVersion" = "1.0.0" } foreach ( $KeyName in $RequiredParameters.Keys ) { if ( $KeyName -notin $ARMTemplate.Keys ) { $ARMTemplate.Add($KeyName, $RequiredParameters[$KeyName]) } } # Sort by custom order $ARMTemplateOrdered = [ordered]@{} $ErrorActionPreference = "SilentlyContinue" $AnalyticsRuleKeys = $ARMTemplate.Keys | Sort-Object { $i = $DefaultSortOrderInArmTemplate.IndexOf($_) ; if ( $i -eq -1 ) { 100 } else { $i } } $ErrorActionPreference = "Continue" foreach ($PropertyName in $AnalyticsRuleKeys) { $ARMTemplateOrdered.Add($PropertyName, $ARMTemplate.$PropertyName) } # Convert hashtable to JSON $JSON = $ARMTemplateOrdered | ConvertTo-Json -Depth 99 # Use ISO8601 format for timespan values $JSON = $JSON -replace '"([0-9]+)m"', '"PT$1M"' -replace '"([0-9]+)h"', '"PT$1H"' -replace '"([0-9]+)d"', '"P$1D"' if ($analyticRule.kind -eq "Scheduled") { $ScheduleKind = "Scheduled" } elseif ($analyticRule.kind -eq "Nrt") { $ScheduleKind = "NRT" } else { $ScheduleKind = $analyticRule.kind.substring(0, 1).toupper() + $analyticRule.kind.substring(1).tolower() } $Result = $Template.Replace("<PROPERTIES>", $JSON) $Result = $Result.Replace("<TEMPLATEID>", $analyticRule.id) $Result = $Result.Replace("<RULEKIND>", $ScheduleKind) if ( $PSVersionTable.PSVersion -ge [version]'7.0.0' ) { # Beautify in PowerShell 7 and above $Result = $Result | ConvertFrom-Json | ConvertTo-Json -Depth 99 } if ($OutFile) { $Result | Out-File $OutFile -Force Write-Verbose "Output written to file: `"$OutFile`"" } else { return $Result } } } # SIG # Begin signature block # MIIn3wYJKoZIhvcNAQcCoIIn0DCCJ8wCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUsCKFU81+KwJlAh4poxOr/XeM # lfyggiEHMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # 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 # BAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUncotlo0i6uddtxngEsjVMl/GFvswDQYJ # KoZIhvcNAQEBBQAEggIACqQCk3Q55HHUmOQtA3y+Kc4Kx8kNqPPPUxROOHtkmo0j # UB6WG7uZqIcbM/vBs7m71VWiPWFNCbtMSseNzLoDSpd8p4ZlNEKBNM/RMhdHehd+ # WuuLmESPDE6gTeSkJZOioAVA2P23QpO66n02piEGdAaI7oaFJFiEUgUVXirHdQLK # s8KlkmvhfkpG4I9yGco1TPBnxfvch1bi8+sCbryB3LdKGVuo3Ymi6XysmjR4wU+o # wB8QL76m9EObIy7I3dniBKM4nFEN1XVCkkxSLNMqBzy5TxYDbFsYq0yO8lrd+sEy # xPXwSvCmZJhhbDOzkptXIS2UUvntNYAn2w1rqaH5LXXE5UVIHZ+8MVMjC5mDRNON # G8N6JI2f7FsoONBc9PireDPasnxCF5DaMFUFhiRX0zJc5cETi3MC94VaUpQeTFB5 # AQfovDlsf3MMjU6df0KFOHMK4qwlgVXJMPPKjypa4CwXFCEk6KJxZD9lxFmo0/Cs # bxn4mbFctZepQlK1MOQvBn55p4tWCzsvamsyKGkHtQ4UJFEpoQguNKwIEoAaWDtF # WY7hS9xlGqaV57T3SiFiqZJ9rQ1cpyDqQU0gh+rrB97QjCrMa1oImcHBKWs1ROvA # zen3+kBtBWRvSKAw746shTk5nI7GFnBzu5ox0PjZPpfabnKxo5pnuw3oNoCDNh2h # ggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQGEwJVUzEX # MBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0 # ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAMTWlyS5T6PCpK # PSkHgD1aMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEH # ATAcBgkqhkiG9w0BCQUxDxcNMjMwNzI2MTA0NTU4WjAvBgkqhkiG9w0BCQQxIgQg # PgmM96xA6acUiz79CDntC0kH2n0ahQFJXb+/DUC6AQUwDQYJKoZIhvcNAQEBBQAE # ggIAXtRkRbcSK8NlL34Hz6sH1w5z11v+NkNTfgIM9tZUQhPmvJqlV/4j5Bf2Ql3n # 9Y0Fhu69S5iJnk8wRtmSGrnYMHhlsS9wRbj3WAfBfh1n0zZsN81qDR7axVRpp3Mu # RuR5s0hpA+yH0Mg0A0L1ew9KGq5ayO3l9S+zKTj79M0DB0eUdtCB/LsEGniQ+9Mp # 8yudMcZuQwdig+YC29j98roJss+HL7xryTqGHBmQfvBe00krPbD+e6Q7cldUglY/ # 2FgqhUXXOBV1OpItew+zHhCKYdyyK9DqIsGHb3bOX2zn0urVB+hkVeY4K2dWxLFu # dqRwq5hNQ3uFV1iffJjN9TKjItz80mu/zNrm0vFH5sTKLVfwG8Xm+PagB/P5hLoC # pw53F8pLzDt0sAYLiH8VjK3LhGMLr7nuCtGC7zLWPqPYpAE3gyShxbI+efpagoEw # ErllEtXnI5uO0f4iWVwI8tMVlSFqJkDTIza29BjgUMxkmZ6LUpQOcZhnvV986O92 # Q954hsCfHdMft0oFUi6afcXLBPFppYJ6cBRYFgCxtEVrNe0k4uVYaSiiJ7+PdKlF # WibsdkFtRZVcIqb56khAc0+gIrbuNZDJquNtLPeJX7hdWDkWBKDcToV69VGkJ1BA # 5Ju26JpiOVlT8XHH92kv00bzyWwc1KFiWwHT7hmO5sBB2Vw= # SIG # End signature block |