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