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