Stop dealing with the SunEC library during the native image generation

This commit is contained in:
Gwenneg Lepage
2020-02-09 23:37:22 +01:00
parent 03ff95fb09
commit 1bfaeed30e
3 changed files with 9 additions and 67 deletions

View File

@@ -1,13 +1,11 @@
package io.quarkus.deployment.steps;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.graalvm.nativeimage.ImageInfo;
import org.jboss.logging.Logger;
import io.quarkus.deployment.annotations.BuildProducer;
@@ -36,8 +34,6 @@ class NativeImageConfigBuildStep {
private static final Logger log = Logger.getLogger(NativeImageConfigBuildStep.class);
private static final String LIB_SUN_EC = "libsunec.so";
@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void build(SslContextConfigurationRecorder sslContextConfigurationRecorder,
@@ -74,50 +70,18 @@ class NativeImageConfigBuildStep {
}
}
Boolean sslNativeEnabled = isSslNativeEnabled(sslNativeConfig, extensionSslNativeSupport);
// For now, we enable SSL native if it hasn't been explicitly disabled
// it's probably overly conservative but it's a first step in the right direction
sslContextConfigurationRecorder.setSslNativeEnabled(!sslNativeConfig.isExplicitlyDisabled());
Boolean sslNativeEnabled = isSslNativeEnabled(sslNativeConfig, extensionSslNativeSupport);
if (sslNativeEnabled) {
// This is an ugly hack but for now it's the only way to make the SunEC library
// available to the native image.
// This makes the native image dependent on the local path used to build it.
// If you want to push your native image to a different environment, you will
// need to put libsunec.so aside the native image or override java.library.path.
String graalVmHome = System.getenv("GRAALVM_HOME");
if (graalVmHome != null) {
Path graalVmLibDirectory = Paths.get(graalVmHome, "jre", "lib");
Path linuxLibDirectory = graalVmLibDirectory.resolve("amd64");
Path linuxPath = linuxLibDirectory.resolve(LIB_SUN_EC);
// We add . as it might be useful in a containerized world
javaLibraryPathAdditionalPath.produce(new JavaLibraryPathAdditionalPathBuildItem("."));
if (Files.exists(linuxPath)) {
// On Linux, the SunEC library is in jre/lib/amd64/
// This is useful for testing or if you have a similar environment in production
javaLibraryPathAdditionalPath
.produce(new JavaLibraryPathAdditionalPathBuildItem(linuxLibDirectory.toString()));
} else {
// On MacOS, the SunEC library is directly in jre/lib/
// This is useful for testing or if you have a similar environment in production
javaLibraryPathAdditionalPath
.produce(new JavaLibraryPathAdditionalPathBuildItem(graalVmLibDirectory.toString()));
}
Path graalVmCacertsPath = Paths.get(graalVmHome, "jre", "lib", "security", "cacerts");
// This is useful for testing but the user will have to override it.
sslTrustStoreSystemProperty.produce(
new SslTrustStoreSystemPropertyBuildItem(
graalVmLibDirectory.resolve(Paths.get("security", "cacerts")).toString()));
} else {
// only warn if we're building a native image
if (ImageInfo.inImageBuildtimeCode()) {
log.warn(
"SSL is enabled but the GRAALVM_HOME environment variable is not set. The java.library.path property has not been set and will need to be set manually.");
}
sslTrustStoreSystemProperty.produce(new SslTrustStoreSystemPropertyBuildItem(graalVmCacertsPath.toString()));
}
}
nativeImage.produce(new NativeImageSystemPropertyBuildItem("quarkus.ssl.native", sslNativeEnabled.toString()));

View File

@@ -158,15 +158,13 @@ And let's build the native executable again:
./mvnw clean install -Pnative
```
== The SunEC library and friends
== The TrustStore path
You haven't noticed anything but, while building the image,
Quarkus has automatically set `java.library.path` to point to the GraalVM library folder (the one containing the SunEC library).
It has also set `javax.net.ssl.trustStore` to point to the `cacerts` file bundled in the GraalVM distribution.
Quarkus has automatically set `javax.net.ssl.trustStore` to point to the `cacerts` file bundled in the GraalVM distribution.
This file contains the root certificates.
This is useful when running tests but, obviously, it is not portable as these paths are hardcoded.
This is useful when running tests but, obviously, it is not portable as this path is hardcoded.
You can check that pretty easily:
@@ -174,13 +172,12 @@ You can check that pretty easily:
* run the native executable `./target/rest-client-1.0-SNAPSHOT-runner`
* in a browser, go to `http://localhost:8080/country/name/greece`
* you will have an Internal Server Error
* in your terminal, you should have a warning `WARNING: The sunec native library, required by the SunEC provider, could not be loaded.`
and an exception too: `java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty`
* in your terminal, you should have an exception: `java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty`
* hit `Ctrl+C` to stop the application
To make it work, you need to manually set `java.library.path` and `javax.net.ssl.trustStore` to point to the new GraalVM home:
To make it work, you need to manually set `javax.net.ssl.trustStore` to point to the new GraalVM home:
```
./target/rest-client-1.0-SNAPSHOT-runner -Djava.library.path=<new-graalvm-home>/jre/lib/amd64 -Djavax.net.ssl.trustStore=<new-graalvm-home>/jre/lib/security/cacerts
./target/rest-client-1.0-SNAPSHOT-runner -Djavax.net.ssl.trustStore=<new-graalvm-home>/jre/lib/security/cacerts
```
Now, the application should work as expected:

View File

@@ -3,11 +3,6 @@ package io.quarkus.it.vertx;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.containsString;
import java.security.Provider;
import java.security.Security;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.NativeImageTest;
@@ -17,20 +12,6 @@ import io.restassured.specification.RequestSpecification;
@NativeImageTest
public class VertxProducerResourceIT extends VertxProducerResourceTest {
private static Provider sunECProvider;
@BeforeAll
public static void setupSecProvider() {
//Remove SunEC provider for the test as it's not being provided for tests.
sunECProvider = Security.getProvider("SunEC");
Security.removeProvider("SunEC");
}
@AfterAll
public static void restoreSecProvider() {
Security.addProvider(sunECProvider);
}
@Test
@Override
public void testRouteRegistrationMTLS() {