Security & Identity

DevSecOps

Security built into the merge path, not bolted on after - lint, secret, and vulnerability scanning as required checks, so unsafe change cannot reach main.

What it is & why I use it

DevSecOps in AutomationLab means the security checks live in the pull-request gate, next to the linters and tests, rather than in a periodic scan someone reviews later. Every change to main goes through branch protection with a set of required checks - and if a security check fails, the merge does not happen.

I do it this way because security that runs after merge is security that finds problems already shipped. Moving the checks left, onto the branch, turns "we found a vulnerability in production" into "the PR could not merge until it was fixed" - a far cheaper place to catch things.

How I use it in the lab

  • Secret scanning. Every change is scanned for committed credentials before it can merge, so a leaked token is caught at the gate rather than discovered later.
  • Vulnerability scanning. Built container images are scanned for known CVEs, so a base image dragging in a critical vulnerability is visible before it is deployed.
  • Config and IaC linting. YAML, Ansible, and Terraform are linted as checks, so malformed or unsafe declarations fail fast instead of at apply time.
  • Required, not advisory. These run as required status checks under branch protection - a red check blocks the merge; they are gates, not suggestions.

Architecture

Diagram coming Merge path: PR -> lint + secret scan + image scan (required checks) -> branch protection -> merge to main. A failed check blocks the merge. Scrubbed of hostnames and addresses.

In action

Screenshot coming A pull request with the security checks reporting status and the merge button blocked on a failing gate. Captured per the publishing checklist - repo detail and any findings redacted.

Lessons learned & gotchas

Gotcha - a caught secret is already burned; rotate it When the secret scanner flags a credential that was committed, deleting the line is not the fix - it is barely half of it. Anything that reached git history has to be assumed compromised, because history is distributed, cloned, and effectively permanent; removing it from the current tree does nothing about every copy that already exists. The real remediation is to rotate the secret so the exposed value is worthless, and only then clean up the reference. Treat "the scanner caught it before merge" as a save, and "it was ever committed at all" as a rotate-now event.
  • Required beats scheduled. A scan that runs nightly finds yesterday's problem in production. The same scan as a required PR check finds it before it exists downstream - same tool, completely different value.
  • Not every vulnerability is instantly fixable - decide deliberately. A base image can carry a CVE with no patched version yet. The check surfacing it is correct; the judgement is whether to wait, swap the base, or accept and track it - explicitly, not by silently muting the scanner.
  • Keep secrets out of the repo entirely. The cleanest way to pass secret scanning is to have no secrets to find - they belong in the secrets manager, fetched at run time, never committed in the first place.

Impact

Left
shift: checks on the PR
Block
merge on a red gate
Rotate
not just delete

DevSecOps is what keeps the lab's "everything is a reviewed PR" discipline from being only about correctness - it makes it about safety too. The rotate-not-delete lesson is the one I would want any team to internalize: once a secret has touched version control it is spent, and the only honest response is to make the leaked value useless.

Code & further reading

Published CI configuration is scrubbed of hostnames, addresses, and any real finding detail before it goes public.