Module 00 · Orientation · 25 min · You are: Platform team
Orientation
In this module
- You learn: Map the delivery path and name the seven surfaces before changing them.
- You do: Create the learner repo, inspect the seeded app and workflows, and open docs/attack-surface.yaml.
- You end with: A running local checkout service, a connected public repository, and seven open surface entries.
An unfamiliar platform can hide trust between source, workflow, build and runtime. Start with the path and the capability at each boundary.
Open this module in the interactive course to track progress.
Change journey practised: Surface → Test → Measure → Prove
Concepts
- Surface: repo and workflows
- A surface is a point where data crosses a trust boundary.
- Trust boundary
- A capability is permission to change code, publish an artifact, or reach data.
- Evidence
- Orientation: a label is not evidence
Files to know
Open them in your editor or on GitHub; the bullets say what to look at.
start/.github/workflows/ci.yml(reference): Course reference file for this surface.- This is the control or seeded condition examined in this module. L6
start/docs/attack-surface.yaml(reference): The small lab fixture used for a bounded test.- This fixture makes the trust assumption visible. L1
Steps
1. Check your tools
Paste this into a terminal. Install each missing tool and confirm Docker is running before creating a local cluster.
check() { if ! command -v "$1" >/dev/null 2>&1; then printf 'MISSING %s: %s\n' "$1" "$5"; bad=$((bad+1)); elif ! eval "$2" >/dev/null 2>&1; then printf 'PROBLEM %s: %s\n' "$1" "$4"; bad=$((bad+1)); else printf 'ok %s %s\n' "$1" "$(eval "$3" 2>&1 | head -n 1)"; fi; }
bad=0
check 'git' 'git --version' 'git --version' 'installed but not usable' 'https://git-scm.com/downloads'
check 'node' 'node --version' 'node --version' 'installed but not usable' 'https://nodejs.org/en/download'
check 'npm' 'npm --version' 'npm --version' 'installed but not usable' 'https://nodejs.org/en/download'
check 'docker' 'docker info' "docker version --format '{{.Server.Version}}'" 'installed, but the Docker daemon is not running' 'https://docs.docker.com/get-docker/'
check 'kind' 'kind version' 'kind version' 'installed but not usable' 'https://kind.sigs.k8s.io/docs/user/quick-start/'
check 'kubectl' 'kubectl version --client' 'kubectl version --client' 'installed but not usable' 'https://kubernetes.io/docs/tasks/tools/'
check 'gh' 'gh auth status' 'gh --version' 'installed, but not logged in: run gh auth login' 'https://cli.github.com/'
check 'gitleaks' 'gitleaks version' 'gitleaks version' 'installed but not usable' 'https://github.com/gitleaks/gitleaks#installing'
check 'zizmor' 'zizmor --version' 'zizmor --version' 'installed but not usable' 'https://docs.zizmor.sh/installation/'
check 'trivy' 'trivy --version' 'trivy --version' 'installed but not usable' 'https://aquasecurity.github.io/trivy/latest/getting-started/installation/'
check 'cosign' 'cosign version' 'cosign version' 'installed but not usable' 'https://docs.sigstore.dev/cosign/system_config/installation/'
check 'kyverno' 'kyverno version' 'kyverno version' 'installed but not usable' 'https://kyverno.io/docs/installation/'
[ "$bad" -eq 0 ] && echo 'All set' || echo "$bad tool(s) need attention"
2. Create your own public lab repository
The course needs issue and pull request events. Create a public repository under your own GitHub login, then copy the contents of start/ from the reference repo into its root. Do not add a real credential.
gh repo create YOUR_GITHUB_USER/devsecops-lab --public --clone
3. Copy the seeded start state
Clone the PlatformEngr reference repo beside your new repo. Copy only start/ into your repo root, add the learner code from /me, and push. This is your owned target for every exercise.
git clone https://github.com/platformengr/devsecops-lab devsecops-lab-reference && cp -R devsecops-lab-reference/start/. devsecops-lab/ && cd devsecops-lab && git add -A && git commit -m "Start DevSecOps lab" && git push -u origin main
4. Surface: map the seven doors
Read the seven entries in docs/attack-surface.yaml and fill docs/attacker-notebook.yaml with your objective, entry, trust assumption, cheapest path, pivot and expected signal before running the first test.
cd devsecops-lab && ./scripts/validate.sh
Simplified for the workshop
The reference repository is a local learning fixture. Canaries, package publishing and service endpoints are disposable and do not grant access to a real account.
The checks read repository files as data. They do not run learner scripts or install dependencies.
Break it on purpose: Evidence is a repeatable test result tied to an owner, commit and retest.
A teammate makes a small change to save time. Work out which trust assumption it changes before you run the test.
You practise: You practise tracing the cheapest path from an input to a capability and identifying an independent control.
1. Break it
cd devsecops-lab && git diff -- .github/ docs/
2. What you see
Expected: the proof is stopped at the intended boundary. You get a successful path or missing evidence. Read the workflow log and the register entry.
3. Fix it yourself
Restore the intended boundary and rerun the same test. Done when the unsafe path is refused, the evidence is recorded and the files pass the repository validator.
Hint 1
Name who controls the input and what privilege consumes it.
Hint 2
Follow the input to the first capability and remove that trust or privilege.
The fix
Use the test and the exact policy file named above; do not add a blanket permission.
cd devsecops-lab && ./scripts/validate.sh
After you fixed it: the five questions
- What failed?
- A trust boundary allowed untrusted input to reach a useful capability.
- How was it detected?
- The predicted result and observed log did not match; preserve the commit and workflow run as evidence.
- Who responds?
- The owner listed for this surface in docs/attack-surface.yaml.
- How is it corrected?
- Close the specific boundary and repeat the original test.
- How is it prevented?
- Keep a parse-only lab check and a review rule on the owning files.
Quiz
- Which question best identifies the cheapest path?
- Which accepted input reaches the most useful capability with the fewest prerequisites?
- Which scanner has the most findings?
- Which team owns the largest number of files?
- What does a passing signature prove?
- The named identity signed these bytes.
- The source code is harmless.
- The image has no known vulnerabilities.
- When is a surface covered?
- The same bounded test is refused and evidence names the control and owner.
- A scanner has no critical findings.
- A policy file exists in the repository.
Answers
- Which accepted input reaches the most useful capability with the fewest prerequisites? Attack paths follow trust and capability, not tool counts.
- The named identity signed these bytes. Signatures bind identity and bytes, not safety.
- The same bounded test is refused and evidence names the control and owner. Presence is not proof; retest the attack path.
Field note
I ask learners to write the expected signal before they run a test. It makes a control failure easier to tell from a test that never reached the boundary.