Skip to content

Commit 4f1de7b

Browse files
author
Marcus Linke
committed
Merge branch 'KostyaSha-refactorKeys't push origin master
2 parents 84cf070 + 63f276a commit 4f1de7b

File tree

2 files changed

+134
-81
lines changed

2 files changed

+134
-81
lines changed

src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
import static com.google.common.base.Preconditions.checkNotNull;
44

5+
import java.io.File;
56
import java.io.Serializable;
7+
import java.nio.file.Files;
8+
import java.nio.file.Paths;
69
import java.security.Security;
710

811
import javax.net.ssl.SSLContext;
@@ -50,9 +53,17 @@ public SSLContext getSSLContext() {
5053
System.setProperty("https.protocols", httpProtocols);
5154
}
5255

53-
sslConfig.keyStore(CertificateUtils.createKeyStore(dockerCertPath));
56+
String caPemPath = dockerCertPath + File.separator + "ca.pem";
57+
String keyPemPath = dockerCertPath + File.separator + "key.pem";
58+
String certPemPath = dockerCertPath + File.separator + "cert.pem";
59+
60+
String keypem = new String(Files.readAllBytes(Paths.get(keyPemPath)));
61+
String certpem = new String(Files.readAllBytes(Paths.get(certPemPath)));
62+
String capem = new String(Files.readAllBytes(Paths.get(caPemPath)));
63+
64+
sslConfig.keyStore(CertificateUtils.createKeyStore(keypem, certpem));
5465
sslConfig.keyStorePassword("docker");
55-
sslConfig.trustStore(CertificateUtils.createTrustStore(dockerCertPath));
66+
sslConfig.trustStore(CertificateUtils.createTrustStore(capem));
5667

5768
return sslConfig.createSSLContext();
5869

src/main/java/com/github/dockerjava/core/util/CertificateUtils.java

Lines changed: 121 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,39 @@
22

33
import java.io.BufferedReader;
44
import java.io.File;
5-
import java.io.FileReader;
65
import java.io.IOException;
6+
import java.io.Reader;
7+
import java.io.StringReader;
78
import java.security.KeyFactory;
8-
import java.security.KeyPair;
99
import java.security.KeyStore;
1010
import java.security.KeyStoreException;
1111
import java.security.NoSuchAlgorithmException;
1212
import java.security.PrivateKey;
13-
import java.security.PublicKey;
1413
import java.security.cert.Certificate;
1514
import java.security.cert.CertificateException;
1615
import java.security.spec.InvalidKeySpecException;
1716
import java.security.spec.PKCS8EncodedKeySpec;
18-
import java.security.spec.X509EncodedKeySpec;
1917
import java.util.ArrayList;
2018
import java.util.List;
2119

22-
import org.apache.commons.io.IOUtils;
20+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21+
22+
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
23+
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
2324
import org.bouncycastle.cert.X509CertificateHolder;
2425
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
2526
import org.bouncycastle.openssl.PEMKeyPair;
2627
import org.bouncycastle.openssl.PEMParser;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
import javax.annotation.CheckForNull;
32+
33+
import static java.util.Objects.requireNonNull;
2734

2835
public class CertificateUtils {
36+
private static final Logger LOG = LoggerFactory.getLogger(CertificateUtils.class);
37+
2938
private CertificateUtils() {
3039
// utility class
3140
}
@@ -41,115 +50,148 @@ public static boolean verifyCertificatesExist(String dockerCertPath) {
4150
return result;
4251
}
4352

44-
public static KeyStore createKeyStore(final String dockerCertPath) throws NoSuchAlgorithmException,
53+
@SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
54+
public static KeyStore createKeyStore(final String keypem, final String certpem) throws NoSuchAlgorithmException,
4555
InvalidKeySpecException, IOException, CertificateException, KeyStoreException {
46-
KeyPair keyPair = loadPrivateKey(dockerCertPath);
47-
List<Certificate> privateCertificates = loadCertificates(dockerCertPath);
56+
PrivateKey privateKey = loadPrivateKey(keypem);
57+
requireNonNull(privateKey);
58+
List<Certificate> privateCertificates = loadCertificates(certpem);
4859

4960
KeyStore keyStore = KeyStore.getInstance("JKS");
5061
keyStore.load(null);
5162

52-
keyStore.setKeyEntry("docker", keyPair.getPrivate(), "docker".toCharArray(),
53-
privateCertificates.toArray(new Certificate[privateCertificates.size()]));
63+
keyStore.setKeyEntry("docker",
64+
privateKey,
65+
"docker".toCharArray(),
66+
privateCertificates.toArray(new Certificate[privateCertificates.size()])
67+
);
68+
5469
return keyStore;
5570
}
5671

57-
public static KeyStore createTrustStore(final String dockerCertPath) throws IOException, CertificateException,
58-
KeyStoreException, NoSuchAlgorithmException {
59-
File caPath = new File(dockerCertPath, "ca.pem");
60-
BufferedReader reader = new BufferedReader(new FileReader(caPath));
61-
PEMParser pemParser = null;
62-
63-
try {
64-
pemParser = new PEMParser(reader);
65-
X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject();
66-
Certificate caCertificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(
67-
certificateHolder);
68-
69-
KeyStore trustStore = KeyStore.getInstance("JKS");
70-
trustStore.load(null);
71-
trustStore.setCertificateEntry("ca", caCertificate);
72-
return trustStore;
73-
74-
} finally {
75-
if (pemParser != null) {
76-
IOUtils.closeQuietly(pemParser);
77-
}
78-
79-
if (reader != null) {
80-
IOUtils.closeQuietly(reader);
81-
}
72+
/**
73+
* from "cert.pem" String
74+
*/
75+
private static List<Certificate> loadCertificates(final String certpem) throws IOException,
76+
CertificateException {
77+
final StringReader certReader = new StringReader(certpem);
78+
try (BufferedReader reader = new BufferedReader(certReader)) {
79+
return loadCertificates(reader);
8280
}
83-
8481
}
8582

86-
private static List<Certificate> loadCertificates(final String dockerCertPath) throws IOException,
83+
/**
84+
* "cert.pem" from reader
85+
*/
86+
private static List<Certificate> loadCertificates(final Reader reader) throws IOException,
8787
CertificateException {
88-
File certificate = new File(dockerCertPath, "cert.pem");
89-
BufferedReader reader = new BufferedReader(new FileReader(certificate));
90-
PEMParser pemParser = null;
91-
92-
try {
88+
try (PEMParser pemParser = new PEMParser(reader)) {
9389
List<Certificate> certificates = new ArrayList<>();
94-
pemParser = new PEMParser(reader);
90+
9591
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter().setProvider("BC");
9692
Object certObj = pemParser.readObject();
9793

98-
while (certObj != null) {
94+
if (certObj instanceof X509CertificateHolder) {
9995
X509CertificateHolder certificateHolder = (X509CertificateHolder) certObj;
10096
certificates.add(certificateConverter.getCertificate(certificateHolder));
101-
102-
certObj = pemParser.readObject();
10397
}
10498

10599
return certificates;
106-
} finally {
107-
if (pemParser != null) {
108-
IOUtils.closeQuietly(pemParser);
109-
}
110-
111-
if (reader != null) {
112-
IOUtils.closeQuietly(reader);
113-
}
114100
}
115-
116101
}
117102

118-
private static KeyPair loadPrivateKey(final String dockerCertPath) throws IOException, NoSuchAlgorithmException,
119-
InvalidKeySpecException {
120-
File certificate = new File(dockerCertPath, "key.pem");
121-
BufferedReader reader = new BufferedReader(new FileReader(certificate));
122103

123-
PEMParser pemParser = null;
104+
/**
105+
* Return private key ("key.pem") from Reader
106+
*/
107+
@CheckForNull
108+
private static PrivateKey loadPrivateKey(final Reader reader) throws IOException, NoSuchAlgorithmException,
109+
InvalidKeySpecException {
110+
try (PEMParser pemParser = new PEMParser(reader)) {
111+
Object readObject = pemParser.readObject();
112+
while (readObject != null) {
113+
if (readObject instanceof PEMKeyPair) {
114+
PEMKeyPair pemKeyPair = (PEMKeyPair) readObject;
115+
PrivateKey privateKey = guessKey(pemKeyPair.getPrivateKeyInfo().getEncoded());
116+
if (privateKey != null) {
117+
return privateKey;
118+
}
119+
} else if (readObject instanceof PrivateKeyInfo) {
120+
PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) readObject;
121+
PrivateKey privateKey = guessKey(privateKeyInfo.getEncoded());
122+
if (privateKey != null) {
123+
return privateKey;
124+
}
125+
} else if (readObject instanceof ASN1ObjectIdentifier) {
126+
// no idea how it can be used
127+
final ASN1ObjectIdentifier asn1ObjectIdentifier = (ASN1ObjectIdentifier) readObject;
128+
LOG.trace("Ignoring asn1ObjectIdentifier {}", asn1ObjectIdentifier);
129+
} else {
130+
LOG.warn("Unknown object '{}' from PEMParser", readObject);
131+
}
132+
133+
readObject = pemParser.readObject();
134+
}
135+
}
124136

125-
try {
126-
pemParser = new PEMParser(reader);
137+
return null;
138+
}
127139

128-
PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
140+
@CheckForNull
141+
private static PrivateKey guessKey(byte[] encodedKey) throws NoSuchAlgorithmException {
142+
//no way to know, so iterate
143+
for (String guessFactory : new String[]{"RSA", "ECDSA"}) {
144+
try {
145+
KeyFactory factory = KeyFactory.getInstance(guessFactory);
129146

130-
byte[] pemPrivateKeyEncoded = pemKeyPair.getPrivateKeyInfo().getEncoded();
131-
byte[] pemPublicKeyEncoded = pemKeyPair.getPublicKeyInfo().getEncoded();
147+
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey);
148+
return factory.generatePrivate(privateKeySpec);
149+
} catch (InvalidKeySpecException ignore) {
150+
}
151+
}
132152

133-
KeyFactory factory = KeyFactory.getInstance("RSA");
153+
return null;
154+
}
134155

135-
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(pemPublicKeyEncoded);
136-
PublicKey publicKey = factory.generatePublic(publicKeySpec);
156+
/**
157+
* Return KeyPair from "key.pem"
158+
*/
159+
@CheckForNull
160+
private static PrivateKey loadPrivateKey(final String keypem) throws IOException, NoSuchAlgorithmException,
161+
InvalidKeySpecException {
162+
try (StringReader certReader = new StringReader(keypem);
163+
BufferedReader reader = new BufferedReader(certReader)) {
164+
return loadPrivateKey(reader);
165+
}
166+
}
137167

138-
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(pemPrivateKeyEncoded);
139-
PrivateKey privateKey = factory.generatePrivate(privateKeySpec);
168+
/**
169+
* "ca.pem" from String
170+
*/
171+
public static KeyStore createTrustStore(String capem) throws IOException, CertificateException,
172+
KeyStoreException, NoSuchAlgorithmException {
173+
try (Reader certReader = new StringReader(capem)) {
174+
return createTrustStore(certReader);
175+
}
176+
}
140177

141-
return new KeyPair(publicKey, privateKey);
178+
/**
179+
* "ca.pem" from Reader
180+
*/
181+
public static KeyStore createTrustStore(final Reader certReader) throws IOException, CertificateException,
182+
KeyStoreException, NoSuchAlgorithmException {
183+
try (PEMParser pemParser = new PEMParser(certReader)) {
184+
X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject();
185+
Certificate caCertificate = new JcaX509CertificateConverter()
186+
.setProvider("BC")
187+
.getCertificate(certificateHolder);
142188

143-
} finally {
144-
if (pemParser != null) {
145-
IOUtils.closeQuietly(pemParser);
146-
}
189+
KeyStore trustStore = KeyStore.getInstance("JKS");
190+
trustStore.load(null);
191+
trustStore.setCertificateEntry("ca", caCertificate);
147192

148-
if (reader != null) {
149-
IOUtils.closeQuietly(reader);
150-
}
193+
return trustStore;
151194
}
152-
153195
}
154196

155197
}

0 commit comments

Comments
 (0)