Documentation
¶
Overview ¶
Package tokenstore provides a pluggable credential store shared by the entiredb and entire-core CLIs.
By default it delegates to the OS keyring (macOS Keychain, Linux Secret Service, etc.). Set ENTIRE_TOKEN_STORE=file to use a JSON file instead, which is useful in CI environments that lack a keyring daemon.
When using the file backend the tokens are stored in $ENTIRE_TOKEN_STORE_PATH (default: ~/.config/entire/tokens.json).
Service-name conventions:
- "entire:<cluster-host>" — entiredb cluster login tokens
- "entire-core:<core-base-url>" — entire-core control-plane tokens
- "<service>:refresh" — refresh-token entry paired with the corresponding access-token service
Index ¶
- Constants
- Variables
- func ClusterKeyringService(host string) string
- func CoreKeyringService(coreURL string) string
- func DecodeTokenWithExpiration(encoded string) (token string, expiresAt time.Time)
- func Delete(service, user string) error
- func EncodeTokenWithExpiration(token string, expiresIn int64) string
- func Get(service, user string) (string, error)
- func IsTokenExpiredOrExpiring(expiresAt time.Time) bool
- func KeyringServiceForIssuerKey(key string) string
- func RefreshService(service string) string
- func Set(service, user, password string) error
- func UseFailingBackendForTesting(path string, failSet func(service, user string) bool) func()
- func UseFailingGetBackendForTesting(path string, failGet func(service, user string) bool) func()
- func UseFileBackendForTesting(path string) func()
Constants ¶
const ( ClusterKeyringPrefix = "entire:" // entiredb cluster-issued tokens CoreKeyringPrefix = "entire-core:" // entire-core control-plane tokens )
Keyring service-name prefixes. Tokens are filed under whichever issuer vouched for them, so a JWT obtained via an entire-core login flow lives at "entire-core:<base-url>" regardless of which CLI wrote it. Two CLIs sharing this prefix on the same machine read each other's writes.
const TokenExpirationBuffer = 5 * time.Minute
TokenExpirationBuffer is how long before expiration we should refresh.
const TokenExpirationSeparator = "|"
TokenExpirationSeparator separates the token from its expiration timestamp. Format: "token|expires_at_unix"
Variables ¶
var ErrNotFound = keyring.ErrNotFound
ErrNotFound is returned when a credential is not present in the store.
Functions ¶
func ClusterKeyringService ¶
ClusterKeyringService returns the service name for tokens issued by an entiredb cluster. host is typically the cluster's entry domain.
func CoreKeyringService ¶
CoreKeyringService returns the service name for tokens issued by entire-core. coreURL is the base URL of the issuer; trailing slashes are normalized away so callers don't have to.
func DecodeTokenWithExpiration ¶
DecodeTokenWithExpiration decodes a token that may have an expiration timestamp. Returns the token and expiration time. If no expiration is encoded, returns the token as-is and a zero time.
func EncodeTokenWithExpiration ¶
EncodeTokenWithExpiration encodes a token with its expiration time as a "token|expires_at_unix" suffix. Callers must pass a positive expiresIn — the encoded suffix is the contract that tells future readers when to refresh, and a zero/negative TTL would record an immediately-expired token.
func IsTokenExpiredOrExpiring ¶
IsTokenExpiredOrExpiring checks if a token is expired or will expire soon. A zero expiresAt is treated as "unknown, assume expired".
func KeyringServiceForIssuerKey ¶
KeyringServiceForIssuerKey infers the right service prefix from a raw issuer key (entire-core URL or entiredb cluster host). URL-shaped keys (anything beginning with a scheme) are treated as entire-core issuers; bare hostnames as cluster issuers. Used by callers that derive a service name without already having a *contexts.Context in hand (tests, entiredb's pre-resolution code paths).
func RefreshService ¶ added in v0.7.4
RefreshService returns the paired refresh-token service name for an access-token service, following the "<service>:refresh" convention documented in this package's service-name conventions. Callers store the raw refresh token under (RefreshService(service), user) alongside the access token at (service, user).
func UseFailingBackendForTesting ¶ added in v0.7.4
UseFailingBackendForTesting wraps a file backend so Set returns an error for any (service, user) pair where failSet reports true; all other operations behave normally. It lets tests exercise partial-write failure paths (e.g. the refresh-then-access ordering in contextTokenStore) without exposing the unexported store interface. Returns a cleanup function.
func UseFailingGetBackendForTesting ¶ added in v0.7.4
UseFailingGetBackendForTesting is the read-side analogue: Get returns an error for any (service, user) pair where failGet reports true. Used to test that callers surface a real store failure rather than swallowing it.
func UseFileBackendForTesting ¶
func UseFileBackendForTesting(path string) func()
UseFileBackendForTesting points the package-level token store at a per-test JSON file and returns a cleanup function that restores the previous backend (re-resolving on next use). It serializes against concurrent Get/Set/Delete calls via the same mutex they use, so it is safe to call from any test even if other goroutines are mid-call.
Each call replaces the active backend; tests that invoke this from parallel subtests will trample each other and should arrange their own per-subtest paths if they actually need isolation.
Types ¶
This section is empty.