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

[BUG] Occurs SecurityException when building native image based on Spring Cloud Azure Native support #30320

Closed
3 tasks done
moarychan opened this issue Aug 8, 2022 · 28 comments
Labels
azure-spring All azure-spring related issues azure-spring-native Issues related to Spring native. bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. Spring Monitor
Milestone

Comments

@moarychan
Copy link
Member

Describe the bug
When using native tools to build, the failure Fatal error: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.AzureCompatibilityVerifierAutoConfiguration"'s signer information does not match signer information of other classes in the same package occurs.

Exception or Stack Trace

Fatal error: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.AzureCompatibilityVerifierAutoConfiguration"'s signer information does not match signer information of other classes in the same package
        at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1151)
        at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:906)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1015)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
        at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:555)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        at com.oracle.svm.hosted.ImageClassLoader.forName(ImageClassLoader.java:285)
        at com.oracle.svm.hosted.ImageClassLoader.findClass(ImageClassLoader.java:278)
        at com.oracle.svm.hosted.config.ReflectionRegistryAdapter.resolveType(ReflectionRegistryAdapter.java:68)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseClass(ReflectionConfigurationParser.java:94)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseClassArray(ReflectionConfigurationParser.java:77)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseAndRegister(ReflectionConfigurationParser.java:72)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.doParseAndRegister(ConfigurationParserUtils.java:127)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.lambda$parseAndRegisterConfigurations$3(ConfigurationParserUtils.java:113)
        at java.base/java.util.stream.ReferencePipeline$4$1.accept(ReferencePipeline.java:212)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils$1.tryAdvance(ConfigurationParserUtils.java:106)
        at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:326)
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
        at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.IntPipeline.reduce(IntPipeline.java:491)
        at java.base/java.util.stream.IntPipeline.sum(IntPipeline.java:449)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.parseAndRegisterConfigurations(ConfigurationParserUtils.java:115)
        at com.oracle.svm.reflect.hosted.ReflectionFeature.duringSetup(ReflectionFeature.java:185)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$setupNativeImage$16(NativeImageGenerator.java:847)
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:74)
        at com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:847)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:534)
        at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:494)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:426)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:587)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:126)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:617)

To Reproduce
Run sample issue-azure-storage-native

Code Snippet
Ref the sample project.

Expected behavior
Build and exec successfully.

Setup (please complete the following information):

  • OS: [Windows 11]
  • IDE: [IntelliJ]
  • Library/Libraries: [com.azure.spring:spring-cloud-azure-starter-storage-blob:4.1.0, com.azure.spring:spring-cloud-azure-native-configuration:4.0.0-beta.1]
  • Java version: [11]
  • Frameworks: [Spring Boot 2.6.6]

Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added
@ghost ghost added the needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. label Aug 8, 2022
@moarychan moarychan added bug This issue requires a change to an existing behavior in the product in order to be resolved. azure-spring All azure-spring related issues and removed needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. labels Aug 8, 2022
@moarychan moarychan moved this to Todo in Spring Cloud Azure Aug 8, 2022
@moarychan moarychan added the Client This issue points to a problem in the data-plane of the library. label Aug 9, 2022
@moarychan moarychan self-assigned this Aug 9, 2022
@moarychan moarychan added this to the 2022-09 milestone Aug 9, 2022
@moarychan moarychan moved this from Todo to In Progress in Spring Cloud Azure Aug 12, 2022
@moarychan
Copy link
Member Author

I opened a new issue spring-attic/spring-native#1699 on the Spring Native side for help.

@moarychan moarychan moved this from In Progress to Blocked in Spring Cloud Azure Aug 31, 2022
@saragluna saragluna modified the milestones: 2022-09, 2022-10 Sep 6, 2022
@sdeleuze
Copy link

FYI the related Spring Framework 6 issue is spring-projects/spring-framework#29019.

@sdeleuze
Copy link

Do you have a workaround for this issue or is it 100% blocking? Does it happen only with native build tools or also with Buildpacks?

@moarychan
Copy link
Member Author

It is currently blocked, and both native build tool and Buildpacks will encounter it.

@sdeleuze
Copy link

sdeleuze commented Sep 22, 2022

Could you please share more on which JARs are signed and when? We would be interested to know if only Azure library jars are signed when they are built (so the fact they are signed is something we can detected during the build) or are all JARs signed during the deployment on Azure?

@moarychan
Copy link
Member Author

