|
6 | 6 | "github.com/openshift/zero-trust-workload-identity-manager/api/v1alpha1" |
7 | 7 | "github.com/openshift/zero-trust-workload-identity-manager/pkg/controller/utils" |
8 | 8 | "github.com/stretchr/testify/assert" |
| 9 | + "github.com/stretchr/testify/require" |
| 10 | + corev1 "k8s.io/api/core/v1" |
9 | 11 | ) |
10 | 12 |
|
11 | 13 | func TestGetHostCertMountPath(t *testing.T) { |
@@ -156,3 +158,67 @@ func TestHostPathTypePtr(t *testing.T) { |
156 | 158 | assert.NotNil(t, result) |
157 | 159 | assert.Equal(t, "DirectoryOrCreate", string(*result)) |
158 | 160 | } |
| 161 | + |
| 162 | +// assertSpireAgentContainerHardening checks container securityContext matches |
| 163 | +// generateSpireAgentSCC: non-privileged, no escalation, cap drop ALL, R/O rootfs (see scc.go). |
| 164 | +func assertSpireAgentContainerHardening(t *testing.T, c *corev1.Container) { |
| 165 | + t.Helper() |
| 166 | + require.NotNil(t, c.SecurityContext, "spire-agent container must set securityContext for SCC hardening") |
| 167 | + sc := c.SecurityContext |
| 168 | + require.NotNil(t, sc.AllowPrivilegeEscalation, "allowPrivilegeEscalation must be explicit (false)") |
| 169 | + assert.False(t, *sc.AllowPrivilegeEscalation, "AllowPrivilegeEscalation must be false to match spire-agent SCC") |
| 170 | + require.NotNil(t, sc.Privileged, "privileged must be explicit (false)") |
| 171 | + assert.False(t, *sc.Privileged, "container must not run privileged; matches AllowPrivilegedContainer: false in SCC") |
| 172 | + require.NotNil(t, sc.ReadOnlyRootFilesystem, "readOnlyRootFilesystem must be explicit (true)") |
| 173 | + assert.True(t, *sc.ReadOnlyRootFilesystem, "ReadOnlyRootFilesystem must be true; matches spire-agent SCC") |
| 174 | + require.NotNil(t, sc.Capabilities, "capabilities must be set") |
| 175 | + require.NotNil(t, sc.Capabilities.Drop, "must drop capabilities") |
| 176 | + assert.Equal(t, []corev1.Capability{corev1.Capability("ALL")}, sc.Capabilities.Drop, "requiredDropCapabilities [ALL] in SCC") |
| 177 | +} |
| 178 | + |
| 179 | +func TestGenerateSpireAgentDaemonSet_SCCSecurityHardening(t *testing.T) { |
| 180 | + ztwim := &v1alpha1.ZeroTrustWorkloadIdentityManager{ |
| 181 | + Spec: v1alpha1.ZeroTrustWorkloadIdentityManagerSpec{ |
| 182 | + TrustDomain: "example.org", |
| 183 | + BundleConfigMap: "spire-bundle", |
| 184 | + }, |
| 185 | + } |
| 186 | + |
| 187 | + t.Run("pod boundary matches spire-agent SCC (host PID, no host network/IPC/ports in SCC)", func(t *testing.T) { |
| 188 | + spec := v1alpha1.SpireAgentSpec{ |
| 189 | + SocketPath: "/tmp/spire-agent/public", |
| 190 | + } |
| 191 | + ds := generateSpireAgentDaemonSet(spec, ztwim, "test-config-hash") |
| 192 | + require.NotNil(t, ds) |
| 193 | + pod := &ds.Spec.Template.Spec |
| 194 | + assert.Equal(t, "spire-agent", pod.ServiceAccountName) |
| 195 | + assert.True(t, pod.HostPID, "HostPID required for k8s workload attestation; SCC AllowHostPID: true") |
| 196 | + assert.False(t, pod.HostNetwork, "HostNetwork disabled; SCC allowHostNetwork: false") |
| 197 | + assert.Equal(t, corev1.DNSClusterFirst, pod.DNSPolicy) |
| 198 | + require.Len(t, pod.Containers, 1) |
| 199 | + assertSpireAgentContainerHardening(t, &pod.Containers[0]) |
| 200 | + }) |
| 201 | + |
| 202 | + t.Run("security context unchanged when kubelet CA hostPath is present", func(t *testing.T) { |
| 203 | + spec := v1alpha1.SpireAgentSpec{ |
| 204 | + SocketPath: "/tmp/spire-agent/public", |
| 205 | + WorkloadAttestors: &v1alpha1.WorkloadAttestors{ |
| 206 | + K8sEnabled: "true", |
| 207 | + WorkloadAttestorsVerification: &v1alpha1.WorkloadAttestorsVerification{ |
| 208 | + Type: utils.WorkloadAttestorVerificationTypeAuto, |
| 209 | + }, |
| 210 | + }, |
| 211 | + } |
| 212 | + ds := generateSpireAgentDaemonSet(spec, ztwim, "hash") |
| 213 | + var sawKubeletCA bool |
| 214 | + for _, v := range ds.Spec.Template.Spec.Volumes { |
| 215 | + if v.Name == "kubelet-ca" { |
| 216 | + sawKubeletCA = true |
| 217 | + break |
| 218 | + } |
| 219 | + } |
| 220 | + require.True(t, sawKubeletCA, "expected kubelet-ca volume for auto verification / host cert") |
| 221 | + require.Len(t, ds.Spec.Template.Spec.Containers, 1) |
| 222 | + assertSpireAgentContainerHardening(t, &ds.Spec.Template.Spec.Containers[0]) |
| 223 | + }) |
| 224 | +} |
0 commit comments