Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Commit

Permalink
Added ability to support HTTPS TCP connection using private/public key.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dynatrace-Asad-Ali committed Jan 27, 2017
1 parent 4e2a088 commit 44dfa41
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 143 deletions.
Binary file added com.dynatrace.docker.plugin_1.0.7.dtp
Binary file not shown.
294 changes: 158 additions & 136 deletions plugin.xml

Large diffs are not rendered by default.

25 changes: 23 additions & 2 deletions src/com/dynatrace/docker/DockerMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public class DockerMonitor implements Monitor {
private static final String LOGIN_USER = "loginUser";
private static final String PASSWORD = "password";
private static final String DOCKER_PORT = "dockerPort";
private static final String DOCKER_PROTOCOL = "dockerProtocol";
private static final String DOCKER_CERTIFICATE_FILE = "dockerCertificateFile";
private static final String DOCKER_CERTIFICATE_SELF_SIGNED = "dockerCertificateSelfSigned";
private static final String MESOS = "Mesos/Marathon";
private static final String UNMANAGED = "Unmanaged";
private static final String[] METRIC_GROUP = { "CPUGroup", "MemoryGroup", "NetworkGroup", "HostGroup", "SummaryGroup"};
Expand Down Expand Up @@ -312,7 +315,7 @@ public Status execute(MonitorEnvironment env) throws Exception {
if (hosts.isEmpty()) {
return new Status(Status.StatusCode.ErrorInfrastructure, "Unable to retreive the host lists from Mesos enironment");
}
else {
else if (log.getLevel() == Level.FINER){
for (String host:hosts) {
log.log(Level.FINER, "Hostname=" + host);
}
Expand Down Expand Up @@ -395,10 +398,28 @@ private DataCollector getCollector(String host, MonitorEnvironment env) throws E
if ( port == null || port.equals("") ) {
throw new Exception("Port number is not defined");
}
String dockerProtocol = env.getConfigString(DOCKER_PROTOCOL);
String dockerCertificateFile = null;
boolean isSelfSigned=false;
log.log(Level.FINER, "Protocol=" + dockerProtocol);
if ( dockerProtocol.equalsIgnoreCase(Protocol.HTTPS.name())) {
dockerCertificateFile = env.getConfigString(DOCKER_CERTIFICATE_FILE);
log.log(Level.FINER, "CertificateFile=" + dockerCertificateFile );
if (dockerCertificateFile == null || dockerCertificateFile.isEmpty()) {
throw new Exception("Certificate file cannot be empty for HTTPS connection.");
}
isSelfSigned = env.getConfigBoolean(DOCKER_CERTIFICATE_SELF_SIGNED).booleanValue();
}
ConnectionConfig connectionConfig = new ConnectionConfig();
connectionConfig.setHost(host);
connectionConfig.setPort(new Integer(port).intValue());
connectionConfig.setProtocol(Protocol.HTTP);
connectionConfig.setProtocol(dockerProtocol.equalsIgnoreCase(Protocol.HTTP.name()) ? Protocol.HTTP : Protocol.HTTPS);
//log.log(Level.FINER, "Protocol=" + connectionConfig.getProtocol().name());
//log.log(Level.FINER, "Certificate file=" + dockerCertificateFile);
if (dockerCertificateFile != null) {
connectionConfig.setCertificateFile(dockerCertificateFile);
}
connectionConfig.setIsSelfSigned(isSelfSigned);
ServerConfig serverConfig = new ServerConfig();
serverConfig.setConnectionConfig(connectionConfig);
dataCollector = new TCPSocketDataCollector(serverConfig);
Expand Down
190 changes: 190 additions & 0 deletions src/com/dynatrace/docker/rest/HTTPSClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package com.dynatrace.docker.rest;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import com.dynatrace.docker.rest.HTTPClient.Method;
import com.dynatrace.docker.util.IOUtils;

public class HTTPSClient {
public static enum ResponseCode {
OK(200),
METHOD_NOT_ALLOWED(405);

ResponseCode(final int code) {
this.code = code;
};

private final int code;

/**
* {@inheritDoc}
*/
@Override
public final String toString() {
return new StringBuilder(code).
append(" (").
append(name())
.append(")").
toString();
}

/**
* Checks if the given integer based response code matches up with
* the response code of this enum value.
*
* @param code the integer response code to check against
*
* @return {@code true} if the given integer response code matches up
* with the response code of this enum value
*/
public final boolean matches(final int code) {
return (this.code == code);
}

/**
* Queries for the right enum value for the given integer response code
*
* @param code the integer response code to query with
*
* @return the enum value matching up with the given integer response
* code or {@code null} if none is matching
*/
public static final ResponseCode fromCode(final int code) {
final ResponseCode[] values = values();
for (ResponseCode value : values) {
if (value.matches(code)) {
return value;
}
}
return null;
}
}


public String request(final URL url,
final Method method,
final String certificateFile,
final boolean isSelfSigned,
boolean unlimitedRead)
throws IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, KeyManagementException {
InputStream in = null;
ByteArrayOutputStream baos= null;

X509Certificate cert = null;
FileInputStream pemFileStream = new FileInputStream(new File(certificateFile));
CertificateFactory certFactory = CertificateFactory.getInstance("X509");
cert = (X509Certificate) certFactory.generateCertificate(pemFileStream);
SSLContext sslContext = SSLContext.getInstance("TLS");
// If the certificate is self signed, using a dummy trust manager.
if (isSelfSigned) {
ServerTrustManager serverTrustManager = new ServerTrustManager();
sslContext.init(null, new TrustManager[]{serverTrustManager}, null);
}
else {
//create truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(null); //create an empty trustore
//add certificate to truststore - you can use a simpler alias
String alias = cert.getSubjectX500Principal().getName() + "["
+ cert.getSubjectX500Principal().getName().hashCode() + "]";
trustStore.setCertificateEntry(alias, cert);
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
}

HttpsURLConnection conn=null;
try {
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
conn.setRequestMethod("GET");
conn.connect();
if (unlimitedRead) {
return readUnlimited(conn);
}
else {
return readLimited(conn);
}
} catch (final IOException e) {
throw e;
} finally {
IOUtils.close(in);
IOUtils.close(baos);
if ( conn != null ) {
conn.disconnect();
}
}

}

private String readUnlimited(HttpsURLConnection connection) throws IOException {
int responseCode = 0;
InputStream in = null;
ByteArrayOutputStream baos= null;
try {
in = connection.getInputStream();
responseCode = connection.getResponseCode();
if (responseCode != ResponseCode.OK.code) {
return null;
}
baos = new ByteArrayOutputStream();
IOUtils.copy(in, baos);
String result = new String(baos.toByteArray());
return result;
} catch (final IOException e) {
throw e;
} finally {
IOUtils.close(in);
IOUtils.close(baos);
if ( connection != null ) {
connection.disconnect();
}
}
}

private String readLimited(HttpsURLConnection connection) throws IOException {
int responseCode = 0;
InputStream in = null;
try {
in = connection.getInputStream();
responseCode = connection.getResponseCode();
if (responseCode != ResponseCode.OK.code) {
return null;
}
InputStreamReader reader = new InputStreamReader(in);
BufferedReader buffReader = new BufferedReader(reader);
String line = buffReader.readLine();
return line;
} catch (final IOException e) {
throw e;
} finally {
IOUtils.close(in);
if ( connection != null ) {
connection.disconnect();
}
}
}


}
33 changes: 28 additions & 5 deletions src/com/dynatrace/docker/rest/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Objects;

import com.dynatrace.docker.rest.HTTPClient.Method;
import com.dynatrace.docker.rest.config.ConnectionConfig;
import com.dynatrace.docker.rest.config.ServerConfig;
import com.dynatrace.docker.util.Protocol;

/**
* Base class for all REST Requests to be executed to the dynaTrace Server
Expand All @@ -20,7 +25,6 @@ public class Request {
static final String ERR_MSG_INVALID_SERVER_CONFIG =
"Server Config is not valid".intern();

private static final HTTPClient httpClient = new HTTPClient();
private String path = null;
/**
* Executes the REST Request to the dynaTrace Server
Expand All @@ -38,10 +42,29 @@ public String execute(final ServerConfig config, boolean unlimitedRead) throws I
}
final ConnectionConfig connectionConfig = config.getConnectionConfig();
final URL url = connectionConfig.createURL(getPath());
String responseStr = httpClient.request(
url,
Method.GET,
config.getCredentials(), unlimitedRead);
String responseStr=null;
if (connectionConfig.getProtocol() == Protocol.HTTP) {
HTTPClient httpClient = new HTTPClient();
responseStr = httpClient.request(
url,
Method.GET,
config.getCredentials(), unlimitedRead);
}
else {
HTTPSClient httpsClient = new HTTPSClient();
try {
responseStr = httpsClient.request(
url,
Method.GET,
connectionConfig.getCertificateFile(),
connectionConfig.getIsSelfSigned(), unlimitedRead);
}
catch (IOException | KeyStoreException | NoSuchAlgorithmException |
CertificateException | KeyManagementException exception) {
throw new IOException(exception);
}

}
if (responseStr == null) {
throw new IOException("Response code is not OK");
}
Expand Down
27 changes: 27 additions & 0 deletions src/com/dynatrace/docker/rest/ServerTrustManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.dynatrace.docker.rest;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class ServerTrustManager implements X509TrustManager {

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub

}

@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
}
20 changes: 20 additions & 0 deletions src/com/dynatrace/docker/rest/config/ConnectionConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ public final class ConnectionConfig {
static final String ATTRIBUTE_PROTOCOL = "protocol";
static final String ATTRIBUTE_HOST = "host";
static final String ATTRIBUTE_PORT = "port";
static final String CERTIFICATE_FILE = "certificateFile";
static final String IS_SELF_SIGNED = "isSelfSigned";

private Protocol protocol = null;
private String host = null;
private int port = UNDEFINED_PORT;
private String certificateFile;
private boolean isSelfSigned;

public ConnectionConfig() {

Expand Down Expand Up @@ -70,6 +74,22 @@ public final void setProtocol(final Protocol protocol) {
this.protocol = protocol;
}

public final void setCertificateFile (String certificateFile) {
this.certificateFile = certificateFile;
}

public final String getCertificateFile() {
return this.certificateFile;
}

public final void setIsSelfSigned(boolean signed) {
this.isSelfSigned = signed;
}

public final boolean getIsSelfSigned() {
return this.isSelfSigned;
}

/**
* @return the host name of IP address of the HTTP server
*/
Expand Down

0 comments on commit 44dfa41

Please sign in to comment.