cliutil

package
v0.7.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package cliutil holds tiny env/flag helpers shared by Wardyn's cmd/* main packages (each cmd is its own `main` package, so these can't just live in one of them without the others importing "main"), plus ScrubChildEnv, the one env denylist shared by every host-exec'd third-party CLI child.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnvBool added in v0.3.1

func EnvBool(name string, def bool) bool

EnvBool reads a bool directly from an env var, with no flag registered — for sites where flag.Parse() has already run before the read (so FlagBool's flag would never be parsed: a dead flag). Same token set and loudness contract as FlagBool: unset/empty keeps def quietly (correct for `docker run -e VAR`), 1/true/yes/on is true, 0/false/no/off is false, anything else exits 2.

func EnvDuration added in v0.3.1

func EnvDuration(name string, def time.Duration) time.Duration

EnvDuration reads a time.Duration directly from an env var, with no flag registered — the non-flag twin of FlagDuration for post-flag.Parse() sites. Unset/empty keeps def quietly; an unparseable value exits 2 rather than silently reinstating the default (a typo'd interval must not be reinterpreted).

func EnvOr

func EnvOr(key, def string) string

EnvOr returns the env var if set and non-empty, else def.

func FlagBool

func FlagBool(name, env string, def bool, usage string) *bool

FlagBool defines a bool flag whose default is overridden by an env var. 1/true/yes/on is true, 0/false/no/off is false (case-insensitive, trimmed). Unset — or set to the empty string, which is what `docker run -e VAR` and a compose `VAR=` passthrough produce for an unset var — means "use the default", silently. Anything else exits 2: a value that is neither truthy nor falsey states no intent this helper can honor, and guessing "false" is the worst guess available (it turns features off).

func FlagDuration

func FlagDuration(name, env string, def time.Duration, usage string) *time.Duration

FlagDuration defines a time.Duration flag whose default is overridden by an env var. Unset/empty keeps the default; an unparseable value exits 2 rather than silently reinstating the default — an operator who typos an interval must not have it quietly reinterpreted as a different, meaningful setting.

func FlagEnv

func FlagEnv(name, env, def, usage string) *string

FlagEnv defines a string flag whose default is overridden by an env var. Unset — or set to the empty string, which is what `docker run -e VAR` and a compose `VAR=` passthrough produce for a var the operator never set — means "use the default", exactly like FlagBool/FlagDuration/FlagIntEnv/EnvOr. It used to honour an explicit empty as an intentional blank, which silently erased thirteen non-empty compiled defaults (WARDYN_LISTEN ":8080", WARDYN_RUNNER "none", WARDYN_DEFAULT_POLICY, WARDYN_GIT_PAT_BROKER "on", ...) for anyone whose orchestrator passes every known variable through. The escape hatch for a genuinely-intended blank is `-name=`, which states it.

The env value is applied to the flag's VARIABLE, never to its registered DEFAULT (F157). flag.String captures whatever default it is handed as Flag.DefValue, and PrintDefaults renders a non-empty string default as `(default "…")` — printed not only for -help but for EVERY parse error, since flag.CommandLine is ExitOnError. Seeding the default from the env therefore wrote WARDYN_ADMIN_TOKEN, WARDYN_AGE_KEY (the secret store's master identity), WARDYN_OIDC_CLIENT_SECRET and WARDYN_GROUNDTRUTH_TOKEN verbatim to stderr — container logs, journald, any log shipper — on one typo'd flag in a compose command, a systemd unit or a Helm args list. Writing through the returned pointer instead keeps the exact same precedence (an explicit -name= set at Parse overwrites the env value, because the flag package only calls Set for flags actually present on the command line) while the usage block shows only the COMPILED default, which is never a credential. FlagBool/FlagDuration/ FlagIntEnv are unaffected: none of them carries a secret, and their env values are bounded token/number sets rather than free-form strings.

func FlagIntEnv

func FlagIntEnv(name, env string, def int, usage string) *int

FlagIntEnv defines an int flag whose default is overridden by an env var. Unset/empty keeps the default; an unparseable value exits 2 (see FlagDuration).

func ScrubChildEnv added in v0.4.4

func ScrubChildEnv(env []string) []string

ScrubChildEnv returns env with the variables a third-party CLI child must never receive removed, without mutating the input: ANTHROPIC_API_KEY, so a resident `claude` authenticates with the subscription session rather than billing or leaking an API key, and every WARDYN_* variable, which is the daemon's own configuration — WARDYN_AGE_KEY is the secret-store MASTER key, WARDYN_ADMIN_TOKEN the API bearer, WARDYN_PG_DSN the database URL.

Denylist, not allowlist, deliberately: these children are resident operator CLIs invoked on the control-plane host, and they legitimately need whatever HTTPS_PROXY / NO_PROXY / NODE_EXTRA_CA_CERTS / AWS_* the operator's shell carries to work on a corp network or against Bedrock. A prefix also covers every future WARDYN_* secret for free, which an enumerated allowlist cannot.

HONEST RESIDUAL: this is defense-in-depth and consistency, NOT containment. A host-exec'd child runs as the same uid as wardynd and can read /proc/<ppid>/environ regardless. Containment is the sandbox composer wire.

ONE documented exception, enforced by cmd/wardyn's childenv_guard_test.go: `docker compose config` in supportbundle.go's gatherComposeConfig, whose entire job is to resolve ${WARDYN_*} against the real environment. Its output goes through redactSecrets before it reaches a bundle.

func SplitCSV

func SplitCSV(s string) []string

SplitCSV splits a comma-separated list, trimming whitespace and dropping empties. Returns nil for an empty input (meaning "no restriction").

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL