Resolve typed credentials safely
This commit is contained in:
@@ -24,11 +24,8 @@ storage:
|
||||
if cfg.Pipeline.Storage.S3.RootPrefix != "dnd" {
|
||||
t.Fatalf("storage.s3.root_prefix = %q, want dnd", cfg.Pipeline.Storage.S3.RootPrefix)
|
||||
}
|
||||
if cfg.Pipeline.Storage.S3.AccessKeyIDEnv != DefaultS3AccessKeyIDEnv {
|
||||
t.Fatalf("storage.s3.access_key_id_env = %q, want %q", cfg.Pipeline.Storage.S3.AccessKeyIDEnv, DefaultS3AccessKeyIDEnv)
|
||||
}
|
||||
if cfg.Pipeline.Storage.S3.SecretKeyEnv != DefaultS3SecretAccessKeyEnv {
|
||||
t.Fatalf("storage.s3.secret_access_key_env = %q, want %q", cfg.Pipeline.Storage.S3.SecretKeyEnv, DefaultS3SecretAccessKeyEnv)
|
||||
if cfg.Pipeline.Storage.S3.AccessKeyID != nil || cfg.Pipeline.Storage.S3.SecretAccessKey != nil {
|
||||
t.Fatal("storage.s3 credentials should be optional without implicit references")
|
||||
}
|
||||
if cfg.Pipeline.Storage.S3.ForcePathStyle {
|
||||
t.Fatalf("storage.s3.force_path_style = true, want false default")
|
||||
@@ -82,14 +79,32 @@ storage:
|
||||
}
|
||||
}
|
||||
|
||||
func TestLegacyCredentialReferenceFieldsFailStrictDecode(t *testing.T) {
|
||||
for _, field := range []string{"access_key_id_env", "secret_access_key_env", "llm_api_key_env"} {
|
||||
t.Run(field, func(t *testing.T) {
|
||||
pipelineYAML := strings.Replace(testPipelineBaseYAML, "audita:\n binary: audita\n", "audita:\n binary: audita\n "+field+": LEGACY_SECRET\n", 1)
|
||||
if strings.HasPrefix(field, "access_") || strings.HasPrefix(field, "secret_access_") {
|
||||
pipelineYAML = testPipelineBaseYAML + "storage:\n backend: s3\n s3:\n bucket: test-bucket\n " + field + ": LEGACY_SECRET\n"
|
||||
}
|
||||
pipelinePath, _ := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
|
||||
_, err := LoadPipeline(pipelinePath)
|
||||
if err == nil || !strings.Contains(err.Error(), field) || !strings.Contains(err.Error(), "strict decode") {
|
||||
t.Fatalf("LoadPipeline() error = %v, want strict rejection of %s", err, field)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorageS3CredentialEnvNamesLoadAndValidate(t *testing.T) {
|
||||
t.Setenv("CUSTOM_KEY_ID", "synthetic-access-key")
|
||||
t.Setenv("CUSTOM_SECRET", "synthetic-secret-key")
|
||||
pipelineYAML := testPipelineBaseYAML + `
|
||||
storage:
|
||||
backend: s3
|
||||
s3:
|
||||
bucket: my-dnd-archive
|
||||
access_key_id_env: CUSTOM_KEY_ID
|
||||
secret_access_key_env: CUSTOM_SECRET
|
||||
access_key_id: CUSTOM_KEY_ID
|
||||
secret_access_key: CUSTOM_SECRET
|
||||
`
|
||||
pipelinePath, sessionPath := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
|
||||
|
||||
@@ -97,55 +112,69 @@ storage:
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error = %v", err)
|
||||
}
|
||||
if cfg.Pipeline.Storage.S3.AccessKeyIDEnv != "CUSTOM_KEY_ID" {
|
||||
t.Fatalf("storage.s3.access_key_id_env = %q, want CUSTOM_KEY_ID", cfg.Pipeline.Storage.S3.AccessKeyIDEnv)
|
||||
if cfg.Pipeline.Storage.S3.AccessKeyID == nil || cfg.Pipeline.Storage.S3.AccessKeyID.EnvName() != "CUSTOM_KEY_ID" || cfg.Pipeline.Storage.S3.AccessKeyID.Value() != "synthetic-access-key" {
|
||||
t.Fatal("storage.s3.access_key_id did not retain its resolved typed reference")
|
||||
}
|
||||
if cfg.Pipeline.Storage.S3.SecretKeyEnv != "CUSTOM_SECRET" {
|
||||
t.Fatalf("storage.s3.secret_access_key_env = %q, want CUSTOM_SECRET", cfg.Pipeline.Storage.S3.SecretKeyEnv)
|
||||
if cfg.Pipeline.Storage.S3.SecretAccessKey == nil || cfg.Pipeline.Storage.S3.SecretAccessKey.EnvName() != "CUSTOM_SECRET" || cfg.Pipeline.Storage.S3.SecretAccessKey.Value() != "synthetic-secret-key" {
|
||||
t.Fatal("storage.s3.secret_access_key did not retain its resolved typed reference")
|
||||
}
|
||||
if err := Validate(cfg); err != nil {
|
||||
t.Fatalf("Validate() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorageS3CredentialEnvValidation(t *testing.T) {
|
||||
func TestStorageS3CredentialReferenceValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pipelineYML string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "invalid access key env name",
|
||||
name: "invalid access key reference",
|
||||
pipelineYML: testPipelineBaseYAML + `
|
||||
storage:
|
||||
backend: s3
|
||||
s3:
|
||||
bucket: my-dnd-archive
|
||||
access_key_id_env: "123BAD"
|
||||
access_key_id: "123BAD"
|
||||
secret_access_key: CUSTOM_SECRET
|
||||
`,
|
||||
wantErr: "pipeline.storage.s3.access_key_id_env must be a valid environment variable name",
|
||||
wantErr: "secret.invalid_name",
|
||||
},
|
||||
{
|
||||
name: "invalid secret key env name",
|
||||
name: "partial pair",
|
||||
pipelineYML: testPipelineBaseYAML + `
|
||||
storage:
|
||||
backend: s3
|
||||
s3:
|
||||
bucket: my-dnd-archive
|
||||
secret_access_key_env: "bad-name"
|
||||
access_key_id: CUSTOM_KEY_ID
|
||||
`,
|
||||
wantErr: "pipeline.storage.s3.secret_access_key_env must be a valid environment variable name",
|
||||
wantErr: "must be configured together",
|
||||
},
|
||||
{
|
||||
name: "missing effective reference",
|
||||
pipelineYML: testPipelineBaseYAML + `
|
||||
storage:
|
||||
backend: s3
|
||||
s3:
|
||||
bucket: my-dnd-archive
|
||||
access_key_id: MISSING_CUSTOM_KEY_ID
|
||||
secret_access_key: MISSING_CUSTOM_SECRET
|
||||
`,
|
||||
wantErr: "secret.unset",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
pipelinePath, sessionPath := writeConfigFiles(t, tt.pipelineYML, testSessionBaseYAML)
|
||||
cfg, err := Load(pipelinePath, sessionPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error = %v", err)
|
||||
pipelinePath, _ := writeConfigFiles(t, tt.pipelineYML, testSessionBaseYAML)
|
||||
t.Setenv("CUSTOM_KEY_ID", "synthetic-access-key")
|
||||
t.Setenv("CUSTOM_SECRET", "synthetic-secret-key")
|
||||
cfg, err := LoadPipeline(pipelinePath)
|
||||
if err == nil {
|
||||
err = ValidatePipelineConfig(cfg)
|
||||
}
|
||||
err = Validate(cfg)
|
||||
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Fatalf("Validate() error = %v, want to contain %q", err, tt.wantErr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user