From d9fbc725657968fd40f52ee701863863f4a602d6 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 10 Sep 2026 20:57:58 +0200 Subject: [PATCH] step-ca: give the CA's own secret material to the uid the CA runs as MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upstream `smallstep/step-ca` image runs as uid 1000. An own-secret lands as a file the host writes root:root 0600 — the module says only a name and a path, so there is nowhere to say who must be able to read it — and the container crash-looped on `permission denied` reading its own root key. The lab got past it first with `chmod 0644`, which hands the root key to every local user, and then by running the CA as root, which is worse. Neither is needed. A module composes its own files, and a `file` resource takes both a `mode` and an `owner`, with `${secret:name}` reaching the module's own secrets — the mechanism redis already uses to hand its password to a server running as 999. So the three pieces of init material are declared as owned files: still 0600, owned by 1000:1000, and those are what the container mounts. The raw own-secret files stay where they were. Nothing mounts them now; they are how the secret comes to exist on the machine, and the host is the only thing that reads them. Same shape as redis's `default.secret`. Verified against the real code rather than by inspection: mesh-control attaches the sealed value to each of the three resources and keeps `owner` and `mode` (`sealedFor` + `intoFile` over this manifest), and mesh-host parses `owner` on a sealed-substituted file and lands it 0600 owned by 1000:1000 (`applyFile`). --- modules/step-ca/module.json | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/step-ca/module.json b/modules/step-ca/module.json index 013e79d..f9f12b0 100644 --- a/modules/step-ca/module.json +++ b/modules/step-ca/module.json @@ -59,6 +59,30 @@ "mode": "0600", "content": "DOCKER_STEPCA_INIT_PASSWORD=${secret:password}\n" }, + { + "id": "root-cert-file", + "type": "file", + "path": "/var/lib/mesh/step-ca/root-cert.pem", + "mode": "0600", + "owner": "1000:1000", + "content": "${secret:root-cert}" + }, + { + "id": "root-key-file", + "type": "file", + "path": "/var/lib/mesh/step-ca/root-key.pem", + "mode": "0600", + "owner": "1000:1000", + "content": "${secret:root-key}" + }, + { + "id": "root-key-password-file", + "type": "file", + "path": "/var/lib/mesh/step-ca/root-key-password.txt", + "mode": "0600", + "owner": "1000:1000", + "content": "${secret:root-key-password}" + }, { "id": "server", "type": "container", @@ -79,9 +103,9 @@ }, "volumes": [ "/var/lib/step-ca:/home/step", - "/var/lib/mesh/step-ca/root-cert:/run/secrets/root_ca.crt:ro", - "/var/lib/mesh/step-ca/root-key:/run/secrets/root_ca_key:ro", - "/var/lib/mesh/step-ca/root-key-password:/run/secrets/root_ca_key_password:ro", + "/var/lib/mesh/step-ca/root-cert.pem:/run/secrets/root_ca.crt:ro", + "/var/lib/mesh/step-ca/root-key.pem:/run/secrets/root_ca_key:ro", + "/var/lib/mesh/step-ca/root-key-password.txt:/run/secrets/root_ca_key_password:ro", "/var/lib/mesh/step-ca/config.json:/run/config/config.json:ro" ] }