Skip to content

Commit f6b15fb

Browse files
author
Marcus Linke
committed
Merge branch 'pr1' of https://github.com/magnayn/docker-java into magnayn-pr1
2 parents b3e5a43 + 138b11e commit f6b15fb

7 files changed

Lines changed: 289 additions & 52 deletions

File tree

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

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
import java.io.File;
77
import java.io.FileInputStream;
88
import java.io.IOException;
9+
import java.io.Serializable;
910
import java.net.URI;
1011
import java.util.Map;
1112
import java.util.Properties;
1213

13-
public class DockerClientConfig {
14+
public class DockerClientConfig implements Serializable {
1415
private static final String DOCKER_HOST_PROPERTY = "DOCKER_HOST";
1516
private static final String DOCKER_CERT_PATH_PROPERTY = "DOCKER_CERT_PATH";
1617
private static final String DOCKER_IO_URL_PROPERTY = "docker.io.url";
@@ -41,21 +42,22 @@ public class DockerClientConfig {
4142
.build();
4243
private static final String DOCKER_IO_PROPERTIES_PROPERTY = "docker.io.properties";
4344
private final URI uri;
44-
private final String version, username, password, email, serverAddress, dockerCertPath, dockerCfgPath;
45+
private final String version, username, password, email, serverAddress, dockerCfgPath;
4546
private final Integer readTimeout;
4647
private final boolean loggingFilterEnabled;
48+
private final SSLConfig sslConfig;
4749

48-
DockerClientConfig(URI uri, String version, String username, String password, String email, String serverAddress, String dockerCertPath, String dockerCfgPath, Integer readTimeout, boolean loggingFilterEnabled) {
50+
DockerClientConfig(URI uri, String version, String username, String password, String email, String serverAddress, String dockerCfgPath, Integer readTimeout, boolean loggingFilterEnabled, SSLConfig sslConfig) {
4951
this.uri = uri;
5052
this.version = version;
5153
this.username = username;
5254
this.password = password;
5355
this.email = email;
5456
this.serverAddress = serverAddress;
55-
this.dockerCertPath = dockerCertPath;
5657
this.dockerCfgPath = dockerCfgPath;
5758
this.readTimeout = readTimeout;
5859
this.loggingFilterEnabled = loggingFilterEnabled;
60+
this.sslConfig = sslConfig;
5961
}
6062

6163
private static Properties loadIncludedDockerProperties(Properties systemProperties) {
@@ -212,23 +214,23 @@ public boolean isLoggingFilterEnabled() {
212214
return loggingFilterEnabled;
213215
}
214216

215-
public String getDockerCertPath() {
216-
return dockerCertPath;
217+
public SSLConfig getSslConfig() {
218+
return sslConfig;
217219
}
218220

219221
public String getDockerCfgPath() {
220222
return dockerCfgPath;
221223
}
222224

223-
@Override
225+
@Override
224226
public boolean equals(Object o) {
225227
if (this == o) return true;
226228
if (o == null || getClass() != o.getClass()) return false;
227229

228230
DockerClientConfig that = (DockerClientConfig) o;
229231

230232
if (loggingFilterEnabled != that.loggingFilterEnabled) return false;
231-
if (dockerCertPath != null ? !dockerCertPath.equals(that.dockerCertPath) : that.dockerCertPath != null)
233+
if (sslConfig != null ? !sslConfig.equals(that.sslConfig) : that.sslConfig != null)
232234
return false;
233235
if (dockerCfgPath != null ? !dockerCfgPath.equals(that.dockerCfgPath) : that.dockerCfgPath != null)
234236
return false;
@@ -252,8 +254,8 @@ public int hashCode() {
252254
result = 31 * result + (password != null ? password.hashCode() : 0);
253255
result = 31 * result + (email != null ? email.hashCode() : 0);
254256
result = 31 * result + (serverAddress != null ? serverAddress.hashCode() : 0);
255-
result = 31 * result + (dockerCertPath != null ? dockerCertPath.hashCode() : 0);
256257
result = 31 * result + (dockerCfgPath != null ? dockerCfgPath.hashCode() : 0);
258+
result = 31 * result + (sslConfig != null ? sslConfig.hashCode() : 0);
257259
result = 31 * result + (readTimeout != null ? readTimeout.hashCode() : 0);
258260
result = 31 * result + (loggingFilterEnabled ? 1 : 0);
259261
return result;
@@ -268,18 +270,19 @@ public String toString() {
268270
", password='" + password + '\'' +
269271
", email='" + email + '\'' +
270272
", serverAddress='" + serverAddress + '\'' +
271-
", dockerCertPath='" + dockerCertPath + '\'' +
272273
", dockerCfgPath='" + dockerCfgPath + '\'' +
274+
", sslConfig='" + sslConfig + '\'' +
273275
", readTimeout=" + readTimeout +
274276
", loggingFilterEnabled=" + loggingFilterEnabled +
275277
'}';
276278
}
277279

278280
public static class DockerClientConfigBuilder {
279281
private URI uri;
280-
private String version, username, password, email, serverAddress, dockerCertPath, dockerCfgPath;
282+
private String version, username, password, email, serverAddress, dockerCfgPath;
281283
private Integer readTimeout;
282284
private boolean loggingFilterEnabled;
285+
private SSLConfig sslConfig;
283286

284287
/**
285288
* This will set all fields in the builder to those contained in the Properties object. The Properties object
@@ -342,7 +345,7 @@ public final DockerClientConfigBuilder withLoggingFilter(boolean loggingFilterEn
342345
}
343346

344347
public final DockerClientConfigBuilder withDockerCertPath(String dockerCertPath) {
345-
this.dockerCertPath = dockerCertPath;
348+
this.sslConfig = new LocalDirectorySSLConfig(dockerCertPath);
346349
return this;
347350
}
348351

@@ -352,6 +355,11 @@ public final DockerClientConfigBuilder withDockerCfgPath(String dockerCfgPath) {
352355
}
353356

354357

358+
public final DockerClientConfigBuilder withSSLConfig(SSLConfig config) {
359+
this.sslConfig = config;
360+
return this;
361+
}
362+
355363
public DockerClientConfig build() {
356364
return new DockerClientConfig(
357365
uri,
@@ -360,10 +368,10 @@ public DockerClientConfig build() {
360368
password,
361369
email,
362370
serverAddress,
363-
dockerCertPath,
364371
dockerCfgPath,
365372
readTimeout,
366-
loggingFilterEnabled
373+
loggingFilterEnabled,
374+
sslConfig
367375
);
368376
}
369377
}
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)