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
+22 -6
View File
@@ -51,9 +51,20 @@ func productionRestoreDependencies(installation config.Installation) restoreDepe
},
cleanupCheckpoint: cleanupRecoveryCheckpoint,
acquireTransaction: lifecycle.AcquireTransaction,
runner: runner,
sleep: time.Sleep,
restoreFile: restoreFilePayload,
beginAuthProjection: func(ctx context.Context, target config.Installation) (authProjectionRestoreTransaction, error) {
projection := target.RuntimeAuthProjection()
if projection == nil {
return nil, errors.New("runtime authentication projection is unavailable")
}
return authconfig.BeginExternalProjectionTransaction(ctx, target.AuthenticationDirectory(), authconfig.ProjectionSpec{
RuntimeRoot: projection.Directory,
UID: projection.UID,
GID: projection.GID,
})
},
runner: runner,
sleep: time.Sleep,
restoreFile: restoreFilePayload,
restoreVolume: func(ctx context.Context, _ config.Installation, volume VolumeMetadata, input io.Reader) error {
result, err := runner.Stream(ctx, volumeRestoreCommand(volume.Name), input, io.Discard)
if err != nil || result.ExitCode != 0 {
@@ -75,8 +86,8 @@ func productionRestoreDependencies(installation config.Installation) restoreDepe
deps.prepareRecovery = func(ctx context.Context, target config.Installation, path string) (PreflightResult, error) {
return deps.preflight(ctx, target, PreflightRequest{Archive: path, Confirm: true, AllowExternalSecrets: true})
}
deps.recover = func(ctx context.Context, target config.Installation, recovery PreflightResult, staged *stagedArchive, wasRunning bool) error {
return recoverRestoreTransaction(ctx, target, recovery, staged, wasRunning, deps)
deps.recover = func(ctx context.Context, target config.Installation, recovery PreflightResult, staged *stagedArchive, wasRunning bool, transaction authProjectionRestoreTransaction) error {
return recoverRestoreTransaction(ctx, target, recovery, staged, wasRunning, deps, transaction)
}
return deps
}
@@ -88,7 +99,7 @@ func cleanupRecoveryCheckpoint(path string) error {
return nil
}
func recoverRestoreTransaction(ctx context.Context, installation config.Installation, recovery PreflightResult, staged *stagedArchive, wasRunning bool, deps restoreDependencies) (resultErr error) {
func recoverRestoreTransaction(ctx context.Context, installation config.Installation, recovery PreflightResult, staged *stagedArchive, wasRunning bool, deps restoreDependencies, transaction authProjectionRestoreTransaction) (resultErr error) {
if staged == nil || staged.file == nil {
return errors.New("recovery checkpoint was not staged before restore mutation")
}
@@ -109,6 +120,11 @@ func recoverRestoreTransaction(ctx context.Context, installation config.Installa
if err := deps.resetAuthenticationState(ctx, installation, deps.runner); err != nil {
return errors.Join(resultErr, err)
}
if transaction != nil {
if err := publishRestoredAuthentication(transaction); err != nil {
return errors.Join(resultErr, err)
}
}
if wasRunning {
if err := composeStartAndVerify(ctx, installation, deps.runner); err != nil {
resultErr = errors.Join(resultErr, err)