A secret reaches a process as a file (ADR 0086)
The broker settings take a _FILE twin like the store connections; the catalogue engine refuses a secret placeholder in a container's env and a secret-carrying env-file unless the container says why with secrets-in-environment, which stays in the catalogue and never reaches the machine.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
// Package envfile reads a setting that may be a secret from the environment or, preferably, from
|
||||
// a file the environment names.
|
||||
//
|
||||
// **A secret reaches a process as a file** (novox/hq ADR 0086). An environment variable is
|
||||
// readable in `docker inspect`, in the process's /proc entry and in whatever composed it; a file
|
||||
// the mesh sealed to the machine and the host wrote at 0600 is readable where it is used and
|
||||
// nowhere else. So every variable of the control plane's that carries a credential has a `_FILE`
|
||||
// twin naming such a file, and the plain form remains only for a control plane a person starts by
|
||||
// hand and for the bundle that raises the first one. The store's connections had this shape
|
||||
// already (internal/store); this is the same rule for the rest.
|
||||
package envfile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Value is the setting named by `name`: the content of the file `name_FILE` points at when that
|
||||
// is set, else the variable itself. Both set is refused — two sources that could disagree is how
|
||||
// a setting silently stops meaning what it says. Neither set is "", nil.
|
||||
func Value(name string) (string, error) {
|
||||
plain, hasPlain := os.LookupEnv(name)
|
||||
path, hasFile := os.LookupEnv(name + "_FILE")
|
||||
switch {
|
||||
case hasFile && hasPlain && strings.TrimSpace(plain) != "" && strings.TrimSpace(path) != "":
|
||||
return "", fmt.Errorf("both %s and %s_FILE are set; one of them, not both", name, name)
|
||||
case hasFile && strings.TrimSpace(path) != "":
|
||||
raw, err := os.ReadFile(strings.TrimSpace(path))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%s_FILE names %s, which cannot be read: %w", name, path, err)
|
||||
}
|
||||
// A file has a line ending and a value does not — trimmed, and only the ending, because a
|
||||
// value may begin or end with a space and still be the value.
|
||||
return strings.TrimRight(string(raw), "\r\n"), nil
|
||||
default:
|
||||
return strings.TrimSpace(plain), nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user