manager
manager
¶
SSH keypair generation for a project scope.
SSHManager generates an SSH keypair in memory, stores the private
material in the credential DB, and assigns it to a project scope. The
generated key never touches the filesystem — the signer serves it over the
per-scope agent socket managed by the vault.
See .ssh_keypair for import/export against OpenSSH files and for the
bytes-level keypair vocabulary (GeneratedKeypair, fingerprint helpers).
DEFAULT_RSA_BITS = 3072
module-attribute
¶
Matches the ssh-keygen default as of OpenSSH 9.x.
__all__ = ['SSHInitResult', 'SSHManager', 'DEFAULT_RSA_BITS', 'GeneratedKeypair']
module-attribute
¶
GeneratedKeypair(key_type, private_der, public_blob, public_line, comment, fingerprint)
dataclass
¶
A keypair in the portable bytes form the vault stores.
private_der is unencrypted PKCS#8 DER — the raw-binary form we
persist and feed straight to the signer. The public half stays in its
usual SSH wire-format blob plus a pre-rendered public_line.
SSHInitResult
¶
SSHManager(*, scope, db)
¶
Mints SSH keypairs for a scope and stores them in the vault.
Each scope may hold multiple keys (e.g. GitHub + GitLab), each with a
distinct fingerprint. init is idempotent for the default
invocation: re-running ssh-init on a scope that already has a
tk-main: key returns that key without minting a new one — the
operator sees the same public line they registered upstream rather
than a fresh side key they'd have to re-register. force=True
rotates atomically (new key takes the scope in a single
transaction that revokes prior assignments), and a custom
comment opts back into the additive path so multi-deploy-key
setups (GitHub + GitLab on one scope) still work — but only when
asked for explicitly.
Two constructors for two ownership stories:
SSHManager(scope=..., db=...)binds the manager to a caller-ownedCredentialDB. The manager uses it and never closes it. Right shape for tests and pooled connections.SSHManager.open_for_configopens its own DB via the supplied config's chain seam (cfg.open_credential_db) and closes it onclose/ context exit / garbage collection. Right shape for one-shot CLI commands. Passdb_pathwhen the caller already holds a runtime path (typicallyVaultStatus.db_path) so the open targets that DB while still using cfg's tier policy.
Bind the manager to a caller-provided CredentialDB.
Source code in src/terok_sandbox/vault/ssh/manager.py
open_for_config(*, scope, cfg, db_path=None, prompt_on_tty=False)
classmethod
¶
Return a manager that owns a connection opened via cfg.open_credential_db.
db_path defaults to cfg.db_path; callers with a runtime
path override (e.g. the daemon's actual VaultStatus.db_path)
pass it explicitly. Tier knobs always come from cfg — no
cross-package fan-out when sandbox adds a new chain tier.
Source code in src/terok_sandbox/vault/ssh/manager.py
close()
¶
Close the DB connection if this manager opened it (idempotent).
__enter__()
¶
__exit__(*exc)
¶
__del__()
¶
init(key_type='ed25519', comment=None, force=False)
¶
Provision a keypair for the scope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_type
|
str
|
|
'ed25519'
|
comment
|
str | None
|
Comment to embed in the public key. When |
None
|
force
|
bool
|
When |
False
|
Returns:
| Type | Description |
|---|---|
SSHInitResult
|
Metadata sufficient to display the key to the user or register |
SSHInitResult
|
it with a remote. No filesystem paths. |
Raises:
| Type | Description |
|---|---|
InvalidScopeName
|
if the scope fails validation. Checked
before any key material is generated so a rejected
call leaves no orphaned row in |
Source code in src/terok_sandbox/vault/ssh/manager.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |