8000 Go: Support private registries via `GOPROXY` by mbg · Pull Request #19248 · github/codeql · GitHub
[go: up one dir, main page]

Skip to content

Go: Support private registries via GOPROXY #19248

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

Merged
merged 9 commits into from
Apr 25, 2025
Prev Previous commit
Next Next commit
Go: Refactor ApplyProxyEnvVars
  • Loading branch information
mbg committed Apr 25, 2025
commit cafe1efefa9c85da7df8d53a61641b15b3fe0ac0
71 changes: 46 additions & 25 deletions go/extractor/util/registryproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,23 @@ type RegistryConfig struct {
URL string `json:"url"`
}

// The address of the proxy including protocol and port (e.g. http://localhost:1234)
var proxy_address string

// The path to the temporary file that stores the proxy certificate, if any.
var proxy_cert_file string

// An array of registry configurations that are relevant to Go.
// This excludes other registry configurations that may be available, but are not relevant to Go.
var proxy_configs []RegistryConfig

// Stores the environment variables that we wish to pass on to `go` commands.
var proxy_vars []string = nil

// Keeps track of whether we have inspected the proxy environment variables.
// Needed since `proxy_vars` may be nil either way.
var proxy_vars_checked bool = false

// Tries to parse the given string value into an array of RegistryConfig values.
func parseRegistryConfigs(str string) ([]RegistryConfig, error) {
var configs []RegistryConfig
Expand All @@ -34,10 +47,21 @@ func parseRegistryConfigs(str string) ([]RegistryConfig, error) {
return configs, nil
}

func checkEnvVars() {
func getEnvVars() []string {
// If `proxy_vars` has been initialised, then we have already performed
// these checks and don't need to do so again. We assume that the environment
// variables are constant throughout the run of the autobuilder.
if proxy_vars != nil {
return proxy_vars
}

var result []string

if proxy_host, proxy_host_set := os.LookupEnv(PROXY_HOST); proxy_host_set {
if proxy_port, proxy_port_set := os.LookupEnv(PROXY_PORT); proxy_port_set {
proxy_address = fmt.Sprintf("http://%s:%s", proxy_host, proxy_port)
result = append(result, fmt.Sprintf("HTTP_PROXY=%s", proxy_address), fmt.Sprintf("HTTPS_PROXY=%s", proxy_address))

slog.Info("Found private registry proxy", slog.String("proxy_address", proxy_address))
}
}
Expand All @@ -61,6 +85,7 @@ func checkEnvVars() {
slog.Error("Failed to close the temporary certificate file", slog.String("error", err.Error()))
} else {
proxy_cert_file = f.Name()
result = append(result, fmt.Sprintf("SSL_CERT_FILE=%s", proxy_cert_file))
}
}

Expand All @@ -71,47 +96,43 @@ func checkEnvVars() {
} else {
// We only care about private registry configurations that are relevant to Go and
// filter others out at this point.
proxy_configs = make([]RegistryConfig, 0)
for _, cfg := range val {
if cfg.Type == GOPROXY_SERVER {
proxy_configs = append(proxy_configs, cfg)
slog.Info("Found GOPROXY server", slog.String("url", cfg.URL))
}
}

if len(proxy_configs) > 0 {
goproxy_val := "https://proxy.golang.org,direct"

for _, cfg := range proxy_configs {
goproxy_val = cfg.URL + "," + goproxy_val
}

result = append(result, fmt.Sprintf("GOPROXY=%s", goproxy_val), "GOPRIVATE=", "GONOPROXY=")
}
}
}
}

// Applies private package proxy related environment variables to `cmd`.
func ApplyProxyEnvVars(cmd *exec.Cmd) {
slog.Info(
slog.Debug(
"Applying private registry proxy environment variables",
slog.String("cmd_args", strings.Join(cmd.Args, " ")),
)

checkEnvVars()

// Preserve environment variables
cmd.Env = os.Environ()

if proxy_address != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("HTTP_PROXY=%s", proxy_address))
cmd.Env = append(cmd.Env, fmt.Sprintf("HTTPS_PROXY=%s", proxy_address))
// If we haven't done so yet, check whether the proxy environment variables are set
// and extract information from them.
if !proxy_vars_checked {
proxy_vars = getEnvVars()
proxy_vars_checked = true
}
if proxy_cert_file != "" {
slog.Info("Setting SSL_CERT_FILE", slog.String("proxy_cert_file", proxy_cert_file))
cmd.Env = append(cmd.Env, fmt.Sprintf("SSL_CERT_FILE=%s", proxy_cert_file))
}

if len(proxy_configs) > 0 {
goproxy_val := "https://proxy.golang.org,direct"

for _, cfg := range proxy_configs {
goproxy_val = cfg.URL + "," + goproxy_val
}

cmd.Env = append(cmd.Env, fmt.Sprintf("GOPROXY=%s", goproxy_val))
cmd.Env = append(cmd.Env, "GOPRIVATE=")
cmd.Env = append(cmd.Env, "GONOPROXY=")
// If the proxy is configured, `proxy_vars` will be not `nil`. We append those
// variables Preserve environment variables
if proxy_vars != nil {
cmd.Env = append(os.Environ(), proxy_vars...)
}
}
0