117 lines
4.1 KiB
Markdown
117 lines
4.1 KiB
Markdown
|
|
---
|
||
|
|
id: KEY-WP-0026
|
||
|
|
type: workplan
|
||
|
|
title: "Reconcile packaging, bootstrap and migration credential handling"
|
||
|
|
domain: infotech
|
||
|
|
repo: key-cape
|
||
|
|
status: finished
|
||
|
|
owner: claude
|
||
|
|
topic_slug: packaging-bootstrap-and-credential-handling
|
||
|
|
created: "2026-09-08"
|
||
|
|
updated: "2026-09-08"
|
||
|
|
---
|
||
|
|
|
||
|
|
Closes gap G09. Five separate defects, only loosely related: the dev stack could
|
||
|
|
not start from a clean checkout, the image shipped one binary of five, the
|
||
|
|
publish workflow named a different registry than the one the cluster pulls from,
|
||
|
|
the exporter took a password on argv, and every migration artifact was written
|
||
|
|
world-readable.
|
||
|
|
|
||
|
|
## Take the bind password off argv
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T01
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
`lldap-export` took `--bind-pw`, so the service account password was visible to
|
||
|
|
any local user through `ps`, and captured by shell history and process
|
||
|
|
accounting. It now prefers `KEYCAPE_LLDAP_BIND_PW`, accepts `--bind-pw-file`, and
|
||
|
|
keeps `--bind-pw` working with a warning — deprecated rather than removed,
|
||
|
|
because existing runbooks use it and silently breaking them would be worse than
|
||
|
|
the exposure for one more cycle.
|
||
|
|
|
||
|
|
Conflicting sources are rejected rather than silently ranked: with two supplied,
|
||
|
|
an operator cannot tell which bind was attempted. A password file has its
|
||
|
|
trailing newline trimmed, since editors and heredocs add one and binding with it
|
||
|
|
fails confusingly. Both migration scripts now pass the password by environment.
|
||
|
|
|
||
|
|
## Stop writing migration artifacts world-readable
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T02
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
The canonical export, the generated LDIF and the Keycloak realm were all written
|
||
|
|
`0644`. None carries credential material, but the snapshot is a directory dump —
|
||
|
|
every username, display name, email and group membership in the estate — and it
|
||
|
|
tended to land in `/tmp`. All three are `0600` now.
|
||
|
|
|
||
|
|
## Ship every binary in the image
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T03
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
The image packaged `keycape` alone, so the validator and the three migration
|
||
|
|
binaries needed a Go toolchain on the host — which defeats shipping an image for
|
||
|
|
the cutover work they exist to support. All five are built and copied; the issuer
|
||
|
|
remains the entrypoint and the rest are reachable by overriding it. Verified by
|
||
|
|
building the image and running each binary inside it.
|
||
|
|
|
||
|
|
## Reconcile the publish target
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T04
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
The workflow published to `92.205.130.254:32166/coulomb/key-cape` while the
|
||
|
|
cluster runs `forgejo.coulomb.social/coulomb/key-cape` (KEY-WP-0013). Whether
|
||
|
|
those are one registry behind two names or two registries is not determinable
|
||
|
|
from this repository, which is exactly the problem: a push could not be assumed
|
||
|
|
to have deployed the current source. Now defaults to the recorded Forgejo name
|
||
|
|
and stays overridable through a repository variable.
|
||
|
|
|
||
|
|
**Unverified, and needs an operator's eye:** this repository cannot test that the
|
||
|
|
runner resolves that hostname or that `REGISTRY_USER`/`REGISTRY_TOKEN` are valid
|
||
|
|
for it. If the next publish fails, set the `REGISTRY` repository variable back to
|
||
|
|
the address.
|
||
|
|
|
||
|
|
## Make the dev stack bootstrappable
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T05
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
`docker-compose.dev.yml` mounts `config/dev-key.pem` and `config/authelia/`,
|
||
|
|
neither in the checkout — correctly, since one is a private key and the other
|
||
|
|
carries a password hash. `scripts/bootstrap-dev.sh` generates both locally: an
|
||
|
|
RSA key created under `umask 077` rather than chmodded afterwards, so it is never
|
||
|
|
briefly world-readable, plus an Authelia configuration, its OIDC signing key and
|
||
|
|
a user fixture. Everything it writes is git-ignored, and re-running it leaves
|
||
|
|
existing material alone.
|
||
|
|
|
||
|
|
The fixture password is published in the script deliberately: a reader can see
|
||
|
|
exactly what it unlocks, which is nothing deployed.
|
||
|
|
|
||
|
|
## Reconcile the records
|
||
|
|
|
||
|
|
```task
|
||
|
|
id: KEY-WP-0026-T06
|
||
|
|
status: done
|
||
|
|
priority: medium
|
||
|
|
```
|
||
|
|
|
||
|
|
`SCOPE.md` and G09's status record what is fixed and what is not: the registry
|
||
|
|
change is unverified from here, and a documented external bootstrap remains the
|
||
|
|
route for anything beyond development.
|