From ed3c91c7a74ba9a2bb913ed8135342f9853d48fb Mon Sep 17 00:00:00 2001 From: Abhi Shah Date: Wed, 18 Jan 2023 12:43:05 +0530 Subject: [PATCH 1/2] SSL certificate validation - method to add SSL certificate - README updated on how to set SSL certificate - Test case updated with commented code using SSL certificate --- README.md | 11 +++++++ .../src/main/java/com/splunk/HttpService.java | 33 ++++++++++++++----- .../src/test/java/com/splunk/SDKTestCase.java | 17 ++++++++-- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 06883597..25a314ad 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,17 @@ To build the documentation for the SDK, it is being automatically generated with cd splunk mvn javadoc:javadoc +###Using SSL Certificates +SSL Certificate validation is turned ON by default. Set SSL Certificate using below code statement +```java + HttpService.setSSLCert(); +``` +Note:- For local/Non-production/any other use cases SSL Certificate validation can be disabled using below line of code. +```java + HttpService.setValidateCertificates(false). +``` + + ### Usage #### Login using username and password ```java diff --git a/splunk/src/main/java/com/splunk/HttpService.java b/splunk/src/main/java/com/splunk/HttpService.java index 707daf24..d572dce2 100644 --- a/splunk/src/main/java/com/splunk/HttpService.java +++ b/splunk/src/main/java/com/splunk/HttpService.java @@ -17,11 +17,10 @@ package com.splunk; import javax.net.ssl.*; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; +import java.io.*; import java.net.*; +import java.security.KeyStore; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.List; @@ -46,6 +45,7 @@ public class HttpService { * Default Value: TRUE */ protected static boolean validateCertificates = true; + protected static byte[] sslCert = null; private static SSLSocketFactory sslSocketFactory = createSSLFactory(); private static String HTTPS_SCHEME = "https"; @@ -566,6 +566,12 @@ public static void setValidateCertificates(boolean validateCertificate) { } } + public static void setSSLCert(byte[] sslCertificate) { + // update the SSL_SOCKET_FACTORY when sslCert is set + sslCert = sslCertificate; + sslSocketFactory = createSSLFactory(); + } + public static SSLSocketFactory createSSLFactory() { try { @@ -578,12 +584,21 @@ public static SSLSocketFactory createSSLFactory() { } else { context = SSLContext.getDefault(); } - - if (validateCertificates) { + if (validateCertificates && sslCert == null) { + // On initialising before ssCert is set, TM and KM set to null context.init(null, null, null); - // For now this check is set as null. - // TODO: Implementation logic for validating client certificate. - } else { + } else if(sslCert != null){ + InputStream is = new ByteArrayInputStream(sslCert); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate)cf.generateCertificate(is); + TrustManagerFactory tmf = TrustManagerFactory + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null); // You don't need the KeyStore instance to come from a file. + ks.setCertificateEntry("cert", cert); + tmf.init(ks); + context.init(null, tmf.getTrustManagers(), null); + } else{ TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { diff --git a/splunk/src/test/java/com/splunk/SDKTestCase.java b/splunk/src/test/java/com/splunk/SDKTestCase.java index c2c623fa..232c34e5 100644 --- a/splunk/src/test/java/com/splunk/SDKTestCase.java +++ b/splunk/src/test/java/com/splunk/SDKTestCase.java @@ -92,9 +92,22 @@ public static Integer getJavaVersion() { } @BeforeClass - public static void preClassLoadActions() { - // Bypass the certification validation here. + public static void preClassLoadActions() throws IOException { + // To Bypass the certification validation. HttpService.setValidateCertificates(false); + /* + // To Set SSL Certificate use below code block + InputStream sslCertificate = ResourceRoot.class.getResourceAsStream("/Certificate.pem"); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + // read bytes from the input stream and store them in the buffer + while ((len = sslCertificate.read(buffer)) != -1) + { + os.write(buffer, 0, len); + } + HttpService.setSSLCert(os.toByteArray()); + */ } @Before From e3d89d5c62ca9b4e1feba5d490df6f2360a31618 Mon Sep 17 00:00:00 2001 From: Abhi Shah Date: Thu, 19 Jan 2023 15:42:27 +0530 Subject: [PATCH 2/2] README updates --- README.md | 22 ++++++++++-- .../src/main/java/com/splunk/HttpService.java | 35 +++++++++++-------- .../src/test/java/com/splunk/SDKTestCase.java | 3 +- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 25a314ad..b89daf2c 100644 --- a/README.md +++ b/README.md @@ -109,12 +109,12 @@ To build the documentation for the SDK, it is being automatically generated with cd splunk mvn javadoc:javadoc -###Using SSL Certificates -SSL Certificate validation is turned ON by default. Set SSL Certificate using below code statement +###SSL Certificate Verification +SSL Certificate validation is turned ON by default in Splunk Java SDK. Set SSL Certificate as shown below. ```java HttpService.setSSLCert(); ``` -Note:- For local/Non-production/any other use cases SSL Certificate validation can be disabled using below line of code. +Note:- For local/Non-production/any other use cases SSL Certificate validation can be disabled as shown below. ```java HttpService.setValidateCertificates(false). ``` @@ -123,6 +123,7 @@ Note:- For local/Non-production/any other use cases SSL Certificate validation c ### Usage #### Login using username and password ```java +import com.splunk.HttpService; import com.splunk.Service; import com.splunk.ServiceArgs; @@ -140,6 +141,9 @@ public class SplunkLogin { loginArgs.setUsername("USERNAME"); // Use your username loginArgs.setPassword("PASSWORD"); // Use your password + //set SSL Certificate for verification + byte[] sslCert = + HttpService.setSSLCert(sslCert); // Initialize the SDK client service = Service.connect(loginArgs); } @@ -148,6 +152,7 @@ public class SplunkLogin { #### Login using Session Token ```java +import com.splunk.HttpService; import com.splunk.Service; import com.splunk.ServiceArgs; @@ -170,6 +175,9 @@ public class SplunkLogin { loginArgs.setScheme("https"); loginArgs.setToken(String.format("Splunk %s", token)); + //set SSL Certificate for verification + byte[] sslCert = + HttpService.setSSLCert(sslCert); // Initialize the SDK client service = Service.connect(loginArgs); } @@ -184,6 +192,7 @@ public class SplunkLogin { #### Login using Authentication Token (RECOMMENDED) ```java +import com.splunk.HttpService; import com.splunk.Service; import com.splunk.ServiceArgs; @@ -206,6 +215,9 @@ public class SplunkLogin { loginArgs.setScheme("https"); loginArgs.setToken(String.format("Bearer %s", token)); + //set SSL Certificate for verification + byte[] sslCert = + HttpService.setSSLCert(sslCert); // Initialize the SDK client service = Service.connect(loginArgs); } @@ -217,6 +229,7 @@ public class SplunkLogin { import com.splunk.Job; import com.splunk.ResultsReader; import com.splunk.ResultsReaderXml; +import com.splunk.HttpService; import com.splunk.Service; import com.splunk.ServiceArgs; @@ -244,6 +257,9 @@ public class SearchExample { loginArgs.setScheme("https"); loginArgs.setToken(String.format("Bearer %s", token)); + //set SSL Certificate for verification + byte[] sslCert = + HttpService.setSSLCert(sslCert); // Initialize the SDK client service = Service.connect(loginArgs); diff --git a/splunk/src/main/java/com/splunk/HttpService.java b/splunk/src/main/java/com/splunk/HttpService.java index d572dce2..1ae1c406 100644 --- a/splunk/src/main/java/com/splunk/HttpService.java +++ b/splunk/src/main/java/com/splunk/HttpService.java @@ -436,6 +436,11 @@ Socket open() throws IOException { * @return The HTTP response. */ public ResponseMessage send(String path, RequestMessage request) { + + if(HttpService.validateCertificates && HttpService.sslCert == null){ + throw new RuntimeException("Set missing SSL Certificate for verification or Disable SSL verification and try again"); + } + // Construct a full URL to the resource URL url = getUrl(path); // Create and initialize the connection object @@ -584,20 +589,22 @@ public static SSLSocketFactory createSSLFactory() { } else { context = SSLContext.getDefault(); } - if (validateCertificates && sslCert == null) { - // On initialising before ssCert is set, TM and KM set to null - context.init(null, null, null); - } else if(sslCert != null){ - InputStream is = new ByteArrayInputStream(sslCert); - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate)cf.generateCertificate(is); - TrustManagerFactory tmf = TrustManagerFactory - .getInstance(TrustManagerFactory.getDefaultAlgorithm()); - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(null); // You don't need the KeyStore instance to come from a file. - ks.setCertificateEntry("cert", cert); - tmf.init(ks); - context.init(null, tmf.getTrustManagers(), null); + if (validateCertificates) { + if(sslCert == null){ + // On initialising before ssCert is set, TM and KM set to null + context.init(null, null, null); + }else{ + InputStream is = new ByteArrayInputStream(sslCert); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate)cf.generateCertificate(is); + TrustManagerFactory tmf = TrustManagerFactory + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null); // You don't need the KeyStore instance to come from a file. + ks.setCertificateEntry("cert", cert); + tmf.init(ks); + context.init(null, tmf.getTrustManagers(), null); + } } else{ TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() { diff --git a/splunk/src/test/java/com/splunk/SDKTestCase.java b/splunk/src/test/java/com/splunk/SDKTestCase.java index 232c34e5..9309c61a 100644 --- a/splunk/src/test/java/com/splunk/SDKTestCase.java +++ b/splunk/src/test/java/com/splunk/SDKTestCase.java @@ -95,8 +95,9 @@ public static Integer getJavaVersion() { public static void preClassLoadActions() throws IOException { // To Bypass the certification validation. HttpService.setValidateCertificates(false); - /* + // To Set SSL Certificate use below code block + /* InputStream sslCertificate = ResourceRoot.class.getResourceAsStream("/Certificate.pem"); ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] buffer = new byte[1024];