You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SPIRE-525: Add e2e tests for SCC hardening (PR #105) and enhance test generation rules
- Add Security hardening Context to e2e_test.go with two tests:
- SCC field validation (AllowHostNetwork, AllowPrivilegeEscalation, etc.)
- DaemonSet and pod security context verification (Privileged, ReadOnlyRootFilesystem, Capabilities.Drop)
- Register securityv1 scheme in e2e_suite_test.go for SCC object access
- Add SpireAgentSCCName constant to constants.go
- Enhance e2e-rules.md Step 6 and Step 7 with structured test case IDs,
priority levels, coverage gap fields, and per-step expected results
- Add test plan document in output/pr-105/test-cases.md
Made-with: Cursor
| 2 |**Operand lifecycle**| CR create/update/delete for each of the 4 operands, condition checks (Ready, all sub-conditions), aggregate status on ZeroTrustWorkloadIdentityManager |
159
-
| 3 |**Security hardening**| SCC field validation (AllowHostNetwork, AllowPrivilegeEscalation, etc.), pod SecurityContext (runAsNonRoot, drop ALL, readOnlyRootFilesystem), restricted-v2 SCC compliance |
| 8 |**Performance**| Load/scale testing if missing: large number of ClusterSPIFFEIDs, concurrent attestation, DaemonSet rollout on many-node clusters |
165
+
| 9 |**Security**| Permission/isolation tests: SCC field validation, pod SecurityContext (runAsNonRoot, drop ALL, readOnlyRootFilesystem), restricted-v2 SCC compliance, RBAC least-privilege |
166
+
| 10 |**Real Customer Scenarios**| Use cases from the RFE/Jira not tested: end-to-end workflows described in the ticket, production-like topologies, day-2 operational patterns |
167
+
168
+
**Prioritization rules:**
169
+
170
+
- For each PR/Jira, identify which categories are impacted by the diff.
171
+
- Generate test cases for impacted categories **first**, then fill gaps in
172
+
un-covered categories if the change is broad.
173
+
- Assign a priority to each test case:
174
+
-**Critical** -- blocks core functionality or security; must pass before merge.
175
+
-**High** -- important gap in coverage; should be addressed in the same release.
176
+
-**Medium** -- nice-to-have hardening; can be deferred if time-constrained.
177
+
178
+
**Test case ID format:**
179
+
180
+
Use `<TICKET>-TC-NNN` where `<TICKET>` is the source identifier:
181
+
182
+
| Source | ID example |
183
+
|---|---|
184
+
| Jira `SPIRE-439`|`SPIRE-439-TC-001`|
185
+
| Jira `OCPSTRAT-1234`|`OCPSTRAT-1234-TC-001`|
186
+
| GitHub PR #105|`PR-105-TC-001`|
187
+
188
+
Number sequentially (`TC-001`, `TC-002`, ...) within a single test plan.
171
189
172
190
### Step 7: Generate test-cases.md
173
191
174
-
Write the test plan to a local output directory:
192
+
Write the test plan to a local output directory. Use the Jira key when
193
+
available, otherwise use the PR number:
175
194
176
195
```bash
177
-
mkdir -p output/${JIRA_KEY:-pr-$PR_NUMBER}
196
+
# Jira source
197
+
mkdir -p output/${JIRA_KEY}
198
+
# GitHub PR source
199
+
mkdir -p output/pr-${PR_NUMBER}
178
200
```
179
201
180
-
Use this template for `output/<key>/test-cases.md`:
202
+
File name: `test-cases.md` (e.g. `output/SPIRE-439/test-cases.md` or
203
+
`output/pr-105/test-cases.md`).
204
+
205
+
Use this template:
181
206
182
207
```markdown
183
208
# Test Plan: <title>
@@ -191,19 +216,22 @@ Use this template for `output/<key>/test-cases.md`:
dropping all Linux capabilities, and updating the custom
12
+
SecurityContextConstraints to restrict host access and privilege escalation.
13
+
E2E tests must verify that these hardened settings are applied to the SCC
14
+
object, the DaemonSet spec, and the running pods on a live OpenShift cluster.
15
+
16
+
## Test Cases
17
+
18
+
### PR-105-TC-001: SPIRE Agent SCC field validation after hardening
19
+
**Priority:** Critical
20
+
**Domain:** openshift-scc, security-context
21
+
**Category:** Security
22
+
**OpenShift-specific:** yes
23
+
**Coverage Gap:** Existing e2e only checks the `SecurityContextConstraintsAvailable` condition (boolean). No test fetches the actual `spire-agent` SCC object to verify individual field values like AllowHostNetwork, AllowPrivilegeEscalation, or RequiredDropCapabilities.
24
+
**Prerequisites:** Operator installed via OLM, SpireAgent CR `cluster` created, `SecurityContextConstraintsAvailable` condition is True
25
+
**Steps:**
26
+
1.`k8sClient.Get(ctx, client.ObjectKey{Name: "spire-agent"}, scc)` -- fetch the SCC object from the cluster
27
+
**Expected:** SCC object exists and is retrievable without error
28
+
2. Assert SCC host-access fields:
29
+
-`scc.AllowHostNetwork == false`
30
+
-`scc.AllowHostPorts == false`
31
+
-`scc.AllowPrivilegedContainer == false`
32
+
-`*scc.AllowPrivilegeEscalation == false`
33
+
**Expected:** All four fields are restrictive (false)
34
+
3. Assert SCC retains required host access:
35
+
-`scc.AllowHostPID == true`
36
+
-`scc.AllowHostDirVolumePlugin == true`
37
+
**Expected:** Both remain true (required for node attestation and socket dir)
38
+
4. Assert SCC filesystem and capability restrictions:
39
+
-`scc.ReadOnlyRootFilesystem == true`
40
+
-`scc.RequiredDropCapabilities` contains `"ALL"`
41
+
**Expected:** Filesystem is read-only and all capabilities are dropped
**Stop condition:** PR-105-TC-002 depends on the SCC being correctly applied (SCC governs pod admission)
46
+
47
+
### PR-105-TC-002: SPIRE Agent DaemonSet and pod security context verification
48
+
**Priority:** Critical
49
+
**Domain:** security-context, controller-manager
50
+
**Category:** Security
51
+
**OpenShift-specific:** no
52
+
**Coverage Gap:** Existing e2e waits for `DaemonSetAvailable` (replica count) but never inspects the DaemonSet pod template or running pod security settings. No test verifies HostNetwork, HostPID, DNSPolicy, Privileged, AllowPrivilegeEscalation, ReadOnlyRootFilesystem, or Capabilities.Drop on the spire-agent workload.
53
+
**Prerequisites:** Operator installed via OLM, SpireAgent CR `cluster` created, DaemonSet `spire-agent` is available with all pods running
54
+
**Steps:**
55
+
1.`clientset.AppsV1().DaemonSets(ns).Get(ctx, "spire-agent", ...)` -- fetch the DaemonSet
56
+
**Expected:** DaemonSet exists and is retrievable without error
0 commit comments