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)
81
82type credsMode uint8
83
84const (
85	credsNone credsMode = iota
86	credsTLS
87	credsALTS
88	credsGoogleDefaultCreds
89	credsComputeEngineCreds
90)
91
92func main() {
93	flag.Parse()
94	var useGDC bool // use google default creds
95	var useCEC bool // use compute engine creds
96	if *customCredentialsType != "" {
97		switch *customCredentialsType {
98		case googleDefaultCredsName:
99			useGDC = true
100		case computeEngineCredsName:
101			useCEC = true
102		default:
103			grpclog.Fatalf("If set, custom_credentials_type can only be set to one of %v or %v",
104				googleDefaultCredsName, computeEngineCredsName)
105		}
106	}
107	if (*useTLS && *useALTS) || (*useTLS && useGDC) || (*useALTS && useGDC) || (*useTLS && useCEC) || (*useALTS && useCEC) {
108		grpclog.Fatalf("only one of TLS, ALTS, google default creds, or compute engine creds can be used")
109	}
110
111	var credsChosen credsMode
112	switch {
113	case *useTLS:
114		credsChosen = credsTLS
115	case *useALTS:
116		credsChosen = credsALTS
117	case useGDC:
118		credsChosen = credsGoogleDefaultCreds
119	case useCEC:
120		credsChosen = credsComputeEngineCreds
121	}
122
123	resolver.SetDefaultScheme("dns")
124	serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
125	var opts []grpc.DialOption
126	switch credsChosen {
127	case credsTLS:
128		var sn string
129		if *tlsServerName != "" {
130			sn = *tlsServerName
131		}
132		var creds credentials.TransportCredentials
133		if *testCA {
134			var err error
135			if *caFile == "" {
136				*caFile = testdata.Path("ca.pem")
137			}
138			creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
139			if err != nil {
140				grpclog.Fatalf("Failed to create TLS credentials %v", err)
141			}
142		} else {
143			creds = credentials.NewClientTLSFromCert(nil, sn)
144		}
145		opts = append(opts, grpc.WithTransportCredentials(creds))
146	case credsALTS:
147		altsOpts := alts.DefaultClientOptions()
148		if *altsHSAddr != "" {
149			altsOpts.HandshakerServiceAddress = *altsHSAddr
150		}
151		altsTC := alts.NewClientCreds(altsOpts)
152		opts = append(opts, grpc.WithTransportCredentials(altsTC))
153	case credsGoogleDefaultCreds:
154		opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials()))
155	case credsComputeEngineCreds:
156		opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials()))
157	case credsNone:
158		opts = append(opts, grpc.WithInsecure())
159	default:
160		grpclog.Fatal("Invalid creds")
161	}
162	if credsChosen == credsTLS {
163		if *testCase == "compute_engine_creds" {
164			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewComputeEngine()))
165		} else if *testCase == "service_account_creds" {
166			jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope)
167			if err != nil {
168				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
169			}
170			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
171		} else if *testCase == "jwt_token_creds" {
172			jwtCreds, err := oauth.NewJWTAccessFromFile(*serviceAccountKeyFile)
173			if err != nil {
174				grpclog.Fatalf("Failed to create JWT credentials: %v", err)
175			}
176			opts = append(opts, grpc.WithPerRPCCredentials(jwtCreds))
177		} else if *testCase == "oauth2_auth_token" {
178			opts = append(opts, grpc.WithPerRPCCredentials(oauth.NewOauthAccess(interop.GetToken(*serviceAccountKeyFile, *oauthScope))))
179		}
180	}
181	opts = append(opts, grpc.WithBlock())
182	conn, err := grpc.Dial(serverAddr, opts...)
183	if err != nil {
184		grpclog.Fatalf("Fail to dial: %v", err)
185	}
186	defer conn.Close()
187	tc := testpb.NewTestServiceClient(conn)
188	switch *testCase {
189	case "empty_unary":
190		interop.DoEmptyUnaryCall(tc)
191		grpclog.Infoln("EmptyUnaryCall done")
192	case "large_unary":
193		interop.DoLargeUnaryCall(tc)
194		grpclog.Infoln("LargeUnaryCall done")
195	case "client_streaming":
196		interop.DoClientStreaming(tc)
197		grpclog.Infoln("ClientStreaming done")
198	case "server_streaming":
199		interop.DoServerStreaming(tc)
200		grpclog.Infoln("ServerStreaming done")
201	case "ping_pong":
202		interop.DoPingPong(tc)
203		grpclog.Infoln("Pingpong done")
204	case "empty_stream":
205		interop.DoEmptyStream(tc)
206		grpclog.Infoln("Emptystream done")
207	case "timeout_on_sleeping_server":
208		interop.DoTimeoutOnSleepingServer(tc)
209		grpclog.Infoln("TimeoutOnSleepingServer done")
210	case "compute_engine_creds":
211		if credsChosen != credsTLS {
212			grpclog.Fatalf("TLS credentials need to be set for compute_engine_creds test case.")
213		}
214		interop.DoComputeEngineCreds(tc, *defaultServiceAccount, *oauthScope)
215		grpclog.Infoln("ComputeEngineCreds done")
216	case "service_account_creds":
217		if credsChosen != credsTLS {
218			grpclog.Fatalf("TLS credentials need to be set for service_account_creds test case.")
219		}
220		interop.DoServiceAccountCreds(tc, *serviceAccountKeyFile, *oauthScope)
221		grpclog.Infoln("ServiceAccountCreds done")
222	case "jwt_token_creds":
223		if credsChosen != credsTLS {
224			grpclog.Fatalf("TLS credentials need to be set for jwt_token_creds test case.")
225		}
226		interop.DoJWTTokenCreds(tc, *serviceAccountKeyFile)
227		grpclog.Infoln("JWTtokenCreds done")
228	case "per_rpc_creds":
229		if credsChosen != credsTLS {
230			grpclog.Fatalf("TLS credentials need to be set for per_rpc_creds test case.")
231		}
232		interop.DoPerRPCCreds(tc, *serviceAccountKeyFile, *oauthScope)
233		grpclog.Infoln("PerRPCCreds done")
234	case "oauth2_auth_token":
235		if credsChosen != credsTLS {
236			grpclog.Fatalf("TLS credentials need to be set for oauth2_auth_token test case.")
237		}
238		interop.DoOauth2TokenCreds(tc, *serviceAccountKeyFile, *oauthScope)
239		grpclog.Infoln("Oauth2TokenCreds done")
240	case "google_default_credentials":
241		if credsChosen != credsGoogleDefaultCreds {
242			grpclog.Fatalf("GoogleDefaultCredentials need to be set for google_default_credentials test case.")
243		}
244		interop.DoGoogleDefaultCredentials(tc, *defaultServiceAccount)
245		grpclog.Infoln("GoogleDefaultCredentials done")
246	case "compute_engine_channel_credentials":
247		if credsChosen != credsComputeEngineCreds {
248			grpclog.Fatalf("ComputeEngineCreds need to be set for compute_engine_channel_credentials test case.")
249		}
250		interop.DoComputeEngineChannelCredentials(tc, *defaultServiceAccount)
251		grpclog.Infoln("ComputeEngineChannelCredentials done")
252	case "cancel_after_begin":
253		interop.DoCancelAfterBegin(tc)
254		grpclog.Infoln("CancelAfterBegin done")
255	case "cancel_after_first_response":
256		interop.DoCancelAfterFirstResponse(tc)
257		grpclog.Infoln("CancelAfterFirstResponse done")
258	case "status_code_and_message":
259		interop.DoStatusCodeAndMessage(tc)
260		grpclog.Infoln("StatusCodeAndMessage done")
261	case "special_status_message":
262		interop.DoSpecialStatusMessage(tc)
263		grpclog.Infoln("SpecialStatusMessage done")
264	case "custom_metadata":
265		interop.DoCustomMetadata(tc)
266		grpclog.Infoln("CustomMetadata done")
267	case "unimplemented_method":
268		interop.DoUnimplementedMethod(conn)
269		grpclog.Infoln("UnimplementedMethod done")
270	case "unimplemented_service":
271		interop.DoUnimplementedService(testpb.NewUnimplementedServiceClient(conn))
272		grpclog.Infoln("UnimplementedService done")
273	default:
274		grpclog.Fatal("Unsupported test case: ", *testCase)
275	}
276}
277