Skip to content

Commit 8a1e16e

Browse files
authored
PINF-989 fill k8s security testing gaps (#761)
1 parent 5461f35 commit 8a1e16e

4 files changed

Lines changed: 41 additions & 5 deletions

File tree

.circleci/config.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
run_pre_commit:
171171
resource_class: small
172172
docker:
173-
- image: quay.io/astronomer/ci-pre-commit:2026-07
173+
- image: quay.io/astronomer/ci-pre-commit:2026-08
174174
steps:
175175
- checkout
176176
- run:
@@ -205,7 +205,7 @@ jobs:
205205

206206
unittest-charts:
207207
docker:
208-
- image: quay.io/astronomer/ci-helm-release:2026-07
208+
- image: quay.io/astronomer/ci-helm-release:2026-08
209209
parallelism: 8
210210
steps:
211211
- setup_remote_docker:
@@ -224,7 +224,7 @@ jobs:
224224

225225
build-and-release-internal:
226226
docker:
227-
- image: quay.io/astronomer/ci-helm-release:2026-07
227+
- image: quay.io/astronomer/ci-helm-release:2026-08
228228
steps:
229229
- checkout
230230
- run:
@@ -265,7 +265,7 @@ jobs:
265265
path: test-results
266266
release-internal:
267267
docker:
268-
- image: quay.io/astronomer/ci-helm-release:2026-07
268+
- image: quay.io/astronomer/ci-helm-release:2026-08
269269
steps:
270270
- checkout
271271
- run:
@@ -274,7 +274,7 @@ jobs:
274274

275275
release-public:
276276
docker:
277-
- image: quay.io/astronomer/ci-helm-release:2026-07
277+
- image: quay.io/astronomer/ci-helm-release:2026-08
278278
steps:
279279
- checkout
280280
- publish-github-release

tests/chart/test_container_security_context.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ def test_all_containers_have_hardened_security_context(kube_version):
6565
)
6666

6767

68+
# mountPropagation isn't a securityContext field, so it's not part of hardening_problems() above,
69+
# and Pod Security Admission doesn't validate it either -- this is a Kyverno/OPA-style customer
70+
# policy control instead, forbidding the two unsafe values (PINF-986: MountPropagation).
71+
UNSAFE_MOUNT_PROPAGATION = {"HostToContainer", "Bidirectional"}
72+
73+
74+
@pytest.mark.parametrize("kube_version", supported_k8s_versions)
75+
def test_no_containers_use_unsafe_mount_propagation(kube_version):
76+
"""Render the whole chart and assert no volumeMount sets an unsafe mountPropagation."""
77+
docs = render_chart(kube_version=kube_version, values=get_all_features())
78+
79+
offenders = {}
80+
checked = 0
81+
for doc in docs:
82+
if doc.get("metadata", {}).get("name") in EXCLUDED_DOCS:
83+
continue
84+
owner = f"{doc['kind']}/{doc['metadata']['name']}"
85+
for name, container in get_containers_by_name(doc, include_init_containers=True).items():
86+
checked += 1
87+
for mount in container.get("volumeMounts") or []:
88+
if mount.get("mountPropagation") in UNSAFE_MOUNT_PROPAGATION:
89+
offenders[f"{owner}:{name}:{mount['name']}"] = mount["mountPropagation"]
90+
91+
assert checked, "No containers were rendered; cannot validate mountPropagation"
92+
assert not offenders, "volumeMounts with an unsafe mountPropagation (mount: value):\n" + "\n".join(
93+
f" {key}: {value}" for key, value in sorted(offenders.items())
94+
)
95+
96+
6897
# --- git-sync-relay PSS-Restricted conformance (PINF-585 follow-up) -----------------
6998
#
7099
# git-sync-relay is not processed by houston's securityHardeningConfig, so unlike

tests/chart/test_dag_server_service.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ def test_dag_server_service_dag_server_enabled(self, kube_version):
2727
assert doc["kind"] == "Service"
2828
assert doc["apiVersion"] == "v1"
2929
assert doc["metadata"]["name"] == "release-name-dag-server"
30+
# No serviceType override exists for this Service -- it must stay unset so Kubernetes'
31+
# own default (ClusterIP) applies. (PINF-986: ServiceOnlyAllowClusterIP)
32+
assert "type" not in doc["spec"]

tests/chart/test_git_sync_relay_service.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def test_gsr_service_gsr_enabled(self, kube_version):
2828
assert doc["kind"] == "Service"
2929
assert doc["apiVersion"] == "v1"
3030
assert doc["metadata"]["name"] == "release-name-git-sync-relay"
31+
# No serviceType override exists for this Service -- it must stay unset so Kubernetes'
32+
# own default (ClusterIP) applies. (PINF-986: ServiceOnlyAllowClusterIP)
33+
assert "type" not in doc["spec"]
3134

3235
@pytest.mark.parametrize("repoShareMode,", ["git_daemon", "shared_volume"])
3336
@pytest.mark.parametrize("repoFetchMode", ["poll", "webhook"])
@@ -53,6 +56,7 @@ def test_gsr_service_gsr_enabled_configured_ports(self, kube_version, repoFetchM
5356
assert doc["kind"] == "Service"
5457
assert doc["apiVersion"] == "v1"
5558
assert doc["metadata"]["name"] == "release-name-git-sync-relay"
59+
assert "type" not in doc["spec"]
5660
ports = get_service_ports_by_name(doc)
5761
if repoFetchMode == "webhook":
5862
assert ports["webhook"]["port"] == 8000

0 commit comments

Comments
 (0)