1/*
2 *
3 * Copyright 2014 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19package main
20
21import (
22	"flag"
23	"net"
24	"strconv"
25
26	"google.golang.org/grpc"
27	_ "google.golang.org/grpc/balancer/grpclb"
28	"google.golang.org/grpc/credentials"
29	"google.golang.org/grpc/credentials/alts"
30	"google.golang.org/grpc/credentials/google"
31	"google.golang.org/grpc/credentials/oauth"
32	"google.golang.org/grpc/grpclog"
33	"google.golang.org/grpc/interop"
34	testpb "google.golang.org/grpc/interop/grpc_testing"
35	"google.golang.org/grpc/resolver"
36	"google.golang.org/grpc/testdata"
37)
38
39const (
40	googleDefaultCredsName = "google_default_credentials"
41	computeEngineCredsName = "compute_engine_channel_creds"
42)
43
44var (
45	caFile                = flag.String("ca_file", "", "The file containning the CA root cert file")
46	useTLS                = flag.Bool("use_tls", false, "Connection uses TLS if true")
47	useALTS               = flag.Bool("use_alts", false, "Connection uses ALTS if true (this option can only be used on GCP)")
48	customCredentialsType = flag.String("custom_credentials_type", "", "Custom creds to use, excluding TLS or ALTS")
49	altsHSAddr            = flag.String("alts_handshaker_service_address", "", "ALTS handshaker gRPC service address")
50	testCA                = flag.Bool("use_test_ca", false, "Whether to replace platform root CAs with test CA as the CA root")
51	serviceAccountKeyFile = flag.String("service_account_key_file", "", "Path to service account json key file")
52	oauthScope            = flag.String("oauth_scope", "", "The scope for OAuth2 tokens")
53	defaultServiceAccount = flag.String("default_service_account", "", "Email of GCE default service account")
54	serverHost            = flag.String("server_host", "localhost", "The server host name")
55	serverPort            = flag.Int("server_port", 10000, "The server port number")
56	tlsServerName         = flag.String("server_host_override", "", "The server name use to verify the hostname returned by TLS handshake if it is not empty. Otherwise, --server_host is used.")
57	testCase              = flag.String("test_case", "large_unary",
58		`Configure different test cases. Valid options are:
59        empty_unary : empty (zero bytes) request and response;
60        large_unary : single request and (large) response;
61        client_streaming : request streaming with single response;
62        server_streaming : single request with response streaming;
63        ping_pong : full-duplex streaming;
64        empty_stream : full-duplex streaming with zero message;
65        timeout_on_sleeping_server: fullduplex streaming on a sleeping server;
66        compute_engine_creds: large_unary with compute engine auth;
67        service_account_creds: large_unary with service account auth;
68        jwt_token_creds: large_unary with jwt token auth;
69        per_rpc_creds: large_unary with per rpc token;
70        oauth2_auth_token: large_unary with oauth2 token auth;
71        google_default_credentials: large_unary with google default credentials
72        compute_engine_channel_credentials: large_unary with compute engine creds
73        cancel_after_begin: cancellation after metadata has been sent but before payloads are sent;
74        cancel_after_first_response: cancellation after receiving 1st message from the server;
75        status_code_and_message: status code propagated back to client;
76        special_status_message: Unicode and whitespace is correctly processed in status message;
77        custom_metadata: server will echo custom metadata;
78        unimplemented_method: client attempts to call unimplemented method;
79        unimplemented_service: client attempts to call unimplemented service;
80        pick_first_unary: all requests are sent to one server despite multiple servers are resolved.`)
81)
82
83type credsMode uint8
84
85const (
86	credsNone credsMode = iota
87	credsTLS
88	credsALTS
89	credsGoogleDefaultCreds
90	credsComputeEngineCreds
91)
92
93func main() {
94	flag.Parse()
95	var useGDC bool // use google default creds
96	var useCEC bool // use compute engine creds
97	if *customCredentialsType != "" {
98		switch *customCredentialsType {
99		case googleDefaultCredsName:
100			useGDC = true
101		case computeEngineCredsName:
102			useCEC = true
103		default:
104			grpclog.Fatalf("If set, custom_credentials_type can only be set to one of %v or %v",
105				googleDefaultCredsName, computeEngineCredsName)
106		}
107	}
108	if (*useTLS && *useALTS) || (*useTLS && useGDC) || (*useALTS && useGDC) || (*useTLS && useCEC) || (*useALTS && useCEC) {
109		grpclog.Fatalf("only one of TLS, ALTS, google default creds, or compute engine creds can be used")
110	}
111
112	var credsChosen credsMode
113	switch {
114	case *useTLS:
115		credsChosen = credsTLS
116	case *useALTS:
117		credsChosen = credsALTS
118	case useGDC:
119		credsChosen = credsGoogleDefaultCreds
120	case useCEC:
121		credsChosen = credsComputeEngineCreds
122	}
123
124	resolver.SetDefaultScheme("dns")
125	serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
126	var opts []grpc.DialOption
127	switch credsChosen {
128	case credsTLS:
129		var sn string
130		if *tlsServerName != "" {
131			sn = *tlsServerName
132		}
133		var creds credentials.TransportCredentials
134		if *testCA {
135			var err error
136			if *caFile == "" {
137				*caFile = testdata.Path("ca.pem")
138			}
139			creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
140			if err != nil {
141				grpclog.Fatalf("Failed to create TLS credentials %v", err)
142			}
143		} else {
144			creds = credentials.NewClientTLSFromCert(nil, sn)
145		}
146		opts = append(opts, grpc.WithTransportCredentials(creds))
147	case credsALTS:
148		altsOpts := alts.DefaultClientOptions()
149		if *altsHSAddr != "" {
150			altsOpts.HandshakerServiceAddress = *altsHSAddr
151		}
152		altsTC := alts.NewClientCreds(altsOpts)
153		opts = append(opts, grpc.WithTransportCredentials(altsTC))
154	case credsGoogleDefaultCreds:
155		opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials()))
156	case credsComputeEngineCreds:
157		opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()))
158	case credsNone:
159		opts = append(opts, grpc.WithInsecure())
160	default:
161		grpclog.Fatal("Invalid creds")
162	}
163	if credsChosen == credsTLS {
164		if *testCase == "compute_engine_creds" {
165			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewComputeEngine()))
166		} else if *testCase == "service_account_creds" {
167			jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope)
168			if err != nil {
169				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
170			}
171			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
172		} else if *testCase == "jwt_token_creds" {
173			jwtCreds, err := oauth.NewJWTAccessFromFile(*serviceAccountKeyFile)
174			if err != nil {
175				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
176			}
177			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
178		} else if *testCase == "oauth2_auth_token" {
179			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope))))
180		}
181	}
182	opts = append(opts, grpc.WithBlock())
183	conn, err := grpc.Dial(serverAddr, opts...)
184	if err != nil {
185		grpclog.Fatalf("Fail to dial: %v", err)
186	}
187	defer conn.Close()
188	tc := testpb.NewTestServiceClient(conn)
189	switch *testCase {
190	case "empty_unary":
191		interop.DoEmptyUnaryCall(tc)
192		grpclog.Infoln("EmptyUnaryCall done")
193	case "large_unary":
194		interop.DoLargeUnaryCall(tc)
195		grpclog.Infoln("LargeUnaryCall done")
196	case "client_streaming":
197		interop.DoClientStreaming(tc)
198		grpclog.Infoln("ClientStreaming done")
199	case "server_streaming":
200		interop.DoServerStreaming(tc)
201		grpclog.Infoln("ServerStreaming done")
202	case "ping_pong":
203		interop.DoPingPong(tc)
204		grpclog.Infoln("Pingpong done")
205	case "empty_stream":
206		interop.DoEmptyStream(tc)
207		grpclog.Infoln("Emptystream done")
208	case "timeout_on_sleeping_server":
209		interop.DoTimeoutOnSleepingServer(tc)
210		grpclog.Infoln("TimeoutOnSleepingServer done")
211	case "compute_engine_creds":
212		if credsChosen != credsTLS {
213			grpclog.Fatalf("TLS credentials need to be set for compute_engine_creds test case.")
214		}
215		interop.DoComputeEngineCreds(tc, *defaultServiceAccount, *oauthScope)
216		grpclog.Infoln("ComputeEngineCreds done")
217	case "service_account_creds":
218		if credsChosen != credsTLS {
219			grpclog.Fatalf("TLS credentials need to be set for service_account_creds test case.")
220		}
221		interop.DoServiceAccountCreds(tc, *serviceAccountKeyFile, *oauthScope)
222		grpclog.Infoln("ServiceAccountCreds done")
223	case "jwt_token_creds":
224		if credsChosen != credsTLS {
225			grpclog.Fatalf("TLS credentials need to be set for jwt_token_creds test case.")
226		}
227		interop.DoJWTTokenCreds(tc, *serviceAccountKeyFile)
228		grpclog.Infoln("JWTtokenCreds done")
229	case "per_rpc_creds":
230		if credsChosen != credsTLS {
231			grpclog.Fatalf("TLS credentials need to be set for per_rpc_creds test case.")
232		}
233		interop.DoPerRPCCreds(tc, *serviceAccountKeyFile, *oauthScope)
234		grpclog.Infoln("PerRPCCreds done")
235	case "oauth2_auth_token":
236		if credsChosen != credsTLS {
237			grpclog.Fatalf("TLS credentials need to be set for oauth2_auth_token test case.")
238		}
239		interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope)
240		grpclog.Infoln("Oauth2TokenCreds done")
241	case "google_default_credentials":
242		if credsChosen != credsGoogleDefaultCreds {
243			grpclog.Fatalf("GoogleDefaultCredentials need to be set for google_default_credentials test case.")
244		}
245		interop.DoGoogleDefaultCredentials(tc, *defaultServiceAccount)
246		grpclog.Infoln("GoogleDefaultCredentials done")
247	case "compute_engine_channel_credentials":
248		if credsChosen != credsComputeEngineCreds {
249			grpclog.Fatalf("ComputeEngineCreds need to be set for compute_engine_channel_credentials test case.")
250		}
251		interop.DoComputeEngineChannelCredentials(tc, *defaultServiceAccount)
252		grpclog.Infoln("ComputeEngineChannelCredentials done")
253	case "cancel_after_begin":
254		interop.DoCancelAfterBegin(tc)
255		grpclog.Infoln("CancelAfterBegin done")
256	case "cancel_after_first_response":
257		interop.DoCancelAfterFirstResponse(tc)
258		grpclog.Infoln("CancelAfterFirstResponse done")
259	case "status_code_and_message":
260		interop.DoStatusCodeAndMessage(tc)
261		grpclog.Infoln("StatusCodeAndMessage done")
262	case "special_status_message":
263		interop.DoSpecialStatusMessage(tc)
264		grpclog.Infoln("SpecialStatusMessage done")
265	case "custom_metadata":
266		interop.DoCustomMetadata(tc)
267		grpclog.Infoln("CustomMetadata done")
268	case "unimplemented_method":
269		interop.DoUnimplementedMethod(conn)
270		grpclog.Infoln("UnimplementedMethod done")
271	case "unimplemented_service":
272		interop.DoUnimplementedService(testpb.NewUnimplementedServiceClient(conn))
273		grpclog.Infoln("UnimplementedService done")
274	case "pick_first_unary":
275		interop.DoPickFirstUnary(tc)
276		grpclog.Infoln("PickFirstUnary done")
277	default:
278		grpclog.Fatal("Unsupported test case: ", *testCase)
279	}
280}
281