Skip to content

Commit

Permalink
JENKINS-49668 - Root CAs component is fixed.
Browse files Browse the repository at this point in the history
Links below provide some explanation example as to how to get the actual
trust store for inspection. They were used to replace the current broken
code which simply tries to enumerate empty KeyStore.

https://github.com/jenkinsci/jenkins-scripts/pull/82/files
https://stackoverflow.com/questions/8884831/listing-certificates-in-jvm-trust-store
  • Loading branch information
duemir committed Mar 20, 2018
1 parent bc37791 commit 2266af7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
49 changes: 30 additions & 19 deletions src/main/java/com/cloudbees/jenkins/support/impl/RootCAs.java
Expand Up @@ -35,7 +35,11 @@
import hudson.model.Node;
import hudson.security.Permission;
import jenkins.model.Jenkins;
import jenkins.security.MasterToSlaveCallable;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
Expand All @@ -44,19 +48,16 @@
import java.io.StringWriter;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
import java.util.WeakHashMap;
import jenkins.security.MasterToSlaveCallable;

/**
* @author schristou88
*/
@Extension
public class RootCAs extends Component {

private final WeakHashMap<Node, String> certCache = new WeakHashMap<Node, String>();
private final WeakHashMap<Node, String> certCache = new WeakHashMap<>();

@Override
public boolean isSelectedByDefault() {
Expand Down Expand Up @@ -104,8 +105,6 @@ public void writeTo(OutputStream os) throws IOException {
out.println(getRootCA(node));
} catch (IOException e) {
SupportLogFormatter.printStackTrace(e, out);
} catch (InterruptedException e) {
SupportLogFormatter.printStackTrace(e, out);
} finally {
out.flush();
}
Expand All @@ -114,7 +113,7 @@ public void writeTo(OutputStream os) throws IOException {
);
}

public String getRootCA(Node node) throws IOException, InterruptedException {
public String getRootCA(Node node) throws IOException {
return AsyncResultCache.get(node, certCache, new GetRootCA(), "Root CA info",
"N/A: Either no connection to node, or no cached result");
}
Expand All @@ -135,18 +134,30 @@ public String call() {
}

public static void getRootCAList(StringWriter writer) {
KeyStore instance = null;
try {
instance = KeyStore.getInstance(KeyStore.getDefaultType());
Enumeration<String> aliases = instance.aliases();
while (aliases.hasMoreElements()) {
String s = aliases.nextElement();
writer.append("========");
writer.append("Alias: " + s);
writer.append(instance.getCertificate(s).getPublicKey().toString());
writer.append("Trusted certificate: " + instance.isCertificateEntry(s));
// Inspired by:
// https://github.com/jenkinsci/jenkins-scripts/pull/82/files
// https://stackoverflow.com/questions/8884831/listing-certificates-in-jvm-trust-store
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
for (int i = 0; i < trustManagers.length; i++) {
writer.append("===== Trust Manager ").append(String.valueOf(i)).append(" =====\n");
TrustManager trustManager = trustManagers[i];
if (trustManager instanceof X509TrustManager) {
final X509Certificate[] acceptedIssuers = ((X509TrustManager) trustManager).getAcceptedIssuers();
writer.append("It is an X.509 Trust Manager containing ")
.append(String.valueOf(acceptedIssuers.length))
.append(" certificates:\n");
for (X509Certificate x509Certificate : acceptedIssuers) {
writer.append(x509Certificate.getSubjectX500Principal().toString()).append('\n');
}
} else {
writer.append("Skipping as it is not an X.509 Trust Manager.\n");
writer.append("Class Name: ").append(trustManager.getClass().getName()).append('\n');
}
}
} catch (KeyStoreException e) {
} catch (KeyStoreException | NoSuchAlgorithmException e) {
writer.write(Functions.printThrowable(e));
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/test/java/com/cloudbees/jenkins/support/impl/RootCAsTest.java
@@ -0,0 +1,21 @@
package com.cloudbees.jenkins.support.impl;

import org.junit.Test;

import java.io.StringWriter;

import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;

public class RootCAsTest {

@Test
public void getRootCAList() {
final StringWriter certsWriter = new StringWriter();
RootCAs.getRootCAList(certsWriter);
final String rootCAs = certsWriter.toString();

assertThat("output doesn't start with the Exception",
rootCAs, startsWith("===== Trust Manager 0 =====\n"));
}
}

0 comments on commit 2266af7

Please sign in to comment.