mirror of https://github.com/apache/jclouds.git
Support supplying key and certificate to Docker as data
This commit is contained in:
parent
42d0576aa9
commit
61fb3ec145
|
@ -38,6 +38,7 @@ import com.google.inject.Module;
|
|||
public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
||||
|
||||
public static final String DOCKER_CA_CERT_PATH = "docker.cacert.path";
|
||||
public static final String DOCKER_CA_CERT_DATA = "docker.cacert.data";
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
|
@ -58,6 +59,7 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
|||
properties.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
|
||||
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
|
||||
properties.setProperty(DOCKER_CA_CERT_PATH, "");
|
||||
properties.setProperty(DOCKER_CA_CERT_DATA, "");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -67,8 +69,8 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
|||
super(DockerApi.class);
|
||||
id("docker")
|
||||
.name("Docker API")
|
||||
.identityName("Path to certificate .pem file")
|
||||
.credentialName("Path to key .pem file")
|
||||
.identityName("Path or data for certificate .pem file")
|
||||
.credentialName("Path or data for key .pem file")
|
||||
.documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
|
||||
.version("1.21")
|
||||
.defaultEndpoint("https://127.0.0.1:2376")
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.jclouds.docker.suppliers;
|
|||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
import org.jclouds.docker.DockerApiMetadata;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.location.Provider;
|
||||
|
@ -26,22 +27,25 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static org.jclouds.docker.suppliers.SSLContextBuilder.isClientKeyAndCertificateData;
|
||||
|
||||
@Singleton
|
||||
public class DockerSSLContextSupplier implements Supplier<SSLContext> {
|
||||
private final Supplier<Credentials> creds;
|
||||
private final String caCertPath;
|
||||
|
||||
private final String caCertData;
|
||||
|
||||
@Inject
|
||||
DockerSSLContextSupplier(@Provider Supplier<Credentials> creds, @Named(DockerApiMetadata.DOCKER_CA_CERT_PATH) String caCertPath) {
|
||||
DockerSSLContextSupplier(@Provider Supplier<Credentials> creds, @Named(DockerApiMetadata.DOCKER_CA_CERT_PATH) String caCertPath, @Named(DockerApiMetadata.DOCKER_CA_CERT_DATA) String caCertData) {
|
||||
this.creds = creds;
|
||||
this.caCertPath = caCertPath;
|
||||
this.caCertData = caCertData;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,9 +53,15 @@ public class DockerSSLContextSupplier implements Supplier<SSLContext> {
|
|||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
try {
|
||||
SSLContextBuilder builder = new SSLContextBuilder();
|
||||
builder.clientKeyAndCertificate(currentCreds.credential, currentCreds.identity);
|
||||
if (isClientKeyAndCertificateData(currentCreds.credential, currentCreds.identity)) {
|
||||
builder.clientKeyAndCertificateData(currentCreds.credential, currentCreds.identity);
|
||||
} else {
|
||||
builder.clientKeyAndCertificatePaths(currentCreds.credential, currentCreds.identity);
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(caCertPath)) {
|
||||
builder.caCertificate(caCertPath);
|
||||
builder.caCertificatePath(caCertPath);
|
||||
} else if (!Strings.isNullOrEmpty(caCertData)) {
|
||||
builder.caCertificateData(caCertData);
|
||||
}
|
||||
return builder.build();
|
||||
} catch (GeneralSecurityException e) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.config.SSLModule;
|
||||
import org.jclouds.location.Provider;
|
||||
|
@ -30,6 +31,7 @@ import java.io.IOException;
|
|||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static org.jclouds.docker.suppliers.SSLContextBuilder.isClientKeyAndCertificateData;
|
||||
|
||||
@Singleton
|
||||
public class DockerUntrustedSSLContextSupplier implements Supplier<SSLContext> {
|
||||
|
@ -45,13 +47,13 @@ public class DockerUntrustedSSLContextSupplier implements Supplier<SSLContext> {
|
|||
|
||||
@Override
|
||||
public SSLContext get() {
|
||||
Credentials currentCreds = creds.get();
|
||||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
try {
|
||||
SSLContextBuilder builder = new SSLContextBuilder();
|
||||
// check if identity and credential are files, to set up sslContext
|
||||
if (currentCreds != null && new File(currentCreds.identity).isFile()
|
||||
&& new File(currentCreds.credential).isFile()) {
|
||||
builder.clientKeyAndCertificate(currentCreds.credential, currentCreds.identity);
|
||||
if (isClientKeyAndCertificateData(currentCreds.credential, currentCreds.identity)) {
|
||||
builder.clientKeyAndCertificateData(currentCreds.credential, currentCreds.identity);
|
||||
} else if (new File(currentCreds.identity).isFile() && new File(currentCreds.credential).isFile()) {
|
||||
builder.clientKeyAndCertificatePaths(currentCreds.credential, currentCreds.identity);
|
||||
}
|
||||
builder.trustManager(insecureTrustManager);
|
||||
return builder.build();
|
||||
|
|
|
@ -18,10 +18,13 @@ package org.jclouds.docker.suppliers;
|
|||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.util.Closeables2;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
|
@ -29,6 +32,7 @@ import javax.net.ssl.SSLContext;
|
|||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -54,22 +58,48 @@ public class SSLContextBuilder {
|
|||
private KeyManager[] keyManagers;
|
||||
private TrustManager[] trustManagers;
|
||||
|
||||
public static final boolean isClientKeyAndCertificateData(String key, String cert) {
|
||||
return (key.startsWith(Pems.PUBLIC_X509_MARKER) || key.startsWith(Pems.PUBLIC_PKCS1_MARKER)) &&
|
||||
cert.startsWith(Pems.CERTIFICATE_X509_MARKER);
|
||||
}
|
||||
|
||||
public SSLContextBuilder() { }
|
||||
|
||||
public SSLContextBuilder clientKeyAndCertificate(String keyPath, String certPath) throws IOException, CertificateException {
|
||||
public SSLContextBuilder clientKeyAndCertificatePaths(String keyPath, String certPath) throws IOException, CertificateException {
|
||||
X509Certificate certificate = getCertificate(loadFile(certPath));
|
||||
PrivateKey privateKey = getKey(loadFile(keyPath));
|
||||
keyManagers = new KeyManager[]{new InMemoryKeyManager(certificate, privateKey)};
|
||||
keyManager(new InMemoryKeyManager(certificate, privateKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder caCertificate(String caCertPath){
|
||||
public SSLContextBuilder clientKeyAndCertificateData(String keyData, String certData) throws CertificateException {
|
||||
X509Certificate certificate = getCertificate(certData);
|
||||
PrivateKey privateKey = getKey(keyData);
|
||||
keyManager(new InMemoryKeyManager(certificate, privateKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder caCertificatePath(String caCertPath) {
|
||||
try {
|
||||
trustManagers = getTrustManagerWithCaCert(loadFile(caCertPath));
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder caCertificateData(String caCertPath) {
|
||||
trustManagers = getTrustManagerWithCaCert(caCertPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder keyManager(KeyManager keyManager) {
|
||||
keyManagers = new KeyManager[] { keyManager };
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder trustManager(TrustManager trustManager) {
|
||||
trustManagers = new TrustManager[]{trustManager};
|
||||
trustManagers = new TrustManager[] { trustManager };
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -79,9 +109,9 @@ public class SSLContextBuilder {
|
|||
return sslContext;
|
||||
}
|
||||
|
||||
private TrustManager[] getTrustManagerWithCaCert(String caCertPath) {
|
||||
private TrustManager[] getTrustManagerWithCaCert(String caCertData) {
|
||||
try {
|
||||
X509Certificate caCert = getCertificate(loadFile(caCertPath));
|
||||
X509Certificate caCert = getCertificate(caCertData);
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
trustStore.setCertificateEntry("ca", caCert);
|
||||
|
@ -132,32 +162,29 @@ public class SSLContextBuilder {
|
|||
|
||||
private final PrivateKey privateKey;
|
||||
|
||||
public InMemoryKeyManager(final X509Certificate certificate, final PrivateKey privateKey)
|
||||
throws IOException, CertificateException {
|
||||
public InMemoryKeyManager(final X509Certificate certificate, final PrivateKey privateKey) throws CertificateException {
|
||||
this.certificate = certificate;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseClientAlias(final String[] keyType, final Principal[] issuers,
|
||||
final Socket socket) {
|
||||
public String chooseClientAlias(final String[] keyType, final Principal[] issuers, final Socket socket) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseServerAlias(final String keyType, final Principal[] issuers,
|
||||
final Socket socket) {
|
||||
public String chooseServerAlias(final String keyType, final Principal[] issuers, final Socket socket) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain(final String alias) {
|
||||
return new X509Certificate[]{certificate};
|
||||
return new X509Certificate[] { certificate };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getClientAliases(final String keyType, final Principal[] issuers) {
|
||||
return new String[]{DEFAULT_ALIAS};
|
||||
return new String[] { DEFAULT_ALIAS };
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,7 +194,7 @@ public class SSLContextBuilder {
|
|||
|
||||
@Override
|
||||
public String[] getServerAliases(final String keyType, final Principal[] issuers) {
|
||||
return new String[]{DEFAULT_ALIAS};
|
||||
return new String[] { DEFAULT_ALIAS };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue