<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Azure Local &#8211; Haikos Blog</title>
	<atom:link href="https://www.hertes.net/category/microsoft/azure/azure-local/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hertes.net</link>
	<description>Blog von Haiko Hertes zu allen Themen rund um Microsoft, Cloud und Datacenter</description>
	<lastBuildDate>Wed, 09 Sep 2026 13:16:45 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>
	<item>
		<title>Azure Local und CheckMK Agent &#8211; Problem und Lösung mit der MSI</title>
		<link>https://www.hertes.net/2026/09/azure-local-und-checkmk-problem-und-loesung/</link>
					<comments>https://www.hertes.net/2026/09/azure-local-und-checkmk-problem-und-loesung/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Wed, 09 Sep 2026 09:20:36 +0000</pubDate>
				<category><![CDATA[Arbeit]]></category>
		<category><![CDATA[Azure Local]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[checkMK]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[MSI]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=4474</guid>

					<description><![CDATA[Dieser Beitrag ist zuerst auf Deutsch verfügbar. Jump to the English version. Wichtig: Die Installation zusätzlicher Softwarekomponenten auf Azure Local kann den Zustand und Support der Umgebung gefährden. Dies muss vorher sorgsam abgewägt werden! Auf einem Azure-Local-Cluster ließ sich der Checkmk-Agent nicht per MSI installieren. Der Installer wurde als Administrator gestartet, die Datei war vorhanden und der Aufruf von msiexec sah korrekt aus – trotzdem erschien der Agent anschließend nicht als installierte Anwendung. Die Ursache war nicht Checkmk und auch kein beschädigtes MSI-Paket. Azure Local führte die Application-Control-Richtlinie im erzwungenen Modus aus. Dadurch wurde nicht vertrauenswürdiger Code blockiert. Gelöst wurde&#8230;]]></description>
										<content:encoded><![CDATA[<p><!-- Suggested WordPress post title: Checkmk-Agent auf Azure Local installieren: Wenn WDAC die MSI blockiert --></p>


<p class="wp-block-paragraph"><strong>Dieser Beitrag ist zuerst auf Deutsch verfügbar.</strong> <a href="#english-version">Jump to the English version</a>.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Wichtig:</strong> Die Installation zusätzlicher Softwarekomponenten auf Azure Local kann den Zustand und Support der Umgebung gefährden. Dies muss vorher sorgsam abgewägt werden!</p>
</blockquote>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-8f761849 wp-block-group-is-layout-flex">
<p class="wp-block-paragraph">Auf einem Azure-Local-Cluster ließ sich der Checkmk-Agent nicht per MSI installieren. Der Installer wurde als Administrator gestartet, die Datei war vorhanden und der Aufruf von <code>msiexec</code> sah korrekt aus – trotzdem erschien der Agent anschließend nicht als installierte Anwendung.</p>
</div>



<p class="wp-block-paragraph">Die Ursache war nicht Checkmk und auch kein beschädigtes MSI-Paket. Azure Local führte die Application-Control-Richtlinie im erzwungenen Modus aus. Dadurch wurde nicht vertrauenswürdiger Code blockiert. Gelöst wurde das Problem mit einer ergänzenden WDAC-Richtlinie für den Checkmk-Agenten. Die bestehende Azure-Local-Basisrichtlinie blieb dabei aktiv.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Wichtig:</strong> Die Befehle in diesem Beitrag verändern die Code-Integrity-Konfiguration eines Clusters. Sie sollten zuerst in einer Wartungsphase und mit einem getesteten Rückweg ausgeführt werden. Der Audit-Modus erlaubt Code, der im erzwungenen Modus blockiert würde.</p>
</blockquote>



<h2 class="wp-block-heading">Das Fehlerbild</h2>



<p class="wp-block-paragraph">Der unbeaufsichtigte Installationsaufruf war grundsätzlich korrekt:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>msiexec.exe /i "C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi" /quiet /norestart</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">msiexec.exe</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">i </span><span style="color: #9ECBFF">&quot;C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi&quot;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">quiet </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">norestart</span></span></code></pre></div>



<p class="wp-block-paragraph">Nach dem Aufruf war der Agent jedoch nicht installiert. Ein erneuter Start mit administrativen Rechten änderte nichts. Ein Aufruf ohne <code>/quiet</code> zeigt dann immerhin einen konkreteren Fehler:</p>



<figure class="wp-block-image size-full"><img decoding="async" src="https://www.hertes.net/wp-content/uploads/2026/09/Screenshot-2026-09-08-150909.png" alt="Fehlermeldung bei der Installation des Checkmk-Agenten auf Azure Local"/></figure>



<p class="wp-block-paragraph">Der Fehlertext lautet: <strong>“The system administrator has set policies to prevent this installation.”</strong></p>



<p class="wp-block-paragraph">Genau an diesem Punkt lohnt es sich, nicht nur das MSI-Protokoll, sondern auch Application Control beziehungsweise Windows Defender Application Control (WDAC) zu prüfen.</p>



<h2 class="wp-block-heading">1. Den WDAC-Status prüfen</h2>



<p class="wp-block-paragraph">Azure Local stellt eigene PowerShell-Cmdlets bereit, um den Richtlinienmodus und die lokal vorhandenen Richtlinien anzuzeigen:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-AsWdacPolicyMode

Get-ASLocalWDACPolicyInfo |
    Select-Object PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced |
    Format-Table -AutoSize</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span></code></pre></div>



<p class="wp-block-paragraph">Steht der Modus auf <code>Enforced</code>, kann WDAC den Installationsvorgang oder vom Installer gestartete Binärdateien blockieren.</p>



<h3 class="wp-block-heading">Relevante Ereignisse kompakt auslesen</h3>



<p class="wp-block-paragraph">Ausführbare Dateien, DLLs und Treiber werden üblicherweise im Code-Integrity-Protokoll erfasst. MSI- und Skript-Ereignisse können im AppLocker-Protokoll erscheinen. Auf Server Core ist das AppLocker-Protokoll für MSI und Skripte möglicherweise nicht vorhanden.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$StartTime = (Get-Date).AddMinutes(-30)
$EventIds = 3076, 3077, 3089, 8028, 8029, 8038
$Logs = @(
    'Microsoft-Windows-CodeIntegrity/Operational'
    'Microsoft-Windows-AppLocker/MSI and Script'
)

foreach ($Log in $Logs) {
    if (-not (Get-WinEvent -ListLog $Log -ErrorAction SilentlyContinue)) {
        Write-Warning "Event log is not available: $Log"
        continue
    }

    Get-WinEvent -FilterHashtable @{
        LogName   = $Log
        StartTime = $StartTime
        Id        = $EventIds
    } -ErrorAction SilentlyContinue |
        Where-Object {
            $_.Message -match 'check&#91;_-&#93;?mk|cmk|msi'
        } |
        Sort-Object TimeCreated |
        Select-Object TimeCreated, Id, LevelDisplayName, Message |
        Format-List
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$StartTime </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Get-Date</span><span style="color: #E1E4E8">).AddMinutes(</span><span style="color: #79B8FF">-30</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">$EventIds </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3076</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3077</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3089</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8028</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8029</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8038</span></span>
<span class="line"><span style="color: #E1E4E8">$Logs </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;Microsoft-Windows-CodeIntegrity/Operational&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;Microsoft-Windows-AppLocker/MSI and Script&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">foreach</span><span style="color: #E1E4E8"> ($Log </span><span style="color: #F97583">in</span><span style="color: #E1E4E8"> $Logs) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Get-WinEvent</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ListLog $Log </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ErrorAction SilentlyContinue)) {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Write-Warning</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Event log is not available: </span><span style="color: #E1E4E8">$Log</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">continue</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Get-WinEvent</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilterHashtable </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">        LogName   </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Log</span></span>
<span class="line"><span style="color: #E1E4E8">        StartTime </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $StartTime</span></span>
<span class="line"><span style="color: #E1E4E8">        Id        </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $EventIds</span></span>
<span class="line"><span style="color: #E1E4E8">    } </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ErrorAction SilentlyContinue </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Message </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check&#91;_-&#93;?mk|cmk|msi&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">        } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Sort-Object</span><span style="color: #E1E4E8"> TimeCreated </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> TimeCreated</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Id</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> LevelDisplayName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Message </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Format-List</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Die wichtigsten IDs für diesen Fall sind <code>3077</code> für einen Block im erzwungenen Modus und <code>3076</code> für das entsprechende Audit-Ereignis. Für MSI- und Skriptsteuerung sind insbesondere <code>8029</code> (Block) und <code>8028</code> (Audit) relevant.</p>



<h2 class="wp-block-heading">2. Warum eine ergänzende Richtlinie?</h2>



<p class="wp-block-paragraph">Die Azure-Local-Basisrichtlinie einfach dauerhaft zu deaktivieren wäre keine gute Lösung. Eine ergänzende Richtlinie erweitert die erlaubte Codebasis gezielt. Basis- und ergänzende Richtlinie werden gemeinsam ausgewertet; die zusätzlich erlaubten Checkmk-Dateien müssen daher nicht in die von Microsoft bereitgestellte Basisrichtlinie eingebaut werden.</p>



<p class="wp-block-paragraph">Für die Regelerzeugung wurde die Publisher-Ebene verwendet. Falls eine Datei keine verwertbare Signatur besitzt, greift <code>-Fallback Hash</code>. Das ist bewusst restriktiv: Eine neue, inhaltlich veränderte Datei hat einen anderen Hash und kann bei einem späteren Agent-Update eine aktualisierte ergänzende Richtlinie erfordern.</p>



<h2 class="wp-block-heading">3. In den Audit-Modus wechseln</h2>



<p class="wp-block-paragraph">Im Beispiel wird der Modus clusterweit geändert. <code>Enable-AsWdacPolicy</code> wirkt auf alle Clusterknoten. Nach der Änderung sollte der Status auf jedem Knoten geprüft werden, bevor die Installation fortgesetzt wird.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-AsWdacPolicyMode

Enable-AsWdacPolicy -Mode Audit
Start-Sleep -Seconds 180

Get-AsWdacPolicyMode</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Enable-AsWdacPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Mode Audit</span></span>
<span class="line"><span style="color: #79B8FF">Start-Sleep</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Seconds </span><span style="color: #79B8FF">180</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span></code></pre></div>



<p class="wp-block-paragraph">Microsoft weist darauf hin, dass die Umschaltung zwei bis drei Minuten dauern kann. Für einen ausschließlich lokalen Test existiert außerdem <code>Enable-ASLocalWDACPolicy</code>; eine lokal abweichende Richtlinienlage muss anschließend aber bewusst wieder bereinigt werden.</p>



<h2 class="wp-block-heading">4. Den Agenten auf einem Referenzknoten installieren</h2>



<p class="wp-block-paragraph">Das MSI wird nun im Audit-Modus installiert. Der folgende vollständige PowerShell-Block prüft die Datei und wertet den Exitcode von <code>msiexec</code> aus:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$MsiPath = 'C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi'

if (-not (Test-Path -LiteralPath $MsiPath -PathType Leaf)) {
    throw "MSI file not found: $MsiPath"
}

$Arguments = @(
    '/i'
    "`"$MsiPath`""
    '/quiet'
    '/norestart'
)

$Process = Start-Process -FilePath 'msiexec.exe' `
    -ArgumentList $Arguments `
    -Wait `
    -PassThru

if ($Process.ExitCode -notin 0, 3010) {
    throw "Checkmk MSI installation failed with exit code $($Process.ExitCode)."
}

Get-Service |
    Where-Object { $_.Name -match 'check|cmk' -or $_.DisplayName -match 'checkmk' } |
    Format-Table Status, Name, DisplayName -AutoSize</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$MsiPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $MsiPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;MSI file not found: </span><span style="color: #E1E4E8">$MsiPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Arguments </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/i&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&quot;</span><span style="color: #79B8FF">`&quot;</span><span style="color: #E1E4E8">$MsiPath</span><span style="color: #79B8FF">`&quot;</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/quiet&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/norestart&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Process </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Start-Process</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath </span><span style="color: #9ECBFF">&#39;msiexec.exe&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ArgumentList $Arguments </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Wait </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PassThru</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($Process.ExitCode </span><span style="color: #F97583">-notin</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">0</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3010</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Checkmk MSI installation failed with exit code </span><span style="color: #F97583">$</span><span style="color: #9ECBFF">(</span><span style="color: #E1E4E8">$Process.ExitCode</span><span style="color: #9ECBFF">)</span><span style="color: #9ECBFF">.&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-Service</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Name </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check|cmk&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-or</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.DisplayName </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;checkmk&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> Status</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Name</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> DisplayName </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span></code></pre></div>



<p class="wp-block-paragraph">Der Exitcode <code>3010</code> bedeutet, dass die Installation erfolgreich war, aber ein Neustart erforderlich ist. Vor dem nächsten Schritt muss der Agent vollständig installiert und getestet sein.</p>



<h2 class="wp-block-heading">5. Die ergänzende Checkmk-Richtlinie erzeugen und verteilen</h2>



<p class="wp-block-paragraph">Im Testsystem lag die Installation unter <code>C:\Program Files (x86)\checkmk</code>. Der Scanpfad muss an die tatsächlich installierte Version angepasst werden. Es sollte nur das notwendige Produktverzeichnis gescannt werden – nicht pauschal <code>C:\</code> oder das gesamte Verzeichnis <code>Program Files</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$PolicyDirectory = 'C:\WDAC\Checkmk'
$ScanPath = 'C:\Program Files (x86)\checkmk'
$PolicyPath = Join-Path $PolicyDirectory 'Checkmk-Agent-Supplemental.xml'
$PolicyName = 'Checkmk Agent Supplemental Policy'
$PolicyVersion = '1.0.0.0'

New-Item -Path $PolicyDirectory -ItemType Directory -Force | Out-Null

if (-not (Test-Path -LiteralPath $ScanPath -PathType Container)) {
    throw "Checkmk installation directory not found: $ScanPath"
}

New-CIPolicy `
    -MultiplePolicyFormat `
    -Level Publisher `
    -Fallback Hash `
    -UserPEs `
    -ScanPath $ScanPath `
    -FilePath $PolicyPath

Set-CIPolicyVersion `
    -FilePath $PolicyPath `
    -Version $PolicyVersion

Set-CIPolicyIdInfo `
    -FilePath $PolicyPath `
    -PolicyID "Checkmk-Agent_$PolicyVersion" `
    -PolicyName $PolicyName

Add-ASWDACSupplementalPolicy -Path $PolicyPath

Get-ASLocalWDACPolicyInfo |
    Where-Object { $_.PolicyName -eq $PolicyName } |
    Format-List PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$PolicyDirectory </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ScanPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\Program Files (x86)\checkmk&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Join-Path</span><span style="color: #E1E4E8"> $PolicyDirectory </span><span style="color: #9ECBFF">&#39;Checkmk-Agent-Supplemental.xml&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyName </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;Checkmk Agent Supplemental Policy&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyVersion </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;1.0.0.0&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">New-Item</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyDirectory </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ItemType Directory </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Force </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Out-Null</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $ScanPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Container)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Checkmk installation directory not found: </span><span style="color: #E1E4E8">$ScanPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">New-CIPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">MultiplePolicyFormat </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Level Publisher </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Fallback Hash </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">UserPEs </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ScanPath $ScanPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Set-CIPolicyVersion</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Version $PolicyVersion</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Set-CIPolicyIdInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PolicyID </span><span style="color: #9ECBFF">&quot;Checkmk-Agent_</span><span style="color: #E1E4E8">$PolicyVersion</span><span style="color: #9ECBFF">&quot;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PolicyName $PolicyName</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Add-ASWDACSupplementalPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyPath</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyName </span><span style="color: #F97583">-eq</span><span style="color: #E1E4E8"> $PolicyName } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-List</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced</span></span></code></pre></div>



<p class="wp-block-paragraph">Die XML-Datei sollte versionskontrolliert und zusammen mit der verwendeten Agent-Version dokumentiert werden. Die erzeugte Policy-ID ist umgebungsspezifisch und darf nicht blind aus einem anderen System übernommen werden.</p>



<h2 class="wp-block-heading">6. Die Supplemental Policy auf alle Clusterknoten verteilen und prüfen</h2>



<p class="wp-block-paragraph">Eine erfolgreiche Installation auf dem Referenzknoten beweist noch nicht, dass die ergänzende Richtlinie auf allen Clusterknoten aktiv ist. Im beschriebenen Lab war die Checkmk-Richtlinie zunächst nur auf AZLHOST01 vorhanden. Auf AZLHOST02 und AZLHOST03 fehlte sie, obwohl die Basisrichtlinie dort bereits im Modus <code>Enforced</code> arbeitete.</p>



<p class="wp-block-paragraph">Deshalb wurde die bereits erzeugte XML-Datei auf AZLHOST01 erneut mit <code>Add-ASWDACSupplementalPolicy</code> bereitgestellt. Das Cmdlet verarbeitet alle Clusterknoten. Anschließend kontrolliert das Skript den Richtlinienmodus und fragt die Policy-ID auf jedem Knoten direkt über <code>CiTool</code> ab. Diese Kontrolle über die Policy-ID ist besonders hilfreich, wenn <code>Get-ASLocalWDACPolicyInfo</code> für eine eigene Richtlinie keinen Namen anzeigt.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$PolicyPath = 'C:\WDAC\Checkmk-2.5.0p12\Checkmk-Supplemental.xml'
$ExpectedPolicyId = 'd9c9bf97-3465-4afb-9714-b457f2341e61'
$ExpectedBasePolicyId = 'a6368f66-e2c9-4aa2-ab79-8743f6597683'
$ClusterNodes = @(
    'AZLHOST01'
    'AZLHOST02'
    'AZLHOST03'
)

if (-not (Test-Path -LiteralPath $PolicyPath -PathType Leaf)) {
    throw "WDAC policy file not found: $PolicyPath"
}

$PolicyContent = Get-Content -LiteralPath $PolicyPath -Raw

if ($PolicyContent -notmatch &#91;regex&#93;::Escape($ExpectedPolicyId)) {
    throw 'The XML does not contain the expected supplemental policy ID.'
}

if ($PolicyContent -notmatch &#91;regex&#93;::Escape($ExpectedBasePolicyId)) {
    throw 'The XML does not reference the expected Azure Local base policy.'
}

Add-ASWDACSupplementalPolicy `
    -Path $PolicyPath `
    -Verbose

Get-AsWdacPolicyMode

$PolicyStatus = Invoke-Command `
    -ComputerName $ClusterNodes `
    -ScriptBlock {
        param($PolicyId)

        $CiToolPath = Join-Path $env:SystemRoot 'System32\CiTool.exe'
        $PolicyInventory = &amp; $CiToolPath -lp -json | ConvertFrom-Json

        $Policy = @(
            $PolicyInventory.Policies |
                Where-Object {
                    (&#91;string&#93;$_.PolicyID).Trim('{}') -ieq $PolicyId
                }
        ) | Select-Object -First 1

        &#91;pscustomobject&#93;@{
            Node         = $env:COMPUTERNAME
            PolicyFound  = $null -ne $Policy
            PolicyID     = $Policy.PolicyID
            BasePolicyID = $Policy.BasePolicyID
            IsOnDisk     = $Policy.IsOnDisk
            IsEnforced   = $Policy.IsEnforced
        }
    } `
    -ArgumentList $ExpectedPolicyId

$PolicyStatus |
    Select-Object Node, PolicyFound, PolicyID, BasePolicyID, IsOnDisk, IsEnforced |
    Format-Table -AutoSize

$MissingNodes = @(
    $PolicyStatus |
        Where-Object {
            -not $_.PolicyFound -or
            -not $_.IsOnDisk -or
            -not $_.IsEnforced
        }
)

if ($MissingNodes.Count -gt 0) {
    throw "The Checkmk supplemental policy is not active on every cluster node."
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$PolicyPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk-2.5.0p12\Checkmk-Supplemental.xml&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ExpectedPolicyId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;d9c9bf97-3465-4afb-9714-b457f2341e61&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ExpectedBasePolicyId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;a6368f66-e2c9-4aa2-ab79-8743f6597683&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ClusterNodes </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST01&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST02&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST03&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $PolicyPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;WDAC policy file not found: </span><span style="color: #E1E4E8">$PolicyPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyContent </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Get-Content</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $PolicyPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Raw</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($PolicyContent </span><span style="color: #F97583">-notmatch</span><span style="color: #E1E4E8"> &#91;</span><span style="color: #F97583">regex</span><span style="color: #E1E4E8">&#93;::Escape($ExpectedPolicyId)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;The XML does not contain the expected supplemental policy ID.&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($PolicyContent </span><span style="color: #F97583">-notmatch</span><span style="color: #E1E4E8"> &#91;</span><span style="color: #F97583">regex</span><span style="color: #E1E4E8">&#93;::Escape($ExpectedBasePolicyId)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;The XML does not reference the expected Azure Local base policy.&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Add-ASWDACSupplementalPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Verbose</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyStatus </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Invoke-Command</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ComputerName $ClusterNodes </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ScriptBlock {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">param</span><span style="color: #E1E4E8">($PolicyId)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        $CiToolPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Join-Path</span><span style="color: #E1E4E8"> $</span><span style="color: #79B8FF">env:</span><span style="color: #E1E4E8">SystemRoot </span><span style="color: #9ECBFF">&#39;System32\CiTool.exe&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">        $PolicyInventory </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">&amp;</span><span style="color: #E1E4E8"> $CiToolPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">lp </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">json </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">ConvertFrom-Json</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        $Policy </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            $PolicyInventory.Policies </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">                </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">                    (&#91;</span><span style="color: #F97583">string</span><span style="color: #E1E4E8">&#93;</span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyID).Trim(</span><span style="color: #9ECBFF">&#39;{}&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #F97583">-ieq</span><span style="color: #E1E4E8"> $PolicyId</span></span>
<span class="line"><span style="color: #E1E4E8">                }</span></span>
<span class="line"><span style="color: #E1E4E8">        ) </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">First </span><span style="color: #79B8FF">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        &#91;</span><span style="color: #F97583">pscustomobject</span><span style="color: #E1E4E8">&#93;</span><span style="color: #F97583">@</span><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">            Node         </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $</span><span style="color: #79B8FF">env:</span><span style="color: #E1E4E8">COMPUTERNAME</span></span>
<span class="line"><span style="color: #E1E4E8">            PolicyFound  </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$null</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-ne</span><span style="color: #E1E4E8"> $Policy</span></span>
<span class="line"><span style="color: #E1E4E8">            PolicyID     </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.PolicyID</span></span>
<span class="line"><span style="color: #E1E4E8">            BasePolicyID </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.BasePolicyID</span></span>
<span class="line"><span style="color: #E1E4E8">            IsOnDisk     </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.IsOnDisk</span></span>
<span class="line"><span style="color: #E1E4E8">            IsEnforced   </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.IsEnforced</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">    } </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ArgumentList $ExpectedPolicyId</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyStatus </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> Node</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyFound</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyID</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyID</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$MissingNodes </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    $PolicyStatus </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyFound </span><span style="color: #F97583">-or</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.IsOnDisk </span><span style="color: #F97583">-or</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.IsEnforced</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($MissingNodes.Count </span><span style="color: #F97583">-gt</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">0</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;The Checkmk supplemental policy is not active on every cluster node.&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Bei einer erfolgreichen Bereitstellung meldet die ausführliche Ausgabe für jeden neuen Knoten <code>Refreshed and activated Code Integrity policy</code> mit Status <code>0x0</code>. Die abschließende Tabelle muss für alle Knoten <code>PolicyFound</code>, <code>IsOnDisk</code> und <code>IsEnforced</code> als <code>True</code> ausweisen. Erst danach sollte das Checkmk-MSI auf den übrigen Knoten installiert werden.</p>



<h2 class="wp-block-heading">7. WDAC wieder erzwingen und die Installation testen</h2>



<p class="wp-block-paragraph">Sobald die ergänzende Richtlinie auf den Knoten vorhanden ist, wird die Basisrichtlinie wieder in den erzwungenen Modus versetzt:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Enable-AsWdacPolicy -Mode Enforced
Start-Sleep -Seconds 180

Get-AsWdacPolicyMode

Get-ASLocalWDACPolicyInfo |
    Where-Object { $_.PolicyName -eq 'Checkmk Agent Supplemental Policy' } |
    Format-List PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Enable-AsWdacPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Mode Enforced</span></span>
<span class="line"><span style="color: #79B8FF">Start-Sleep</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Seconds </span><span style="color: #79B8FF">180</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyName </span><span style="color: #F97583">-eq</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;Checkmk Agent Supplemental Policy&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-List</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced</span></span></code></pre></div>



<p class="wp-block-paragraph">Danach sollte der entscheidende Test unter <code>Enforced</code> erfolgen: Agent starten, Status prüfen und die MSI-Installation auf den übrigen Knoten wiederholen. Nur ein erfolgreicher Test im erzwungenen Modus zeigt, dass die ergänzende Richtlinie vollständig ist.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-Service |
    Where-Object { $_.Name -match 'check|cmk' -or $_.DisplayName -match 'checkmk' } |
    Format-Table Status, Name, DisplayName -AutoSize

$Controller = 'C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe'
if (Test-Path -LiteralPath $Controller -PathType Leaf) {
    &amp; $Controller status
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-Service</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Name </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check|cmk&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-or</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.DisplayName </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;checkmk&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> Status</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Name</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> DisplayName </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Controller </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe&#39;</span></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $Controller </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">&amp;</span><span style="color: #E1E4E8"> $Controller status</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<h2 class="wp-block-heading">Das Ergebnis im Lab</h2>



<p class="wp-block-paragraph">Im beschriebenen Cluster blieb die Azure-Local-Basisrichtlinie <code>AS_Base_Policy</code> aktiv. Ihre Policy-ID war <code>a6368f66-e2c9-4aa2-ab79-8743f6597683</code>. Ergänzt wurde sie durch die Richtlinie <code>Checkmk Agent Supplemental Policy</code> mit der Policy-ID <code>d9c9bf97-3465-4afb-9714-b457f2341e61</code>. Die ergänzende Richtlinie wurde auf dem Datenträger gefunden und als erzwungen gemeldet. Anschließend ließ sich <code>check-mk-agent_2.5.0p12.msi</code> installieren.</p>



<p class="wp-block-paragraph">Diese GUIDs dokumentieren nur das konkrete Lab. Für eine neue Richtlinie werden eigene IDs erzeugt.</p>



<h2 class="wp-block-heading">Nach der Installation: TCP/6556 nicht vergessen</h2>



<p class="wp-block-paragraph">Die erfolgreiche Installation bedeutet noch nicht, dass der Checkmk-Server den Agenten erreichen kann. Der klassische Checkmk-Agent benötigt eingehend TCP/6556. Der Installer legt normalerweise eine lokale Firewallregel an. In Umgebungen mit zentral verwalteten oder restriktiven Firewallrichtlinien kann trotzdem eine passende Gruppenrichtlinie erforderlich sein.</p>



<p class="wp-block-paragraph">Im Lab war die Vererbung an der Azure-Local-OU deaktiviert. Eine weiter oben verknüpfte Firewall-GPO erreichte die Server deshalb nicht. Die Freigabe für TCP/6556 musste direkt an der Server-OU verknüpft werden. Danach konnte Checkmk den Agenten verbinden.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Die Firewall war ein separates Problem nach der Installation. Sie war nicht die Ursache dafür, dass WDAC das MSI beziehungsweise dessen Code zuvor blockierte.</p>
</blockquote>



<h2 class="wp-block-heading">Was bei Agent-Updates zu beachten ist</h2>



<ul class="wp-block-list">
<li>Die Richtlinien-XML und die zugehörige Checkmk-Version gemeinsam dokumentieren.</li>



<li>Neue Agent-Versionen zuerst auf einem Referenzknoten unter <code>Enforced</code> testen.</li>



<li>Bei neuen Blockereignissen die ergänzende Richtlinie gezielt aktualisieren und versionieren.</li>



<li>Den Audit-Modus nur so lange wie erforderlich verwenden.</li>



<li>Firewall-GPO, OU-Verknüpfung und Sicherheitsfilterung ebenfalls nach Änderungen kontrollieren.</li>
</ul>



<h2 class="wp-block-heading">Fazit</h2>



<p class="wp-block-paragraph">Wenn eine MSI-Installation auf Azure Local scheinbar ohne Ergebnis endet, sollte WDAC früh in die Diagnose einbezogen werden. Der saubere Weg besteht darin, die Blockierung über die Ereignisprotokolle zu bestätigen, die Software kontrolliert im Audit-Modus zu installieren, aus dem eng begrenzten Installationsverzeichnis eine ergänzende Richtlinie zu erzeugen und anschließend wieder auf <code>Enforced</code> umzuschalten. So bleibt das Sicherheitsmodell von Azure Local erhalten, während der Checkmk-Agent gezielt zugelassen wird.</p>



<h2 class="wp-block-heading">Quellen</h2>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/manage-wdac?view=azloc-2608">Microsoft Learn: Manage Application Control for Azure Local</a></li>



<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/operations/event-id-explanations">Microsoft Learn: Application Control event ID explanations</a></li>



<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/design/deploy-multiple-appcontrol-policies">Microsoft Learn: Deploy multiple Application Control policies</a></li>



<li><a href="https://docs.checkmk.com/latest/en/agent_windows.html">Checkmk documentation: The agent for Windows</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="english-version" class="wp-block-heading">Installing the Checkmk agent on Azure Local when WDAC blocks the MSI</h2>



<p class="wp-block-paragraph">On an Azure Local cluster, the Checkmk agent could not be installed from its MSI package. The installer was launched with administrative privileges, the file existed, and the <code>msiexec</code> command looked correct—yet the agent did not appear as an installed application.</p>



<p class="wp-block-paragraph">The cause was neither Checkmk nor a damaged MSI package. Azure Local was running its Application Control policy in enforced mode, which blocked untrusted code. The issue was resolved with a supplemental WDAC policy for the Checkmk agent while keeping the existing Azure Local base policy active.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Important:</strong> The commands in this article change the code-integrity configuration of a cluster. Use a maintenance window and have a tested recovery path. Audit mode permits code that enforced mode would block.</p>
</blockquote>



<h2 class="wp-block-heading">The symptoms</h2>



<p class="wp-block-paragraph">The unattended installation command itself was valid:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>msiexec.exe /i "C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi" /quiet /norestart</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">msiexec.exe</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">i </span><span style="color: #9ECBFF">&quot;C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi&quot;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">quiet </span><span style="color: #F97583">/</span><span style="color: #E1E4E8">norestart</span></span></code></pre></div>



<p class="wp-block-paragraph">After the command completed, however, the agent was not installed. Running it again with administrative privileges made no difference. Running the installer without <code>/quiet</code> at least displayed a more specific error:</p>



<figure class="wp-block-image size-full"><img decoding="async" src="https://www.hertes.net/wp-content/uploads/2026/09/Screenshot-2026-09-08-150909.png" alt="Error message while installing the Checkmk agent on Azure Local"/></figure>



<p class="wp-block-paragraph">The error message was: <strong>“The system administrator has set policies to prevent this installation.”</strong></p>



<p class="wp-block-paragraph">At this point, it is worth checking Application Control or Windows Defender Application Control (WDAC), not only the MSI log.</p>



<h2 class="wp-block-heading">1. Check the WDAC state</h2>



<p class="wp-block-paragraph">Azure Local provides PowerShell cmdlets that show the policy mode and locally available policies:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-AsWdacPolicyMode

Get-ASLocalWDACPolicyInfo |
    Select-Object PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced |
    Format-Table -AutoSize</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span></code></pre></div>



<p class="wp-block-paragraph">If the mode is <code>Enforced</code>, WDAC can block the installation process or binaries launched by the installer.</p>



<h3 class="wp-block-heading">Query the relevant events</h3>



<p class="wp-block-paragraph">Executables, DLLs, and drivers are typically recorded in the Code Integrity log. MSI and script events can appear in the AppLocker log. On Server Core, the AppLocker MSI and Script log may not exist.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$StartTime = (Get-Date).AddMinutes(-30)
$EventIds = 3076, 3077, 3089, 8028, 8029, 8038
$Logs = @(
    'Microsoft-Windows-CodeIntegrity/Operational'
    'Microsoft-Windows-AppLocker/MSI and Script'
)

foreach ($Log in $Logs) {
    if (-not (Get-WinEvent -ListLog $Log -ErrorAction SilentlyContinue)) {
        Write-Warning "Event log is not available: $Log"
        continue
    }

    Get-WinEvent -FilterHashtable @{
        LogName   = $Log
        StartTime = $StartTime
        Id        = $EventIds
    } -ErrorAction SilentlyContinue |
        Where-Object {
            $_.Message -match 'check&#91;_-&#93;?mk|cmk|msi'
        } |
        Sort-Object TimeCreated |
        Select-Object TimeCreated, Id, LevelDisplayName, Message |
        Format-List
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$StartTime </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Get-Date</span><span style="color: #E1E4E8">).AddMinutes(</span><span style="color: #79B8FF">-30</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">$EventIds </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3076</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3077</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3089</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8028</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8029</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">8038</span></span>
<span class="line"><span style="color: #E1E4E8">$Logs </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;Microsoft-Windows-CodeIntegrity/Operational&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;Microsoft-Windows-AppLocker/MSI and Script&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">foreach</span><span style="color: #E1E4E8"> ($Log </span><span style="color: #F97583">in</span><span style="color: #E1E4E8"> $Logs) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Get-WinEvent</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ListLog $Log </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ErrorAction SilentlyContinue)) {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Write-Warning</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Event log is not available: </span><span style="color: #E1E4E8">$Log</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">continue</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Get-WinEvent</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilterHashtable </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">        LogName   </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Log</span></span>
<span class="line"><span style="color: #E1E4E8">        StartTime </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $StartTime</span></span>
<span class="line"><span style="color: #E1E4E8">        Id        </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $EventIds</span></span>
<span class="line"><span style="color: #E1E4E8">    } </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ErrorAction SilentlyContinue </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Message </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check&#91;_-&#93;?mk|cmk|msi&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">        } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Sort-Object</span><span style="color: #E1E4E8"> TimeCreated </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> TimeCreated</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Id</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> LevelDisplayName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Message </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Format-List</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p class="wp-block-paragraph">The most relevant IDs here are <code>3077</code> for a block in enforced mode and <code>3076</code> for its audit equivalent. For MSI and script control, pay particular attention to <code>8029</code> (block) and <code>8028</code> (audit).</p>



<h2 class="wp-block-heading">2. Why use a supplemental policy?</h2>



<p class="wp-block-paragraph">Permanently disabling the Azure Local base policy is not a good solution. A supplemental policy adds a narrowly defined set of allowed code. The base and supplemental policies are evaluated together, so the Checkmk files do not have to be merged into Microsoft&#8217;s base policy.</p>



<p class="wp-block-paragraph">The policy in this example uses publisher rules. If a file does not have a usable signature, <code>-Fallback Hash</code> creates a hash rule. That is intentionally restrictive: changed files receive new hashes, so a future agent upgrade may require an updated supplemental policy.</p>



<h2 class="wp-block-heading">3. Switch to audit mode</h2>



<p class="wp-block-paragraph">This example changes the mode cluster-wide. <code>Enable-AsWdacPolicy</code> affects all cluster nodes. Verify the state on every node before continuing.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-AsWdacPolicyMode

Enable-AsWdacPolicy -Mode Audit
Start-Sleep -Seconds 180

Get-AsWdacPolicyMode</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Enable-AsWdacPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Mode Audit</span></span>
<span class="line"><span style="color: #79B8FF">Start-Sleep</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Seconds </span><span style="color: #79B8FF">180</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span></code></pre></div>



<p class="wp-block-paragraph">Microsoft notes that the change can take two to three minutes. <code>Enable-ASLocalWDACPolicy</code> is also available for a local-only test, but any deliberately different local policy state must be cleaned up afterward.</p>



<h2 class="wp-block-heading">4. Install the agent on a reference node</h2>



<p class="wp-block-paragraph">Install the MSI while the policy is in audit mode. The complete PowerShell block below verifies the file and evaluates the <code>msiexec</code> exit code:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$MsiPath = 'C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi'

if (-not (Test-Path -LiteralPath $MsiPath -PathType Leaf)) {
    throw "MSI file not found: $MsiPath"
}

$Arguments = @(
    '/i'
    "`"$MsiPath`""
    '/quiet'
    '/norestart'
)

$Process = Start-Process -FilePath 'msiexec.exe' `
    -ArgumentList $Arguments `
    -Wait `
    -PassThru

if ($Process.ExitCode -notin 0, 3010) {
    throw "Checkmk MSI installation failed with exit code $($Process.ExitCode)."
}

Get-Service |
    Where-Object { $_.Name -match 'check|cmk' -or $_.DisplayName -match 'checkmk' } |
    Format-Table Status, Name, DisplayName -AutoSize</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$MsiPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk\check-mk-agent_2.5.0p12.msi&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $MsiPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;MSI file not found: </span><span style="color: #E1E4E8">$MsiPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Arguments </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/i&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&quot;</span><span style="color: #79B8FF">`&quot;</span><span style="color: #E1E4E8">$MsiPath</span><span style="color: #79B8FF">`&quot;</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/quiet&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;/norestart&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Process </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Start-Process</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath </span><span style="color: #9ECBFF">&#39;msiexec.exe&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ArgumentList $Arguments </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Wait </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PassThru</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($Process.ExitCode </span><span style="color: #F97583">-notin</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">0</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">3010</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Checkmk MSI installation failed with exit code </span><span style="color: #F97583">$</span><span style="color: #9ECBFF">(</span><span style="color: #E1E4E8">$Process.ExitCode</span><span style="color: #9ECBFF">)</span><span style="color: #9ECBFF">.&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-Service</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Name </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check|cmk&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-or</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.DisplayName </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;checkmk&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> Status</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Name</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> DisplayName </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span></code></pre></div>



<p class="wp-block-paragraph">Exit code <code>3010</code> means that the installation succeeded but requires a restart. Ensure that the agent is fully installed and tested before creating the policy.</p>



<h2 class="wp-block-heading">5. Create and deploy the supplemental Checkmk policy</h2>



<p class="wp-block-paragraph">In the lab, Checkmk was installed below <code>C:\Program Files (x86)\checkmk</code>. Adjust the scan path to the actual installation. Scan only the required product directory—never scan all of <code>C:\</code> or the complete <code>Program Files</code> tree.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$PolicyDirectory = 'C:\WDAC\Checkmk'
$ScanPath = 'C:\Program Files (x86)\checkmk'
$PolicyPath = Join-Path $PolicyDirectory 'Checkmk-Agent-Supplemental.xml'
$PolicyName = 'Checkmk Agent Supplemental Policy'
$PolicyVersion = '1.0.0.0'

New-Item -Path $PolicyDirectory -ItemType Directory -Force | Out-Null

if (-not (Test-Path -LiteralPath $ScanPath -PathType Container)) {
    throw "Checkmk installation directory not found: $ScanPath"
}

New-CIPolicy `
    -MultiplePolicyFormat `
    -Level Publisher `
    -Fallback Hash `
    -UserPEs `
    -ScanPath $ScanPath `
    -FilePath $PolicyPath

Set-CIPolicyVersion `
    -FilePath $PolicyPath `
    -Version $PolicyVersion

Set-CIPolicyIdInfo `
    -FilePath $PolicyPath `
    -PolicyID "Checkmk-Agent_$PolicyVersion" `
    -PolicyName $PolicyName

Add-ASWDACSupplementalPolicy -Path $PolicyPath

Get-ASLocalWDACPolicyInfo |
    Where-Object { $_.PolicyName -eq $PolicyName } |
    Format-List PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$PolicyDirectory </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ScanPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\Program Files (x86)\checkmk&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Join-Path</span><span style="color: #E1E4E8"> $PolicyDirectory </span><span style="color: #9ECBFF">&#39;Checkmk-Agent-Supplemental.xml&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyName </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;Checkmk Agent Supplemental Policy&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$PolicyVersion </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;1.0.0.0&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">New-Item</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyDirectory </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ItemType Directory </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Force </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Out-Null</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $ScanPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Container)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;Checkmk installation directory not found: </span><span style="color: #E1E4E8">$ScanPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">New-CIPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">MultiplePolicyFormat </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Level Publisher </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Fallback Hash </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">UserPEs </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ScanPath $ScanPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Set-CIPolicyVersion</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Version $PolicyVersion</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Set-CIPolicyIdInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">FilePath $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PolicyID </span><span style="color: #9ECBFF">&quot;Checkmk-Agent_</span><span style="color: #E1E4E8">$PolicyVersion</span><span style="color: #9ECBFF">&quot;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PolicyName $PolicyName</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Add-ASWDACSupplementalPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyPath</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyName </span><span style="color: #F97583">-eq</span><span style="color: #E1E4E8"> $PolicyName } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-List</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced</span></span></code></pre></div>



<p class="wp-block-paragraph">Keep the XML file under version control and document the matching agent version. The generated policy ID belongs to this environment and should not be copied blindly to another system.</p>



<h2 class="wp-block-heading">6. Deploy and verify the supplemental policy on every cluster node</h2>



<p class="wp-block-paragraph">A successful installation on the reference node does not prove that the supplemental policy is active on every cluster node. In this lab, the Checkmk policy was initially present only on AZLHOST01. It was missing from AZLHOST02 and AZLHOST03 even though their base policies were already running in <code>Enforced</code> mode.</p>



<p class="wp-block-paragraph">The existing XML file was therefore deployed again from AZLHOST01 with <code>Add-ASWDACSupplementalPolicy</code>. The cmdlet processes every cluster node. The script then checks the policy mode and queries the policy ID directly through <code>CiTool</code> on every node. Checking the ID is particularly useful when <code>Get-ASLocalWDACPolicyInfo</code> does not display a name for a custom policy.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>$PolicyPath = 'C:\WDAC\Checkmk-2.5.0p12\Checkmk-Supplemental.xml'
$ExpectedPolicyId = 'd9c9bf97-3465-4afb-9714-b457f2341e61'
$ExpectedBasePolicyId = 'a6368f66-e2c9-4aa2-ab79-8743f6597683'
$ClusterNodes = @(
    'AZLHOST01'
    'AZLHOST02'
    'AZLHOST03'
)

if (-not (Test-Path -LiteralPath $PolicyPath -PathType Leaf)) {
    throw "WDAC policy file not found: $PolicyPath"
}

$PolicyContent = Get-Content -LiteralPath $PolicyPath -Raw

if ($PolicyContent -notmatch &#91;regex&#93;::Escape($ExpectedPolicyId)) {
    throw 'The XML does not contain the expected supplemental policy ID.'
}

if ($PolicyContent -notmatch &#91;regex&#93;::Escape($ExpectedBasePolicyId)) {
    throw 'The XML does not reference the expected Azure Local base policy.'
}

Add-ASWDACSupplementalPolicy `
    -Path $PolicyPath `
    -Verbose

Get-AsWdacPolicyMode

$PolicyStatus = Invoke-Command `
    -ComputerName $ClusterNodes `
    -ScriptBlock {
        param($PolicyId)

        $CiToolPath = Join-Path $env:SystemRoot 'System32\CiTool.exe'
        $PolicyInventory = &amp; $CiToolPath -lp -json | ConvertFrom-Json

        $Policy = @(
            $PolicyInventory.Policies |
                Where-Object {
                    (&#91;string&#93;$_.PolicyID).Trim('{}') -ieq $PolicyId
                }
        ) | Select-Object -First 1

        &#91;pscustomobject&#93;@{
            Node         = $env:COMPUTERNAME
            PolicyFound  = $null -ne $Policy
            PolicyID     = $Policy.PolicyID
            BasePolicyID = $Policy.BasePolicyID
            IsOnDisk     = $Policy.IsOnDisk
            IsEnforced   = $Policy.IsEnforced
        }
    } `
    -ArgumentList $ExpectedPolicyId

$PolicyStatus |
    Select-Object Node, PolicyFound, PolicyID, BasePolicyID, IsOnDisk, IsEnforced |
    Format-Table -AutoSize

$MissingNodes = @(
    $PolicyStatus |
        Where-Object {
            -not $_.PolicyFound -or
            -not $_.IsOnDisk -or
            -not $_.IsEnforced
        }
)

if ($MissingNodes.Count -gt 0) {
    throw "The Checkmk supplemental policy is not active on every cluster node."
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">$PolicyPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\WDAC\Checkmk-2.5.0p12\Checkmk-Supplemental.xml&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ExpectedPolicyId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;d9c9bf97-3465-4afb-9714-b457f2341e61&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ExpectedBasePolicyId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;a6368f66-e2c9-4aa2-ab79-8743f6597683&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">$ClusterNodes </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST01&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST02&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #9ECBFF">&#39;AZLHOST03&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $PolicyPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;WDAC policy file not found: </span><span style="color: #E1E4E8">$PolicyPath</span><span style="color: #9ECBFF">&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyContent </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Get-Content</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $PolicyPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Raw</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($PolicyContent </span><span style="color: #F97583">-notmatch</span><span style="color: #E1E4E8"> &#91;</span><span style="color: #F97583">regex</span><span style="color: #E1E4E8">&#93;::Escape($ExpectedPolicyId)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;The XML does not contain the expected supplemental policy ID.&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($PolicyContent </span><span style="color: #F97583">-notmatch</span><span style="color: #E1E4E8"> &#91;</span><span style="color: #F97583">regex</span><span style="color: #E1E4E8">&#93;::Escape($ExpectedBasePolicyId)) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;The XML does not reference the expected Azure Local base policy.&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Add-ASWDACSupplementalPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Path $PolicyPath </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Verbose</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyStatus </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Invoke-Command</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ComputerName $ClusterNodes </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ScriptBlock {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">param</span><span style="color: #E1E4E8">($PolicyId)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        $CiToolPath </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Join-Path</span><span style="color: #E1E4E8"> $</span><span style="color: #79B8FF">env:</span><span style="color: #E1E4E8">SystemRoot </span><span style="color: #9ECBFF">&#39;System32\CiTool.exe&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">        $PolicyInventory </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">&amp;</span><span style="color: #E1E4E8"> $CiToolPath </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">lp </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">json </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">ConvertFrom-Json</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        $Policy </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            $PolicyInventory.Policies </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">                </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">                    (&#91;</span><span style="color: #F97583">string</span><span style="color: #E1E4E8">&#93;</span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyID).Trim(</span><span style="color: #9ECBFF">&#39;{}&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #F97583">-ieq</span><span style="color: #E1E4E8"> $PolicyId</span></span>
<span class="line"><span style="color: #E1E4E8">                }</span></span>
<span class="line"><span style="color: #E1E4E8">        ) </span><span style="color: #F97583">|</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">First </span><span style="color: #79B8FF">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">        &#91;</span><span style="color: #F97583">pscustomobject</span><span style="color: #E1E4E8">&#93;</span><span style="color: #F97583">@</span><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">            Node         </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $</span><span style="color: #79B8FF">env:</span><span style="color: #E1E4E8">COMPUTERNAME</span></span>
<span class="line"><span style="color: #E1E4E8">            PolicyFound  </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$null</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-ne</span><span style="color: #E1E4E8"> $Policy</span></span>
<span class="line"><span style="color: #E1E4E8">            PolicyID     </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.PolicyID</span></span>
<span class="line"><span style="color: #E1E4E8">            BasePolicyID </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.BasePolicyID</span></span>
<span class="line"><span style="color: #E1E4E8">            IsOnDisk     </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.IsOnDisk</span></span>
<span class="line"><span style="color: #E1E4E8">            IsEnforced   </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> $Policy.IsEnforced</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">    } </span><span style="color: #F97583">`</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">ArgumentList $ExpectedPolicyId</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$PolicyStatus </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Select-Object</span><span style="color: #E1E4E8"> Node</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyFound</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyID</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyID</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$MissingNodes </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">@</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    $PolicyStatus </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyFound </span><span style="color: #F97583">-or</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.IsOnDisk </span><span style="color: #F97583">-or</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #F97583">-not</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.IsEnforced</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> ($MissingNodes.Count </span><span style="color: #F97583">-gt</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">0</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;The Checkmk supplemental policy is not active on every cluster node.&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p class="wp-block-paragraph">For a successful deployment, the verbose output reports <code>Refreshed and activated Code Integrity policy</code> with status <code>0x0</code> for each newly updated node. The final table must show <code>PolicyFound</code>, <code>IsOnDisk</code>, and <code>IsEnforced</code> as <code>True</code> for every node. Only then should the Checkmk MSI be installed on the remaining nodes.</p>



<h2 class="wp-block-heading">7. Return to enforced mode and test the installation</h2>



<p class="wp-block-paragraph">Once the supplemental policy is present on the nodes, return the base policy to enforced mode:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Enable-AsWdacPolicy -Mode Enforced
Start-Sleep -Seconds 180

Get-AsWdacPolicyMode

Get-ASLocalWDACPolicyInfo |
    Where-Object { $_.PolicyName -eq 'Checkmk Agent Supplemental Policy' } |
    Format-List PolicyName, PolicyId, BasePolicyId, IsSignedPolicy, IsOnDisk, IsEnforced</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Enable-AsWdacPolicy</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Mode Enforced</span></span>
<span class="line"><span style="color: #79B8FF">Start-Sleep</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">Seconds </span><span style="color: #79B8FF">180</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-AsWdacPolicyMode</span></span>
<span class="line"></span>
<span class="line"><span style="color: #79B8FF">Get-ASLocalWDACPolicyInfo</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.PolicyName </span><span style="color: #F97583">-eq</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;Checkmk Agent Supplemental Policy&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-List</span><span style="color: #E1E4E8"> PolicyName</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> PolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> BasePolicyId</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsSignedPolicy</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsOnDisk</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> IsEnforced</span></span></code></pre></div>



<p class="wp-block-paragraph">Now perform the decisive test under <code>Enforced</code>: start the agent, check its status, and repeat the MSI installation on the remaining nodes. Only a successful test in enforced mode confirms that the supplemental policy is complete.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#e1e4e8;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2f363c;color:#d3d7dd">PowerShell</span><span role="button" tabindex="0" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Get-Service |
    Where-Object { $_.Name -match 'check|cmk' -or $_.DisplayName -match 'checkmk' } |
    Format-Table Status, Name, DisplayName -AutoSize

$Controller = 'C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe'
if (Test-Path -LiteralPath $Controller -PathType Leaf) {
    &amp; $Controller status
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #79B8FF">Get-Service</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Where-Object</span><span style="color: #E1E4E8"> { </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.Name </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;check|cmk&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-or</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">$_</span><span style="color: #E1E4E8">.DisplayName </span><span style="color: #F97583">-match</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;checkmk&#39;</span><span style="color: #E1E4E8"> } </span><span style="color: #F97583">|</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">Format-Table</span><span style="color: #E1E4E8"> Status</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> Name</span><span style="color: #F97583">,</span><span style="color: #E1E4E8"> DisplayName </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">AutoSize</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">$Controller </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;C:\Program Files (x86)\checkmk\service\cmk-agent-ctl.exe&#39;</span></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (</span><span style="color: #79B8FF">Test-Path</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">LiteralPath $Controller </span><span style="color: #F97583">-</span><span style="color: #E1E4E8">PathType Leaf) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">&amp;</span><span style="color: #E1E4E8"> $Controller status</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<h2 class="wp-block-heading">The result in the lab</h2>



<p class="wp-block-paragraph">In this cluster, the Azure Local base policy <code>AS_Base_Policy</code> remained active. Its policy ID was <code>a6368f66-e2c9-4aa2-ab79-8743f6597683</code>. It was supplemented by <code>Checkmk Agent Supplemental Policy</code> with policy ID <code>d9c9bf97-3465-4afb-9714-b457f2341e61</code>. The supplemental policy was reported as present on disk and enforced. The <code>check-mk-agent_2.5.0p12.msi</code> package could then be installed.</p>



<p class="wp-block-paragraph">These GUIDs document this specific lab only. New policies receive their own IDs.</p>



<h2 class="wp-block-heading">After installation: do not forget TCP/6556</h2>



<p class="wp-block-paragraph">A successful installation does not yet mean that the Checkmk server can reach the agent. The traditional Checkmk agent requires inbound TCP/6556. The installer normally creates a local firewall rule, but a suitable Group Policy rule may still be required in environments with centrally managed or restrictive firewall policies.</p>



<p class="wp-block-paragraph">In the lab, inheritance was disabled on the Azure Local OU. A firewall GPO linked higher in the hierarchy therefore did not reach the servers. The TCP/6556 rule had to be linked directly to the server OU. Checkmk could connect to the agent after that change.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">The firewall was a separate post-installation issue. It was not the reason why WDAC had previously blocked the MSI or its code.</p>
</blockquote>



<h2 class="wp-block-heading">What to consider for agent upgrades</h2>



<ul class="wp-block-list">
<li>Document the policy XML together with the corresponding Checkmk version.</li>



<li>Test new agent versions on a reference node under <code>Enforced</code> first.</li>



<li>If new block events appear, update and version the supplemental policy selectively.</li>



<li>Use audit mode only for as long as necessary.</li>



<li>Recheck the firewall GPO, OU link, and security filtering after changes.</li>
</ul>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">If an MSI installation on Azure Local appears to finish without a result, include WDAC early in the investigation. Confirm the block in the event logs, install the software under controlled audit-mode conditions, generate a supplemental policy from the narrowly scoped installation directory, and then return to <code>Enforced</code>. This preserves the Azure Local security model while allowing the Checkmk agent explicitly.</p>



<h2 class="wp-block-heading">Sources</h2>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/azure/azure-local/manage/manage-wdac?view=azloc-2608">Microsoft Learn: Manage Application Control for Azure Local</a></li>



<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/operations/event-id-explanations">Microsoft Learn: Application Control event ID explanations</a></li>



<li><a href="https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/design/deploy-multiple-appcontrol-policies">Microsoft Learn: Deploy multiple Application Control policies</a></li>



<li><a href="https://docs.checkmk.com/latest/en/agent_windows.html">Checkmk documentation: The agent for Windows</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2026/09/azure-local-und-checkmk-problem-und-loesung/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
