Skip to content

Commit 33ab3bb

Browse files
seonWKimikhoonjrhee17minwoox
authored
Add TlsEngineType enum (#5029)
Motivation: Add `TlsEngineType` to let users choose the type of tls engine. (Using `Flags`) Modifications: - Add `TlsEngineType` enum - Deprecate `useOpenSsl` Result: - Related to #<[4949](#4949)>. - Related to #4962 (comment) - `TlsEngineType` is added - `useOpenSsl` is deprecated <!-- Visit this URL to learn more about how to write a pull request description: https://armeria.dev/community/developer-guide#how-to-write-pull-request-description --> --------- Co-authored-by: Ikhun Um <[email protected]> Co-authored-by: Ikhun Um <[email protected]> Co-authored-by: jrhee17 <[email protected]> Co-authored-by: minwoox <[email protected]> Co-authored-by: minux <[email protected]>
1 parent c8cc094 commit 33ab3bb

File tree

10 files changed

+208
-53
lines changed

10 files changed

+208
-53
lines changed

core/src/main/java/com/linecorp/armeria/common/DefaultFlagsProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.common.collect.ImmutableSet;
2828

2929
import com.linecorp.armeria.common.util.Sampler;
30+
import com.linecorp.armeria.common.util.TlsEngineType;
3031
import com.linecorp.armeria.common.util.TransportType;
3132
import com.linecorp.armeria.server.TransientServiceOption;
3233

@@ -160,6 +161,11 @@ public Boolean useOpenSsl() {
160161
return true;
161162
}
162163

164+
@Override
165+
public TlsEngineType tlsEngineType() {
166+
return TlsEngineType.OPENSSL;
167+
}
168+
163169
@Override
164170
public Boolean dumpOpenSslInfo() {
165171
return false;

core/src/main/java/com/linecorp/armeria/common/Flags.java

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import com.linecorp.armeria.common.util.Exceptions;
5454
import com.linecorp.armeria.common.util.Sampler;
5555
import com.linecorp.armeria.common.util.SystemInfo;
56+
import com.linecorp.armeria.common.util.TlsEngineType;
5657
import com.linecorp.armeria.common.util.TransportType;
5758
import com.linecorp.armeria.internal.common.FlagsLoaded;
5859
import com.linecorp.armeria.internal.common.util.SslContextUtil;
@@ -107,7 +108,6 @@ public final class Flags {
107108
.sorted(Comparator.comparingInt(FlagsProvider::priority).reversed())
108109
.collect(Collectors.toList());
109110
flagsProviders.add(0, SystemPropertyFlagsProvider.INSTANCE);
110-
flagsProviders.add(DefaultFlagsProvider.INSTANCE);
111111
FLAGS_PROVIDERS = ImmutableList.copyOf(flagsProviders);
112112
}
113113

@@ -190,7 +190,8 @@ private static boolean validateTransportType(TransportType transportType, String
190190
getValue(FlagsProvider::transportType, "transportType", TRANSPORT_TYPE_VALIDATOR);
191191

192192
@Nullable
193-
private static Boolean useOpenSsl;
193+
private static TlsEngineType tlsEngineType;
194+
194195
@Nullable
195196
private static Boolean dumpOpenSslInfo;
196197

@@ -431,7 +432,6 @@ public static Sampler<Class<? extends Throwable>> verboseExceptionSampler() {
431432
* stack trace of the exceptions that are thrown frequently by Armeria.
432433
*
433434
* @see #verboseExceptionSampler()
434-
*
435435
* @deprecated Use {@link #verboseExceptionSampler()} and
436436
* {@code -Dcom.linecorp.armeria.verboseExceptions=<specification>}.
437437
*/
@@ -540,32 +540,67 @@ public static TransportType transportType() {
540540
*
541541
* <p>This flag is enabled by default for supported platforms. Specify the
542542
* {@code -Dcom.linecorp.armeria.useOpenSsl=false} JVM option to disable it.
543+
*
544+
* @deprecated Use {@link #tlsEngineType()} and {@code -Dcom.linecorp.armeria.tlsEngineType=openssl}.
543545
*/
546+
@Deprecated
544547
public static boolean useOpenSsl() {
545-
if (useOpenSsl != null) {
546-
return useOpenSsl;
548+
return tlsEngineType() == TlsEngineType.OPENSSL;
549+
}
550+
551+
/**
552+
* Returns the {@link TlsEngineType} that will be used for processing TLS connections.
553+
*
554+
* <p>The default value of this flag is {@link TlsEngineType#OPENSSL}.
555+
* Specify the {@code -Dcom.linecorp.armeria.tlsEngineType=<jdk|openssl>} JVM option to override
556+
* the default value.
557+
*/
558+
@UnstableApi
559+
public static TlsEngineType tlsEngineType() {
560+
if (tlsEngineType != null) {
561+
return tlsEngineType;
547562
}
548-
setUseOpenSslAndDumpOpenSslInfo();
549-
return useOpenSsl;
563+
detectTlsEngineAndDumpOpenSslInfo();
564+
return tlsEngineType;
550565
}
551566

552-
private static void setUseOpenSslAndDumpOpenSslInfo() {
553-
final boolean useOpenSsl = getValue(FlagsProvider::useOpenSsl, "useOpenSsl");
554-
if (!useOpenSsl) {
555-
// OpenSSL explicitly disabled
556-
Flags.useOpenSsl = false;
557-
dumpOpenSslInfo = false;
558-
return;
567+
private static void detectTlsEngineAndDumpOpenSslInfo() {
568+
569+
final Boolean useOpenSsl = getUserValue(FlagsProvider::useOpenSsl, "useOpenSsl",
570+
ignored -> true);
571+
final TlsEngineType tlsEngineTypeValue = getUserValue(FlagsProvider::tlsEngineType,
572+
"tlsEngineType", ignored -> true);
573+
574+
if (useOpenSsl != null && (useOpenSsl != (tlsEngineTypeValue == TlsEngineType.OPENSSL))) {
575+
logger.warn("useOpenSsl({}) and tlsEngineType({}) are incompatible, tlsEngineType will be used",
576+
useOpenSsl, tlsEngineTypeValue);
577+
}
578+
579+
TlsEngineType preferredTlsEngineType = null;
580+
if (tlsEngineTypeValue != null) {
581+
preferredTlsEngineType = tlsEngineTypeValue;
582+
} else if (useOpenSsl != null) {
583+
preferredTlsEngineType = useOpenSsl ? TlsEngineType.OPENSSL : TlsEngineType.JDK;
584+
}
585+
if (preferredTlsEngineType == TlsEngineType.OPENSSL) {
586+
if (!OpenSsl.isAvailable()) {
587+
final Throwable cause = Exceptions.peel(OpenSsl.unavailabilityCause());
588+
logger.info("OpenSSL not available: {}", cause.toString());
589+
preferredTlsEngineType = TlsEngineType.JDK;
590+
}
591+
}
592+
if (preferredTlsEngineType == null) {
593+
preferredTlsEngineType = OpenSsl.isAvailable() ? TlsEngineType.OPENSSL : TlsEngineType.JDK;
559594
}
560-
if (!OpenSsl.isAvailable()) {
561-
final Throwable cause = Exceptions.peel(OpenSsl.unavailabilityCause());
562-
logger.info("OpenSSL not available: {}", cause.toString());
563-
Flags.useOpenSsl = false;
595+
tlsEngineType = preferredTlsEngineType;
596+
597+
if (tlsEngineType != TlsEngineType.OPENSSL) {
564598
dumpOpenSslInfo = false;
599+
logger.info("Using TLS engine: {}", tlsEngineType);
565600
return;
566601
}
567-
Flags.useOpenSsl = true;
568-
logger.info("Using OpenSSL: {}, 0x{}", OpenSsl.versionString(),
602+
603+
logger.info("Using Tls engine: OpenSSL {}, 0x{}", OpenSsl.versionString(),
569604
Long.toHexString(OpenSsl.version() & 0xFFFFFFFFL));
570605
dumpOpenSslInfo = getValue(FlagsProvider::dumpOpenSslInfo, "dumpOpenSslInfo");
571606
if (dumpOpenSslInfo) {
@@ -590,14 +625,14 @@ private static void setUseOpenSslAndDumpOpenSslInfo() {
590625
* <p>This flag is disabled by default. Specify the {@code -Dcom.linecorp.armeria.dumpOpenSslInfo=true} JVM
591626
* option to enable it.
592627
*
593-
* <p>If {@link #useOpenSsl()} returns {@code false}, this also returns {@code false} no matter you
594-
* specified the JVM option.
628+
* <p>If {@link #tlsEngineType()} does not return {@link TlsEngineType#OPENSSL}, this also returns
629+
* {@code false} no matter what the specified JVM option is.
595630
*/
596631
public static boolean dumpOpenSslInfo() {
597632
if (dumpOpenSslInfo != null) {
598633
return dumpOpenSslInfo;
599634
}
600-
setUseOpenSslAndDumpOpenSslInfo();
635+
detectTlsEngineAndDumpOpenSslInfo();
601636
return dumpOpenSslInfo;
602637
}
603638

@@ -1236,7 +1271,6 @@ public static String dnsCacheSpec() {
12361271
* to override the default value.
12371272
*
12381273
* @see ExceptionVerbosity
1239-
*
12401274
* @deprecated Use {@link LoggingService} or log exceptions using
12411275
* {@link ServerBuilder#errorHandler(ServerErrorHandler)}.
12421276
*/
@@ -1589,24 +1623,37 @@ private static <T> T getValue(Function<FlagsProvider, @Nullable T> method, Strin
15891623

15901624
private static <T> T getValue(Function<FlagsProvider, @Nullable T> method,
15911625
String flagName, Predicate<T> validator) {
1626+
final T t = getUserValue(method, flagName, validator);
1627+
if (t != null) {
1628+
return t;
1629+
}
1630+
1631+
return method.apply(DefaultFlagsProvider.INSTANCE);
1632+
}
1633+
1634+
@Nullable
1635+
private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName,
1636+
Predicate<T> validator) {
15921637
for (FlagsProvider provider : FLAGS_PROVIDERS) {
15931638
try {
15941639
final T value = method.apply(provider);
15951640
if (value == null) {
15961641
continue;
15971642
}
1643+
15981644
if (!validator.test(value)) {
15991645
logger.warn("{}: {} ({}, validation failed)", flagName, value, provider.name());
16001646
continue;
16011647
}
1648+
16021649
logger.info("{}: {} ({})", flagName, value, provider.name());
16031650
return value;
16041651
} catch (Exception ex) {
16051652
logger.warn("{}: ({}, {})", flagName, provider.name(), ex.getMessage());
16061653
}
16071654
}
1608-
// Should never reach here because DefaultFlagsProvider always returns a normal value.
1609-
throw new Error();
1655+
1656+
return null;
16101657
}
16111658

16121659
private Flags() {}

core/src/main/java/com/linecorp/armeria/common/FlagsProvider.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.linecorp.armeria.common.util.Exceptions;
4343
import com.linecorp.armeria.common.util.Sampler;
4444
import com.linecorp.armeria.common.util.SystemInfo;
45+
import com.linecorp.armeria.common.util.TlsEngineType;
4546
import com.linecorp.armeria.common.util.TransportType;
4647
import com.linecorp.armeria.server.HttpService;
4748
import com.linecorp.armeria.server.ServerBuilder;
@@ -198,21 +199,36 @@ default TransportType transportType() {
198199
*
199200
* <p>This flag is enabled by default for supported platforms. Specify the
200201
* {@code -Dcom.linecorp.armeria.useOpenSsl=false} JVM option to disable it.
202+
*
203+
* @deprecated Use {@link #tlsEngineType()} and {@code -Dcom.linecorp.armeria.tlsEngineType=openssl}.
201204
*/
202205
@Nullable
206+
@Deprecated
203207
default Boolean useOpenSsl() {
204208
return null;
205209
}
206210

211+
/**
212+
* Returns the {@link TlsEngineType} that will be used for processing TLS connections.
213+
*
214+
* <p>The default value of this flag is "openssl", which means the {@link TlsEngineType#OPENSSL} will
215+
* be used. Specify the {@code -Dcom.linecorp.armeria.tlsEngineType=<jdk|openssl>} JVM option to override
216+
* the default.</p>
217+
*/
218+
@Nullable
219+
default TlsEngineType tlsEngineType() {
220+
return null;
221+
}
222+
207223
/**
208224
* Returns whether information about the OpenSSL environment should be dumped when first starting the
209225
* application, including supported ciphers.
210226
*
211227
* <p>This flag is disabled by default. Specify the {@code -Dcom.linecorp.armeria.dumpOpenSslInfo=true} JVM
212228
* option to enable it.
213229
*
214-
* <p>If {@link #useOpenSsl()} returns {@code false}, this also returns {@code false} no matter you
215-
* specified the JVM option.
230+
* <p>If {@link #tlsEngineType()} does not return {@link TlsEngineType#OPENSSL}, this also returns
231+
* {@code false} no matter what the specified JVM option is.
216232
*/
217233
@Nullable
218234
default Boolean dumpOpenSslInfo() {

core/src/main/java/com/linecorp/armeria/common/SystemPropertyFlagsProvider.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import com.linecorp.armeria.common.annotation.Nullable;
4040
import com.linecorp.armeria.common.util.InetAddressPredicates;
4141
import com.linecorp.armeria.common.util.Sampler;
42+
import com.linecorp.armeria.common.util.TlsEngineType;
4243
import com.linecorp.armeria.common.util.TransportType;
4344
import com.linecorp.armeria.server.TransientServiceOption;
4445

@@ -148,6 +149,23 @@ public Boolean useOpenSsl() {
148149
return getBoolean("useOpenSsl");
149150
}
150151

152+
@Override
153+
public TlsEngineType tlsEngineType() {
154+
final String strTlsEngineType = getNormalized("tlsEngineType");
155+
if (strTlsEngineType == null) {
156+
return null;
157+
}
158+
switch (strTlsEngineType) {
159+
case "jdk":
160+
return TlsEngineType.JDK;
161+
case "openssl":
162+
return TlsEngineType.OPENSSL;
163+
default:
164+
throw new IllegalArgumentException(
165+
String.format("%s isn't one of 'jdk' or 'openssl'", strTlsEngineType));
166+
}
167+
}
168+
151169
@Override
152170
public Boolean dumpOpenSslInfo() {
153171
return getBoolean("dumpOpenSslInfo");
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2023 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* https://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, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package com.linecorp.armeria.common.util;
18+
19+
import com.linecorp.armeria.common.annotation.UnstableApi;
20+
21+
import io.netty.handler.ssl.SslProvider;
22+
23+
/**
24+
* Tls engine types.
25+
*/
26+
@UnstableApi
27+
public enum TlsEngineType {
28+
/**
29+
* JDK's default implementation.
30+
*/
31+
JDK(SslProvider.JDK),
32+
/**
33+
* OpenSSL-based implementation.
34+
*/
35+
OPENSSL(SslProvider.OPENSSL);
36+
37+
private final SslProvider sslProvider;
38+
39+
TlsEngineType(SslProvider sslProvider) {
40+
this.sslProvider = sslProvider;
41+
}
42+
43+
/**
44+
* Returns the {@link SslProvider} corresponding to this {@link TlsEngineType}.
45+
*/
46+
public SslProvider sslProvider() {
47+
return sslProvider;
48+
}
49+
}

core/src/main/java/com/linecorp/armeria/internal/common/util/SslContextUtil.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public static SslContext createSslContext(
103103

104104
return MinifiedBouncyCastleProvider.call(() -> {
105105
final SslContextBuilder builder = builderSupplier.get();
106-
final SslProvider provider = Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK;
106+
final SslProvider provider = Flags.tlsEngineType().sslProvider();
107107
builder.sslProvider(provider);
108108

109109
final Set<String> supportedProtocols = supportedProtocols(builder);
@@ -147,7 +147,7 @@ public static SslContext createSslContext(
147147
"You must specify at least one cipher suite.");
148148

149149
if (forceHttp1) {
150-
// Skip validation
150+
// Skip validation
151151
} else {
152152
validateHttp2Ciphers(ciphers, tlsAllowUnsafeCiphers);
153153
}

core/src/main/java/com/linecorp/armeria/server/ServerBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
import com.linecorp.armeria.common.util.EventLoopGroups;
9191
import com.linecorp.armeria.common.util.SystemInfo;
9292
import com.linecorp.armeria.common.util.ThreadFactories;
93+
import com.linecorp.armeria.common.util.TlsEngineType;
9394
import com.linecorp.armeria.internal.common.BuiltInDependencyInjector;
9495
import com.linecorp.armeria.internal.common.ReflectiveDependencyInjector;
9596
import com.linecorp.armeria.internal.common.RequestContextUtil;
@@ -2181,7 +2182,7 @@ private DefaultServerConfig buildServerConfig(List<ServerPort> serverPorts) {
21812182
ports = ImmutableList.of(new ServerPort(0, HTTP));
21822183
}
21832184
} else {
2184-
if (!Flags.useOpenSsl() && !SystemInfo.jettyAlpnOptionalOrAvailable()) {
2185+
if (Flags.tlsEngineType() != TlsEngineType.OPENSSL && !SystemInfo.jettyAlpnOptionalOrAvailable()) {
21852186
throw new IllegalStateException(
21862187
"TLS configured but this is Java 8 and neither OpenSSL nor Jetty ALPN could be " +
21872188
"detected. To use TLS with Armeria, you must either use Java 9+, enable OpenSSL, " +

0 commit comments

Comments
 (0)