Securing RESTful Connections: Enabling and Disabling SSL with Spring Boot

Rakesh
System Weakness
Published in
5 min readFeb 7, 2024

--

Photo by Markus Spiske on Unsplash

Embarking on any topic starts with getting the flavour of the basics. Let’s spice it up and dig into the core!

What exactly is SSL?
SSL stands for Secure Socket Layer. It’s a standard security technology used for establishing an encrypted link between a server and a client, typically a web server (like a website) and a browser. SSL ensures that all data transmitted between the server and browser remains encrypted and secure.

Why is SSL necessary?

  • Data Security: SSL encrypts data transmitted over the internet, preventing unauthorised access or eavesdropping.
  • Trust and Authentication: SSL certificates verify the identity of websites, assuring users that they’re connecting to legitimate servers and not imposters.
  • Compliance: Many data protection regulations require SSL encryption to protect sensitive information.

What are the consequences of not having SSL?

  • Data transmitted over the network could be intercepted and read by attackers.
  • Users might hesitate to input sensitive information (like passwords or credit card details) on unsecured websites, leading to loss of trust and potential loss of business.

How is an SSL certificate generated?
SSL certificates are generated using public key cryptography. Certification Authorities (CAs) issue SSL certificates after verifying the identity of the certificate holder, which includes information like domain ownership and organisation details.

How is an SSL certificate applied and utilized?
SSL involves a handshake process where the client (browser) and server establish a secure connection. Here are the steps:

  • The server has an SSL certificate installed.
  • When a client (browser) connects to the server, it requests the server’s SSL certificate.
  • The server sends the SSL certificate to the client.
  • The client verifies the certificate’s authenticity and checks if it trusts the issuer.
  • If verified, the client and server establish a secure, encrypted connection for data exchange.

How can SSL certificates be employed with Application?
Many articles and resources suggest disabling SSL for non-production environments. However, developers often prefer to have control and visibility into how most components behave, especially in their local environments. This allows them to closely monitor and understand the behavior of the systems they’re working on, even if it means configuring SSL differently.

To straightforwardly disable SSL certificate verification using RestTemplate recommended for only local environment.

// Method to get a RestTemplate with SSL verification disabled
public RestTemplate getRestTemplate() throws NoSuchAlgorithmException, KeyManagementException {

// Create SSL context to trust all certificates
SSLContext sslContext = SSLContext.getInstance("TLS");

// Define trust managers to accept all certificates
TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
// Method to check client's trust - accepting all certificates
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
}

// Method to check server's trust - accepting all certificates
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}

// Method to get accepted issuers - returning an empty array
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}};

// Initialize SSL context with the defined trust managers
sslContext.init(null, trustManagers, null);

// Disable SSL verification for RestTemplate

// Set the default SSL socket factory to use the custom SSL context
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

// Set the default hostname verifier to allow all hostnames
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);

// Create a RestTemplate with a custom request factory

// Build RestTemplate with SimpleClientHttpRequestFactory
RestTemplate restTemplate = new RestTemplateBuilder().requestFactory(SimpleClientHttpRequestFactory.class)
.build();

return restTemplate; // Return the configured RestTemplate
}

Are you wondering where we typically store these necessary certificates within an application for local development?

Discover the certificates currently employed by the JVM by executing the provided command.

command: keytool -list -keystore $JAVA_HOME/lib/security/cacerts

example: keytool -list -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts

To import a certificate into the JVM’s default truststore (cacerts), you can use the keytool command in Java.

command: keytool -import -alias your_alias -file /path/to/certificate.crt -keystore /path/to/keystore.jks

example:sudo keytool -import -alias _.view.com.cer -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts -file /Users/rid/Downloads/_.examplecertificate.com.cer

After adding the certificate, restart the application. Then, verify the available keystores locally. The default password for the keystore is usually set as “changeit”.

userid@USER security % keytool -list -keystore /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/security/cacerts
Warning: use -cacerts option to access cacerts keystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 92 entries

_.examplecertificate.com.cer, 03-Dec-2023, trustedCertEntry,
Certificate fingerprint (SHA-256): 1C:1D:EB:88:FD:FA:DF:85:21:CB:4A:B1:4B:54:A8:F9:20:A4:3B:23:F9:47:2A:92:51:F4:D0:C2:B3:C1:C2:EA

Let’s look into adding SSL certificates in a production environment.

We encourage to convert the dowloaded or received certificate into .jks file where you can keep in your trustworthy location. We prefer to store it in valut and our application access this to serve this request.

# Importing the certificate into the JKS keystore
keytool -import -v -trustcacerts -alias certificateView -file ./_.certificateName.com.cer -keystore jksname.jks -keypass secret -storepass changeit

# Listing the contents of the JKS keystore
keytool -list -v -keystore jksname.jks

# Convert to base64 encoded format
cat jksname.jks | base64
# JVM option to enable debugging for SSL/TLS
-Djavax.net.debug=all

# This help you to check the all the certificates
openssl s_client -connect login.view.com:443 -showcerts > ~/Downloads/chain.txt

Just downloading from the browser can give a certificate which can be intermediate certificate. Where few needs the chain of certificate with Root CA, intermediate certificate. All these are needed for successful ssl connection.

# Help you to download all the chain certificates and stored in different files
openssl s_client -connect login.view.com:443 -showcerts </dev/null | awk '/BEGIN CERT/{out="cert"++i".pem"}; {if(out) print > out}'

The code snippet retrieves SSL configuration settings, including trust store and trust password, from an external source, likely a vault. It then sets up an HTTP client factory with basic authentication, ensuring that confidential details are not hardcoded in the application code. This approach enhances security and allows for easier management of sensitive data.

@Bean
ConnectionConfiguration getConfiguration() {
ConnectionConfiguration config = new ConnectionConfiguration();
byte[] trustStoreBytes = Base64.getDecoder().decode(defaultConfiguration.getTrustStore());
SSLConfiguration sslConfiguration =
new SSLConfiguration(
new ByteArrayInputStream(trustStoreBytes),
defaultConfiguration.getTrustPass().toCharArray());
config.setSslConfiguration(sslConfiguration);
return config;
}

@Bean
public OkHttpClientFactory basicAuthHttpClientFactory() {
ConnectionConfiguration config = getConfiguration();
config.setConnectionAuthType(AuthenticationType.NONE);
OkHttpClientFactory httpClientFactory = new OkHttpClientFactory(config);
return httpClientFactory;
}

@Bean
RestClient getRestClient(
@Autowired OkHttpClientFactory httpClientFactory,
@Autowired ObjectMapper objectMapper) {
return new OkHttpRestClient(httpClientFactory, objectMapper);
}

The getConfiguration() method retrieves a ConnectionConfiguration object with SSL settings, including trust store and trust password, from a base64-encoded string.

The basicAuthHttpClientFactory() method creates an OkHttpClientFactory bean for configuring an HTTP client with basic authentication. It sets the connection authentication type to "NONE" and initializes the factory with the ConnectionConfiguration obtained earlier.

In conclusion, the provided code snippet demonstrates a secure approach to configuring HTTP client connections in a Spring application, emphasizing the importance of SSL encryption and certificate management. By externalizing sensitive data and leveraging SSL configurations, the code enhances security and mitigates risks associated with hardcoded credentials. This implementation ensures secure communication over HTTPS while maintaining flexibility and ease of management within the application architecture.

--

--

Staff Software Engineer, Software Designer, Programmer worked @ Equinix