-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[native image] Bouncycastle JSSE fails with GraalVM 21.1 #17046
Comments
Issue tracked in quarkusio#17046
@sberyozkin I tried testing this with oracle/graal@a0ea2cd reverted and
but I am getting:
while
do you have any clue why it might be failing to find |
Well, that was apparently because So after including the resources, reverting oracle/graal@a0ea2cd does indeed make the test pass with 21.1. The issue persists in the upcoming 21.2 version, even when explicitly passing all security providers using Looking a bit more into this it looks like some BouncyCastle security services are not getting registered despite explicitly adding the providers we need. Looking further into it... |
The issue appears to be related to the way that we add the "BC" and "BCJSSE" providers. The way we currently do it is through a static initializer: Lines 193 to 204 in cdd3a38
This static initializer however appears to be called after the before-analysis phase were the available services are calculated: This essentially means that when calculating the available services we have not yet registered the bouncycastle providers. The solution should be to move the addition of the bouncycastle providers in the after-registration phase, e.g.: @AutomaticFeature
public class BouncyCastleFeature implements Feature {
@Override
public void afterRegistration(AfterRegistrationAccess access) {
Security.addProvider(new BouncyCastleProvider());
}
} @sberyozkin the following "prototype" makes the test pass. Do you think you can take it from here? diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java
index 3b933d2522..111016f716 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java
@@ -1,5 +1,6 @@
package io.quarkus.deployment.steps;
+import static io.quarkus.gizmo.MethodDescriptor.ofConstructor;
import static io.quarkus.gizmo.MethodDescriptor.ofMethod;
import java.io.ObjectStreamClass;
@@ -10,6 +11,8 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
+import java.security.Provider;
+import java.security.Security;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -79,10 +82,13 @@ public class NativeImageAutoFeatureStep {
"ignoreResources", void.class, String.class);
static final String RUNTIME_REFLECTION = RuntimeReflection.class.getName();
static final String JNI_RUNTIME_ACCESS = "com.oracle.svm.core.jni.JNIRuntimeAccess";
+ static final String AFTER_REGISTRATION_ACCESS = Feature.AfterRegistrationAccess.class.getName();
static final String BEFORE_ANALYSIS_ACCESS = Feature.BeforeAnalysisAccess.class.getName();
static final String DYNAMIC_PROXY_REGISTRY = "com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry";
static final String LEGACY_LOCALIZATION_FEATURE = "com.oracle.svm.core.jdk.LocalizationFeature";
static final String LOCALIZATION_FEATURE = "com.oracle.svm.core.jdk.localization.LocalizationFeature";
+ static final String BOUNCYCASTLE_PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider";
+ static final String BOUNCYCASTLE_JSSE_PROVIDER = "org.bouncycastle.jsse.provider.BouncyCastleJsseProvider";
@BuildStep
GeneratedResourceBuildItem generateNativeResourcesList(List<NativeImageResourceBuildItem> resources,
@@ -125,7 +131,13 @@ public class NativeImageAutoFeatureStep {
Object.class.getName(), Feature.class.getName());
file.addAnnotation("com.oracle.svm.core.annotate.AutomaticFeature");
- //MethodCreator afterReg = file.getMethodCreator("afterRegistration", void.class, "org.graalvm.nativeimage.Feature$AfterRegistrationAccess");
+ MethodCreator afterReg = file.getMethodCreator("afterRegistration", "V", AFTER_REGISTRATION_ACCESS);
+ afterReg.invokeStaticMethod(ofMethod(Security.class, "insertProviderAt", int.class, Provider.class, int.class),
+ afterReg.newInstance(ofConstructor(BOUNCYCASTLE_PROVIDER)), afterReg.load(4));
+ afterReg.invokeStaticMethod(ofMethod(Security.class, "insertProviderAt", int.class, Provider.class, int.class),
+ afterReg.newInstance(ofConstructor(BOUNCYCASTLE_JSSE_PROVIDER)), afterReg.load(5));
+ afterReg.returnValue(null);
+
MethodCreator beforeAn = file.getMethodCreator("beforeAnalysis", "V", BEFORE_ANALYSIS_ACCESS);
TryBlock overallCatch = beforeAn.tryBlock();
//TODO: at some point we are going to need to break this up, as if it get too big it will hit the method size limit
diff --git a/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java b/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java
index 99e3bb2856..23a120e5d3 100644
--- a/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java
+++ b/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java
@@ -188,21 +188,21 @@ public class SecurityProcessor {
}
- @BuildStep
- @Record(ExecutionTime.STATIC_INIT)
- void recordBouncyCastleProviders(SecurityProviderRecorder recorder,
- Optional<BouncyCastleProviderBuildItem> bouncyCastleProvider,
- Optional<BouncyCastleJsseProviderBuildItem> bouncyCastleJsseProvider) {
- if (bouncyCastleJsseProvider.isPresent()) {
- if (bouncyCastleJsseProvider.get().isInFipsMode()) {
- recorder.addBouncyCastleFipsJsseProvider();
- } else {
- recorder.addBouncyCastleJsseProvider();
- }
- } else if (bouncyCastleProvider.isPresent()) {
- recorder.addBouncyCastleProvider(bouncyCastleProvider.get().isInFipsMode());
- }
- }
+// @BuildStep
+// @Record(ExecutionTime.STATIC_INIT)
+// void recordBouncyCastleProviders(SecurityProviderRecorder recorder,
+// Optional<BouncyCastleProviderBuildItem> bouncyCastleProvider,
+// Optional<BouncyCastleJsseProviderBuildItem> bouncyCastleJsseProvider) {
+// if (bouncyCastleJsseProvider.isPresent()) {
+// if (bouncyCastleJsseProvider.get().isInFipsMode()) {
+// recorder.addBouncyCastleFipsJsseProvider();
+// } else {
+// recorder.addBouncyCastleJsseProvider();
+// }
+// } else if (bouncyCastleProvider.isPresent()) {
+// recorder.addBouncyCastleProvider(bouncyCastleProvider.get().isInFipsMode());
+// }
+// }
@BuildStep
void addBouncyCastleProvidersToNativeImage(BuildProducer<NativeImageSecurityProviderBuildItem> additionalProviders,
diff --git a/integration-tests/bouncycastle-jsse/src/test/java/io/quarkus/it/bouncycastle/BouncyCastleJsseITCase.java b/integration-tests/bouncycastle-jsse/src/test/java/io/quarkus/it/bouncycastle/BouncyCastleJsseITCase.java
index dd0942d42c..28fc7c1e55 100644
--- a/integration-tests/bouncycastle-jsse/src/test/java/io/quarkus/it/bouncycastle/BouncyCastleJsseITCase.java
+++ b/integration-tests/bouncycastle-jsse/src/test/java/io/quarkus/it/bouncycastle/BouncyCastleJsseITCase.java
@@ -2,13 +2,12 @@ package io.quarkus.it.bouncycastle;
import org.junit.jupiter.api.Test;
-import io.quarkus.test.junit.DisabledOnNativeImage;
import io.quarkus.test.junit.NativeImageTest;
@NativeImageTest
public class BouncyCastleJsseITCase extends BouncyCastleJsseTestCase {
@Test
- @DisabledOnNativeImage
+ // @DisabledOnNativeImage
@Override
public void testListProviders() {
doTestListProviders(); |
@zakkak Hi - I'm sorry - I keep missing the notifications and I've no idea what is causing it. Let me look into after PTO, thanks for spending your time on this issue, it is appreciated |
@zakkak Quick question about this code:
I think it can not be done directly in
?
Update: prototyping around the 2nd approach etc ? Also, in your prototype you start with a Thanks |
Hi @sberyozkin sorry for the delay, I was on PTO.
I guess so, not sure to be honest.
What's the status of this? Is the only problem the provider indices? To my understanding the index is calculated at build time even without the patch. WDYT? |
Hi @zakkak np, I've just got back from PTO as well :-) I haven't looked into it since the time of my last comment; but this index even if it is made available to the build code it would have to be wrapped in |
Issue tracked in quarkusio/quarkus#17046
Describe the bug
Bouncycastle JSSE fails (at runtime) with GraalVM 21.1
Expected behavior
The test should build and run
Actual behavior
The test compiles but fails with:
See https://github.com/zakkak/quarkus/runs/2510421681?check_suite_focus=true
To Reproduce
Steps to reproduce the behavior:
Environment (please complete the following information):
OpenJDK Runtime Environment 18.9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.11+9, mixed mode, sharing)
Maven home: /home/zakkak/.m2/wrapper/dists/apache-maven-3.8.1-bin/2l5mhf2pq2clrde7f7qp1rdt5m/apache-maven-3.8.1
Java version: 11.0.11, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-11-openjdk-11.0.11.0.9-0.fc34.x86_64
Default locale: en_IE, platform encoding: UTF-8
OS name: "linux", version: "5.11.15-300.fc34.x86_64", arch: "amd64", family: "unix"
The text was updated successfully, but these errors were encountered: