Documentation
¶
Overview ¶
Package creds resolves credentials (spec §7). M1 implements the read class.
tailkeeper never reads variables it did not define: TS_* and TAILSCALE_* are ignored even when present, because developer shells often hold full-permission user tokens in them.
Index ¶
Constants ¶
const ( EnvClientID = "TAILKEEPER_READ_CLIENT_ID" EnvClientSecret = "TAILKEEPER_READ_CLIENT_SECRET" EnvAPIKey = "TAILKEEPER_READ_API_KEY" EnvOIDCToken = "TAILKEEPER_OIDC_TOKEN" EnvReexec = "TAILKEEPER_REEXEC" )
Variable names of the read class (spec §7.3).
Variables ¶
var ErrReexecRequired = tkerr.New(tkerr.CredentialUnavailable,
"the exec provider must re-run tailkeeper under its wrapper", "")
ErrReexecRequired means the exec provider must re-run tailkeeper under its wrapper.
Functions ¶
func PrivacyKey ¶
PrivacyKey reads TAILKEEPER_PRIVACY_KEY from where provider p keeps the read credential (spec §7.6): the environment for env and exec (exec's wrapper puts it there), the credential file for file. oidc stores no secret, so it has no key. No key set is not an error: masking then names nothing.
Types ¶
type Read ¶
type Read struct {
Kind Kind
ClientID string // OAuth client or federated identity ID: not a secret
ClientSecret Secret // OAuth only
APIKey Secret // API access token only
Audience string // federated only
IDToken func(ctx context.Context) (string, error)
Provider string // env, file, exec or oidc
}
Read is a resolved read credential. Its String method never prints a secret, and shows only the start of the client ID.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret holds a credential's bytes in a closure, not in a field: fmt prints a struct's fields itself, without calling Format, for a bad verb (%p, %w) and for an unexported field of another struct, and a function prints as an address under every verb. So no verb, on a Secret or on anything holding one, and no JSON encoder or logger, can reach the bytes. privacy.Key is built the same way.
func (Secret) Format ¶
Format keeps the bytes out of every verb fmt hands a Format method; it has a value receiver so that a Secret printed by value, as a field or an element, calls it.
func (Secret) MarshalText ¶
MarshalText keeps the bytes out of JSON and of text-based loggers.
type System ¶
type System struct {
Getenv func(string) string
ReadFile func(string) ([]byte, error) // files a variable names ("file:" values) and the OIDC token file
// ReadSecretFile checks a credential file and reads it through the file it
// checked, so nothing can be put in the path's place between the check and the
// read. It is config.ReadSecretFile when nil: a System built without it takes the
// safe read, and there is no path that checks a file by name and reads it by name
// afterwards. A test that has no real file replaces it with a fake that does both.
ReadSecretFile func(string) ([]byte, error)
HTTPClient *http.Client // used only to fetch platform OIDC tokens
}
System is the environment and filesystem a provider reads. Tests replace it.