Help us shape the future of Go! Take the 2026 Go Developer Survey

vauthlogin

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: ISC Imports: 21 Imported by: 1

README

vauth-login

A Vault token, ready to use

Authenticate to Vault with your SSH agent or JWT and get the token on stdout. The encrypted cache keeps it ready for the next call. Available as a Node module and CLI, a Go module and CLI, and binaries for Windows and Linux.

Quick login

export VAULT_TOKEN=$(vauth-login)

Install

Pick whichever fits the machine in front of you:

# node
npm install -g vauth-login

# go
go install github.com/131/vauth-login/cmd/vauth-login@latest

# binary, linux
wget -O vauth-login https://github.com/131/vauth-login/releases/latest/download/vauth-login-linux-amd64
chmod +x vauth-login

# binary, windows (cmd or PowerShell)
curl.exe -fsSL -o vauth-login.exe https://github.com/131/vauth-login/releases/latest/download/vauth-login-windows-amd64.exe

The npm package carries the Node CLI and module. Windows binaries are Authenticode signed, with SHA256SUMS on every release. Check the checksum and put the binary on your PATH. The release workflow requires the signing server.

Usage

Get a token using your configured authentication and available cache:

export VAULT_TOKEN=$(vauth-login)

The token is written raw to stdout, without a trailing newline. Status goes to stderr, for example Vauth token: reused · 11h.

Force a fresh login:

vauth-login --renew

In CI, trust the Vault selected by the project's ./.vauthrc without the confirmation described under Configuration:

export VAULT_TOKEN=$(vauth-login --accept)

Check the version or show help:

vauth-login version
vauth-login --help

login and connect are optional aliases for the default operation. The Node library returns the token; cnyks writes that result with --ir://raw. Its help prints the generated command list on stderr, and --ir://run=version selects the version method directly.

Configuration

The first existing file wins: VAUTHRC, ./.vauthrc, then ~/.vauthrc. VAULT_ADDR supplies the default Vault address. Authentication fields support $${env.NAME} substitution from the process environment.

vault_addr: https://vault.example.test
ssh_auth:
  path: ssh
  role: developer
# Or jwt_auth: {path: jwt, role: developer, jwt: "$${env.LOGIN_JWT}"}
token_cache: true

Configuration keys: vault_addr, ssh_auth, jwt_auth, token_cache, and known_vaults.

A ./.vauthrc belongs to the project; ~/.vauthrc belongs to the user. Before the first request to a Vault selected by a project file, the user must vouch for that address: either it is the vault_addr of ~/.vauthrc, or it is listed in its known_vaults. Otherwise vauth-login asks Continue? [y/N] once on the terminal, and refuses without one. VAUTHRC and ~/.vauthrc never ask; --accept never asks either (CI). Reusing a valid cached token makes no request and asks nothing.

# ~/.vauthrc
known_vaults:
  - https://vault.example.test
  - https://vault.partner.example

SSH authentication uses SSH_AUTH_SOCK. Without it, the native Windows binary autodiscovers the Pageant (0.75+) named pipe, then the OpenSSH agent pipe. Disk caching requires an SSH agent; JWT authentication can still work. The Node implementation uses ssh2's Pageant transport when no Windows socket is configured.

What It Does

An inherited VAULT_TOKEN is the caller's: it is returned as is, announced as Vauth token: inherited, and never looked up, renewed or written to the cache. Without it, a usable cached token is reused locally. In the last third of its lease it is renewed if renewable, otherwise replaced by a fresh login. An expired cache or a 400/403 from token lookup/renewal triggers login; other lookup/renewal failures propagate to the caller. --renew forces a fresh login.

The cache is ~/.vauth/tokens/<session-sha256>.creds, encrypted and authenticated by ssh-agent-crypt v3. The session hash and JSON payload are identical between Node and Go: either implementation can read the other's cache. Native Windows uses the Windows user's home; WSL uses the Linux user's home.

