Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions components/egress/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ func main() {
ctx = withLogger(ctx)
defer log.Logger.Sync()

// Erase any stale mitmproxy CA left on the shared volume by a previous
// egress generation so the agent's bootstrap wait-loop blocks for this
// generation's export. See PurgeStaleExportedCA / upstream issue #1370.
mitmproxy.PurgeStaleExportedCA()
Comment thread
Pangjiping marked this conversation as resolved.

otelShutdown, err := telemetry.Init(ctx)
if err != nil {
log.Warnf("OpenTelemetry metrics disabled (continuing without OTLP): %v", err)
Expand Down
34 changes: 34 additions & 0 deletions components/egress/pkg/mitmproxy/cacert_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,40 @@ func waitMitmCACertPath(confDirEnv, home string) (string, error) {
return "", fmt.Errorf("mitmproxy CA not found after %v (tried: %v)", waitCACert, cands)
}

// PurgeStaleExportedCA removes any mitmproxy-ca-cert.pem left on the shared
// volume by a previous generation of this egress container. mitmproxy's CA
// lives in the egress container's ephemeral confdir, so an egress container
// restart rotates the CA while the previous public cert is still on the
// (pod-scoped) shared volume; without this purge, an agent container starting
// alongside us would pass its bootstrap readiness check on the stale file
// and install a CA that no longer matches what mitmproxy will sign with.
// See upstream issue #1370. Must be called as early as possible in main().
func PurgeStaleExportedCA() {
if !constants.IsTruthy(os.Getenv(constants.EnvMitmproxyTransparent)) {
return
}
purgeStaleExportedCAFrom(constants.OpenSandboxRootDir)
}

// purgeStaleExportedCAFrom is the testable core of PurgeStaleExportedCA.
func purgeStaleExportedCAFrom(rootDir string) {
path := filepath.Join(rootDir, mitmCACertName)
err := os.Remove(path)
switch {
case err == nil:
// warn: on first pod startup this file should not exist; its presence
// means the egress container (or process) has restarted, which is
// useful signal when diagnosing HTTPS-from-agent problems.
log.Warnf("[mitmproxy] removed stale exported CA at %s (previous egress generation left it behind; see upstream issue #1370)", path)
case os.IsNotExist(err):
// Common on first pod startup.
default:
// Non-fatal: SyncRootCA will overwrite the file. But on the race
// path the agent may still grab the old contents before we do.
log.Warnf("[mitmproxy] failed to remove stale exported CA at %s: %v", path, err)
}
}

func SyncRootCA(confDirEnv, home string) error {
src, err := waitMitmCACertPath(confDirEnv, home)
if err != nil {
Expand Down
39 changes: 39 additions & 0 deletions components/egress/pkg/mitmproxy/cacert_export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package mitmproxy

import (
"os"
"path/filepath"
"testing"

Expand All @@ -33,3 +34,41 @@ func TestCandidateCACertPaths(t *testing.T) {
filepath.Join(h, ".mitmproxy", mitmCACertName),
}, got)
}

func TestPurgeStaleExportedCAFrom_RemovesExistingFile(t *testing.T) {
root := t.TempDir()
path := filepath.Join(root, mitmCACertName)
require.NoError(t, os.WriteFile(path, []byte("stale-ca"), 0o644))

purgeStaleExportedCAFrom(root)

_, err := os.Stat(path)
require.True(t, os.IsNotExist(err), "expected file to be removed, got err=%v", err)
}

func TestPurgeStaleExportedCAFrom_NoFileIsNoOp(t *testing.T) {
root := t.TempDir()
// No file present; must not panic and must not create anything.
purgeStaleExportedCAFrom(root)

entries, err := os.ReadDir(root)
require.NoError(t, err)
require.Empty(t, entries)
}

func TestPurgeStaleExportedCAFrom_LeavesUnrelatedFiles(t *testing.T) {
root := t.TempDir()
stale := filepath.Join(root, mitmCACertName)
require.NoError(t, os.WriteFile(stale, []byte("stale-ca"), 0o644))

// A sibling file that must survive (e.g. the agent's merged bundle).
other := filepath.Join(root, "merged-ca-certificates.pem")
require.NoError(t, os.WriteFile(other, []byte("merged"), 0o644))

purgeStaleExportedCAFrom(root)

_, err := os.Stat(stale)
require.True(t, os.IsNotExist(err))
_, err = os.Stat(other)
require.NoError(t, err)
}
Loading