fix: harden read-only target diagnostics
This commit is contained in:
@@ -188,9 +188,12 @@ func (a *Adapter) DiagnosticChecks(_ context.Context, _ *profile.Profile) []targ
|
||||
} else if proxies, _, err := childObject(config, "proxies"); err != nil {
|
||||
schemaCheck.OK = false
|
||||
schemaCheck.Evidence = profile.RedactText(err.Error())
|
||||
} else if _, _, err := childObject(proxies, "default"); err != nil {
|
||||
} else if defaults, _, err := childObject(proxies, "default"); err != nil {
|
||||
schemaCheck.OK = false
|
||||
schemaCheck.Evidence = profile.RedactText(err.Error())
|
||||
} else if err := validateManagedProxyStrings(defaults); err != nil {
|
||||
schemaCheck.OK = false
|
||||
schemaCheck.Evidence = err.Error()
|
||||
} else if _, _, err := a.readRecovery(); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
schemaCheck.OK = false
|
||||
schemaCheck.Evidence = profile.RedactText("Docker client recovery metadata is invalid or unreadable: " + err.Error())
|
||||
@@ -305,6 +308,9 @@ func (a *Adapter) enable(active *profile.Profile) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateManagedProxyStrings(defaults); err != nil {
|
||||
return err
|
||||
}
|
||||
if !managed {
|
||||
metadata = recovery{ConfigPresent: configPresent, ProxiesPresent: proxiesPresent, DefaultPresent: defaultPresent, Original: make(map[string]priorValue)}
|
||||
for _, key := range managedKeys {
|
||||
@@ -463,6 +469,20 @@ func childObject(parent map[string]json.RawMessage, key string) (map[string]json
|
||||
object, err := decodeObject(raw, "Docker client "+key+" setting")
|
||||
return object, true, err
|
||||
}
|
||||
func validateManagedProxyStrings(defaults map[string]json.RawMessage) error {
|
||||
for _, key := range managedKeys {
|
||||
raw, present := defaults[key]
|
||||
if !present {
|
||||
continue
|
||||
}
|
||||
var value string
|
||||
if err := json.Unmarshal(raw, &value); err != nil {
|
||||
return fmt.Errorf("Docker client proxies.default.%s must be a JSON string", key)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setChildObject(parent map[string]json.RawMessage, key string, child map[string]json.RawMessage) {
|
||||
data, _ := json.Marshal(child)
|
||||
parent[key] = data
|
||||
|
||||
@@ -67,6 +67,43 @@ func TestDiagnosticChecksCoverSchemaAndAuthorityWithoutMutation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiagnosticsAndEnableRejectMalformedManagedProxyTypesWithoutMutation(t *testing.T) {
|
||||
for _, document := range []string{
|
||||
`{"proxies":[]}`,
|
||||
`{"proxies":{"default":[]}}`,
|
||||
`{"proxies":{"default":{"httpProxy":42}}}`,
|
||||
`{"proxies":{"default":{"httpsProxy":false}}}`,
|
||||
`{"proxies":{"default":{"allProxy":{}}}}`,
|
||||
`{"proxies":{"default":{"noProxy":[]}}}`,
|
||||
} {
|
||||
t.Run(document, func(t *testing.T) {
|
||||
files := &countingFS{FileSystem: dockerclient.OSFileSystem{}}
|
||||
a := newAdapterWithFS(t, files)
|
||||
writeConfig(t, a.ConfigPath(), document)
|
||||
before, err := os.ReadFile(a.ConfigPath())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checks := a.DiagnosticChecks(context.Background(), activeProfile())
|
||||
if checks[1].OK {
|
||||
t.Fatalf("malformed schema passed diagnostics: %#v", checks)
|
||||
}
|
||||
writesBefore := files.writes
|
||||
result := a.SetDesired(context.Background(), true, activeProfile())
|
||||
if result.Err == nil {
|
||||
t.Fatalf("enable accepted malformed schema: %#v", result)
|
||||
}
|
||||
after, err := os.ReadFile(a.ConfigPath())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(after) != string(before) || files.writes != writesBefore {
|
||||
t.Fatalf("malformed config was modified: writes %d -> %d", writesBefore, files.writes)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerClientAdapterRunsReusableTargetContract(t *testing.T) {
|
||||
targettest.Run(t, func(t *testing.T) targettest.Fixture {
|
||||
a := newAdapter(t, nil)
|
||||
|
||||
Reference in New Issue
Block a user