Cache encryption chooses VAUTH_USER_IDENTITY, then VAUTH_USER_MAIL, then the ssh-agent-crypt default selector. Decryption uses the fingerprint embedded in the armor. Writes use distinct temporary files and atomic replacement; normal reuse leaves the cache unchanged. Cache failures keep the token available for the current call. token_cache: false disables cache access.

Security

The selected configuration file determines the Vault origin and authentication role. Review it before permitting SSH-agent signing. Whoever controls the agent socket can decrypt its caches. Tokens are bearer credentials: keep them out of logs, shell traces and plaintext files.

API & SDK

Node module, Go module, token lifecycle, Vault HTTP transport and the test matrix: API_and_tests.md.

Security audit

Two independent reviews of the design and of the two implementations, each scoring Coolness, Robustness and Safety out of 20: SECURITY_AUDIT_fable-5.1.md and SECURITY_AUDIT_gpt-6.1-sol.md.

Criterion Codex (Claude Fable 5.1) Codex (GPT 6.1)
✨ Coolness 17/20 18/20
Robustness 16/20 14/20
Safety 14/20 13/20

Both reviews converge on the same items: the trust model of a ./.vauthrc found in the current directory, cached tokens trusted until expiry without a revocation check, and the Node CLI exiting 0 with an empty token when no authentication method is configured. Scores are opinions, not a certification.

Since these reviews, a project ./.vauthrc pointing at a Vault unknown to ~/.vauthrc requires confirmation (known_vaults), and an inherited VAULT_TOKEN is returned as is instead of being looked up and cached.

Credits

ISC license.

Documentation

Overview

Package vauthlogin authenticates to Vault using ssh-agent or JWT and caches the token with ssh-agent-crypt. It does not resolve environments.

Index

Constants

View Source
const PackageName = "vauth-login"

PackageName is the npm name a project uses to pin vauth: `"dependencies": {"vauth-login": "^1.0.0"}` in its package.json.

Variables

View Source
var Version string

Version is the running version (ldflags -X or debug.ReadBuildInfo), checked by New against the current directory's package.json; empty or non-semver values ("(devel)") skip the check.

Functions

func CheckProjectVersion

func CheckProjectVersion(manifest, version string) error

CheckProjectVersion fails when manifest (a package.json) declares a dependency on PackageName that version does not satisfy. A missing manifest, dependency or unparseable version is not an error.

func Environ

func Environ() map[string]string

Environ converts os.Environ() into a map.

func HumanDiff

func HumanDiff(seconds float64, max int) string

HumanDiff formats a duration in seconds with at most max units ("1d 3h"), like nyks/date/humanDiff.

func KnownVault added in v1.1.0

func KnownVault(addr, home string, environ map[string]string) bool

KnownVault reports whether addr is the vault_addr or one of the known_vaults of the user's ~/.vauthrc at home. A missing or unreadable file knows nothing.

func LocateRC

func LocateRC(environ map[string]string, cwd, home string) string

LocateRC returns the first existing configuration file among VAUTHRC, ./.vauthrc and ~/.vauthrc, or an empty string.

func ReplaceEnv

func ReplaceEnv(str string, dict Lookup) string

ReplaceEnv expands $$key and $${key} macros against dict (nyks string/replaceEnv semantics): unknown keys stay, expansions recurse.

Types

type HTTPError

type HTTPError struct {
	Status int
	Body   string
}

HTTPError reports an unexpected Vault status code.

func (*HTTPError) Error

func (e *HTTPError) Error() string

type JWTAuth

type JWTAuth struct {
	Path string `yaml:"path"`
	JWT  string `yaml:"jwt"`
	Role string `yaml:"role"`
}

JWTAuth configures a Vault jwt login.

type Lookup

type Lookup map[string]any

Lookup resolves dotted paths ($${env.X}) in nested string maps.

type LookupToken

type LookupToken struct {
	TTL           float64 `json:"ttl"`
	Renewable     bool    `json:"renewable"`
	CreationTTL   int64   `json:"creation_ttl"`
	EntityID      string  `json:"entity_id"`
	LeaseDuration int64   `json:"lease_duration"`
}

LookupToken is the token metadata returned by lookup-self.

type RC

type RC struct {
	VaultAddr  string   `yaml:"vault_addr"`
	SSHAuth    *SSHAuth `yaml:"ssh_auth"`
	JWTAuth    *JWTAuth `yaml:"jwt_auth"`
	TokenCache *bool    `yaml:"token_cache"`
	// KnownVaults lists, in ~/.vauthrc, the Vault addresses a project's
	// ./.vauthrc may select without confirmation.
	KnownVaults []string `yaml:"known_vaults"`
	// contains filtered or unexported fields
}

RC is the parsed .vauthrc, after $${env.X} expansion.

func ParseRC

func ParseRC(body []byte, file string, environ map[string]string) (*RC, error)

ParseRC parses a .vauthrc body and expands its $${env.X} macros against environ. All other configuration sections are ignored.

func (*RC) AuthKey

func (rc *RC) AuthKey() string

AuthKey renders ssh_auth and jwt_auth as JSON members, in the order of the parsed document. Programmatic configurations are rendered from the structs.

type SSHAuth

type SSHAuth struct {
	Path string `yaml:"path"`
	Role string `yaml:"role"`
}

SSHAuth configures the Vault ssh auth plugin (nonce challenge).

type Vauth

type Vauth struct {
	RC         RC
	VaultAddr  string
	VaultToken string
	// Agent is the ssh-agent address; empty disables ssh authentication.
	Agent string
	// TokenCache enables the on-disk token cache in CacheDir.
	TokenCache bool
	CacheDir   string
	HomeDir    string
	// Environ is the process environment snapshot used for macros.
	Environ map[string]string
	// Stderr defaults to the process error stream.
	Stderr     io.Writer
	HTTPClient *http.Client
	// Now overrides the clock (tests).
	Now func() time.Time
	// RCFile is the configuration file New selected, if any.
	RCFile string
	// Confirm is asked once before the first request to a Vault selected by
	// a project's ./.vauthrc that ~/.vauthrc does not know; nil prompts on
	// the terminal and refuses without one.
	Confirm func(addr, file string) (bool, error)
	// Accept trusts the selected Vault without confirmation (--accept, CI).
	Accept bool
	// contains filtered or unexported fields
}

Vauth is a configured client. New builds one from the process environment; fields may be set directly for programmatic use.

func New

func New() (*Vauth, error)

New loads the configuration from the environment and the first .vauthrc found (VAUTHRC, ./.vauthrc, ~/.vauthrc).

func (*Vauth) Connect

func (v *Vauth) Connect(renew bool) (string, error)

Connect establishes VaultToken: an inherited token is returned as is; otherwise the cached one (renewed in the last third of its lease), then a new login. With renew, a new login is forced. Without an authentication method, no token is used.

func (*Vauth) LookupSelf

func (v *Vauth) LookupSelf(token string) (*LookupToken, error)

LookupSelf validates a token online and returns metadata including entity ID.

func (*Vauth) Request

func (v *Vauth) Request(method, path, token string, payload any, expect int) (int, []byte, error)

Request performs a JSON Vault call. Set expect to zero to handle status yourself.

func (*Vauth) TokenCacheFile

func (v *Vauth) TokenCacheFile() string

TokenCacheFile is the armored cache file for this configuration.

func (*Vauth) TokenCacheKey

func (v *Vauth) TokenCacheKey() string

TokenCacheKey isolates cached tokens by Vault address and authentication configuration. It matches the Node implementation byte for byte.

func (*Vauth) VaultURL

func (v *Vauth) VaultURL(path string) string

VaultURL returns an API URL relative to this configured Vault.

Directories

Path Synopsis
cmd
vauth-login command
Command vauth-login authenticates to Vault and writes the token to stdout.
Command vauth-login authenticates to Vault and writes the token to stdout.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL