credentials: add compute engine channel creds (#2708)

This commit is contained in:
apolcyn
2019-03-25 14:47:12 -07:00
committed by Menghan Li
parent ef9bac2604
commit 6d8271a06c
3 changed files with 81 additions and 19 deletions

View File

@ -38,7 +38,17 @@ const tokenRequestTimeout = 30 * time.Second
//
// This API is experimental.
func NewDefaultCredentials() credentials.Bundle {
c := &creds{}
c := &creds{
newPerRPCCreds: func() credentials.PerRPCCredentials {
ctx, cancel := context.WithTimeout(context.Background(), tokenRequestTimeout)
defer cancel()
perRPCCreds, err := oauth.NewApplicationDefault(ctx)
if err != nil {
grpclog.Warningf("google default creds: failed to create application oauth: %v", err)
}
return perRPCCreds
},
}
bundle, err := c.NewWithMode(internal.CredsBundleModeFallback)
if err != nil {
grpclog.Warningf("google default creds: failed to create new creds: %v", err)
@ -46,6 +56,24 @@ func NewDefaultCredentials() credentials.Bundle {
return bundle
}
// NewComputeEngineCredentials returns a credentials bundle that is configured to work
// with google services. This API must only be used when running on GCE. Authentication configured
// by this API represents the GCE VM's default service account.
//
// This API is experimental.
func NewComputeEngineCredentials() credentials.Bundle {
c := &creds{
newPerRPCCreds: func() credentials.PerRPCCredentials {
return oauth.NewComputeEngine()
},
}
bundle, err := c.NewWithMode(internal.CredsBundleModeFallback)
if err != nil {
grpclog.Warningf("compute engine creds: failed to create new creds: %v", err)
}
return bundle
}
// creds implements credentials.Bundle.
type creds struct {
// Supported modes are defined in internal/internal.go.
@ -54,6 +82,8 @@ type creds struct {
transportCreds credentials.TransportCredentials
// The per RPC credentials associated with this bundle.
perRPCCreds credentials.PerRPCCredentials
// Creates new per RPC credentials
newPerRPCCreds func() credentials.PerRPCCredentials
}
func (c *creds) TransportCredentials() credentials.TransportCredentials {
@ -70,7 +100,10 @@ func (c *creds) PerRPCCredentials() credentials.PerRPCCredentials {
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
// existing Bundle may cause races.
func (c *creds) NewWithMode(mode string) (credentials.Bundle, error) {
newCreds := &creds{mode: mode}
newCreds := &creds{
mode: mode,
newPerRPCCreds: c.newPerRPCCreds,
}
// Create transport credentials.
switch mode {
@ -81,20 +114,11 @@ func (c *creds) NewWithMode(mode string) (credentials.Bundle, error) {
// to create new ALTS client creds here.
newCreds.transportCreds = alts.NewClientCreds(alts.DefaultClientOptions())
default:
return nil, fmt.Errorf("google default creds: unsupported mode: %v", mode)
return nil, fmt.Errorf("unsupported mode: %v", mode)
}
if mode == internal.CredsBundleModeFallback || mode == internal.CredsBundleModeBackendFromBalancer {
// Create per RPC credentials.
// For the time being, we required per RPC credentials for both TLS and
// ALTS. In the future, this will only be required for TLS.
ctx, cancel := context.WithTimeout(context.Background(), tokenRequestTimeout)
defer cancel()
var err error
newCreds.perRPCCreds, err = oauth.NewApplicationDefault(ctx)
if err != nil {
grpclog.Warningf("google default creds: failed to create application oauth: %v", err)
}
newCreds.perRPCCreds = newCreds.newPerRPCCreds()
}
return newCreds, nil

View File

@ -38,6 +38,7 @@ import (
const (
googleDefaultCredsName = "google_default_credentials"
computeEngineCredsName = "compute_engine_channel_creds"
)
var (
@ -68,6 +69,7 @@ var (
per_rpc_creds: large_unary with per rpc token;
oauth2_auth_token: large_unary with oauth2 token auth;
google_default_credentials: large_unary with google default credentials
compute_engine_channel_credentials: large_unary with compute engine creds
cancel_after_begin: cancellation after metadata has been sent but before payloads are sent;
cancel_after_first_response: cancellation after receiving 1st message from the server;
status_code_and_message: status code propagated back to client;
@ -84,19 +86,26 @@ const (
credsTLS
credsALTS
credsGoogleDefaultCreds
credsComputeEngineCreds
)
func main() {
flag.Parse()
var useGDC bool // use google default creds
var useCEC bool // use compute engine creds
if *customCredentialsType != "" {
if *customCredentialsType != googleDefaultCredsName {
grpclog.Fatalf("custom_credentials_type can only be set to %v or not set", googleDefaultCredsName)
switch *customCredentialsType {
case googleDefaultCredsName:
useGDC = true
case computeEngineCredsName:
useCEC = true
default:
grpclog.Fatalf("If set, custom_credentials_type can only be set to one of %v or %v",
googleDefaultCredsName, computeEngineCredsName)
}
useGDC = true
}
if (*useTLS && *useALTS) || (*useTLS && useGDC) || (*useALTS && useGDC) {
grpclog.Fatalf("only one of TLS, ALTS and google default creds can be used")
if (*useTLS && *useALTS) || (*useTLS && useGDC) || (*useALTS && useGDC) || (*useTLS && useCEC) || (*useALTS && useCEC) {
grpclog.Fatalf("only one of TLS, ALTS, google default creds, or compute engine creds can be used")
}
var credsChosen credsMode
@ -107,6 +116,8 @@ func main() {
credsChosen = credsALTS
case useGDC:
credsChosen = credsGoogleDefaultCreds
case useCEC:
credsChosen = credsComputeEngineCreds
}
resolver.SetDefaultScheme("dns")
@ -141,6 +152,8 @@ func main() {
opts = append(opts, grpc.WithTransportCredentials(altsTC))
case credsGoogleDefaultCreds:
opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials()))
case credsComputeEngineCreds:
opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()))
case credsNone:
opts = append(opts, grpc.WithInsecure())
default:
@ -230,6 +243,12 @@ func main() {
}
interop.DoGoogleDefaultCredentials(tc, *defaultServiceAccount)
grpclog.Infoln("GoogleDefaultCredentials done")
case "compute_engine_channel_credentials":
if credsChosen != credsComputeEngineCreds {
grpclog.Fatalf("ComputeEngineCreds need to be set for compute_engine_channel_credentials test case.")
}
interop.DoComputeEngineChannelCredentials(tc, *defaultServiceAccount)
grpclog.Infoln("ComputeEngineChannelCredentials done")
case "cancel_after_begin":
interop.DoCancelAfterBegin(tc)
grpclog.Infoln("CancelAfterBegin done")

View File

@ -393,7 +393,7 @@ func DoPerRPCCreds(tc testpb.TestServiceClient, serviceAccountKeyFile, oauthScop
}
}
// DoGoogleDefaultCredentials performs a unary RPC with google default credentials
// DoGoogleDefaultCredentials performs an unary RPC with google default credentials
func DoGoogleDefaultCredentials(tc testpb.TestServiceClient, defaultServiceAccount string) {
pl := ClientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize)
req := &testpb.SimpleRequest{
@ -412,6 +412,25 @@ func DoGoogleDefaultCredentials(tc testpb.TestServiceClient, defaultServiceAccou
}
}
// DoComputeEngineChannelCredentials performs an unary RPC with compute engine channel credentials
func DoComputeEngineChannelCredentials(tc testpb.TestServiceClient, defaultServiceAccount string) {
pl := ClientNewPayload(testpb.PayloadType_COMPRESSABLE, largeReqSize)
req := &testpb.SimpleRequest{
ResponseType: testpb.PayloadType_COMPRESSABLE,
ResponseSize: int32(largeRespSize),
Payload: pl,
FillUsername: true,
FillOauthScope: true,
}
reply, err := tc.UnaryCall(context.Background(), req)
if err != nil {
grpclog.Fatal("/TestService/UnaryCall RPC failed: ", err)
}
if reply.GetUsername() != defaultServiceAccount {
grpclog.Fatalf("Got user name %q; wanted %q. ", reply.GetUsername(), defaultServiceAccount)
}
}
var testMetadata = metadata.MD{
"key1": []string{"value1"},
"key2": []string{"value2"},