feat(security): mirror Argo CD repo server
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m28s
CD Pipeline / build-and-deploy (push) Successful in 11m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m54s

This commit is contained in:
ogt
2026-07-14 23:57:10 +08:00
parent abdf179f1b
commit 5a593fba5e
2 changed files with 92 additions and 3 deletions

View File

@@ -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",

View File

@@ -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: