Contents

DSC v3.2 — Built-in Windows Resources and the Bicep Bridge


Microsoft Desired State Configuration v3.2 was released at the end of April, and unlike the usual point release, this one brings substantial changes. First-class Windows resources without the PSDSC adapter dance, an experimental Bicep ↔ DSC bridge, and a properly grown-up expression language.

If you haven’t caught up on DSC v3 yet, start with my DSC v3 primer — this post assumes you know what dsc.exe is and how a v3 configuration document is structured. For everything else that happened in PowerShell-land over the same window, see the April roundup.

The headline change is a set of native Windows resources that don’t need the PSDSC adapter sitting in front of them. If you’ve ever had to wrestle the adapter just to manage a Windows service or a firewall rule, you’ll appreciate this list:

  • Microsoft.Windows/Service — Windows services
  • Microsoft.Windows/OptionalFeatureList — Windows Optional Features (requires the ZIP package)
  • Microsoft.Windows/FeatureOnDemandList — Features on Demand (also ZIP package)
  • Microsoft.Windows/FirewallRuleList — Windows Firewall rules
  • Microsoft.OpenSSH.SSHD/sshd_config — full sshd_config management
  • Microsoft.OpenSSH.SSHD/Subsystem and Microsoft.OpenSSH.SSHD/SubsystemList — SSH subsystem entries
  • Microsoft.OpenSSH.SSHD/Windows — Windows-specific SSH server config

The OpenSSH set is particularly nice — Windows OpenSSH config has historically been a small, fiddly thing to automate well, and having dedicated resources for it removes a lot of the friction.

You’d think they’d show up the moment you install DSC — the announcement says they’re “ready to use without additional installation”. On my machine, though, none of the four appeared in dsc resource list. They are in the package; each manifest just carries a condition:

"condition": "[not(equals(tryWhich('sshd'), null()))]"

In other words: DSC only offers the OpenSSH resources when it can find sshd. No OpenSSH Server installed, no OpenSSH resources — so if they’re missing from your list, that’s the first thing to check.

This is the bit I find most interesting. DSC v3.2 ships a gRPC server that lets Bicep orchestrate DSC resources directly. The dsc-bicep-ext extension is included in the MSIX package and put on PATH for you.

What this practically unlocks: you can describe Azure resources and the in-guest configuration in the same Bicep file, with DSC handling the bit Bicep can’t see (services, registry, sshd_config, etc.). It’s still flagged experimental, and the official wording calls it “the foundation for the Bicep to DSC integration” — meaning more to come. It’s a clear signal of where the team is taking this though.

A small but useful addition: --what-if now works on dsc resource set, so you can preview what a single resource change will do without committing. The announcement demos it against the Windows service resource, and you’d think that’s the one example guaranteed to work. It took me two attempts to find out it doesn’t (yet).

First stumble: the announcement uses "startType": "disabled", and DSC rejects that outright:

ERROR Schema: "disabled" is not one of "Automatic", "AutomaticDelayedStart" or 2 other candidates

The startType values are case-sensitive and PascalCase, so it has to be Disabled:

dsc resource set --what-if --resource Microsoft.Windows/Service --input '{
    "name": "Spooler",
    "startType": "Disabled"
}'

Second stumble: with the casing fixed, 3.2.0 still refuses:

ERROR Not implemented: cannot process what-if execution type, as resource implements pre-test and does not support what-if

So dsc resource set --what-if exists, but Microsoft.Windows/Service doesn’t support it in this release. It’s a known gap — issue #1506 was opened by someone going through the very same announcement example, and a fix is already open. In the meantime, dsc config set --what-if with a configuration document that uses the same resource does work, so that’s the way to preview a service change for now.

Resource manifests can declare a whatIfReturns field for richer preview output — so authors of community resources get a way to make their --what-if story properly informative rather than a vague “something would change.”

Configuration documents now support pinning to specific DSC and resource versions using the version directive and the new requireVersion field (which replaces apiVersion). Semver constraints — which is the version pinning experience you actually want.

You’d think you could copy the announcement’s example straight in. It pins Microsoft/OSInfo to ^1.0 — but OSInfo ships as version 0.1.0, so nothing matches and the whole document fails:

ERROR Error: Resource not found: Microsoft/OSInfo ^1.0

That does at least prove the pinning works: DSC errors out when it can’t find a compatible version, rather than quietly using whatever is installed. Check the Version column in dsc resource list before pinning. The fix is a single line — pin OSInfo to ^0.1 (which, for a 0.x version, means >=0.1.0, <0.2.0):

  requireVersion: '^0.1'

With that change the same document runs fine. The full version:

$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
directives:
  version: '=3.2.0'
resources:
- name: os
  type: Microsoft/OSInfo
  requireVersion: '^0.1'
  properties: {}
- name: echo
  type: Microsoft.DSC.Debug/Echo
  requireVersion: '>=1.0.0, <1.3'
  properties:
    output: echo

The expression language has grown up a fair bit. The additions worth knowing:

  • Lambda expressions via map() and filter() — borrowed from ARM template syntax
  • dataUri() and dataUriToString() — for embedding content directly into configurations
  • reference() inside copy loops — you can now reference iterating resources properly
  • requireVersion replacing apiVersion, as mentioned above

If you’ve ever found yourself wanting to filter a collection of resources mid-configuration without resorting to PowerShell preamble code, this is the change for you. Credit where it’s due — these came largely from community contributor @Gijsreyn, who shows up multiple times in the release notes.

Two new extension types were added:

  • Import — process arbitrary files as DSC configuration documents. The example given is processing TOML files; the spirit is “bring your own format”
  • Secret — retrieve secrets at runtime via a new secret() configuration expression, so credentials don’t have to be baked into manifests

Both are practical answers to real problems people have hit when using DSC v3 for actual work.

On Windows via winget:

winget install --id 9NVTPZWRC6KQ --source msstore

Or grab the ZIP for Windows, Linux, or macOS from the PowerShell/DSC repository and drop it on PATH. The full announcement has the complete list.

The first v3.3 preview was published on 7 May, barely a week after v3.2 went GA, so the cadence isn’t slowing down.

Update (October 2026): DSC v3.3.0 went GA on 17 September 2026, and the first v3.4 preview is already out. --what-if support for Microsoft.Windows/Service arrived in v3.3 (PR #1507).

Happy configuring 😊