-
Notifications
You must be signed in to change notification settings - Fork 802
/
GrpcServerProperties.java
473 lines (423 loc) · 18.5 KB
/
GrpcServerProperties.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
/*
* Copyright (c) 2016-2023 The gRPC-Spring Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.devh.boot.grpc.server.config;
import static net.devh.boot.grpc.common.security.KeyStoreUtils.FORMAT_AUTODETECT;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.boot.convert.DurationUnit;
import org.springframework.core.io.Resource;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
import io.grpc.ServerBuilder;
import io.grpc.internal.GrpcUtil;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;
import lombok.Data;
import net.devh.boot.grpc.common.security.KeyStoreUtils;
import net.devh.boot.grpc.common.util.GrpcUtils;
import net.devh.boot.grpc.common.util.SocketUtils;
/**
* The properties for the gRPC server that will be started as part of the application.
*
* @author Michael (yidongnan@gmail.com)
* @since 5/17/16
*/
@Data
@ConfigurationProperties("grpc.server")
@SuppressWarnings("javadoc")
public class GrpcServerProperties {
/**
* A constant that defines, that the server should listen to any IPv4 and IPv6 address.
*/
public static final String ANY_IP_ADDRESS = "*";
/**
* A constant that defines, that the server should listen to any IPv4 address.
*/
public static final String ANY_IPv4_ADDRESS = "0.0.0.0";
/**
* A constant that defines, that the server should listen to any IPv6 address.
*/
public static final String ANY_IPv6_ADDRESS = "::";
/**
* Bind address for the server. Defaults to {@link #ANY_IP_ADDRESS "*"}. Alternatively you can restrict this to
* {@link #ANY_IPv4_ADDRESS "0.0.0.0"} or {@link #ANY_IPv6_ADDRESS "::"}. Or restrict it to exactly one IP address.
* On unix systems it is also possible to prefix it with {@link GrpcUtils#DOMAIN_SOCKET_ADDRESS_PREFIX unix:} to use
* domain socket addresses/paths (Additional dependencies may be required).
*
* @param address The address to bind to.
* @return The address the server should bind to.
*/
private String address = ANY_IP_ADDRESS;
/**
* Server port to listen on. Defaults to {@code 9090}. If set to {@code 0} a random available port will be selected
* and used. Use {@code -1} to disable the inter-process server (for example if you only want to use the in-process
* server).
*
* @param port The port the server should listen on.
* @return The port the server will listen on.
*/
private int port = 9090;
/**
* The name of the in-process server. If not set, then the in process server won't be started.
*
* @param inProcessName The name of the in-process server.
* @return The name of the in-process server or null if isn't configured.
*/
private String inProcessName;
/**
* The time to wait for the server to gracefully shutdown (completing all requests after the server started to
* shutdown). If set to a negative value, the server waits forever. If set to {@code 0} the server will force
* shutdown immediately. Defaults to {@code 30s}.
*
* @param shutdownGracePeriod The time to wait for a graceful shutdown.
* @return The time to wait for a graceful shutdown.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration shutdownGracePeriod = Duration.of(30, ChronoUnit.SECONDS);
/**
* Setting to enable keepAlive. Default to {@code false}.
*
* @param enableKeepAlive Whether keep alive should be enabled.
* @return True, if keep alive should be enabled. False otherwise.
*/
private boolean enableKeepAlive = false;
/**
* The default delay before we send a keepAlives. Defaults to {@code 2h}. Default unit {@link ChronoUnit#SECONDS
* SECONDS}.
*
* @see #setEnableKeepAlive(boolean)
* @see NettyServerBuilder#keepAliveTime(long, TimeUnit)
*
* @param keepAliveTime The new default delay before sending keepAlives.
* @return The default delay before sending keepAlives.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration keepAliveTime = Duration.of(2, ChronoUnit.HOURS);
/**
* The default timeout for a keepAlives ping request. Defaults to {@code 20s}. Default unit
* {@link ChronoUnit#SECONDS SECONDS}.
*
* @see #setEnableKeepAlive(boolean)
* @see NettyServerBuilder#keepAliveTimeout(long, TimeUnit)
*
* @param keepAliveTimeout Sets the default timeout for a keepAlives ping request.
* @return The default timeout for a keepAlives ping request.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration keepAliveTimeout = Duration.of(20, ChronoUnit.SECONDS);
/**
* Specify the most aggressive keep-alive time clients are permitted to configure. Defaults to {@code 5min}. Default
* unit {@link ChronoUnit#SECONDS SECONDS}.
*
* @see NettyServerBuilder#permitKeepAliveTime(long, TimeUnit)
*
* @param permitKeepAliveTime The most aggressive keep-alive time clients are permitted to configure.
* @return The most aggressive keep-alive time clients are permitted to configure.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration permitKeepAliveTime = Duration.of(5, ChronoUnit.MINUTES);
/**
* Whether clients are allowed to send keep-alive HTTP/2 PINGs even if there are no outstanding RPCs on the
* connection. Defaults to {@code false}.
*
* @see NettyServerBuilder#permitKeepAliveWithoutCalls(boolean)
*
* @param permitKeepAliveWithoutCalls Whether to allow clients to send keep-alive requests without calls.
* @return True, if clients are allowed to send keep-alive requests without calls. False otherwise.
*/
@DurationUnit(ChronoUnit.SECONDS)
private boolean permitKeepAliveWithoutCalls = false;
/**
* Specify a max connection idle time. Defaults to disabled. Default unit {@link ChronoUnit#SECONDS SECONDS}.
*
* @see NettyServerBuilder#maxConnectionIdle(long, TimeUnit)
*
* @param maxConnectionIdle The max connection idle time.
* @return The max connection idle time.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration maxConnectionIdle = null;
/**
* Specify a max connection age. Defaults to disabled. Default unit {@link ChronoUnit#SECONDS SECONDS}.
*
* @see NettyServerBuilder#maxConnectionAge(long, TimeUnit)
*
* @param maxConnectionAge The max connection age.
* @return The max connection age.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration maxConnectionAge = null;
/**
* Specify a grace time for the graceful max connection age termination. Defaults to disabled. Default unit
* {@link ChronoUnit#SECONDS SECONDS}.
*
* @see NettyServerBuilder#maxConnectionAgeGrace(long, TimeUnit)
*
* @param maxConnectionAgeGrace The max connection age grace time.
* @return The max connection age grace time.
*/
@DurationUnit(ChronoUnit.SECONDS)
private Duration maxConnectionAgeGrace = null;
/**
* The maximum message size allowed to be received by the server. If not set ({@code null}) then
* {@link GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE gRPC's default} should be used.
*
* @return The maximum message size allowed.
*/
@DataSizeUnit(DataUnit.BYTES)
private DataSize maxInboundMessageSize = null;
/**
* The maximum size of metadata allowed to be received. If not set ({@code null}) then
* {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE gRPC's default} should be used.
*
* @return The maximum metadata size allowed.
*/
@DataSizeUnit(DataUnit.BYTES)
private DataSize maxInboundMetadataSize = null;
/**
* Whether gRPC health service is enabled or not. Defaults to {@code true}.
*
* @param healthServiceEnabled Whether gRPC health service is enabled.
* @return True, if the health service is enabled. False otherwise.
*/
private boolean healthServiceEnabled = true;
/**
* Whether proto reflection service is enabled or not. Defaults to {@code true}.
*
* @param reflectionServiceEnabled Whether gRPC reflection service is enabled.
* @return True, if the reflection service is enabled. False otherwise.
*/
private boolean reflectionServiceEnabled = true;
/**
* Security options for transport security. Defaults to disabled. We strongly recommend to enable this though.
*
* @return The security options for transport security.
*/
private final Security security = new Security();
/**
* The security configuration for the gRPC server.
*/
@Data
public static class Security {
/**
* Flag that controls whether transport security is used. Defaults to {@code false}. If {@code true}, either set
* {@link #certificateChain} and {@link #privateKey}, or {@link #keyStore}.
*
* @param enabled Whether transport security should be enabled.
* @return True, if transport security should be enabled. False otherwise.
*/
private boolean enabled = false;
/**
* The resource containing the SSL certificate chain. Use is combination with {@link #privateKey}. Cannot be
* used in conjunction with {@link #keyStore}.
*
* @see GrpcSslContexts#forServer(InputStream, InputStream, String)
*
* @param certificateChain The certificate chain resource.
* @return The certificate chain resource or null.
*/
private Resource certificateChain = null;
/**
* The resource containing the private key. Use in combination with {@link #certificateChain}. Cannot be used in
* conjunction with {@link #keyStore}.
*
* @see GrpcSslContexts#forServer(InputStream, InputStream, String)
*
* @param privateKey The private key resource.
* @return The private key resource or null.
*/
private Resource privateKey = null;
/**
* Password for the private key. Use is combination with {@link #privateKey}.
*
* @see GrpcSslContexts#forServer(File, File, String)
*
* @param privateKeyPassword The password for the private key.
* @return The password for the private key or null.
*/
private String privateKeyPassword = null;
/**
* The format of the {@link #keyStore}.
*
* <p>
* Possible values includes:
* </p>
* <ul>
* <li>{@link KeyStoreUtils#FORMAT_AUTODETECT AUTODETECT} (default)</li>
* <li>{@code JKS} ({@code .jks})</li>
* <li>{@code PKCS12} ({@code .p12})</li>
* <li>any supported {@link KeyStore} format</li>
* <li>Fallback to {@code KeyStore#getDefaultType()}</li>
* </ul>
*
* @param keyStoreFormat The trust store format to use.
* @return The trust store format to use.
*/
private String keyStoreFormat = FORMAT_AUTODETECT;
/**
* The resource containing the key store. Cannot be used in conjunction with {@link #privateKey}.
*
* @param keyStore The key store resource.
* @return The key store resource or null.
*/
private Resource keyStore = null;
/**
* Password for the key store. Use is combination with {@link #keyStore}.
*
* @param keyStorePassword The password for the key store.
* @return The password for the key store or null.
*/
private String keyStorePassword = null;
/**
* Whether the client has to authenticate himself via certificates. Can be either of {@link ClientAuth#NONE
* NONE}, {@link ClientAuth#OPTIONAL OPTIONAL} or {@link ClientAuth#REQUIRE REQUIRE}. Defaults to
* {@link ClientAuth#NONE}.
*
* @see SslContextBuilder#clientAuth(io.grpc.netty.shaded.io.netty.handler.ssl.ClientAuth)
* SslContextBuilder#clientAuth(ClientAuth)
*
* @param clientAuth Whether the client has to authenticate himself via certificates.
* @return Whether the client has to authenticate himself via certificates.
*/
private ClientAuth clientAuth = ClientAuth.NONE;
/**
* The resource containing the trusted certificate collection. Cannot be used in conjunction with
* {@link #trustStore}. If neither this nor {@link #trustCertCollection} is set then the system's trust store
* will be used.
*
* @see SslContextBuilder#trustManager(InputStream)
*
* @param trustCertCollection The trusted certificate collection resource.
* @return The trusted certificate collection resource or null.
*/
private Resource trustCertCollection = null;
/**
* The format of the {@link #trustStore}.
*
* <p>
* Possible values includes:
* </p>
* <ul>
* <li>{@link KeyStoreUtils#FORMAT_AUTODETECT AUTODETECT} (default)</li>
* <li>{@code JKS} ({@code .jks})</li>
* <li>{@code PKCS12} ({@code .p12})</li>
* <li>any supported {@link KeyStore} format</li>
* <li>Fallback to {@code KeyStore#getDefaultType()}</li>
* </ul>
*
* @param trustStoreFormat The trust store format to use.
* @return The trust store format to use.
*/
private String trustStoreFormat = FORMAT_AUTODETECT;
/**
* The resource containing the trust store. Cannot be used in conjunction with {@link #trustCertCollection}. If
* neither this nor {@link #trustCertCollection} is set then the system's trust store will be used.
*
* @param trustStore The trust store resource.
* @return The trust store resource or null.
*/
private Resource trustStore = null;
/**
* Password for the trust store. Use is combination with {@link #trustStore}.
*
* @param trustStorePassword The password for the trust store.
* @return The password for the trust store or null.
*/
private String trustStorePassword = null;
/**
* Specifies the cipher suite. If {@code null} or empty it will use the system's default cipher suite.
*
* @param ciphers List of allowed ciphers
* @return The cipher suite accepted for secure connections or null.
*/
private List<String> ciphers = null;
public void setCiphers(final String ciphers) {
this.ciphers = Arrays.asList(ciphers.split("[ :,]"));
}
/**
* Specifies the protocols accepted for secure connections. If {@code null} or empty it will use the system's
* default (all supported) protocols.
*
* @param protocols Protocol list consisting of one or more protocols separated by colons, commas or spaces.
* @return The protocols accepted for secure connections or null.
*/
private String[] protocols = null;
public void setProtocols(final String protocols) {
this.protocols = protocols.split("[ :,]");
}
}
/**
* Gets the port the server should listen on. Defaults to {@code 9090}. If set to {@code 0} a random available port
* will be selected and used.
*
* @return The server port to listen to.
*
* @see #setPort(int)
*/
public int getPort() {
if (this.port == 0) {
this.port = SocketUtils.findAvailableTcpPort();
}
return this.port;
}
/**
* Sets the maximum message size allowed to be received by the server. If not set ({@code null}) then it will
* default to {@link GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE gRPC's default}. If set to {@code -1} then it will use the
* highest possible limit (not recommended).
*
* @param maxInboundMessageSize The new maximum size allowed for incoming messages. {@code -1} for max possible.
* Null to use the gRPC's default.
*
* @see ServerBuilder#maxInboundMessageSize(int)
*/
public void setMaxInboundMessageSize(final DataSize maxInboundMessageSize) {
if (maxInboundMessageSize == null || maxInboundMessageSize.toBytes() >= 0) {
this.maxInboundMessageSize = maxInboundMessageSize;
} else if (maxInboundMessageSize.toBytes() == -1) {
this.maxInboundMessageSize = DataSize.ofBytes(Integer.MAX_VALUE);
} else {
throw new IllegalArgumentException("Unsupported maxInboundMessageSize: " + maxInboundMessageSize);
}
}
/**
* Sets the maximum metadata size allowed to be received by the server. If not set ({@code null}) then it will
* default to {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE gRPC's default}. If set to {@code -1} then it will use
* the highest possible limit (not recommended).
*
* @param maxInboundMetadataSize The new maximum size allowed for incoming metadata. {@code -1} for max possible.
* Null to use the gRPC's default.
*
* @see ServerBuilder#maxInboundMetadataSize(int)
*/
public void setMaxInboundMetadataSize(final DataSize maxInboundMetadataSize) {
if (maxInboundMetadataSize == null || maxInboundMetadataSize.toBytes() >= 0) {
this.maxInboundMetadataSize = maxInboundMetadataSize;
} else if (maxInboundMetadataSize.toBytes() == -1) {
this.maxInboundMetadataSize = DataSize.ofBytes(Integer.MAX_VALUE);
} else {
throw new IllegalArgumentException("Unsupported maxInboundMetadataSize: " + maxInboundMetadataSize);
}
}
}