The part services.msc never did

Snapshots and drift

Every other tool tells you what a machine looks like now. The question an administrator actually has is what is different from when it worked - and nothing on a stock Windows answers it.

What a snapshot holds

The whole machine at one moment: every service and driver, with its start type, account, launch path and arguments, the hash and the signer of the file it runs, its dependencies and what depends on it, its triggers, its required privileges, its SID type and its security descriptor - plus the name of the machine, the account that took it, and whether that account was an administrator.

bws snapshot create before.json --note "before the patch"

It is JSON with one field per line. That is deliberate: it means a snapshot goes into a repository and git diff reads it, so the tool's own comparison is not the only way to look at one.

File it like what it is. A snapshot describes the whole machine, down to every launch path and security descriptor. It is written with whatever permissions its directory already has, and the tool narrows nothing - so a directory other people can read is one they can read all of that in.

Then ask what is different

$ bws snapshot diff before.json --live --exit-code
Changed (2):
  Spooler  Print Spooler
    startType: Manual -> Automatic
    status: Stopped -> Running  (running state, not configuration)
  wlidsvc  Microsoft Account Sign-in Assistant
    status: Stopped -> Running  (running state, not configuration)

Added 0, removed 0, changed 2. Fields differing: 1 in configuration, 2 in running state.
  • Configuration and running state are reported apart. Two snapshots taken a day apart differ in what happens to be running, and almost none of that is drift. Mixed together, the one line that matters - a start type somebody changed - is buried under forty that do not.
  • What could not be compared is listed, not hidden. A field one of the two snapshots never read, because that session had no rights to it, comes out as not compared under its entry, and the summary counts those entries. So a diff that says nothing changed means nothing changed in what both sides could see.
  • An elevated snapshot against an unelevated one would lie, reporting entries as removed that nobody removed. Each file records whether the account that took it was an administrator, and the comparison says so.
  • Two files, not just a file and this machine. Take one on staging and one on production and diff them anywhere - the answer to why does staging differ does not need either machine present.

The exit code is the point

--exit-code ends with 5 when anything differs. Not a failure - drift is what this tool is for finding, and finding it is not a failure - which is why it has a number of its own rather than borrowing the one that means something went wrong.

# the day the machine goes into service
bws snapshot create C:\baselines\web01.json --note "after the build"

# every night, from a scheduled task
bws snapshot diff C:\baselines\web01.json --live --exit-code --json > C:\logs\drift.json
#   0 - nothing differs
#   5 - something differs, and drift.json says what
#   3 - it ran and could not read everything, so the answer is partial

That is the whole mechanism: a baseline taken when the machine was known good, and a question asked every night. The first night it answers 5, somebody finds out on the first night rather than on the morning something breaks.

What this does not do yet

The second half of the audit story is not built, and saying so is cheaper than somebody discovering it.

  • Snapshots are on the command line only. The window shows, searches and changes, and it does not take or compare them.
  • No change journal. Who changed a start type, and when, is not read from the event log. A snapshot at deployment and a diff against the machine answer what changed, which is most of the question.
  • No stock Windows baseline. How many of these are not from a clean install is not counted yet, and the opening screen says so rather than showing a number it cannot stand behind.
  • No restore. A diff tells you what drifted, and putting it back is by hand or by script from the commands the diff shows you.
Using this for an audit