From 054cfca04c8b1c353f0464c390f5d3e23c898e0c Mon Sep 17 00:00:00 2001 From: Alessandro Patti Date: Thu, 17 Aug 2023 20:29:08 +0200 Subject: [PATCH] Allow setting CA file for backend proxy --- README.md | 8 ++++++++ config/config.go | 6 ++++++ config/proxy.go | 19 ++++++++++++++++--- utils/flags/flags.go | 12 ++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14d5b7cd6..bf656c79b 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,10 @@ OPTIONS: grpc_proxy.key_file must also be specified. [BAZEL_REMOTE_GRPC_PROXY_CERT_FILE] + --grpc_proxy.ca_file value Path to a certificate autority used to validate + the proxy backend certificate. + [BAZEL_REMOTE_GRPC_PROXY_CA_FILE] + --http_proxy.url value The base URL to use for a http proxy backend. [$BAZEL_REMOTE_HTTP_PROXY_URL] @@ -270,6 +274,10 @@ OPTIONS: http_proxy.key_file must also be specified. [$BAZEL_REMOTE_HTTP_PROXY_CERT_FILE] + --http_proxy.ca_file value Path to a certificate autority used to validate + the http proxy backend certificate + [BAZEL_REMOTE_HTTP_PROXY_CA_FILE] + --gcs_proxy.bucket value The bucket to use for the Google Cloud Storage proxy backend. [$BAZEL_REMOTE_GCS_BUCKET] diff --git a/config/config.go b/config/config.go index 7d2bfbf82..05584a3ed 100644 --- a/config/config.go +++ b/config/config.go @@ -35,6 +35,7 @@ type URLBackendConfig struct { BaseURL *url.URL `yaml:"url"` CertFile string `yaml:"cert_file"` KeyFile string `yaml:"key_file"` + CaFile string `yaml:"ca_file"` } func (c *URLBackendConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { @@ -72,6 +73,9 @@ func (c *URLBackendConfig) validate(protocol string) error { return fmt.Errorf("When mTLS is enabled, the %[1]s proxy backend protocol must be %[1]ss", protocol) } } + if c.CaFile != "" && c.BaseURL.Scheme != "grpcs" { + return errors.New("When TLS is enabled, the grpc proxy backend protocol must be grpcs") + } return nil } @@ -530,6 +534,7 @@ func get(ctx *cli.Context) (*Config, error) { BaseURL: u, KeyFile: ctx.String("http_proxy.key_file"), CertFile: ctx.String("http_proxy.cert_file"), + CaFile: ctx.String("http_proxy.ca_file"), } } @@ -544,6 +549,7 @@ func get(ctx *cli.Context) (*Config, error) { BaseURL: u, KeyFile: ctx.String("grpc_proxy.key_file"), CertFile: ctx.String("grpc_proxy.cert_file"), + CaFile: ctx.String("grpc_proxy.ca_file"), } } diff --git a/config/proxy.go b/config/proxy.go index 00293af2b..c19213822 100644 --- a/config/proxy.go +++ b/config/proxy.go @@ -2,8 +2,10 @@ package config import ( "crypto/tls" + "crypto/x509" "fmt" "net/http" + "os" "github.com/buchgr/bazel-remote/v2/cache/azblobproxy" "github.com/buchgr/bazel-remote/v2/cache/gcsproxy" @@ -19,7 +21,7 @@ import ( prom "github.com/prometheus/client_golang/prometheus" ) -func getTLSConfig(certFile, keyFile string) (*tls.Config, error) { +func getTLSConfig(certFile, keyFile, caFile string) (*tls.Config, error) { config := &tls.Config{} if certFile != "" && keyFile != "" { readCert, err := tls.LoadX509KeyPair(certFile, keyFile) @@ -29,6 +31,17 @@ func getTLSConfig(certFile, keyFile string) (*tls.Config, error) { config.Certificates = []tls.Certificate{readCert} } + if caFile != "" { + caCert, err := os.ReadFile(caFile) + if err != nil { + return nil, err + } + caCertPool := x509.NewCertPool() + if added := caCertPool.AppendCertsFromPEM(caCert); !added { + return nil, fmt.Errorf("Failed to add ca cert to cert pool.") + } + config.RootCAs = caCertPool + } return config, nil } @@ -48,7 +61,7 @@ func (c *Config) setProxy() error { if c.GRPCBackend != nil { var opts []grpc.DialOption if c.GRPCBackend.BaseURL.Scheme == "grpcs" { - config, err := getTLSConfig(c.GRPCBackend.CertFile, c.GRPCBackend.KeyFile) + config, err := getTLSConfig(c.GRPCBackend.CertFile, c.GRPCBackend.KeyFile, c.GRPCBackend.CaFile) if err != nil { return err } @@ -84,7 +97,7 @@ func (c *Config) setProxy() error { if c.HTTPBackend != nil { httpClient := &http.Client{} if c.HTTPBackend.BaseURL.Scheme == "https" { - config, err := getTLSConfig(c.HTTPBackend.CertFile, c.HTTPBackend.KeyFile) + config, err := getTLSConfig(c.HTTPBackend.CertFile, c.HTTPBackend.KeyFile, c.HTTPBackend.CaFile) if err != nil { return err } diff --git a/utils/flags/flags.go b/utils/flags/flags.go index c48f07b3c..8dbd29d04 100644 --- a/utils/flags/flags.go +++ b/utils/flags/flags.go @@ -201,6 +201,12 @@ func GetCliFlags() []cli.Flag { Usage: "Path to a certificate used to authenticate with the proxy backend using mTLS. If this flag is provided, then grpc_proxy.key_file must also be specified.", EnvVars: []string{"BAZEL_REMOTE_GRPC_PROXY_CERT_FILE"}, }, + &cli.StringFlag{ + Name: "grpc_proxy.ca_file", + Value: "", + Usage: "Path to a certificate autority used to validate the grpc proxy backend certificate.", + EnvVars: []string{"BAZEL_REMOTE_GRPC_PROXY_CA_FILE"}, + }, &cli.StringFlag{ Name: "http_proxy.url", Value: "", @@ -219,6 +225,12 @@ func GetCliFlags() []cli.Flag { Usage: "Path to a certificate used to authenticate with the proxy backend using mTLS. If this flag is provided, then http_proxy.key_file must also be specified.", EnvVars: []string{"BAZEL_REMOTE_HTTP_PROXY_CERT_FILE"}, }, + &cli.StringFlag{ + Name: "http_proxy.ca_file", + Value: "", + Usage: "Path to a certificate autority used to validate the http proxy backend certificate.", + EnvVars: []string{"BAZEL_REMOTE_HTTP_PROXY_CA_FILE"}, + }, &cli.StringFlag{ Name: "gcs_proxy.bucket", Value: "",