Documentation
¶
Overview ¶
Package secrets resolves declared secret REFERENCES (which live in git: EnvVar.secret_ref / secret_key) to secret VALUES (which never live in git) for one environment.
A secret has two halves:
- a non-sensitive REFERENCE — the env-var NAME, the k8s Secret name, and the key within it. KCL projects this into the manifest as a `secretKeyRef`. It is reproducible and version-controlled.
- a sensitive VALUE — obtained at resolve time from a per-env PROVIDER. Never in git, never in KCL render output.
This package owns the VALUE side. KCL only emits the provider DECLARATION (type + path); all value resolution happens here in Go so secrets never enter the KCL renderer.
Two provider kinds:
- "dotenv" (dev/local): forge reads a gitignored dotenv keyed by env-var NAME, resolves declared refs from it, and — for k8s targets — RENDERS Secret objects from it CLI-side. Local clusters only.
- "external" (prod/staging): forge never sees values. k8s references pre-existing Secrets (External Secrets Operator / sealed); host & external runtimes obtain secrets via workload identity / ambient env. forge only validates the secretKeyRef wiring (it can't, and so does not, validate the values themselves).
The package is intentionally decoupled from internal/cli to avoid an import cycle (cli depends on secrets, not the reverse). It reuses internal/hostlaunch's dotenv reader, which only imports the stdlib — no cycle risk.
forge:exclude-contract secrets is a secret-reference→value resolution utility (per-env dotenv / external providers), not a contract-shaped service. Opt out of the require-contract rule.
Index ¶
- func RenderDeclaredSecrets(declared []DeclaredSecret, dot Provider, env, namespace string) ([]map[string]any, error)
- func RenderK8sSecrets(p Provider, refs []SecretRef, namespace string) []map[string]any
- func ValidateDeclaredRefs(p Provider, refs []SecretRef, dotenvPath string) error
- type DeclaredSecret
- type DeclaredSecretKey
- type Provider
- type ProviderConfig
- type SecretRef
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RenderDeclaredSecrets ¶
func RenderDeclaredSecrets(declared []DeclaredSecret, dot Provider, env, namespace string) ([]map[string]any, error)
RenderDeclaredSecrets builds k8s Secret manifests from a RenderedSecrets provider's declared Secrets. Each declared key resolves to its value:
- from="dotenv": resolve Key from the dotenv provider `dot` (the same .env.<env> machinery DotenvSecrets uses). A missing dotenv key is an error (listed per Secret/key) — the value can't be rendered.
- from="literal": use the inline Value, but ONLY when env is dev/e2e. A literal in any other env is a hard error (the trust-safe gate).
Returns the Secret manifests (one per declared Secret) in deterministic order, or a single aggregated error listing every problem. namespace is stamped on each Secret's metadata.
func RenderK8sSecrets ¶
RenderK8sSecrets builds k8s Secret manifests (as []map[string]any, ready to marshal to YAML/JSON) from the resolved values, grouping refs by SecretName; each Secret's stringData[SecretKey] = resolved(EnvName). Only Kind "dotenv" produces output; "external"/"none" return nil (prod references pre-existing Secrets). Skips refs whose value doesn't resolve (ValidateDeclaredRefs is the gate for those). Deterministic ordering (sorted Secret names + keys) for stable diffs.
func ValidateDeclaredRefs ¶
ValidateDeclaredRefs returns a single fail-fast error listing every declared ref the provider cannot supply. For Kind "dotenv": each EnvName must be present in All(). For "external"/"none": returns nil (forge cannot see those values).
Types ¶
type DeclaredSecret ¶
type DeclaredSecret struct {
Name string
Keys map[string]DeclaredSecretKey
}
DeclaredSecret is one explicitly-declared k8s Secret a RenderedSecrets provider renders: a Secret NAME and a map of in-Secret key -> value SOURCE. Mirrors the cli RenderedSecretEntity (the secrets package stays decoupled from cli, so cli maps its entity -> this).
type DeclaredSecretKey ¶
DeclaredSecretKey is the value source for one key in a DeclaredSecret. From is "dotenv" (resolve Key from the dotenv provider) or "literal" (inline Value, gated to dev/e2e by RenderDeclaredSecrets).
type Provider ¶
type Provider interface {
Kind() string // "dotenv" | "external" | "none"
// Resolve returns the value for an env var by NAME (dotenv-key
// convention: the key in the dotenv == the EnvVar.name). ok=false
// when this provider has no value for name.
Resolve(name string) (value string, ok bool)
// All returns every value the provider can supply, keyed by name.
// dotenv: the whole file. external/none: nil.
All() map[string]string
}
Provider resolves declared secret references to values for one env.
func NewProvider ¶
func NewProvider(cfg *ProviderConfig) (Provider, error)
NewProvider builds a Provider. cfg==nil -> a noop provider (Kind "none", All nil, Resolve always !ok) so callers need no nil checks. dotenv: loads the file now; a MISSING dotenv file is a non-fatal empty provider with a returned error==nil but Kind "dotenv" and empty All (so validation, not load, reports missing declared keys) — BUT if the file exists and is unreadable/malformed, return the error.
type ProviderConfig ¶
type ProviderConfig struct {
Type string // "dotenv" | "external"
Path string // dotenv path (already resolved to an absolute/project path by caller)
}
ProviderConfig is the cli-decoupled view of the KCL secret_provider entity. (cli maps KCLEntities.SecretProvider -> this.)