Skip to content
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

Quarkus runner jar failing to start with error java.lang.SecurityException with signed jars #13146

Closed
rohit-s8 opened this issue Nov 5, 2020 · 2 comments
Labels
kind/question Further information is requested

Comments

@rohit-s8
Copy link

rohit-s8 commented Nov 5, 2020

Describe the bug
I have an application that runs on oracle cloud and uses the oci java sdk https://github.com/oracle/oci-java-sdk. The oci-sdk modules used in the application are:

❯ mvn dependency:resolve | grep oci
[INFO]    com.oracle.oci.sdk:oci-java-sdk-common:jar:1.24.0:compile
[INFO]    com.oracle.oci.sdk:oci-java-sdk-vault:jar:1.24.0:compile
[INFO]    com.oracle.oci.sdk:oci-java-sdk-identity:jar:1.24.0:compile
[INFO]    com.oracle.oci.sdk:oci-java-sdk-circuitbreaker:jar:1.24.0:compile
[INFO]    com.oracle.oci.sdk:oci-java-sdk-secrets:jar:1.24.0:compile

I used producer methods to convert some of the classes in the oci modules to CDI discoverable beans as follows:

// Producers.java
public class Producers {
  ...
  ...
  @Produces
  @Singleton
  public ConfigFileAuthenticationDetailsProvider provider(ApplicationConfiguration configuration)
      throws IOException {
    ConfigFile config = ConfigFileReader.parse(configuration.getOci().getConfigFile());
    return new ConfigFileAuthenticationDetailsProvider(config);
  }

  @Produces
  @RequestScoped
  public IdentityClient identityClient(ConfigFileAuthenticationDetailsProvider provider) {
    return new IdentityClient(provider);
  }
  ...
  ...
}

and this worked just fine while in dev mode.
I then ran mvn clean package and the runner jar was generated. I tried running this using java -jar target/*-runner.jar as usual. However, here is where the problem arises. I got the following unexplainable error:

❯ java -jar target/*-runner.jar
Exception in thread "main" java.lang.ExceptionInInitializerError
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.lang.Class.newInstance(Class.java:584)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:60)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:106)
	at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
Caused by: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:326)
	... 9 more
Caused by: java.lang.RuntimeException: Failed to initialize Arc
	at io.quarkus.arc.Arc.initialize(Arc.java:26)
	at io.quarkus.arc.runtime.ArcRecorder.getContainer(ArcRecorder.java:35)
	at io.quarkus.deployment.steps.ArcProcessor$generateResources1649676420.deploy_0(ArcProcessor$generateResources1649676420.zig:76)
	at io.quarkus.deployment.steps.ArcProcessor$generateResources1649676420.deploy(ArcProcessor$generateResources1649676420.zig:40)
	at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:273)
	... 9 more
Caused by: java.lang.SecurityException: class "com.oracle.bmc.identity.IdentityClient"'s signer information does not match signer information of other classes in the same package
	at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1150)
	at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:905)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1014)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at <my-package>.Producers_ProducerMethod_identityClient_38d695926d5e197aa8df80ed7caa7186d867b1c5_Bean.<init>(Producers_ProducerMethod_identityClient_38d695926d5e197aa8df80ed7caa7186d867b1c5_Bean.zig:124)
	at io.quarkus.arc.setup.Default_ComponentsProvider.addBeans3(Default_ComponentsProvider.zig:1153)
	at io.quarkus.arc.setup.Default_ComponentsProvider.getComponents(Default_ComponentsProvider.zig:48)
	at io.quarkus.arc.impl.ArcContainerImpl.<init>(ArcContainerImpl.java:109)
	at io.quarkus.arc.Arc.initialize(Arc.java:20)
	... 13 more

After researching this issue a bit i found https://stackoverflow.com/questions/8878068/signer-information-does-not-match and according to accepted answer:

It means that you have two or more classes in the same package with different signature data. Usually that means the classes come from different JARs, one of which is signed and the other is unsigned.

So I looked into the runner jar and the target/lib folder where all the 3rd party dependencies are kept and found that this was indeed the case.

❯ jar tf target/*-runner.jar | grep IdentityClient
com/oracle/bmc/identity/IdentityClient.class

❯ ls target/lib | grep oci
com.oracle.oci.sdk.oci-java-sdk-circuitbreaker-1.24.0.jar
com.oracle.oci.sdk.oci-java-sdk-common-1.24.0.jar
com.oracle.oci.sdk.oci-java-sdk-secrets-1.24.0.jar
com.oracle.oci.sdk.oci-java-sdk-vault-1.24.0.jar
modified-com.oracle.oci.sdk.oci-java-sdk-identity-1.24.0.jar

❯ jar tf target/lib/modified-com.oracle.oci.sdk.oci-java-sdk-identity-1.24.0.jar | grep IdentityClient
com/oracle/bmc/identity/IdentityClient$1.class
com/oracle/bmc/identity/IdentityClient$Builder.class

We can see that the class com.oracle.bmc.identity.IdentityClient is present both in the runner jar as well as the 3rd party jar (although this has been renamed with a "modified" prefix for reasons beyond my comprehension), and in the 3rd party jar it is signed while in the runner jar it is not.

Strangely enough, once I changed the scope of the producer method from RequestScoped to Dependant or even Singleton, the IdentityClient.class was no longer present in the runner jar and indeed, it worked just fine. My guess is that this issue only comes up with normal scoped beans and not pseudo scoped ones.

Expected behavior
the generated runner jar should have worked with whatever scope was provided to the producer method.

Actual behavior
the jar did not run and raised the error as already explained.

To Reproduce
Steps to reproduce the behavior:

  1. create a small application and import the oci-sdk modules already mentioned.
  2. use the same Producers.java class as shown above.
  3. Inject the IdentityCient somewhere (not entirely sure if this is necessary)
  4. run mvn clean package and subsequently java -jar target/*-runner.jar

Configuration

# Add your application.properties here, if applicable.

Screenshots
(If applicable, add screenshots to help explain your problem.)

Environment (please complete the following information):

  • Output of uname -a or ver:
❯ uname -a
Darwin <my-user>-mac 18.7.0 Darwin Kernel Version 18.7.0: Thu Jun 18 20:50:10 PDT 2020; root:xnu-4903.278.43~1/RELEASE_X86_64 x86_64
  • Output of java -version:
❯ java -version
java version "11.0.4" 2019-07-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.4+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.4+10-LTS, mixed mode)
  • GraalVM version (if different from Java): Not used
  • Quarkus version or git rev: 1.7.1.Final
  • Build tool (ie. output of mvnw --version or gradlew --version):
❯ mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/local/Cellar/maven/3.6.3_1/libexec
Java version: 11.0.4, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-11.0.4.jdk/Contents/Home
Default locale: en_GB, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"

Additional context
My guess this is that this issue would come up with any signed jar because of the way quarkus seems to be optimizing things. Also not sure why quarkus is creating a "modified" version of the 3rd party dependency if the contents are exactly the same. A possible solution then might be to remove the specific class file and signing information from this modified 3rd party jar?

@rohit-s8 rohit-s8 added the kind/bug Something isn't working label Nov 5, 2020
@rohit-s8 rohit-s8 changed the title Quarkus runner jar failing to start with oci-sdk Quarkus runner jar failing to start with error java.lang.SecurityException with oci-sdk Nov 6, 2020
@rohit-s8 rohit-s8 changed the title Quarkus runner jar failing to start with error java.lang.SecurityException with oci-sdk Quarkus runner jar failing to start with error java.lang.SecurityException with signed jars Nov 7, 2020
@rohit-s8
Copy link
Author

Tried uber jar creation and this seems to have solved my problem. I would still like some help in understanding why this didn't work with the normal quarkus jar though.

@gsmet gsmet added kind/question Further information is requested and removed kind/bug Something isn't working labels Nov 19, 2020
@ppalaga
Copy link
Contributor

ppalaga commented Mar 5, 2021

This happened to me with com.azure.storage.blob.BlobServiceClient which happens to come from a signed jar. With this setup the issue was occurring:

@ApplicationScoped
public class SftpAzureRoutes extends RouteBuilder {

    @ConfigProperty(name = "azure.storage.account-name")
    String azureAccountName;
    @ConfigProperty(name = "azure.storage.account-key")
    String azureAccessKey;
    @ConfigProperty(name = "azure.storage.container-name")
    String azureContainer;

    @Produces
    @ApplicationScoped
    @Named("azureBlobServiceClient")
    BlobServiceClient azureBlobServiceClient() {
        StorageSharedKeyCredential credential = new StorageSharedKeyCredential(azureAccountName, azureAccessKey);
        String uri = String.format("https://%s.blob.core.windows.net", azureAccountName);
        return new BlobServiceClientBuilder()
                .endpoint(uri)
                .credential(credential)
                .buildClient();
    }
...
}

It started working when I removed the @ApplicationScoped annotation from the azureBlobServiceClient() method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants