From 303a252dd7b183bd776d88ea04ee8773a78b08f2 Mon Sep 17 00:00:00 2001 From: Alessandro Patti Date: Fri, 18 Aug 2023 09:32:31 +0200 Subject: [PATCH] Basic --- config/BUILD.bazel | 1 + config/proxy.go | 16 ++++++++++++++++ server/grpc_basic_auth.go | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/config/BUILD.bazel b/config/BUILD.bazel index 31363c6f2..5e1409d42 100644 --- a/config/BUILD.bazel +++ b/config/BUILD.bazel @@ -30,6 +30,7 @@ go_library( "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//credentials/insecure:go_default_library", + "@org_golang_google_grpc//metadata:go_default_library", ], ) diff --git a/config/proxy.go b/config/proxy.go index c19213822..92850ca57 100644 --- a/config/proxy.go +++ b/config/proxy.go @@ -1,8 +1,10 @@ package config import ( + "context" "crypto/tls" "crypto/x509" + "encoding/base64" "fmt" "net/http" "os" @@ -16,6 +18,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/metadata" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" prom "github.com/prometheus/client_golang/prometheus" @@ -70,6 +73,19 @@ func (c *Config) setProxy() error { } else { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } + if password, ok := c.GRPCBackend.BaseURL.User.Password(); ok { + username := c.GRPCBackend.BaseURL.User.Username() + auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) + header := fmt.Sprintf("Basic %s", auth) + unaryAuth := func(ctx context.Context, method string, req, res interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + return invoker(metadata.AppendToOutgoingContext(ctx, "Authorization", header), method, req, res, cc, opts...) + } + streamAuth := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + return streamer(metadata.AppendToOutgoingContext(ctx, "Authorization", header), desc, cc, method, opts...) + } + opts = append(opts, grpc.WithChainUnaryInterceptor(unaryAuth), grpc.WithStreamInterceptor(streamAuth)) + } + metrics := grpc_prometheus.NewClientMetrics(func(o *prom.CounterOpts) { o.Namespace = "proxy" }) metrics.EnableClientHandlingTimeHistogram(func(o *prom.HistogramOpts) { o.Namespace = "proxy" }) err := prom.Register(metrics) diff --git a/server/grpc_basic_auth.go b/server/grpc_basic_auth.go index 8fa6064b0..61754f509 100644 --- a/server/grpc_basic_auth.go +++ b/server/grpc_basic_auth.go @@ -2,6 +2,7 @@ package server import ( "context" + "encoding/base64" "strings" "google.golang.org/grpc" @@ -123,6 +124,23 @@ func getLogin(ctx context.Context) (username, password string, err error) { return username, password, nil } + + if k == "authorization" && len(v) > 0 && strings.HasPrefix(v[0], "Basic ") { + // When bazel-remote is run with --grpc_proxy.url=grpc://user:pass@address/" + // the value looks like "Basic ". + auth, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(v[0], "Basic ")) + if err != nil { + continue + } + parts := strings.SplitN(string(auth), ":", 2) + if len(parts) < 2 { + continue + } + + username, password = parts[0], parts[1] + + return username, password, nil + } } return "", "", errNoAuthMetadata