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

FileNotFoundException is thrown eagerly from unused SSL bundles #38659

Closed
azeem87 opened this issue Dec 5, 2023 · 11 comments
Closed

FileNotFoundException is thrown eagerly from unused SSL bundles #38659

azeem87 opened this issue Dec 5, 2023 · 11 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@azeem87
Copy link

azeem87 commented Dec 5, 2023

Though I have configured it below and disabled the SSL for the local profile, it is still looking for the certificate file and private key file

application.yml

spring:
  ssl:
    bundle:
      pem:
        server-ssl-bundle:
          keystore:
            certificate: ${CERT_FILE_PATH}
            private-key: ${CERT_PRIVATE_KEY_PATH}

application-local.yml as per #2241

server:
  ssl:
    enabled: false 
.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.0)

16:37:43.205 [restartedMain] INFO  c.e.r.m.DemoApplication  Starting DemoApplication using Java 17.0.6 with PID 20963
16:37:43.208 [restartedMain] INFO  c.e.r.m.DemoApplication  The following 1 profile is active: "local"
16:37:44.738 [restartedMain] WARN  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext  Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server
16:37:44.766 [restartedMain] ERROR o.s.boot.SpringApplication  Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:610)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:323)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331)
        at DemoApplication.main(DemoApplication.java:27)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tomcatServletWebServerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]: Error creating bean with name 'servletWebServerFactoryCustomizer' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer]: Factory method 'servletWebServerFactoryCustomizer' threw exception with message: Error creating bean with name 'sslBundleRegistry' defined in class path resource [org/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:223)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:186)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
        ... 13 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'servletWebServerFactoryCustomizer' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer]: Factory method 'servletWebServerFactoryCustomizer' threw exception with message: Error creating bean with name 'sslBundleRegistry' defined in class path resource [org/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:643)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1166)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:663)
        at org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor.getWebServerFactoryCustomizerBeans(WebServerFactoryCustomizerBeanPostProcessor.java:87)
        at org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor.getCustomizers(WebServerFactoryCustomizerBeanPostProcessor.java:78)
        at org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor.postProcessBeforeInitialization(WebServerFactoryCustomizerBeanPostProcessor.java:70)
        at org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor.postProcessBeforeInitialization(WebServerFactoryCustomizerBeanPostProcessor.java:58)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:421)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1767)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
        ... 21 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer]: Factory method 'servletWebServerFactoryCustomizer' threw exception with message: Error creating bean with name 'sslBundleRegistry' defined in class path resource [org/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
        ... 38 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sslBundleRegistry' defined in class path resource [org/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: java.io.IOException: Error reading certificate or key from file '${SSL_CERT_FILE_PATH}'
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:643)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1166)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1441)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getIfAvailable(DefaultListableBeanFactory.java:2110)
        at org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration.servletWebServerFactoryCustomizer(ServletWebServerFactoryAutoConfiguration.java:81)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140)
        ... 39 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
        ... 57 common frames omitted
Caused by: java.io.UncheckedIOException: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.boot.autoconfigure.ssl.PropertiesSslBundle.get(PropertiesSslBundle.java:113)
        at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$0(SslPropertiesBundleRegistrar.java:59)
        at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$2(SslPropertiesBundleRegistrar.java:61)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
        at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.registerBundles(SslPropertiesBundleRegistrar.java:58)
        at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.registerBundles(SslPropertiesBundleRegistrar.java:52)
        at org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration.lambda$sslBundleRegistry$0(SslAutoConfiguration.java:59)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
        at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
        at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
        at org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration.sslBundleRegistry(SslAutoConfiguration.java:59)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140)
        ... 58 common frames omitted
Caused by: java.io.IOException: Error reading certificate or key from file '${CERT_FILE_PATH}'
        at org.springframework.boot.ssl.pem.PemContent.load(PemContent.java:125)
        at org.springframework.boot.ssl.pem.LoadedPemSslStore.loadCertificates(LoadedPemSslStore.java:49)
        at org.springframework.boot.ssl.pem.LoadedPemSslStore.<init>(LoadedPemSslStore.java:44)
        at org.springframework.boot.ssl.pem.PemSslStore.load(PemSslStore.java:101)
        at org.springframework.boot.autoconfigure.ssl.PropertiesSslBundle.getPemSslStore(PropertiesSslBundle.java:119)
        at org.springframework.boot.autoconfigure.ssl.PropertiesSslBundle.get(PropertiesSslBundle.java:103)
        ... 81 common frames omitted
