Turning compliance controls into alerts that page someone
A government-cloud environment had its vulnerability posture sitting in a scanner's dashboards that someone was supposed to look at. I rebuilt those views in Splunk, then kept going — because a dashboard nobody opens on a Tuesday is not a control.
- Where
- Deltek, on a consulting engagement via SP6
- When
- 2021
- Role
- Detection and dashboard build
- Stack
- Splunk, Qualys, ServiceNow
The situation
The environment was in scope for a federal compliance regime, which meant a written set of continuous-monitoring controls: scan everything on this cadence, remediate criticals within this window, keep unauthenticated scans below this share of the total, and so on.
All the underlying data existed. The vulnerability scanner had good dashboards and they were accurate. The problem was that satisfying a control depended on a person remembering to go and look, and then remembering what normal looked like when they got there. That works right up until the week it doesn’t, and an audit is precisely the exercise of finding that week.
The ask, initially, was to replicate the scanner’s dashboards in Splunk so the data lived alongside everything else.
Replication first, and it wasn’t enough
I did the replication. Rebuilt the vulnerability views, the asset coverage views, the port and protocol inventories. Along the way I put in base searches so the panels shared work instead of each running its own scan of the data, and re-accelerated the data models so the dashboards would hold up over the longer time ranges the compliance windows actually needed.
But sitting in the review meetings, the same question kept coming up in different forms, and it was never about the visualisation. It was who gets told, and what are they supposed to do about it?
That’s the real finding from this project. Every control in the document decomposed into the same four parts, and only three of them were technical:
- a search that expresses the control,
- a baseline of what normal is,
- a threshold that says when to care, and
- an owner who receives it.
The owner is the part everyone forgets, and it’s the part that decides whether any of the rest matters.
What I built
Port baselining with change detection
Rather than a panel showing currently-open ports, I inventoried ports, services, and protocols, classified them by range — system, user, dynamic — and snapshotted that as a baseline. From then on the alert fires on change, not on state.
If the count of open user ports moves, a ticket opens automatically, and a human confirms the change went through the approved change-control process. If it didn’t, security has a real lead. This inverts the work: instead of someone auditing a list periodically and hoping to spot a difference, the system notices the difference and asks a person one specific question.
Weak-protocol and cipher detection
The scanner already flagged deprecated TLS versions and weak ciphers in red on a dashboard. I turned each of those conditions into a detection that opened a ticket, so “red on a dashboard” became “assigned to a queue with a clock on it.”
Scan-freshness thresholds
Several controls were fundamentally about coverage rather than findings — a host that hasn’t been scanned in too long is a gap regardless of what its last scan said. Those became straightforward age-based alerts.
The subtler one was tracking unauthenticated scans as a proportion of the total. The scanner marks a scan unauthenticated when it can’t determine the OS or log in, and the control capped what share of scans could be in that state. The naive version of that alert is useless, because a stable set of hosts can never authenticate by design and they’d pin the metric permanently over threshold. Getting it right meant accounting for that known population so the alert only fired on genuine drift.
Routing into the ticketing system, not into email
Alerts opened incidents in ServiceNow rather than sending mail. Email has no owner, no state, and no SLA — three things a compliance control needs and an inbox cannot provide. Letting the ticketing system handle notification also meant Splunk only had to do the part it was good at.
A compliance control is an alert nobody has written yet. Read the control document as a detection backlog and most of it translates directly — the hard part isn’t the search, it’s establishing the baseline and finding out who owns the response.
Where it landed
- Continuous-monitoring controls moved from periodic manual review to automated detection with tickets attached.
- Port, protocol, and service changes surfaced within a scan cycle instead of at the next audit.
- Dashboards performed over compliance-length time ranges rather than timing out on them.
- The organisation had, for the first time, a written mapping from each control to the specific alert satisfying it — which turned out to be as useful to the auditors as the alerts themselves.
What I’d do differently
I’d settle ownership before building a single detection. I built several alerts that were technically correct and then sat unrouted while we worked out which team should receive them, and an alert with no owner is just a more-expensive dashboard. The right sequence is to agree the owner first and let that shape the threshold — because how noisy an alert is allowed to be depends entirely on who has to read it.
This describes the approach, not the environment. The specific control identifiers, the findings themselves, host and asset counts, scanner configuration, and the teams involved are all left out — a former employer’s security posture isn’t mine to publish, and the transferable part is the method anyway.