Documentation
¶
Overview ¶
Package secrets provides an encrypted, ACL-controlled secrets vault.
Secrets are encrypted at rest with AES-256-GCM and stored in SQLite. Each secret carries an ACL that restricts access by agent name, tenant, and forbidden patterns (all supporting glob matching). Every access — both allowed and denied — is logged to an audit table for compliance.
Index ¶
- Variables
- func RecordSecretAccess(ctx context.Context, secretName, agentID, outcome string)
- type ACL
- type AccessRecord
- type Secret
- type SecretMetadata
- type SecretStore
- func (s *SecretStore) AuditLog(ctx context.Context, tenantID, secretName string, limit int) ([]AccessRecord, error)
- func (s *SecretStore) Close() error
- func (s *SecretStore) Get(ctx context.Context, name, tenantID, agentID string) (*Secret, error)
- func (s *SecretStore) List(ctx context.Context, tenantID string) ([]SecretMetadata, error)
- func (s *SecretStore) ListAll(ctx context.Context) ([]SecretMetadata, error)
- func (s *SecretStore) RecordEnvFallback(ctx context.Context, secretName, tenantID, agentID string)
- func (s *SecretStore) RecordVaultMissNoFallback(ctx context.Context, secretName, tenantID, agentID string)
- func (s *SecretStore) Rotate(ctx context.Context, name string) error
- func (s *SecretStore) Set(ctx context.Context, name string, value []byte, acl ACL) error
Constants ¶
This section is empty.
Variables ¶
var ( // ErrSecretNotFound is returned when a secret name does not exist in the vault. ErrSecretNotFound = errors.New("secret not found") // ErrSecretAccessDenied is returned when the requesting agent/tenant is // not permitted by the secret's ACL. The denial is still audit-logged. ErrSecretAccessDenied = errors.New("secret access denied by ACL") // ErrInvalidEncryptionKey is returned when the vault encryption key is // not exactly 32 bytes (required for AES-256). ErrInvalidEncryptionKey = errors.New("invalid encryption key") )
Functions ¶
func RecordSecretAccess ¶
RecordSecretAccess increments the secret access counter.
Types ¶
type ACL ¶
type ACL struct {
Agents []string `json:"agents"` // Allowed agents (glob patterns)
Tenants []string `json:"tenants"` // Allowed tenants (glob patterns)
ForbiddenAgents []string `json:"forbidden_agents"` // Explicitly denied agents
}
ACL defines who can access a secret.
func (ACL) CheckAccess ¶
CheckAccess verifies if a tenant+agent combination can access the secret. Forbidden list is checked first (explicit deny). Empty allow lists mean allow-all.
type AccessRecord ¶
type AccessRecord struct {
ID string `json:"id"`
SecretName string `json:"secret_name"`
TenantID string `json:"tenant_id"`
AgentID string `json:"agent_id"`
Timestamp time.Time `json:"timestamp"`
Allowed bool `json:"allowed"`
Reason string `json:"reason,omitempty"`
}
AccessRecord is a single secret access audit entry.
type Secret ¶
type Secret struct {
Name string
Value []byte
ACL ACL
CreatedAt time.Time
AccessedAt time.Time
AccessCount int
}
Secret is a decrypted secret with metadata.
type SecretMetadata ¶
type SecretMetadata struct {
Name string `json:"name"`
ACL ACL `json:"acl"`
CreatedAt time.Time `json:"created_at"`
AccessedAt time.Time `json:"accessed_at"`
AccessCount int `json:"access_count"`
}
SecretMetadata is the public view of a secret (no plaintext value).
type SecretStore ¶
type SecretStore struct {
// contains filtered or unexported fields
}
SecretStore manages encrypted secrets with ACL enforcement and audit logging.
func NewSecretStore ¶
func NewSecretStore(dbPath string, encryptionKey string) (*SecretStore, error)
NewSecretStore creates an encrypted secret store backed by SQLite. The encryptionKey must be exactly 32 raw bytes or 64 hex characters (decoded to 32 bytes for AES-256).
func (*SecretStore) AuditLog ¶
func (s *SecretStore) AuditLog(ctx context.Context, tenantID, secretName string, limit int) ([]AccessRecord, error)
AuditLog returns access records for compliance review. If tenantID is non-empty, only records for that tenant are returned (multi-tenant isolation). Pass empty secretName to get all records for the tenant. Limit <= 0 means no limit.
func (*SecretStore) Close ¶
func (s *SecretStore) Close() error
Close releases the database connection.
func (*SecretStore) Get ¶
Get retrieves and decrypts a secret after checking ACL. Both allowed and denied access attempts are logged.
func (*SecretStore) List ¶
func (s *SecretStore) List(ctx context.Context, tenantID string) ([]SecretMetadata, error)
List returns metadata for all secrets visible to a tenant (values are NOT included). Use ListAll for an operator-style view of every secret regardless of ACL.
func (*SecretStore) ListAll ¶
func (s *SecretStore) ListAll(ctx context.Context) ([]SecretMetadata, error)
ListAll returns metadata for every secret in the vault (no ACL filtering). Intended for operator use (e.g. talon secrets list). Values are never included.
func (*SecretStore) RecordEnvFallback ¶
func (s *SecretStore) RecordEnvFallback(ctx context.Context, secretName, tenantID, agentID string)
RecordEnvFallback records that a run used the environment variable fallback for this secret (vault lookup was denied or missing). Only call when the env var is actually set. SecOps can see this in "talon secrets audit" as allowed=true, reason=env_fallback.
func (*SecretStore) RecordVaultMissNoFallback ¶
func (s *SecretStore) RecordVaultMissNoFallback(ctx context.Context, secretName, tenantID, agentID string)
RecordVaultMissNoFallback records that vault had no key and no environment fallback was available. SecOps sees this as allowed=false, reason=no_key so the audit trail is accurate.