Skip to content

Let a vault manifest import other vaults by ref (cross-repo secret composition) #113

Description

@ineedjet

Problem

vaults/*.yml can currently only source values from the current repo's
own secrets/vars GitHub context (GITHUB_SECRETS_JSON/GITHUB_VARS_JSON
in encrypt-env). There's no way for a vault to pull in a value that's
only known to a different repository — e.g. a third repo holds a
Telegram bot token as its own secret, and several other repos' vaults need
to include that value without each of them independently knowing the raw
secret.

If the source repo is in the same GitHub organization, this is already
solved natively by GitHub Organization Secrets (shared across repos by
policy) — no new flightdeck mechanism needed for that case. This issue is
specifically for when that's not enough: a different org, or a value
that's produced by another repo's own vault-preparation pipeline rather
than being a static GH secret.

Proposal

Let a vault manifest declare other already-published, encrypted vault
assets to import:

asset: hawkeye.sops.env
keys:
  - hawkeye
vaults:
  - owner/repo3@latest:shared.sops.env
env:
  APPS_DOMAIN: RUBYKATZEN_COM_DOMAIN
  TELEGRAM_BOT_TOKEN: TELEGRAM_BOT_TOKEN   # sourced from the imported vault

At encrypt time, before rendering env:, encrypt-env would download each
vaults: entry's asset, decrypt it, parse it as dotenv, and add its
key=value pairs into the pool of sources available to render_env()'s
resolution — alongside (not replacing) GITHUB_SECRETS_JSON/
GITHUB_VARS_JSON.

Mechanics / open questions to resolve when designing this

  • A new CI-side decrypt key is required. No private age key material
    exists in CI today — the server's own private key
    (flightdeck_sops_age_key_file) only ever lives on the target server,
    never in CI. Importing a vault means decrypting it during the CI build
    step, which needs its own dedicated keypair: the source vault
    (owner/repo3) encrypts for this recipient specifically, and the
    private half lives as a CI secret in whichever repo(s) perform the
    import (a new encrypt-env input, e.g. import-age-key). This is a
    genuinely new trust boundary, distinct from the existing keys: (who
    the output vault is encrypted for) — worth being deliberate about, not
    bolted on casually.
  • Resolution precedence. Today it's secrets > variables. Adding
    imported-vault values as a third source needs an explicit rule: does an
    imported value win over this repo's own secret of the same source name,
    or lose? Or is a name collision here an error, matching the fail-loud
    philosophy already used for env_refs merging in ansible/deploy.yml?
  • Cycle protection. If vaults can import each other by ref, a
    self-reference or cycle (A imports B, B imports A) needs at least a
    documented "don't do this." Doesn't need hard validation given the
    "keep readers dumb" philosophy used elsewhere in this repo
    (load-yaml-matrix), but worth deciding consciously rather than
    discovering it by accident.
  • Scope of what gets imported. Import brings in all of the source
    vault's decrypted key=value pairs, not a scoped subset — worth
    confirming that's actually wanted vs. letting the importing manifest
    cherry-pick specific keys.

Related

#104 (env_refs / multi-vault merging) explicitly flagged cross-repo
age-key distribution as an unresolved obstacle — this issue is the
concrete proposal for solving it. Touches .github/actions/encrypt-env
(render-env.py, action.yml) and the vault manifest schema documented
in the main README's "Vaults And Targets" section.

Not urgent — deliberately deferred, real design work needed before
implementing.

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