1 // Encapsulates common RPC server setup.
14 "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
15 "golang.org/x/net/http2"
16 "golang.org/x/net/trace"
17 "google.golang.org/grpc"
18 "google.golang.org/grpc/credentials"
22 requireClientAuth
= flag
.Bool("tls_require_client_auth",
24 "Require TLS Client Authentication")
28 // Disable grpc tracing until
29 // https://github.com/grpc/grpc-go/issues/695 is fixed.
30 grpc
.EnableTracing
= false
33 // grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC
34 // connections or otherHandler otherwise. Copied from cockroachdb.
35 func grpcHandlerFunc(grpcServer
*grpc
.Server
, otherHandler http
.Handler
) http
.Handler
{
36 return http
.HandlerFunc(func(w http
.ResponseWriter
, r
*http
.Request
) {
37 // This is a partial recreation of gRPC's internal checks:
38 // https://github.com/grpc/grpc-go/blob/7834b974e55fbf85a5b01afb5821391c71084efd/transport/handler_server.go#L61
39 if r
.ProtoMajor
== 2 && strings
.Contains(r
.Header
.Get("Content-Type"), "application/grpc") {
40 grpcServer
.ServeHTTP(w
, r
)
42 otherHandler
.ServeHTTP(w
, r
)
47 func DialTLS(addr
, certFile
, keyFile
string) (*grpc
.ClientConn
, error
) {
48 cert
, err
:= tls
.LoadX509KeyPair(certFile
, keyFile
)
52 roots
:= x509
.NewCertPool()
53 contents
, err
:= ioutil
.ReadFile(certFile
)
57 if !roots
.AppendCertsFromPEM(contents
) {
58 return nil, fmt
.Errorf("Could not parse %q as PEM file (contents: %q)", certFile
, contents
)
60 auth
:= credentials
.NewTLS(&tls
.Config
{
62 Certificates
: []tls
.Certificate
{cert
}})
64 return grpc
.Dial(addr
,
65 grpc
.WithTransportCredentials(auth
),
66 grpc
.WithStreamInterceptor(grpc_opentracing
.StreamClientInterceptor()),
67 grpc
.WithUnaryInterceptor(grpc_opentracing
.UnaryClientInterceptor()))
70 func ListenAndServeTLS(addr
, certFile
, keyFile
string, register
func(s
*grpc
.Server
)) error
{
71 ln
, err
:= net
.Listen("tcp", addr
)
76 auth
, err
:= credentials
.NewServerTLSFromFile(certFile
, keyFile
)
83 grpc
.StreamInterceptor(grpc_opentracing
.StreamServerInterceptor()),
84 grpc
.UnaryInterceptor(grpc_opentracing
.UnaryServerInterceptor()))
92 Handler
: grpcHandlerFunc(s
, http
.DefaultServeMux
),
94 if err
:= http2
.ConfigureServer(&srv
, nil); err
!= nil {
97 roots
:= x509
.NewCertPool()
98 contents
, err
:= ioutil
.ReadFile(certFile
)
102 if !roots
.AppendCertsFromPEM(contents
) {
103 return fmt
.Errorf("Could not parse %q as PEM file (contents: %q)", certFile
, contents
)
106 if *requireClientAuth
{
107 srv
.TLSConfig
.ClientCAs
= roots
108 srv
.TLSConfig
.ClientAuth
= tls
.RequireAndVerifyClientCert
109 trace
.AuthRequest
= func(req
*http
.Request
) (bool, bool) {
113 srv
.TLSConfig
.Certificates
= make([]tls
.Certificate
, 1)
114 srv
.TLSConfig
.Certificates
[0], err
= tls
.LoadX509KeyPair(certFile
, keyFile
)
115 return srv
.Serve(tls
.NewListener(ln
, srv
.TLSConfig
))