Documentation
¶
Index ¶
- Variables
- func AppRoleLogin(ctx context.Context, httpClient *http.Client, addr, roleID, secretID string) (token string, ttl time.Duration, err error)
- func Bootstrap(ctx context.Context, client *Client, jwtAuthPath string, ...) error
- func EnrollCredential(ctx context.Context, client *Client, sub, service string, data map[string]any) error
- func InitAppRole(ctx context.Context, addr, roleID, tokenFile string) (token string, ttl time.Duration, err error)
- func ReadTokenFile(path string) (string, error)
- func RenewSelf(ctx context.Context, httpClient *http.Client, addr, token string) (time.Duration, error)
- func ResolveSessionSecret(ctx context.Context, client *Client) (string, error)
- func ResolveWorkerKey(ctx context.Context, client *Client) ([]byte, error)
- func WriteTokenFile(path, token string) error
- type Client
- func (c *Client) Addr() string
- func (c *Client) AdminToken() string
- func (c *Client) Health(ctx context.Context) error
- func (c *Client) JWTLogin(ctx context.Context, mountPath, accessToken string) (token string, ttl time.Duration, err error)
- func (c *Client) KVRead(ctx context.Context, path string, token string) (map[string]any, error)
- func (c *Client) KVWrite(ctx context.Context, path string, data map[string]any) error
- func (c *Client) SecretExists(ctx context.Context, path string) (bool, error)
- type TokenRenewer
- type VaultTokenCache
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("secret not found")
ErrNotFound is returned by KVRead when the secret path does not exist in vault. Callers can use errors.Is to distinguish this from transient failures.
Functions ¶
func AppRoleLogin ¶
func AppRoleLogin(ctx context.Context, httpClient *http.Client, addr, roleID, secretID string) (token string, ttl time.Duration, err error)
AppRoleLogin authenticates to OpenBao using AppRole credentials. Returns the client token and its TTL.
func Bootstrap ¶
func Bootstrap(ctx context.Context, client *Client, jwtAuthPath string, skipPolicyScopeCheck bool) error
Bootstrap verifies OpenBao is configured correctly for blockyard. Checks:
- OpenBao is reachable and unsealed (GET /v1/sys/health)
- JWT auth method is enabled at the configured path
- The "blockyard-user" role exists
- KV v2 secrets engine is mounted at "secret/"
- At least one attached policy uses per-user path scoping (warning only)
Returns nil if all checks pass. Returns an error describing the first failure. The caller decides whether to treat this as fatal.
func EnrollCredential ¶
func EnrollCredential(ctx context.Context, client *Client, sub, service string, data map[string]any) error
EnrollCredential writes a user's credential for a service into OpenBao's KV v2 store at secret/data/users/{sub}/apikeys/{service}. Uses the admin token, not the user's scoped token.
func InitAppRole ¶ added in v0.0.3
func InitAppRole(ctx context.Context, addr, roleID, tokenFile string) (token string, ttl time.Duration, err error)
InitAppRole authenticates to vault using AppRole. It first tries a persisted token (renew-self), then falls back to AppRole login with secret_id from the environment.
func ReadTokenFile ¶
ReadTokenFile reads a vault token from the given file path. Returns an empty string and nil error if the file does not exist.
func RenewSelf ¶
func RenewSelf(ctx context.Context, httpClient *http.Client, addr, token string) (time.Duration, error)
RenewSelf renews the given vault token. Returns the new TTL.
func ResolveSessionSecret ¶ added in v0.0.3
ResolveSessionSecret reads or generates session_secret from vault. If the key exists at secret/data/blockyard/server-secrets, it's used. Otherwise, a new 32-byte random value is generated, stored, and returned.
func ResolveWorkerKey ¶ added in v0.0.3
ResolveWorkerKey reads or generates the worker signing key from vault. Follows the same pattern as ResolveSessionSecret: read if exists, generate + store if not. Transient vault errors are fatal -- only ErrNotFound triggers generation.
func WriteTokenFile ¶
WriteTokenFile atomically writes a vault token to the given file path. Uses temp file + rename for crash safety. File mode is 0600.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a lightweight HTTP client for OpenBao's REST API. It targets only the endpoints blockyard needs: JWT auth login, KV v2 read/write, and sys/health.
func NewClient ¶
NewClient creates a new OpenBao client. The adminToken is retrieved via a callback to avoid holding the plaintext value in a long-lived struct field.
func (*Client) AdminToken ¶
AdminToken returns the current admin token. Satisfies config.SecretResolver.
func (*Client) Health ¶
Health checks if OpenBao is reachable and unsealed. GET {addr}/v1/sys/health
func (*Client) JWTLogin ¶
func (c *Client) JWTLogin(ctx context.Context, mountPath, accessToken string) (token string, ttl time.Duration, err error)
JWTLogin exchanges an IdP access token for a scoped OpenBao token. POST {addr}/v1/auth/{mountPath}/login
func (*Client) KVRead ¶
KVRead reads a secret from the KV v2 secrets engine. GET {addr}/v1/secret/data/{path}
func (*Client) KVWrite ¶
KVWrite writes a secret to the KV v2 secrets engine using the admin token. PUT {addr}/v1/secret/data/{path}
func (*Client) SecretExists ¶
SecretExists checks whether a secret exists at the given KV v2 data path without reading its value. It queries the metadata endpoint (secret/metadata/...) which requires only metadata-read permission. GET {addr}/v1/secret/metadata/{path}
type TokenRenewer ¶
type TokenRenewer struct {
// contains filtered or unexported fields
}
TokenRenewer manages the lifecycle of a renewable vault token. It periodically renews the token at half its TTL, persists it to disk after each renewal, and tracks health for readyz checks.
func NewTokenRenewer ¶
func NewTokenRenewer(addr, initialToken, tokenFile string) *TokenRenewer
NewTokenRenewer creates a TokenRenewer with the given initial token. The token is immediately marked as healthy.
func (*TokenRenewer) Healthy ¶
func (r *TokenRenewer) Healthy() bool
Healthy reports whether the vault token is valid and renewable.
func (*TokenRenewer) Run ¶
func (r *TokenRenewer) Run(ctx context.Context, ttl time.Duration)
Run starts the renewal loop. It renews the token at ttl/2 intervals. On failure, it retries with exponential backoff (1s → 60s cap). Blocks until ctx is cancelled.
func (*TokenRenewer) Token ¶
func (r *TokenRenewer) Token() string
Token returns the current vault token. Safe for concurrent use. This is intended as the adminTokenFunc callback for Client.
type VaultTokenCache ¶
type VaultTokenCache struct {
// contains filtered or unexported fields
}
VaultTokenCache caches OpenBao tokens keyed by user sub. Avoids calling OpenBao's JWT login endpoint on every proxied request.
func NewVaultTokenCache ¶
func NewVaultTokenCache() *VaultTokenCache
NewVaultTokenCache creates an empty token cache.
func (*VaultTokenCache) Delete ¶
func (c *VaultTokenCache) Delete(sub string)
Delete removes a cached token (e.g. on logout).
func (*VaultTokenCache) Get ¶
func (c *VaultTokenCache) Get(sub string) (string, bool)
Get returns a cached token if it exists and has at least renewalBuffer of remaining validity. Returns ("", false) on miss or near-expiry.
func (*VaultTokenCache) Set ¶
func (c *VaultTokenCache) Set(sub string, token string, ttl time.Duration)
Set stores a token with the given TTL.
func (*VaultTokenCache) Sweep ¶
func (c *VaultTokenCache) Sweep() int
Sweep removes all expired tokens from the cache.