Skip to content

[glassine] gantry djrhails-dev worker age key is not a recipient — all encrypted skills fail to decrypt #68

Description

@DJRHails

Summary

The gantry:djrhails-dev worker container cannot decrypt any glassine-managed
skill (slack, gantry-cli, runpod-ant-cluster, saint-chrome,
tailscale-topology, uptime-alerts, discord, research-meeting-playbook,
web-animation-design, diagram-design). The worker's provisioned age identity is
not among the recipients of the envelopes, so every recipient block fails and the
SKILL.md files stay as ciphertext in the checkout. This blocks skills the worker base
prompt tells it to read (e.g. runpod-ant-cluster before any cluster action).

First surfaced as a gantry worker feedback (warning) from run thrd_stoic-lofty-vale.

Root cause (verified)

.sops.yaml registers gantry:djrhails-dev as:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDgVBcMfDRmqpxzMaWuAlATJxaUgb3IzPgAEblU5dK4D  # gantry:djrhails-dev

But the running container's provisioned identity (/home/dev/.ssh/ant-cluster-key,
pointed to by SOPS_AGE_SSH_PRIVATE_KEY_FILE) has a different public half:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJICpmwHaldwDJB+/AYvlRCJWJw2M3fBzKpVs1C7VzXT  gantry-djrhails-dev-worker

...JICpmwHaldwDJB... appears in none of the 10 encrypted skills (verified by
grepping each envelope's recipient list; sops -d fails all recipient blocks). The
key looks freshly generated / rotated without a corresponding glassine allow, or
provisioning mounted the wrong key — it does not match the registered recipient.

The reporter's secondary claim is incorrect

The original report also stated "sops 3.13.3 does not honour
SOPS_AGE_SSH_PRIVATE_KEY_FILE"
. It does. Controlled test (sops 3.13.3, clean
env -i, only that var set, key at a non-default path, empty $HOME):

env -i PATH=$PATH HOME=$EMPTY SOPS_AGE_SSH_PRIVATE_KEY_FILE=$KEY sops decrypt enc.yaml
# -> exit 0, decrypts correctly

The misleading part is sops' failure string — Did not find keys in locations 'SOPS_AGE_SSH_PRIVATE_KEY_CMD', '~/.ssh/id_ed25519', '~/.ssh/id_rsa', 'SOPS_AGE_KEY', 'SOPS_AGE_KEY_FILE', 'SOPS_AGE_KEY_CMD' omits SOPS_AGE_SSH_PRIVATE_KEY_FILE even
though sops honours it. So the env-var plumbing is fine; the only defect is the
recipient mismatch.

Remediation (needs a host holding an existing recipient key — operator)

Re-encryption requires decrypting first, so this can't be done from the broken worker
(it holds no recipient key). Pick one:

  • A — provisioning mounts the registered key. Ensure the djrhails-dev worker is
    provisioned with the private key whose public half is the registered
    ...IDgVBcMfDRmqpxzMaWuAlATJxaUgb3IzPgAEblU5dK4D, and point
    SOPS_AGE_SSH_PRIVATE_KEY_FILE at it. Best if that key is the intended stable
    identity.

  • B — register the new worker key. From a checkout on a host with an existing
    recipient key:

    glassine allow 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJICpmwHaldwDJB+/AYvlRCJWJw2M3fBzKpVs1C7VzXT gantry-djrhails-dev-worker'
    git add -A && git commit && git push
    

    Best if the worker key legitimately rotated. If worker keys are regenerated
    per-spawn, prefer A (a per-spawn key can never stay a recipient).

Whichever: confirm with glassine status / sops -d modules/agents/skills/slack/SKILL.md
from a fresh djrhails-dev worker.

Impact / workaround

Not fully blocking for skills whose capability is otherwise reachable — the reporting
worker used $SLACK_BOT_TOKEN + the Slack Web API directly instead of the slack
skill. But cluster/other skills gated behind "read the skill first" are effectively
unavailable, and every affected worker pays the same failed-decrypt cost.


via gantry

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions