Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions transport/grpc/dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,3 +548,137 @@ func WithConnPool(p ConnPool) option.ClientOption {
func (o connPoolOption) Apply(s *internal.DialSettings) {
s.GRPCConnPool = o.ConnPool
}

// DirectPathStatus encapsulates the logic to determine why DirectPath
// is not being used.
type DirectPathStatus struct {
Enabled string
CustomGRPCConn string
CustomGRPCConnPool string
CustomHTTPClient string
EndpointFetchError string
XdsNotEnabled string
OptionDisabled string
UnsupportedEndpoint string
EnvDisabled string
NotOnGCE string
NoAuth string
APIKey string
MissingTokenSource string
TokenFetchError string
NotComputeMetadata string
NotDefaultServiceAccount string
onGCE func() bool
}

// NewDirectPathStatus creates a new DirectPathStatus with descriptive reason strings.
func NewDirectPathStatus() *DirectPathStatus {
return &DirectPathStatus{
Enabled: "enabled",
CustomGRPCConn: "custom_grpc_conn",
CustomGRPCConnPool: "custom_grpc_conn_pool",
CustomHTTPClient: "custom_http_client",
EndpointFetchError: "endpoint_fetch_error",
XdsNotEnabled: "xds_not_enabled",
OptionDisabled: "option_disabled",
UnsupportedEndpoint: "unsupported_endpoint",
EnvDisabled: "env_disabled",
NotOnGCE: "not_on_gce",
NoAuth: "no_auth",
APIKey: "api_key",
MissingTokenSource: "missing_token_source",
TokenFetchError: "token_fetch_error",
NotComputeMetadata: "not_compute_metadata",
NotDefaultServiceAccount: "not_default_service_account",
onGCE: metadata.OnGCE,
}
}

// CheckWithReason evaluates the current environment and options to return the
// highest priority reason for fallback.
func (d *DirectPathStatus) CheckWithReason(ctx context.Context, opts ...option.ClientOption) string {
o, err := processAndValidateOpts(opts)
if err != nil {
return d.EndpointFetchError
}
// Check for custom resources that preclude DirectPath.
if o.GRPCConn != nil {
return d.CustomGRPCConn
}
if o.GRPCConnPool != nil {
return d.CustomGRPCConnPool
}
if o.HTTPClient != nil {
return d.CustomHTTPClient
}

_, endpoint, err := internal.GetGRPCTransportConfigAndEndpoint(o)
if err != nil {
return d.EndpointFetchError
}
// DirectPath not attempted via xDS.
if !isDirectPathXdsUsed(o) {
return d.XdsNotEnabled
}
// DirectPath disabled by option.
if !o.EnableDirectPath {
return d.OptionDisabled
}
// DirectPath disabled by unsupported endpoint scheme (e.g., https://).
if !checkDirectPathEndPoint(endpoint) {
return d.UnsupportedEndpoint
}
// DirectPath disabled by environment variable.
if strings.EqualFold(os.Getenv(disableDirectPath), "true") {
return d.EnvDisabled
}

if !d.onGCE() {
return d.NotOnGCE
}
// Specific credential compatibility check.
if reason := d.authReason(ctx, o); reason != "" {
return reason
}
return d.Enabled
}

func (d *DirectPathStatus) authReason(ctx context.Context, o *internal.DialSettings) string {
if o.NoAuth {
return d.NoAuth
}
if o.APIKey != "" {
return d.APIKey
}

creds, err := internal.Creds(ctx, o)
if err != nil {
return d.TokenFetchError
}
if creds.TokenSource == nil {
return d.MissingTokenSource
}

tok, err := creds.TokenSource.Token()
if err != nil {
return d.TokenFetchError
}
if tok == nil {
return d.TokenFetchError
}

// AllowNonDefaultServiceAccount bypasses the metadata source and default account checks.
if o.AllowNonDefaultServiceAccount {
return ""
}

// Verify the token source is the GCE Metadata Server.
if source, _ := tok.Extra("oauth2.google.tokenSource").(string); source != "compute-metadata" {
return d.NotComputeMetadata
}
// Verify the default service account is used.
if acct, _ := tok.Extra("oauth2.google.serviceAccount").(string); acct != "default" {
return d.NotDefaultServiceAccount
}
return ""
}
Loading