137 lines
6.3 KiB
Go
137 lines
6.3 KiB
Go
package engine
|
|
|
|
import (
|
|
"bytes"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestInheritanceSensitivityFollowsCopiesWithoutMaskingNeighbors(t *testing.T) {
|
|
const canary = "INHERITED-CANARY-CREDENTIAL"
|
|
input := parseCompositionDocument(t, "source-1", "parent: {token: "+canary+", plain: visible}\nchild: {extends: parent}\nnext: {extends: child}\nother: {extends: parent}\n")
|
|
for _, classified := range []Path{Keys("parent", "token"), Keys("next", "token")} {
|
|
t.Run(classified.String(), func(t *testing.T) {
|
|
inspection, _ := inheritanceInspectionForTest(t, input)
|
|
inspection.secrets = classifySecretPaths(nil, func(path Path) bool {
|
|
return path.String() == classified.String()
|
|
}, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
|
for _, path := range []Path{Keys("parent", "token"), Keys("child", "token"), Keys("next", "token"), Keys("other", "token")} {
|
|
explanation, found := inspection.Explain(path)
|
|
if !found || !explanation.Effective.Redacted || strings.Contains(explanation.Effective.YAML, canary) {
|
|
t.Fatalf("sensitive copy %s = %#v, %v", path, explanation, found)
|
|
}
|
|
for _, change := range explanation.History {
|
|
if strings.Contains(change.Before.YAML, canary) || strings.Contains(change.After.YAML, canary) {
|
|
t.Fatalf("historical canary at %s: %#v", path, change)
|
|
}
|
|
}
|
|
}
|
|
plain, found := inspection.Explain(Keys("other", "plain"))
|
|
if !found || plain.Effective.Redacted || plain.Effective.YAML != "visible\n" {
|
|
t.Fatalf("unrelated field = %#v, %v", plain, found)
|
|
}
|
|
var output bytes.Buffer
|
|
if err := inspection.WriteEffective(&output); err != nil || strings.Contains(output.String(), canary) || !strings.Contains(output.String(), "visible") {
|
|
t.Fatalf("effective rendering = %q, %v", output.String(), err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInheritanceSensitivityPreservesDisplacedHistoryAndControl(t *testing.T) {
|
|
const canary = "DISPLACED-CANARY-CREDENTIAL"
|
|
inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {branch: {token: "+canary+"}}\nchild: {extends: parent, branch: public}\n"))
|
|
inspection.secrets = classifySecretPaths(nil, func(path Path) bool {
|
|
return path.String() == Keys("parent", "branch", "token").String() || path.String() == Keys("child", inheritanceKey).String()
|
|
}, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
|
path := Keys("child", "branch", "token")
|
|
explanation, found := inspection.Explain(path)
|
|
if !found || explanation.Effective.Present {
|
|
t.Fatalf("displaced sensitive path = %#v, %v", explanation, found)
|
|
}
|
|
for _, change := range explanation.History {
|
|
if strings.Contains(change.Before.YAML, canary) || strings.Contains(change.After.YAML, canary) ||
|
|
(change.After.Present && !change.After.Redacted) {
|
|
t.Fatalf("displaced secret leaked: %#v", explanation.History)
|
|
}
|
|
}
|
|
var rendered bytes.Buffer
|
|
if err := inspection.WriteExplanation(&rendered, path); err != nil || strings.Contains(rendered.String(), canary) {
|
|
t.Fatalf("displaced explanation rendering = %q, %v", rendered.String(), err)
|
|
}
|
|
control, found := inspection.Explain(Keys("child", inheritanceKey))
|
|
if !found || control.Effective.Present || len(control.History) == 0 || !control.History[0].After.Redacted {
|
|
t.Fatalf("sensitive control history = %#v, %v", control, found)
|
|
}
|
|
info, found := inspection.Metadata().Lookup(Keys("child", "branch"))
|
|
if !found || len(info.Origin.Inheritance) != 0 {
|
|
t.Fatalf("independent replacement provenance = %#v, %v", info, found)
|
|
}
|
|
}
|
|
|
|
func TestInheritanceSensitivityIncludesSchemaTaggedSource(t *testing.T) {
|
|
type entry struct {
|
|
Token string `yaml:"token"`
|
|
}
|
|
type configuration struct {
|
|
Parent struct {
|
|
Token string `yaml:"token" configkit:"secret"`
|
|
} `yaml:"parent"`
|
|
Child entry `yaml:"child"`
|
|
}
|
|
schema, issue := buildSchema(reflect.TypeFor[configuration](), testSecretBinding())
|
|
if issue != nil {
|
|
t.Fatal(issue)
|
|
}
|
|
inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {token: TAGGED-CANARY}\nchild: {extends: parent}\n"))
|
|
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
|
child, found := inspection.Explain(Keys("child", "token"))
|
|
if !found || !child.Effective.Redacted || strings.Contains(child.Effective.YAML, "TAGGED-CANARY") {
|
|
t.Fatalf("tagged source copy = %#v, %v", child, found)
|
|
}
|
|
}
|
|
|
|
func TestInheritedSecretReferencesResolveOnlyAfterExpansion(t *testing.T) {
|
|
type entry struct {
|
|
Credential Secret `yaml:"credential"`
|
|
}
|
|
type configuration struct {
|
|
Entries map[string]entry `yaml:"entries"`
|
|
}
|
|
schema, issue := buildSchema(reflect.TypeFor[configuration](), testSecretBinding())
|
|
if issue != nil {
|
|
t.Fatal(issue)
|
|
}
|
|
composed, diagnostics := composeDocuments(parseCompositionDocument(t, "source-1", "entries:\n parent: {credential: INHERITED_SECRET_NAME}\n child: {extends: parent}\n"))
|
|
if len(diagnostics) != 0 {
|
|
t.Fatal(diagnostics)
|
|
}
|
|
expanded, diagnostics := expandInheritanceWithOrigins(composed.root, composed.origins, defaultProjectionLimits())
|
|
if len(diagnostics) != 0 {
|
|
t.Fatal(diagnostics)
|
|
}
|
|
lookupCount := 0
|
|
decoded, issues := decodeConfiguration(schema, reflect.Zero(reflect.TypeFor[configuration]()), expanded.root)
|
|
if len(issues) != 0 || lookupCount != 0 {
|
|
t.Fatalf("decoding and lookup order = %#v, %d", issues, lookupCount)
|
|
}
|
|
resolved := resolveSecretReferences(decoded.value, schema, expanded.root, func(name string) (string, bool) {
|
|
lookupCount++
|
|
if name != "INHERITED_SECRET_NAME" {
|
|
t.Fatalf("inherited reference name = %q", name)
|
|
}
|
|
return "RESOLVED-CREDENTIAL-CANARY", true
|
|
})
|
|
if len(resolved.diagnostics) != 0 || lookupCount != 1 ||
|
|
decoded.value.Interface().(configuration).Entries["child"].Credential.Value() != "RESOLVED-CREDENTIAL-CANARY" {
|
|
t.Fatalf("inherited reference resolution = %#v, %d", resolved.diagnostics, lookupCount)
|
|
}
|
|
inspection, _ := inheritanceInspectionFromComposition(t, composed)
|
|
inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input)
|
|
var rendered bytes.Buffer
|
|
if err := inspection.WriteEffective(&rendered); err != nil || strings.Contains(rendered.String(), "RESOLVED-CREDENTIAL-CANARY") {
|
|
t.Fatalf("reference rendering = %q, %v", rendered.String(), err)
|
|
}
|
|
}
|