mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Go: Detect and apply proxy settings (WIP)
This commit is contained in:
@@ -139,7 +139,9 @@ func SupportsWorkspaces() bool {
|
||||
|
||||
// Constructs a `*exec.Cmd` for `go` with the specified arguments.
|
||||
func GoCommand(arg ...string) *exec.Cmd {
|
||||
return exec.Command("go", arg...)
|
||||
cmd := exec.Command("go", arg...)
|
||||
util.ApplyProxyEnvVars(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Run `go mod tidy -e` in the directory given by `path`.
|
||||
|
||||
2
go/extractor/util/BUILD.bazel
generated
2
go/extractor/util/BUILD.bazel
generated
@@ -6,6 +6,7 @@ go_library(
|
||||
name = "util",
|
||||
srcs = [
|
||||
"extractvendordirs.go",
|
||||
"registryproxy.go",
|
||||
"semver.go",
|
||||
"util.go",
|
||||
],
|
||||
@@ -17,6 +18,7 @@ go_library(
|
||||
go_test(
|
||||
name = "util_test",
|
||||
srcs = [
|
||||
"registryproxy_test.go",
|
||||
"semver_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
|
||||
114
go/extractor/util/registryproxy.go
Normal file
114
go/extractor/util/registryproxy.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const PROXY_HOST = "CODEQL_PROXY_HOST"
|
||||
const PROXY_PORT = "CODEQL_PROXY_PORT"
|
||||
const PROXY_CA_CERTIFICATE = "CODEQL_PROXY_CA_CERTIFICATE"
|
||||
const PROXY_URLS = "CODEQL_PROXY_URLS"
|
||||
const GOPROXY_SERVER = "goproxy_server"
|
||||
|
||||
type RegistryConfig struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
var proxy_address string
|
||||
var proxy_cert_file string
|
||||
var proxy_configs []RegistryConfig
|
||||
|
||||
// Tries to parse the given string value into an array of RegistryConfig values.
|
||||
func parseRegistryConfigs(str string) ([]RegistryConfig, error) {
|
||||
var configs []RegistryConfig
|
||||
if err := json.Unmarshal([]byte(str), &configs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func checkEnvVars() {
|
||||
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)
|
||||
slog.Info("Found private registry proxy", slog.String("proxy_address", proxy_address))
|
||||
}
|
||||
}
|
||||
|
||||
if proxy_cert, proxy_cert_set := os.LookupEnv(PROXY_CA_CERTIFICATE); proxy_cert_set {
|
||||
// Write the certificate to a temporary file
|
||||
slog.Info("Found certificate")
|
||||
|
||||
f, err := os.CreateTemp("", "codeql-proxy.crt")
|
||||
if err != nil {
|
||||
slog.Error("Unable to create temporary file for the proxy certificate", slog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
_, err = f.WriteString(proxy_cert)
|
||||
if err != nil {
|
||||
slog.Error("Failed to write to the temporary certificate file", slog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
slog.Error("Failed to close the temporary certificate file", slog.String("error", err.Error()))
|
||||
} else {
|
||||
proxy_cert_file = f.Name()
|
||||
}
|
||||
}
|
||||
|
||||
if proxy_urls, proxy_urls_set := os.LookupEnv(PROXY_URLS); proxy_urls_set {
|
||||
val, err := parseRegistryConfigs(proxy_urls)
|
||||
if err != nil {
|
||||
slog.Error("Unable to parse proxy configurations", slog.String("error", err.Error()))
|
||||
} 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Applies private package proxy related environment variables to `cmd`.
|
||||
func ApplyProxyEnvVars(cmd *exec.Cmd) {
|
||||
slog.Info(
|
||||
"Applying private registry proxy environment variables",
|
||||
slog.String("cmd_args", strings.Join(cmd.Args, " ")),
|
||||
)
|
||||
|
||||
checkEnvVars()
|
||||
|
||||
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 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=")
|
||||
}
|
||||
}
|
||||
49
go/extractor/util/registryproxy_test.go
Normal file
49
go/extractor/util/registryproxy_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func parseRegistryConfigsFail(t *testing.T, str string) {
|
||||
_, err := parseRegistryConfigs(str)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("Expected `parseRegistryConfigs` to fail, but it succeeded.")
|
||||
}
|
||||
}
|
||||
|
||||
func parseRegistryConfigsSuccess(t *testing.T, str string) []RegistryConfig {
|
||||
val, err := parseRegistryConfigs(str)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Expected `parseRegistryConfigs` to succeed, but it failed: %s", err.Error())
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func TestParseRegistryConfigs(t *testing.T) {
|
||||
// parseRegistryConfigsFail(t, "")
|
||||
|
||||
empty := parseRegistryConfigsSuccess(t, "[]")
|
||||
|
||||
if len(empty) != 0 {
|
||||
t.Fatal("Expected `parseRegistryConfigs(\"[]\")` to return no configurations, but got some.")
|
||||
}
|
||||
|
||||
single := parseRegistryConfigsSuccess(t, "[{ \"type\": \"goproxy_server\", \"url\": \"https://proxy.example.com/mod\" }]")
|
||||
|
||||
if len(single) != 1 {
|
||||
t.Fatalf("Expected `parseRegistryConfigs` to return one configuration, but got %d.", len(single))
|
||||
}
|
||||
|
||||
first := single[0]
|
||||
|
||||
if first.Type != "goproxy_server" {
|
||||
t.Fatalf("Expected `Type` to be `goproxy_server`, but got `%s`", first.Type)
|
||||
}
|
||||
|
||||
if first.URL != "https://proxy.example.com/mod" {
|
||||
t.Fatalf("Expected `URL` to be `https://proxy.example.com/mod`, but got `%s`", first.URL)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user