Skip to content

Commit 2887613

Browse files
committed
Support for any OS where conscrypt is not available
Such as Apple Silicon and ARM architectures.
1 parent 6be8ea3 commit 2887613

File tree

4 files changed

+132
-5
lines changed

4 files changed

+132
-5
lines changed

build.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ dependencies {
5353
compileOnly("org.conscrypt:conscrypt-openjdk-uber:$conscrypt")
5454
implementation("org.eclipse.jetty.http2:http2-server:$jetty")
5555
implementation("org.eclipse.jetty:jetty-alpn-conscrypt-server:$jetty")
56+
implementation("org.eclipse.jetty:jetty-alpn-java-server:$jetty")
5657

5758

5859

@@ -66,10 +67,13 @@ dependencies {
6667
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junit")
6768

6869
integrationTestImplementation("org.junit.jupiter:junit-jupiter-api:$junit")
69-
integrationTestImplementation("io.javalin:javalin-bundle:$javalin")
70+
integrationTestImplementation("io.javalin:javalin:$javalin")
7071
integrationTestImplementation("io.github.hakky54:sslcontext-kickstart:$sslContextKickstart")
7172
integrationTestImplementation("io.github.hakky54:sslcontext-kickstart-for-jetty:$sslContextKickstart")
7273
integrationTestImplementation("io.github.hakky54:sslcontext-kickstart-for-pem:$sslContextKickstart")
74+
integrationTestImplementation("org.eclipse.jetty.http2:http2-server:$jetty")
75+
integrationTestImplementation("org.eclipse.jetty:jetty-alpn-java-server:$jetty")
76+
integrationTestImplementation("org.eclipse.jetty:jetty-alpn-conscrypt-server:$jetty")
7377
integrationTestImplementation("com.squareup.okhttp3:okhttp:$okhttp")
7478
integrationTestImplementation("com.squareup.okhttp3:okhttp-tls:$okhttp")
7579
integrationTestImplementation('org.slf4j:slf4j-simple:2.0.3')

src/intTest/java/io/javalin/community/ssl/SSLConfigTests.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
11
package io.javalin.community.ssl;
22

33
import io.javalin.Javalin;
4+
import io.javalin.community.ssl.util.SSLUtils;
45
import okhttp3.OkHttpClient;
56
import okhttp3.Protocol;
67
import okhttp3.Request;
78
import okhttp3.Response;
89
import org.eclipse.jetty.server.Connector;
10+
import org.eclipse.jetty.server.ServerConnector;
11+
import org.eclipse.jetty.server.SslConnectionFactory;
912
import org.junit.jupiter.api.Tag;
1013
import org.junit.jupiter.api.Test;
14+
import org.junit.jupiter.api.condition.EnabledOnOs;
15+
import org.junit.jupiter.api.condition.OS;
1116

1217
import java.io.IOException;
18+
import java.security.Provider;
1319
import java.util.Collections;
1420
import java.util.Objects;
1521

1622
import static org.junit.jupiter.api.Assertions.*;
23+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
1724

1825
@Tag("integration")
1926
public class SSLConfigTests extends IntegrationTestClass {
@@ -330,4 +337,72 @@ void testConnectorConfigConsumer(){
330337
fail(e);
331338
}
332339
}
340+
341+
@Test
342+
void testNullSecurityProvider(){
343+
int securePort = ports.getAndIncrement();
344+
String https = HTTPS_URL_WITH_PORT.apply(securePort);
345+
try (Javalin app = IntegrationTestClass.createTestApp(config -> {
346+
config.insecure = false;
347+
config.securePort = securePort;
348+
config.pemFromString(CERTIFICATE_AS_STRING, NON_ENCRYPTED_KEY_AS_STRING);
349+
config.securityProvider = null;
350+
}).start()) {
351+
printSecurityProviderName(app);
352+
testSuccessfulEndpoint(https, Protocol.HTTP_2);
353+
} catch (IOException e) {
354+
fail(e);
355+
}
356+
}
357+
358+
@Test
359+
void testDefaultSecurityProvider(){
360+
int securePort = ports.getAndIncrement();
361+
String https = HTTPS_URL_WITH_PORT.apply(securePort);
362+
try (Javalin app = IntegrationTestClass.createTestApp(config -> {
363+
config.insecure = false;
364+
config.securePort = securePort;
365+
config.pemFromString(CERTIFICATE_AS_STRING, NON_ENCRYPTED_KEY_AS_STRING);
366+
}).start()) {
367+
printSecurityProviderName(app);
368+
testSuccessfulEndpoint(https, Protocol.HTTP_2);
369+
} catch (IOException e) {
370+
fail(e);
371+
}
372+
}
373+
374+
@Test
375+
@EnabledOnOs({OS.LINUX, OS.MAC, OS.WINDOWS})
376+
void checkSupportedOsUsesConscrypt() {
377+
assumeTrue(SSLUtils.osIs64Bit());
378+
379+
int securePort = ports.getAndIncrement();
380+
String https = HTTPS_URL_WITH_PORT.apply(securePort);
381+
try (Javalin app = IntegrationTestClass.createTestApp(config -> {
382+
config.insecure = false;
383+
config.securePort = securePort;
384+
config.pemFromString(CERTIFICATE_AS_STRING, NON_ENCRYPTED_KEY_AS_STRING);
385+
}).start()) {
386+
printSecurityProviderName(app);
387+
assertTrue(getSecurityProviderName(app).contains("Conscrypt"));
388+
testSuccessfulEndpoint(https, Protocol.HTTP_2);
389+
} catch (IOException e) {
390+
fail(e);
391+
}
392+
}
393+
394+
private static String getSecurityProviderName(Javalin app){
395+
ServerConnector conn = (ServerConnector) app.jettyServer().server().getConnectors()[0];
396+
return conn.getConnectionFactories().stream()
397+
.filter(cf -> cf instanceof SslConnectionFactory)
398+
.map(cf -> (SslConnectionFactory) cf)
399+
.map(sslConnectionFactory -> sslConnectionFactory.getSslContextFactory().getSslContext().getProvider().getName())
400+
.findFirst()
401+
.orElseThrow();
402+
}
403+
404+
private static void printSecurityProviderName(Javalin app) {
405+
System.out.println("Security provider: " + getSecurityProviderName(app));
406+
}
407+
333408
}

src/main/java/io/javalin/community/ssl/SSLConfig.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package io.javalin.community.ssl;
22

3+
import io.javalin.community.ssl.util.SSLUtils;
34
import lombok.Getter;
4-
import org.conscrypt.Conscrypt;
5+
//import org.conscrypt.Conscrypt;
56
import org.eclipse.jetty.server.ServerConnector;
67
import org.jetbrains.annotations.Nullable;
78

@@ -349,7 +350,7 @@ public void keystoreFromClasspath(String keyStoreFile, String keyStorePassword)
349350
/**
350351
* Security provider to use for the SSLContext.
351352
*/
352-
public Provider securityProvider = Conscrypt.newProvider();
353+
public Provider securityProvider = SSLUtils.getSecurityProvider();
353354

354355

355356
}

src/main/java/io/javalin/community/ssl/util/SSLUtils.java

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import nl.altindag.ssl.SSLFactory;
66
import nl.altindag.ssl.util.JettySslUtils;
77
import nl.altindag.ssl.util.PemUtils;
8-
import org.conscrypt.Conscrypt;
98
import org.eclipse.jetty.util.ssl.SslContextFactory;
109

1110
import javax.net.ssl.X509ExtendedKeyManager;
11+
import java.security.Provider;
1212

1313
/**
1414
* Utility class for SSL related tasks.
@@ -42,7 +42,7 @@ public static SslContextFactory.Server createSslContextFactory(SSLConfig config)
4242
/**
4343
* Helper method to parse the given config and add Identity Material to the given builder.
4444
*
45-
* @param config The config to use.
45+
* @param config The config to use.
4646
* @throws SSLConfigException if the key configuration is invalid.
4747
*/
4848
public static void parseIdentity(SSLConfig config, SSLFactory.Builder builder) throws SSLConfigException {
@@ -102,4 +102,51 @@ public static void parseIdentity(SSLConfig config, SSLFactory.Builder builder) t
102102

103103
builder.withIdentityMaterial(keyManager);
104104
}
105+
106+
/**
107+
* Helper method to create a working {@link Provider} for the current JVM.
108+
*/
109+
public static Provider getSecurityProvider() {
110+
if(osSupportsConscrypt()){
111+
return new org.conscrypt.OpenSSLProvider();
112+
} else {
113+
return null;
114+
}
115+
}
116+
117+
/**
118+
* Checks if the current OS is supported by Conscrypt.
119+
* Currently only Windows (x86, x64), Linux (x64) and Mac OS X (x64) are supported.
120+
* @return true if the current OS is supported by Conscrypt.
121+
*/
122+
public static boolean osSupportsConscrypt() {
123+
String osName = System.getProperty("os.name").toLowerCase();
124+
//Remove all non-alphanumeric characters from the os name
125+
osName = osName.replaceAll("[^a-z0-9]", "");
126+
127+
if (osName.contains("windows")) {
128+
return true;
129+
} else if (osName.contains("linux") || (osName.contains("macosx") || osName.contains("osx"))) {
130+
return osIs64Bit();
131+
} else {
132+
return false;
133+
}
134+
}
135+
136+
/**
137+
* Checks if the current OS runs on an x86_64 architecture.
138+
* @return true if the current OS runs on an x86_64 architecture.
139+
*/
140+
public static boolean osIs64Bit() {
141+
String osArch = System.getProperty("os.arch").toLowerCase();
142+
osArch = osArch.replaceAll("[^a-z0-9]", "");
143+
144+
String[] archNames = new String[]{"x8664", "amd64", "ia32e", "em64t", "x64"};
145+
for (String archName : archNames) {
146+
if (osArch.contains(archName)) {
147+
return true;
148+
}
149+
}
150+
return false;
151+
}
105152
}

0 commit comments

Comments
 (0)