I have to access one https rest web service(https://example.com) for which certificate has been provided by the client which contains 2 .cer files.
I have created keystore.jks
and truststore.jks
files and imported the .cer files to jks file
. by using the below command
keytool -genkeypair -alias abcd -keyalg RSA -sigalg garegar -keysize 2048 -storetype jks -keystore keystore.jks -validity 365 -storepass changeit
keytool -import -alias abcd -trustcacerts -file free/ca_bundle.cer -keystore keystore.jksccessfull
I have added all properties to application.yml
truststore-location:
keystore-location:
truststore-password:
keystore-password:
key-alias:
Created the bean in configuration class to get the webclient object.
@Data
@NoArgsConstructor
@AllArgsConstructor
@Configuration
public class WebServiceRestConfig {
@Value(value = "${wcc.rest.endpoint}")
private String url;
@Value(value = "${wcc.dam.username}")
private String username;
@Value(value = "${wcc.dam.password}")
private String password;
@Value(value = "${ssl.truststore-location}")
private String trustStore;
@Value(value = "${ssl.keystore-location}")
private String keyStore;
@Value(value = "${ssl.truststore-password}")
private String trustStorePassword;
@Value(value = "${ssl.keystore-password}")
private String keyStorePassword;
@Value(value = "${ssl.key-alias}")
private String keyAlias;
@Bean
WebClientCustomizer configureWebclient() {
return (WebClient.Builder webClientBuilder) -> {
SslContext sslContext;
final PrivateKey privateKey;
final X509Certificate[] certificates;
try {
final KeyStore trustStore;
final KeyStore keyStore;
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(new FileInputStream(ResourceUtils.getFile(getTrustStore())),
trustStorePassword.toCharArray());
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(ResourceUtils.getFile(getKeyStore())), keyStorePassword.toCharArray());
List<Certificate> certificateList = Collections.list(trustStore.aliases()).stream().filter(t -> {
try {
return trustStore.isCertificateEntry(t);
} catch (KeyStoreException e1) {
throw new RuntimeException("Error reading truststore", e1);
}
}).map(t -> {
try {
return trustStore.getCertificate(t);
} catch (KeyStoreException e2) {
throw new RuntimeException("Error reading truststore", e2);
}
}).collect(Collectors.toList());
certificates = certificateList.toArray(new X509Certificate[certificateList.size()]);
privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyStorePassword.toCharArray());
Certificate[] certChain = keyStore.getCertificateChain(keyAlias);
X509Certificate[] x509CertificateChain = Arrays.stream(certChain)
.map(certificate -> (X509Certificate) certificate).collect(Collectors.toList())
.toArray(new X509Certificate[certChain.length]);
sslContext = SslContextBuilder.forClient().keyManager(privateKey, keyStorePassword, x509CertificateChain)
.trustManager(certificates).build();
HttpClient httpClient = HttpClient.create()
.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
webClientBuilder.clientConnector(connector).baseUrl(getUrl()).build();
} catch (KeyStoreException e) {
throw new RuntimeException(e);
}catch(CertificateException e) {
throw new RuntimeException(e);
}catch(NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}catch(IOException e) {
throw new RuntimeException(e);
}catch(UnrecoverableKeyException e) {
throw new RuntimeException(e);
}
};
}
}
But when i am running the application I am getting below exception
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is reactor.core.Exceptions$ReactiveException: javax.net.ssl.SSLHandshakeException: General SSLEngine problem] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:281)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1465)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:969)
Right now I am completely clueless what to do and how to resolve this do i need to add anything in resources folder or am i missing something here?