fix: harden operations and configuration recovery

This commit is contained in:
proxyctl coordinator
2026-08-30 11:13:45 +08:00
parent e34bf7d989
commit 8928986830
27 changed files with 542 additions and 125 deletions
+13 -2
View File
@@ -323,8 +323,19 @@ func (a *Adapter) disable() error {
if metadata.OriginalScript != nil {
restored = []byte(*metadata.OriginalScript)
}
if err := a.writeOwned(a.configuration.EnvironmentFile, restored); err != nil {
return fmt.Errorf("restore Shell environment: %w", err)
current, err := a.files.ReadFile(a.configuration.EnvironmentFile)
if err != nil {
return fmt.Errorf("read managed Shell environment before restore: %w", err)
}
switch currentFingerprint := fingerprint(current); currentFingerprint {
case fingerprint(restored):
// A previous recovery completed the file write but not metadata cleanup.
case metadata.Fingerprint:
if err := a.writeOwned(a.configuration.EnvironmentFile, restored); err != nil {
return fmt.Errorf("restore Shell environment: %w", err)
}
default:
return errors.New("Shell environment changed after proxyctl applied it; refusing to overwrite current configuration or discard recovery metadata")
}
if err := a.files.Remove(a.configuration.RecoveryFile); err != nil && !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("remove Shell recovery metadata after environment changed: %w", err)
+21
View File
@@ -296,6 +296,27 @@ func TestShellTargetContract(t *testing.T) {
assertState(t, a, activeProfile(), target.Drifted)
})
t.Run("drifted-environment-refuses-destructive-restore", func(t *testing.T) {
a := newAdapter(t, shellName, nil)
if result := a.SetDesired(context.Background(), true, activeProfile()); result.Err != nil {
t.Fatal(result.Err)
}
changed := "export HTTP_PROXY='http://user-change.example:8080'\n"
if err := os.WriteFile(a.EnvironmentPath(), []byte(changed), 0o600); err != nil {
t.Fatal(err)
}
result := a.SetDesired(context.Background(), false, nil)
if result.Err == nil || result.Inspection.State != target.Drifted {
t.Fatalf("unsafe restore = %#v", result)
}
if got := readFile(t, a.EnvironmentPath()); got != changed {
t.Fatalf("drifted environment overwritten:\n%s", got)
}
if _, err := os.Stat(a.RecoveryPath()); err != nil {
t.Fatalf("recovery metadata removed after refused restore: %v", err)
}
})
t.Run("validation-and-redaction", func(t *testing.T) {
fs := &failingFS{FileSystem: shell.OSFileSystem{}, failWrite: true}
a := newAdapterWithFS(t, shellName, nil, fs)