Configuration Drift Detection¶
A spoke is handed over to a workload team that can change what is in its subscription. That freedom is by design, but a platform team needs to see when the baseline of a spoke has moved away from its spoke file. This page records the design for a scheduled drift report per spoke, why it is built from the existing spoke pipeline, and what it can and cannot tell you.
Decision record
This is a design decision, written from an architecture decision record of the spoke canvas. It is guidance. Check that the version you run ships the drift pipeline and how it is wired in your configuration repository.
The problem¶
Nothing stops the owners of a spoke from changing the canvas resources. Contributor and Owner are given on purpose, to keep roles simple and the team flexible (Access, groups and PIM). They are not meant to be used for the canvas resources, for example to change subnets.
The platform team wants to see undesired changes. The scope is limited to what Terraform can find in its own scope.
Requirements¶
| Requirement | Consequence for the design |
|---|---|
| A report must be available historically | Store each report with its date and time in the file name |
| A report must be available and up to date | Also store the report under a fixed name that is always overwritten |
| Reports must be produced regularly | A scheduled pipeline, with the schedule in the pipeline definition |
Options¶
| Option | Remark |
|---|---|
| Clone the spoke pipeline and reuse its components (chosen) | Little to build, and it stays stable when the spoke deployment changes, because most of it is the same code |
| A function app that compares the spoke files with the deployed configuration | Needs a new component and its own logic for what "different" means |
| Analyse the activity log for unwanted changes | Shows who did what, but does not compare with the intended state |
Decision¶
Run a plan for every spoke file on a schedule and report the spokes that have changes to make. A plan that is not empty means that the real configuration differs from the spoke file. The result is written as a report to a storage account.
Consequences¶
- Minimal effort and maintenance, because the pipeline reuses the spoke deployment.
- The insight is limited. Only what appears in a Terraform plan is detected. Resources that the spoke canvas does not manage, or settings that are ignored in code, do not show up. Treat the report as an indicator and not as an audit.
- The plan can show noise that is not drift. See Known issues and Reading the spoke plans.
How it works¶
flowchart LR
t["Schedule"] --> p["Plan for every spoke file"]
p --> d["Spokes with changes?"]
d --> rep["Drift report (JSON)"]
rep --> h["Timestamped file<br/>(history)"]
rep --> l["Fixed-name file<br/>(latest)"]
h --> st[("Storage account:<br/>dedicated container")]
l --> st
| Part | Detail |
|---|---|
| Storage | A dedicated container in a storage account. A fully deployed spoke is a good place: its storage account already has private endpoints and the spoke's groups. Give the readers of the report the blob reader role on the container |
| Access | Pipeline agents need network access to the storage account (preferably through a private endpoint), and the deployment identity needs permission to write blobs. If you need network or policy exceptions for this, record them as exemptions (Governance) |
| Reports | Each run stores the same report twice: once with the date and time in the name, for history, and once under a fixed name that is overwritten, for automation |
| Schedule | A cron expression in the pipeline. Start the pipeline manually once, because a schedule cannot ask for the approval to use the agent pool |
Drift in the hub¶
The hub has no separate drift pipeline. Drift in the hub is found by running hub in Plan mode: any change that you did not
commit is drift (Monthly health check,
Operating responsibilities). A scheduled spoke drift report brings the
same idea to the spokes.
What to do with a report¶
| Finding | Action |
|---|---|
| A change that was done by hand and is wanted | Bring it into the spoke file through a pull request (Change spoke) |
| A change that was done by hand and is not wanted | Revert it. A normal spoke run restores the defined state |
| A spoke file that no longer matches the plan for an unclear reason | Check the plan noise in Known issues first |
Related¶
- Spoke canvas: what a deployment creates
- Pipelines and workflows
- Design principles and Philosophy
- Spoke drift detection: set-up and operation of the spoke drift pipeline