Back to path
AdvancedLedgerline · Project 9 of 12 ~6h· 5 milestones

Encode the rules as policy that blocks bad config

Continues from the last build: Images are signed, attested and verified before they run, and the pipeline is pinned and least-privilege.

Every rule you have earned so far, non-root containers, pinned actions, least-privilege tokens, signed images, lives in your head, in a README, and in the memory of whoever wrote the fix.

Rego policy authoringConftest / OPApolicy as codeCI pipeline gatingGitHub Actions security configunit testing policy codeexception managementOWASP CI/CD Top 10 mapping

What you'll build

A conftest policy suite in security/policy gates the Dockerfile and GitHub Actions workflows on every PR, failing the build on real violations (root user, floating tags, missing permissions blocks) while warning on softer issues, with a documented exception process for the rare justified case. The Rego itself has unit tests with pass and fail fixtures, and a security baseline doc maps every rule to the OWASP CI/CD Top 10 category it enforces, so humans and machines agree on what "secure enough" means.

See how we teach, before you sign up

You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:

security/policy/docker/docker.regorego
package main

deny[msg] {
	input[i].Cmd == "user"
	val := input[i].Value[0]
	val == "root"
	msg := "Dockerfile runs as USER root; switch to a non-root user (CWE-250)"
}

# Intentionally incomplete: add a second deny rule here for the
# case where there is no USER instruction in the Dockerfile at all.

Reading this file

  • input[i].Cmd == "user"the parsed Dockerfile instruction array, index i walks every instruction
  • val == "root"only fires on an explicit USER root, not on a missing USER instruction, that gap is what the learner fills
  • Intentionally incompletemarks exactly what milestone 1 asks the learner to add

Starts with only the explicit-root check. The learner adds the missing-USER-instruction rule in milestone 1.

That's 1 of 8 explained code blocks in this single project.

The build, milestone by milestone

  1. 1

    Write Rego policies for the Dockerfile and the workflow YAML

    5 guided steps

    A README says "don't run as root" and "pin your actions", but nothing stops a PR that ignores it. Conftest parses the Dockerfile and the workflow YAML into structured data and lets you write deny rules against that structure in Rego, the same policy language OPA uses everywhere else. Once the rule exists as code, it applies to every future PR automatically, not just the ones a reviewer happens to read carefully.

  2. 2

    Gate the Dockerfile and workflow policies in CI

    5 guided steps

    A policy that only runs on your laptop protects nothing, the next contributor never runs it. It has to live in the same pipeline that already blocks on failing tests, so a violation is a red X on the PR before a human ever has to notice it by eye.

  3. 3

    Choose guardrails over gates where an outright block would backfire

    5 guided steps

    If every rule is a hard deny, the first time a legitimate release is blocked by an edge case, someone disables the whole check to ship, and you lose enforcement on everything, not just the one rule that was wrong. Warn rules keep visibility without that pressure, and a written exception process with an owner and an expiry date handles the genuine edge cases without anyone reaching for --no-verify.

  4. 4

    Test the Rego policies with pass and fail fixtures

    5 guided steps

    Policy is code, and code without tests regresses silently. If someone tweaks the root-user rule to fix a false positive and accidentally breaks the case it was meant to catch, only a test fixture with a known-bad input will catch that before it ships to the real gate.

  5. 5

    Write the security baseline doc the policies enforce

    5 guided steps

    A green pipeline is not the same thing as a documented standard. The Rego is the enforcement, but nobody onboarding to the team should have to read Rego to find out what "secure" means here. The baseline doc is the plain-English contract the policy code is a mechanical translation of, and it is what you hand a new hire or an auditor.

What's inside when you start

3 starter files, ready to clone
5 guided milestones
5 full reference solutions
8 code blocks explained line-by-line
5 "is it working?" checks
6 interview questions it prepares you for

You'll walk away with

security/policy/docker/docker.rego and docker_test.rego enforcing non-root containers and a modern base image tag
security/policy/workflow/workflow.rego and workflow_test.rego enforcing pinned actions and a least-privilege permissions block
a policy-gate job in ci.yml that fails the build on any deny result, proven against a deliberately bad PR
security/policy-exceptions.yml with a working expiry check, gated by CODEOWNERS review
security/baseline.md mapping every enforced rule to its OWASP CI/CD Top 10 category
a passing conftest verify run for both policy packages

This is portfolio-grade. Build it free.

Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.

Start building