Harden CLI lane filtering and diagnostics redaction

This commit is contained in:
2026-07-03 20:54:22 +00:00
parent fd835b582c
commit bf2c0f692d
6 changed files with 182 additions and 9 deletions

View File

@@ -1,5 +1,7 @@
package config
import "gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
const redactedSecret = "[REDACTED]"
func (c Config) Redacted() Config {
@@ -12,3 +14,44 @@ func (c Config) Redacted() Config {
}
return redacted
}
func (c Config) RedactedDiagnosticsPayload() any {
return c.Redacted()
}
func (e EffectiveConfig) RedactedDiagnosticsPayload() any {
return EffectiveConfig{
Config: e.Config.Redacted(),
PipelineID: e.PipelineID,
Only: append([]string(nil), e.Only...),
ResolvedPipeline: cloneResolvedPipeline(e.ResolvedPipeline),
}
}
func cloneResolvedPipeline(in pipeline.ResolvedPipeline) pipeline.ResolvedPipeline {
out := in
out.Input = cloneModuleBinding(in.Input)
out.Chunk = cloneModuleBinding(in.Chunk)
out.Output = cloneModuleBinding(in.Output)
if len(in.ArtifactLanes) > 0 {
out.ArtifactLanes = make([]pipeline.ResolvedArtifactLane, len(in.ArtifactLanes))
for i, lane := range in.ArtifactLanes {
out.ArtifactLanes[i] = cloneResolvedArtifactLane(lane)
}
}
return out
}
func cloneResolvedArtifactLane(in pipeline.ResolvedArtifactLane) pipeline.ResolvedArtifactLane {
out := in
out.Extract = cloneModuleBinding(in.Extract)
out.Merge = cloneModuleBinding(in.Merge)
out.Normalize = cloneModuleBinding(in.Normalize)
if len(in.Validators) > 0 {
out.Validators = make([]pipeline.ModuleBinding, len(in.Validators))
for i, binding := range in.Validators {
out.Validators[i] = cloneModuleBinding(binding)
}
}
return out
}

View File

@@ -35,3 +35,67 @@ func TestRedactedConfigRemovesAPIKeyValues(t *testing.T) {
t.Fatalf("redaction mutated original config")
}
}
func TestConfigRedactedDiagnosticsPayloadRedactsAPIKeys(t *testing.T) {
cfg := Default()
profile := cfg.LLMProfiles[pipeline.DefaultLLMProfile]
profile.APIKey = "secret"
profile.Model = "test-model"
cfg.LLMProfiles[pipeline.DefaultLLMProfile] = profile
payload, ok := cfg.RedactedDiagnosticsPayload().(Config)
if !ok {
t.Fatalf("expected Config payload, got %T", cfg.RedactedDiagnosticsPayload())
}
if payload.LLMProfiles[pipeline.DefaultLLMProfile].APIKey != redactedSecret {
t.Fatalf("expected API key redacted, got %+v", payload.LLMProfiles[pipeline.DefaultLLMProfile])
}
if payload.LLMProfiles[pipeline.DefaultLLMProfile].Model != "test-model" {
t.Fatalf("expected non-secret fields preserved, got %+v", payload.LLMProfiles[pipeline.DefaultLLMProfile])
}
if cfg.LLMProfiles[pipeline.DefaultLLMProfile].APIKey != "secret" {
t.Fatalf("redacted diagnostics payload mutated original config")
}
}
func TestEffectiveConfigRedactedDiagnosticsPayloadRedactsAndCopies(t *testing.T) {
cfg := validConfig()
profile := cfg.LLMProfiles[pipeline.DefaultLLMProfile]
profile.APIKey = "secret"
cfg.LLMProfiles[pipeline.DefaultLLMProfile] = profile
lane := cfg.Pipelines["example"].Artifacts["events"]
lane.Extract.Options = map[string]any{"temperature": 0.2}
cfg.Pipelines["example"].Artifacts["events"] = lane
effective, err := cfg.Resolve(ResolveInput{
PipelineID: "example",
Only: []string{"events"},
Catalog: fakeCatalog(t),
})
if err != nil {
t.Fatalf("Resolve: %v", err)
}
payload, ok := effective.RedactedDiagnosticsPayload().(EffectiveConfig)
if !ok {
t.Fatalf("expected EffectiveConfig payload, got %T", effective.RedactedDiagnosticsPayload())
}
if payload.Config.LLMProfiles[pipeline.DefaultLLMProfile].APIKey != redactedSecret {
t.Fatalf("expected nested API key redacted, got %+v", payload.Config.LLMProfiles[pipeline.DefaultLLMProfile])
}
if cfg.LLMProfiles[pipeline.DefaultLLMProfile].APIKey != "secret" {
t.Fatalf("redacted diagnostics payload mutated source config")
}
if payload.PipelineID != effective.PipelineID || payload.ResolvedPipeline.Digest != effective.ResolvedPipeline.Digest {
t.Fatalf("expected pipeline metadata preserved, got %+v", payload)
}
payload.Only[0] = "changed"
if effective.Only[0] != "events" {
t.Fatalf("expected only lanes to be copied")
}
payload.ResolvedPipeline.ArtifactLanes[0].Extract.Options["temperature"] = 1.0
if effective.ResolvedPipeline.ArtifactLanes[0].Extract.Options["temperature"] != 0.2 {
t.Fatalf("expected resolved pipeline options to be copied")
}
}

View File

@@ -42,6 +42,10 @@ type RetentionDecisionInput struct {
HasWarnings bool
}
type RedactedEffectiveConfigPayload interface {
RedactedDiagnosticsPayload() any
}
// InvocationMetadata captures non-secret invocation details for diagnostics.
type InvocationMetadata struct {
Operation string `json:"operation"`
@@ -134,8 +138,11 @@ func (r *RunDirectory) WriteInvocationMetadata(metadata InvocationMetadata) erro
return r.WriteJSONArtifact(ArtifactInvocationMetadata, metadata)
}
func (r *RunDirectory) WriteRedactedEffectiveConfig(payload any) error {
return r.WriteJSONArtifact(ArtifactEffectiveConfig, payload)
func (r *RunDirectory) WriteRedactedEffectiveConfig(payload RedactedEffectiveConfigPayload) error {
if payload == nil {
return fmt.Errorf("redacted effective config payload must not be nil")
}
return r.WriteJSONArtifact(ArtifactEffectiveConfig, payload.RedactedDiagnosticsPayload())
}
func (r *RunDirectory) WriteResolvedPipeline(payload any) error {

View File

@@ -167,7 +167,7 @@ func TestWriteInvocationMetadataPreservesProvidedRunIDAndStartTime(t *testing.T)
func TestWriteTypedArtifacts(t *testing.T) {
runDir := newTestRunDirectory(t)
if err := runDir.WriteRedactedEffectiveConfig(map[string]any{"redacted": true}); err != nil {
if err := runDir.WriteRedactedEffectiveConfig(fakeRedactedEffectiveConfig{payload: map[string]any{"redacted": true}}); err != nil {
t.Fatalf("WriteRedactedEffectiveConfig: %v", err)
}
if err := runDir.WriteResolvedPipeline(map[string]any{"pipeline": "test"}); err != nil {
@@ -200,6 +200,24 @@ func TestWriteTypedArtifacts(t *testing.T) {
}
}
func TestWriteRedactedEffectiveConfigWritesPayloadReturnedByProvider(t *testing.T) {
runDir := newTestRunDirectory(t)
if err := runDir.WriteRedactedEffectiveConfig(fakeRedactedEffectiveConfig{
payload: map[string]any{
"api_key": "[REDACTED]",
"model": "test-model",
},
}); err != nil {
t.Fatalf("WriteRedactedEffectiveConfig: %v", err)
}
data := string(readArtifact(t, runDir, ArtifactEffectiveConfig))
if !strings.Contains(data, `"api_key": "[REDACTED]"`) || !strings.Contains(data, `"model": "test-model"`) {
t.Fatalf("unexpected effective config artifact: %s", data)
}
}
func TestWriteErrorLogWritesPlainTextWithTrailingNewline(t *testing.T) {
runDir := newTestRunDirectory(t)
@@ -320,3 +338,11 @@ func readArtifact(t *testing.T, runDir *RunDirectory, name string) []byte {
}
return data
}
type fakeRedactedEffectiveConfig struct {
payload any
}
func (f fakeRedactedEffectiveConfig) RedactedDiagnosticsPayload() any {
return f.payload
}