Skip to content

Commit 8ff31aa

Browse files
authored
Merge pull request #1371 from Pangjiping/fix/egress-purge-stale-mitm-ca
fix(egress): purge stale mitmproxy CA on startup
2 parents 924774e + b5d41e7 commit 8ff31aa

3 files changed

Lines changed: 78 additions & 0 deletions

File tree

components/egress/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ func main() {
5050
ctx = withLogger(ctx)
5151
defer log.Logger.Sync()
5252

53+
// Erase any stale mitmproxy CA left on the shared volume by a previous
54+
// egress generation so the agent's bootstrap wait-loop blocks for this
55+
// generation's export. See PurgeStaleExportedCA / upstream issue #1370.
56+
mitmproxy.PurgeStaleExportedCA()
57+
5358
otelShutdown, err := telemetry.Init(ctx)
5459
if err != nil {
5560
log.Warnf("OpenTelemetry metrics disabled (continuing without OTLP): %v", err)

components/egress/pkg/mitmproxy/cacert_export.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@ func waitMitmCACertPath(confDirEnv, home string) (string, error) {
6262
return "", fmt.Errorf("mitmproxy CA not found after %v (tried: %v)", waitCACert, cands)
6363
}
6464

65+
// PurgeStaleExportedCA removes any mitmproxy-ca-cert.pem left on the shared
66+
// volume by a previous generation of this egress container. mitmproxy's CA
67+
// lives in the egress container's ephemeral confdir, so an egress container
68+
// restart rotates the CA while the previous public cert is still on the
69+
// (pod-scoped) shared volume; without this purge, an agent container starting
70+
// alongside us would pass its bootstrap readiness check on the stale file
71+
// and install a CA that no longer matches what mitmproxy will sign with.
72+
// See upstream issue #1370. Must be called as early as possible in main().
73+
func PurgeStaleExportedCA() {
74+
if !constants.IsTruthy(os.Getenv(constants.EnvMitmproxyTransparent)) {
75+
return
76+
}
77+
purgeStaleExportedCAFrom(constants.OpenSandboxRootDir)
78+
}
79+
80+
// purgeStaleExportedCAFrom is the testable core of PurgeStaleExportedCA.
81+
func purgeStaleExportedCAFrom(rootDir string) {
82+
path := filepath.Join(rootDir, mitmCACertName)
83+
err := os.Remove(path)
84+
switch {
85+
case err == nil:
86+
// warn: on first pod startup this file should not exist; its presence
87+
// means the egress container (or process) has restarted, which is
88+
// useful signal when diagnosing HTTPS-from-agent problems.
89+
log.Warnf("[mitmproxy] removed stale exported CA at %s (previous egress generation left it behind; see upstream issue #1370)", path)
90+
case os.IsNotExist(err):
91+
// Common on first pod startup.
92+
default:
93+
// Non-fatal: SyncRootCA will overwrite the file. But on the race
94+
// path the agent may still grab the old contents before we do.
95+
log.Warnf("[mitmproxy] failed to remove stale exported CA at %s: %v", path, err)
96+
}
97+
}
98+
6599
func SyncRootCA(confDirEnv, home string) error {
66100
src, err := waitMitmCACertPath(confDirEnv, home)
67101
if err != nil {

components/egress/pkg/mitmproxy/cacert_export_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package mitmproxy
1616

1717
import (
18+
"os"
1819
"path/filepath"
1920
"testing"
2021

@@ -33,3 +34,41 @@ func TestCandidateCACertPaths(t *testing.T) {
3334
filepath.Join(h, ".mitmproxy", mitmCACertName),
3435
}, got)
3536
}
37+
38+
func TestPurgeStaleExportedCAFrom_RemovesExistingFile(t *testing.T) {
39+
root := t.TempDir()
40+
path := filepath.Join(root, mitmCACertName)
41+
require.NoError(t, os.WriteFile(path, []byte("stale-ca"), 0o644))
42+
43+
purgeStaleExportedCAFrom(root)
44+
45+
_, err := os.Stat(path)
46+
require.True(t, os.IsNotExist(err), "expected file to be removed, got err=%v", err)
47+
}
48+
49+
func TestPurgeStaleExportedCAFrom_NoFileIsNoOp(t *testing.T) {
50+
root := t.TempDir()
51+
// No file present; must not panic and must not create anything.
52+
purgeStaleExportedCAFrom(root)
53+
54+
entries, err := os.ReadDir(root)
55+
require.NoError(t, err)
56+
require.Empty(t, entries)
57+
}
58+
59+
func TestPurgeStaleExportedCAFrom_LeavesUnrelatedFiles(t *testing.T) {
60+
root := t.TempDir()
61+
stale := filepath.Join(root, mitmCACertName)
62+
require.NoError(t, os.WriteFile(stale, []byte("stale-ca"), 0o644))
63+
64+
// A sibling file that must survive (e.g. the agent's merged bundle).
65+
other := filepath.Join(root, "merged-ca-certificates.pem")
66+
require.NoError(t, os.WriteFile(other, []byte("merged"), 0o644))
67+
68+
purgeStaleExportedCAFrom(root)
69+
70+
_, err := os.Stat(stale)
71+
require.True(t, os.IsNotExist(err))
72+
_, err = os.Stat(other)
73+
require.NoError(t, err)
74+
}

0 commit comments

Comments
 (0)