| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package resultstore |
| |
| import ( |
| "context" |
| "crypto/x509" |
| "fmt" |
| |
| "go.chromium.org/luci/auth" |
| api "google.golang.org/genproto/googleapis/devtools/resultstore/v2" |
| "google.golang.org/grpc" |
| "google.golang.org/grpc/credentials" |
| "google.golang.org/grpc/credentials/oauth" |
| ) |
| |
| // Connect returns a new Service connected to the ResultStore backend at the given host. |
| func Connect(ctx context.Context, host string) (Service, error) { |
| conn, err := connectToGRPCHost(ctx, host) |
| if err != nil { |
| return nil, err |
| } |
| return NewService(api.NewResultStoreUploadClient(conn)), nil |
| } |
| |
| // AuthMode specifies how to authenticate with ResultStore. |
| type AuthMode string |
| |
| // AuthMode constants. |
| const ( |
| // LUCIAuth uses LUCI auth with SilentLogin. See the docs at |
| // go.chromium.org/luci/common/auth#SilentLogin for more details. This mode should |
| // always be used in production. |
| LUCIAuth AuthMode = "luci" |
| |
| // GAEDefaultAuth uses the Google application default credentials, which are read from |
| // the environment variable GOOGLE_APPLICATION_CREDENTIALS. This is useful for local |
| // debugging and testing. |
| GAEDefaultAuth AuthMode = "gae_default" |
| ) |
| |
| const ( |
| // Google Cloud API scope required to use ResultStore Upload API. |
| scope = "https://www.googleapis.com/auth/cloud-platform" |
| ) |
| |
| func connectToGRPCHost(ctx context.Context, host string) (*grpc.ClientConn, error) { |
| // TODO(IN-699): AuthMode and Options should be initialized by command-line flags. |
| var authOpts auth.Options |
| perRPC, err := perRPCCredentials(ctx, GAEDefaultAuth, authOpts) |
| if err != nil { |
| return nil, err |
| } |
| |
| pool, err := x509.SystemCertPool() |
| if err != nil { |
| return nil, fmt.Errorf("failed to create cert pool: %v", err) |
| } |
| transportCreds := credentials.NewClientTLSFromCert(pool, "") |
| return grpc.Dial(host, |
| grpc.WithTransportCredentials(transportCreds), |
| grpc.WithPerRPCCredentials(perRPC), |
| ) |
| } |
| |
| func perRPCCredentials(ctx context.Context, authMode AuthMode, authOpts auth.Options) (credentials.PerRPCCredentials, error) { |
| switch authMode { |
| case LUCIAuth: |
| authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, authOpts) |
| return authenticator.PerRPCCredentials() |
| case GAEDefaultAuth: |
| return oauth.NewApplicationDefault(ctx, scope) |
| default: |
| return nil, fmt.Errorf("invalid authenticatation mode: %v", authMode) |
| } |
| } |