feat(server): activate projected authentication safely
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user