All the jars from Azure side will be signed before they are published to Maven Central, this action is built in the release pipeline for each Azure Java library, the libraries with group id com.azure.spring and artifact id prefix spring-cloud-azure-xxx are maintained and released by our team, like: spring-cloud-azure-autoconfigure, spring-cloud-azure-starter, see more from https://mvnrepository.com/artifact/com.azure.spring.

all JARs signed during the deployment on Azure

I understand the deployment on Azure is that deploy the Spring Boot application jar to Azure service, like Azure App Services, etc, this jar does not need to be signed.

@sdeleuze
Copy link

sdeleuze commented Oct 6, 2022

Juergen Hoeller has provided the following feedback about this issue here:

After a lot of consideration, we have realized that this is a problem that is not practical to solve at the core framework level. Our generated configuration needs to have access to package-local elements in common scenarios, not least of it all in order to avoid unnecessary reflection. For that reason, we decided to preserve our package-local generation approach.

If a separate jar with a split package arrangement or different jar signatures turns out to be an issue (also e.g. in the module system), the application build may combine them into a single jar that contains both the original classes and the generated configuration. Alternatively, the application build may also simply remove the jar signature before proceeding.

So I would like to discuss with you to try to find a workaround that works for Azure use case.

The real issue here is not the validation of JAR integrity with the signature which can happen separately via jarsigner -verify foo.jar, but the fact that when JAR are signed, the JVM don't accept additional classes in the same package.

So what are the possible workarounds:

  • Disabling JAR signature verification as described here
  • Combine all JARs into a single one
  • Explode the dependency JARs before using it (signature are only verified for JARs)
  • Leverage Gradle artifact transformation to remove the signature during the build

Do you think we could find a workaround suitable for Azure?

@moarychan moarychan modified the milestones: 2022-10, 2022-11 Oct 9, 2022
@saragluna
Copy link
Member

Thanks @sdeleuze. Did you mean disabling the JAR signature verification during the native build? Could you elaborate on combine all JARs into a single one? When and what should we combine? What does the explode mean in option 3?

@moarychan moarychan moved this from Blocked to In Progress in Spring Cloud Azure Oct 10, 2022
@sdeleuze
Copy link

Did you mean disabling the JAR signature verification during the native build?
Yes.

On JVM side, running from that fat JAR works since no verification is done on the embedded JARs, only running in exploded mode when AOT is enabled is broken, but using that path is pretty involved (AOT processing needs to be enable + -Dspring.aot.enabled=true net to be set) and that's not really a first class use case, so I think that's ok at least for now to not support this.

Could you elaborate on combine all JARs into a single one?
I mean using build plugins to create one JAR by merging all the classes and resources of the application and its dependencies. I think https://imperceptiblethoughts.com/shadow/ does something like that.

What does the explode mean in option 3?
That means extracting each dependency in a directory and use those directories instead of the dependencies JAR as the classpath.

The issue with option 2 and 3 is that I am not sure that will integrate properly with Native Build Tools and Buildpacks.
Option 1 is the simpler but require creating a local file where the native-image compiler runs (local machine for Native Build Tools and container for Buildpacks).
Option 4 is IMO the the more robust since it produces artifact that will work for all use case, should be easy with Gradle but not sure how to handle it with Maven.

Maybe we can ask GraalVM team to add native-image option to disable JAR signature verification with a simple option and for the time being we move forward by creating the file and configuring it manually.

Please let me know what would be the best path for you.

@moarychan
Copy link
Member Author

moarychan commented Oct 11, 2022

@sdeleuze thanks for your update!

I tried option 1 using the Spring Cloud Azure 4.10, it resulted in the below same exception.

  • If not configured the custom.security file, the build failed in the first phrase [1/7] Initializing.

    Not configured the costom.security file

    image

          </p>
    
  • If configured the custom.security file which has already added a line jdk.jar.disabledAlgorithms=MD2, MD5, RSA, DSA, the build failed after the phrase [2/7] Performing analysis... [*********]. From the exception stack, seems that the later command with java (should be) does not take the custome.security file configuration, so it still executed the signature verification.

    Configured the costom.security file

    image

          </p>
    

I checked with the reproducer sample https://github.com/mhalbritter/spring-aot-jarsigner-reproducer, after the custome.security file was configured, the exception is the same as before.

Console log from command `gradlew.bat bootRun -Djava.security.properties=custom-java17.security`

image

@sdeleuze Could you help to give more suggestions for option 1? I think this workaround is simpler for users.

@moarychan
Copy link
Member Author

New update: The sample spring-aot-jarsigner-reproducer works through the code setting systemProperty('java.security.properties', 'D:\\xxx\\java17.security')

But when using native compile, the exception seems the same with my local testing.

[2/7] Performing analysis...  [*]                                                                       (24.3s @ 1.33GB)
   5,951 (84.08%) of  7,078 classes reachable
   8,148 (59.99%) of 13,582 fields reachable
  27,107 (52.88%) of 51,266 methods reachable
     248 classes,   118 fields, and   873 methods registered for reflection
       3 native libraries: crypt32, ncrypt, psapi

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing com.example.signerdemo.SignerDemoApplication__ApplicationContextInitializer.initialize(org.springframework.context.support.GenericApplicationContext)
Parsing context:
   at com.example.signerdemo.SignerDemoApplication__ApplicationContextInitializer.initialize(SignerDemoApplication__ApplicationContextInitializer.java:16)
   at com.example.signerdemo.SignerDemoApplication__ApplicationContextInitializer.initialize(SignerDemoApplication__ApplicationContextInitializer.java:13)
   at org.springframework.boot.context.config.DelegatingApplicationContextInitializer.applyInitializers(DelegatingApplicationContextInitializer.java:107)
   at org.springframework.boot.context.config.DelegatingApplicationContextInitializer.applyInitializerClasses(DelegatingApplicationContextInitializer.java:88)
   at org.springframework.boot.context.config.DelegatingApplicationContextInitializer.initialize(DelegatingApplicationContextInitializer.java:56)
   at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:72)
   at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)

        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:152)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:104)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:83)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraph(MethodTypeFlow.java:65)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultVirtualInvokeTypeFlow.java:109)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:558)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis$1.run(PointsToAnalysis.java:635)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Error loading a referenced type: java.lang.SecurityException: class "dependency.DependencyAutoConfiguration__BeanDefinitions"'s signer information does not match signer information of other classes in the same package
        at parsing com.example.signerdemo.SignerDemoApplication__BeanFactoryRegistrations.registerBeanDefinitions(SignerDemoApplication__BeanFactoryRegistrations.java:46)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2506)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:105)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3367)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3319)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3164)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:84)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:79)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.run(Phase.java:49)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:261)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:135)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:685)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.lookupEncodedGraph(InlineBeforeAnalysis.java:180)
        at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.doInline(PEGraphDecoder.java:1162)
        at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.tryInline(PEGraphDecoder.java:1145)
        at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.trySimplifyInvoke(PEGraphDecoder.java:1003)
        at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.handleInvoke(PEGraphDecoder.java:957)
        at jdk.internal.vm.compiler/org.graalvm.compiler.nodes.GraphDecoder.processNextNode(GraphDecoder.java:817)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.processNextNode(InlineBeforeAnalysis.java:240)
        at jdk.internal.vm.compiler/org.graalvm.compiler.nodes.GraphDecoder.decode(GraphDecoder.java:548)
        at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.decode(PEGraphDecoder.java:833)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysis.decodeGraph(InlineBeforeAnalysis.java:98)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:176)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:343)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:93)
        ... 13 more
Caused by: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Error loading a referenced type: java.lang.SecurityException: class "dependency.DependencyAutoConfiguration__BeanDefinitions"'s signer information does not match signer information of other classes in the same package
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.loadReferencedType(WrappedConstantPool.java:153)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.loadReferencedType(WrappedConstantPool.java:159)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SubstrateClassInitializationPlugin.loadReferencedType(SubstrateClassInitializationPlugin.java:58)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.loadReferenceType(BytecodeParser.java:4250)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.maybeEagerlyResolve(BytecodeParser.java:4232)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.maybeEagerlyResolve(SharedGraphBuilderPhase.java:153)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.lookupMethod(BytecodeParser.java:4172)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genInvokeStatic(BytecodeParser.java:1636)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5224)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3359)
        ... 38 more
Caused by: java.lang.SecurityException: class "dependency.DependencyAutoConfiguration__BeanDefinitions"'s signer information does not match signer information of other classes in the same package
        at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1158)
        at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:902)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
        at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
        at jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool(Native Method)
------------------------------------------------------------------------------------------------------------------------
        at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotConstantPool.loadReferencedType(HotSpotConstantPool.java:865)
        at java.base/jdk.internal.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.loadReferencedType(WrappedConstantPool.java:142)
        ... 47 more
                        1.5s (3.9% of total time) in 16 GCs | Peak RSS: 1.95GB | CPU load: 2.73

@sdeleuze
Copy link

sdeleuze commented Oct 12, 2022

For gradle bootRun you should configure something like that in app/build.gradle:

bootRun {
	systemProperty("java.security.properties", "/home/seb/playground/spring-aot-jarsigner-reproducer/custom.security")
	systemProperty('spring.aot.enabled', 'true')
}

See related Spring Boot documentation. It should be even possible to create the custom.security file in build.gradle.

For native image, you can configure the application module in app/build.gradle with

graalvmNative {
	binaries {
		main {
			buildArgs('-Djava.security.properties=/home/seb/playground/spring-aot-jarsigner-reproducer/custom.security')
		}
	}
}

With custom.security content behing:

jdk.jar.disabledAlgorithms=MD2, MD5, RSA, DSA

Works for me on spring-aot-jarsigner-reproducer

The only thing I am not sure yet is how to make this supported with Buildpacks, but let's for now see if it works for you with Native Build Tools.

@moarychan
Copy link
Member Author

Thanks @sdeleuze, it works for now with the Native Build Tools.

Below are my testing steps in Windows 11:

  1. Locate your file java.security, like D:\xxx\graalvm-ce-java11-22.0.0.2\conf\security\java.security.

  2. Comment out the default configuration, it maybe is in line 697

    image

  3. Add a new value MD2, MD5, RSA, DSA for the commented key jdk.jar.disabledAlgorithms

    image

  4. Then go ahead with the native executable building.

I will test the other possible workarounds and update you here if available.

@sdeleuze
Copy link

sdeleuze commented Oct 21, 2022

Good to know, I have updated my comment to show the content of the custom.security file which should provide the same result than the direct JDK modification specified above.

We are open to discuss Buildpacks support for this.

@moarychan moarychan modified the milestones: 2022-11, 2022-12 Nov 4, 2022
@saragluna saragluna assigned saragluna and unassigned moarychan Nov 4, 2022
@saragluna saragluna modified the milestones: 2022-12, Backlog Nov 4, 2022
@saragluna saragluna removed their assignment Dec 8, 2022
@sdeleuze
Copy link

sdeleuze commented Dec 9, 2022

FYI the currrent workaround proposed to get both Native Build Tools and Buildpacks support is:

<build>
   <plugins>
      <plugin>
         <groupId>org.graalvm.buildtools</groupId>
         <artifactId>native-maven-plugin</artifactId>
         <configuration>
            <buildArgs>
               <arg>-Djava.security.properties=src/main/resources/custom.security</arg>
            </buildArgs>
         </configuration>
      </plugin>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
         <configuration>
            <image>
               <env>
                  <BP_NATIVE_IMAGE_BUILD_ARGUMENTS>-Djava.security.properties=/workspace/BOOT-INF/classes/custom.security</BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
               </env>
            </image>
         </configuration>
      </plugin>
   </plugins>
</build>

With an src/main/resources/custom.security file with the following content:

jdk.jar.disabledAlgorithms=MD2, MD5, RSA, DSA

I suggest to document that properly to allow Azure Java SDK to be able to use Spring Boot 3 AOT/native support.

@saragluna
Copy link
Member

FYI, for the Gradle project to use a project level custom.security file, you could set as following:

graalvmNative {
  binaries {
    main {
      buildArgs('-Djava.security.properties=' + file("$rootDir/custom.security").absolutePath)
    }
  }  
}
bootRun {
  systemProperty("java.security.properties", file("$rootDir/custom.security").absolutePath)
  systemProperty('spring.aot.enabled', 'true')
}

@jeanbisutti
Copy link
Contributor

@sdeleuze I have the same kind of issue with Spring Boot 3.1.4 and the spring-cloud-azure-starter-monitor dependency:

[INFO]     [creator]     Caused by: java.lang.SecurityException: class "com.azure.monitor.applicationinsights.spring.AzureSpringMonitorConfig__BeanDefinitions"'s signer information does not match signer information of other classes in the same package
[INFO]     [creator]            at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1158)
[INFO]     [creator]            at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:902)
[INFO]     [creator]            at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010)
[INFO]     [creator]            at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
[INFO]     [creator]            at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
[INFO]     [creator]            at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
[INFO]     [creator]            at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
[INFO]     [creator]            at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
[INFO]     [creator]            at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
[INFO]     [creator]            at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
[INFO]     [creator]            at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
[INFO]     [creator]            at jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool(Native Method)
[INFO]     [creator]            at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotConstantPool.loadReferencedType(HotSpotConstantPool.java:818)
[INFO]     [creator]            at com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.loadReferencedType(WrappedConstantPool.java:100)
[INFO]     [creator]            ... 51 more

