Skip to content

Support SSH-agent identities in existing secret declarations #435

Description

@domenkozar

Projects sometimes need permission to use an SSH identity without retrieving its private key—for example, running git push with a developer's vault key or deploying with a dedicated repository key. Can we express that through existing secret declarations and have secretspec run provide an SSH-agent connection?

Related: #434 (hardware-backed SSH identities), #9 (secret generation), and #300 (notifications and approvals). Factorseal is one motivating provider, but the interface should accommodate other agents and hardware-backed keys.

Proposed configuration

Prefer an entry in the existing profile structure over requiring a separate [ssh-agent] section. Illustrative syntax only; the type name and reference semantics are open for discussion:

[providers]
identities = "factorseal://default"

[profiles.default]
WORK_SSH = { description = "SSH identity for Git access", type = "ssh", providers = ["identities"], ref = { item = "work-github" } }
  • WORK_SSH is the project's logical identity ID. Does the existing entry name suffice, or is there a reason to add an explicit id? My preference is to reuse the name.
  • The existing ref/refs mechanism could identify the provider's key, avoiding another key_id field. The example's item coordinate would need an agreed provider mapping; this is not currently supported Factorseal syntax.
  • Consider type = "ssh_identity" instead of "ssh" to make signing-only semantics clearer. SecretSpec already documents ssh_private_key for 0.21 generation/export workflows; existing declarations must retain their behavior.
  • Multiple projects may reference the same developer identity. Dedicated deploy keys also fit; this does not require a new key per project. Personal provider/key mappings should be possible without committing a developer-specific key ID to a shared project.

Command behavior

For secretspec run -- git push:

  1. Resolve the active profile's SSH identity declarations through an agent-capable provider operation, separate from ordinary secret-value reads.
  2. Obtain an invocation-scoped agent endpoint exposing only the selected identities, and set SSH_AUTH_SOCK for the child command. Multiple declarations should work through one endpoint; composition across providers needs a defined contract.
  3. When SSH requests a signature, let the provider enforce application/key authorization and obtain user approval when required. Providers may additionally constrain destination/user/forwarding information when available; a project name alone is not an authenticated security boundary.
  4. Keep private keys inside the provider. Do not export WORK_SSH as private-key bytes or silently fetch a key into a temporary file or another agent.
  5. Close invocation-scoped resources when the command ends. Provider grant expiration, revocation, and vault locking must continue to take effect while it runs.

Design questions

  • Is a new identity type sufficient, or should agent delivery be an explicit mode on an existing type? Can we keep this within the existing profile declarations without a separate section?
  • How should provider/IPC capability negotiation represent identities and agent endpoints? Unsupported providers should return a clear error, with no automatic fallback to private-key export.
  • What should get, check, SDK resolution, and generated types return for a signing capability rather than a string secret? Value caching and composition must not accidentally turn this into ordinary secret retrieval.
  • How should multiple providers, an inherited SSH_AUTH_SOCK, Windows endpoints, and child-process lifetime be handled? Merely pointing at an unrestricted existing agent would not enforce the declared identity selection.

This would be optional project integration: normal use of an existing SSH agent should continue to work without any SSH declarations in secretspec.toml.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions