Hakky54 opened a new pull request, #706:
URL: https://github.com/apache/tomcat/pull/706

   This PR is a followup of the following earlier PR 
https://github.com/apache/tomcat/pull/673 Although that pull request didn't get 
merged, the code changes has been comitted to the main branch by the main 
developer, see here for the specific commit: 
https://github.com/apache/tomcat/commit/b0df9819c8d130adab0490b89dce1ab4ca6a3448
   
   **Context**
   With the earlier commit it is now possible to programatically configure the 
ssl configuration of tomcat instead of using properties and delegating to 
tomcat to construct the ssl configuration. This opens the possibility of 
reloading the ssl configuration or other sorts of customizations.
   
   I want to provide an example with my own code to give a better 
understanding, the project is also available here: [Instant SSL Reloading with 
Tomcat](https://github.com/Hakky54/java-tutorials/tree/main/instant-ssl-reloading-with-spring-tomcat)
   
   **SSLContext wrapper**
   ```java
   import nl.altindag.ssl.SSLFactory;
   import org.apache.tomcat.util.net.SSLContext;
   
   import javax.net.ssl.KeyManager;
   import javax.net.ssl.SSLEngine;
   import javax.net.ssl.SSLParameters;
   import javax.net.ssl.SSLServerSocketFactory;
   import javax.net.ssl.SSLSessionContext;
   import javax.net.ssl.TrustManager;
   import java.security.SecureRandom;
   import java.security.cert.X509Certificate;
   
   public final class TomcatSSLContext implements SSLContext {
   
       private final SSLFactory sslFactory;
   
       public TomcatSSLContext(SSLFactory sslFactory) {
           this.sslFactory = sslFactory;
       }
   
       @Override
       public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) {
           // not needed to initialize as it is already initialized
       }
   
       @Override
       public void destroy() {
   
       }
   
       @Override
       public SSLSessionContext getServerSessionContext() {
           return sslFactory.getSslContext().getServerSessionContext();
       }
   
       @Override
       public SSLEngine createSSLEngine() {
           return sslFactory.getSSLEngine();
       }
   
       @Override
       public SSLServerSocketFactory getServerSocketFactory() {
           return sslFactory.getSslServerSocketFactory();
       }
   
       @Override
       public SSLParameters getSupportedSSLParameters() {
           return sslFactory.getSslParameters();
       }
   
       @Override
       public X509Certificate[] getCertificateChain(String alias) {
           return sslFactory.getKeyManager()
                   .map(keyManager -> keyManager.getCertificateChain(alias))
                   .orElseThrow();
       }
   
       @Override
       public X509Certificate[] getAcceptedIssuers() {
           return sslFactory.getTrustedCertificates().toArray(new 
X509Certificate[0]);
       }
   
   }
   ```
   
   ```java
   import nl.altindag.ssl.SSLFactory;
   import org.apache.catalina.connector.Connector;
   import org.apache.coyote.http11.AbstractHttp11Protocol;
   import org.apache.tomcat.util.net.SSLHostConfig;
   import org.apache.tomcat.util.net.SSLHostConfigCertificate;
   import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
   import org.springframework.beans.factory.annotation.Value;
   import 
org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
   import org.springframework.context.annotation.Configuration;
   
   @Configuration
   public class SSLConnectorCustomizer implements TomcatConnectorCustomizer {
   
       private final SSLFactory sslFactory;
       private final int port;
   
       public SSLConnectorCustomizer(SSLFactory sslFactory, 
@Value("${server.port}") int port) {
           this.sslFactory = sslFactory;
           this.port = port;
       }
   
       @Override
       public void customize(Connector connector) {
           connector.setScheme("https");
           connector.setSecure(true);
           connector.setPort(port);
   
           AbstractHttp11Protocol<?> protocol = (AbstractHttp11Protocol<?>) 
connector.getProtocolHandler();
           protocol.setSSLEnabled(true);
   
           SSLHostConfig sslHostConfig = new SSLHostConfig();
           SSLHostConfigCertificate certificate = new 
SSLHostConfigCertificate(sslHostConfig, Type.UNDEFINED);
           certificate.setSslContext(new TomcatSSLContext(sslFactory));
           sslHostConfig.addCertificate(certificate);
           protocol.addSslHostConfig(sslHostConfig);
       }
   
   }
   ```
   
   **Problem statement**
   Boilerplate code is needed by the end-user to provide a custom ssl 
configuration. Tomcat takes a custom SSLContext, the full name is 
`org.apache.tomcat.util.net.SSLContext` while the end-user has 
`javax.net.ssl.SSLContext`. So the end-user is required to create an 
implementation of `org.apache.tomcat.util.net.SSLContext` which acts as a 
wrapper. This sslcontext needs to be passed to `SSLHostConfigCertificate` to 
further configure the server.
   
   **Solution**
   Provide a helper class which acts as a wrapper to reduce the boilerplate 
code. The interface is able to provide a method to wrap the required objects, 
in this case `javax.net.ssl.SSLContext`, KeyManager, TrustManager in a 
`org.apache.tomcat.util.net.SSLContext`


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to