Outputs/output-html.ps1
using module "..\MCCA.psm1" class html : MCCAOutput { $OutputDirectory = $null $DisplayReport = $True html() { $this.Name = "HTML" } RunOutput($Checks, $Collection) { <# OUTPUT GENERATION / Header #> # Obtain the tenant domain and date for the report $TenantDomain = ($Collection["AcceptedDomains"] | Where-Object { $_.InitialDomain -eq $True }).DomainName $ReportDate = "$(Get-Date -format 'dd-MMM-yyyy HH:mm') $($(Get-TimeZone).Id)" # Obtain the Remediation Report File name if ($null -eq $this.OutputDirectory) { $OutputDir = $this.DefaultOutputDirectory } else { $OutputDir = $this.OutputDirectory } $RemediationReportFileName = "$OutputDir\MCCA-$(Get-Date -Format 'yyyyMMddHHmm')-Remediation.html" # Summary $RecommendationCount = $($Checks | Where-Object { $_.Result -eq "Fail" }).Count $OKCount = $($Checks | Where-Object { $_.Result -eq "Pass" }).Count $InfoCount = $($Checks | Where-Object { $_.Result -eq "Recommendation" }).Count #> # Misc $ReportTitle = "Microsoft Compliance Configuration Analyzer" # Area icons $AreaIcon = @{} $AreaIcon["Default"] = "fas fa-user-cog" $AreaIcon["Data Loss Prevention"] = "fas fa-scroll" # Output start if ($null -ne $this.VersionCheck.Version) { $version = $($this.VersionCheck.Version.ToString()) } else { $Version = '' } $output = "<!doctype html> <html lang='en'> <head> <!-- Required meta tags --> <meta charset='utf-8'> <meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'> <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css' crossorigin='anonymous'> <link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css' integrity='sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T' crossorigin='anonymous'> <script src='https://code.jquery.com/jquery-3.3.1.slim.min.js' integrity='sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo' crossorigin='anonymous'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js' integrity='sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1' crossorigin='anonymous'></script> <script src='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js' integrity='sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM' crossorigin='anonymous'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.js'></script> <style> .navbar-custom { background-color: #005494; color: white; padding-bottom: 10px; } /* Modify brand and text color */ .navbar-custom .navbar-brand, .navbar-custom .navbar-text { color: white; padding-top: 70px; padding-bottom: 10px; } .card-header { background-color: #0078D4;; color: white; } .table-borderless td, .table-borderless th { border: 0; padding:5px; } .bd-callout { padding: 1.25rem; margin-top: 1.25rem; margin-bottom: 1.25rem; border: 1px solid #eee; border-left-width: .25rem; border-radius: .25rem } .bd-callout h4 { margin-top: 0; margin-bottom: .25rem } .bd-callout p:last-child { margin-bottom: 0 } .bd-callout code { border-radius: .25rem } .bd-callout+.bd-callout { margin-top: -.25rem } .bd-callout-info { border-left-color: #5bc0de } .bd-callout-info h4 { color: #5bc0de } .bd-callout-warning { border-left-color: #f0ad4e } .bd-callout-warning h4 { color: #f0ad4e } .bd-callout-danger { border-left-color: #d9534f } .bd-callout-danger h4 { color: #d9534f } .bd-callout-success { border-left-color: #00bd19 } .app-footer{ background-color: #005494; color: white; padding-top:2px; padding-bottom :2px; } </style> <title>$($ReportTitle)</title> </head> <body class='app bg-light'> <nav class='navbar navbar-custom' > <div class='container-fluid'> <div class='col-sm' style='text-align:left'> <div class='row'><div><i class='fas fa-binoculars'></i></div><div class='ml-3'><strong>Microsoft Compliance Configuration Analyzer (MCCA)</strong></div></div> </div> <div class='col-sm' style='text-align:right'> <button type='button' class='btn btn-primary' onclick='javascript:window.print();'>Print</button> <BR/> </div> </div> </nav> <div class='app-body p-3'> <main class='main'> <!-- Main content here --> <div class='container' style='padding-top:10px;'></div> <div class='card'> <div class='card-body'> <h2 class='card-title'>$($ReportTitle)</h2> <strong>Version $version </strong> <p> MCCA assesses your compliance posture, highlights risks and recommends remediation steps to ensure compliance with essential data protection and regulatory standards.</p>" If ($this.VersionCheck.Preview -eq $True) { $Output += " <div class='alert alert-warning pt-2' role='alert'> You are running a preview version of MCCA! Preview versions may contain errors which could result in an incorrect report. Verify the results and any configuration before deploying changes. </div> " } $Output += "<table><tr><td> <strong>Date</strong> </td> <td><strong>: $($ReportDate)</strong> </td> </tr> " if ($Collection["GetOrganisationConfig"] -ne "Error") { $OrganisationName = $Collection["GetOrganisationConfig"].DisplayName if (($null -ne $($OrganisationName)) -and ($($OrganisationName) -ne "")) { $output += " <tr><td><strong>Organization </strong> </td> <td><strong>: $($OrganisationName)</strong> </td></tr> " } } if (($null -ne $($TenantDomain)) -and ($($TenantDomain) -ne "")) { $output += " <tr><td><strong>Tenant </strong> </td> <td><strong>: $($TenantDomain)</strong> </td></tr> " } $TenantGeoLocations = $Collection["GetOrganisationRegion"] | Where-Object { $_ -ne "INTL" } if ($TenantGeoLocations -ne "Error") { $RegionString = "" $NumberToRegionMapping = Get-NumberRegionMappingHashTable foreach ($Region in $TenantGeoLocations) { foreach ($Numbers in $($NumberToRegionMapping.Keys)) { if ($($NumberToRegionMapping[$Numbers].Code) -eq $Region) { if ($RegionString -eq "") { $RegionString += "$($NumberToRegionMapping[$Numbers].Description)" } else { $RegionString += ", $($NumberToRegionMapping[$Numbers].Description)" } } } } $output += " <tr><td><strong>Note </strong> </td> <td><strong>:</strong> The following report is customized for following geolocation(s): $RegionString</td></tr> " } else { $output += " <tr><td><strong>Note </strong> </td> <td><strong>:</strong> The following report is generalized on all geolocations</td></tr> " } $output += " </table>" <# OUTPUT GENERATION / Version Warning #> If ($this.VersionCheck.Updated -eq $False) { $Output += " <div class='alert alert-danger pt-2' role='alert'> MCCA is out of date. You're running version $($this.VersionCheck.Version) but version $($this.VersionCheck.GalleryVersion) is available! Run Update-Module MCCA to get the latest definitions! </div> " } $Output += "</div> </div>" <# OUTPUT GENERATION / Summary cards #> $Output += "<br/>" <# OUTPUT GENERATION / Summary #> $Output += " <div class='card m-3'> <a name='Solutionsummary'></a> <div class='card-header'> Solutions Summary </div> <div class='card-body'>" $Output += "<table class='table table-borderless'> <tr> <td width='20'><i class='fas fa-user-cog'></i> <td><strong>All Solutions</strong></td> <td align='right'> <span class='badge badge-secondary' style='padding:15px;text-align:center;width:40px;"; $output += "'>$($InfoCount)</span> <span class='badge badge-warning' style='padding:15px;text-align:center;width:40px;"; $output += "'>$($RecommendationCount)</span> <span class='badge badge-success' style='padding:15px;text-align:center;width:40px;"; $output += "'>$($OkCount)</span> </td> </tr> " ForEach ($ParentArea in ($Checks | Where-Object { $_.Completed -eq $true } | Group-Object ParentArea)) { $Icon = $AreaIcon["Default"] If ($Null -eq $Icon) { $Icon = $AreaIcon["Default"] } $Output += " <tr > <td width='20'><i class='$Icon'></i> <td><strong>$($ParentArea.Name)</strong></td> </tr> " ForEach ($Area in ($Checks | Where-Object { $_.Completed -eq $true } | Where-Object { $_.ParentArea -eq $ParentArea.Name } | Group-Object Area)) { $Pass = @($Area.Group | Where-Object { $_.Result -eq "Pass" }).Count $Fail = @($Area.Group | Where-Object { $_.Result -eq "Fail" }).Count $Info = @($Area.Group | Where-Object { $_.Result -eq "Recommendation" }).Count $Output += " <tr> <td width='20'> <td style='vertical-align:middle;'> <i class='fa fa-cog'></i> <a href='`#$($Area.Name)'>$($Area.Name)</a></td> <td align='right' style='vertical-align:middle;'> <span class='badge badge-secondary' style='padding:10px;text-align:center;width:30px;"; $output += "'>$($Info)</span> <span class='badge badge-warning' style='padding:10px;text-align:center;width:30px;"; $output += "'>$($Fail)</span> <span class='badge badge-success' style='padding:10px;text-align:center;width:30px;"; $output += "'>$($Pass)</span> </td> </tr> " } } $Output += " <tr><td colspan='3' style='text-align:right'> <span class='badge badge-secondary'style='padding:5px;text-align:center'> </span> Recommendation <span class='badge badge-warning'style='padding:5px;text-align:center'> </span> Improvement <span class='badge badge-success' style='padding:5px;text-align:center'> </span> OK </td></tr></table>" $Output += " </div> </div> " <# OUTPUT GENERATION / Zones #> [bool] $UncompletedChecks = $False [string] $UncompletedChecksName = "" ForEach ($Area in ($Checks | Where-Object { $_.Completed -eq $False } | Group-Object Area)) { if ($UncompletedChecks -eq $False) { $UncompletedChecks = $True } # Each check if ($UncompletedChecksName -eq "") { $UncompletedChecksName += "Note: There was an issue in fetching $($Area.Name)" } else { $UncompletedChecksName += ", $($Area.Name)" } } if ($UncompletedChecks -eq $True) { $UncompletedChecksName += " information. Please try running the tool again after some time." $Output += " <div style='color:red;'> $UncompletedChecksName </div>" } ForEach ($Area in ($Checks | Where-Object { $_.Completed -eq $True } | Group-Object Area)) { # Write the top of the card $CollapseId = $($Area.Name).Replace(" " , "_") $Output += "<a name='$($Area.Name)'></a> <div class='card m-3'> <div class='card-header'> <div class=""row""> <div class='col-sm' style='text-align:left; margin-top:auto; margin-bottom:auto;'><a>$($Area.Name)</a></div> <div class='col-sm' style='text-align:right; padding-right:10px;'> <span id='more_$($CollapseId)' data-toggle='collapse' data-target='#$($CollapseId)_body'> <i class='fas fa-chevron-down' > </i> </span> </div> </div> </div> <div class='card-body collapse show' id='$($CollapseId)_body'>" # Each check [int] $count = 1 ForEach ($Check in ($Area.Group | Sort-Object Result -Descending)) { $RemediationActionsExist = $false $CheckCollapseId = $($CollapseId) + $count.ToString() If ($Check.Result -eq "Pass") { $CalloutType = "bd-callout-success" $BadgeType = "badge-success" $BadgeName = "OK" $Icon = "fas fa-thumbs-up" $IconColor = "green" $Title = $Check.PassText } ElseIf ($Check.Result -eq "Recommendation") { $CalloutType = "bd-callout-secondary" $BadgeType = "badge-secondary" $BadgeName = "Recommendation" $Icon = "fas fa-thumbs-up" $IconColor = "gray" $Title = $Check.FailRecommendation } Else { $CalloutType = "bd-callout-warning" $BadgeType = "badge-warning" $BadgeName = "Improvement" $Icon = "fas fa-thumbs-down" $IconColor = "#e5ad06" $Title = $Check.FailRecommendation } $Output += " <div class='row border-bottom' style='padding:5px; vertical-align:middle;'> <div class='col-sm-10' style='text-align:left; margin-top:auto; margin-bottom:auto;'><h6>$($Check.Name)</h6></div> <div class='col' style='text-align:right;padding-right:10px;'> <h6> <span class='badge $($BadgeType)'>$($BadgeName)</span> <i class='fas fa-chevron-down' data-toggle='collapse' data-target='#$($CheckCollapseId)'></i> </h6> </div> </div> " $Output += " <div class='row collapse' id='$($CheckCollapseId)'> <div class='bd-callout $($CalloutType) b-t-1 b-r-1 b-b-1 p-3' > <div class='container-fluid'> <div class='row'> <div><i class='$($Icon)' color='$($IconColor)'></i></div> <div class='col-8'><h6>$($Title)</h6></div> </div>" if ($Check.Importance) { $Output += " <div class='row p-3'> <div><p>$($Check.Importance)</p></div> </div>" } If ($Check.ExpandResults -eq $True) { # We should expand the results by showing a table of Config Data and Items $Output += " <div class='row pl-2 pt-3'>" if ($Check.Control -ne "Compliance Manager") { $Output += " <table class='table'> <thead class='border-bottom'> <tr>" If ($Check.CheckType -eq [CheckType]::ObjectPropertyValue) { # Object, property, value checks need three columns $Output += " <th align='center' text-align='center'>$($Check.ObjectType)</th> <th align='center' text-align='center'>$($Check.ItemName)</th> <th align='center' text-align='center'> $($Check.DataType)</th> <th align='center' text-align='center'>Status</th> " } Else { $Output += " <th align='center' text-align='center'>$($Check.ItemName)</th> <th align='center' text-align='center'>$($Check.DataType)</th> <th align='center' text-align='center'>Status</th> " } $Output += " <th style='width:50px'></th> </tr> </thead> <tbody> " ForEach ($o in $Check.Config | Sort-Object Level -Descending) { $ActionRequired = $false if ($o.Level -ne [MCCAConfigLevel]::None -and $o.Level -ne [MCCAConfigLevel]::Recommendation) { $oicon = "fas fa-check-circle text-success" $LevelText = $o.Level.ToString() } ElseIf ($o.Level -eq [MCCAConfigLevel]::Recommendation) { $oicon = "fas fa-info-circle text-muted" $LevelText = $o.Level.ToString() } Else { $oicon = "fas fa-times-circle text-danger" $LevelText = "Improvement" $ActionRequired = $true } $Output += " <tr> " if ($($o.RemediationAction)) { $RemediationActionsExist = $true } If ($Check.CheckType -eq [CheckType]::ObjectPropertyValue) { # Object, property, value checks need three columns $Output += " <td>$($o.Object)</td> <td style='word-wrap:break-word;' width = '35%'>$($o.ConfigItem)</td> <td style='word-wrap:break-word;' width = '30%'>$($o.ConfigData)</td> " } Else { $Output += " <td>$($o.ConfigItem)</td> <td style='word-wrap:break-word;' width = '35%'>$($o.ConfigData)</td> " } $Output += " <td style='text-align:left'> <div class='row badge badge-pill badge-light'>" if ($o.Level -eq [MCCAConfigLevel]::Informational) { $Output += "<span style='vertical-align: left;'>$($LevelText)</span><br/></div>" } else { $Output += "<span class='$($oicon)' style='vertical-align: left;'></span> <span style='vertical-align: left;'>$($LevelText)</span><br/></div>" } if ($ActionRequired -eq $true -and $($o.RemediationAction)) { $Output += " <span style='vertical-align: left;'><small><center>Remediation Available</center></small></span> " } $Output += " </td> </tr> " # Recommendation segment #if($o.Level -eq [MCCAConfigLevel]::Recommendation) #{ if (($null -ne $($o.InfoText)) -and ($($o.InfoText) -ne "" ) ) { $Output += " <tr>" If ($Check.CheckType -eq [CheckType]::ObjectPropertyValue) { $Output += "<td colspan='4' style='border: 0;'>" } else { $Output += "<td colspan='3' style='border: 0;'>" } $Output += " <div class='alert alert-light' role='alert' style='text-align: left;'> <span class='fas fa-info-circle text-muted' style='vertical-align: left; padding-right:5px'></span> <span style='vertical-align: middle;'>$($o.InfoText)</span> </div> " $Output += "</td></tr> " } } #} $Output += " </tbody> </table>" } # If any links exist If ($Check.Links) { $Output += " <table class='table'> <tr>" $LinksInfo = $Check.Links [int] $CountOfLinks = $LinksInfo.Keys.Count [int] $itr = 0 $LinksNameValuePair = $LinksInfo.GetEnumerator() | Sort-Object -Property Name while ($itr -lt $CountOfLinks) { $Output += " <td style='padding-top:20px;'><i class='fas fa-external-link-square-alt'></i> <a href='$($LinksNameValuePair.Value[$itr])' target=""blank"">$($LinksNameValuePair.Name[$itr])</a></td> " $itr = $itr + 1 } if ($RemediationActionsExist -eq $true) { $Output += " <td ><a class='btn btn-primary' href='$($RemediationReportFileName)' target='_blank' role='button'>Remediation Script</a></td> " } $Output += " </tr> </table> " $Output += " </table> " } $Output += " </div>" } $Output += " </div> </div> </div> " $count += 1 } # End the card $Output += " <div class='col-sm' style='text-align:right; padding-right:10px;'> <a href='#Solutionsummary'>Go to Solutions Summary</a></div> </div> </div>" } <# OUTPUT GENERATION / Footer #> $Output += " </main> <center>Bugs? Issues? Suggestions? <a href='https://github.com/OfficeDev/MCCA'>GitHub</center> </div> <footer class='app-footer'> <p><center><i> Disclaimer: Recommendations from (MCCA) should not be interpreted as a guarantee of compliance. It is up to you to evaluate and validate the effectiveness of customer controls per your regulatory environment. <br> </i></center> </p></footer> </body> </html>" # Write to file $Tenant = $(($Collection["AcceptedDomains"] | Where-Object { $_.InitialDomain -eq $True }).DomainName -split '\.')[0] $ReportFileName = "MCCA-$($tenant)-$(Get-Date -Format 'yyyyMMddHHmm').html" $OutputFile = "$OutputDir\$ReportFileName" $Output | Out-File -FilePath $OutputFile If ($this.DisplayReport) { Invoke-Expression $OutputFile } $this.Completed = $True $this.Result = $OutputFile } } # SIG # Begin signature block # MIIhnwYJKoZIhvcNAQcCoIIhkDCCIYwCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAqpkjodXya3ML6 # pVkRysK+AHPRrvFfyIkgS7wBogv34qCCC4QwggUAMIID6KADAgECAhMzAAAEU+We # zhfpk+4QAAAAAARTMA0GCSqGSIb3DQEBCwUAMHkxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29mdCBUZXN0aW5nIFBD # QSAyMDEwMB4XDTIwMTIxNTE5NDMyN1oXDTIxMTIwMjE5NDMyN1owfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdQ29kZSBTaWdu # IFRlc3QgKERPIE5PVCBUUlVTVCkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK # AoIBAQDIbLqmXHPCGqCpfikwr9Gwu7mmwKaRk2l2c7HiFdxA4N/5QBm3ZfoonyX/ # oaX3WbsvBD3MoCMZJCYGVJeCkW0Iy0ahCtcxjmCmy9T7g0Du1vR29P+TTghXQ4ZP # fVj+XDxo82IsqpD7uxaa/VujruYpxvYfwRZB11kf0SpaRLae1TvONYQZ/eNifGSx # zUridwIkDPogu1vzsehp1O+SMhv3foM6Rz95ajbWOJMxgooE+LoAapjHe8jDciok # 4jPC/5F5HGbf50i6Wj/QLN3VKLQFsSBzBC1RFqUITmcRP4ngQeDvLpvTluC8KFmy # IlZunmBqGx2ynTmebwVysIa+qV/NAgMBAAGjggF8MIIBeDATBgNVHSUEDDAKBggr # BgEFBQcDAzAdBgNVHQ4EFgQUrvqOOBCgPTy+cAoXZUhGw1P2yF4wUAYDVR0RBEkw # R6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNv # MRYwFAYDVQQFEw0yMzAwNzIrNDYzMDE4MB8GA1UdIwQYMBaAFN3WR4sjFC/YOGhC # oz5tw/CQ9yzQMFkGA1UdHwRSMFAwTqBMoEqGSGh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRlc3RpbmclMjBQQ0ElMjAyMDEw # LmNybDBmBggrBgEFBQcBAQRaMFgwVgYIKwYBBQUHMAKGSmh0dHA6Ly93d3cubWlj # cm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGVzdGluZyUyMFBD # QSUyMDIwMTAuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBACnT # 9Iwyq9Jk/Ee6QBrLTjw5+p0XjjxX7Oocz1R/iNdfx7iJtSf4VHWcDGXr92BPQLgl # MOdq6PCrIRstWMg1aBQ4eH9Q6VfiWZq3FyaQNpDG4g/+Z6Zo5A6LgbtEnZB5tboP # ZsE4o0wDlIXX5pGCsCTIiVMtJqbCZPn5hLG5V7wMlLae9A4xOW+JyBy8vA/FpE+A # QQoHSJ4LrC22bwpn2+cQRF5SlFRIqZVx+wclji96Nerfosz2ZPLfydHvs8jH65dA # 2WFAMvN8/KxdX7fp98Bzk+vhCPYc4/CKyPdscD7yJvOxveEAzDiLyyWrnbFU9qP7 # aI/JTxrVA5IGS7wIJKwwggZ8MIIEZKADAgECAgphEYRvAAAAAAADMA0GCSqGSIb3 # DQEBCwUAMIGQMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTow # OAYDVQQDEzFNaWNyb3NvZnQgVGVzdGluZyBSb290IENlcnRpZmljYXRlIEF1dGhv # cml0eSAyMDEwMB4XDTEwMDcwMTIxMjMwMVoXDTI1MDcwMTIxMzMwMVoweTELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9z # b2Z0IFRlc3RpbmcgUENBIDIwMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK # AoIBAQDBvSHVS2YGAJIwORjKy3NCWbHvmyeo4OhVvSmw+SQfOtHow1mJ7ZG2wegz # Y/ZaZBniLnwMkIAFOL8cproNai/vJ5er3vbvUPOD59fDRTciPxi1wpYRto0Sg1mL # J1EGVnW5YGoTDtUmPy2WqgXMoYc/vk807wxMb8wE1KHmZ80KJzOf46+bb2h8vLQM # czSMWoH5h/tUHMVHbOqfV7RZ/c4ZqXd8h0KftXmUvMt2ktuWl6FfBCQ5/qGV4Z+G # 417ZXFbfQ5CfyRTq0fWgW6vzCATdKK8b4qouE6AK7dKZRCr1mUT7K6RP8bthwh0t # 9SUnAqh475M59F51ge7S4HYMWyPvAgMBAAGjggHsMIIB6DAQBgkrBgEEAYI3FQEE # AwIBADAdBgNVHQ4EFgQU3dZHiyMUL9g4aEKjPm3D8JD3LNAwGQYJKwYBBAGCNxQC # BAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYD # VR0jBBgwFoAUowEEfjCIM+u5MZzK64V2Z/xltNEwWQYDVR0fBFIwUDBOoEygSoZI # aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGVz # Um9vQ2VyQXV0XzIwMTAtMDYtMTcuY3JsMF0GCCsGAQUFBwEBBFEwTzBNBggrBgEF # BQcwAoZBaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUZXNS # b29DZXJBdXRfMjAxMC0wNi0xNy5jcnQwgaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYB # BAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # UEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBn # AGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqG # SIb3DQEBCwUAA4ICAQBAYQU+N90ze1LCSGuA92ADFrbJLol+vdlYHGPT9ZLS9loE # DQjuh7/rmDQ6ZXxQ5MgbKVB5VXsYOZG1QSbzF3+YlWd8TN1y5B21BM3DSPb6r+3b # rl50kW2t1JqACtiLbZnmhmh5hkdJi8HYUfLQ7xKcP0g1CIJP9CyKil7UJv/HnMXK # igTGiBaHjfVtVwG5k8roymrEirpBDcOMVB0OZiTXxYIHDbM4v7LItZYIISdPs6+L # wxwzwdroMdpj42+3dWQBumpRGQAgqJ9i5UiBQtUM+9vLpKIRnujnWfQxbaIuIt2H # RLFpHUYKGOXRlf148o+71dX3YWap88+ocaxkM8rkavgDNkcWSe9Dpoq8a3tS2P9B # pxewDV+iSzF0JRo9UOZeciaSQDZvrkQskxJjtdO725L6E5Fu1Ti+lGl6exRCnhPb # ooxCqHEGLRdiwXkrmLp+huTGAK8zmfEt0d1JFrrDdu5kqoG3OVT2dN4JVFNpOFvC # U/LNiVDCyCIcG0cSRVtDjyNckMhu1PcPtberjr1mcL8RkTzvonoH4pIvQk1k4IOL # pdxslOj2oigApZjqCBJA3mIEZHlnwRuglg4Er74nSmL6953C0r1Vwl7T0vXnQO8i # zb+incAb1r6Y+45N5aVXww+PqHJBRjvhjyBKG+1aDLVM3ixjV9P6OZkOvp4uozGC # FXEwghVtAgEBMIGQMHkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xIzAhBgNVBAMTGk1pY3Jvc29mdCBUZXN0aW5nIFBDQSAyMDEwAhMzAAAEU+We # zhfpk+4QAAAAAARTMA0GCWCGSAFlAwQCAQUAoIGwMBkGCSqGSIb3DQEJAzEMBgor # BgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3 # DQEJBDEiBCBxjCCfwAo4b3P6tuodWT99JUXkY85+fcP+iVJ8BZzfDTBEBgorBgEE # AYI3AgEMMTYwNKAUgBIATQBpAGMAcgBvAHMAbwBmAHShHIAaaHR0cHM6Ly93d3cu # bWljcm9zb2Z0LmNvbSAwDQYJKoZIhvcNAQEBBQAEggEAlO6rFc5JgStzQ1Wo2SnK # iAS0MF0/mkMnLHBtOTpyVmiWLXE1hlfa0am1hC/EGCNlWBGFCV1D4Hy51KFkKjIF # EYhlcqk+hlYjFCGkXpOTew3kvhtsd43oKUikvRSlXeL+EsYoII4Q3Yd2sA3xS9+C # thLQecqsakxzFAyeKm8eNsdoS6BuZpaxeXkDwvjIlAMfZLOrC5NtvENIxnjdDSov # Lr6So7hE46EnScrFvAwjDPQXrTkGeNUUL7gosKzF3Id45Cyxye7GF3U0KzD+jOr9 # j2NkYmJl3cebwEYzhsHeBJBb1iD6YwOVGfF34wqJcakqaD4Gq6LefEJkCvWf8VNQ # jqGCEv4wghL6BgorBgEEAYI3AwMBMYIS6jCCEuYGCSqGSIb3DQEHAqCCEtcwghLT # AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIB # QAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCDx6n3V+sdQBPffv9eV # YXynAQSxhPg+4dPh3entkIpVkgIGYNSgVhrtGBMyMDIxMDcwOTA2MDk0NS40MDNa # MASAAgH0oIHYpIHVMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0 # ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjhENDEtNEJGNy1CM0I3MSUwIwYD # VQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIOTTCCBPkwggPhoAMC # AQICEzMAAAE6jY0x93dJScIAAAAAATowDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjAxMDE1MTcyODIyWhcNMjIwMTEyMTcy # ODIyWjCB0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsG # A1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYD # VQQLEx1UaGFsZXMgVFNTIEVTTjo4RDQxLTRCRjctQjNCNzElMCMGA1UEAxMcTWlj # cm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEP # ADCCAQoCggEBAM5fJOdfD5c/CUyF2J/zvTmpKnFqnSfGVyYQJLPYciwfPgDVu2Z4 # G9be4sO05oHqKDsDJ24QkEB9eFMFnfIUBVnsSqlaXCBZ2N29efj2JoFXkOFyn1id # zzzI04l7u93qVx4/V1+5oUtiFasBLwzrnTiN8kC/A/DjhtuG/tdMwwxMjecL2eQN # VnL5dnkIQhutRnhzWl71zpaE0G5VRWzFjphr4h74EZUYUY4DZrr9Sdsun0BbYhMN # KXVygkBuvMUJQYXLuC5/m2C+B6Hk9pq7ZKRxMg2fn66/imv81Az9wbHB5CnZDRjj # g37yXVh2ldFs69cJz7lILTm35wTtKEoyKQUCAwEAAaOCARswggEXMB0GA1UdDgQW # BBQUVqCfFl8Sa6bJbxx1rK0JhUXzyzAfBgNVHSMEGDAWgBTVYzpcijGQ80N7fEYb # xTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5j # b20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmww # WgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNV # HRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IB # AQBeN+Q+pAEto3gCfARtSk5uQM9I6W3Y6akrzC7e3zla2gBB5XYJNOASnE5oc420 # 17I8IAjDAkvo1+E6KotHJ83EqA9i6YWQPfA13h+pUR+6kHV2x4MdP726tGMlZJbU # kzL9Y88yO+WeXYab3OFMJ+BW+ggmhdv/q+0a9I/tgxgsJfGlqr0Ks4Qif6O3DaGF # HyeFkgh7NTrI4DJlk5oJbjyMbd5FfIi2ZdiGYMq+XDTojYk62hQ6u4cSNeqA7KFt # BECglfOJ1dcFklntUogCiMK+QbamMCfoZaHD8OanoVmwYky57XC68CnQG8LYRa9Q # x390WMBaA88jbSkgf0ybAdmzMIIGcTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg # VGltZS1TdGFtcCBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC # ggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5m # K1vwFVMnBDEfQRsalR3OCROOfGEwWbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcm # gqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5 # hoC732H8RsEnHSRnEnIaIYqvS2SJUGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/Vm # wAOWRH7v0Ev9buWayrGo8noqCjHw2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQB # wSAJk3jN/LzAyURdXhacAQVPIk0CAwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQD # AgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIE # DB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNV # HSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVo # dHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29D # ZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAC # hj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1 # dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMw # gYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9j # cy9DUFMvZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8A # UABvAGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQEL # BQADggIBAAfmiFEN4sbgmD+BcQM9naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJ # at/15/B4vceoniXj+bzta1RXCCtRgkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1 # mCRWS3TvQhDIr79/xn/yN31aPxzymXlKkVIArzgPF/UveYFl2am1a+THzvbKegBv # SzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/ # amJ/3cVKC5Em4jnsGUpxY517IW3DnKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqW # hqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua # 2A5HmoDF0M2n0O99g/DhO3EJ3110mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46Pio # SKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqH # czsI5pgt6o3gMy4SKfXAL1QnIffIrE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw # 07t0MkvfY3v1mYovG8chr1m1rtxEPJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P # 6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+NR4Iuto229Nfj950iEkSoYIC1zCCAkAC # AQEwggEAoYHYpIHVMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0 # ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjhENDEtNEJGNy1CM0I3MSUwIwYD # VQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoD # FQAHJZHZ9Y9YF4Hcr2I+NQfK5DWeCKCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0 # YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA5JI8CDAiGA8yMDIxMDcwOTEx # MDc1MloYDzIwMjEwNzEwMTEwNzUyWjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDk # kjwIAgEAMAoCAQACAhXwAgH/MAcCAQACAhFKMAoCBQDkk42IAgEAMDYGCisGAQQB # hFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAw # DQYJKoZIhvcNAQEFBQADgYEAnS8dvxwVIXyZa4zOGtc1jYNX4AadkB9Y7Ppnod4Q # uvWT/KvnOj1wAhD1/QJJmGiC0bxTUPW3IE/5uRXRe76A3D95XOfm+qT7WqDaVCge # D84zWLz6sFqZz6Yj1Do3t/Ov/JR4FAabroNi60XKP75Gau9J7tYXT8H9N7EJIfq7 # /+IxggMNMIIDCQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT # MwAAATqNjTH3d0lJwgAAAAABOjANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcN # AQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCDd8yxvabiZvZlapCsc # G4bQ5shWPr1rtn10FImlxbz3iTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0E # IJ+v0IQHqSxf+wXbL37vBjk/ooS/XOHIKOTX9WlDfLRtMIGYMIGApH4wfDELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z # b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAE6jY0x93dJScIAAAAAATowIgQg # O20H+OgjRggk2gx4VjhNe+DQbx+mhtJPzVJ0TymE1tEwDQYJKoZIhvcNAQELBQAE # ggEAq9PtEHykeNRW2uvZ1vEs+m+uEf3qWrEBOuMUzLMKgxcC0DjtvYyKaQ87Q+kY # zqK4elBijL+jcgz5RO1gzyRoxuP2RzE4UWbcE9cALV0+mg2bAm/LTmIClykBE25Q # iUsqONGlLhK8JMEzHzmC0we8wgvxkKzVCOrov3E3yr8n7OJM5h4a+S1QYog8RSwk # 4n2fPFEnIdptJVlrSabzWe11Ot8sa1fuOowGLwKHBIkMLo+kB0qAreZliP5jbimf # HMOWVCU4IFdiB9gjSuMbMOHfN96dfMjru8dscGDJmfCST5kIyvkmCijvq/bzbHjO # cobwJWtzXbtP/0Bm2IMSmRzagA== # SIG # End signature block |