feat(server): activate projected authentication safely

This commit is contained in:
User
2026-08-22 01:01:36 +02:00
parent 903c0b4de5
commit 3d9a9f0675
32 changed files with 1837 additions and 38 deletions
+97
View File
@@ -12,6 +12,7 @@ import (
"time"
"github.com/aritmolab/thothii/tools/tht/internal/authconfig"
"github.com/aritmolab/thothii/tools/tht/internal/authprojection"
"github.com/aritmolab/thothii/tools/tht/internal/compose"
"github.com/aritmolab/thothii/tools/tht/internal/config"
"github.com/aritmolab/thothii/tools/tht/internal/doctor"
@@ -99,6 +100,102 @@ func TestRunConfiguresAndStaticallyValidatesLocalAuthBeforeComposeRender(t *test
assertSetupStages(t, runner, "docker engine", "docker compose", "architecture", "compose config")
}
func TestRunConfigureOnlyPublishesInitialProjectedServerAuthentication(t *testing.T) {
projectRoot, request := setupRunFixture(t, true)
request.Profile = "server"
if err := os.WriteFile(filepath.Join(projectRoot, "deploy", "compose.auth-runtime-projection.yaml"), []byte("services: {}\n"), 0o600); err != nil {
t.Fatal(err)
}
if _, err := Run(context.Background(), &setupRunner{}, request, strings.NewReader(""), io.Discard); err != nil {
t.Fatal(err)
}
installation, err := config.Load(filepath.Join(projectRoot, "deploy", "ci", "thothii-installation.yaml"))
if err != nil {
t.Fatal(err)
}
projection := installation.RuntimeAuthProjection()
if projection == nil {
t.Fatal("generated server installation has no runtime auth projection")
}
status, err := authprojection.Inspect(authprojection.Spec{RuntimeRoot: projection.Directory, UID: projection.UID, GID: projection.GID})
if err != nil || status.Selector.State != "ready" {
t.Fatalf("initial runtime auth projection = %#v, %v; want ready", status, err)
}
}
func TestRunConfigureOnlyLeavesProjectedAuthenticationBlockedWhenInitialPublicationFails(t *testing.T) {
projectRoot, request := setupRunFixture(t, true)
request.Profile = "server"
if err := os.WriteFile(filepath.Join(projectRoot, "deploy", "compose.auth-runtime-projection.yaml"), []byte("services: {}\n"), 0o600); err != nil {
t.Fatal(err)
}
previous := publishProjectedCanonical
publishProjectedCanonical = func(ctx context.Context, canonicalRoot string, spec authconfig.ProjectionSpec) (authconfig.ProjectionStatus, error) {
transaction, err := authconfig.BeginExternalProjectionTransaction(ctx, canonicalRoot, spec)
if err != nil {
return authconfig.ProjectionStatus{}, err
}
if err := transaction.Close(); err != nil {
return authconfig.ProjectionStatus{}, err
}
return authconfig.ProjectionStatus{}, errors.New("synthetic-password-sentinel")
}
t.Cleanup(func() { publishProjectedCanonical = previous })
_, err := Run(context.Background(), &setupRunner{}, request, strings.NewReader(""), io.Discard)
if err == nil || strings.Contains(err.Error(), "synthetic-password-sentinel") {
t.Fatalf("Run() error = %v, want sanitized publication failure", err)
}
installation, loadErr := config.Load(filepath.Join(projectRoot, "deploy", "ci", "thothii-installation.yaml"))
if loadErr != nil {
t.Fatal(loadErr)
}
projection := installation.RuntimeAuthProjection()
if projection == nil {
t.Fatal("generated server installation has no runtime auth projection")
}
_, inspectErr := authprojection.Inspect(authprojection.Spec{RuntimeRoot: projection.Directory, UID: projection.UID, GID: projection.GID})
if !errors.Is(inspectErr, authprojection.ErrBlocked) {
t.Fatalf("Inspect() error = %v, want blocked projection", inspectErr)
}
}
func TestRunConfigureOnlyVerifiesProjectedAuthenticationAfterPublication(t *testing.T) {
projectRoot, request := setupRunFixture(t, true)
request.Profile = "server"
if err := os.WriteFile(filepath.Join(projectRoot, "deploy", "compose.auth-runtime-projection.yaml"), []byte("services: {}\n"), 0o600); err != nil {
t.Fatal(err)
}
previous := requireRuntimeAuthProjectionReady
calls := 0
requireRuntimeAuthProjectionReady = func(installation config.Installation) error {
calls++
projection := installation.RuntimeAuthProjection()
if projection == nil {
t.Fatal("post-publication readiness received an unprojected installation")
}
status, err := authprojection.Inspect(authprojection.Spec{
RuntimeRoot: projection.Directory,
UID: projection.UID,
GID: projection.GID,
})
if err != nil || status.Selector.State != "ready" {
t.Fatalf("post-publication projection = %#v, %v; want ready", status, err)
}
return errors.New("synthetic-readiness-secret")
}
t.Cleanup(func() { requireRuntimeAuthProjectionReady = previous })
_, err := Run(context.Background(), &setupRunner{}, request, strings.NewReader(""), io.Discard)
if err == nil || strings.Contains(err.Error(), "synthetic-readiness-secret") {
t.Fatalf("Run() error = %v, want sanitized post-publication readiness failure", err)
}
if calls != 1 {
t.Fatalf("post-publication readiness calls = %d, want 1", calls)
}
}
func TestRunRejectsIncompleteNonInteractiveLocalAuthenticationBeforeComposeRender(t *testing.T) {
_, request := setupRunFixture(t, true)
request.NonInteractive = true