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" .PARAMETER NamePrefix Set prefix for the name of the ARM template. Default is none .PARAMETER Severity Overwrite the severity of the provided YAML file with a custom one. Default is emtpy .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", [Parameter()] [string]$NamePrefix, [ValidateSet("Informational", "Low", "Medium", "High")] [Parameter()] [string]$Severity ) 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" } # Generate new guid if id is not a valid guid if ($analyticRule.id -notmatch "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") { Write-Warning "Error reading current Id. Generating new Id." $analyticRule.id = (New-Guid).Guid } # Add prefix to name if specified if ($NamePrefix) { $analyticRule.name = $NamePrefix + $analyticRule.name } # Overwrite severity with custom severity if (-not [string]::IsNullOrWhiteSpace($Severity) ) { $analyticRule.severity = $Severity } 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) $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]) } } # Convert hashtable to JSON $JSON = $ARMTemplate | 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) # Sort all property keys in ARM template and convert to JSON string object $Result = Invoke-SortJSONObject -object ( $Result | ConvertFrom-Json ) $Result = $Result | 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 # MIIn4QYJKoZIhvcNAQcCoIIn0jCCJ84CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUIPbRSVjwvoxLrEs+VAsBBAbJ # 4/yggiEJMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # 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+lB3nYxs6hlZ4TjCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJ # KoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2 # IFRpbWVTdGFtcGluZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTla # MEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UE # AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4IC # DwAwggIKAoICAQCjU0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIV # WMGpkxGnzaqyat0QKYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9Yr # IBzBl5S0pVCB8s/LB6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5x # XsQGmjzwxS55DxtmUuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4 # KTlr4HhZl+NEK0rVlc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUd # vJscsrdf3/Dudn0xmWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZ # BzcBkQ8ctVHNqkxmg4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02ke # fGRNnQ/fztFejKqrUBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1 # x4Nk1nXNjxJ2VqUk+tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhv # ltXhEBP+YUcKjP7wtsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPs # CvERLmTgyyIryvEoEyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQAB # o4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/ # BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB # MB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T # 5+/N0GSh1VapZTGj3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0 # YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGlt # ZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1P # ijxonNgl/8ss5M3qXSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09 # SI64a7p8Xb3CYTdoSXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5 # j9smViuw86e9NwzYmHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXT # UOREEr4gDZ6pRND45Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08z # jdSNd311RaGlWCZqA0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9N # UvPJYCHEVkft2hFLjDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg2 # 1Llyln6XeThIX8rC3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44Owde # OVj0fHMxVaCAEcsUDH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZr # uhf9xHdsFWyuq69zOuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7 # KP845VJa1qwXIiNO9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywG # Ru9BHvDwX+Db2a2QgESvgBBBijCCB0gwggUwoAMCAQICEAqCMJBHqzYjysMfsj2s # 65owDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMTAeFw0yMjA1MTgwMDAwMDBaFw0y # NTA1MTcyMzU5NTlaME0xCzAJBgNVBAYTAkRFMRAwDgYDVQQHEwdIYW1idXJnMRUw # EwYDVQQKEwxGYWJpYW4gQmFkZXIxFTATBgNVBAMTDEZhYmlhbiBCYWRlcjCCAiIw # DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMEjxUm2ziBQmPNov//zacCKh7+x # iQg6o7vgiYO0wKIw1dgg0s+9qjdj2I1eWp34f43iVRrQOwawnilpC81R/T+KVudo # 7hIcEXu327+7Pj5KU4SwXcEF4fyRxF6SL/Yy5Dhh92Ma8aCEuW3Z8yn7slK/Kify # flOmvUoJDpBTTOqRhxRmNk7EQPMDI03aYWBkyn+fOYR+Jg+/xqtXW+9iEA6aKCl2 # D2aG0PiwLi7Rf0YE1R9WLYP+tZndvKVd+UMmbowHHKGCY4A1s3nMezu3HWLsAJbD # 34ei/mBVTsfS8rmlRUIOsOt3tQzWBILiJj5erVrQDDh5oF8XeGuMPx9Lb1JKozh+ # SuHVOAlpnCEp5HYdrHRzcMfII32Ht08KVsZRTlNRxGnuhwDRerVbSMlYUEcEuydQ # zSTtSiDhmQwYSoYj5Ja9e1jJ0eXmBAjnXGnJBw0/cmSd0B5E9BjGtyp2UkeekYTm # 8+zR/JZSUUmf9sswzjwIYhTqyo2T2GC/EeduPGZMTsW0yVqU4Vud3SjzOm/TaLao # iVua7uHjlatMo0jHbTy7bUALuhxLTSiNfdAIr+Vzz0GDMiNTx1S2ObFe6Zt+oSKW # ORFttx5ybN9NuAIheORTdZsR5VJJu3PgmLDQG58kSZSHFMhddtWpBTVbhkFMGyEJ # 7ZkKGv5MXf76WNqRAgMBAAGjggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG # +/5hewiIZfROQjAdBgNVHQ4EFgQU9QqUwn2Wwx5W7kpA5piphcoCDjkwDgYDVR0P # AQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BR # oE+GTWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENv # ZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8v # Y3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JT # QTQwOTZTSEEzODQyMDIxQ0ExLmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcG # CCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUF # BwEBBIGHMIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20w # XAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwG # A1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAAnByFUoYIEa6FQ8Yvkg3yTq # lTNmfdk9uWL/MclhjFJteGxhDgYJ3x4iFCZivQaZtJP4Z2BKVeSJZfP0X9tJfsr5 # cE49ZuLLdka+HPOEUhpq1vN5pGMTIYOWC7S4mXWnzQnJLvftunYGed+yu2A4RriH # loO9PFXIQJwxG/ApYqljGC8OieL2oEPdROXpj6auxYQ7NqjTBJZ641lC40JGERpQ # 38NtgHKbLQqxAZHPtfFmZegQ9jsNQ9cITFej9eO9mYE3KOj3KfASoa6qKFF6tgg8 # GFyW/4hTcEZ7uwrO/LvnZS7vrFzcbGxrj0/SIPuTrwtRYhzHjmuGkvB2UqU27uMP # HHJS/RHV6pYFVxQtj5Q4q/9lvVY/bOrYkqd4XZR+3SDuRREIfCS63TxcCl2fHa4L # z9ujH9dYwr8pDPkEJvY4Qf1YQJ8IrJIFKHSJH6MdEYybQkJDU9aF6iVRK8AapfyF # UFDUAke0O3wPFNo1PBQU5GK8lEAEGiBKsWr93PhqjPeE4dwuRb6zruAlNvPx2bk4 # 2WQgT+7NhFv/+G0VEEp1weJmrM1Efv/Efm1/vsnx/zrtR0C+WhqPati9+qGlRY2j # NvNsNacxQBFH9I4KVJAXiThVHhb4q2FsqnsfqCsMvFc4LPgSnexTkoS2u8AmotX4 # 32L6TuxsW6XWCampzTJgMYIGQjCCBj4CAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUG # A1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQg # RzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAKgjCQR6s2 # I8rDH7I9rOuaMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAA # MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgor # BgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBQpzsym5ylacl0ghch9mFMZevhxnTAN # BgkqhkiG9w0BAQEFAASCAgACR73+g849uEpzx/tO7qvtOfSieWf1lldlNWJGCHLJ # yZxwY8DTfo/oJlhXr8XZPQwHgiQ+vxUpvHHOXVNeTm1QVxIENN/lW47j8hlbSJgE # Oh2G0rL0kH+hBp+9VQX6VHpL15haiz2IxsAmFzl2JQgNaLL1lwPs8yjJKmXusHL5 # INgjSFwT0xZRz6Dj9sW/ta7PyqTf2oK09bohCjCMYwm9wKubXNMoFeU4ezjavXRC # LS7IctUSUXVGpqW4dycR/vtF5uSSDJuX2Z+Je62Z11qk5WYzf4BW4Sb55U8Pqbgs # ThRdV6CEd5bl8O44eCj798DGNBw0x7Sl8bwFlFxZXjUqiIgX2dBz2mlnQIey5O4m # maxP2txMIHRqINpk6IrIHDrgRdVbSAJ4p92kofFnHyInmUa1zRbDY7bjQ02POzAy # tRWgLNTBiun42ubgc1TRd7tymFdycr2JVhCsW4/aiDvQ9p6zqjU4Hp1BE3lh70CY # bUlc9JaAlThkvCNW4mc42yKTj6iPcgHY0ODy2CNlFUwbhfs2AY1VT7QlAPhAlVHD # cs9P2hdf3BegJyVD8c27CsGqg+BRKBfKJSG61pslzAgpIJ3iyMEN69BqK36BHWyP # Ews+rF1W+x36wOtb9ALxqFdkJ8GndulyFEJi1zwg08i2IAnPG+kFf/IQAgP5WqRy # fqGCAyAwggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1 # c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVEr/OUnQg5 # pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcN # AQcBMBwGCSqGSIb3DQEJBTEPFw0yMzExMDYxMDI3MTBaMC8GCSqGSIb3DQEJBDEi # BCDwoQvxPQz6OohWjoPXhWM6Usp2uOnZHUGXMN5qoJHlezANBgkqhkiG9w0BAQEF # AASCAgBg15JYbvY9gXEeczFGcGKskoKCIcKR50swajasDy+P/DkjPzUquTaLZVxB # x7RcASLgCN+wZxxBxK9NHOdiRGDSVFiKtiq2VqOb8k/YgdMMjUaFzH9ENgo57KH4 # OZXrMuNlNY+FeCQlXk9UzSb+wQkDSckJuNajXt/TogvW4qbr2cFoVbor2CwRmbdo # orREFdTeW9zI4T3l3OkHjiDRmIOGpebmaFRCW4SRVTw5yJYfo4sZzo00b0YAdWjC # bltF67ZnFupCcDoPacbIX9S77iiSXSFr3dZUnoK7vH3erC1qVGN++r/uMUikmwzr # fDkkAPE2WZ/ACvmCgI++/Qcxe0LSUfaHxysjWwjVYgZwz8PyThUFHEHLvVftw7Um # 4iiagDXFnzWoDa0+i1i3EgmIRlXerTN1/9kckKUQr7C0cCH4t3CZItBuPZ7MEt2k # MfIc7zJe8N1MfrKBWIZHyr0QvbcmKPN3f63cfJVaL4lm2q9jz/bkY+3HyaE8ohKq # l2KK73ssCHkLA0ifAsCrxIRzbSrZKLRFJO2nPtdhVrWMW641chJTi21QxB2xQN+3 # zniY+tnnZB2KLxUD3tqaRoXuNsF9Dhz9tg3FETXkkKQHv04dreSQwaxBYDv1WVE5 # a5X8GR5HvMt0apDrZjdHTIspxjqojBh9P3fOgRc7vuvZqvUItQ== # SIG # End signature block |