0.27.0 — Infisical hardening: runtime refresh, audit logging, CLI verify/audit, startup verification, SSH host key verification, interface consolidation
This commit is contained in:
@@ -24,6 +24,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/dtoro/oikos/internal/config"
|
||||
"github.com/dtoro/oikos/internal/actuator"
|
||||
"github.com/dtoro/oikos/internal/db"
|
||||
"github.com/dtoro/oikos/internal/httpapi/gen"
|
||||
mcphandler "github.com/dtoro/oikos/internal/mcp"
|
||||
@@ -53,22 +54,12 @@ type actor struct {
|
||||
type Server struct {
|
||||
pool *db.Pool
|
||||
cfg config.Config
|
||||
secretsManager secretsBackend
|
||||
secretsManager secrets.Backend
|
||||
sseBroker *sseBroker
|
||||
sseSubs map[*sseSubscriber]struct{}
|
||||
sseMu sync.Mutex
|
||||
}
|
||||
|
||||
// secretsBackend is a minimal interface for secrets operations used by the
|
||||
// HTTP API (enrollment key storage, listing, retrieval). Compatible with
|
||||
// internal/secrets.Backend. If Infisical is configured, a real backend is
|
||||
// wired in; otherwise the field stays nil and all guarded paths are no-ops.
|
||||
type secretsBackend interface {
|
||||
Get(ctx context.Context, key string) (string, error)
|
||||
Set(ctx context.Context, key string, value string) error
|
||||
List(ctx context.Context) ([]string, error)
|
||||
}
|
||||
|
||||
// NewHandler builds the full HTTP handler: /healthz (unauthenticated,
|
||||
// SG18) + the OpenAPI surface under /api/v1 behind bearer auth.
|
||||
//
|
||||
@@ -84,7 +75,7 @@ func NewHandler(ctx context.Context, pool *db.Pool, cfg config.Config) http.Hand
|
||||
sseSubs: make(map[*sseSubscriber]struct{}),
|
||||
}
|
||||
|
||||
// Wire Infisical backend when configured.
|
||||
// Wire secrets backend: Infisical primary with SOPS DR fallback.
|
||||
if cfg.InfisicalSiteURL != "" {
|
||||
infCfg := secrets.InfisicalConfig{
|
||||
SiteURL: cfg.InfisicalSiteURL,
|
||||
@@ -97,8 +88,24 @@ func NewHandler(ctx context.Context, pool *db.Pool, cfg config.Config) http.Hand
|
||||
if infCfg.Env == "" {
|
||||
infCfg.Env = "dev"
|
||||
}
|
||||
s.secretsManager = secrets.NewInfisicalBackend(infCfg)
|
||||
slog.Info("secrets backend wired", "backend", "infisical", "site", cfg.InfisicalSiteURL)
|
||||
primary := secrets.NewInfisicalBackend(infCfg)
|
||||
var fallback secrets.Backend
|
||||
if cfg.SecretsDir != "" {
|
||||
fallback = secrets.NewSOPSBackend(cfg.SecretsDir)
|
||||
}
|
||||
s.secretsManager = secrets.NewManager(primary, fallback)
|
||||
slog.Info("secrets backend wired", "backend", "infisical+sops", "site", cfg.InfisicalSiteURL)
|
||||
|
||||
// Start background secret refresh loop.
|
||||
if mgr, ok := s.secretsManager.(*secrets.Manager); ok {
|
||||
mgr.StartRefreshLoop(ctx)
|
||||
}
|
||||
|
||||
// Pre-load SSH host keys from Infisical for host verification.
|
||||
if hosts := actuator.ResolveSSHHosts(ctx, pool); len(hosts) > 0 {
|
||||
hkSrc := actuator.NewInfisicalHostKeySource(s.secretsManager)
|
||||
actuator.LoadHostKeys(ctx, hosts, hkSrc)
|
||||
}
|
||||
}
|
||||
|
||||
// Start background SSE listener, tied to ctx for clean shutdown.
|
||||
|
||||
Reference in New Issue
Block a user