From 5a593fba5e110288185c5498509b43c37bc52859 Mon Sep 17 00:00:00 2001 From: ogt Date: Tue, 14 Jul 2026 23:57:10 +0800 Subject: [PATCH] feat(security): mirror Argo CD repo server --- .../security/runtime-image-mirror-policy.json | 29 ++++++++ .../test_runtime_image_mirror_controller.py | 66 ++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/config/security/runtime-image-mirror-policy.json b/config/security/runtime-image-mirror-policy.json index 351f5f0b7..745de9d6b 100644 --- a/config/security/runtime-image-mirror-policy.json +++ b/config/security/runtime-image-mirror-policy.json @@ -72,6 +72,35 @@ "container": "argocd-notifications-controller" } }, + { + "asset_id": "runtime-image:argocd-repo-server", + "source_index_digest": "sha256:16b92ba472fbb9287459cc52e0ecff07288dff461209955098edb56ce866fe49", + "platform_digest": "sha256:2f25a42949ea69c0dd33f4ce1918c6a01039d6c14a7ecc1d19088504a9d3e94f", + "target_registry_digest": "sha256:8b7e25d7e6036d6750c5bda8920cbd80d8902c25771666f6767dc97bd7fab8fc", + "push_ref": "registry.wooo.work/awoooi/runtime-mirror/argocd:v3.3.6-linux-amd64", + "runtime_ref": "192.168.0.110:5000/awoooi/runtime-mirror/argocd@sha256:8b7e25d7e6036d6750c5bda8920cbd80d8902c25771666f6767dc97bd7fab8fc", + "workload": { + "kind": "deployment", + "namespace": "argocd", + "name": "argocd-repo-server", + "container": "argocd-repo-server" + } + }, + { + "asset_id": "runtime-image:argocd-repo-server-copyutil", + "source_index_digest": "sha256:16b92ba472fbb9287459cc52e0ecff07288dff461209955098edb56ce866fe49", + "platform_digest": "sha256:2f25a42949ea69c0dd33f4ce1918c6a01039d6c14a7ecc1d19088504a9d3e94f", + "target_registry_digest": "sha256:8b7e25d7e6036d6750c5bda8920cbd80d8902c25771666f6767dc97bd7fab8fc", + "push_ref": "registry.wooo.work/awoooi/runtime-mirror/argocd:v3.3.6-linux-amd64", + "runtime_ref": "192.168.0.110:5000/awoooi/runtime-mirror/argocd@sha256:8b7e25d7e6036d6750c5bda8920cbd80d8902c25771666f6767dc97bd7fab8fc", + "workload": { + "kind": "deployment", + "namespace": "argocd", + "name": "argocd-repo-server", + "container": "copyutil", + "container_kind": "init_container" + } + }, { "asset_id": "runtime-image:kured", "source_index_digest": "sha256:2c5d73bb4517a269def38a6cd54d34d82be81793bea9ff1bb35c6533515ad209", diff --git a/scripts/security/tests/test_runtime_image_mirror_controller.py b/scripts/security/tests/test_runtime_image_mirror_controller.py index 58134a7a9..309405e7d 100644 --- a/scripts/security/tests/test_runtime_image_mirror_controller.py +++ b/scripts/security/tests/test_runtime_image_mirror_controller.py @@ -47,7 +47,7 @@ class RuntimeImageMirrorControllerTest(unittest.TestCase): self.assertEqual(policy.work_item_id, "AIA-P0-006-02A") self.assertEqual(policy.risk_level, "high") - self.assertEqual(len(policy.images), 8) + self.assertEqual(len(policy.images), 10) self.assertNotIn("github.com", raw) self.assertNotIn("ghcr.io", raw) self.assertIn('"external_pull_allowed": false', raw) @@ -72,8 +72,8 @@ class RuntimeImageMirrorControllerTest(unittest.TestCase): ) ) container_kinds = [image.workload.container_kind for image in policy.images] - self.assertEqual(container_kinds.count("container"), 7) - self.assertEqual(container_kinds.count("init_container"), 1) + self.assertEqual(container_kinds.count("container"), 8) + self.assertEqual(container_kinds.count("init_container"), 2) def test_policy_loads_and_validates_init_container_kind(self) -> None: image = self._image_with_container_kind("init_container") @@ -184,6 +184,66 @@ class RuntimeImageMirrorControllerTest(unittest.TestCase): image.runtime_ref.endswith("@" + image.target_registry_digest) ) + def test_argocd_repo_server_batch_reuses_verified_staging_artifact(self) -> None: + policy = controller.load_policy(POLICY_PATH) + staging = controller.load_staging_policy(STAGING_POLICY_PATH).images[0] + batch = { + image.asset_id: image + for image in policy.images + if image.asset_id + in { + "runtime-image:argocd-repo-server", + "runtime-image:argocd-repo-server-copyutil", + } + } + + self.assertEqual( + set(batch), + { + "runtime-image:argocd-repo-server", + "runtime-image:argocd-repo-server-copyutil", + }, + ) + self.assertEqual( + { + ( + image.workload.kind, + image.workload.namespace, + image.workload.name, + image.workload.container, + image.workload.container_kind, + ) + for image in batch.values() + }, + { + ( + "deployment", + "argocd", + "argocd-repo-server", + "argocd-repo-server", + "container", + ), + ( + "deployment", + "argocd", + "argocd-repo-server", + "copyutil", + "init_container", + ), + }, + ) + for image in batch.values(): + self.assertEqual(image.source_index_digest, staging.source_index_digest) + self.assertEqual(image.platform_digest, staging.platform_digest) + self.assertEqual(image.push_ref, staging.push_ref) + self.assertEqual( + image.target_registry_digest, + "sha256:8b7e25d7e6036d6750c5bda8920cbd80d8902c25771666f6767dc97bd7fab8fc", + ) + self.assertTrue( + image.runtime_ref.endswith("@" + image.target_registry_digest) + ) + def test_policy_rejects_external_pull_and_mutable_runtime_ref(self) -> None: payload = json.loads(POLICY_PATH.read_text(encoding="utf-8")) with tempfile.TemporaryDirectory() as temp: