Skip to content

Commit 6c45ffa

Browse files
committed
FAB-1259 Create Basic Common GRPC Server
This is the initial phase of creating a common GRPC server object to handle common operations such as TLS. This change set provides a basic GRPC server object and functions to create plain and TLS enabled GRPC servers Fixes FAB-1259 Change-Id: Ic63bec9e8747083016dbcddab06f1061903d5a59 Signed-off-by: Gari Singh <[email protected]>
1 parent bc1d8ae commit 6c45ffa

File tree

6 files changed

+787
-0
lines changed

6 files changed

+787
-0
lines changed

core/comm/server.go

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package comm
18+
19+
import (
20+
"crypto/tls"
21+
"crypto/x509"
22+
"errors"
23+
"net"
24+
25+
"google.golang.org/grpc"
26+
"google.golang.org/grpc/credentials"
27+
)
28+
29+
//GRPCServer defines an interface representing a GRPC-based server
30+
type GRPCServer interface {
31+
//Address returns the listen address for the GRPCServer
32+
Address() string
33+
//Start starts the underlying grpc.Server
34+
Start() error
35+
//Stop stops the underlying grpc.Server
36+
Stop()
37+
//Server returns the grpc.Server instance for the GRPCServer
38+
Server() *grpc.Server
39+
//Listener returns the net.Listener instance for the GRPCServer
40+
Listener() net.Listener
41+
//ServerCertificate returns the tls.Certificate used by the grpc.Server
42+
ServerCertificate() tls.Certificate
43+
//TLSEnabled is a flag indicating whether or not TLS is enabled for this GRPCServer instance
44+
TLSEnabled() bool
45+
}
46+
47+
type grpcServerImpl struct {
48+
//Listen address for the server specified as hostname:port
49+
address string
50+
//Listener for handling network requests
51+
listener net.Listener
52+
//GRPC server
53+
server *grpc.Server
54+
//Certificate presented by the server for TLS communication
55+
serverCertificate tls.Certificate
56+
//Key used by the server for TLS communication
57+
serverKeyPEM []byte
58+
//List of certificate authorities to optionally pass to the client during the TLS handshake
59+
serverRootCAs []tls.Certificate
60+
//List of certificate authorities to be used to authenticate clients if client authentication is required
61+
clientRootCAs *x509.CertPool
62+
//Is TLS enabled?
63+
tlsEnabled bool
64+
}
65+
66+
/*
67+
NewGRPCServer creates a new implementation of a GRPCServer given a listen address.
68+
In order to enable TLS, serverKey and ServerCertificate are required.
69+
70+
Parameters:
71+
address: Listen address to use formatted as hostname:port
72+
serverKey: PEM-encoded private key to be used by the server for TLS communication
73+
serverCertificate: PEM-encoded X509 public key to be used by the server for TLS communication
74+
serverRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to optionally send as part of
75+
the server handshake
76+
clientRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to use when verifying client
77+
certificates
78+
*/
79+
func NewGRPCServer(address string, serverKey []byte, serverCertificate []byte, serverRootCAs [][]byte,
80+
clientRootCAs [][]byte) (GRPCServer, error) {
81+
82+
if address == "" {
83+
return nil, errors.New("Missing address parameter")
84+
}
85+
//create our listener
86+
lis, err := net.Listen("tcp", address)
87+
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
return NewGRPCServerFromListener(lis, serverKey, serverCertificate, serverRootCAs, clientRootCAs)
93+
94+
}
95+
96+
/*
97+
NewGRPCServerFromListener creates a new implementation of a GRPCServer given an existing Listener instance.
98+
In order to enable TLS, serverKey and ServerCertificate are required.
99+
100+
Parameters:
101+
listener: Listener to use
102+
serverKey: PEM-encoded private key to be used by the server for TLS communication
103+
serverCertificate: PEM-encoded X509 public key to be used by the server for TLS communication
104+
serverRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to optionally send as part of
105+
the server handshake
106+
clientRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to use when verifying client
107+
certificates
108+
*/
109+
func NewGRPCServerFromListener(listener net.Listener, serverKey []byte, serverCertificate []byte,
110+
serverRootCAs [][]byte, clientRootCAs [][]byte) (GRPCServer, error) {
111+
112+
grpcServer := &grpcServerImpl{
113+
address: listener.Addr().String(),
114+
listener: listener,
115+
}
116+
117+
//set up our server options
118+
var serverOpts []grpc.ServerOption
119+
//check for TLS parameters
120+
if serverKey != nil || serverCertificate != nil {
121+
//both are required
122+
if serverKey != nil && serverCertificate != nil {
123+
grpcServer.tlsEnabled = true
124+
//load server public and private keys
125+
cert, err := tls.X509KeyPair(serverCertificate, serverKey)
126+
if err != nil {
127+
return nil, err
128+
}
129+
grpcServer.serverCertificate = cert
130+
131+
//set up our TLS config
132+
133+
//base server certificate
134+
certificates := []tls.Certificate{grpcServer.serverCertificate}
135+
136+
/**
137+
//if we have server root CAs append them
138+
if len(serverRootCAs) > 0 {
139+
//certificates = append(certificates, serverRootCAs...)
140+
}
141+
142+
//if we have client root CAs, create a certPool
143+
if len(clientRootCAs) > 0 {
144+
grpcServer.clientRootCAs = x509.NewCertPool()
145+
}
146+
*/
147+
tlsConfig := &tls.Config{
148+
Certificates: certificates,
149+
}
150+
151+
//create credentials
152+
creds := credentials.NewTLS(tlsConfig)
153+
154+
//add to server options
155+
serverOpts = append(serverOpts, grpc.Creds(creds))
156+
157+
} else {
158+
return nil, errors.New("Both serverKey and serverCertificate are required in order to enable TLS")
159+
}
160+
}
161+
162+
grpcServer.server = grpc.NewServer(serverOpts...)
163+
164+
return grpcServer, nil
165+
}
166+
167+
//Address returns the listen address for this GRPCServer instance
168+
func (gServer *grpcServerImpl) Address() string {
169+
return gServer.address
170+
}
171+
172+
//Listener returns the net.Listener for the GRPCServer instance
173+
func (gServer *grpcServerImpl) Listener() net.Listener {
174+
return gServer.listener
175+
}
176+
177+
//Server returns the grpc.Server for the GRPCServer instance
178+
func (gServer *grpcServerImpl) Server() *grpc.Server {
179+
return gServer.server
180+
}
181+
182+
//ServerCertificate returns the tls.Certificate used by the grpc.Server
183+
func (gServer *grpcServerImpl) ServerCertificate() tls.Certificate {
184+
return gServer.serverCertificate
185+
}
186+
187+
//TLSEnabled is a flag indicating whether or not TLS is enabled for the GRPCServer instance
188+
func (gServer *grpcServerImpl) TLSEnabled() bool {
189+
return gServer.tlsEnabled
190+
}
191+
192+
//Start starts the underlying grpc.Server
193+
func (gServer *grpcServerImpl) Start() error {
194+
return gServer.server.Serve(gServer.listener)
195+
}
196+
197+
//Stop stops the underlying grpc.Server
198+
func (gServer *grpcServerImpl) Stop() {
199+
gServer.server.Stop()
200+
}

0 commit comments

Comments
 (0)