From e955c204f4f2bfdc92ff0ad52786232b975efcc2 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Fri, 4 Nov 2022 12:02:35 -0400 Subject: [PATCH] Default to using FindDeafultCredentials for credentials (#527) * default to using FindDeafultCredentials for credentials, which allows using with workload identity federation --- exporter/collector/config.go | 81 +++++++++++++++++++++++++++++++++++ exporter/collector/logs.go | 7 +-- exporter/collector/metrics.go | 3 +- exporter/collector/traces.go | 76 +------------------------------- 4 files changed, 84 insertions(+), 83 deletions(-) diff --git a/exporter/collector/config.go b/exporter/collector/config.go index be29a791f..1823be1f5 100644 --- a/exporter/collector/config.go +++ b/exporter/collector/config.go @@ -15,13 +15,21 @@ package collector import ( + "context" + "errors" "fmt" + "strings" "time" + "go.opencensus.io/plugin/ocgrpc" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pmetric" + "golang.org/x/oauth2/google" + "google.golang.org/api/impersonate" "google.golang.org/api/option" monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) const ( @@ -175,3 +183,76 @@ func ValidateConfig(cfg Config) error { } return nil } + +func setVersionInUserAgent(cfg *Config, version string) { + cfg.UserAgent = strings.ReplaceAll(cfg.UserAgent, "{{version}}", version) +} + +func generateClientOptions(ctx context.Context, clientCfg *ClientConfig, cfg *Config, scopes []string) ([]option.ClientOption, error) { + var copts []option.ClientOption + // option.WithUserAgent is used by the Trace exporter, but not the Metric exporter (see comment below) + if cfg.UserAgent != "" { + copts = append(copts, option.WithUserAgent(cfg.UserAgent)) + } + if clientCfg.Endpoint != "" { + if clientCfg.UseInsecure { + // option.WithGRPCConn option takes precedent over all other supplied options so the + // following user agent will be used by both exporters if we reach this branch + dialOpts := []grpc.DialOption{ + grpc.WithStatsHandler(&ocgrpc.ClientHandler{}), + grpc.WithTransportCredentials(insecure.NewCredentials()), + } + if cfg.UserAgent != "" { + dialOpts = append(dialOpts, grpc.WithUserAgent(cfg.UserAgent)) + } + conn, err := grpc.Dial(clientCfg.Endpoint, dialOpts...) + if err != nil { + return nil, fmt.Errorf("cannot configure grpc conn: %w", err) + } + copts = append(copts, option.WithGRPCConn(conn)) + } else { + copts = append(copts, option.WithEndpoint(clientCfg.Endpoint)) + } + } + if cfg.ImpersonateConfig.TargetPrincipal != "" { + if cfg.ProjectID == "" { + creds, err := google.FindDefaultCredentials(ctx, scopes...) + if err != nil { + return nil, fmt.Errorf("error finding default application credentials: %v", err) + } + if creds.ProjectID == "" { + return nil, errors.New("no project found with application default credentials") + } + cfg.ProjectID = creds.ProjectID + } + tokenSource, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{ + TargetPrincipal: cfg.ImpersonateConfig.TargetPrincipal, + Delegates: cfg.ImpersonateConfig.Delegates, + Subject: cfg.ImpersonateConfig.Subject, + Scopes: scopes, + }) + if err != nil { + return nil, err + } + copts = append(copts, option.WithTokenSource(tokenSource)) + } else if !clientCfg.UseInsecure { + creds, err := google.FindDefaultCredentials(ctx, scopes...) + if err != nil { + return nil, fmt.Errorf("error finding default application credentials: %v", err) + } + copts = append(copts, option.WithCredentials(creds)) + if cfg.ProjectID == "" { + if creds.ProjectID == "" { + return nil, errors.New("no project found with application default credentials") + } + cfg.ProjectID = creds.ProjectID + } + } + if clientCfg.GRPCPoolSize > 0 { + copts = append(copts, option.WithGRPCConnectionPool(clientCfg.GRPCPoolSize)) + } + if clientCfg.GetClientOptions != nil { + copts = append(copts, clientCfg.GetClientOptions()...) + } + return copts, nil +} diff --git a/exporter/collector/logs.go b/exporter/collector/logs.go index d38421e90..4564a3852 100644 --- a/exporter/collector/logs.go +++ b/exporter/collector/logs.go @@ -129,12 +129,7 @@ func NewGoogleCloudLogsExporter( cfg Config, log *zap.Logger, ) (*LogsExporter, error) { - err := setProjectFromADC(ctx, &cfg, loggingv2.DefaultAuthScopes()) - if err != nil { - return nil, err - } - - clientOpts, err := generateClientOptions(ctx, &cfg.LogConfig.ClientConfig, cfg.UserAgent, cfg.ImpersonateConfig) + clientOpts, err := generateClientOptions(ctx, &cfg.LogConfig.ClientConfig, &cfg, loggingv2.DefaultAuthScopes()) if err != nil { return nil, err } diff --git a/exporter/collector/metrics.go b/exporter/collector/metrics.go index a2a1451b4..772114860 100644 --- a/exporter/collector/metrics.go +++ b/exporter/collector/metrics.go @@ -122,9 +122,8 @@ func NewGoogleCloudMetricsExporter( view.Register(MetricViews()...) view.Register(ocgrpc.DefaultClientViews...) setVersionInUserAgent(&cfg, version) - setProjectFromADC(ctx, &cfg, monitoring.DefaultAuthScopes()) - clientOpts, err := generateClientOptions(ctx, &cfg.MetricConfig.ClientConfig, cfg.UserAgent, cfg.ImpersonateConfig) + clientOpts, err := generateClientOptions(ctx, &cfg.MetricConfig.ClientConfig, &cfg, monitoring.DefaultAuthScopes()) if err != nil { return nil, err } diff --git a/exporter/collector/traces.go b/exporter/collector/traces.go index c1d7bd789..152d2338c 100644 --- a/exporter/collector/traces.go +++ b/exporter/collector/traces.go @@ -18,23 +18,15 @@ package collector import ( "context" - "errors" "fmt" - "strings" "time" - monitoring "cloud.google.com/go/monitoring/apiv3/v2" traceapi "cloud.google.com/go/trace/apiv2" "go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/stats/view" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/otel/attribute" sdktrace "go.opentelemetry.io/otel/sdk/trace" - "golang.org/x/oauth2/google" - "google.golang.org/api/impersonate" - "google.golang.org/api/option" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" ) @@ -48,75 +40,9 @@ func (te *TraceExporter) Shutdown(ctx context.Context) error { return te.texporter.Shutdown(ctx) } -func setVersionInUserAgent(cfg *Config, version string) { - cfg.UserAgent = strings.ReplaceAll(cfg.UserAgent, "{{version}}", version) -} - -func setProjectFromADC(ctx context.Context, cfg *Config, scopes []string) error { - if cfg.ProjectID == "" { - creds, err := google.FindDefaultCredentials(ctx, scopes...) - if err != nil { - return fmt.Errorf("error finding default application credentials: %v", err) - } - if creds.ProjectID == "" { - return errors.New("no project found with application default credentials") - } - cfg.ProjectID = creds.ProjectID - } - return nil -} - -func generateClientOptions(ctx context.Context, cfg *ClientConfig, userAgent string, impersonateConfig ImpersonateConfig) ([]option.ClientOption, error) { - var copts []option.ClientOption - // option.WithUserAgent is used by the Trace exporter, but not the Metric exporter (see comment below) - if userAgent != "" { - copts = append(copts, option.WithUserAgent(userAgent)) - } - if cfg.Endpoint != "" { - if cfg.UseInsecure { - // option.WithGRPCConn option takes precedent over all other supplied options so the - // following user agent will be used by both exporters if we reach this branch - dialOpts := []grpc.DialOption{ - grpc.WithStatsHandler(&ocgrpc.ClientHandler{}), - grpc.WithTransportCredentials(insecure.NewCredentials()), - } - if userAgent != "" { - dialOpts = append(dialOpts, grpc.WithUserAgent(userAgent)) - } - conn, err := grpc.Dial(cfg.Endpoint, dialOpts...) - if err != nil { - return nil, fmt.Errorf("cannot configure grpc conn: %w", err) - } - copts = append(copts, option.WithGRPCConn(conn)) - } else { - copts = append(copts, option.WithEndpoint(cfg.Endpoint)) - } - } - if impersonateConfig.TargetPrincipal != "" { - tokenSource, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{ - TargetPrincipal: impersonateConfig.TargetPrincipal, - Delegates: impersonateConfig.Delegates, - Subject: impersonateConfig.Subject, - Scopes: monitoring.DefaultAuthScopes(), - }) - if err != nil { - return nil, err - } - copts = append(copts, option.WithTokenSource(tokenSource)) - } - if cfg.GRPCPoolSize > 0 { - copts = append(copts, option.WithGRPCConnectionPool(cfg.GRPCPoolSize)) - } - if cfg.GetClientOptions != nil { - copts = append(copts, cfg.GetClientOptions()...) - } - return copts, nil -} - func NewGoogleCloudTracesExporter(ctx context.Context, cfg Config, version string, timeout time.Duration) (*TraceExporter, error) { view.Register(ocgrpc.DefaultClientViews...) setVersionInUserAgent(&cfg, version) - setProjectFromADC(ctx, &cfg, traceapi.DefaultAuthScopes()) topts := []cloudtrace.Option{ cloudtrace.WithProjectID(cfg.ProjectID), @@ -126,7 +52,7 @@ func NewGoogleCloudTracesExporter(ctx context.Context, cfg Config, version strin topts = append(topts, cloudtrace.WithAttributeMapping(mappingFuncFromAKM(cfg.TraceConfig.AttributeMappings))) } - copts, err := generateClientOptions(ctx, &cfg.TraceConfig.ClientConfig, cfg.UserAgent, cfg.ImpersonateConfig) + copts, err := generateClientOptions(ctx, &cfg.TraceConfig.ClientConfig, &cfg, traceapi.DefaultAuthScopes()) if err != nil { return nil, err }