CLI command

skarbiec ci

Keep a repository's GitHub Actions secrets, or a cluster's Kubernetes Secret, the same as the vault: the bindings file exec --env-from reads names which value each secret holds, so CI, the cluster and local runs read the same credentials and a rotation reaches them by running this again.

Invocation#

Shell
skarbiec ci set|keep github <owner/repo> --env-from <file> [--environment <name>] [--yes]
skarbiec ci set|keep kubernetes <namespace>/<name> --env-from <file> [--context <name>] [--yes]
skarbiec ci kept
skarbiec ci forget <target> <place>

Purpose#

Keep a repository's GitHub Actions secrets, or a cluster's Kubernetes Secret, the same as the vault: the bindings file exec --env-from reads names which value each secret holds, so CI, the cluster and local runs read the same credentials and a rotation reaches them by running this again.

Required inputs and options#

  • set or keep, then github and the repository as owner/repo, or kubernetes and the Secret as namespace/name. --env-from is the bindings file, NAME=<id>:<field> a line, as env import writes it; --environment sets the secrets of one Actions environment instead of the repository's; --context names the kubectl context, the current one otherwise; --yes sets them. gh, signed in, or kubectl, able to reach the cluster, must be on this machine.

Output and state effects#

  • set without --yes prints ok, applied false, the repo or secret, the environment or context and secrets (each secret's name, item and field) and sets nothing. With --yes, reads every value first. For github it runs gh secret set <NAME> --repo <owner/repo> [--env <environment>] once per binding with the value on gh's standard input, journals ci-secrets-set with the names and counts, and prints applied true, set (the secrets gh set) and refused (each one gh refused, with gh's status and sentence); ok is true only when none was refused. For kubernetes it hands kubectl apply --server-side --force-conflicts --field-manager skarbiec one Opaque Secret whose stringData holds every value under its variable name on its standard input — server-side apply keeps no last-applied annotation, which would hold the values again in plain text — journals ci-secrets-kubernetes, and prints applied true with kubectl's answer; a Deployment reads it through envFrom.secretRef. No value is printed or passed as an argument. keep <target> <place> sets the secrets as set --yes does and, when every one was set, records the target, its place, the bindings file as an absolute path, its --environment or --context and each bound item's revision in <vault file>.ci-secrets.json beside the vault — this host's, never the vault's — and journals ci-secrets-kept; every maintain pass on this host then sets a kept target again once one of its items has a new revision, recording the new revisions, and fails naming a target it could not set. kept prints each target, place, bindings, scope, changed_since (the items whose revision moved since the last set) and error when the bindings or an item cannot be read; forget removes one and journals ci-secrets-forgotten. The operator API answers set at POST /v1/operator/ci-secrets with target (github or kubernetes), place, bindings as an absolute path, optional environment or context, and yes, and keep, kept and forget at /v1/operator/ci-secrets/keep, /kept and /forget, on the machine it runs on only.

Refusals#

  • No verb, a verb ci has no form for, a target and place without set or keep, a target that is neither github nor kubernetes, a repository that is not owner/repo, a Secret that is not namespace/name, no --env-from, or an empty --environment or --context exits 2 with `usage: ci set|keep github <owner/repo> --env-from <file> [--environment <name>] [--yes] | ci set|keep kubernetes <namespace>/<name> --env-from <file> [--context <name>] [--yes] | ci kept | ci forget <target> <place>`. A bindings file that cannot be read or holds a line that is not NAME=<id>:<field> is refused quoting the line, and an item or field a binding names that is missing is refused before anything is set. kubectl's refusal of the Secret fails with kubectl's status and sentence, and a CLI that is not installed is named with the operating system's error. keep records nothing when the set fails, with `<target> <place> was not set, so it is not kept: <refused>`; forget refuses a target that is not kept with `<target> <place> is not kept here; `skarbiec ci kept` lists what is`.

Examples#

skarbiec ci set github acme/api --env-from .env.skarbiec skarbiec ci set github acme/api --env-from .env.skarbiec --environment production --yes skarbiec ci set kubernetes prod/api-env --env-from .env.skarbiec --context prod-cluster --yes skarbiec ci keep github acme/api --env-from .env.skarbiec # maintain sets them again after a rotation skarbiec ci kept skarbiec ci forget github acme/api