Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for trustStore and trustStorePassword #34

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;

import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
import brooklyn.location.jclouds.JcloudsLocation;
Expand All @@ -25,23 +30,24 @@
import brooklyn.test.entity.LocalManagementContextForTests;
import brooklyn.util.exceptions.Exceptions;

import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;

public class NatServiceMicroserviceLiveTest extends AbstractRestApiTest {

private static final Logger LOG = LoggerFactory.getLogger(NatServiceMicroserviceLiveTest.class);

private ManagementContext mgmt;
private JcloudsLocation loc;

private String trustStore;
private String trustStorePassword;

@BeforeClass(alwaysRun=true)
@Override
public void setUp() throws Exception {
mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault());
loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve("canopy-vCHS");
trustStore = (String) loc.getAllConfigBag().getStringKey("trustStore");
trustStorePassword = (String) loc.getAllConfigBag().getStringKey("trustStorePassword");

super.setUp();
}

Expand All @@ -54,7 +60,7 @@ public void tearDown() throws Exception {

protected NatServiceDispatcher newNatServiceDispatcher() {
return NatServiceDispatcher.builder()
.endpoint(endpoint(loc), new TrustConfig(null, null))
.endpoint(endpoint(loc), new TrustConfig(trustStore, trustStorePassword))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public NatDirectClient(JcloudsLocation loc) {
.endpoint(endpoint)
.identity(loc.getIdentity())
.credential(loc.getCredential())
.trustStore((String) loc.getAllConfigBag().getStringKey("trustStore"))
.trustStorePassword((String) loc.getAllConfigBag().getStringKey("trustStorePassword"))
.mutex(MutexRegistry.INSTANCE.getMutexFor(endpoint))
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
/*
* *******************************************************
* Copyright VMware, Inc. 2010-2013. All Rights Reserved.
* *******************************************************
*
* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT
* WARRANTIES OR CONDITIONS # OF ANY KIND, WHETHER ORAL OR WRITTEN,
* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY # DISCLAIMS ANY IMPLIED
* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY # QUALITY,
* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package brooklyn.networking.vclouddirector;

import java.io.FileInputStream;
Expand All @@ -26,43 +15,42 @@

import org.apache.http.conn.ssl.SSLSocketFactory;

import com.google.common.base.Throwables;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file Copyright VMware, Inc, as it says at the top of the file?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started from a VMware class, but I've completely re-written that. Removing the copyright


public class CustomSSLSocketFactory {

private CustomSSLSocketFactory() {
}

public static SSLSocketFactory getInstance()
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, KeyManagementException, IOException {

TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
try{
String trustStore = System.getProperty("javax.net.ssl.trustStore");
String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
if(trustStore == null || trustStorePassword == null){
throw new IOException("javax.net.ssl.trustStore/javax.net.ssl.trustStorePassword property - not set");
}
public static SSLSocketFactory getInstance(String trustStore, String trustStorePassword) {
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
FileInputStream keystoreStream = new FileInputStream(trustStore);
try{
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
try {
keystore.load(keystoreStream, trustStorePassword.toCharArray());
} finally{
} finally {
keystoreStream.close();
}
} catch(FileNotFoundException e){
e.printStackTrace();
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);
return new SSLSocketFactory(sslContext, SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
} catch (CertificateException e) {
throw Throwables.propagate(e);
} catch (NoSuchAlgorithmException e) {
throw Throwables.propagate(e);
} catch (KeyStoreException e) {
throw Throwables.propagate(e);
} catch (KeyManagementException e) {
throw Throwables.propagate(e);
} catch (FileNotFoundException e) {
throw Throwables.propagate(e);
} catch (IOException e) {
e.printStackTrace();
throw Throwables.propagate(e);
}
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);

return new SSLSocketFactory(sslContext,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
/*
* *******************************************************
* Copyright VMware, Inc. 2010-2013. All Rights Reserved.
* *******************************************************
*
* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT
* WARRANTIES OR CONDITIONS # OF ANY KIND, WHETHER ORAL OR WRITTEN,
* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY # DISCLAIMS ANY IMPLIED
* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY # QUALITY,
* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package brooklyn.networking.vclouddirector;

import java.security.KeyManagementException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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

import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Iterator;
Expand All @@ -15,13 +16,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.Protocol;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;

import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Predicates;
Expand Down Expand Up @@ -51,6 +45,14 @@
import com.vmware.vcloud.sdk.constants.Version;
import com.vmware.vcloud.sdk.constants.query.QueryReferenceType;

import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.Protocol;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;

/**
* For adding/removing NAT rules to vcloud-director.
*
Expand Down Expand Up @@ -477,8 +479,12 @@ protected VcloudClient newVcloudClient() {
return newVcloudClient(baseUrl, identity, credential, trustStore, trustStorePassword, logLevel);
}

// FIXME Don't set sysprop as could affect all other activities of the JVM!
protected VcloudClient newVcloudClient(String endpoint, String identity, String credential, String trustStore, String trustStorePassword, Level logLevel) {

if (trustStore == null) {
trustStore = getDefaultTrustStore();
}

try {
if (logLevel != null) {
// Logging is extremely verbose at INFO - it logs in full every http request/response (including payload).
Expand All @@ -493,6 +499,16 @@ protected VcloudClient newVcloudClient(String endpoint, String identity, String
try {
vcloudClient = new VcloudClient(endpoint, version);
LOG.debug("VCloudClient - trying login to {} using {}", endpoint, version);

// Performing Certificate Validation
if (Strings.isNonBlank(trustStorePassword)) {
LOG.debug("Registering HTTPS scheme using trustStore ='{}'", trustStore);
vcloudClient.registerScheme("https", 443, CustomSSLSocketFactory.getInstance(trustStore, trustStorePassword));
} else {
LOG.warn("Registering HTTPS scheme using FakeSSLSocketFactory, as trustStore ='{}' and/or trustStorePassword are not valid.", trustStore);
vcloudClient.registerScheme("https", 443, FakeSSLSocketFactory.getInstance());
}

vcloudClient.login(identity, credential);
versionFound = true;
LOG.info("VCloudClient - Logged into {} using version {}", endpoint, version);
Expand All @@ -504,23 +520,29 @@ protected VcloudClient newVcloudClient(String endpoint, String identity, String
if (!versionFound) {
throw new IllegalStateException("Cannot login to " + endpoint + " using any of " + VCLOUD_VERSIONS);
}

// Performing Certificate Validation
if (Strings.isNonBlank(trustStore)) {
System.setProperty("javax.net.ssl.trustStore", trustStore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
vcloudClient.registerScheme("https", 443, CustomSSLSocketFactory.getInstance());

} else {
LOG.warn("Ignoring the Certificate Validation using FakeSSLSocketFactory");
vcloudClient.registerScheme("https", 443, FakeSSLSocketFactory.getInstance());
}
return vcloudClient;
} catch (Exception e) {
throw Exceptions.propagate(e);
}
}

/**
* http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization
*
* @return the default truststore, jssecacerts, if it exists. Otherwise, cacerts
*/
private String getDefaultTrustStore() {
String trustStore;
String trustStoreFolder = Os.mergePaths(System.getProperty("java.home"), "lib", "security");
trustStore = Os.mergePaths(trustStoreFolder, "jssecacerts");
if (!new File(trustStore).exists()) {
trustStore = Os.mergePaths(trustStoreFolder, "cacerts");
} else {
throw new IllegalStateException("Cannot find a valid default truststore (jssecacerts or cacerts) in " + trustStoreFolder);
}
return trustStore;
}

private GatewayNatRuleType generateGatewayNatRule(Protocol protocol, HostAndPort original,
HostAndPort translated, ReferenceType interfaceRef) {
GatewayNatRuleType gatewayNatRule = new GatewayNatRuleType();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package brooklyn.networking.vclouddirector;

import static org.testng.Assert.assertNotNull;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.vmware.vcloud.api.rest.schema.NatRuleType;

import brooklyn.entity.BrooklynAppLiveTestSupport;
import brooklyn.location.jclouds.JcloudsLocation;
import brooklyn.util.exceptions.Exceptions;

/**
* Tests assume that brooklyn.properties have been configured with location specs for vCHS and TAI.
* For example:
*
* <pre>
* brooklyn.location.named.canopy-vCHS=jclouds:vcloud-director:https://p5v1-vcd.vchs.vmware.com/api
* brooklyn.location.named.canopy-vCHS.identity=jo.blogs@cloudsoftcorp.com@M123456789-1234
* brooklyn.location.named.canopy-vCHS.credential=pa55w0rd
* brooklyn.location.named.canopy-vCHS.advancednetworking.vcloud.network.id=041e176a-befc-4b28-89e2-3c5343ff4d12
* brooklyn.location.named.canopy-vCHS.advancednetworking.vcloud.network.publicip=23.92.230.21
* brooklyn.location.named.canopy-vCHS.trustStorePassword=changeit
*
* brooklyn.location.named.canopy-TAI=jclouds:vcloud-director:https://svdc.it-solutions.atos.net/api
* brooklyn.location.named.canopy-TAI.identity=jo.blogs@myvorg_01
* brooklyn.location.named.canopy-TAI.credential=pa55w0rd
* brooklyn.location.named.canopy-TAI.trustStore=/Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home/jre/lib/security/cacerts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this trustStore= line anymore I presume, so can remove?
Or say in comment that it will be automatically inferred, but can be overridden by...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added more info in the javadoc

* brooklyn.location.named.canopy-TAI.trustStorePassword=changeit
* </pre>
*
* Notice `trustStore` will be automatically inferred as in canopy-vCHS location, but it can be overridden by using
* `trustStore` as in canopy-TAI location
*/
public class SecureNatServiceLiveTest extends BrooklynAppLiveTestSupport {

//
private static final String LOCATION_SPEC = "canopy-vCHS";

private static final String LOCATION_TAI_SPEC = "canopy-TAI";

protected JcloudsLocation loc;

@BeforeMethod(alwaysRun=true)
@Override
public void setUp() throws Exception {
super.setUp();
loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve(LOCATION_SPEC);
}

// TAI (as at 2014-12-16) is running vcloud-director version 5.1
@Test(groups="Live")
public void testGetNatRulesAtTai() throws Exception {
loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve(LOCATION_TAI_SPEC);
NatService service = newServiceBuilder(loc).build();
List<NatRuleType> rules = service.getNatRules(service.getEdgeGateway());
assertNotNull(rules);
}

// Simple test that just checks no errors (e.g. can authenticate etc)
@Test(groups="Live")
public void testGetNatRules() throws Exception {
NatService service = newServiceBuilder(loc).build();
List<NatRuleType> rules = service.getNatRules(service.getEdgeGateway());
assertNotNull(rules);
}

private NatService.Builder newServiceBuilder(JcloudsLocation loc) {
String endpoint = loc.getEndpoint();

// jclouds endpoint has suffix "/api"; but VMware SDK wants it without "api"
String convertedUri;
try {
URI uri = URI.create(endpoint);
convertedUri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null).toString();
} catch (URISyntaxException e) {
throw Exceptions.propagate(e);
}

String trustStore = (String) loc.getAllConfigBag().getStringKey("trustStore"); // if null, it will use default trustore
String trustStorePassword = (String) loc.getAllConfigBag().getStringKey("trustStorePassword");
assertNotNull(trustStorePassword, "trustStorePassword not set on location " + loc);

return NatService.builder()
.identity(loc.getIdentity())
.credential(loc.getCredential())
.endpoint(convertedUri)
.trustStore(trustStore)
.trustStorePassword(trustStorePassword);
}
}