Mutual Authentication(Two-Way TLS/SSL) with cloud residing KeyStores and TrustStores(Secret Manager) -Spring boot

2.2k views Asked by At


I'm working on Mutual Authentication in spring boot and I could implement it locally and its running smooth.
But I wanted to get certificates/stores from Amazon/Google certificates manager or may be from s3 bucket.

Previous Configuration
As I have stores locally, this way i could get them

#ApplicationProperties.yaml
server.ssl.enabled=true
#KeyStore
server.ssl.key-alias=1
server.ssl.key-store=classpath:clientKeystore.p12
server.ssl.key-store-password=whatever

#TrustStore
server.ssl.trust-store=classpath:clientTrustStore.p12
server.ssl.trust-store-password=possiblyAnything
server.ssl.client-auth=need

RestTemplate Configuration

   @Value("${server.ssl.trust-store}")
   private String trustStorePath;
   @Value("${server.ssl.trust-store-password}")
   private String trustStorePass;
   @Value("${server.ssl.key-store}")
   private String keyStorePath;
   @Value("${server.ssl.key-store-password}")
   private String keyStorePass;
   @Value("${server.ssl.key-alias}")
@Bean
public RestTemplate restTemplate()       
{
         SSLContext sslContext = null;
         SSLConnectionSocketFactory sslSocketFactory = 
                 new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
         sslContext = new SSLContextBuilder()
                       .loadKeyMaterial(keystore, keyStorePassword)
                       .loadTrustMaterial(trustStore,new TrustSelfSignedStrategy())
                       .build();
          HttpClient httpClient  = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
           HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
           requestFactory.setHttpClient(httpClient);
           return new RestTemplate(requestFactory);
}

Now the same truststores and keystores are in the cloud, and i want to fetch them at Application load/start time.


I'm really confused Why are we using stores both in config(appPropeties) and in sslContext. Whats the difference ?
Can't I just set them at sslContext alone ? If i can do that, i can just fetch them from cloud, process it into keystore and truststore, set them right away.
*Is there a better working approach?*
Pardon if this looks lame, I'm new to security so still i'm figuring out how things work.

**Also one more question**
  • In a typical Client Server setting(Multiple servers), what if i want to communicate with server1 on mutual TLS and server2 on http(without ssl)
2

There are 2 answers

1
stackstack293 On

It could happen that your application have to trust certificates that are used by another applications you are communicating with, and that is managed by the same company. In this case you can create a truststore locally and use it. You don't need certificates signed by a company that are used in general for websites.

You don't need to set keystore/truststore in both the places. My preferred way to set the keystore and truststore:

@Configuration
public class SSLConfig {
    @Autowired private Environment env;

    @PostConstruct
    private void configureSSL() {
        System.setProperty("javax.net.ssl.keyStore", env.getProperty("server.ssl.key-store"));
        System.setProperty("javax.net.ssl.keyStorePassword", env.getProperty("server.ssl.key-store-password"));
        System.setProperty("javax.net.ssl.trustStore", env.getProperty("server.ssl.trust-store"));
        System.setProperty("javax.net.ssl.trustStorePassword", env.getProperty("server.ssl.trust-store-password"));
    }
}

In the application.properties:

server.ssl.key-store=keystores/client.jks
server.ssl.key-store-password=changeit
server.ssl.trust-store=keystores/mycustom.truststore
server.ssl.trust-store-password=changeit
0
wunt On

The difference is in upstream and downstream configuration.

application.properties:

When you use application.properties with server.ssl.* you are actually configures your server side. I.e. you are creating server.port to accept https traffic with specified server.ssl.key. server.ssl.client-auth=need specifies that client's browser (or another app) should use client certificate to pass authentication. And server.ssl.trust-store specifies trusted client's certificates.

sslContext:

When you use sslContext you are configuring your outbound connections from your java app to outside services. And you use loadKeyMaterial and loadTrustMaterial for use some third-party service in your app. loadTrustMaterial specifies which server certificates you are trusting and loadKeyMaterial specifies which key your app should use to connect to some resource.