fix(auth): harden unified diagnostic execution
This commit is contained in:
@@ -43,10 +43,7 @@ func TestAuthCheckRunsOneShotCoreDiagnosticWithPristineJSON(t *testing.T) {
|
||||
if len(calls) != 1 {
|
||||
t.Fatalf("Docker calls = %#v, want one", calls)
|
||||
}
|
||||
want := installation.ComposeArgs("run", "--rm", "--no-deps", "--no-TTY", "core", "node", "dist/auth/diagnostic-command.js", "--json")
|
||||
if strings.Join(calls[0], "\x00") != strings.Join(want, "\x00") {
|
||||
t.Fatalf("auth check Docker call = %#v, want %#v", calls[0], want)
|
||||
}
|
||||
assertAuthOneShotCommand(t, installation, calls[0], false)
|
||||
}
|
||||
|
||||
func TestAuthCheckEmitsValidFailedReportFromRealExitError(t *testing.T) {
|
||||
@@ -142,6 +139,8 @@ func TestAuthDiagnosticsContractRejectsContradictionsDuplicatesAndAttackerFields
|
||||
|
||||
func TestAuthCheckRejectsNullAndUnexpectedDiagnosticFields(t *testing.T) {
|
||||
for _, report := range []string{
|
||||
`{"mode":"oidc","checks":[{"level":"error","code":"oidc_secret_missing","message":"failure"}]}`,
|
||||
`{"ready":null,"mode":"oidc","checks":[{"level":"error","code":"oidc_secret_missing","message":"failure"}]}`,
|
||||
`{"ready":false,"mode":"oidc","checks":[{"level":"error","code":"oidc_mapped_group_missing","message":"failure","field":null}]}`,
|
||||
`{"ready":false,"mode":"oidc","checks":[{"level":"error","code":"oidc_secret_missing","message":"failure","unexpected":"attacker"}]}`,
|
||||
} {
|
||||
@@ -185,9 +184,27 @@ func TestAuthCheckInteractiveForwardsOnlyTheValidatedDevicePrompt(t *testing.T)
|
||||
if len(calls) != 1 {
|
||||
t.Fatalf("Docker calls = %#v, want one", calls)
|
||||
}
|
||||
want := installation.ComposeArgs("run", "--rm", "--no-deps", "--no-TTY", "core", "node", "dist/auth/diagnostic-command.js", "--json", "--interactive")
|
||||
if strings.Join(calls[0], "\x00") != strings.Join(want, "\x00") {
|
||||
t.Fatalf("interactive auth command = %#v, want %#v", calls[0], want)
|
||||
assertAuthOneShotCommand(t, installation, calls[0], true)
|
||||
}
|
||||
|
||||
func TestAuthCheckFailsBeforeExecutionWhenDeclaredSecretCorpusIsIncomplete(t *testing.T) {
|
||||
installation := authInstallation(newAuthDirectory(t))
|
||||
installation.EnvFile = filepath.Join(t.TempDir(), "operator.env")
|
||||
missing := filepath.Join(t.TempDir(), "missing-pi-auth.json")
|
||||
if err := os.WriteFile(installation.EnvFile, []byte("PI_AUTH_FILE="+missing+"\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
calls := 0
|
||||
runner := runnerFunc(func(_ context.Context, _ []string, _ io.Reader) (compose.Result, error) {
|
||||
calls++
|
||||
return compose.Result{Stdout: `{"ready":true,"mode":"oidc","checks":[{"level":"info","code":"auth_ready","message":"Authentication is ready."}]}`}, nil
|
||||
})
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := RunWithRunner(context.Background(), installation, []string{"check", "--json"}, strings.NewReader(""), &stdout, &stderr, runner)
|
||||
|
||||
if code != 1 || calls != 0 || stdout.Len() != 0 || stderr.String() != "tht: authentication diagnostics could not be completed\n" {
|
||||
t.Fatalf("incomplete corpus was not refused before execution: code=%d calls=%d stdout=%q stderr=%q", code, calls, stdout.String(), stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +249,29 @@ func (run runnerFunc) Run(ctx context.Context, args []string, input io.Reader) (
|
||||
return run(ctx, args, input)
|
||||
}
|
||||
|
||||
func assertAuthOneShotCommand(t *testing.T, installation config.Installation, got []string, interactive bool) {
|
||||
t.Helper()
|
||||
prefix := installation.ComposeArgs("run", "--rm", "--no-deps", "--no-TTY", "--name")
|
||||
suffix := []string{"core", "node", "dist/auth/diagnostic-command.js", "--json"}
|
||||
if interactive {
|
||||
suffix = append(suffix, "--interactive")
|
||||
}
|
||||
if len(got) != len(prefix)+1+len(suffix) ||
|
||||
strings.Join(got[:len(prefix)], "\x00") != strings.Join(prefix, "\x00") ||
|
||||
strings.Join(got[len(prefix)+1:], "\x00") != strings.Join(suffix, "\x00") {
|
||||
t.Fatalf("auth check Docker call = %#v, want named one-shot command", got)
|
||||
}
|
||||
name := got[len(prefix)]
|
||||
if !strings.HasPrefix(name, "thothii-auth-check-") || len(name) != len("thothii-auth-check-")+24 {
|
||||
t.Fatalf("auth check container name = %q, want unique bounded name", name)
|
||||
}
|
||||
for _, character := range name {
|
||||
if !(character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '-') {
|
||||
t.Fatalf("auth check container name = %q, want safe characters", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfiguresLocalRegistryAndRedactsStatusJSON(t *testing.T) {
|
||||
directory := newAuthDirectory(t)
|
||||
passwordFile := writePasswordFile(t, "this is a local test password\n")
|
||||
@@ -538,7 +578,7 @@ func writeAuthExecutable(t *testing.T, contents string) string {
|
||||
func stringPointer(value string) *string { return &value }
|
||||
|
||||
func authInstallation(directory string) config.Installation {
|
||||
installation := config.Installation{}
|
||||
installation := config.Installation{EnvFile: filepath.Join(filepath.Dir(directory), "operator.env")}
|
||||
installation.Authentication.ConfigDirectory = directory
|
||||
return installation
|
||||
}
|
||||
@@ -549,6 +589,9 @@ func newAuthDirectory(t *testing.T) string {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(root, "operator.env"), []byte("SAFE_VALUE=1\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return filepath.Join(root, "auth")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user