diff --git a/doc/splunk-devops-usage.md b/doc/splunk-devops-usage.md index 2cb2b96b..8ba16996 100644 --- a/doc/splunk-devops-usage.md +++ b/doc/splunk-devops-usage.md @@ -147,7 +147,7 @@ Example: `java -Dsplunkins.buffer=4096 -jar jenkins.war` |splunkins.debugLogBatchSize|128|batch size for sending verbose level (FINE,FINER,FINEST) log record| |splunkins.enableRemoteTaskListenerDecorator|true|whether to capture remote TaskListener| |splunkins.ignoreConfigChangePattern|(?:queue|nodeMonitors|UpdateCenter|global-build-stats).xml|/(?:fingerprint|builds|config-history)/.*?xml|regular expression for ignoring config file changes| -|splunkins.verifySSL|false|enable ssl certificate verification for splunk endpoint| +|splunkins.verifySSL|false|enable ssl certificate verification for splunk endpoint,deprecated, use form config instead| |splunkins.junitStdioLimit|2097152|trim long junit standard output/error, set it to 0 for unlimited| |splunkins.decodePipelineConsole|true|decode pipeline job console note to get parallel label, link href| |splunkins.auditPostRequest|true|audit trail for script invoking, credentials updating| diff --git a/pom.xml b/pom.xml index 8d341267..243aab00 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,9 @@ splunk-artifactory Splunk Releases https://splunk.jfrog.io/splunk/ext-releases-local + + false + diff --git a/splunk-devops/src/main/java/com/splunk/splunkjenkins/SplunkJenkinsInstallation.java b/splunk-devops/src/main/java/com/splunk/splunkjenkins/SplunkJenkinsInstallation.java index 9a848bce..9dfad1b8 100644 --- a/splunk-devops/src/main/java/com/splunk/splunkjenkins/SplunkJenkinsInstallation.java +++ b/splunk-devops/src/main/java/com/splunk/splunkjenkins/SplunkJenkinsInstallation.java @@ -2,6 +2,7 @@ import com.splunk.splunkjenkins.model.EventType; import com.splunk.splunkjenkins.model.MetaDataConfigItem; +import com.splunk.splunkjenkins.utils.CustomSSLConnectionSocketFactory; import com.splunk.splunkjenkins.utils.SplunkLogService; import groovy.lang.GroovyCodeSource; import hudson.Extension; @@ -26,27 +27,16 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import java.net.*; +import java.security.cert.CertificateException; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import static com.splunk.splunkjenkins.Constants.*; -import static com.splunk.splunkjenkins.utils.LogEventHelper.getDefaultDslScript; -import static com.splunk.splunkjenkins.utils.LogEventHelper.nonEmpty; -import static com.splunk.splunkjenkins.utils.LogEventHelper.validateGroovyScript; -import static com.splunk.splunkjenkins.utils.LogEventHelper.verifyHttpInput; +import static com.splunk.splunkjenkins.utils.LogEventHelper.*; import static groovy.lang.GroovyShell.DEFAULT_CODE_BASE; import static java.util.regex.Pattern.CASE_INSENSITIVE; import static org.apache.commons.lang.StringUtils.isEmpty; @@ -80,6 +70,8 @@ public class SplunkJenkinsInstallation extends GlobalConfiguration { private String metadataSource; private String ignoredJobs; private Boolean globalPipelineFilter; + private Boolean verifyCertificate; + private String customCA; //below are all transient properties public transient Properties metaDataProperties = new Properties(); @@ -166,6 +158,7 @@ public boolean configure(StaplerRequest req, JSONObject formData) throws FormExc Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); this.metadataItemSet = null; // otherwise bindJSON will never clear it once set boolean previousState = this.enabled; + String previousCAConfig = this.customCA + "|" + this.verifyCertificate; req.bindJSON(this, formData); if (this.metadataItemSet == null) { this.metaDataConfig = ""; @@ -178,6 +171,14 @@ public boolean configure(StaplerRequest req, JSONObject formData) throws FormExc } updateCache(); save(); + String currentCAConfig = this.customCA + "|" + this.verifyCertificate; + // updated ca cert or tls verify flag + if (this.useSSL && this.enabled && !currentCAConfig.endsWith(previousCAConfig)) { + LOG.warning("tls config changed, need rebuild connection pool"); + this.enabled = false; + SplunkLogService.getInstance().rebuild(this.verifyCertificate, this.customCA); + this.enabled = true; + } if (previousState && !this.enabled) { //switch from enable to disable SplunkLogService.getInstance().stopWorker(); @@ -223,7 +224,9 @@ public FormValidation doCheckToken(@QueryParameter("value") String value) { @RequirePOST public FormValidation doTestHttpInput(@QueryParameter String host, @QueryParameter int port, @QueryParameter String token, @QueryParameter boolean useSSL, - @QueryParameter String metaDataConfig) { + @QueryParameter String metaDataConfig, @QueryParameter boolean verifyCertificate, + @QueryParameter String customCA + ) { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); //create new instance to avoid pollution global config SplunkJenkinsInstallation config = new SplunkJenkinsInstallation(false); @@ -233,6 +236,8 @@ public FormValidation doTestHttpInput(@QueryParameter String host, @QueryParamet config.useSSL = useSSL; config.metaDataConfig = metaDataConfig; config.enabled = true; + config.verifyCertificate = verifyCertificate; + config.customCA = customCA; config.updateCache(); if (!config.isValid()) { return FormValidation.error(Messages.InvalidHostOrToken()); @@ -268,6 +273,18 @@ public FormValidation doCheckIgnoredJobs(@QueryParameter String value) { return FormValidation.ok(); } + @RequirePOST + public FormValidation doCheckCustomCA(@QueryParameter("value") String value) { + if (StringUtils.isNotBlank(value)) { + try { + CustomSSLConnectionSocketFactory.textToX509Cert(value); + } catch (CertificateException e) { + return FormValidation.error("can not parse certificate"); + } + } + return FormValidation.ok(); + } + ////////END OF FORM VALIDATION///////// protected void updateCache() { if (!this.enabled) { @@ -534,6 +551,8 @@ public Map toMap() { map.put("retriesOnError", retriesOnError); map.put("metadataHost", metadataHost); map.put("metadataSource", metadataSource); + map.put("verifyCertificate", verifyCertificate); + map.put("customCA", customCA); return map; } @@ -645,6 +664,10 @@ private void migrate() { if (this.globalPipelineFilter == null) { this.globalPipelineFilter = true; } + if (this.verifyCertificate == null) { + // previous version doesn't have such field + this.verifyCertificate = Boolean.getBoolean("splunkins.verifySSL"); + } } public String getIgnoredJobs() { @@ -666,4 +689,24 @@ public void setGlobalPipelineFilter(Boolean globalPipelineFilter) { public boolean isPipelineFilterEnabled() { return Boolean.TRUE.equals(globalPipelineFilter); } + + public Boolean getVerifyCertificate() { + return verifyCertificate; + } + + public boolean isTlsVerify() { + return Boolean.TRUE.equals(verifyCertificate); + } + + public void setVerifyCertificate(Boolean verifyCertificate) { + this.verifyCertificate = verifyCertificate; + } + + public String getCustomCA() { + return customCA; + } + + public void setCustomCA(String customCA) { + this.customCA = customCA; + } } diff --git a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactory.java b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactory.java index b0d54bbe..3928ab6f 100644 --- a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactory.java +++ b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactory.java @@ -1,21 +1,74 @@ package com.splunk.splunkjenkins.utils; +import org.apache.commons.lang.StringUtils; import shaded.splk.org.apache.http.HttpHost; +import shaded.splk.org.apache.http.conn.ssl.NoopHostnameVerifier; import shaded.splk.org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import shaded.splk.org.apache.http.conn.ssl.TrustStrategy; import shaded.splk.org.apache.http.protocol.HttpContext; +import shaded.splk.org.apache.http.ssl.SSLContexts; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.logging.Level; +import static java.nio.charset.StandardCharsets.UTF_8; import static com.splunk.splunkjenkins.utils.MultipleHostResolver.NAME_DELIMITER; public class CustomSSLConnectionSocketFactory extends SSLConnectionSocketFactory { + public static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CustomSSLConnectionSocketFactory.class.getName()); + + public static SSLConnectionSocketFactory getSocketFactory(boolean verifyCA, String certificate) { + if (!verifyCA) { + SSLContext sslContext = null; + try { + TrustStrategy acceptingTrustStrategy = new TrustAllStrategy(); + sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); + } catch (Exception e) { + LOG.log(Level.WARNING, "init custom ssl context with TrustAllStrategy failed", e); + sslContext = SSLContexts.createDefault(); + } + return new CustomSSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); + } + // tls verify is on + SSLContext sslContext; + if (StringUtils.isNotBlank(certificate)) { + try { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + X509Certificate customCA = textToX509Cert(certificate); + trustStore.setCertificateEntry("splunk-http-events-ca", customCA); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + TrustManager[] trustManagers = tmf.getTrustManagers(); + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustManagers, null); + } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException | KeyManagementException ex) { + LOG.log(Level.WARNING, "init custom ssl context failed", ex); + //invalid CA or keystore error + sslContext = SSLContexts.createDefault(); + } + } else { + sslContext = SSLContexts.createDefault(); + } + return new CustomSSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); + } public CustomSSLConnectionSocketFactory(SSLContext sslContext, HostnameVerifier hostnameVerifier) { - super(sslContext, hostnameVerifier); + super(sslContext, new String[]{"TLSv1.3", "TLSv1.2"}, null, hostnameVerifier); } @Override @@ -23,8 +76,20 @@ public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, In if (host.getHostName().contains(NAME_DELIMITER)) { HttpHost resolvedHost = new HttpHost(remoteAddress.getHostName(), host.getPort(), host.getSchemeName()); return super.connectSocket(connectTimeout, socket, resolvedHost, remoteAddress, localAddress, context); - } else{ + } else { return super.connectSocket(connectTimeout, socket, host, remoteAddress, localAddress, context); } } + + public static X509Certificate textToX509Cert(String permCert) throws CertificateException { + X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(permCert.getBytes(UTF_8))); + return certificate; + } + + static class TrustAllStrategy implements TrustStrategy { + public boolean isTrusted(X509Certificate[] certificate, + String type) { + return true; + } + } } diff --git a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/LogEventHelper.java b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/LogEventHelper.java index beb1b1bc..58ea7d07 100644 --- a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/LogEventHelper.java +++ b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/LogEventHelper.java @@ -35,10 +35,14 @@ import org.apache.commons.io.IOUtils; import shaded.splk.org.apache.http.HttpResponse; import shaded.splk.org.apache.http.client.HttpClient; +import shaded.splk.org.apache.http.client.config.CookieSpecs; +import shaded.splk.org.apache.http.client.config.RequestConfig; import shaded.splk.org.apache.http.client.entity.GzipCompressingEntity; import shaded.splk.org.apache.http.client.methods.HttpPost; import shaded.splk.org.apache.http.client.utils.URIBuilder; +import shaded.splk.org.apache.http.conn.HttpClientConnectionManager; import shaded.splk.org.apache.http.entity.StringEntity; +import shaded.splk.org.apache.http.impl.client.HttpClients; import shaded.splk.org.apache.http.util.EntityUtils; import java.io.*; @@ -138,7 +142,10 @@ private static void updateContent(HttpPost postMethod, String message, boolean i public static FormValidation verifyHttpInput(SplunkJenkinsInstallation config) { HttpPost post = buildPost(new EventRecord("ping from jenkins plugin", EventType.LOG), config); - HttpClient client = SplunkLogService.getInstance().getClient(); + HttpClientConnectionManager mgr=SplunkLogService.getInstance().buildConnectionManager(config.isTlsVerify(),config.getCustomCA()); + HttpClient client=HttpClients.custom().setConnectionManager(mgr).useSystemProperties() + .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()) + .build(); try { HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() != 200) { @@ -165,6 +172,7 @@ public static FormValidation verifyHttpInput(SplunkJenkinsInstallation config) { return FormValidation.error(e.getMessage()); } finally { post.releaseConnection(); + mgr.shutdown(); } return FormValidation.ok("Splunk connection verified"); } diff --git a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/SplunkLogService.java b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/SplunkLogService.java index a4951ae0..33a5de34 100644 --- a/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/SplunkLogService.java +++ b/splunk-devops/src/main/java/com/splunk/splunkjenkins/utils/SplunkLogService.java @@ -15,17 +15,12 @@ import shaded.splk.org.apache.http.conn.HttpClientConnectionManager; import shaded.splk.org.apache.http.conn.socket.ConnectionSocketFactory; import shaded.splk.org.apache.http.conn.socket.PlainConnectionSocketFactory; -import shaded.splk.org.apache.http.conn.ssl.NoopHostnameVerifier; import shaded.splk.org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import shaded.splk.org.apache.http.conn.ssl.TrustStrategy; import shaded.splk.org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; import shaded.splk.org.apache.http.impl.client.HttpClients; import shaded.splk.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import shaded.splk.org.apache.http.protocol.HttpContext; -import shaded.splk.org.apache.http.ssl.SSLContexts; -import javax.net.ssl.SSLContext; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -42,7 +37,6 @@ public class SplunkLogService { public static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(SplunkLogService.class.getName()); - private static final boolean VERIFY_SSL = Boolean.getBoolean("splunkins.verifySSL"); private final static int SOCKET_TIMEOUT = 3; private final static int QUEUE_SIZE = Integer.getInteger(SplunkLogService.class.getName() + ".queueSize", 1 << 17); private final static long KEEP_ALIVE_TIME_MINUTES = 2; @@ -60,8 +54,8 @@ private SplunkLogService() { this.workers = new ArrayList(); } - private void initHttpClient() { - this.connMgr = buildConnectionManager(); + private void initHttpClient(boolean verifyCA, String certificate) { + this.connMgr = buildConnectionManager(verifyCA, certificate); ConnectionKeepAliveStrategy myStrategy = new DefaultConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) { @@ -73,36 +67,27 @@ public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpCont } }; this.client = HttpClients.custom() - .setConnectionManager(this.connMgr) - .setKeepAliveStrategy(myStrategy) - .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()) - .useSystemProperties() - .build(); + .setConnectionManager(this.connMgr) + .setKeepAliveStrategy(myStrategy) + .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()) + .useSystemProperties() + .build(); } public static SplunkLogService getInstance() { return InstanceHolder.service; } - private HttpClientConnectionManager buildConnectionManager() { - SSLConnectionSocketFactory sslConnectionSocketFactory = null; - if (!VERIFY_SSL) { - SSLContext sslContext = null; - try { - TrustStrategy acceptingTrustStrategy = new TrustAllStrategy(); - sslContext = SSLContexts.custom().setProtocol("TLSv1.2").loadTrustMaterial( - null, acceptingTrustStrategy).build(); - } catch (Exception e) { - sslContext = SSLContexts.createDefault(); - } - sslConnectionSocketFactory = new CustomSSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); - } else { - sslConnectionSocketFactory = new SSLConnectionSocketFactory( - SSLContexts.createDefault(), - new String[]{"TLSv1.2"}, - null, - SSLConnectionSocketFactory.getDefaultHostnameVerifier()); - } + public void rebuild(boolean verifyCA, String certificate) { + LOG.warning("refresh http client configs, shutdown connection pool"); + stopWorker(); + connMgr.shutdown(); + initHttpClient(verifyCA, certificate); + } + + protected static HttpClientConnectionManager buildConnectionManager(boolean verifyCA, String certificate) { + LOG.log(Level.FINE, "build connection mgr using verify-ca={0} root-ca={1}", new Object[]{verifyCA, certificate}); + SSLConnectionSocketFactory sslConnectionSocketFactory = CustomSSLConnectionSocketFactory.getSocketFactory(verifyCA, certificate); Registry registry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory) @@ -168,7 +153,7 @@ record = new EventRecord(message, eventType); } else { record = (EventRecord) message; } - Object content=record.getMessage(); + Object content = record.getMessage(); if (content == null || "".equals(content) || "\n".equals(content)) { continue; } @@ -329,7 +314,8 @@ private static class InstanceHolder { static { service = new SplunkLogService(); try { - service.initHttpClient(); + SplunkJenkinsInstallation splkInstall = SplunkJenkinsInstallation.get(); + service.initHttpClient(splkInstall.isTlsVerify(), splkInstall.getCustomCA()); } catch (java.lang.NoSuchFieldError e) { /* java.lang.NoSuchFieldError: INSTANCE @@ -346,11 +332,4 @@ public String getStats() { .append("sent:").append(this.getSentCount()); return sbr.toString(); } - - static class TrustAllStrategy implements TrustStrategy { - public boolean isTrusted(X509Certificate[] certificate, - String type) { - return true; - } - } } diff --git a/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/config.jelly b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/config.jelly index 6bbfd321..5a15dfcc 100644 --- a/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/config.jelly +++ b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/config.jelly @@ -19,6 +19,12 @@ help="/descriptorByName/com.splunk.splunkjenkins.SplunkJenkinsInstallation/help/httpInputConfig"> + + + + + + @@ -26,7 +32,7 @@ + with="host,port,token,useSSL,metaDataConfig,verifyCertificate,customCA"/> diff --git a/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-customCA.html b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-customCA.html new file mode 100644 index 00000000..42ee2968 --- /dev/null +++ b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-customCA.html @@ -0,0 +1,12 @@ +
+ PEM formatted CA certificate
+ please check splunk doc + How to self-sign certificates
+ the "HTTP Input Host" field should match certificate's common name or one of the subject alternative names.
+ splunk default CA certificate is $SPLUNK_HOME/auth/cacert.pem, please only copy certificate from section
+ "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
+ To verify CA using curl command
+ + curl --cacert $SPLUNK_HOME/auth/cacert.pem https://host:port/services/collector/health + +
\ No newline at end of file diff --git a/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-verifyCertificate.html b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-verifyCertificate.html new file mode 100644 index 00000000..82db69d6 --- /dev/null +++ b/splunk-devops/src/main/resources/com/splunk/splunkjenkins/SplunkJenkinsInstallation/help-verifyCertificate.html @@ -0,0 +1,3 @@ +
+ If checked, server certificate will be verified using system default trusted certificates and custom certificate if provided +
\ No newline at end of file diff --git a/splunk-devops/src/test/java/com/splunk/splunkjenkins/SplunkConfigUtil.java b/splunk-devops/src/test/java/com/splunk/splunkjenkins/SplunkConfigUtil.java index d9856dd1..57adbfe8 100644 --- a/splunk-devops/src/test/java/com/splunk/splunkjenkins/SplunkConfigUtil.java +++ b/splunk-devops/src/test/java/com/splunk/splunkjenkins/SplunkConfigUtil.java @@ -124,6 +124,7 @@ public static boolean setupSender(String host, String token) { config.setHost(host); config.setPort(8088); config.setUseSSL(true); + config.setVerifyCertificate(false); config.setToken(token); config.setRawEventEnabled(true); config.setEnabled(true); diff --git a/splunk-devops/src/test/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactoryTest.java b/splunk-devops/src/test/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactoryTest.java new file mode 100644 index 00000000..7ba2ac5d --- /dev/null +++ b/splunk-devops/src/test/java/com/splunk/splunkjenkins/utils/CustomSSLConnectionSocketFactoryTest.java @@ -0,0 +1,49 @@ +package com.splunk.splunkjenkins.utils; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +public class CustomSSLConnectionSocketFactoryTest extends TestCase { + + @Test + public void testTextToX509Cert() throws CertificateException { + String testCA = + "-----BEGIN CERTIFICATE-----\n" + + "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\n" + + "-----END CERTIFICATE-----"; + X509Certificate cert = CustomSSLConnectionSocketFactory.textToX509Cert(testCA); + Assert.assertNotNull(cert.getIssuerDN().getName()); + } +} \ No newline at end of file