Caused by: java.io.FileNotFoundException: /demo-service/${CERT_FILE_PATH} (No such file or directory)
        at java.base/java.io.FileInputStream.open0(Native Method)
        at java.base/java.io.FileInputStream.open(FileInputStream.java:216)
        at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
        at java.base/java.io.FileInputStream.<init>(FileInputStream.java:111)
        at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
        at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:189)
        at java.base/java.net.URL.openStream(URL.java:1161)
        at org.springframework.boot.ssl.pem.PemContent.load(PemContent.java:144)
        at org.springframework.boot.ssl.pem.PemContent.load(PemContent.java:122)
        ... 86 common frames omitted
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 5, 2023
@mhalbritter
Copy link
Contributor

mhalbritter commented Dec 5, 2023

Regardless of your server.ssl.enabled property, the SslBundles are still loaded on startup. They are loaded eagerly and not "on-request", e.g. when the webserver needs to get the bundle.

You could move the bundle definition from your application.yaml to a application-default.yaml. The default profile gets activated if no other profiles are active.

I don't think there's a way to override the map which contains "server-ssl-bundle" with an empty one in the local profile (see #22894).

Does this help?

@mhalbritter mhalbritter added the status: waiting-for-feedback We need additional information before we can continue label Dec 5, 2023
@azeem87
Copy link
Author

azeem87 commented Dec 5, 2023

@mhalbritter thanks for the comment, the same setup works in version 3.1.3

@mhalbritter
Copy link
Contributor

Thanks, that's an important information.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 5, 2023
@mhalbritter
Copy link
Contributor

mhalbritter commented Dec 5, 2023

That's a side effect of 9b71ef4#diff-d76d8c6ae728a7f8c886725ec85f5597140e17ec3c7ce3b9a2ccd935b19c87e5R103.

In 3.1.x, the loading of PEM stores (and I think JKS stores, too) was indeed lazy. In 3.2.x, this is no longer the case.

But I would argue that your setup only worked by accident in 3.1.x. You specified a SSL bundle with two (non-existent) files, and it was the implementation leaking out that this worked.

I'll flag this to get opinions from the team.

@mhalbritter mhalbritter added the for: team-attention An issue we'd like other members of the team to review label Dec 5, 2023
@azeem87
Copy link
Author

azeem87 commented Dec 5, 2023

@mhalbritter thanks for the quick reply, also please check this issue #2241 , where the spring team recommended to configure "server.ssl.enabled" property to conditionally disable SSL configuration based on profile.

@mhalbritter
Copy link
Contributor

mhalbritter commented Dec 5, 2023

The problem has nothing to do with SSL on your webserver.

It's failing because you defined an SslBundle and instructed it to load two files, which do not exist.

This worked in 3.1.x as nothing called getKeyStore from the bundle when SSL was disabled on your webserver and hence the SslBundle never tries to access the files. This doesn't work in 3.2.x anymore, as now we load the SslBundles eagerly on startup and hence the failure. This eager loading has nothing to do with SSL being enabled on your webserver or not.

@azeem87
Copy link
Author

azeem87 commented Dec 5, 2023

I completely understand @mhalbritter, but because of eager loading, why an existing functionality should break. This new change makes server.ssl.enabled property becomes obsolete.

Is it possible to apply condition based bean loading based on this property. Please share us your thoughts.

@philwebb
Copy link
Member

philwebb commented Dec 7, 2023

We might be able to change LoadedPemSslStore so that the loading is lazy. I think we'll need to discuss this a bit as team.

@mhalbritter mhalbritter added for: team-meeting An issue we'd like to discuss as a team to make progress and removed for: team-attention An issue we'd like other members of the team to review labels Dec 11, 2023
@philwebb
Copy link
Member

We're going to look at using SingletonSupplier to make LoadedPemSslStore lazy.

@philwebb philwebb added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided for: team-meeting An issue we'd like to discuss as a team to make progress labels Dec 14, 2023
@philwebb philwebb added this to the 3.2.x milestone Dec 14, 2023
@philwebb philwebb self-assigned this Dec 14, 2023
@philwebb philwebb changed the title Server SSL Disable State still checks for the certificate and private key file FileNotFoundException is thrown eagerly from unused SSL bundles Dec 14, 2023
@philwebb philwebb modified the milestones: 3.2.x, 3.2.1 Dec 15, 2023
@azeem87
Copy link
Author

azeem87 commented Dec 15, 2023

Thanks, @philwebb and @mhalbritter for the fix and the support from the spring team.

@lindanasredin
Copy link

lindanasredin commented Apr 21, 2024

@azeem87 How did you deal with security auto-configuration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants