fix(auth): harden unified diagnostic execution

This commit is contained in:
2026-08-17 17:25:26 +02:00
parent 30ee9433dc
commit ef244ab56d
18 changed files with 670 additions and 68 deletions
+24 -7
View File
@@ -98,7 +98,7 @@ func RunWithProbe(ctx context.Context, installation config.Installation, runner
if probe == nil {
return Report{}, errors.New("doctor requires an HTTP probe")
}
secretValues := secretValues(installation)
secretValues, secretErr := secretValues(installation)
report := Report{Checks: make([]Check, 0, 12)}
add := func(name, status, detail string) {
report.Checks = append(report.Checks, Check{Name: name, Status: status, Detail: output.SanitizeDetail(detail, secretValues)})
@@ -109,11 +109,28 @@ func RunWithProbe(ctx context.Context, installation config.Installation, runner
} else {
add("descriptor", StatusPassed, "installation descriptor is loaded")
}
if err := filePermissions(installation); err != nil {
add("files", StatusFailed, err.Error())
if err := filePermissions(installation); err != nil || secretErr != nil {
if secretErr != nil {
add("files", StatusFailed, "declared secret files could not be read")
} else {
add("files", StatusFailed, err.Error())
}
} else {
add("files", StatusPassed, "declared host files have safe permissions")
}
if secretErr != nil {
add("docker", StatusSkipped, "declared secret files are unavailable")
add("compose", StatusSkipped, "declared secret files are unavailable")
add("configuration", StatusSkipped, "declared secret files are unavailable")
add("authentication", StatusSkipped, "declared secret files are unavailable")
add("services", StatusSkipped, "declared secret files are unavailable")
add("core-http", StatusSkipped, "declared secret files are unavailable")
add("frontend-http", StatusSkipped, "declared secret files are unavailable")
add("workspace-registry", StatusSkipped, "declared secret files are unavailable")
add("workflow", StatusSkipped, "declared secret files are unavailable")
add("pi", StatusSkipped, "declared secret files are unavailable")
return finalize(report), nil
}
if !commandCheck(ctx, runner, []string{"version", "--format", "{{.Client.Version}}"}, secretValues, add, "docker", "Docker Engine") {
add("compose", StatusSkipped, "Docker Engine is unavailable")
@@ -307,16 +324,16 @@ func validateInstallation(installation config.Installation) error {
return nil
}
func secretValues(installation config.Installation) []string {
func secretValues(installation config.Installation) ([]string, error) {
files, err := installation.SecretFiles()
if err != nil {
return nil
return nil, errors.New("declared secret files could not be read")
}
values, err := output.SecretValuesFromFiles(files)
if err != nil {
return nil
return nil, errors.New("declared secret files could not be read")
}
return values
return values, nil
}
func filePermissions(installation config.Installation) error {
+22
View File
@@ -181,6 +181,28 @@ func TestRunRedactsWorkflowDiagnosticFailures(t *testing.T) {
}
}
func TestRunFailsBeforeDockerWhenDeclaredSecretCorpusIsIncomplete(t *testing.T) {
installation := doctorInstallation(t, "")
missing := filepath.Join(filepath.Dir(installation.EnvFile), "missing-pi-auth.json")
if err := os.WriteFile(installation.EnvFile, []byte("PI_AUTH_FILE="+missing+"\n"), 0o600); err != nil {
t.Fatal(err)
}
runner := &doctorRunner{services: healthyServices}
report, err := Run(context.Background(), installation, runner)
if err != nil {
t.Fatal(err)
}
if report.OK || checkStatus(report, "files") != StatusFailed || len(runner.calls) != 0 {
t.Fatalf("incomplete corpus was not refused before Docker: report=%#v calls=%v", report, runner.calls)
}
if strings.Contains(reportText(report), missing) {
t.Fatalf("incomplete corpus report exposed a secret path: %#v", report)
}
assertChecklist(t, report, []string{"descriptor", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
}
func doctorInstallation(t *testing.T, _ string) config.Installation {
t.Helper()
base, err := filepath.EvalSymlinks(os.TempDir())