See the Attack Surface – Threat Modeling & Control Mapping
Duration: ~20 minutes
Overview
Work this module last in the 201 series. The control map should use RBAC, SCC, secrets, pipelines, audit, compliance, admission, mTLS, and isolation labs you already ran—not a blank cluster.
This is a walkthrough, not a build: you map STRIDE threats to OpenShift controls you already practiced, then see how an enterprise applies the same row at fleet scale (the 301 series). You do not create empty projects as visual aids.
Why it matters
Designing security without a threat model is like installing locks, cameras, and safes randomly in a new office tower—expensive and still full of blind spots. A compact model acts as the floor plan: you know where valuables sit, which doors are public, and which hallways connect sensitive rooms. Business outcome: money and time focus on the riskiest failure paths first; audit narratives become “why” stories, not scattered spreadsheets; incident responders already know likely pivot routes. Most high-impact improvements are ordinary: remove a wildcard Role, add default-deny NetworkPolicy, enforce image signatures. Ordinary, but chosen with intent.
What does it solve
Without modeling, teams drift into:
-
Reactive, ticket-whack hardening (“fix whatever the scanner yells at today”)
-
Lateral movement oversight (frontend quietly reaches database pods)
-
Everything labeled “critical,” so nothing truly is
-
Re-litigated design debates (no shared artifact of prior reasoning)
With a model:
-
Shared vocabulary: assets, boundaries, flows, threats
-
Traceability: every control defends an identified path
-
Faster audits: reviewers see risk rationale, not guesswork
-
Focused backlog: sequence of high leverage, low regret steps
Your Mission
Walk the STRIDE table. For each row, confirm you can name the 101/201 lab that practiced the control and the 301 lab that scales it. Click a step only if you need a hint.
Data flow (keep it small)
Browser → Route (TLS) → frontend → backend API → database; CI → registry → cluster.
Assets on that path: source, images, secrets, the database, CI credentials, the Kubernetes API. Trust boundaries: internet-to-Route, frontend-to-backend, CI-to-cluster, process-to-node.
STRIDE control map
This table is the 201 capstone. 301 is how you apply the same row when one wiki page cannot reach every cluster.
| STRIDE | Typical OpenShift threat | Primary controls | You already practiced | At enterprise scale |
|---|---|---|---|---|
Spoofing |
Stolen or long-lived service account token |
Bound tokens, short TTL, tight RBAC, |
301-08 SPIFFE; 301-01 Policy that forbids automount / over-broad Roles |
|
Tampering |
Unsigned or vulnerable image admitted |
Signing, ACS/Quay admission, digest pin, approved base images |
301-02 GitOps of a Red Hat catalog Python image; 301-06 SBOM / attest / admit |
|
Repudiation |
RBAC or SCC change with no durable trail |
API audit + off-cluster forward (CIS 1.2.21 / 3.2.1) |
301-05 Splunk hunt; Git history of policy in 301-02 |
|
Information disclosure |
Secrets in env / etcd plaintext / open east-west |
External secrets, etcd |
||
Denial of service |
Unbounded pods / noisy neighbor |
Quota, LimitRange, PDB, taints |
301-01 musthave Quota/LimitRange Policy |
|
Elevation of privilege |
Privileged, |
|
301-04 ACS kill-on-violation; 301-01 PSA restricted Policy |
Lateral movement sits on Tampering + Information disclosure for east-west traffic. Tenant NetworkPolicy is 101-05. Platform-owned AdminNetworkPolicy is 301-03 so a project admin cannot leave the front door open.
Confirm you are still on the same cluster
No new projects. This is a sanity check before you treat the table as “done.”
oc whoami
oc project
You should still be lab-user (or cluster-admin) on the roadshow cluster. If this fails, fix login before 301.
|
How an enterprise applies the map
One threat → one control → one delivery mechanism. Wikis do not scale; these do:
| Delivery | What it ships | Lab |
|---|---|---|
RHACM Policy / PolicySet |
Namespace PSA, Quota, NetworkPolicy, SA automount — inform then enforce across a ClusterSet |
|
GitOps (manifests in Git) |
The same YAML, reviewable, with digest-pinned images |
|
Cluster-scoped ANP |
Default-deny east-west tenants cannot delete |
|
RHACS runtime enforce |
Kill the pod when a violating process runs |
|
SIEM (Splunk) + ACS |
Audit identity joined to runtime process |
Optional backlog (discussion — do not oc apply)
Five to seven tickets is a working backlog. Each ticket is one sentence of threat plus one acceptance criterion that names the control.
-
Stolen SA token → no automount on app SAs; SPIFFE for the database (301-08)
-
Mutable
:latest→ GitOps deploy of UBI Python by digest (301-02) -
Tenant can delete NetworkPolicy → AdminNetworkPolicy deny cross-tenant (301-03)
-
dnfin a running container → ACS runtime enforce (301-04) -
Exec with no SIEM hit → Splunk audit + ACS violation timeline (301-05)
-
Privileged pod in a “restricted” namespace → RHACM PSA labels + admission deny (301-01 / 201-10)
-
Unbounded noisy neighbor → musthave ResourceQuota (301-01)
Commit threat-model-app.md in Git and put a quarterly review on the calendar. A model that is not in Git will not survive the next architecture change.
|
Debrief
Threat modeling turns controls into a blueprint: you map data flows and privileges to concrete OpenShift defenses instead of stacking tools at random. The 301 series is that blueprint executed at platform scale.
What breaks without this:
-
Defenses without a model → locked side doors and an open front door
-
Stale models → architecture drift leaves new paths unguarded
-
Controls only in wikis → the next cluster is a snowflake
| map registry, service-to-service, CI→cluster, SA tokens, syscalls, and privileged RBAC to scan/sign, NetworkPolicy/ANP, secrets/RBAC, admission, ACS enforce, and custom roles; revisit when architecture changes. |
| start at tier (app/platform) detail enough to prioritize; re-run when you add a trust boundary or on a fixed cadence. Continue with 301. |
