@@ -26,6 +26,25 @@ import (
26
26
"google.golang.org/grpc/credentials"
27
27
)
28
28
29
+ //A SecureServerConfig structure is used to configure security (e.g. TLS) for a
30
+ //GRPCServer instance
31
+ type SecureServerConfig struct {
32
+ //Whether or not to use TLS for communication
33
+ UseTLS bool
34
+ //PEM-encoded X509 public key to be used by the server for TLS communication
35
+ ServerCertificate []byte
36
+ //PEM-encoded private key to be used by the server for TLS communication
37
+ ServerKey []byte
38
+ //Set of PEM-encoded X509 certificate authorities to optionally send
39
+ //as part of the server handshake
40
+ ServerRootCAs [][]byte
41
+ //Whether or not TLS client must present certificates for authentication
42
+ RequireClientCert bool
43
+ //Set of PEM-encoded X509 certificate authorities to use when verifying
44
+ //client certificates
45
+ ClientRootCAs [][]byte
46
+ }
47
+
29
48
//GRPCServer defines an interface representing a GRPC-based server
30
49
type GRPCServer interface {
31
50
//Address returns the listen address for the GRPCServer
@@ -40,7 +59,8 @@ type GRPCServer interface {
40
59
Listener () net.Listener
41
60
//ServerCertificate returns the tls.Certificate used by the grpc.Server
42
61
ServerCertificate () tls.Certificate
43
- //TLSEnabled is a flag indicating whether or not TLS is enabled for this GRPCServer instance
62
+ //TLSEnabled is a flag indicating whether or not TLS is enabled for this
63
+ //GRPCServer instance
44
64
TLSEnabled () bool
45
65
}
46
66
@@ -55,29 +75,19 @@ type grpcServerImpl struct {
55
75
serverCertificate tls.Certificate
56
76
//Key used by the server for TLS communication
57
77
serverKeyPEM []byte
58
- //List of certificate authorities to optionally pass to the client during the TLS handshake
78
+ //List of certificate authorities to optionally pass to the client during
79
+ //the TLS handshake
59
80
serverRootCAs []tls.Certificate
60
- //List of certificate authorities to be used to authenticate clients if client authentication is required
81
+ //List of certificate authorities to be used to authenticate clients if
82
+ //client authentication is required
61
83
clientRootCAs * x509.CertPool
62
84
//Is TLS enabled?
63
85
tlsEnabled bool
64
86
}
65
87
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 ) {
88
+ //NewGRPCServer creates a new implementation of a GRPCServer given a
89
+ //listen address.
90
+ func NewGRPCServer (address string , secureConfig SecureServerConfig ) (GRPCServer , error ) {
81
91
82
92
if address == "" {
83
93
return nil , errors .New ("Missing address parameter" )
@@ -89,25 +99,13 @@ func NewGRPCServer(address string, serverKey []byte, serverCertificate []byte, s
89
99
return nil , err
90
100
}
91
101
92
- return NewGRPCServerFromListener (lis , serverKey , serverCertificate , serverRootCAs , clientRootCAs )
102
+ return NewGRPCServerFromListener (lis , secureConfig )
93
103
94
104
}
95
105
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 ) {
106
+ //NewGRPCServerFromListener creates a new implementation of a GRPCServer given
107
+ //an existing net.Listener instance.
108
+ func NewGRPCServerFromListener (listener net.Listener , secureConfig SecureServerConfig ) (GRPCServer , error ) {
111
109
112
110
grpcServer := & grpcServerImpl {
113
111
address : listener .Addr ().String (),
@@ -116,13 +114,13 @@ func NewGRPCServerFromListener(listener net.Listener, serverKey []byte, serverCe
116
114
117
115
//set up our server options
118
116
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 {
117
+ //check secureConfig
118
+ if secureConfig . UseTLS {
119
+ //both key and cert are required
120
+ if secureConfig . ServerKey != nil && secureConfig . ServerCertificate != nil {
123
121
grpcServer .tlsEnabled = true
124
122
//load server public and private keys
125
- cert , err := tls .X509KeyPair (serverCertificate , serverKey )
123
+ cert , err := tls .X509KeyPair (secureConfig . ServerCertificate , secureConfig . ServerKey )
126
124
if err != nil {
127
125
return nil , err
128
126
}
@@ -132,21 +130,24 @@ func NewGRPCServerFromListener(listener net.Listener, serverKey []byte, serverCe
132
130
133
131
//base server certificate
134
132
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
133
tlsConfig := & tls.Config {
148
134
Certificates : certificates ,
149
135
}
136
+ //checkif client authentication is required
137
+ if secureConfig .RequireClientCert {
138
+ //require TLS client auth
139
+ tlsConfig .ClientAuth = tls .RequireAndVerifyClientCert
140
+ //if we have client root CAs, create a certPool
141
+ if len (secureConfig .ClientRootCAs ) > 0 {
142
+ grpcServer .clientRootCAs = x509 .NewCertPool ()
143
+ for _ , clientRootCA := range secureConfig .ClientRootCAs {
144
+ if ! grpcServer .clientRootCAs .AppendCertsFromPEM (clientRootCA ) {
145
+ return nil , errors .New ("Failed to load client root certificates" )
146
+ }
147
+ }
148
+ tlsConfig .ClientCAs = grpcServer .clientRootCAs
149
+ }
150
+ }
150
151
151
152
//create credentials
152
153
creds := credentials .NewTLS (tlsConfig )
@@ -155,10 +156,10 @@ func NewGRPCServerFromListener(listener net.Listener, serverKey []byte, serverCe
155
156
serverOpts = append (serverOpts , grpc .Creds (creds ))
156
157
157
158
} else {
158
- return nil , errors .New ("Both serverKey and serverCertificate are required in order to enable TLS" )
159
+ return nil , errors .New ("secureConfig must contain both ServerKey and " +
160
+ "ServerCertificate when UseTLS is true" )
159
161
}
160
162
}
161
-
162
163
grpcServer .server = grpc .NewServer (serverOpts ... )
163
164
164
165
return grpcServer , nil
@@ -184,7 +185,8 @@ func (gServer *grpcServerImpl) ServerCertificate() tls.Certificate {
184
185
return gServer .serverCertificate
185
186
}
186
187
187
- //TLSEnabled is a flag indicating whether or not TLS is enabled for the GRPCServer instance
188
+ //TLSEnabled is a flag indicating whether or not TLS is enabled for the
189
+ //GRPCServer instance
188
190
func (gServer * grpcServerImpl ) TLSEnabled () bool {
189
191
return gServer .tlsEnabled
190
192
}
0 commit comments