Allow for short lived, provisioned SSH keys #104
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Key management for agents is kind of annoying to do manually, and potentially insecure (ssh keys are not invalidated). Also I'm having issues with the git-gate layer and need to refactor it regardless. Would be nice to have some method to auto inject keys that live for a set period of time.
Proposed solution:
deploy_key_provisionerRather than SSH CA certificates (also considered — see below), the cleanest approach is to generate a fresh SSH keypair at spin-up, register the public key as a deploy key via the Gitea/GitHub API, and delete it at teardown.
Manifest change
Add an optional
deploy_key_provisionerblock toGitEntry. It is mutually exclusive withidentity_file— exactly one must be present:token_refis the API token used to register and delete the deploy key (i.e. the provisioning credential). It is separate from the generated SSH keypair that git-gate actually uses for git operations.Dataclass sketch
Platform (Gitea vs GitHub) is inferred from
UpstreamHost— no explicit field needed yet.Runtime flow
prepare()— generate fresh ed25519 keypair into a temp dir, POST the public key to the Gitea/GitHub API, store the private key path asIdentityFilefor git-gatelaunch()— register astack.callback()to DELETE the deploy key via API; the existingExitStack+finallyguarantees this runs even on crash, andteardown()swallows exceptions so a failed delete doesn't mask the original errorIdentityFileas it does todayWhy not SSH CA certificates
CA certs were considered first. The per-session ephemerality is equivalent, but the operational tradeoffs favour deploy keys here:
SSH_TRUSTED_USER_CA_KEYSinapp.ini+ restart, or a KRL file Gitea needs to hot-reload.token_refAPI token lets an attacker create visible, auditable keys. A leaked CA key silently mints valid certs for any repo trusting that CA.Orphan management
If a container crashes before teardown runs, the deploy key persists. The dashboard (supervise plane) is the right place to surface and revoke these — active deploy keys per agent, with a manual revoke action for orphans. This follows the same pattern as the existing orphan state-dir detection in
cleanup.py.Think that makes sense. We should also use this as an opportunity to introduce a
contribstructure for scoping things like specific deploy key provisioners, specific agent provisioners, etc.Agreed —
bot_bottle/contrib/fits cleanly as the home for anything that is platform-specific rather than core: deploy-key provisioners per forge, agent provisioners per runtime, etc. The core defines the abstract interface (DeployKeyProvisionerABC); each contrib sub-package ships a concrete implementation alongside any platform-specific helpers it needs.For this feature:
bot_bottle/contrib/gitea/— first contrib sub-package, shippingGiteaDeployKeyProvisionermanifest_git.pygrows aDeployKeyConfigdataclass;deploy_key:becomes an alternative toidentity:ingit-gate.reposentries (mutually exclusive, parser rejects both-or-neither)Filing PRD 0048 to nail down the full schema and runtime contract.
Implemented in PR #170 (merged 2026-06-03). See also PRD 0048 at
docs/prds/0048-ssh-deploy-key-provisioning.mdand the implementation atbot_bottle/contrib/gitea/deploy_key_provisioner.py.