Skip to content

Commit

Permalink
Default to using FindDeafultCredentials for credentials (#527)
Browse files Browse the repository at this point in the history
* default to using FindDeafultCredentials for credentials, which allows using with workload identity federation
  • Loading branch information
dashpole committed Nov 4, 2022
1 parent 8c6aae1 commit e955c20
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 83 deletions.
81 changes: 81 additions & 0 deletions exporter/collector/config.go
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
}
7 changes: 1 addition & 6 deletions exporter/collector/logs.go
Expand Up @@ -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
}
Expand Down
3 changes: 1 addition & 2 deletions exporter/collector/metrics.go
Expand Up @@ -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
}
Expand Down
76 changes: 1 addition & 75 deletions exporter/collector/traces.go
Expand Up @@ -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"
)
Expand All @@ -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),
Expand All @@ -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
}
Expand Down

0 comments on commit e955c20

Please sign in to comment.