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

FileWatcher used for SSL reload does not support symlinks #43586

Conversation

tmaciejewski
Copy link
Contributor

This allows using symlinks for SSL certificate hot reloading.

In my company we have services on k8s with SSL certificates stored on a mounted volumes. Since they are symlinks, we cannot use hot-reloading, because the content is changed in the file under the symlink, not the symlink itself. This change make FileWatcher watch not only the symlink, but also the file it resolves to.

This allows using symlinks for SSL certificate hot reloading.
@pivotal-cla
Copy link

@tmaciejewski Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 20, 2024
@pivotal-cla
Copy link

@tmaciejewski Thank you for signing the Contributor License Agreement!

@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 20, 2024
@philwebb philwebb changed the title Add support for symlinks in FileWatcher FileWatcher used for SSL reload does not support symlinks Dec 20, 2024
@philwebb philwebb added this to the 3.3.x milestone Dec 20, 2024
Copy link
Member

@snicoll snicoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. This looks good but I am wondering about something and added a question.

private Set<Path> resolveSymlinks(Set<Path> paths) throws IOException {
Set<Path> result = new HashSet<>();
for (Path path : paths) {
result.add(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for adding the symlink to the files to watch. Shouldn't we only add the real file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. Yeah, you're right. I wanted to keep backward compatibility, but since the real file is watched, it would still be there if the link is changed to some other file, which is less intuitive. Changed it to watch only the real file.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Dec 23, 2024
@snicoll snicoll removed the status: waiting-for-feedback We need additional information before we can continue label Dec 24, 2024
@snicoll snicoll self-assigned this Dec 24, 2024
@snicoll snicoll modified the milestones: 3.3.x, 3.3.8 Dec 24, 2024
snicoll pushed a commit that referenced this pull request Dec 24, 2024
This commit allows using symlinks for SSL certificate hot reloading.

See gh-43586
snicoll added a commit that referenced this pull request Dec 24, 2024
@snicoll snicoll closed this in a5b917f Dec 24, 2024
@snicoll
Copy link
Member

snicoll commented Dec 24, 2024

@tmaciejewski thank you for making your first contribution to Spring Boot.

bclozel added a commit that referenced this pull request Jan 28, 2025
Prior to this commit, a change in gh-43586 unlocked the support for
symlinks: instead of watching the link itself which might never change,
this would watch the target file which is likely to change.

This could break with an `IllegalStateException` in case the symlink is
using a path relative to the link itself.

This commit ensures that the target is resolved against the current
link path to avoid incorrect watch operations.

Fixes gh-43966
@PetarDimitrovZH
Copy link

PetarDimitrovZH commented Feb 18, 2025

Hi Everyone!

Is this released? I have the same or similar issue. I use kubernetes cert manager in order to manage my certs. It stores those as sym links:

drwxr-xr-x 2 maniax maniax 4096 Feb 18 10:58 ..data
lrwxrwxrwx 1 maniax maniax   19 Feb 18 10:59 keystore.p12 -> ..data/keystore.p12
lrwxrwxrwx 1 maniax maniax   21 Feb 18 11:00 truststore.p12 -> ..data/truststore.p12

ssl config:

spring:
  application:
    name: "shell"
  ssl:
    bundle:
      jks:
        shell:
          reload-on-update: false
          keystore:
            location: ${KEYSTORE:file:/opt/certs/keystore.p12}
            password: ${KEYSTORE_PW:changeit}
            type: "PKCS12"
          truststore:
            location: ${TRUSTSTORE:file:/opt/certs/truststore.p12}
            password: ${TRUSTSTORE_PW:changeit}
            type: "PKCS12"

But somehow spring cannot resolve them and I got this exception:

Caused by: java.lang.IllegalStateException: Unable to watch for reload on update
	at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.watchForUpdates(SslPropertiesBundleRegistrar.java:85) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$2(SslPropertiesBundleRegistrar.java:70) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	... 74 common frames omitted
Caused by: java.io.UncheckedIOException: Failed to register paths for watching: [/opt/certs/keystore.p12, /opt/certs/truststore.p12]
	at org.springframework.boot.autoconfigure.ssl.FileWatcher.watch(FileWatcher.java:96) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.watchForUpdates(SslPropertiesBundleRegistrar.java:82) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	... 75 common frames omitted
Caused by: java.io.IOException: '/home/maniax/projects/am-hub/..data/keystpre.p12' is neither a file nor a directory
	at org.springframework.boot.autoconfigure.ssl.FileWatcher$WatcherThread.register(FileWatcher.java:150) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	at org.springframework.boot.autoconfigure.ssl.FileWatcher.watch(FileWatcher.java:93) ~[spring-boot-autoconfigure-3.4.2.jar:3.4.2]
	... 76 common frames omitted

**The problem is in the FileWatcher class witch resolves the file wrong and add the wrong absolute path to the resolved file. I my case int should prepend /opt/certs. The corect path is /opt/certs/..data/keystore.p12

image

The logs are from my local machine but in a kubernetes cluster I got the same result, just the path prefix is the path where the jar file executed.**

Can anyone help?

@bclozel
Copy link
Member

bclozel commented Feb 18, 2025

@PetarDimitrovZH See #43966 which will be released this week.

@PetarDimitrovZH
Copy link

@bclozel Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants