Documentation
¶
Overview ¶
Package sensitive routes ResourceOutput fields flagged as Sensitive through a secrets.Provider, returning sanitized placeholders for state persistence and a hydrated map for in-process consumers.
Per the engine-sensitive-output-routing design (workflow v0.27.0):
- Route is invoked on Create/Update only. Read/Adoption/Refresh paths use Sanitize-only logic (not in this package — see cmd/wfctl/infra_apply.go) to prevent cache pollution.
- The placeholder format "secret_ref://<SecretKey(resource,key)>" is distinct from the user-supplied "secret://<key>" config-reference convention.
- Routing trigger is exclusively out.Sensitive[k]==true (per-call dynamic). ResourceDriver.SensitiveKeys() is NOT consulted here; it remains a display-masking signal.
Limitation (v0.27.0): only string-typed sensitive output values are supported. Non-string sensitive outputs (e.g., []byte, int) yield an error from Route. Future expansion via a MarshalSensitive interface is out of scope.
Index ¶
- Constants
- func IsPlaceholder(v any) bool
- func MaskSensitiveForDiff(driverKeys []string, desired, current map[string]any) (map[string]any, map[string]any)
- func Placeholder(resourceName, outputKey string) string
- func Revoke(ctx context.Context, provider secrets.Provider, resourceName string, ...) error
- func Route(ctx context.Context, provider secrets.Provider, resourceName string, ...) (sanitized map[string]any, hydrated map[string]string, err error)
- func SecretKey(resourceName, outputKey string) string
Constants ¶
const ( // PlaceholderPrefix is the URI scheme used in state.Outputs values to // reference a routed secret stored in the configured secrets.Provider. // Distinct from secrets.SecretPrefix ("secret://") which is for // user-supplied config references. PlaceholderPrefix = "secret_ref://" )
Variables ¶
This section is empty.
Functions ¶
func IsPlaceholder ¶
IsPlaceholder reports whether v is a string with the PlaceholderPrefix. Non-string values return false.
func MaskSensitiveForDiff ¶
func MaskSensitiveForDiff(driverKeys []string, desired, current map[string]any) (map[string]any, map[string]any)
MaskSensitiveForDiff returns copies of desired and current with sensitive keys elided from BOTH sides. A key is considered sensitive when:
- it is named in driverKeys (i.e., ResourceDriver.SensitiveKeys()), OR
- its value in current matches the PlaceholderPrefix.
Eliding from both sides ensures driver.Diff or other field-by-field comparators don't report drift when state has a placeholder and live has a different (or absent) value. Non-sensitive keys are passed through unchanged.
Either input may be nil; the corresponding output is also nil.
func Placeholder ¶
Placeholder returns PlaceholderPrefix + SecretKey(resourceName, outputKey), replacing a routed value in state.Outputs.
func Revoke ¶
func Revoke( ctx context.Context, provider secrets.Provider, resourceName string, mergedKeys []string, ) error
Revoke deletes routed secrets for resourceName. mergedKeys is the union of placeholder-derived keys (caller extracts from pre-delete state.Outputs) and any legacy heuristic keys. Errors from provider.Delete are aggregated via errors.Join — Revoke does NOT stop on the first error so partial cleanup proceeds. Keys that were never stored (provider returns secrets.ErrNotFound) are silently treated as success.
func Route ¶
func Route( ctx context.Context, provider secrets.Provider, resourceName string, out *interfaces.ResourceOutput, ) (sanitized map[string]any, hydrated map[string]string, err error)
Route routes sensitive fields from out through provider, keying each secret via SecretKey(resourceName, outputKey). Returns:
- sanitized: a copy of out.Outputs with sensitive values replaced by PlaceholderPrefix + SecretKey(resourceName, k). Suitable for persistence to interfaces.IaCStateStore.
- hydrated: a flat map keyed by SecretKey of values that were routed. Suitable for in-process hand-off to post-apply consumers in the same wfctl invocation. Empty when no fields were routed.
Routing trigger is out.Sensitive[k] == true with out.Outputs[k] present (any value, including empty string). When the sensitive key's value is absent from out.Outputs the key is silently SKIPPED — neither provider.Set is called nor a placeholder inserted (the engine has no value to route; existing routed-secret in provider stays as-is).
Errors:
- resourceName == "" with non-empty Sensitive map → error (defensive; out.Name is intentionally NOT consulted, since Read/Adoption paths may have empty out.Name).
- provider == nil with non-empty Sensitive map AND any sensitive key present in out.Outputs → error naming the resource and keys.
- provider.Set returns an error → error wrapping the failed key. Set is invoked in sorted order by key for determinism; on first error the loop stops and previously-Set values are NOT cleaned up (idempotent overwrite on Apply rerun is the recovery path).
Out is not mutated.
func SecretKey ¶
SecretKey returns the canonical secrets.Provider key for a resource's output. The key is provider-safe and collision-resistant for distinct (resourceName, outputKey) pairs. Exported so audit-state-secrets and other consumers can recompute routed-secret names from known resource/output pairs.
Types ¶
This section is empty.