By the end of this you have the Azure compute security baseline assigned in audit against a pilot scope, its per-setting result read rather than its headline percentage, a deliberate choice between visible drift and silent auto-correction, the machines that were already adrift remediated in a change window, and the meter and its waivers confirmed before you widen it. This lands the two decisions the doctrine article said you could not avoid, and it names the real policy, the real modes, and the real commands so you can reproduce it. The portal walk comes first, then the same thing as a script.
Before Step 1: Arc-connected machines (the machine configuration agent ships inside the Connected Machine agent, so there is nothing to install), rights to assign Azure Policy at your chosen scope and to create a remediation task, and a pilot resource group or a tag you can scope to. The name to know throughout is Azure machine configuration, which is what guest configuration is now called.
Step 1: Assign the built-in baseline in audit, at a pilot scope
Start in audit every time, because you want to see what the baseline would flag before anything changes. In Azure Policy, open Definitions, filter to the Guest Configuration category, and find the built-in policy named “Windows machines should meet requirements of the Azure compute security baseline”, definition ID 72650e9f-97bc-4b2a-ab5f-9781a9fcecbc. Search by the ID rather than the name, because a preview initiative with an almost identical name (“[Preview]: Windows machines should meet requirements for the Azure compute security baseline”) sits next to it and is not what you want. Assign it scoped to your pilot resource group. On the Parameters tab, clear “Only show parameters that need input or review” and set Include Arc connected servers to true. It defaults to false, and if you leave it there the assignment only looks at Azure VMs, so a resource group full of Arc servers reports nothing at all. This definition is AuditIfNotExists, so it reports compliance and changes nothing. Leave it reporting and collect the truth about your current state.
| Setting | Value | Why |
|---|---|---|
| Definition | Windows machines should meet requirements of the Azure compute security baseline (72650e9f-97bc-4b2a-ab5f-9781a9fcecbc) | A built-in, maintained for you. Author a custom package only when no built-in fits. |
| Include Arc connected servers | true | The parameter defaults to false. Leave it and the assignment never evaluates an Arc machine. |
| Scope | The pilot resource group, not a management group | A management group reaches every server beneath it. Prove the baseline small before you widen it. |
| Effect | AuditIfNotExists | Reports compliant or not and changes nothing, so you see the blast radius before you accept it. |
If the default baseline would flag something you have deliberately accepted, customize it before you assign. Under Policy, Machine Configuration, Definitions, pick Azure Security Baseline for Windows and use Modify settings to exclude or adjust individual rules. The settings carry straight into the assignment and land in the same definition’s Baseline Settings parameter, and you can export them as JSON for source control. Later you change a live assignment with Edit Settings instead of rebuilding it.
The same as a script. You assign the built-in definition to the pilot resource group by its definition id:
az policy assignment create \
--name "MC-ComputeBaseline-Pilot" \
--display-name "Windows compute security baseline (audit, pilot)" \
--policy "72650e9f-97bc-4b2a-ab5f-9781a9fcecbc" \
--params '{ "IncludeArcMachines": { "value": "true" } }' \
--scope "/subscriptions/<sub-id>/resourceGroups/rg-arc-servers-pilot"
Expected result: the assignment appears and, after the first evaluation, the pilot machines report compliant or not against each setting. Failure mode: assigning at a management group “to cover everything” reaches your whole estate at once, which is the opposite of a pilot. On Arc there is nothing else to install, because the machine configuration agent is part of the Connected Machine agent already.
Step 2: Read the per-setting result, and expect lag
Give it time before you trust the number. The in-guest service requests its assignment list every five minutes, and the compliance rollup you see can trail the real state, so a machine that reads non-compliant for a few minutes after assignment is normal, not broken. Read the per-setting detail in the compliance view, not just the headline percentage, because that detail is where you learn which controls will actually change something when you move to enforcement. A baseline that flags forty settings you already meet is a different decision from one that flags three you do not.
Step 3: Promote to enforcement, and make the drift decision
The built-in definition you assigned in Step 1 only audits. Its effect is AuditIfNotExists and it has no apply mode. The customizable security baseline that went generally available at the end of May 2026 does not change that. It lets you include or exclude rules and edit expected values, but those edits feed a parameter on the same audit definition, so you still get a sharper audit and nothing more. Enforcement through Azure Policy on Windows Arc servers today means a custom machine configuration package. You build it from the settings the audit told you matter, package it as AuditAndSet, and generate a DeployIfNotExists definition from it with the GuestConfiguration module. That definition is the one that carries an apply mode. This is the moment the doctrine article warned about, because the mode you choose decides whether you can prove drift happened later. Choose it per baseline, deliberately, and record why.
| Mode | Behavior | Choose it when |
|---|---|---|
| Audit | Reports state, makes no change | You are still assessing, or something else owns enforcement |
| ApplyAndMonitor | Applies once, then reports drift without correcting it. Drift stays visible and is only fixed by a remediation run. | You need drift visible for audit or investigation more than you need it auto-healed |
| ApplyAndAutoCorrect | Re-asserts state at every evaluation and reports Compliant unless an error occurs. Machine configuration has no record that a drift was corrected, so you cannot show that the machine was ever wrong, let alone for how long. | Continuous enforcement matters more than a timestamped drift trail |
Keep two effects straight, because it is the easiest thing to get wrong here. The baseline you assigned in Step 1 is AuditIfNotExists, which only reports. The definitions that push changes inside the machine use the DeployIfNotExists effect, and that is also what the remediation path in the next step runs on. Auditing and enforcing are different definitions, not a toggle on one. The customizable baseline makes the audit fit your estate. It does not enforce anything. The enforcing definition is one you generate from a custom package, and you can run it alongside the Step 1 audit assignment as long as the two describe the same expected values.
Step 4: Remediate the machines that were already adrift
A machine that comes online after the enforcing assignment is in place is brought into line by the normal evaluation cycle. A machine that already existed and was already non-compliant does not self-heal from the assignment alone; it needs a remediation task run once against it. In the portal, open the assignment’s Remediation tab and create a remediation task. It runs under the system-assigned managed identity that belongs to the policy assignment itself, the one created and granted a role when you set up the enforcing assignment, not the identity of the machine, which is why a DeployIfNotExists assignment must be created with an identity and the correct role. Run the task deliberately, in a change window, because for these machines this is the moment state actually changes.
az policy remediation create \
--name "remediate-compute-baseline-pilot" \
--policy-assignment "MC-ComputeBaselineEnforce-Pilot" \
--resource-group "rg-arc-servers-pilot"
Expected result: the pre-existing machines move to compliant after the task completes, and the in-guest agent maintains the state going forward. Failure mode: if the assignment was created from the CLI or a template and nobody granted its managed identity the role the definition asks for, the remediation deployments fail and the machines stay adrift. The portal grants that role for you. The CLI does not unless you pass --role and --identity-scope, so check the remediation task’s deployment results, not just whether it finished.
Step 5: Confirm the meter and its waivers
Before you widen the scope to the fleet, know what it costs. Machine configuration bills at roughly six dollars per server per month, on a combined meter with change tracking and inventory, and that charge is waived under conditions worth checking against your estate rather than assuming.
| Situation | Machine configuration charge |
|---|---|
| Plain Arc machine, no qualifying licensing | Billed on the combined per-server meter, about six dollars per server per month |
| Windows Server with active Software Assurance or subscription licenses, attested | Waived under Windows Server Management enabled by Azure Arc |
| Windows Server pay-as-you-go enabled by Azure Arc | Waived. Enrollment counts, no separate attestation needed |
| Defender for Servers Plan 2 enabled on the subscription | Included at no additional cost |
| Machine enrolled in Extended Security Updates through Arc | Included for the enrolled machine |
| Machine enrolled through Essential Machine Management (preview) | Billed on that bundle’s own per-server meter unless SA, pay-as-you-go, ESU or Defender for Servers Plan 2 covers it. Check which meter you are actually on before you compare costs |
A worked example
Take a pilot of three Windows file servers that carry Software Assurance. You assign “Windows machines should meet requirements of the Azure compute security baseline” to rg-arc-servers-pilot in audit, and reading the per-setting result you see the baseline would tighten SMB signing and disable a legacy protocol the application team still relies on. Because you need that change to be visible and reversible rather than silently healed, you first customize the audit baseline to exclude the legacy protocol rule the application team still needs, then stand up an enforcing assignment from a custom package that carries only the SMB signing setting, in ApplyAndMonitor rather than ApplyAndAutoCorrect. The three servers predate that enforcing assignment, so you run a remediation task against it during Saturday’s window and confirm they move to compliant. The meter reads zero for them, because they are attested under Windows Server Management enabled by Azure Arc, so widening to the rest of the file-server fleet adds settings governance at no new cost. Every choice here was a decision you can defend, not a default you accepted.
Naming convention
Name assignments so a compliance dashboard reads cleanly at a glance. Use a prefix and purpose, for example MC-ComputeBaseline-Pilot and later MC-ComputeBaseline-Prod, and keep the same scheme across every baseline you assign. Scope pilots by a dedicated resource group or a Stage=Pilot tag so promotion to production is a scope change, not a new invention. Consistent assignment names are what let you read fleet compliance by baseline rather than by hunting through a list.
The end-to-end test
Prove the enforcement path on one machine before you trust it across the fleet. On a test server carrying the enforced baseline, deliberately change one governed setting out of compliance, then wait for the next evaluation. If you chose ApplyAndMonitor, the machine should report the drift and leave it for you. If you chose ApplyAndAutoCorrect, the setting should return to its enforced value on its own within an evaluation cycle. Seeing the mode behave exactly as designed on a setting you broke on purpose is the difference between believing the baseline works and knowing it does.
Rolling it back
This is the rollback with the sharpest caveat in the series, so read the caveat before the steps: removing an assignment stops future enforcement, it does not revert settings already applied to a machine. A baseline you enforced and then rolled back leaves the machine configured the way the baseline wanted it. If you need the previous state back, you need a deliberate change, not a deletion.
- Delete the remediation task first, so nothing is mid-flight while you remove what it targets:
az policy remediation delete --name "remediate-compute-baseline-pilot" --resource-group "rg-arc-servers-pilot". - Remove the enforcing DeployIfNotExists assignment:
az policy assignment delete --name "MC-ComputeBaselineEnforce-Pilot" --resource-group "rg-arc-servers-pilot". Deleting the assignment deletes its system-assigned identity, but not the role assignment that identity held. That role assignment stays on the scope as “Identity not found”, so remove it rather than leave a dangling privileged grant in your IAM blade. - Check the machine’s Guest assignments for anything the enforcing policy left behind. Deleting a policy assignment deletes the guest assignments it created, but if you delivered the baseline inside an initiative and removed it from that initiative, or created a guest assignment by template, you delete those by hand. A leftover guest assignment keeps reporting on a baseline nobody owns anymore.
- Remove the audit assignment, for example
MC-ComputeBaseline-Pilot, once you no longer want the compliance reporting either. Keeping audit while dropping enforce is a perfectly reasonable half-rollback, and often the right one. - Confirm the settings on one machine by hand and decide explicitly whether to leave them. This is the step people skip, and it is the only one that tells you what your estate is actually configured like now.
- Check the meter, because machine configuration bills on a combined per-server meter with change tracking and inventory. If change tracking arrived alongside this baseline and you leave it running, the charge does not go away just because the baseline did.
Before you widen the scope
- Baseline assigned in audit first, at a pilot scope, with the per-setting result read before enforcing.
- Enforcement mode chosen per baseline, with the drift-visibility trade recorded, not defaulted, and the AuditIfNotExists-versus-DeployIfNotExists distinction kept straight: the customizable baseline audits, and only a custom package enforces.
- Remediation task run for pre-existing non-compliant machines in a change window, with the managed identity confirmed so it actually changes state.
- Meter confirmed, and any waiver (Software Assurance attestation, Defender Plan 2, ESU enrollment) verified against the real machines.
- End-to-end test passed: a deliberately broken setting was caught or corrected exactly as the chosen mode dictates.
- Any Windows Server 2025 machine whose role changes, for example a member server promoted to a domain controller, has its baseline assignment deleted and reapplied, because the platform does not pick up the role change on its own.
With settings under control, the other half of what the domain did for a server comes next: keeping it patched. The following article takes up Azure Update Manager and the WSUS story it is written to replace.
Azure Arc
‹ Previous: [ARC 3] Policy and Machine Configuration: The GPO Question, Answered Honestly
Next: [ARC 4] Update Manager: Patching After WSUS ›




