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

Add support for multiple/optional trust certificates #41932

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

elisabeteaprcd
Copy link

@elisabeteaprcd elisabeteaprcd commented Aug 19, 2024

Problem Statement

The challenge is the dynamic updating and management of certificates in an application that supports mTLS and interacts with client services that are frequently added and removed.

Suppose your application needs to support mTLS with two well-known client services, foo and bar, each having a specific intermediate CA (Certificate Authority). Client services are dynamically installed/removed from the cluster. For improved resiliency/manageability, you do not want to change the deployment of your application whenever a new client service is installed in the cluster: the client CAs must be dynamically added/removed to your server truststore as their services installed/removed from the cluster.

Proposed Solution

This PR aims to address this issue by allowing certificates to be marked as optional. With this feature, the application can start and continue running regardless of the availability of these certificates. And allows the addition of multiple certificates as mentioned here.

Current Status

This pull request is currently a draft/proof of concept. It does not yet include tests or documentation and is intended to gather feedback. The implementation includes several TODOs.

An example of an application.yaml with multiple/optional certificates would look like:

spring.ssl.bundle.pem.server.truststore.certificates[0]=optional:/var/secrets/foo/ca.crt
spring.ssl.bundle.pem.server.truststore.certificates[1]=optional:/var/secrets/bar/ca.crt
spring.ssl.bundle.pem.server.truststore.certificates[2]=/var/secrets/other/ca.crt

Some use cases:

1.The configuration with the deprecated property continues to work as expected:

spring.ssl.bundle.pem.server.keystore.certificate=classpath:certs/server.crt
spring.ssl.bundle.pem.server.keystore.private-key=classpath:certs/server.key
spring.ssl.bundle.pem.server.truststore.certificate=classpath:certs/ca.crt
spring.ssl.bundle.pem.server.reload-on-update=true
server.ssl.client-auth=need

TODO: Since the structure for loading certificates is the same for both keystore and truststore, should there be limitations on optionality and multiple certificates in the keystore? Should the certificate property allow optionality?

TODO: Consider creating a validation to ensure that certificate and certificates cannot be used simultaneously.

  1. In this case, both certificates in the truststore will be required for proper functionality.
spring.ssl.bundle.pem.server.keystore.certificates=classpath:certs/server.crt
spring.ssl.bundle.pem.server.keystore.private-key=classpath:certs/server.key
spring.ssl.bundle.pem.server.truststore.certificates[0]=/resources/main/ca.crt
spring.ssl.bundle.pem.server.truststore.certificates[1]=/resources/main/ca_cert.crt
spring.ssl.bundle.pem.server.reload-on-update=true
server.ssl.client-auth=need
  1. If the files (ca.crt and ca_cert) do not exist, they will be treated as empty, as no certificates will be available for loading at that moment. However, since the reload-on-update property is set to true, the parent directory will be monitored. Once changes are detected and the files become available, they will be loaded.
spring.ssl.bundle.pem.server.keystore.certificates=classpath:certs/server.crt
spring.ssl.bundle.pem.server.keystore.private-key=classpath:certs/server.key
spring.ssl.bundle.pem.server.truststore.certificates[0]=optional:/resources/main/ca.crt
spring.ssl.bundle.pem.server.truststore.certificates[1]=optional:/resources/main/ca_cert.crt
spring.ssl.bundle.pem.server.reload-on-update=true
server.ssl.client-auth=need
  1. In this case, if the isReloadOnUpdate property is set to true, the ca.crt certificate will still be observed.
spring.ssl.bundle.pem.server.keystore.certificates=classpath:certs/server.crt
spring.ssl.bundle.pem.server.keystore.private-key=classpath:certs/server.key
spring.ssl.bundle.pem.server.truststore.certificates[0]=optional:/resources/main/ca.crt
spring.ssl.bundle.pem.server.truststore.certificates[1]=`---BEGIN CERTIFICATE-----
MIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL
...
V0IJjcmYjEZbTvpjFKznvaFiOUv+8L7jHQ1/Yf+9c3C8gSjdUfv88m17pqYXd+Ds
ngX6JBJI7fw7tXoqWSLHNiBODM88fUlQSho8
-----END CERTIFICATE-----
spring.ssl.bundle.pem.server.reload-on-update=true
server.ssl.client-auth=need

TODO: Or should we keep the exception if one or more items in the list are not observable?

Related Issue

This PR is related to this comment in the issue #38754

@pivotal-cla
Copy link

@elisabeteaprcd 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 Aug 19, 2024
@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Aug 19, 2024
@scottfrederick
Copy link
Contributor

@elisabeteaprcd Thanks for the suggestion. We will take a look at the changes and give some feedback.

An alternative to these changes would be a boolean property at the top of the bundle structure such as spring.ssl.bundle.pem.server.required: false or spring.ssl.bundle.pem.server.ignore-non-existing: true that would provide the same "optional" behavior for all certificates in the bundle, without needing to introduce a new optional: keyword to the certificate property value. Would that also meet your needs?

@chicobento
Copy link
Contributor

Hi @scottfrederick,

Im also working with @elisabeteaprcd on this. While the scope of this change is to support optionality for the single item - which is what is currently supported by SB, the end goal is to have it working with multiple items as proposed in #38754 (comment).

So, in the scenario of multiple CAs we should be able to define which ones are mandatory for the service to start and which ones are optional, and in this sense your single-property proposal would not work at the spring boot level, however it could be expressed at the k8s deployment level by making the volume mounts mandatory.

@pivotal-cla
Copy link

@elisabeteaprcd Thank you for signing the Contributor License Agreement!

@elisabeteaprcd elisabeteaprcd changed the title Add support for optional trust certificates Add support for multiple/optional trust certificates Sep 10, 2024
@chicobento
Copy link
Contributor

hi @scottfrederick , just a heads-up that this has been now updated with support for multiple/optional certificates (initial PR had just support for optional)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: team-meeting An issue we'd like to discuss as a team to make progress status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants