◇ OpenCyber Academy
Engineering · Chapter 27 · English

Chapter 27 — Cloud and container security: control design

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 27 — Cloud and container security: control design

Lesson map

Lesson 27 published. Map, example, EX079.

flowchart TD
  N0["Learning outcomes"]
  N1["27.1 Admission control"]
  N2["27.2 Failure mode"]
  N3["27.3 Identity controls"]
  N4["27.4 Storage controls"]
  N5["27.5 Exceptions"]
  N6["27.6 Observability"]
  N7["Policy testing"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Worked example"]
  EX --> Q["Exercise EX079"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["27.1 Admission control"]
  N2["27.2 Failure mode"]
  N3["27.3 Identity controls"]
  N4["27.4 Storage controls"]
  N5["27.5 Exceptions"]
  N6["27.6 Observability"]
  N7["Policy testing"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX079"]
[Learning outcomes]
    |
    v
[27.1 Admission control]
    |
    v
[27.2 Failure mode]
    |
    v
[27.3 Identity controls]
    |
    v
[27.4 Storage controls]
    |
    v
[27.5 Exceptions]
    |
    v
[27.6 Observability]
    |
    v
[Policy testing]
    |
    v
[Worked example] --> [Exercise EX079]

Learning outcomes

You will (1) design admission, identity and storage controls in detail; (2) specify behaviour, exceptions and failure modes; (3) make controls observable; (4) avoid single points of failure.

27.1 Admission control

Pod Security admission enforces the Restricted profile on production namespaces; a policy engine adds checks for image signatures, resource limits and allowed registries. Policies are code, reviewed and tested.

Admission control is the last check before a pod runs, so it catches mistakes regardless of how the manifest was produced. Pod Security admission handles the standard profile with no extra software. The policy engine covers rules the profiles do not, such as requiring signatures or limits. Writing policies as code means they are tested like application code, with compliant and non-compliant examples, before being enforced in production.

27.2 Failure mode

If the policy engine is unavailable, should deployments fail closed (blocked) or open (allowed)? Solent chooses fail closed for production with a monitored, highly available engine, and fail open with alerts for test clusters.

Failing closed in production means an outage of the policy engine stops deployments, which is inconvenient but safe: nothing unchecked can run. Making the engine highly available and monitoring it keeps such outages rare and short. In test clusters, blocking work would frustrate developers for little security gain, so failing open with alerts lets work continue while the problem is visible.

27.3 Identity controls

Workload identity bindings map each service account to one cloud role with minimal permissions. Organisation policy disallows creating long-lived keys for service accounts.

One service account mapped to one role keeps permissions easy to read: anyone can see exactly what the ingest service may do in the cloud. Preventing long-lived keys at the organisation level stops someone from creating a key as a quick fix, which is how the leaked key came to exist. Teams that need cloud access must use workload identity, so credentials are short-lived and never stored in images.

27.4 Storage controls

Account-level settings block public access to storage; bucket policies require encrypted connections; customer-managed keys protect readings.

Blocking public access at account level overrides any individual bucket setting, so a mistaken bucket policy cannot expose readings. Requiring encrypted connections stops data from crossing networks in clear text. Customer-managed keys add a further layer, since even someone with storage access must also have permission to use the key. Each control covers a different way data could leak. Elena verifies each setting with a configuration query.

27.5 Exceptions

Exceptions are labels on namespaces or workloads that reference a ticket and expiry date; the policy engine checks expiry.

Putting exceptions on the workload itself, rather than in a separate spreadsheet, means the policy engine can see and enforce them. The ticket reference explains why the exception exists; the expiry date makes it temporary by design. When the date passes, the engine rejects the workload, prompting a renewal decision rather than letting the exception linger forgotten. Elena's report lists exceptions due to expire within a month.

27.6 Observability

Every denial is logged with the rule and reason and counted on a dashboard; repeated denials for the same team prompt help, not punishment.

Logged denials with reasons let developers fix problems themselves. The dashboard shows which rules are triggered most, which might indicate a confusing rule or a common mistake worth addressing in documentation. Treating repeated denials as a sign that a team needs help, not as misconduct, keeps teams cooperative and avoids pressure to weaken rules. Denial counts are reviewed weekly.

Policy testing

Policies are code, so they have unit tests: each rule is tested with a compliant and a non-compliant synthetic object. Tests run in the pipeline before a policy change reaches any cluster. A policy change that breaks a test cannot merge, which prevents a typo from blocking every deployment in production or, worse, silently allowing what it should block.

Worked example

Elena tests the fail-closed design by stopping one of three policy engine replicas in staging; deployments continue. Stopping all three blocks deployments as intended, and an alert fires within a minute, confirming the failure mode is visible.

Synthetic case. Controls and tests are synthetic.

Errors and limits

Fail-closed controls become availability risks; invest in their reliability.

Exercises

Synthesis

Specify how controls behave, fail and are observed.

Continue studying — chapter 27 of 50

← Chapter 26 (draft) · Course chapter index · Chapter 28 (draft) →