From this comment, I understand that the issue is related to Spring AOT and won't be fixed on the Spring side?

Disabling JAR signature verification has fixed the issue.

Please let me know, and I could add documentation for the spring-cloud-azure-starter-monitor dependency.

@moarychan
Copy link
Member Author

I understand that the issue is related to Spring AOT and won't be fixed on the Spring side?

@jeanbisutti Yes, we should disable the JAR signature verification.

@jeanbisutti
Copy link
Contributor

From this comment: "this is a problem that is not practical to solve at the core framework level"

@sdeleuze Perhaps the workaround could be implemented on the Spring side?

For example, the custom.security file could be generated in the performAotProcessing method of the ContextAotProcessor class: https://github.com/spring-projects/spring-framework/blob/f60791a8e28bca4985d2f8d3366544b496ac8a49/spring-context/src/main/java/org/springframework/context/aot/ContextAotProcessor.java#L110

In addition, the spring-boot-starter-parent pom could be updated:

image

image

@snicoll
Copy link

snicoll commented Oct 17, 2023

Thanks for the suggestion but adding java security properties in our parent is not an option I am afraid.

@jeanbisutti
Copy link
Contributor

Thanks for the suggestion but adding java security properties in our parent is not an option I am afraid.

It could only be added with a Spring option to be able to generate Spring native images for projects having signed jar (like Azure SDK JARs)

@jeanbisutti
Copy link
Contributor

With the Buildpacks case ( mvn -Pnative spring-boot:build-image with Maven), could the Spring Boot Maven / Gradle plugin combine all the JARs into a single JAR to fix the JAR signature issue?

@saragluna saragluna added the azure-spring-native Issues related to Spring native. label Nov 20, 2023
@vath-rav
Copy link

vath-rav commented Feb 6, 2024

I tried the above work around, but it still gives the same error. I did in gladle with kotlin. Here is my configuration:
graalvmNative {
binaries {
named("main") {
buildArgs("-Djava.security.properties=src/main/resources/custom.security")
}
}
}
tasks.named("bootRun") {
println("rootDir = $rootDir")
systemProperty("java.security.properties", "src/main/resources/custom.security")
systemProperty("spring.aot.enabled", "true")
}

@vath-rav
Copy link

vath-rav commented Feb 6, 2024

Caused by: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.implementation.compatibility.AzureCompatibilityVerifierAutoConfiguration__BeanDefinitions"'s signer information does not match signer information of other classes in the same package
[creator] at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1173)
[creator] at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:917)
[creator] at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1025)
[creator] at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
[creator] at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.defineClass(NativeImageClassLoader.java:500)
[creator] at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.findClassViaClassPath(NativeImageClassLoader.java:452)
[creator] at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.loadClass(NativeImageClassLoader.java:640)
[creator] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
[creator] at jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool(Native Method)
[creator] at jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool(CompilerToVM.java:468)

@cosmintudora
Copy link

Hello,

A workaround for Buildpacks gradle (bootBuildImage), also explained in this post : spring-projects/spring-framework#29019 (comment)

bootBuildImage { environment["BP_NATIVE_IMAGE_BUILD_ARGUMENTS"] = "-Djava.security.properties=/workspace/BOOT-INF/classes/custom.security" }

@philipschikora
Copy link

the workaround works fine, but are there plans to eliminate this problem?

@saragluna
Copy link
Member

Hi @philipschikora, we are working with both Spring team and Azure JDK team to see whether we can solve this issue, but there's no ETA for the fix.

Copy link
Contributor

github-actions bot commented Aug 7, 2024

Hi @moarychan, we deeply appreciate your input into this project. Regrettably, this issue has remained unresolved for over 2 years and inactive for 30 days, leading us to the decision to close it. We've implemented this policy to maintain the relevance of our issue queue and facilitate easier navigation for new contributors. If you still believe this topic requires attention, please feel free to create a new issue, referencing this one. Thank you for your understanding and ongoing support.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 7, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Aug 7, 2024
@github-project-automation github-project-automation bot moved this from In Progress to Done in Spring Cloud Azure Aug 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
azure-spring All azure-spring related issues azure-spring-native Issues related to Spring native. bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. Spring Monitor
Projects
Archived in project
Development

No branches or pull requests

8 participants