-
Notifications
You must be signed in to change notification settings - Fork 21
Propagate DIFC proxy TLS CA trust to git/gh/curl via process environment #4042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
13c8864
7f15b33
39ade88
6ff7df7
11cf12a
f274154
d0e7f64
0ed4820
d676b90
2430c39
a2d0e31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,14 @@ import ( | |
| "context" | ||
| "crypto/tls" | ||
| "fmt" | ||
| "io" | ||
| "log" | ||
| "net" | ||
| "net/http" | ||
| "os" | ||
| "os/signal" | ||
| "path/filepath" | ||
| "strings" | ||
| "syscall" | ||
| "time" | ||
|
|
||
|
|
@@ -24,6 +26,14 @@ import ( | |
|
|
||
| var logProxyCmd = logger.New("cmd:proxy") | ||
|
|
||
| var tlsTrustEnvKeys = []string{ | ||
| "NODE_EXTRA_CA_CERTS", | ||
| "SSL_CERT_FILE", | ||
| "GIT_SSL_CAINFO", | ||
| "CURL_CA_BUNDLE", | ||
| "REQUESTS_CA_BUNDLE", | ||
| } | ||
|
|
||
| // Proxy subcommand flag variables | ||
| var ( | ||
| proxyGuardWasm string | ||
|
|
@@ -223,6 +233,9 @@ func runProxy(cmd *cobra.Command, args []string) error { | |
| if err != nil { | ||
| return fmt.Errorf("failed to generate TLS certificates: %w", err) | ||
| } | ||
| if err := configureTLSTrustEnvironment(tlsCfg.CACertPath); err != nil { | ||
| return err | ||
| } | ||
| logger.LogInfo("startup", "TLS certificates generated: ca=%s", tlsCfg.CACertPath) | ||
| } | ||
|
|
||
|
|
@@ -268,6 +281,8 @@ func runProxy(cmd *cobra.Command, args []string) error { | |
| fmt.Fprintf(os.Stderr, "\nConnect with:\n") | ||
| fmt.Fprintf(os.Stderr, " export GH_HOST=%s\n", clientAddr(actualAddr)) | ||
| fmt.Fprintf(os.Stderr, " export NODE_EXTRA_CA_CERTS=%s\n", tlsCfg.CACertPath) | ||
| fmt.Fprintf(os.Stderr, " export SSL_CERT_FILE=%s\n", tlsCfg.CACertPath) | ||
| fmt.Fprintf(os.Stderr, " export GIT_SSL_CAINFO=%s\n", tlsCfg.CACertPath) | ||
| fmt.Fprintf(os.Stderr, " gh issue list -R org/repo\n\n") | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "\nConnect with:\n") | ||
|
|
@@ -302,3 +317,37 @@ func clientAddr(addr string) string { | |
| } | ||
| return addr | ||
| } | ||
|
|
||
| func configureTLSTrustEnvironment(caCertPath string) error { | ||
| if strings.ContainsAny(caCertPath, "\r\n") { | ||
| return fmt.Errorf("invalid TLS CA cert path contains newline") | ||
| } | ||
|
|
||
| for _, key := range tlsTrustEnvKeys { | ||
| if err := os.Setenv(key, caCertPath); err != nil { | ||
| return fmt.Errorf("failed to set %s: %w", key, err) | ||
| } | ||
| } | ||
|
|
||
| githubEnvPath := os.Getenv("GITHUB_ENV") | ||
| if githubEnvPath == "" { | ||
| return nil | ||
| } | ||
|
|
||
| // Best-effort append: the proxy should still start even if GITHUB_ENV cannot be opened. | ||
| f, err := os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644) | ||
| if err != nil { | ||
| logger.LogWarn("startup", "Skipping GITHUB_ENV TLS trust export: open failed for %s: %v", githubEnvPath, err) | ||
| return nil | ||
| } | ||
| defer f.Close() | ||
|
|
||
| for _, key := range tlsTrustEnvKeys { | ||
| if _, err := io.WriteString(f, key+"="+caCertPath+"\n"); err != nil { | ||
| return fmt.Errorf("failed writing %s to GITHUB_ENV file: %w", key, err) | ||
| } | ||
|
||
| } | ||
|
|
||
| logProxyCmd.Printf("Appended TLS trust environment to GITHUB_ENV: %s", githubEnvPath) | ||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -409,3 +409,52 @@ func TestClientAddr(t *testing.T) { | |||||
| }) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| func TestConfigureTLSTrustEnvironment(t *testing.T) { | ||||||
| caPath := "/tmp/proxy-tls/ca.crt" | ||||||
|
|
||||||
| t.Run("sets trust environment variables in process", func(t *testing.T) { | ||||||
| assert := assert.New(t) | ||||||
| t.Setenv("GITHUB_ENV", "") | ||||||
| for _, key := range tlsTrustEnvKeys { | ||||||
| t.Setenv(key, "") | ||||||
| } | ||||||
|
|
||||||
| err := configureTLSTrustEnvironment(caPath) | ||||||
| require.NoError(t, err) | ||||||
|
|
||||||
| for _, key := range tlsTrustEnvKeys { | ||||||
| assert.Equal(caPath, os.Getenv(key), "expected %s to be set", key) | ||||||
| } | ||||||
| }) | ||||||
|
|
||||||
| t.Run("skips GITHUB_ENV append when env var is unset", func(t *testing.T) { | ||||||
|
||||||
| t.Run("skips GITHUB_ENV append when env var is unset", func(t *testing.T) { | |
| t.Run("skips GITHUB_ENV append when env var is unset or empty", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644)does not use the provided permissions unlessos.O_CREATEis set, so0o644is effectively ignored here. To avoid implying that permissions are being applied, consider passing0(or addingos.O_CREATEif you actually want to create the file when missing).