Documentation
¶
Overview ¶
Package clustercred is where the credential a self-hosted Burrow issued lives on disk (ADR-0084 §1).
Until now a self-hosted install had one token, in a Secret on the cluster, that everybody presented. Signing in mints a credential for one person, and this is where it is kept: beside the Burrow Cloud credential, under the same 0700 directory, written with the same discipline (internal/credfile). One shape for both, because the mechanism is the same one — a random token the control plane stores only the hash of — and the whole point of ADR-0084 §2 converging on it was to stop having two.
SIGNING IN ISSUES A PAIR, exactly as the Burrow Cloud sign-in does (ADR-0084 §3): the person's, which authenticates `burrow`, and the agent's, which authenticates `burrow-agent`. They are two files, in two directories, so that revoking either leaves the other working — an over-eager agent and a lost laptop are different decisions, and one credential cannot express both.
IT IS KEYED BY INSTALL ID, NOT BY CONTEXT NAME. A kube context name is a label: it can be renamed, two merged kubeconfigs can share one, and a provider regenerates it deterministically for a rebuilt cluster (ADR-0084 §5). The credential belongs to the Burrow that issued it, so the install is what names the file — a renamed context still finds it, and a rebuilt cluster does not accidentally present the old install's token to the new one. Two targets pointed at the same install share one credential, which is correct: it is one install and one principal.
NOTHING HERE PUTS A TOKEN IN AN ERROR, a log line, or a returned string, on exactly the terms internal/cloudcred does not.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoCredential = errors.New("no Burrow credential for this install")
ErrNoCredential reports that no credential for this install is on disk. Callers match on it to tell "never signed in to this install" — the ordinary state of every install today, and the one that falls back to the shared install token — from "signed in and something is wrong with the file".
Functions ¶
func EnsureWritable ¶
EnsureWritable checks that a credential could be stored, without storing one. It exists because of the ORDER a sign-in happens in: burrowd mints the token, returns it once, and never produces it again, so a write that fails afterwards has destroyed a credential that already exists on the server. On a first claim that is worse than it sounds — the install is now claimed by a principal whose only token is gone.
So the directory is created and probed BEFORE anything is minted, which turns the common cause of that state (a home directory that cannot be written) into a refusal with nothing lost. It cannot rule the state out — a disk can fill between the probe and the write — and it removes the case that actually happens.
func Path ¶
Path returns the file an install's credential is read from and written to. It is the single answer to "where is it", used by both the writer and the reader, so the two cannot drift into writing one place and reading another.
func Store ¶
func Store(kind Kind, cred Credential) (string, error)
Store writes an install's credential and returns the path it wrote. The file handling — 0600 under a 0700 directory, an O_EXCL temporary and a rename — is internal/credfile's.
func Token ¶
Token returns the token to present to an install, or empty when there is none to present.
EVERY FAILURE IS AN EMPTY STRING, deliberately, because of where this is called from: the caller is about to connect, and its fallback is the shared install token, which still works (ADR-0084 "Existing installs keep working"). An install nobody has signed in to, a credential file somebody deleted, a home directory that cannot be read — all of them mean "present nothing extra" rather than "refuse to connect". A credential that exists and is broken is reported by Load, which is what `burrow auth status` and the sign-in path call.
Types ¶
type Credential ¶
type Credential struct {
// InstallID is the Burrow that issued this (ADR-0084 §5).
InstallID string `json:"installId"`
// PrincipalID is the opaque identity it authenticates as.
PrincipalID string `json:"principalId"`
// Principal is that principal's handle, carried so a message can name who is signed in without
// a round trip.
Principal string `json:"principal"`
// CredentialID is which credential this is, so a revocation can name it.
CredentialID string `json:"credentialId"`
// Kind is what burrowd RECORDED this credential as (`user`, `agent`, `machine`). It is stored
// for display only: what a credential is, is the control plane's answer, read from its own row
// on every request and never taken from anything the client says (ADR-0084 §3).
Kind string `json:"kind,omitempty"`
// ExpiresAt is when it stops authenticating, RFC 3339, or empty when it does not expire.
ExpiresAt string `json:"expiresAt,omitempty"`
// Token is the secret.
Token string `json:"token"`
}
Credential is one credential a self-hosted install issued, as stored.
It records WHICH INSTALL issued it as well as living in a file named for it, so a file that ends up under the wrong name is caught rather than spent against an install that never issued it — the same check cloudcred makes on its kind.
type Kind ¶
type Kind string
Kind is which of the pair a credential is. It is stored in the file as well as implied by the directory, so somebody who opens one can see what they are holding, and so a file that ends up in the wrong directory is caught rather than spent.
It is the same distinction cloudcred draws, in the same two directories, because it is the same distinction: which BINARY the credential belongs to. What burrowd recorded the credential AS is the Kind field on the stored Credential, which is burrowd's answer and never this one — a client that decided its own kind is exactly what ADR-0084 §3 refuses.