X Tutup
Skip to content

Commit 20a72fc

Browse files
committed
Currently, the certificates present for SSL access must all be
accessible on the local disk. This is inconvenient for some clients who may already have a pre-baked keystore in hand. Create different options for retrieving the neccessary SSLContext, so that the two different options can be used. Signed-off-by: Nigel Magnay <nigel.magnay@gmail.com>
1 parent f86abdb commit 20a72fc

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package com.github.dockerjava.core;
2+
3+
import com.google.common.base.Objects;
4+
import com.google.common.base.Preconditions;
5+
6+
import java.io.File;
7+
import java.io.FileInputStream;
8+
import java.io.IOException;
9+
import java.io.Serializable;
10+
import java.security.KeyManagementException;
11+
import java.security.KeyStore;
12+
import java.security.KeyStoreException;
13+
import java.security.NoSuchAlgorithmException;
14+
import java.security.SecureRandom;
15+
import java.security.UnrecoverableKeyException;
16+
import java.security.cert.CertificateException;
17+
import java.security.cert.X509Certificate;
18+
19+
import javax.net.ssl.KeyManagerFactory;
20+
import javax.net.ssl.SSLContext;
21+
import javax.net.ssl.TrustManager;
22+
import javax.net.ssl.X509TrustManager;
23+
24+
/**
25+
* An SSL Config that is based on an pre-existing or pre-loaded KeyStore.
26+
*/
27+
public class KeystoreSSLConfig implements SSLConfig, Serializable {
28+
29+
private final KeyStore keystore;
30+
private final String keystorePassword;
31+
32+
/**
33+
* @param keystore a KeyStore
34+
* @param keystorePassword key password
35+
*/
36+
public KeystoreSSLConfig(KeyStore keystore, String keystorePassword) {
37+
this.keystorePassword = keystorePassword;
38+
Preconditions.checkNotNull(keystore);
39+
this.keystore = keystore;
40+
}
41+
42+
/**
43+
*
44+
* @param pfxFile a PKCS12 file
45+
* @param password Password for the keystore
46+
* @throws KeyStoreException
47+
* @throws IOException
48+
* @throws CertificateException
49+
* @throws NoSuchAlgorithmException
50+
*/
51+
public KeystoreSSLConfig(File pfxFile, String password)
52+
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
53+
Preconditions.checkNotNull(pfxFile);
54+
Preconditions.checkNotNull(password);
55+
keystore = KeyStore.getInstance("pkcs12");
56+
keystore.load(new FileInputStream(pfxFile), password.toCharArray());
57+
keystorePassword = password;
58+
}
59+
60+
61+
/**
62+
* Get the SSL Context out of the keystore.
63+
* @return java SSLContext
64+
* @throws KeyManagementException
65+
* @throws UnrecoverableKeyException
66+
* @throws NoSuchAlgorithmException
67+
* @throws KeyStoreException
68+
*/
69+
@Override
70+
public SSLContext getSSLContext()
71+
throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException,
72+
KeyStoreException {
73+
74+
final SSLContext context = SSLContext.getInstance("TLS");
75+
76+
String httpProtocols = System.getProperty("https.protocols");
77+
System.setProperty("https.protocols", "TLSv1");
78+
79+
if (httpProtocols != null)
80+
System.setProperty("https.protocols", httpProtocols);
81+
82+
final KeyManagerFactory
83+
keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
84+
keyManagerFactory.init(keystore, keystorePassword.toCharArray());
85+
context.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{
86+
new X509TrustManager() {
87+
@Override
88+
public X509Certificate[] getAcceptedIssuers() {
89+
return new X509Certificate[]{};
90+
}
91+
92+
@Override
93+
public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) {
94+
95+
}
96+
97+
@Override
98+
public void checkServerTrusted(final X509Certificate[] arg0, final String arg1) {
99+
100+
}
101+
}
102+
}, new SecureRandom());
103+
104+
return context;
105+
}
106+
107+
@Override
108+
public boolean equals(Object o) {
109+
if (this == o) {
110+
return true;
111+
}
112+
if (o == null || getClass() != o.getClass()) {
113+
return false;
114+
}
115+
116+
KeystoreSSLConfig that = (KeystoreSSLConfig) o;
117+
118+
return keystore.equals(that.keystore);
119+
120+
}
121+
122+
@Override
123+
public int hashCode() {
124+
return keystore.hashCode();
125+
}
126+
127+
@Override
128+
public String toString() {
129+
return Objects.toStringHelper(this)
130+
.add("keystore", keystore)
131+
.toString();
132+
}
133+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.github.dockerjava.core;
2+
3+
import com.google.common.base.Objects;
4+
import com.google.common.base.Preconditions;
5+
6+
import com.github.dockerjava.api.DockerClientException;
7+
8+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
9+
import org.glassfish.jersey.SslConfigurator;
10+
11+
import java.io.Serializable;
12+
import java.security.KeyStore;
13+
import java.security.Security;
14+
15+
import javax.net.ssl.SSLContext;
16+
17+
/**
18+
* SSL Config from local files.
19+
*/
20+
public class LocalDirectorySSLConfig implements SSLConfig, Serializable {
21+
22+
private final String dockerCertPath;
23+
24+
public LocalDirectorySSLConfig(String dockerCertPath) {
25+
Preconditions.checkNotNull(dockerCertPath);
26+
this.dockerCertPath = dockerCertPath;
27+
}
28+
29+
public String getDockerCertPath() {
30+
return dockerCertPath;
31+
}
32+
33+
@Override
34+
public SSLContext getSSLContext() {
35+
36+
boolean certificatesExist = CertificateUtils.verifyCertificatesExist(dockerCertPath);
37+
38+
if (certificatesExist) {
39+
40+
try {
41+
42+
Security.addProvider(new BouncyCastleProvider());
43+
44+
KeyStore keyStore = CertificateUtils.createKeyStore(dockerCertPath);
45+
KeyStore trustStore = CertificateUtils.createTrustStore(dockerCertPath);
46+
47+
// properties acrobatics not needed for java > 1.6
48+
String httpProtocols = System.getProperty("https.protocols");
49+
System.setProperty("https.protocols", "TLSv1");
50+
SslConfigurator sslConfig = SslConfigurator.newInstance(true);
51+
if (httpProtocols != null) {
52+
System.setProperty("https.protocols", httpProtocols);
53+
}
54+
55+
sslConfig.keyStore(keyStore);
56+
sslConfig.keyStorePassword("docker");
57+
sslConfig.trustStore(trustStore);
58+
59+
return sslConfig.createSSLContext();
60+
61+
62+
} catch (Exception e) {
63+
throw new DockerClientException(e.getMessage(), e);
64+
}
65+
66+
}
67+
68+
return null;
69+
70+
}
71+
72+
@Override
73+
public boolean equals(Object o) {
74+
if (this == o) {
75+
return true;
76+
}
77+
if (o == null || getClass() != o.getClass()) {
78+
return false;
79+
}
80+
81+
LocalDirectorySSLConfig that = (LocalDirectorySSLConfig) o;
82+
83+
if (!dockerCertPath.equals(that.dockerCertPath)) {
84+
return false;
85+
}
86+
87+
return true;
88+
}
89+
90+
@Override
91+
public int hashCode() {
92+
return dockerCertPath.hashCode();
93+
}
94+
95+
@Override
96+
public String toString() {
97+
return Objects.toStringHelper(this)
98+
.add("dockerCertPath", dockerCertPath)
99+
.toString();
100+
}
101+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.github.dockerjava.core;
2+
3+
import java.security.KeyManagementException;
4+
import java.security.KeyStoreException;
5+
import java.security.NoSuchAlgorithmException;
6+
import java.security.UnrecoverableKeyException;
7+
8+
import javax.net.ssl.SSLContext;
9+
10+
/**
11+
* Get an SSL Config. Allows for various different implementations.
12+
*/
13+
public interface SSLConfig {
14+
15+
/**
16+
* Get the SSL Context, from wherever it comes (file, keystore).
17+
* @return an SSL context.
18+
*/
19+
SSLContext getSSLContext()
20+
throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException,
21+
KeyStoreException;
22+
}

0 commit comments

Comments
 (0)
X Tutup