From 2609cdd8ec2288707d9c182429057d1ac79cfa98 Mon Sep 17 00:00:00 2001 From: Matthew Morrissette Date: Sat, 9 Mar 2019 14:29:03 -0800 Subject: [PATCH] Add TLS support for `prototool grpc` command (#364) --- CHANGELOG.md | 1 + Makefile | 11 + docs/grpc.md | 45 +++ etc/bin/grpcgen.sh | 57 ++++ internal/cmd/BUILD.bazel | 1 + internal/cmd/cmd_test.go | 311 +++++++++++++++++- internal/cmd/flags.go | 32 +- internal/cmd/templates.go | 8 +- internal/cmd/testdata/grpc/tls/cacert.crl | 16 + internal/cmd/testdata/grpc/tls/cacert.crt | 29 ++ internal/cmd/testdata/grpc/tls/cacert.key | 51 +++ internal/cmd/testdata/grpc/tls/client.crt | 25 ++ internal/cmd/testdata/grpc/tls/client.csr | 15 + internal/cmd/testdata/grpc/tls/client.key | 27 ++ .../testdata/grpc/tls/self-signed-client.crt | 20 ++ .../testdata/grpc/tls/self-signed-client.key | 28 ++ .../testdata/grpc/tls/self-signed-server.crt | 22 ++ .../testdata/grpc/tls/self-signed-server.key | 28 ++ internal/cmd/testdata/grpc/tls/server.crt | 25 ++ internal/cmd/testdata/grpc/tls/server.csr | 16 + internal/cmd/testdata/grpc/tls/server.key | 27 ++ internal/exec/exec.go | 2 +- internal/exec/runner.go | 26 +- internal/grpc/BUILD.bazel | 1 + internal/grpc/grpc.go | 12 + internal/grpc/handler.go | 29 +- 26 files changed, 848 insertions(+), 17 deletions(-) create mode 100644 etc/bin/grpcgen.sh create mode 100644 internal/cmd/testdata/grpc/tls/cacert.crl create mode 100644 internal/cmd/testdata/grpc/tls/cacert.crt create mode 100644 internal/cmd/testdata/grpc/tls/cacert.key create mode 100644 internal/cmd/testdata/grpc/tls/client.crt create mode 100644 internal/cmd/testdata/grpc/tls/client.csr create mode 100644 internal/cmd/testdata/grpc/tls/client.key create mode 100644 internal/cmd/testdata/grpc/tls/self-signed-client.crt create mode 100644 internal/cmd/testdata/grpc/tls/self-signed-client.key create mode 100644 internal/cmd/testdata/grpc/tls/self-signed-server.crt create mode 100644 internal/cmd/testdata/grpc/tls/self-signed-server.key create mode 100644 internal/cmd/testdata/grpc/tls/server.crt create mode 100644 internal/cmd/testdata/grpc/tls/server.csr create mode 100644 internal/cmd/testdata/grpc/tls/server.key diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ea20f35..097cfaf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add file locking around the `protoc` downloader to eliminate concurrency issues where multiple `prototool` invocations may be accessing the cache at the same time. +- Add TLS support to the `grpc` command. - Add `--details` flag to the `grpc` command to output headers, trailers, and statuses as well as the responses. - Unix domain sockets can now be specified for the `--address` flag of the diff --git a/Makefile b/Makefile index da3046b4..5ae46ae1 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,13 @@ $(PROTOC_GEN_GO): @cd $(PROTOC_GEN_GO_TMP); go get github.com/golang/protobuf/protoc-gen-go@$(PROTOC_GEN_GO_VERSION) @rm -rf $(PROTOC_GEN_GO_TMP) +CERTSTRAP_VERSION := v1.1.1 +CERTSTRAP := $(TMP_BIN)/certstrap +$(CERTSTRAP): + $(eval CERTSTRAP_TMP := $(shell mktemp -d)) + @cd $(CERTSTRAP_TMP); go get github.com/square/certstrap@$(CERTSTRAP_VERSION) + @rm -rf $(CERTSTRAP_TMP) + unexport GOPATH export GO111MODULE := on export GOBIN := $(abspath $(TMP_BIN)) @@ -131,6 +138,10 @@ internalgen: install $(PROTOC_GEN_GO) bazelgen: $(BAZEL) bash etc/bin/bazelgen.sh +.PHONY: grpcgen +grpcgen: $(CERTSTRAP) + bash etc/bin/grpcgen.sh + .PHONY: generate generate: license golden example internalgen bazelgen go mod tidy -v diff --git a/docs/grpc.md b/docs/grpc.md index 739c82c8..4ce16eb9 100644 --- a/docs/grpc.md +++ b/docs/grpc.md @@ -9,6 +9,8 @@ The `prototool grpc` command calls a gRPC endpoint using a JSON input. What this All these steps take on the order of milliseconds, for example the overhead for a file with four dependencies is about 30ms, so there is little overhead for CLI calls to gRPC. +## Example + There is a full example for gRPC in the [example](../example) directory. Run `make example` to make sure everything is installed and generated. Start the example server in a separate terminal by doing `go run example/cmd/excited/main.go`. @@ -68,3 +70,46 @@ $ prototool grpc example \ {"response":{"value":"o"}} {"response":{"value":"!"}} ``` + +## TLS Connections + +To enable TLS connections to the server, use the `--tls` command line flag. + +If not specified, setting any of the following flags will produce an error. + +The following flags mirror the flags of the same names from from the `curl` command line tool. + +By default host validation is enabled. To disable, pass the `--insecure` command line flag. If using this tool in any +a production setting (which is not recommended to begin with), it is HIGHLY recommended not to use the `--insecure` +flag as it allows for multiple network exploits. + +If `--insecure` is specified, setting any of the following flags will produce an error. + +If the certificate presented by the server is not generated by a system trusted CA, you must also set the `--cacert` +flag to a pem encoded file of the CA public certificate that generated the server certificate or the server public +certificate itself. The cacert file may contain multiple certificates or certificate authorities appended together +(new line separated). You must also include any intermediary certificates if required to validate the server +certificate against the given CA certificate (generally only true in commercially generated certificates, +not self signed ones). + +By default, the "Common Name" (and any "Subject Alternative Names") will be used to validate the authenticity of the +server connection based upon the `--address` specified. If your server certificate's common name does not match the +address you are accessing it from (for example, if your address is an IP address), pass `--server-name` command line +flag with the value expected in the "Common Name" field of the server certificate. + +To use mutual TLS with a client key and certificate, pass the `--key` and `--cert` command line flag to the path of +the files in pem format. If one is specified the other must also be specified. Unlike curl, you cannot pass a file with +the key and cert concatenated together as the `--cert` flag. Also unlike curl, you cannot pass the `-E` flag as an alias +for the `--cert` flag. + +```bash +$ prototool grpc path/to/root \ + --address 192.168.1.15:443 \ + --method uber.foo.v1.BarAPI/Baz \ + --data '{"value":"hello"}' \ + --tls \ + --cacert server.crt \ + --cert client.crt \ + --key client.key \ + --server-name foo.bar.com +``` diff --git a/etc/bin/grpcgen.sh b/etc/bin/grpcgen.sh new file mode 100644 index 00000000..abfe54d9 --- /dev/null +++ b/etc/bin/grpcgen.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -euo pipefail + +DIR="$(cd "$(dirname "${0}")/../.." && pwd)" +cd "${DIR}" + +# https://bbengfort.github.io/programmer/2017/03/03/secure-grpc.html + +check_which() { + if ! command -v "${1}" >/dev/null 2>/dev/null; then + echo "${1} is not installed" >&2 + exit1 + fi +} + +check_which openssl +check_which certstrap + +cd internal/cmd/testdata/grpc +rm -rf tls + +certstrap --depot-path tls init --common-name "cacert" --passphrase "" +certstrap --depot-path tls request-cert --ip 127.0.0.1 --cn server --passphrase "" +certstrap --depot-path tls sign server --CA cacert --expires "100 years" +certstrap --depot-path tls request-cert --cn client --passphrase "" +certstrap --depot-path tls sign client --CA cacert --expires "100 years" + +openssl req -new -newkey rsa:2048 -x509 -sha256 -nodes -days 36500 -extensions v3_req \ + -keyout tls/self-signed-server.key -out tls/self-signed-server.crt \ + -config <(cat <<-EOF +[req] +default_bits = 2048 +req_extensions = v3_req +prompt = no +distinguished_name = dn + +[ dn ] +C=US +ST=Denial +L=Springfield +O=Dis +emailAddress=server@server.local +CN = server.local + +[ v3_req ] +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names + +[ alt_names ] +IP.1 = 127.0.0.1 +EOF +) +openssl req -new -newkey rsa:2048 -x509 -sha256 -nodes -days 36500 \ + -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=client.local" \ + -keyout tls/self-signed-client.key -out tls/self-signed-client.crt diff --git a/internal/cmd/BUILD.bazel b/internal/cmd/BUILD.bazel index b04be4b6..7276a725 100644 --- a/internal/cmd/BUILD.bazel +++ b/internal/cmd/BUILD.bazel @@ -34,5 +34,6 @@ go_test( "@com_github_stretchr_testify//require:go_default_library", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//credentials:go_default_library", ], ) diff --git a/internal/cmd/cmd_test.go b/internal/cmd/cmd_test.go index 9f64945a..9ae16bb7 100644 --- a/internal/cmd/cmd_test.go +++ b/internal/cmd/cmd_test.go @@ -23,6 +23,8 @@ package cmd import ( "bytes" "context" + "crypto/tls" + "crypto/x509" "fmt" "io" "io/ioutil" @@ -43,6 +45,7 @@ import ( "github.com/uber/prototool/internal/settings" "github.com/uber/prototool/internal/vars" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" ) func TestCompile(t *testing.T) { @@ -1116,17 +1119,32 @@ option php_namespace = "Foo\\V1";`, func TestGRPC(t *testing.T) { t.Parallel() + const ( + serverCrt = "testdata/grpc/tls/server.crt" + serverKey = "testdata/grpc/tls/server.key" + clientCrt = "testdata/grpc/tls/client.crt" + clientKey = "testdata/grpc/tls/client.key" + caCrt = "testdata/grpc/tls/cacert.crt" + ssServerCrt = "testdata/grpc/tls/self-signed-server.crt" + ssServerKey = "testdata/grpc/tls/self-signed-server.key" + ssClientCrt = "testdata/grpc/tls/self-signed-client.crt" + ssClientKey = "testdata/grpc/tls/self-signed-client.key" + helloJSONValue = `{"value":"hello"}` + helloExclaimValue = `{"value":"hello!"}` + grpcFilePath = "testdata/grpc/grpc.proto" + exclamationMethod = "grpc.ExcitedService/Exclamation" + ) assertGRPC(t, 0, - `{"value":"hello!"}`, - "testdata/grpc/grpc.proto", - "grpc.ExcitedService/Exclamation", - `{"value":"hello"}`, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, ) assertGRPC(t, 0, `{"value":"hellosalutations!"}`, - "testdata/grpc/grpc.proto", + grpcFilePath, "grpc.ExcitedService/ExclamationClientStream", `{"value":"hello"} {"value":"salutations"}`, @@ -1139,9 +1157,9 @@ func TestGRPC(t *testing.T) { {"value":"l"} {"value":"o"} {"value":"!"}`, - "testdata/grpc/grpc.proto", + grpcFilePath, "grpc.ExcitedService/ExclamationServerStream", - `{"value":"hello"}`, + helloJSONValue, ) assertGRPC(t, 0, @@ -1149,7 +1167,7 @@ func TestGRPC(t *testing.T) { {"value":"hello!"} {"value":"salutations!"} `, - "testdata/grpc/grpc.proto", + grpcFilePath, "grpc.ExcitedService/ExclamationBidiStream", `{"value":"hello"} {"value":"salutations"}`, @@ -1163,11 +1181,223 @@ func TestGRPC(t *testing.T) { {"response":{"value":"l"}} {"response":{"value":"o"}} {"response":{"value":"!"}}`, - "testdata/grpc/grpc.proto", + grpcFilePath, "grpc.ExcitedService/ExclamationServerStream", - `{"value":"hello"}`, + helloJSONValue, `--details`, ) + assertGRPC(t, + 255, + "tls must be specified if insecure, cacert, cert, key or server-name are specified", + grpcFilePath, + exclamationMethod, + helloJSONValue, + "--cert", + clientCrt, + ) + assertGRPC(t, + 255, + "if cert is specified, key must be specified", + grpcFilePath, + exclamationMethod, + helloJSONValue, + "--tls", + "--cert", + clientCrt, + "--cacert", + caCrt, + ) + assertGRPC(t, + 255, + "if insecure then cacert, cert, key, and server-name must not be specified", + grpcFilePath, + exclamationMethod, + helloJSONValue, + "--tls", + "--cert", + clientCrt, + "--insecure", + ) + // CA issued server certificate valid when using ca cert as server cert + assertGRPCTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + serverCrt, + serverKey, + caCrt, + ) + // Self signed server certificate valid when using self-signed server cert + assertGRPCTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + ssServerCrt, + ) + // Self signed server certificate valid when using system CA and insecure flag + assertGRPCTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + "", + "--tls", + "--insecure", + ) + // server uses plaintext but client attempts a TLS connection + assertGRPC(t, + 1, + "tls: first record does not look like a TLS handshake", + grpcFilePath, + exclamationMethod, + helloJSONValue, + "--tls", + ) + // Self signed server certificate invalid when using ca cert as server cert + assertGRPCTLS(t, + 1, + "x509: certificate signed by unknown authority", + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + caCrt, + ) + // Server uses TLS but client does not + assertGRPCTLS(t, + 1, + "context deadline exceeded", + grpcFilePath, + exclamationMethod, + helloJSONValue, + serverCrt, + serverKey, + "", + ) + // Mututal TLS with CA issued server certificate and self-signed client certificate valid when using ca cert as server cert + assertGRPCmTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + serverCrt, + serverKey, + caCrt, + clientCrt, + clientKey, + caCrt, + ) + // Mututal TLS with self-signed server and client certificates properly exchanged + assertGRPCmTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + ssServerCrt, + ssClientCrt, + ssClientKey, + ssClientCrt, + ) + + // Mututal TLS with CA issued server certificate but using self-signed client certificate NOT valid when using ca cert as client cert + assertGRPCmTLS(t, + 1, + "remote error: tls: bad certificate", + grpcFilePath, + exclamationMethod, + helloJSONValue, + serverCrt, + serverKey, + caCrt, + ssClientCrt, + ssClientKey, + caCrt, + ) + // Mututal TLS with CA issued client certificate and self-signed server certificate NOT valid when using server cert CA as client CA + assertGRPCmTLS(t, + 1, + "remote error: tls: bad certificate", + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + ssServerCrt, + clientCrt, + clientKey, + ssServerCrt, + ) + // Mututal TLS with self-signed certificate and self-signed client certificate NOT valid when using ca cert as server cert + assertGRPCmTLS(t, + 1, + "x509: certificate signed by unknown authority", + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + caCrt, + ssClientCrt, + ssClientKey, + ssClientCrt, + ) + // server uses mutual TLS but client does not use TLS at all + assertGRPCmTLS(t, + 1, + "context deadline exceeded", + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + "", + "", + "", + ssClientCrt, + ) + // server uses mutual TLS but client does not use mutual TLS + assertGRPCmTLS(t, + 1, + "remote error: tls: bad certificate", + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssServerCrt, + ssServerKey, + ssServerCrt, + "", + "", + ssClientCrt, + ) + + assertGRPCmTLS(t, + 0, + helloExclaimValue, + grpcFilePath, + exclamationMethod, + helloJSONValue, + ssClientCrt, + ssClientKey, + ssClientCrt, + ssClientCrt, + ssClientKey, + ssClientCrt, + "--server-name", "client.local", + ) } func TestVersion(t *testing.T) { @@ -1450,7 +1680,31 @@ func assertDescriptorSet(t *testing.T, expectSuccess bool, dirOrFile string, inc func assertGRPC(t *testing.T, expectedExitCode int, expectedLinePrefixes string, filePath string, method string, jsonData string, extraFlags ...string) { excitedTestCase := startExcitedTestCase(t) defer excitedTestCase.Close() - assertDoStdin(t, strings.NewReader(jsonData), true, expectedExitCode, expectedLinePrefixes, append([]string{"grpc", filePath, "--address", excitedTestCase.Address(), "--method", method, "--stdin"}, extraFlags...)...) + assertDoStdin(t, strings.NewReader(jsonData), true, expectedExitCode, expectedLinePrefixes, append([]string{"grpc", filePath, "--address", excitedTestCase.Address(), "--method", method, "--stdin", "--connect-timeout", "500ms"}, extraFlags...)...) +} + +// GRPC Server TLS assert +func assertGRPCTLS(t *testing.T, expectedExitCode int, expectedLinePrefixes string, filePath string, method string, jsonData string, serverCrt string, serverKey string, caCrt string, extraFlags ...string) { + assertGRPCmTLS(t, expectedExitCode, expectedLinePrefixes, filePath, method, jsonData, serverCrt, serverKey, caCrt, "", "", "", extraFlags...) +} + +// GRPC Mutual TLS assert +func assertGRPCmTLS(t *testing.T, expectedExitCode int, expectedLinePrefixes string, filePath string, method string, jsonData string, serverCrt string, serverKey string, serverCaCert string, clientCert string, clientKey string, clientCaCert string, extraFlags ...string) { + var excitedTestCase *excitedTestCase + if clientCaCert != "" { + excitedTestCase = startmTLSExcitedTestCase(t, serverCrt, serverKey, clientCaCert) + } else { + excitedTestCase = startTLSExcitedTestCase(t, serverCrt, serverKey) + } + defer excitedTestCase.Close() + args := []string{"grpc", filePath, "--address", excitedTestCase.Address(), "--method", method, "--stdin", "--connect-timeout", "500ms"} + if serverCaCert != "" { + args = append(args, "--cacert", serverCaCert, "--tls") + } + if clientCert != "" { + args = append(args, "--cert", clientCert, "--key", clientKey) + } + assertDoStdin(t, strings.NewReader(jsonData), true, expectedExitCode, expectedLinePrefixes, append(args, extraFlags...)...) } func assertRegexp(t *testing.T, extraErrorFormat bool, expectedExitCode int, expectedRegexp string, args ...string) { @@ -1501,10 +1755,43 @@ type excitedTestCase struct { excitedServer *excitedServer } +func startTLSExcitedTestCase(t *testing.T, serverCert string, serverKey string) *excitedTestCase { + creds, err := credentials.NewServerTLSFromFile(serverCert, serverKey) + require.NoError(t, err) + grpcServer := grpc.NewServer(grpc.Creds(creds)) + return startExcitedTestCaseWithServer(t, grpcServer) +} + +func startmTLSExcitedTestCase(t *testing.T, serverCert string, serverKey string, clientCaCerts string) *excitedTestCase { + certificate, err := tls.LoadX509KeyPair(serverCert, serverKey) + require.NoError(t, err) + + // Create a certificate pool from the certificate authority + certPool := x509.NewCertPool() + ca, err := ioutil.ReadFile(clientCaCerts) + require.NoError(t, err) + + // Append the client certificates from the CA + if ok := certPool.AppendCertsFromPEM(ca); !ok { + require.NoError(t, err) + } + // Create the TLS credentials + creds := credentials.NewTLS(&tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + Certificates: []tls.Certificate{certificate}, + ClientCAs: certPool, + }) + grpcServer := grpc.NewServer(grpc.Creds(creds)) + return startExcitedTestCaseWithServer(t, grpcServer) +} + func startExcitedTestCase(t *testing.T) *excitedTestCase { + return startExcitedTestCaseWithServer(t, grpc.NewServer()) +} + +func startExcitedTestCaseWithServer(t *testing.T, grpcServer *grpc.Server) *excitedTestCase { listener, err := getFreeListener() require.NoError(t, err) - grpcServer := grpc.NewServer() excitedServer := newExcitedServer() grpcpb.RegisterExcitedServiceServer(grpcServer, excitedServer) go func() { _ = grpcServer.Serve(listener) }() diff --git a/internal/cmd/flags.go b/internal/cmd/flags.go index 7104e6a9..26c9bbe9 100644 --- a/internal/cmd/flags.go +++ b/internal/cmd/flags.go @@ -28,6 +28,8 @@ type flags struct { address string cachePath string callTimeout string + cacert string + cert string configData string connectTimeout string data string @@ -44,10 +46,12 @@ type flags struct { fix bool gitBranch string headers []string + insecure bool includeImports bool includeSourceInfo bool json bool keepaliveTime string + key string listAllLinters bool listLinters bool listAllLintGroups bool @@ -55,13 +59,15 @@ type flags struct { lintMode bool method string name string + outputPath string overwrite bool pkg string protocBinPath string protocWKTPath string protocURL string - outputPath string + serverName string stdin bool + tls bool tmp bool uncomment bool } @@ -225,3 +231,27 @@ func (f *flags) bindUncomment(flagSet *pflag.FlagSet) { func (f *flags) bindTmp(flagSet *pflag.FlagSet) { flagSet.BoolVar(&f.tmp, "tmp", false, "Write the FileDescriptorSet to a temporary file and print the file path instead of outputting to stdout.") } + +func (f *flags) bindTLS(flagSet *pflag.FlagSet) { + flagSet.BoolVar(&f.tls, "tls", false, "Enable SSL/TLS connection to remote host.") +} + +func (f *flags) bindInsecure(flagSet *pflag.FlagSet) { + flagSet.BoolVar(&f.insecure, "insecure", false, "Disable host certificate validation for TLS connections. If set, --tls is required and --cert, --key, --cacert and --server-name must not be set.") +} + +func (f *flags) bindCacert(flagSet *pflag.FlagSet) { + flagSet.StringVar(&f.cacert, "cacert", "", "File containing trusted root certificates for verifying the server. Can also be a file containing the public certificate of the server itself. If set, --tls is required.") +} + +func (f *flags) bindCert(flagSet *pflag.FlagSet) { + flagSet.StringVar(&f.cert, "cert", "", "File containing client certificate (public key) in pem encoded format to present to the server for mutual TLS authentication. If set, --tls and --key is required.") +} + +func (f *flags) bindKey(flagSet *pflag.FlagSet) { + flagSet.StringVar(&f.key, "key", "", "File containing client key (private key) in pem encoded format to use for mutual TLS authentication. If set, --tls and --cert is required.") +} + +func (f *flags) bindServerName(flagSet *pflag.FlagSet) { + flagSet.StringVar(&f.serverName, "server-name", "", "Override expected server \"Common Name\" when validating TLS certificate. Should usually be set if using a HTTP proxy or an IP for the --address. If set, --tls is required.") +} diff --git a/internal/cmd/templates.go b/internal/cmd/templates.go index 97153207..c2a25880 100644 --- a/internal/cmd/templates.go +++ b/internal/cmd/templates.go @@ -373,7 +373,7 @@ $ prototool grpc example \ {"response":{"value":"!"}}`, Args: cobra.MaximumNArgs(1), Run: func(runner exec.Runner, args []string, flags *flags) error { - return runner.GRPC(args, flags.headers, flags.address, flags.method, flags.data, flags.callTimeout, flags.connectTimeout, flags.keepaliveTime, flags.stdin, flags.details) + return runner.GRPC(args, flags.headers, flags.address, flags.method, flags.data, flags.callTimeout, flags.connectTimeout, flags.keepaliveTime, flags.stdin, flags.details, flags.tls, flags.insecure, flags.cacert, flags.cert, flags.key, flags.serverName) }, BindFlags: func(flagSet *pflag.FlagSet, flags *flags) { flags.bindCachePath(flagSet) @@ -391,6 +391,12 @@ $ prototool grpc example \ flags.bindProtocURL(flagSet) flags.bindProtocBinPath(flagSet) flags.bindProtocWKTPath(flagSet) + flags.bindTLS(flagSet) + flags.bindInsecure(flagSet) + flags.bindCacert(flagSet) + flags.bindCert(flagSet) + flags.bindKey(flagSet) + flags.bindServerName(flagSet) }, } diff --git a/internal/cmd/testdata/grpc/tls/cacert.crl b/internal/cmd/testdata/grpc/tls/cacert.crl new file mode 100644 index 00000000..bab9d3c5 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/cacert.crl @@ -0,0 +1,16 @@ +-----BEGIN X509 CRL----- +MIICgDBqAgEBMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMTBmNhY2VydBcNMTkw +MzA5MjE0MTM4WhcNMjAwOTA5MjE0MTM2WjAAoCMwITAfBgNVHSMEGDAWgBQutivJ +fLPpGQzEsIrXebSLEuhXhDANBgkqhkiG9w0BAQsFAAOCAgEAGAwfi4/RGV/Wd3QR +GF+DcnlAYb0JY+fcmhJ0hChsSLAnOv34SDk1O9G1/TCPgNRXIedg3QLYiF3Ogbed +rELehUT5RdB6F8gbpxRE/gk6raE6VmFwrwvnBG4eKBTX9+4xVJQ6c+9ZigRU4vQm +EEXVnwHpIu0YBJ+LGajZfApYWSbgiAcEVFkqLFcXpYvMR/yTptghJxL5aulZbI8X +YnWwguk4XX8+leLfoAEbSNEHlMzP7OntOqea/lLOuTP9QStM3fYHbCtQwhx4iYwv +hhoNJGTBkAH/HQlIUMFYVqGtPyCNhVBcS5feMBKKASb3l9kr5hyFbxc4MFSH/1Tf +1gLBi0wtV2p55qckT+bC2kj3CJbzaWlTw2U7T6QtR1KBjgYnZGlVQj/Sxr6Tof8F +qeULqbX7bbQdZFomIXiS+VAI4ZDJQ1uB9SAkEJU/Q05hOygvaDuAH+imFyyOwSW3 +/x+mGwRVElvWmcdvWjpta6knoKZsWGYGgd381IlFBZvBcpS2atQFC43bTXtixKls +UlPAp0VOeE6om2BoR2Olf75EmnXVZNSNW3Jd7CwESf2llYLKWMNg94UuTbzclGo5 +nxoijG5IrSg7e0mTtlVTO+9KmgOUC4beodjoAZ36oc/bh/xIuIlztP8CLn1Sre62 +B0cuYAZP9Aw5JSGI+yxLTJ0DFPw= +-----END X509 CRL----- diff --git a/internal/cmd/testdata/grpc/tls/cacert.crt b/internal/cmd/testdata/grpc/tls/cacert.crt new file mode 100644 index 00000000..1b585e44 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/cacert.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZjYWNl +cnQwHhcNMTkwMzA5MjE0MTM2WhcNMjAwOTA5MjE0MTM2WjARMQ8wDQYDVQQDEwZj +YWNlcnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM3s17wcNfv2AH +ljOMIPUD4ZcXjWJvs16Nrdff91lmq0f9RK2dYP1r4c2XtT4E81JD+mZMCaTI/AqY +UMrxJlrF0nDB7GiILGkrQhr1hrncM0r7pHC91j6HvdHbQVttmSrjgGrVDbk4URmR +sNZdx4GCDHRlMZqfDfVZp4KR0Fgh9Hm1pW2d9E3nqtUKFIAiho7hYsO9ok141NSg +nSHbXBC7G8eaCo0AJb+S++b7q3sHW7CNna1a/95+zoj+m64n88hHY27aIH8mRlhW +6n5a3lxgRUQbygWY30IJ5wKYKEKqymRzD38Q7L3BC2utbCHDPMJhl9GO9tG8l6j6 +rMXbsJXGgTHQ7qmN7gboy3bOyGA9ePFW00HCOZURn5l5oxcQVGbzTA6LoTuTMdnx +SmtRL+lZvkciXVs9GEgvwZjb5+GFpvwvS3WICgiI3lrjx8vir7cRCuOeWqitPvZP +KqSvSQVLg9LLr+AxchxbbsdYimwFI1EmhNDEEzgzapah9M4q182OB4T3TUxsgrF+ +1Bvbu/BQuKng1KhDo4JyR1259RgAeYso/OqxJMMXRY9T8rahnmktBmglPW6E8sZS +fRNjKnovLgBIEJk0ZycfpWWLnSX1sW9pMWtuFXf0aB1TPyAw3E7ek93cRYtcBzLT +A1NvEFjw9IXXdfGrX320I/wWOo6auQIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYw +EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQULrYryXyz6RkMxLCK13m0ixLo +V4QwDQYJKoZIhvcNAQELBQADggIBAFx5PYMUEDzRmHuDZuH5nq652Eicq+/uJ1Ph ++7F6WsXgWyWQY/+VNNKm+BWUiBlvI29Vn4abGTxTZehGPeeK3au7DvFWtPFkqVSo +fxMnaYkUG6fvKgrOWcY0U6IWsF6WBKrD1YyVZ2QutF2r6qGHaQxbqqWUbfD4IPEU +uHWWZ1SYv/moPiyLU1R7/OZ3lxrjeiB7cNwrgKkGT6Bf77DPd6+5m2jZ1x1RUrr5 +ex8XwkztVPsoGZFXacPTpq9nOxlRGaKPD75xl7chwkCfx9vtnHokPYOACzvl7GZU +Ak8s+/8riEx3DHLzjVoPTxG4ON8qMcs9V9jmBsj+1MD0b6Li288a5TbQEXVcVzBj +2FHywqztOSFCICOh6kizVzohLWWWmIeXEEl0t+TXF/YlDB8ldr7CalTldbAQCv/K +omrATRd2EUcyrmEE1fPuMCJqKwpDSEmgVW5MNhmqdCvxpP9tinxmPXTI8YmjX04+ +7w8AJQdDbrXdGwXLrFIkTdhafQY33wX4RRZ4gK/tVPid97a/qyAH+Ipx8apsrdYV +E1xmiNsCmbCKyNDA3ZO6KkFh8UJ0/GNjIzT3ThGG2TPXclHX1TXIjdM7sG1zN3xh +1JWqWWYFKNEcFhV7+8UcLtrDaI2ZF8Wg2yrCbn6ISNZ/Argi88Ele8sa7F+d8EQT +1Kpr/yuI +-----END CERTIFICATE----- diff --git a/internal/cmd/testdata/grpc/tls/cacert.key b/internal/cmd/testdata/grpc/tls/cacert.key new file mode 100644 index 00000000..afb4ae6a --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/cacert.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/internal/cmd/testdata/grpc/tls/client.crt b/internal/cmd/testdata/grpc/tls/client.crt new file mode 100644 index 00000000..bf0acadc --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/client.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAgWgAwIBAgIQeOOoRS8IXPFTa9rfz03IojANBgkqhkiG9w0BAQsFADAR +MQ8wDQYDVQQDEwZjYWNlcnQwHhcNMTkwMzA5MjE0MTM4WhcNMjAwOTA5MjE0MTM2 +WjARMQ8wDQYDVQQDEwZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDDEMxSkdh6R90L+d9kXl7lHx2178kBloGyx07j4whoCsxy98/6LVEBDtEZ +nXZtdI4z3F6VaQakqx3CTc1lkQHwvSa150E7puAUgmRPp5xwpR7O2qEaIXujhWfo +4kV/DJ3po6I5tioPdEF82URNBfz2pw93m5i6Kgecaojw5j2uevwIPe70H5PXqAZg +pn3zcVC5JKUg8dm7GvPy5sYiJ9ZYX/sj04ErvLKQhcZoyjJufz9szwyvQfosiDri +fo5Tzd/iu/LErRgVN/iKA9DNZdVn1Pi2Wc3bbXjgjHVpEc732/n85Co8QdoUDblb +Fq4aglxzx6qcj+qwQmXwHEG6k9I3AgMBAAGjcTBvMA4GA1UdDwEB/wQEAwIDuDAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFCh9r78vxk9s +olJJVN1t5BiQqwz1MB8GA1UdIwQYMBaAFC62K8l8s+kZDMSwitd5tIsS6FeEMA0G +CSqGSIb3DQEBCwUAA4ICAQCFQVsbsg/XwCsOT9mDw6bBzkQcF2q9LwVSwQr36saH +GGzpUtRlx5xoIdXobBTIv7yZcat9mNJc74b8R2A2qtS9r7VqTI6jU8Z9sWaUEiHz +y+kP1EFGhk6JOaU4PxtDvIuuZr7yBV5KHMq7EN06PmVb8hC+MbK5OURUaciV7UzG +haGZp6avCbidi4gD2fHv7ffF8zwCZH/ynkFoOSzf/KGDfIRjkKJVVhNAVMklYmBD +TjsNfL1uZcd4Y/p9q+Umc4v+cDLdmtQt1FwA8huKz5oI45LdkqYaAgMmfEfLPD38 +Li6SAHpgr+VyQ9YYDxLuryT8BDL69xCq3CNKyUtkfNMKlFP6mZdUO5tvxlV8HerM +ZgD6rH/JHeT1sX+t7pEHh6knOhyCuQ/grjugz4cirDCPgICdAH7VwFBS14mAv+lr +oqUdoloqdI3xevZnVODH+9IT/Y83yEjtaumeyfFyYMQ3mM3/y5NDgDg6gUu3gGSm +19AAXzloYW9Re3kAYCesXNfKZiDn4Mk2AiBC4Le3Yucs5nVwFLT9Wn3JHdL6vTog +9AiPsXo0AkENhA9ij41p7xPB5cOmLvhoCD0jSXCF2BHRx8HjGxqLYdlO6hYc07Cd +Ur8jRUhZwaYc0KNzxlGHbo8OmJfYgJWKx+TEuutYbE9MgWm9pwwGTF0YDECfemk7 +NA== +-----END CERTIFICATE----- diff --git a/internal/cmd/testdata/grpc/tls/client.csr b/internal/cmd/testdata/grpc/tls/client.csr new file mode 100644 index 00000000..b25caf5a --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/client.csr @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICVjCCAT4CAQAwETEPMA0GA1UEAxMGY2xpZW50MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwxDMUpHYekfdC/nfZF5e5R8dte/JAZaBssdO4+MIaArM +cvfP+i1RAQ7RGZ12bXSOM9xelWkGpKsdwk3NZZEB8L0mtedBO6bgFIJkT6eccKUe +ztqhGiF7o4Vn6OJFfwyd6aOiObYqD3RBfNlETQX89qcPd5uYuioHnGqI8OY9rnr8 +CD3u9B+T16gGYKZ983FQuSSlIPHZuxrz8ubGIifWWF/7I9OBK7yykIXGaMoybn8/ +bM8Mr0H6LIg64n6OU83f4rvyxK0YFTf4igPQzWXVZ9T4tlnN22144Ix1aRHO99v5 +/OQqPEHaFA25WxauGoJcc8eqnI/qsEJl8BxBupPSNwIDAQABoAAwDQYJKoZIhvcN +AQELBQADggEBAIzkEMlnvDzhCeG7PJiTAISWqwhuIooyD9AOBF2Nefd5CzzleGP2 +Ou9OTyGc7yhNk2mgQz/4F37aenCglDwxgRiHijOqGnQhT4W8S+sh9uYut0SaPfE4 +BgiEk4Bw+ESy2jIibjxg8//J2753GZsIvlMALQNBSGbk2Mew1Y9CfRxyjWBDJ8Mt +WHJBpVf33CPNACdWDXwZVLsWWCOBqcCjogh1iPNv6srQBBR810M6vF17bumX5rv3 +cl5T0aq8pdY4VvEOUnHeAQHEZOb1akDbfoVKOJW4JUTDFgsV5y1VYQB93J7bjODQ +J2C/CQMEXum5T0OEXQcyT0v2beJ3eXbV4Z0= +-----END CERTIFICATE REQUEST----- diff --git a/internal/cmd/testdata/grpc/tls/client.key b/internal/cmd/testdata/grpc/tls/client.key new file mode 100644 index 00000000..3be03b25 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwxDMUpHYekfdC/nfZF5e5R8dte/JAZaBssdO4+MIaArMcvfP ++i1RAQ7RGZ12bXSOM9xelWkGpKsdwk3NZZEB8L0mtedBO6bgFIJkT6eccKUeztqh +GiF7o4Vn6OJFfwyd6aOiObYqD3RBfNlETQX89qcPd5uYuioHnGqI8OY9rnr8CD3u +9B+T16gGYKZ983FQuSSlIPHZuxrz8ubGIifWWF/7I9OBK7yykIXGaMoybn8/bM8M +r0H6LIg64n6OU83f4rvyxK0YFTf4igPQzWXVZ9T4tlnN22144Ix1aRHO99v5/OQq +PEHaFA25WxauGoJcc8eqnI/qsEJl8BxBupPSNwIDAQABAoIBAQCzrK9nhuuNhtA3 +DcwVGU/zX/vv75SIn+eLk0Y5ZpABtaCobVbmrAMnJEy6eW3yWB/76Qo+OWVjHDLn +HN8KpMzSwIf9matelNFmUsyvCkZxA8ci5gLqnNjTwDf8LR+ybR6vbIgq/H41ifIg +W8gr4k4lq6/1jh7Zq4kjLIZCzvEV2poRnGZdyzVtXV127NoObsrwTuvY11FGjQw7 +O97rPMhph9AhTOU8mP9iI4iDfMwb8eJpebx3VYbAnsMfQIVYUpXns916sSI3xxqE +M3tfNdmRDuLD0GtQbwXS8uuDLOfueK14Ts9CavSpNkd5/bXZ6kKxOug8orjyxHmW +Ik1PLw1BAoGBANKVzuNlsC+m3dW5dBXv2Q3xfqU43cgvTLLfIQl9IxrXJ1UXBY6O +0yvSeuUkHTg7aUEocZiVaXtMYce5/xAhm1HVG6xWl6h1GVwHq3/HLcWZWHPBCKBV +TLGdnY6OaiIccfeYujw0s6ypS+hm3iAM7NaMAy/Lp1HTtPB57d+PCX4RAoGBAO0i +K6IuIwsY9AJgVPKbOaJljzNQhAzw8FjOu1Z6pUyMFdMbpsKtVw7IRqFJid+sqT/K +Q2x63d9g6U6ekmMtulx6IdFoNj0uekD2NkpHSwgip+UeoD0M1NDsD8HswuwBVS3F +PAXbiyDA11+fK8G//nRtS4JOpxQcGWDSxnX6DqPHAoGAa3GgE4nosQd0m/15a0/q +8SBMO8Sd8+ueOI1777l3VdR87v9GCIx61hsYNR2OAwjdFS+rdeyV2yEHqr4Nk49y +Dfirm+y6iGrmu3v2VsWrZuxsovLUkemzrdP7dabYI/tbcrbsHpfNLMVcQ4Fox/WQ +SY86eQJxpmBcK24qniv+7eECgYEA7Eaj21DFMgWG++coPSNVZe5zpNmQ+aQIlzRF +jYFeusrJ5DMlEczNdbkwRvyTF/9eFGVgkPJLqItTbDar/Y5Opl463ABOKt/oiFnK +9m/a3xxI1g6R8sKaOiE8Ain6flVFnflsORnropMDBg/+9WpsC23rUsczyuHEl6js +fhjOBXkCgYAJV8PQSr7JSU57ru/A6TP1oJ8trtWmOqReRFGGtt0vqMKv6CIANyjY +A1THhVVvAU6tUep07SJizYcSXW7I9gpNpa+F9u0H1pS4qK/aimbAufhUtoV8EGsM ++y/TbN2tEIQymmQIAjnjAReKQqhhBNSbk6zf6zhxC3ERSB/3OLSy1g== +-----END RSA PRIVATE KEY----- diff --git a/internal/cmd/testdata/grpc/tls/self-signed-client.crt b/internal/cmd/testdata/grpc/tls/self-signed-client.crt new file mode 100644 index 00000000..2f538208 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/self-signed-client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMDCCAhgCCQCmeuVGybe3JzANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJV +UzEPMA0GA1UECAwGRGVuaWFsMRQwEgYDVQQHDAtTcHJpbmdmaWVsZDEMMAoGA1UE +CgwDRGlzMRUwEwYDVQQDDAxjbGllbnQubG9jYWwwIBcNMTkwMzA5MjE0MTQxWhgP +MjExOTAyMTMyMTQxNDFaMFkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZEZW5pYWwx +FDASBgNVBAcMC1NwcmluZ2ZpZWxkMQwwCgYDVQQKDANEaXMxFTATBgNVBAMMDGNs +aWVudC5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGR2H7b +hblSyJPLoN8XE/+dMx2E7NLI5xX2Ey7e1IIrq05az310doqtZ9AwXzYMTKjZwMG6 +6Gno3pnlgm7skevzlQszO4kHeHsBnPiL/USL9pMhKLMnshTaTfP4e9X8qUMZOfvq +pIiQdlNlNqRHi5JdgEbeztGoDMj/2+/EqB96zm6ig0tRpH9NJ9UxSutrWW2jtlYD +495txR+SI3OSYPoGNC3tNBIBWcQCAVwVld5Evd8bVQzq15eUYkX0rvq0UI92Sl9P +UqCG1Ba393fbWL20dNsxYxrq037ku9aJUF590FvpNSsoCk/cA8mES/sTn0cpb4V+ +TQzJsigetUHcMsUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEADJjkrInxAlBs/vJP +QmmfncLaTxo/zROAGgbIvpUssB43/AmP6Rgv3nly22bhsI8fHw+I9wZTPESdc802 +89D8uhseSghH/iLSSQfnEOe1inyz8IuNv9L2h6+mKB11jw99R2chUxJc7NjZrXWd +bLcg9byuaR3Jx2wHb3T05Ay1FEfCmXQKe9K9ZukmAJy8h929+23f8JqMUqmTnmKX +0cUWtw8c3TvaYi8AXuhK0yK3Hr08cJ8agYXzPlV25slnVft6KA1+cOgaeIyuK783 +e5hRU3myuvDNV6Bz2yMAfsfGch6Sc7BLmq7vjPO4wYo0aUKmFbcuaJrVPPi3AwEy +u8GBhg== +-----END CERTIFICATE----- diff --git a/internal/cmd/testdata/grpc/tls/self-signed-client.key b/internal/cmd/testdata/grpc/tls/self-signed-client.key new file mode 100644 index 00000000..dc59ae0c --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/self-signed-client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBkdh+24W5UsiT +y6DfFxP/nTMdhOzSyOcV9hMu3tSCK6tOWs99dHaKrWfQMF82DEyo2cDBuuhp6N6Z +5YJu7JHr85ULMzuJB3h7AZz4i/1Ei/aTISizJ7IU2k3z+HvV/KlDGTn76qSIkHZT +ZTakR4uSXYBG3s7RqAzI/9vvxKgfes5uooNLUaR/TSfVMUrra1lto7ZWA+PebcUf +kiNzkmD6BjQt7TQSAVnEAgFcFZXeRL3fG1UM6teXlGJF9K76tFCPdkpfT1KghtQW +t/d321i9tHTbMWMa6tN+5LvWiVBefdBb6TUrKApP3APJhEv7E59HKW+Ffk0MybIo +HrVB3DLFAgMBAAECggEAD3oRzVLQBllQIEEPw8acmrt+8sVGCjR2BZN/RSgb5ayI +LeOk42sEb2IeAs9bTX7+QiHm/5ZqLs2nvrZTD3tqz2rSZ+rYv8QRJgSjAFxxC6IF +PQ5RqsFpw7EQuokLnbht8Cd8M2A3d5PVYiWdkNUHm9ROBVybPLgrDYcnlqwqpRmQ ++2DShs7wt4ocMNEjt5FIjyMovFAYR6CKqaVoDO/EJQAlBSi5izZT2Qrn899h7bMm +Hp0ptV8e+z6Z7YabsP6sfyFOQoeUQkf/MD5zseymcf/uUbbMR3Xg4dY+bO8/pBsh +S8oA4HpAFPn8W2i+DAsbXvID+KG1AWYWPmy+Dzn3oQKBgQDk2yAbkiph7Iok2BMQ +geZpurjOfhYcgdlnBST8KEoie1qC8X7AhwULeTYdceM8LvStib95PIJ7v/bJQlRH +kM3PqOVsucf17VMCY1OktIA3lu+Lmp2MSqm0n83iKOKG5QbxY+cw1ETOl1QZE4+l +ti189gxlaiQgTjNnVxOCWa7rTwKBgQDYh04ikAskjYrwee0m1e2s2EGtolfc3xRz +fhZN32td64FiBv8gGgoH+Mfu6wLGexVAUhJdcvTZL6wyaZwLlfMiCK0iPzv9PoY2 +6p2VlAwpbM8OsUe5MdvgWdsJ/Lb6jm8uXK7uVMfY4EupkVvCkQ5rTbk7nTl1rgVO +5Ti1QOVrqwKBgFe1d2e5rA6dlhAq05um/USWME/LWPQR+90UxqjxVABFIFpA7aAh +3xgXm1rLlBgzsshzm3N+ck+1MYLOrfhDke09QLhbtzwUeZTXtm3QU7d6XFI3rpve +3Y2BFWnQ24hxbCjFbgxzve8jZjK6IXqUCHj036ladYAAGIlJgQubDYPXAoGBALr1 +YU7Qhv6BxITNEiqlLro+Y79T3H+WkqcCKKoGjkMjFK0ak3EZaq3lbmRpwRS1s+y8 +sKTFnIpm8kz5CUarq6ooSa23YcnREbwbKgO8OCAQllv+UIqkdVCq5UkjTq7bCz7B +wj2BMKmfSVVZcBx4eTXHf3fs0m882dJ8c1F1fmJPAoGBAK/DEdJVF69Ea2qUneBg +Y0pLXB5uATafx/Ob1C/45LZWmq/bhrnzya7BtasjZqZq8TgYr/OhBzz3L8c1GQEb +OwkgYm2HMEpxF19HqrrxCYxffc17P4itKfXkLvgBFwNraEBD83Lqt1sjjHkqNV6X +nrbcoTab17oeYFI1WKreIdJB +-----END PRIVATE KEY----- diff --git a/internal/cmd/testdata/grpc/tls/self-signed-server.crt b/internal/cmd/testdata/grpc/tls/self-signed-server.crt new file mode 100644 index 00000000..3b39b57b --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/self-signed-server.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqjCCApKgAwIBAgIJAMbsccMGDD1zMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVTMQ8wDQYDVQQIDAZEZW5pYWwxFDASBgNVBAcMC1NwcmluZ2ZpZWxkMQww +CgYDVQQKDANEaXMxIjAgBgkqhkiG9w0BCQEWE3NlcnZlckBzZXJ2ZXIubG9jYWwx +FTATBgNVBAMMDHNlcnZlci5sb2NhbDAgFw0xOTAzMDkyMTQxNDBaGA8yMTE5MDIx +MzIxNDE0MFowfTELMAkGA1UEBhMCVVMxDzANBgNVBAgMBkRlbmlhbDEUMBIGA1UE +BwwLU3ByaW5nZmllbGQxDDAKBgNVBAoMA0RpczEiMCAGCSqGSIb3DQEJARYTc2Vy +dmVyQHNlcnZlci5sb2NhbDEVMBMGA1UEAwwMc2VydmVyLmxvY2FsMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6m8Mlkfb7TSuZk8nfv4pMRN4Ad/p8jQb +6NWiuHBcOAFQE97ximbXzEYQdt9N8hJHeHC+Fz9zwk4nPgiDpGhz9vvyfiyzrEet +bFvEKbzqDwxh4cXiyWMRWvompP6nAf9hnZPsgra2j5nUgVg1bQ8dppDY5YvZUxyg +/r83N1CHRgTHxHuuK9BUjRzZwUH0K31+AspuS1awxXW0BMyVIwBJstfr4O2GHuX+ +UY3wq7Q0rao4BVxaodKhkEDiSXunvQRqydmq2rwctWEP1wbz7gotymT9z6usR3Xy ++B013XQYz8teed8Sz0FsjzEgq5U6BGD6+tnBNZBZPkDXugHoqoJntQIDAQABoysw +KTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAPBgNVHREECDAGhwR/AAABMA0GCSqG +SIb3DQEBCwUAA4IBAQBBQPHAd6ecmyCPY5u5J0N7ZiaVHf9oTjKqMDd8JbzieuBY +Bj1J9J3J5L63E45EpoqNDzdXzD86yweydhZz6tvtEGRH0r/mAJJ6PbePRAs6wMSr +jatHTXCLkbODrGcd+xDvi4Aq3+UdopyXap+wxJdAAuTmh/DVOBOe4jLQFFee3tdq +lqCq8dhHgEzs3wNHeaNNxVIWJIVWEs5Xkk8nEEK5e4N142/k9Qk7KSf8HJA2F7Im +jwlLT62jPS57zCkljs+uzEe+6HJ4QjTCJ6tbk4RFNlltExWalubguMpTPgA6/9Qj +eab0jQ/tvD/nbvWteGhHUXckGOttiZwPRpxIlbMW +-----END CERTIFICATE----- diff --git a/internal/cmd/testdata/grpc/tls/self-signed-server.key b/internal/cmd/testdata/grpc/tls/self-signed-server.key new file mode 100644 index 00000000..e18485b3 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/self-signed-server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDqbwyWR9vtNK5m +Tyd+/ikxE3gB3+nyNBvo1aK4cFw4AVAT3vGKZtfMRhB2303yEkd4cL4XP3PCTic+ +CIOkaHP2+/J+LLOsR61sW8QpvOoPDGHhxeLJYxFa+iak/qcB/2Gdk+yCtraPmdSB +WDVtDx2mkNjli9lTHKD+vzc3UIdGBMfEe64r0FSNHNnBQfQrfX4Cym5LVrDFdbQE +zJUjAEmy1+vg7YYe5f5RjfCrtDStqjgFXFqh0qGQQOJJe6e9BGrJ2aravBy1YQ/X +BvPuCi3KZP3Pq6xHdfL4HTXddBjPy1553xLPQWyPMSCrlToEYPr62cE1kFk+QNe6 +Aeiqgme1AgMBAAECggEBAN9qj4tU1lI8Z4xXGSPconMDw9W9iB3r7UE7AAVYB3rU +PXWCfZzRoA0sJJq0+3qcUwKEJ5TOQsrFYn6q7JItfX6+4329qkmgUbU3yz2frUxE +F7Brv1L/l9WlGlkZ2x17PZNIGxkDef5msu/Fmbzir/ZCioJQgf/EA+ZjYwLTOufM +6YYudo6TvLB0/xekPfXyLh/oY+6bLqXAL1GHprspBOFBKt7rVelfZlHf0zq2rTfl +mKObmTEofzdXiQNAx/lWSWDny55pp8Y/YVb3Ww15eSIa0yoaNOL7/byLQ6CIYXCQ +G5jpY1nPSH89K+/EZBGOi/XEHGpgLiCWfxeH76xZ/K0CgYEA9mjlXH/xOWGTa3ms +j6QfaNsKujhcQPaLbUup7V72dv7sJvihQAb4V7uu5+auzMdjz/r5tIT2MfwueXDC +nMwtLLl4BbT4Sobg/3r7yYboSHm7H7tPCfHPWFKw3kv0hKg9jOwHBGV2c/i7BW0s +UsYxLdBSzhSL4CMVgzSD6Sh4c/cCgYEA847Up6smHwa493XdtsIvXCJZPNf0bUV4 +WF2c6fM/5gxR7XooX3hwF8PY215uoH9tnhyCZSKYuuHxO3UFFlOql0+XvC6Z0dRc +yojj2pEV9R8y+/XR7Q4mx4jFv7lru3ugcWVLXgk/JIRJ3fy3dkJYMXRrnjhM6NIH +AO4U50uIvrMCgYARxs+FNNW6RgfUoRqJ4lVBw0uq05YUObUlVWgU79zoCMwQo68+ +Z0JTUf70S/ggXeIdhwWsuErqoD7aFAB2P2Si7V5zSvL+rWxeAglYKJtpXx7Y0zKI +jSFgRdbssp4ZU+nc2MpIzukUxMT5Rz8DWbkCjRzsMR9GNEHBDXDWyUynUQKBgEMt +NgI49n7AP+whGlH6JU3oO2zIs6Yf7x2QVGNCsHEnHMG/W7tZYLFtVzbKSQEDpJxj +iKOUc0O4ZezcTdbmpLqvPU6uG8cAJ8fFEfOK6N9/B3TvTENyD8ghNUm4PrqrUol0 +QuFg84WC50zPE1sO2Xxqe/Rb2vqsUzoycJmK/+B5AoGBANJKdfeK1SQ26P6OdnpG +GzTNLvGYS00xhO6OmEnYjieaeX76ub/k3uQZB7SrzBrN/lHEOnjXKPS4Cchtr3IB +/j+w4wtdG6vA5dRLoN8zDptmPinJPzVwvlu/X/ofaaXpphEuV9lkCpzn4zPFC2Tn +DGeZxYkDsoE5gwB25SiFi//c +-----END PRIVATE KEY----- diff --git a/internal/cmd/testdata/grpc/tls/server.crt b/internal/cmd/testdata/grpc/tls/server.crt new file mode 100644 index 00000000..e02b72b7 --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/server.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEMTCCAhmgAwIBAgIRAMTOBLoHKcIhvg5r0yi9isowDQYJKoZIhvcNAQELBQAw +ETEPMA0GA1UEAxMGY2FjZXJ0MB4XDTE5MDMwOTIxNDEzOFoXDTIwMDkwOTIxNDEz +NlowETEPMA0GA1UEAxMGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEArxCOOhqYanFgVkvMKb2MiH6roqd/2Wa5zkZOxFSbcalou6XVr0ccI1rB +C+4361krCV6NIocvNxFvbULpAEquxC5hPVW69lg5l1wZKtk8+ZehC5a1UIHyy/Ol +lym5hMshC5WGPTWvUmijqVcH7rSGwhbDX5aquWlnRx92TDKsVHK7yA6Abimt8XxA +8sauguHJ6q4uGRlDM1RFec6fSa4+YdBimxxAQAH9DFsvVYT7bfCjLtYF1A2SAjx/ +Vvdh0foUJ6XT0o67ooucaZLkoXLAIf/v2LIoTzBSqtGoQAyHYtv9FaCJxkf/ktTi +kh8UG7e/CnGcK4rt67VzUzIvj+zbEQIDAQABo4GDMIGAMA4GA1UdDwEB/wQEAwID +uDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFJIIFkKZ +mbe/JSiObqYIluFv5AytMB8GA1UdIwQYMBaAFC62K8l8s+kZDMSwitd5tIsS6FeE +MA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggIBAGH7kgeV7NdMTgmS +IUhffssB3bT02WjSNuMfdeTRXqRYgYevEOt/+eaYl60lRWRAtIS/2t1iQuIWQY4U +wQ3jiAB9HFEURDNhrQSeFnqor/qtzawD+o1JjpKIjbj/1D5QR6VeBXxHmUk7VM2q +4JPvuCKhLUzCBTMhTk7XmjE/y/dEb17XXsQsfFDfB7efEdWUyv/X6WYVK9uhWWYp +bkML+RzvoRQZ8A4oxn7WZCvGvVc16PIHQx6pAtjWmbS78pGHAOGI7rI0mOOmMMtr +GjQYNrhM3ENmZIblJZ7lcxB0LR4hN+tSt+I2qHgrRlC1+aiuDjDbeUX3W/Hw6gVd +TAlOHYIs+HeF/dm0NmDTVywSTvGhsfVqP7k+b4nhPrPKkMRItFIUMYk446UTIIw9 +ZbvC7vEDBxuThQ3cDlr2kJYOn9l0rpUY/7mcvRok/bGLIGGVeBv2YRrpC7db5bRe +70p720mC7Ugc8p9GuDQPYN3kxtYaKLgVpSESHphaybwxtC4JjixBlayh3vGAObVI +x0k23g+Awv2QznkFpt8QCXe9b+SmKVVziybp4CuVWck8zH27v8zflwgLslHmzWk2 +kGSgOeJHvj/ayr37VPK+1jojQYiBb8fPCNS/eWrDRd9XKJa6gO3NTjPdXQlB1pvL +TR6KBpLH8c5GU5aBtiyavRktP/XF +-----END CERTIFICATE----- diff --git a/internal/cmd/testdata/grpc/tls/server.csr b/internal/cmd/testdata/grpc/tls/server.csr new file mode 100644 index 00000000..9f045bad --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/server.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICeDCCAWACAQAwETEPMA0GA1UEAxMGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArxCOOhqYanFgVkvMKb2MiH6roqd/2Wa5zkZOxFSbcalo +u6XVr0ccI1rBC+4361krCV6NIocvNxFvbULpAEquxC5hPVW69lg5l1wZKtk8+Zeh +C5a1UIHyy/Ollym5hMshC5WGPTWvUmijqVcH7rSGwhbDX5aquWlnRx92TDKsVHK7 +yA6Abimt8XxA8sauguHJ6q4uGRlDM1RFec6fSa4+YdBimxxAQAH9DFsvVYT7bfCj +LtYF1A2SAjx/Vvdh0foUJ6XT0o67ooucaZLkoXLAIf/v2LIoTzBSqtGoQAyHYtv9 +FaCJxkf/ktTikh8UG7e/CnGcK4rt67VzUzIvj+zbEQIDAQABoCIwIAYJKoZIhvcN +AQkOMRMwETAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCZlmJN +nnq0UoM12zzyyEmnAqohLPg+ucyi/uRDjOCQy+IZRdyUtJ68y6V9sBf7Ye+DDzGT +P9H4K3EJ8Wd1n1rx0SA/ZigE+qqmDXWzgTaDfxL73DMV+myuvRscZl1tpzCAuTN6 +K2mrPXyboFrzl0OUU7H5WQ8NZrhe5ARPcmfQeUyVVRUcb4Kcw7mc8AV/MBmRIDK1 +FI+6bTq01ivSdIWCe77aYw05JsvQaqN26qLsM/hOYW/CGN50bM/2iGu1w0wFPGoQ +NX0uVWGlgo1CAib12uyF3z0UsppchozGd3pBdNwACLcGoDNLfm6au+YxMc3cKXnp +I8lGlLiBskMVecsD +-----END CERTIFICATE REQUEST----- diff --git a/internal/cmd/testdata/grpc/tls/server.key b/internal/cmd/testdata/grpc/tls/server.key new file mode 100644 index 00000000..0cc9a58a --- /dev/null +++ b/internal/cmd/testdata/grpc/tls/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEArxCOOhqYanFgVkvMKb2MiH6roqd/2Wa5zkZOxFSbcalou6XV +r0ccI1rBC+4361krCV6NIocvNxFvbULpAEquxC5hPVW69lg5l1wZKtk8+ZehC5a1 +UIHyy/Ollym5hMshC5WGPTWvUmijqVcH7rSGwhbDX5aquWlnRx92TDKsVHK7yA6A +bimt8XxA8sauguHJ6q4uGRlDM1RFec6fSa4+YdBimxxAQAH9DFsvVYT7bfCjLtYF +1A2SAjx/Vvdh0foUJ6XT0o67ooucaZLkoXLAIf/v2LIoTzBSqtGoQAyHYtv9FaCJ +xkf/ktTikh8UG7e/CnGcK4rt67VzUzIvj+zbEQIDAQABAoIBAGX6ze9ZCMqQ6x66 +Ht991Ly6lX819csOBVT9Les+oiKPHjyZeSYW1XRe7K/ngFmv4tsdYjfn6gA5PuC2 +JocN+kq7/dc99qCEemAKvXpxfAylYKIgk9SnLmnSr/ajzrdloQVfgAhuGoh1/kiq +MyvBq/KqUfuACEnj9c6/rCjtJ+g0ytCUpai4XyhN8QbDHbCUuVuJLIKdj6gU05hf +Opbl00OvT7a+VmCdzN/ajJj1/+7eKFdq5xjbSAB8JflPwiewnZ5SpK4w45P74GMd +ySo5Ek7NRHXnHZ8AV//XbcSqshsL3Xn2/Uv6YWG1VgolbzTV7RcE0G/nniIgXwmh +s0/xuKUCgYEA4Ghk4hGX5nMPcdSsF1HGQWR6gy7PZAQiUXjC1FVoOgb1DfJr6xsK +DSNWoxnOCpV4Kw4arbFyrutTX8FtJYBIRXg2tY+hGJSO4X4TRP3Dv6r8sMKLIpWb +TmjiVijD9iio+cpeqYXpJrEj88UQ9QII6vVTq/IVVoEx+5T3D8/I+o8CgYEAx7XY +vncwxSK5pXpOFi2OuP9QoPxQEOODLHNYJlnM4sUR2fBx9oIrJrsbu5W4UPAWTfBj +stLMjnPvwIyW/I8nKralxNYo1DG2L0aSrB5T3MIlKWEcTaRMebEOrAhaijObnDJG +m79Guz4CVzDPslVjhmRFRToD+mR+x4h5TjWaIF8CgYEAmAZhAb4Fd/tO5UC8bPfb +JYXacXCO0yTx0tvKsWpCt7zq2s32SkoBHzFnigr7SLRFunVNoYnrNZD65I33UUZ8 +r4NnHMz2x94shZqRl1WK/RfrJBxHgeB0XEQ1wUTQrLyS7NYqFxI/BxVOU+CXQkRk +ojgcvQm9ZuMTZ2pdjXqonwUCgYAWugj6U9IG/RanUC3GtFSDlPp194CdC2cIDfBA +HQQF4mtPo980MEf81lonlLgu7cN8BxkxZm/E3kiwXs9n2lqYr8RZjA2FaErVQnC6 +iZD9lFJqTRTNeR8C0jVbOnAjPhA9TDNg0fmYoUve5D0ejD0RNCP15s5BFmKfDlbP +oaXyfQKBgQCoZBBF9IE67CtvusTL8sC3RlkmEWgOnMQy2B/shHuhBUqQEeBAvyQN +vq+8DDvJ3jSDb1kdXaHsl4YXbst4tZ5f2fJWavegJMzuHteTYIO7qj7fB9wWqFWp +AQggfmRK8zX3+sMmDrLa5xx8NrsM59ir3SGIOqnpJguAcAxiKtctLQ== +-----END RSA PRIVATE KEY----- diff --git a/internal/exec/exec.go b/internal/exec/exec.go index 542e0460..bc8d172c 100644 --- a/internal/exec/exec.go +++ b/internal/exec/exec.go @@ -56,7 +56,7 @@ type Runner interface { Lint(args []string, listAllLinters bool, listLinters bool, listAllLintGroups bool, listLintGroup string, diffLintGroups string) error Format(args []string, overwrite, diffMode, lintMode, fix bool) error All(args []string, disableFormat, disableLint, fix bool) error - GRPC(args, headers []string, address, method, data, callTimeout, connectTimeout, keepaliveTime string, stdin bool, details bool) error + GRPC(args, headers []string, address, method, data, callTimeout, connectTimeout, keepaliveTime string, stdin bool, details bool, tls bool, insecure bool, cacert string, cert string, key string, serverName string) error InspectPackages(args []string) error InspectPackageDeps(args []string, name string) error InspectPackageImporters(args []string, name string) error diff --git a/internal/exec/runner.go b/internal/exec/runner.go index c359e27c..b087753e 100644 --- a/internal/exec/runner.go +++ b/internal/exec/runner.go @@ -523,7 +523,7 @@ func (r *runner) All(args []string, disableFormat, disableLint, fixFlag bool) er return nil } -func (r *runner) GRPC(args, headers []string, address, method, data, callTimeout, connectTimeout, keepaliveTime string, stdin bool, details bool) error { +func (r *runner) GRPC(args, headers []string, address, method, data, callTimeout, connectTimeout, keepaliveTime string, stdin bool, details bool, tls bool, insecure bool, cacert string, cert string, key string, serverName string) error { if address == "" { return newExitErrorf(255, "must set address") } @@ -536,6 +536,15 @@ func (r *runner) GRPC(args, headers []string, address, method, data, callTimeout if data != "" && stdin { return newExitErrorf(255, "must set only one of data or stdin") } + if tls { + if insecure && (cacert != "" || cert != "" || key != "" || serverName != "") { + return newExitErrorf(255, "if insecure then cacert, cert, key, and server-name must not be specified") + } else if (cert != "") != (key != "") { + return newExitErrorf(255, "if cert is specified, key must be specified") + } + } else if insecure || cacert != "" || cert != "" || key != "" || serverName != "" { + return newExitErrorf(255, "tls must be specified if insecure, cacert, cert, key or server-name are specified") + } reader := r.getInputReader(data, stdin) parsedHeaders := make(map[string]string) @@ -587,6 +596,12 @@ func (r *runner) GRPC(args, headers []string, address, method, data, callTimeout parsedConnectTimeout, parsedKeepaliveTime, details, + tls, + insecure, + cacert, + cert, + key, + serverName, ).Invoke(fileDescriptorSets.Unwrap(), address, method, reader, r.output) } @@ -968,6 +983,12 @@ func (r *runner) newGRPCHandler( connectTimeout time.Duration, keepaliveTime time.Duration, details bool, + tls bool, + insecure bool, + cacert string, + cert string, + key string, + serverName string, ) grpc.Handler { handlerOptions := []grpc.HandlerOption{ grpc.HandlerWithLogger(r.logger), @@ -987,6 +1008,9 @@ func (r *runner) newGRPCHandler( if details { handlerOptions = append(handlerOptions, grpc.HandlerWithDetails()) } + if tls { + handlerOptions = append(handlerOptions, grpc.HandlerWithTLS(insecure, cacert, cert, key, serverName)) + } return grpc.NewHandler(handlerOptions...) } diff --git a/internal/grpc/BUILD.bazel b/internal/grpc/BUILD.bazel index e6099c60..ffa7423e 100644 --- a/internal/grpc/BUILD.bazel +++ b/internal/grpc/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "@com_github_jhump_protoreflect//desc:go_default_library", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//keepalive:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", "@org_golang_google_grpc//status:go_default_library", diff --git a/internal/grpc/grpc.go b/internal/grpc/grpc.go index 5ac0ebbf..f0cc9e27 100644 --- a/internal/grpc/grpc.go +++ b/internal/grpc/grpc.go @@ -102,6 +102,18 @@ func HandlerWithHeader(key string, value string) HandlerOption { } } +// HandlerWithTLS returns a HandlerOption that enables TLS connections to the remote host with the given configuration attributes. +func HandlerWithTLS(insecure bool, cacert string, cert string, key string, serverName string) HandlerOption { + return func(handler *handler) { + handler.tls = true + handler.insecure = insecure + handler.cacert = cacert + handler.cert = cert + handler.key = key + handler.serverName = serverName + } +} + // NewHandler returns a new Handler. func NewHandler(options ...HandlerOption) Handler { return newHandler(options...) diff --git a/internal/grpc/handler.go b/internal/grpc/handler.go index 0d4ff5b9..b143b489 100644 --- a/internal/grpc/handler.go +++ b/internal/grpc/handler.go @@ -36,6 +36,7 @@ import ( "github.com/uber/prototool/internal/desc" "go.uber.org/zap" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/keepalive" ) @@ -46,6 +47,12 @@ type handler struct { keepaliveTime time.Duration headers []string details bool + tls bool + insecure bool + cacert string + cert string + key string + serverName string } func newHandler(options ...HandlerOption) *handler { @@ -98,7 +105,11 @@ func (h *handler) dial(address string) (*grpc.ClientConn, error) { if err != nil { return nil, fmt.Errorf("grpc dial: %v", err) } - return grpcurl.BlockingDial(ctx, network, address, nil, h.getDialOptions()...) + creds, err := h.getClientTransportCredentials() + if err != nil { + return nil, fmt.Errorf("grpc credentials: %v", err) + } + return grpcurl.BlockingDial(ctx, network, address, creds, h.getDialOptions()...) } func getNetworkAddress(address string) (string, string, error) { @@ -114,6 +125,22 @@ func getNetworkAddress(address string) (string, string, error) { } } +func (h *handler) getClientTransportCredentials() (credentials.TransportCredentials, error) { + if !h.tls { + return nil, nil + } + creds, err := grpcurl.ClientTransportCredentials(h.insecure, h.cacert, h.cert, h.key) + if err != nil { + return nil, err + } + if h.serverName != "" { + if err := creds.OverrideServerName(h.serverName); err != nil { + return nil, err + } + } + return creds, nil +} + func (h *handler) getDialOptions() []grpc.DialOption { var dialOptions []grpc.DialOption if h.keepaliveTime != 0 {