Skip to content

access

View on pkg.go.dev

import "github.com/thesimonho/warden/access"

Package access defines the credential passthrough model for Warden containers. An Item groups one or more Credential entries that share host access with a container. Each credential declares how to detect and read a value on the host (Source), an optional transformation (Transform), and how to deliver the result into the container (Injection).

Resolution is stateless — Warden never stores credential values, only the recipes that describe how to obtain and inject them.

Built-in access item IDs. These are stable identifiers stored in the database and referenced by frontends.

const (
BuiltInIDGit = "git"
BuiltInIDSSH = "ssh"
)

func IsBuiltInID(id string) bool

IsBuiltInID reports whether the given ID belongs to a built-in access item.

Credential is the atomic unit of the access system. It pairs one or more host Source entries (tried in order, first detected wins) with an optional Transform and one or more container Injection targets.

type Credential struct {
// Label is a human-readable name for this credential (e.g. "SSH Agent Socket").
Label string `json:"label"`
// Sources are tried in order; the first detected value is used.
Sources []Source `json:"sources"`
// Transform is an optional processing step applied to the resolved value.
Transform *Transform `json:"transform,omitempty"`
// Injections are the container-side delivery targets.
Injections []Injection `json:"injections"`
}

CredentialStatus reports whether a single credential’s sources are available on the host, without reading their values.

type CredentialStatus struct {
// Label is the credential's human-readable name.
Label string `json:"label"`
// Available is true when at least one source was detected.
Available bool `json:"available"`
// SourceMatched describes which source was detected (empty when unavailable).
SourceMatched string `json:"sourceMatched,omitempty"`
}

DetectionResult reports which credentials within an access item are available on the current host.

type DetectionResult struct {
// ID is the access item identifier.
ID string `json:"id"`
// Label is the access item display name.
Label string `json:"label"`
// Available is true when at least one credential was detected.
Available bool `json:"available"`
// Credentials contains per-credential detection results.
Credentials []CredentialStatus `json:"credentials"`
}

func Detect(item Item, env EnvResolver) DetectionResult

Detect checks whether each credential’s sources are available on the host without reading their values. This is a lightweight availability check for the UI.

If env is nil, a default ProcessEnvResolver is used.

EnvResolver abstracts environment variable lookup so callers can provide a combined process + shell environment. This allows Warden to resolve credentials from shell config files (.bashrc, .zshrc, .profile) even when launched from a desktop entry that doesn’t inherit the user’s shell environment.

type EnvResolver interface {
// LookupEnv returns the value of the named environment variable.
LookupEnv(key string) (string, bool)
// ExpandEnv replaces ${var} and $var references in the string
// using the resolver's environment.
ExpandEnv(s string) string
// Environ returns the full environment as a []string slice
// (KEY=VALUE format), suitable for use as exec.Cmd.Env.
Environ() []string
}

Injection describes how a resolved credential is delivered into the container.

type Injection struct {
// Type is the kind of container injection.
Type InjectionType `json:"type"`
// Key is the env var name or container path for the injection target.
Key string `json:"key"`
// Value is a static override for the resolved value. When set, this
// is used instead of the source-resolved value. Useful when the
// injection needs a fixed container-side path (e.g. SSH_AUTH_SOCK
// env var pointing to the container socket path).
Value string `json:"value,omitempty"`
// ReadOnly applies to mount injections — when true the mount is read-only.
ReadOnly bool `json:"readOnly,omitempty"`
}

InjectionType describes how a resolved credential is delivered into the container.

type InjectionType string

const (
// InjectionEnvVar sets an environment variable inside the container.
InjectionEnvVar InjectionType = "env"
// InjectionMountFile bind-mounts a host file into the container.
InjectionMountFile InjectionType = "mount_file"
// InjectionMountSocket bind-mounts a Unix domain socket into the
// container.
InjectionMountSocket InjectionType = "mount_socket"
)

Item is a named group of credentials that share host access with containers. Items can be built-in (shipped with Warden, not deletable) or user-created.

type Item struct {
// ID is a stable identifier. Built-in items use well-known IDs
// (e.g. "git", "ssh"); user items get generated UUIDs.
ID string `json:"id"`
// Label is the human-readable display name (e.g. "Git Config").
Label string `json:"label"`
// Description explains what this access item provides.
Description string `json:"description"`
// Method is the delivery strategy (only "transport" for now).
Method Method `json:"method"`
// Credentials are the individual credential entries in this group.
Credentials []Credential `json:"credentials"`
// BuiltIn is true for items that ship with Warden.
BuiltIn bool `json:"builtIn"`
}

func BuiltInGit() Item

BuiltInGit returns the built-in Git access item. It mounts the host’s .gitconfig (read-only) so git commands inside the container use the host user’s identity and settings.

func BuiltInItemByID(id string) *Item

BuiltInItemByID returns a built-in access item by ID, or nil if not found.

func BuiltInItems() []Item

BuiltInItems returns all built-in access items.

func BuiltInSSH() Item

BuiltInSSH returns the built-in SSH access item. It mounts the host’s SSH config (filtered to strip IdentitiesOnly), known_hosts, and optionally forwards the SSH agent socket.

Method identifies the strategy used to deliver credentials into a container. Only MethodTransport is implemented; the interface exists so a proxy-based method can be added later without changing callers.

type Method string

const (
// MethodTransport extracts a credential on the host and injects it
// directly into the container (env var, bind mount, or socket mount).
MethodTransport Method = "transport"
)

ProcessEnvResolver delegates directly to the os package. It is the default resolver used when no shell environment is available, and is the test-friendly implementation (works with t.Setenv).

type ProcessEnvResolver struct{}

func (ProcessEnvResolver) Environ() []string

Environ delegates to os.Environ.

func (ProcessEnvResolver) ExpandEnv(s string) string

ExpandEnv delegates to os.ExpandEnv.

func (ProcessEnvResolver) LookupEnv(key string) (string, bool)

LookupEnv delegates to os.LookupEnv.

Refresher is implemented by EnvResolver implementations that support refreshing their cached environment (e.g. by re-spawning the user’s login shell). The service layer type-asserts against this interface before Test and container-create operations.

type Refresher interface {
Refresh() error
}

ResolvedCredential holds the resolution output for a single credential.

type ResolvedCredential struct {
// Label is the credential's human-readable name.
Label string `json:"label"`
// Resolved is true when a source was detected and all injections
// were produced.
Resolved bool `json:"resolved"`
// SourceMatched describes which source was matched (empty when unresolved).
SourceMatched string `json:"sourceMatched,omitempty"`
// Injections are the resolved container-side deliveries.
Injections []ResolvedInjection `json:"injections,omitempty"`
// Error is set when resolution failed (distinct from "not detected").
Error string `json:"error,omitempty"`
}

ResolvedInjection is a single resolved delivery into the container.

type ResolvedInjection struct {
// Type is the injection kind (env, mount_file, mount_socket).
Type InjectionType `json:"type"`
// Key is the env var name or container path.
Key string `json:"key"`
// Value is the resolved content (env var value, host file path,
// or host socket path).
Value string `json:"value"`
// ReadOnly applies to mount injections.
ReadOnly bool `json:"readOnly,omitempty"`
}

ResolvedItem holds the full resolution output for an access item.

type ResolvedItem struct {
// ID is the access item identifier.
ID string `json:"id"`
// Label is the access item display name.
Label string `json:"label"`
// Credentials contains per-credential resolution results.
Credentials []ResolvedCredential `json:"credentials"`
}

func Resolve(item Item, env EnvResolver) (*ResolvedItem, error)

Resolve resolves all credentials in the given access item, returning the resolved injections for each credential. Credentials whose sources are not detected on the host are skipped (partial resolution is normal). An error is returned only for hard failures like an invalid transform configuration.

If env is nil, a default ProcessEnvResolver is used (backward compatible with direct os.LookupEnv behavior).

ShellEnvResolver captures the user’s full shell environment by spawning their login shell. This allows Warden to see env vars defined in .bashrc, .zshrc, .profile, etc. even when launched from a desktop entry that doesn’t inherit the shell environment.

Process env always takes precedence over the shell cache — if a variable is set in both, the process value wins.

type ShellEnvResolver struct {
// contains filtered or unexported fields
}

func NewShellEnvResolver() *ShellEnvResolver

NewShellEnvResolver creates a resolver that will spawn the user’s login shell to capture environment variables. Call [Load] (typically in a background goroutine) to populate the cache eagerly at startup.

func (r *ShellEnvResolver) Environ() []string

Environ returns the full combined environment as a []string slice (KEY=VALUE format). Shell cache is the base; process env is overlaid so process values always win on conflicts.

func (r *ShellEnvResolver) ExpandEnv(s string) string

ExpandEnv replaces ${var} and $var in the string using the combined process + shell environment.

func (r *ShellEnvResolver) Load() error

Load spawns the user’s login shell and caches the resulting environment. Safe to call from a goroutine. If the shell fails or times out, the resolver degrades gracefully to process-only env.

func (r *ShellEnvResolver) LookupEnv(key string) (string, bool)

LookupEnv checks the process environment first, then falls back to the cached shell environment. Process env takes precedence because explicitly set variables are the most intentional.

func (r *ShellEnvResolver) Refresh() error

Refresh re-spawns the login shell to pick up any env changes since the last load. Skips the spawn if the cache was loaded less than 30 seconds ago (cooldown).

Source describes how to detect and read a credential value on the host. Detection is implicit: an env var must be set, a file or socket must exist, and a command must exit 0.

type Source struct {
// Type is the kind of host source.
Type SourceType `json:"type"`
// Value is the env var name, file path, socket path, or command string.
Value string `json:"value"`
}

SourceType describes where a credential value lives on the host.

type SourceType string

const (
// SourceEnvVar reads a value from a host environment variable.
SourceEnvVar SourceType = "env"
// SourceFilePath reads a file from the host filesystem.
SourceFilePath SourceType = "file"
// SourceSocketPath references a Unix domain socket on the host.
SourceSocketPath SourceType = "socket"
// SourceCommand runs a host command and captures stdout.
SourceCommand SourceType = "command"
)

Transform describes an optional processing step between source resolution and injection. Only used by built-in access items.

type Transform struct {
// Type identifies the transformation.
Type TransformType `json:"type"`
// Params holds type-specific configuration (e.g. "pattern" for strip_lines).
Params map[string]string `json:"params,omitempty"`
}

TransformType identifies a built-in transformation applied between source resolution and container injection. Transforms are internal — they are not exposed in the user-facing UI.

type TransformType string

const (
// TransformStripLines removes lines matching a case-insensitive
// pattern. Params: "pattern" (regex).
TransformStripLines TransformType = "strip_lines"
// TransformGitInclude writes an include directive rather than
// mounting over the container's .gitconfig.
TransformGitInclude TransformType = "git_include"
)

Generated by gomarkdoc