CLI command

skarbiec helper

Let a tool on this machine read its credentials from the vault each time it needs them — the AWS CLI and SDKs, kubectl, Terraform, Cargo, git and Docker — so none sits in the tool's own file in plain text and a replaced secret is used at once, and move the ones already sitting there into the vault in one step. It is one operation for every tool; each tool is an adapter that knows where the tool keeps its configuration and how it asks for a credential, and `helper list` names them with each one's usage line.

Invocation#

Shell
skarbiec helper list
skarbiec helper status [<tool>]
skarbiec helper setup aws <id> --profile <name>
skarbiec helper setup kube <id> --user <kubeconfig user>
skarbiec helper setup terraform
skarbiec helper setup cargo
skarbiec helper setup git <host>
skarbiec helper setup docker <registry> --link <dir>
skarbiec helper import aws <id> --profile <name> [--tags <tag,...>]
skarbiec helper import kube <id> --user <kubeconfig user> [--tags <tag,...>]
skarbiec helper import terraform <id> --host <host> [--tags <tag,...>]
skarbiec helper import cargo <id> --registry <name> --host <index host> [--tags <tag,...>]
skarbiec helper import git <id> <host> [--username <name>] [--tags <tag,...>]
skarbiec helper import docker <id> <registry> --link <dir> [--tags <tag,...>]
skarbiec helper unset aws --profile <name> | kube --user <kubeconfig user> | terraform | cargo | git <host> | docker <registry>
# what each tool then runs itself
skarbiec helper answer aws <id>
skarbiec helper answer kube <id>
skarbiec helper answer cargo
skarbiec helper answer git get|store|erase
terraform-credentials-skarbiec get|store|forget <host>
docker-credential-skarbiec get|store|erase|list

Purpose#

Let a tool on this machine read its credentials from the vault each time it needs them — the AWS CLI and SDKs, kubectl, Terraform, Cargo, git and Docker — so none sits in the tool's own file in plain text and a replaced secret is used at once, and move the ones already sitting there into the vault in one step. It is one operation for every tool; each tool is an adapter that knows where the tool keeps its configuration and how it asks for a credential, and `helper list` names them with each one's usage line.

Required inputs and options#

  • The verb, then the tool, then what that tool's usage line declares for the verb; a flag the form does not take is refused before the adapter runs. aws: an access-key item and the AWS profile — default for the default one — in AWS_CONFIG_FILE, else ~/.aws/config, with static keys in AWS_SHARED_CREDENTIALS_FILE, else ~/.aws/credentials. kube: a token or certificate item and the kubeconfig user; kubectl must be on PATH and reads KUBECONFIG, else ~/.kube/config. terraform: setup and unset take nothing and act on TF_CLI_CONFIG_FILE, else ~/.terraformrc, and the plugin directory ~/.terraform.d/plugins; import takes --host, a host credentials.tfrc.json (TF_CLI_CONFIG_DIR, else ~/.terraform.d) holds a token for. cargo: setup and unset take nothing and act on config.toml in CARGO_HOME, else ~/.cargo; import takes --registry — crates-io for [registry], or a [registries.<name>] table — and --host, the registry's index host. git: the forge's host as git names it, with a port after a colon when it uses one; import takes --username when the store keeps several sign-ins for the host. docker: the registry's host, and for setup and import --link, an existing directory on PATH where docker-credential-skarbiec is linked. import always takes the new item's id first and optional --tags. A login offered on a host answers terraform, cargo, git and docker: its password is the token. answer is the tool's own protocol, run by the configuration setup writes: the AWS CLI's credential_process, kubectl's exec plugin, Cargo's token-from-stdout provider with the index in CARGO_REGISTRY_INDEX_URL, git's credential helper with its request on standard input, and Docker's and Terraform's helper programs, which run this binary under their own names. POST /v1/operator/helper/list and /status (with an optional tool) and /setup, /import and /unset take tool and the arguments and flags of that tool's form by name, a --link only as an absolute path; they act on the machine serving the API and are never forwarded to a remote vault owner.

Output and state effects#

  • Every answer names the tool. aws: setup writes `credential_process = "<this binary>" helper answer aws <id>` into the profile's section, replacing an earlier credential_process line and keeping every other line, and prints item, profile, config and line; answer prints Version, AccessKeyId, SecretAccessKey and a temporary key's SessionToken and journals aws-credential with the item and key id; import stores the profile's key as a new access-key item named AWS profile <name>, reads it back, takes it out of the credentials file and runs setup; unset removes this vault's line. kube: setup runs `kubectl config set-credentials <user>` with this binary as the exec command and `helper answer kube <id>` as its arguments, apiVersion client.authentication.k8s.io/v1 and interactive mode Never, and prints kubectl's sentence; answer prints the ExecCredential — status.token for a token item, status.clientCertificateData with its chain and status.clientKeyData for a certificate item — and journals kube-credential; import moves a bearer token, or inline client-certificate-data and client-key-data, into a new token or certificate item, runs setup and only then has kubectl unset what it moved; unset runs `kubectl config unset users.<user>.exec`. terraform: setup links terraform-credentials-skarbiec in the plugin directory to this binary and appends a credentials_helper "skarbiec" block, run again changing nothing, and names the hosts credentials.tfrc.json still holds, which Terraform no longer reads; Terraform's get <host> is answered {"token": …} and journalled as terraform-credential, a host with no login {} with the reason on standard error; import moves one host's token into a new login offered on it; unset removes the block and the link. cargo: setup adds `global-credential-providers = ["cargo:token-from-stdout <this binary> helper answer cargo"]` under [registry], run again changing nothing, and names the registries credentials.toml still holds; answer prints the token of the login offered on the index host and journals cargo-credential; import moves one registry's token into a new login offered on the index host; unset removes the line. git: setup sets credential.https://<host>.helper globally to `!<this binary> helper answer git`; answer get prints username= and password= of the login login get chooses for the request's host and journals git-credential, store and erase read the request and change nothing; import moves the https sign-in git's store helper left in ~/.git-credentials or $XDG_CONFIG_HOME/git/credentials into a new login, runs setup and only then removes that line; unset removes the setting. docker: setup links <dir>/docker-credential-skarbiec to this binary and sets credHelpers.<registry> to skarbiec in config.json (DOCKER_CONFIG, else ~/.docker), keeping every other member; get prints {"ServerURL","Username","Secret"} and journals docker-credential, or Docker's `credentials not found in native keychain` when no login fits; import moves the base64 sign-in docker login left under auths into a new login, runs setup and only then removes it; unset removes the registry's entry and keeps the link. setup, import and unset journal <tool>-credential-setup, -import and -unset. status prints, for one tool or each, its state — the AWS profiles and kubeconfig users that run this vault with the item and whether the program is still there, Terraform's and Cargo's configured, program and plain-text hosts or registries, the forges git asks here and the hosts ~/.git-credentials still keeps, and the registries Docker sends here with the program on PATH and the base64 sign-ins left — or the error that kept it from being read. list prints each tool with what it serves and its usage line. No answer of the person's side carries a credential, and doctor's helpers check names every setting whose program is gone with the setup that points it here again.

Refusals#

  • An unknown tool is refused naming the tools there are; a verb a tool has no form for, a flag its form does not take and a missing argument or flag exit 2 with the tool's usage line. aws: an item that is not an access-key or holds no key id or secret; setup of a profile that keeps aws_access_key_id in the credentials or config file, which AWS uses first, naming the helper import aws that moves it; import of a profile with no key there; unset of a profile with no credential_process or one that is not this vault's. kube: an item that is neither a token nor a certificate; import of a user with no inline credential, one whose certificate sits in files — naming `kubectl config set-credentials --embed-certs` — or inline data that is not base64 PEM; unset of a user whose exec is not this vault's; kubectl's own refusal with its words. terraform: setup when the configuration names another credentials helper or the plugin path holds another program; import of a host with no token; unset when no skarbiec helper is named; store and forget naming login new and delete. cargo: setup when global-credential-providers holds a list this vault did not write, naming the line to add, or this binary's path holds a quote or space; import of a registry with no token; unset when no skarbiec provider is named; answer without CARGO_REGISTRY_INDEX_URL or with no login on its host. git: a host that is not one; import of a host the store keeps no sign-in for or several without --username, naming them; answer for any protocol but https, with `skarbiec answers only https`, and for a host no login fits, so git asks elsewhere. docker: a --link that is not an absolute existing directory, or a link naming another binary; import of a registry auths keeps nothing for — Docker Desktop's credsStore keeps them elsewhere — or that is not base64 username:password; unset of a registry with no entry; store naming set, erase naming delete, and list. Every import refuses an id that exists before anything changes, checks the item reads back, and when setup is refused writes the tool's file back as it was, the item holding a copy, both named. answer is refused on the operator API, whose answer must never be a credential.

Examples#

skarbiec helper list skarbiec helper import aws aws-ci --profile ci --tags cloud aws sts get-caller-identity --profile ci skarbiec helper import kube prod-cluster-token --user prod-admin --tags cluster skarbiec helper setup terraform skarbiec helper import cargo crates-io-token --registry crates-io --host index.crates.io skarbiec helper import git github-token github.com --tags forge skarbiec helper import docker ghcr-token ghcr.io --link /usr/local/bin --tags registry skarbiec helper status skarbiec helper unset aws --profile ci