Documentation
¶
Overview ¶
Package secretref is the reference to a stored secret a caller writes into a request, `{{secret:<name>}}`, and the redaction of a secret's value from whatever comes back (#2051).
A placeholder is filled at the last moment, as the request is built for sending, so everything that records the call (the audit row, the call record, a script's recording, the arguments a cut response hands back) holds the placeholder and never the value. What the upstream sends back is then put through a Redactor holding the values the request carried, so an upstream that echoes one cannot hand it to the caller.
The package knows nothing about where secrets are stored or who may use them: a Lookup answers for one name, and refuses by name.
Index ¶
- Constants
- Variables
- func Fill(s string, lookup Lookup, escape func(string) string) (string, error)
- func FillConnection(ctx context.Context, connection, s string, escape func(string) string) (string, error)
- func FillPath(path string, lookup Lookup) (string, error)
- func FillStrings(m map[string]string, lookup Lookup) (map[string]string, error)
- func FillValue(v any, lookup Lookup) (any, error)
- func HasPlaceholder(s string) bool
- func IsPlaceholder(s string) bool
- func IsTOTPName(qualified string) (string, bool)
- func JSONString(s string) string
- func Malformed(s string) bool
- func Names(s string) []string
- func Raw(s string) string
- func Redaction(name string) string
- func TOTPName(name string) string
- func Transport(base http.RoundTripper) http.RoundTripper
- func ValidName(name string) bool
- func WithoutPlaceholders(s string) string
- type ConnectionSource
- type Lookup
- type Redactor
- func (r *Redactor) Add(name, value string)
- func (r *Redactor) Bytes(b []byte) []byte
- func (r *Redactor) Empty() bool
- func (r *Redactor) Error(err error) string
- func (r *Redactor) Reader(src io.ReadCloser) io.ReadCloser
- func (r *Redactor) Recording(lookup Lookup) Lookup
- func (r *Redactor) String(s string) string
- func (r *Redactor) Strings(h map[string][]string)
- type Request
Constants ¶
const MinValueLength = 6
MinValueLength is the shortest value a secret may hold. Redaction replaces every occurrence of a value in a response, and a value of a character or two would rewrite ordinary text.
const NamePattern = `[a-z0-9][a-z0-9_.-]{0,62}`
NamePattern is the grammar of a secret's name: lower case, digits, and . _ - after the first character. It is narrow so a name reads the same in a placeholder, a URL and a log line.
const TOTPPrefix = "totp:"
TOTPPrefix qualifies the name a {{totp:<name>}} placeholder is looked up by: Lookup is asked for "totp:<name>", which no secret can be called, so one lookup answers both kinds and tells them apart.
Variables ¶
var ErrMalformed = errors.New("malformed secret placeholder")
ErrMalformed is wrapped by the refusal of text that opens a placeholder and does not complete one.
Functions ¶
func Fill ¶
Fill replaces each placeholder in s with its secret's value as escape writes it. A placeholder whose lookup fails fails the fill, and so does text that opens a placeholder without completing one: neither is ever sent as written.
func FillConnection ¶ added in v1.142.0
func FillConnection(ctx context.Context, connection, s string, escape func(string) string) (string, error)
FillConnection fills the placeholders in one value of connection's configuration, escaping each value with escape.
func FillPath ¶
FillPath fills the placeholders of a request path, in either form a path carries one: as the caller wrote it, or with its braces escaped by path_params substitution. The value is path-escaped, so it cannot add a segment.
func FillStrings ¶
FillStrings fills the values of a string map, returning a copy.
func FillValue ¶
FillValue fills every string in a JSON-shaped value (maps, lists and strings, nested), returning a copy: the value the caller passed is the one recorded, and keeps its placeholders. Map keys are filled too.
func HasPlaceholder ¶ added in v1.142.0
HasPlaceholder reports whether s names a stored secret, or opens a placeholder that Fill would refuse as malformed.
func IsPlaceholder ¶ added in v1.142.0
IsPlaceholder reports whether s is exactly one placeholder: a reference with nothing secret written beside it, which a connection's configuration can read back as written.
func IsTOTPName ¶ added in v1.142.0
IsTOTPName reports whether a lookup was asked for a one-time code, and returns the secret's own name.
func JSONString ¶
JSONString writes a value as the inside of a JSON string, for a body sent as JSON text.
func Malformed ¶ added in v1.142.0
Malformed reports whether s opens a placeholder it does not complete, which Fill refuses rather than sending as written.
func Names ¶ added in v1.142.0
Names returns the names s's placeholders are looked up by, in order, each once: a secret's name, or TOTPName of one for {{totp:<name>}}.
func Raw ¶
Raw writes a value as it is: for a body object, query values and header values, which are encoded on their way out.
func TOTPName ¶ added in v1.142.0
TOTPName is the name a lookup is asked for to fill {{totp:<name>}}.
func Transport ¶
func Transport(base http.RoundTripper) http.RoundTripper
Transport wraps base so that a response to a request whose context carries a Redactor with values in it comes back with them redacted: from every header value, and from the body as it is read, however it is read. A request that filled no placeholder passes through untouched.
The redacted body is a different length from the one the upstream sent, so its declared length is dropped.
func WithoutPlaceholders ¶ added in v1.142.0
WithoutPlaceholders is s with every placeholder removed, for a check on the text an operator wrote around one: a placeholder's own ':' is not a colon in a Basic auth userid.
Types ¶
type ConnectionSource ¶ added in v1.142.0
ConnectionSource reads a stored secret on behalf of the connection whose own configuration names it (secretstore.Store.ConnectionValue): the value, or a refusal naming the secret and the connection.
func SetConnectionSource ¶ added in v1.142.0
func SetConnectionSource(src ConnectionSource) ConnectionSource
SetConnectionSource installs the source a connection's configuration is filled from (#2066), and returns the one it replaces so a test can put it back. The platform installs its store once at startup; a nil src removes it, after which a configuration naming a secret is refused when it is used.
type Lookup ¶
Lookup returns a secret's value, or an error that names the secret and says why it may not be used here. A {{totp:<name>}} placeholder is looked up as TOTPName(name), and answered with the current code.
func ConnectionLookup ¶ added in v1.142.0
ConnectionLookup is the lookup a connection's own configuration is filled through as a request is sent: a credential, a header the operator fixed, a sign-in body. Each value is read from the installed source as of this moment, so a rotated secret is used from the next request on, and is recorded on ctx's Redactor so a response that echoes it is redacted.
type Redactor ¶
type Redactor struct {
// contains filtered or unexported fields
}
Redactor replaces the values of the secrets one call used with their redaction. A call adds each value as it fills it; the response side then passes everything it returns through the Redactor.
Each value is matched as written and in the forms an upstream echoes one in: escaped inside a JSON string (once, or twice for a JSON body echoed inside JSON), and query- and path-escaped.
func FromContext ¶
FromContext is the call's Redactor, or nil when the call made none, which every method treats as empty.
func WithRedactor ¶
WithRedactor returns ctx carrying a fresh Redactor, and the Redactor, for one call: the request side adds to it, the response side reads it.
func (*Redactor) Empty ¶
Empty reports whether no value was recorded, so a caller can skip the pass over a response that cannot need it.
func (*Redactor) Reader ¶
func (r *Redactor) Reader(src io.ReadCloser) io.ReadCloser
Reader redacts a stream, for a response written somewhere without being held whole. It holds back the bytes that could be the start of a value until the next read shows whether they are.
func (*Redactor) Recording ¶
Recording returns lookup with every value it answers recorded on r, so the response to the request it fills is redacted of them. A one-time code is not recorded (#2065): six to eight digits would rewrite ordinary numbers in a response, and the code is useless once its period passes. The seed it was computed from is recorded by the lookup that read it.
type Request ¶
type Request struct {
Path string
Headers map[string]string
Query map[string]any
Body any
ContentType string
}
Request is the parts of an outbound request a placeholder may sit in. ContentType is the type the body will be sent as, which says how a value written into a string body is escaped.