Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

credentials: support google default creds #2315

Merged
merged 18 commits into from
Sep 25, 2018

Conversation

menghanl
Copy link
Contributor

Google default creds is a combo of ALTS, TLS and OAuth2. The right set of creds will be picked to use based on environment.

This PR contains:

  • A new creds.Bundle type
    • changes to use it in ClientConn and transport
    • dial option to set the bundle for a ClientConn
    • balancer options and NewSubConnOption to set it for SubConn
  • Google default creds implementation by @cesarghali
  • grpclb changes to use different creds mode for different servers
  • interop client changes for google default creds testing

if !vmOnGCP {
return nil, errors.New("ALTS, as part of google default credentials, is only supported on GCP")
}
newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a comment that Google Default Credentials are only use by clients, so we only create a new ALTS client creds, or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

newCreds.transportCreds = credentials.NewTLS(nil)
case internal.CredsBundleModeALTS, internal.CredsBundleModeGRPCLB:
if !vmOnGCP {
return nil, errors.New("ALTS, as part of google default credentials, is only supported on GCP")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to prefix the error message with something like google default creds:, similar to the other error before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
default:
return nil, fmt.Errorf("unsupported mode: %v", mode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same RE the prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

dialoptions.go Outdated
// WithTransportCredentials.
//
// This API is experimental.
func WithCreds(b credentials.Bundle) DialOption {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about changing the name to something like WithCredentialsBundle, or something more expressive. WithCreds might be a bit ambiguous about the creds type, e.g., the above API is for transport credentials.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -166,7 +166,19 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
isSecure bool
authInfo credentials.AuthInfo
)
if creds := opts.TransportCredentials; creds != nil {
var creds credentials.TransportCredentials
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call this transportCreds?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

@menghanl menghanl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. PTAL.

newCreds.transportCreds = credentials.NewTLS(nil)
case internal.CredsBundleModeALTS, internal.CredsBundleModeGRPCLB:
if !vmOnGCP {
return nil, errors.New("ALTS, as part of google default credentials, is only supported on GCP")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if !vmOnGCP {
return nil, errors.New("ALTS, as part of google default credentials, is only supported on GCP")
}
newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
default:
return nil, fmt.Errorf("unsupported mode: %v", mode)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

dialoptions.go Outdated
// WithTransportCredentials.
//
// This API is experimental.
func WithCreds(b credentials.Bundle) DialOption {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -166,7 +166,19 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts Conne
isSecure bool
authInfo credentials.AuthInfo
)
if creds := opts.TransportCredentials; creds != nil {
var creds credentials.TransportCredentials
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@cesarghali cesarghali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the fixes.

@@ -39,6 +40,7 @@ var (
caFile = flag.String("ca_file", "", "The file containning the CA root cert file")
useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true")
useALTS = flag.Bool("use_alts", false, "Connection uses ALTS if true (this option can only be used on GCP)")
useGoogleDefaultCreds = flag.Bool("use_google_default_creds", false, "Uses google default creds if true")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is ugly here, but in order to be consistent with Java and C++, mind switching the command arg from "--use_google_default_credentials" to "--custom_credentials_type", and then when use google default credentials when "google_default_credentials" is passed in as the value?

Doing so would just make it consistent with the other languages (See e.g.https://github.com/grpc/grpc/blob/master/tools/run_tests/run_interop_tests.py#L782)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This indeed makes me feel sad. But done anyway.

@menghanl menghanl force-pushed the google_default_creds branch 2 times, most recently from 567d9bf to 99430b6 Compare September 21, 2018 18:19
perRPCCreds = append(perRPCCreds, t)
}
}
if transportCreds == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: to be consistent with how perRPCCreds is set, initialize transportCreds := opt.TransportCredentials at the top and then set:

if t := b.TransportCredentials(); t != nil {
        transportCreds = t
}

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

case internal.CredsBundleModeTLS:
newCreds.transportCreds = credentials.NewTLS(nil)
case internal.CredsBundleModeALTS, internal.CredsBundleModeGRPCLB:
if !vmOnGCP {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure it's necessary to make the also check that we're running on GCP within this credentials bundle; doesn't ALTS credentials itself already make this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cesarghali what do you think about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cesarghali I removed this checking so we don't need to export IsRunningOnGCP. Let me know if you think this is not OK.

I also modified the error string that will be returned by ALTS if not running on GCP.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ALTS does the check. However, would oauth.NewApplicationDefault work properly if we're not on GCP?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oauth.NewApplicationDefault calls FindDefaultCredentials, and seems it handles non-GCP cases: https://github.com/golang/oauth2/blob/d2e6202438beef2727060aa7cabdd924d92ebfd9/google/go19.go#L47:6

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, thanks for checking.

ctx, cancel := context.WithTimeout(context.Background(), tokenRequestTimeout)
defer cancel()
var err error
newCreds.perRPCCreds, err = oauth.NewApplicationDefault(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connection to the grpclb server doesn't actually need OAuth credentials.

Should probably be consistent with Java and C++ on this.
cc @jiangtaoli2016 @yihuazhang can we confirm that Java and C++ don't send OAuth creds to the balancer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure c++ strips call credentials (Oauth creds) when communicating with the balancer.

cc @ejona86 @zhangkun83 Could you pls confirm Java case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipped for GRPCLB.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java does not currently have a way to set CallCredentials in ManagedChannelBuilder. So there's naturally no way it could be used when communicating with the balancer.

// existing Bundle may cause races.
//
// SwitchMode returns nil if the requested mode is not supported.
SwitchMode(mode string) (Bundle, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comment: going by the name and documentation for this SwitchMode API, it seems that there's an implementations have an implied state change when it's called. But statefulness doesn't actually seem to be needed for the the GoogleDefaultCredentials implementation. Is this API just geared to handle the general case where a state change on the creds bunde can occur? If not, is there some way to make this stateless?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is stateless -- or at least, there is state, but it is immutable.

Maybe a different name would be better. BundleWithMode or BundleFor or NewBundle or NewWithMode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to NewWithMode.

clientconn.go Outdated
@@ -80,6 +80,9 @@ var (
// being set for ClientConn. Users should either set one or explicitly
// call WithInsecure DialOption to disable security.
errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
// errTransportCredsAndBundle indicates that creds bundle is used together
// with other individual Transport Credentials.
errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle shouldn't be used together with individual TransportCredentials")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nits: "shouldn't" -> "may not" (more precise/formal) and s/together// (it's cleaner).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// running on GCP.
func isRunningOnGCP() bool {
func IsRunningOnGCP() bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be moved to internal/?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Un-exported. The GCP checking in google default creds is removed.

// existing Bundle may cause races.
//
// SwitchMode returns nil if the requested mode is not supported.
SwitchMode(mode string) (Bundle, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is stateless -- or at least, there is state, but it is immutable.

Maybe a different name would be better. BundleWithMode or BundleFor or NewBundle or NewWithMode?

//
// This API is experimental.
func NewDefaultCredentials() credentials.Bundle {
return new()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not move the contents of new here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

var vmOnGCP bool

func init() {
vmOnGCP = alts.IsRunningOnGCP()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, this should be fine instead: var vmOnGCP = alts.IsRunningOnGCP() (no init function)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

}

func (c *creds) TransportCredentials() credentials.TransportCredentials {
if c == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this defensive programming is necessary. I don't believe it is possible to get a nil *creds from this package. (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

if err != nil {
grpclog.Warningf("lbBalancer: client connection creds SwitchMode failed: %v", err)
}
lb.grpclbBackendCreds, err = opt.CredsBundle.SwitchMode(internal.CredsBundleModeALTS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't expect GRPCLB to need to be aware of ALTS at all. Can this be named something else, like CredsBundleModeGRPCLBBackend?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to CredsBundleModeBackendFromBalancer...

// CredsBundleModeGRPCLB switches GoogleDefaultCreds to grpclb CredsBundleMode.
CredsBundleModeGRPCLB = "grpclb"
// CredsBundleModeTLS switches GoogleDefaultCreds to TLS CredsBundleMode.
CredsBundleModeTLS = "tls"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this could be moved inside credentials/google.go, since it isn't referenced elsewhere?

In general, I want to keep grpc and grpclb talking only in terms of concepts and not specific technologies (i.e. "balancer" or "backend" not "tls" or "alts"). (This is related to my other comment about CredsBundleModeALTS.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those consts are kept in internal but renamed to non alts/tls specific names.

dialoptions.go Outdated
@@ -286,7 +286,8 @@ func WithInsecure() DialOption {
}

// WithTransportCredentials returns a DialOption which configures a connection
// level security credentials (e.g., TLS/SSL).
// level security credentials (e.g., TLS/SSL). This should not be used together
// with WithCreds.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WithCreds->WithCredentialsBundle

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


package test

// TODO: move all creds releated tests to this file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please file an issue and reference it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

 - rename mode consts
 - rename SwitchMode to NewWithMode
 - comments and minor changes
@menghanl menghanl merged commit 4dedfdc into grpc:master Sep 25, 2018
@menghanl menghanl deleted the google_default_creds branch September 25, 2018 21:00
@dfawley dfawley added the Type: Feature New features or improvements in behavior label Sep 27, 2018
@dfawley dfawley added this to the 1.16 Release milestone Sep 27, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Mar 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: Feature New features or improvements in behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants