From 6c57052fbac995144762febc684e9a7a6fc29c59 Mon Sep 17 00:00:00 2001 From: Yannic Bonenberger Date: Thu, 28 Sep 2023 17:35:51 -0600 Subject: [PATCH 1/2] [go] Add support for authentication via Credential Helper This change adds support for Credential Helpers, similar to Bazel's support for Credential Helpers. --- go.mod | 3 ++- go.sum | 6 ++++-- go/pkg/client/BUILD.bazel | 2 ++ go/pkg/client/client.go | 19 +++++++++++++++++++ go/pkg/flags/BUILD.bazel | 1 + go/pkg/flags/flags.go | 13 +++++++++++++ go_deps.bzl | 7 +++++++ 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9a5b749a5..d3f90eb88 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/bazelbuild/remote-apis-sdks go 1.20 require ( + github.com/EngFlow/credential-helper-go v0.0.0-20230928231836-1ae22fe3da4b github.com/bazelbuild/remote-apis v0.0.0-20230411132548-35aee1c4a425 github.com/golang/glog v1.1.0 github.com/google/go-cmp v0.5.9 @@ -17,7 +18,7 @@ require ( google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577 google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d - google.golang.org/grpc v1.58.0-dev.0.20230804151048-7aceafcc52f9 + google.golang.org/grpc v1.58.0 google.golang.org/protobuf v1.31.0 ) diff --git a/go.sum b/go.sum index dba81f686..60e6d6eb8 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/EngFlow/credential-helper-go v0.0.0-20230928231836-1ae22fe3da4b h1:mf0b15Wn/T7RzMXjyDW+TKyO80CR1BnM9/B9u05TJ5Q= +github.com/EngFlow/credential-helper-go v0.0.0-20230928231836-1ae22fe3da4b/go.mod h1:feR+azx/GSHyRcazMg8aGZFtiBkpv3jFdT81w+b+PBM= github.com/bazelbuild/remote-apis v0.0.0-20230411132548-35aee1c4a425 h1:Lj8uXWW95oXyYguUSdQDvzywQb4f0jbJWsoLPQWAKTY= github.com/bazelbuild/remote-apis v0.0.0-20230411132548-35aee1c4a425/go.mod h1:ry8Y6CkQqCVcYsjPOlLXDX2iRVjOnjogdNwhvHmRcz8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -152,8 +154,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.58.0-dev.0.20230804151048-7aceafcc52f9 h1:q+IouZau98MiF17oKDj80j5J4KKnzmcxXsujTA9WGMk= -google.golang.org/grpc v1.58.0-dev.0.20230804151048-7aceafcc52f9/go.mod h1:eQ5TbWncHnnyuYfjb+hBJFRvLf9SSLgqMR7pVc1on3I= +google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= +google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/go/pkg/client/BUILD.bazel b/go/pkg/client/BUILD.bazel index 3f163c5d7..07d56661d 100644 --- a/go/pkg/client/BUILD.bazel +++ b/go/pkg/client/BUILD.bazel @@ -31,6 +31,8 @@ go_library( "//go/pkg/retry", "//go/pkg/uploadinfo", "@com_github_bazelbuild_remote_apis//build/bazel/remote/execution/v2:remote_execution_go_proto", + "@com_github_engflow_credential_helper_go//:go_default_library", + "@com_github_engflow_credential_helper_go//credentialhelpergrpc:go_default_library", "@com_github_golang_glog//:go_default_library", "@com_github_klauspost_compress//zstd:go_default_library", "@com_github_mostynb_zstdpool_syncpool//:go_default_library", diff --git a/go/pkg/client/client.go b/go/pkg/client/client.go index 9f5031197..a850d7662 100644 --- a/go/pkg/client/client.go +++ b/go/pkg/client/client.go @@ -14,6 +14,8 @@ import ( "sync" "time" + "github.com/EngFlow/credential-helper-go" + "github.com/EngFlow/credential-helper-go/credentialhelpergrpc" "github.com/bazelbuild/remote-apis-sdks/go/pkg/actas" "github.com/bazelbuild/remote-apis-sdks/go/pkg/balancer" "github.com/bazelbuild/remote-apis-sdks/go/pkg/casng" @@ -61,6 +63,9 @@ const ( // NoAuth refers to no authentication when connecting to the RBE service. NoAuth + // CredentialHelperAuth refers to using a Credential Helper for athentication. + CredentialHelperAuth + // ExternalTokenAuth is used to connect to the RBE service. ExternalTokenAuth @@ -510,6 +515,11 @@ type DialParams struct { // not need to authenticate with the server. NoAuth bool + // CredentialHelper specifies the Credential Helper to use for getting credentials. + // + // If this is specified, it takes precedence over all other client-wide credentials other than transport credentials (i.e., it takes precedence over `ExternalPerRPCCreds`, `UseApplicationDefault` and similar, but not over `mTLS` credentials). + CredentialHelper credentialhelper.CredentialHelper + // TransportCredsOnly is true if it's the caller's responsibility to set per-RPC credentials // on individual calls. This overrides ActAsAccount, UseApplicationDefault, and UseComputeEngine. // This is not the same as NoSecurity, as transport credentials will still be set. @@ -618,6 +628,15 @@ func Dial(ctx context.Context, endpoint string, params DialParams) (*grpc.Client return nil, authUsed, fmt.Errorf("could not create TLS config: %v", err) } opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) + } else if params.CredentialHelper != nil { + authUsed = CredentialHelperAuth + opts = append(opts, grpc.WithPerRPCCredentials(credentialhelpergrpc.NewPerRPCCredentials(params.CredentialHelper))) + // Set the ServerName and RootCAs fields, if needed. + tlsConfig, err := createTLSConfig(params) + if err != nil { + return nil, authUsed, fmt.Errorf("could not create TLS config: %w", err) + } + opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) } else if params.UseExternalAuthToken { authUsed = ExternalTokenAuth if params.ExternalPerRPCCreds == nil { diff --git a/go/pkg/flags/BUILD.bazel b/go/pkg/flags/BUILD.bazel index 0572a941a..28ae85264 100644 --- a/go/pkg/flags/BUILD.bazel +++ b/go/pkg/flags/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "//go/pkg/balancer", "//go/pkg/client", "//go/pkg/moreflag", + "@com_github_engflow_credential_helper_go//:go_default_library", "@com_github_golang_glog//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//keepalive:go_default_library", diff --git a/go/pkg/flags/flags.go b/go/pkg/flags/flags.go index d07d8a7e4..1aec34f2d 100644 --- a/go/pkg/flags/flags.go +++ b/go/pkg/flags/flags.go @@ -6,6 +6,7 @@ import ( "flag" "time" + "github.com/EngFlow/credential-helper-go" "github.com/bazelbuild/remote-apis-sdks/go/pkg/balancer" "github.com/bazelbuild/remote-apis-sdks/go/pkg/client" "github.com/bazelbuild/remote-apis-sdks/go/pkg/moreflag" @@ -37,6 +38,8 @@ var ( UseGCECredentials = flag.Bool("use_gce_credentials", false, "If true (and --use_application_default_credentials is false), use the default GCE credentials to authenticate with remote execution.") // UseRPCCredentials can be set to false to disable all per-RPC credentials. UseRPCCredentials = flag.Bool("use_rpc_credentials", true, "If false, no per-RPC credentials will be used (disables --credential_file, --use_application_default_credentials, and --use_gce_credentials.") + // CredentialHelper specifies the path to the Credential Helper to use for authentication. + CredentialHelper = flag.String("credential_helper", "", "Specifies the path to a Credential Helper to use for authentication. If set, this takes precedence over any other authentication method.") // UseExternalAuthToken specifies whether to use an externally provided auth token, given via PerRPCCreds dial option, should be used. UseExternalAuthToken = flag.Bool("use_external_auth_token", false, "If true, se an externally provided auth token, given via PerRPCCreds when the SDK is initialized.") // Service represents the host (and, if applicable, port) of the remote execution service. @@ -113,6 +116,15 @@ func NewClientFromFlags(ctx context.Context, opts ...client.Opt) (*client.Client } } + var credentialHelper credentialhelper.CredentialHelper + if *CredentialHelper != "" { + helper, err := credentialhelper.NewClient(*CredentialHelper) + if err != nil { + return nil, err + } + credentialHelper = helper + } + dialOpts := make([]grpc.DialOption, 0) if *KeepAliveTime > 0*time.Second { params := keepalive.ClientParameters{ @@ -129,6 +141,7 @@ func NewClientFromFlags(ctx context.Context, opts ...client.Opt) (*client.Client NoAuth: *ServiceNoAuth, CASService: *CASService, CredFile: *CredFile, + CredentialHelper: credentialHelper, DialOpts: dialOpts, UseApplicationDefault: *UseApplicationDefaultCreds, UseComputeEngine: *UseGCECredentials, diff --git a/go_deps.bzl b/go_deps.bzl index ec1326e7b..92958e8c9 100644 --- a/go_deps.bzl +++ b/go_deps.bzl @@ -49,6 +49,13 @@ def remote_apis_sdks_go_deps(): sum = "h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=", version = "v1.1.0", ) + go_repository( + name = "com_github_engflow_credential_helper_go", + importpath = "github.com/EngFlow/credential-helper-go", + sum = "h1:mf0b15Wn/T7RzMXjyDW+TKyO80CR1BnM9/B9u05TJ5Q=", + version = "v0.0.0-20230928231836-1ae22fe3da4b", + ) + go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", From 9f9b7de67353fb92f802bbf7cbbea2e692fdaaa8 Mon Sep 17 00:00:00 2001 From: Yannic Bonenberger Date: Thu, 28 Sep 2023 17:40:23 -0600 Subject: [PATCH 2/2] fmt --- go/pkg/client/client.go | 10 +++++----- go/pkg/flags/flags.go | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go/pkg/client/client.go b/go/pkg/client/client.go index a850d7662..c04a434a6 100644 --- a/go/pkg/client/client.go +++ b/go/pkg/client/client.go @@ -630,11 +630,11 @@ func Dial(ctx context.Context, endpoint string, params DialParams) (*grpc.Client opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) } else if params.CredentialHelper != nil { authUsed = CredentialHelperAuth - opts = append(opts, grpc.WithPerRPCCredentials(credentialhelpergrpc.NewPerRPCCredentials(params.CredentialHelper))) - // Set the ServerName and RootCAs fields, if needed. - tlsConfig, err := createTLSConfig(params) - if err != nil { - return nil, authUsed, fmt.Errorf("could not create TLS config: %w", err) + opts = append(opts, grpc.WithPerRPCCredentials(credentialhelpergrpc.NewPerRPCCredentials(params.CredentialHelper))) + // Set the ServerName and RootCAs fields, if needed. + tlsConfig, err := createTLSConfig(params) + if err != nil { + return nil, authUsed, fmt.Errorf("could not create TLS config: %w", err) } opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) } else if params.UseExternalAuthToken { diff --git a/go/pkg/flags/flags.go b/go/pkg/flags/flags.go index 1aec34f2d..7de493b4d 100644 --- a/go/pkg/flags/flags.go +++ b/go/pkg/flags/flags.go @@ -117,13 +117,13 @@ func NewClientFromFlags(ctx context.Context, opts ...client.Opt) (*client.Client } var credentialHelper credentialhelper.CredentialHelper - if *CredentialHelper != "" { - helper, err := credentialhelper.NewClient(*CredentialHelper) - if err != nil { - return nil, err - } - credentialHelper = helper - } + if *CredentialHelper != "" { + helper, err := credentialhelper.NewClient(*CredentialHelper) + if err != nil { + return nil, err + } + credentialHelper = helper + } dialOpts := make([]grpc.DialOption, 0) if *KeepAliveTime > 0*time.Second {