From 3b0a6c690344f33bdb3e9aa6d14df39a3777e951 Mon Sep 17 00:00:00 2001
From: Everett Toews
Date: Wed, 23 Jan 2013 17:30:29 -0600
Subject: [PATCH] The SSL Termination API for Rackspace Cloud Load Balancers.
---
.../CloudLoadBalancersApi.java | 9 ++
.../CloudLoadBalancersAsyncApi.java | 9 ++
.../CloudLoadBalancersRestClientModule.java | 3 +
.../domain/SSLTermination.java | 112 ++++++++++++++---
.../features/HealthMonitorApi.java | 2 +-
.../features/SSLTerminationApi.java | 87 +++++++++++++
.../features/SSLTerminationAsyncApi.java | 81 ++++++++++++
.../features/HealthMonitorApiLiveTest.java | 4 +-
.../features/SSLTerminationApiExpectTest.java | 116 ++++++++++++++++++
.../features/SSLTerminationApiLiveTest.java | 88 +++++++++++++
.../resources/ssltermination-certificate.txt | 13 ++
.../test/resources/ssltermination-create.json | 1 +
.../test/resources/ssltermination-get.json | 10 ++
...ssltermination-intermediatecertificate.txt | 13 ++
.../resources/ssltermination-privatekey.txt | 15 +++
15 files changed, 546 insertions(+), 17 deletions(-)
create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApi.java
create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationAsyncApi.java
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiExpectTest.java
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiLiveTest.java
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-certificate.txt
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-create.json
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-get.json
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-intermediatecertificate.txt
create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-privatekey.txt
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java
index 9f93d688ae..ef6206d4bc 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java
@@ -31,6 +31,7 @@ import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi;
import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorApi;
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi;
import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi;
+import org.jclouds.rackspace.cloudloadbalancers.features.SSLTerminationApi;
import org.jclouds.rackspace.cloudloadbalancers.features.SessionPersistenceApi;
import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPApi;
import org.jclouds.rest.annotations.Delegate;
@@ -115,4 +116,12 @@ public interface CloudLoadBalancersApi {
@Path("/loadbalancers/{lbId}")
ContentCachingApi getContentCachingApiForZoneAndLoadBalancer(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
+
+ /**
+ * Provides synchronous access to SSL Termination features.
+ */
+ @Delegate
+ @Path("/loadbalancers/{lbId}")
+ SSLTerminationApi getSSLTerminationApiForZoneAndLoadBalancer(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java
index 6a11704833..7871cbdd19 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java
@@ -32,6 +32,7 @@ import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi;
+import org.jclouds.rackspace.cloudloadbalancers.features.SSLTerminationAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.SessionPersistenceAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPAsyncApi;
import org.jclouds.rest.annotations.Delegate;
@@ -116,4 +117,12 @@ public interface CloudLoadBalancersAsyncApi {
@Path("/loadbalancers/{lbId}")
ContentCachingAsyncApi getContentCachingApiForZoneAndLoadBalancer(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
+
+ /**
+ * Provides asynchronous access to SSL Termination features.
+ */
+ @Delegate
+ @Path("/loadbalancers/{lbId}")
+ SSLTerminationAsyncApi getSSLTerminationApiForZoneAndLoadBalancer(
+ @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java
index 2f283213fc..2c3c6860e7 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java
@@ -40,6 +40,8 @@ import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi;
import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi;
+import org.jclouds.rackspace.cloudloadbalancers.features.SSLTerminationApi;
+import org.jclouds.rackspace.cloudloadbalancers.features.SSLTerminationAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.SessionPersistenceApi;
import org.jclouds.rackspace.cloudloadbalancers.features.SessionPersistenceAsyncApi;
import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPApi;
@@ -70,6 +72,7 @@ public class CloudLoadBalancersRestClientModule extends
.put(HealthMonitorApi.class, HealthMonitorAsyncApi.class)
.put(SessionPersistenceApi.class, SessionPersistenceAsyncApi.class)
.put(ContentCachingApi.class, ContentCachingAsyncApi.class)
+ .put(SSLTerminationApi.class, SSLTerminationAsyncApi.class)
.build();
public CloudLoadBalancersRestClientModule() {
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java
index 993ef2676c..ce626c92f6 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java
@@ -18,8 +18,13 @@
*/
package org.jclouds.rackspace.cloudloadbalancers.domain;
+import java.beans.ConstructorProperties;
+
+import javax.inject.Named;
+
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
/**
* The SSL Termination feature allows a load balancer user to terminate SSL traffic at the load balancer layer versus
@@ -53,15 +58,24 @@ import com.google.common.base.Objects.ToStringHelper;
* @author Everett Toews
*/
public class SSLTermination {
-
private final boolean enabled;
private final boolean secureTrafficOnly;
private final int securePort;
+ private final Optional certificate;
+ @Named("privatekey")
+ private final Optional privateKey;
+ private final Optional intermediateCertificate;
- protected SSLTermination(boolean enabled, boolean secureTrafficOnly, int securePort) {
+ @ConstructorProperties({ "enabled", "secureTrafficOnly", "securePort", "certificate", "privatekey",
+ "intermediateCertificate" })
+ protected SSLTermination(boolean enabled, boolean secureTrafficOnly, int securePort, String certificate,
+ String privateKey, String intermediateCertificate) {
this.enabled = enabled;
this.secureTrafficOnly = secureTrafficOnly;
this.securePort = securePort;
+ this.certificate = Optional.fromNullable(certificate);
+ this.privateKey = Optional.fromNullable(privateKey);
+ this.intermediateCertificate = Optional.fromNullable(intermediateCertificate);
}
public boolean getEnabled() {
@@ -76,9 +90,21 @@ public class SSLTermination {
return this.securePort;
}
+ public Optional getCertificate() {
+ return this.certificate;
+ }
+
+ public Optional getPrivateKey() {
+ return this.privateKey;
+ }
+
+ public Optional getIntermediateCertificate() {
+ return this.intermediateCertificate;
+ }
+
@Override
public int hashCode() {
- return Objects.hashCode(enabled, secureTrafficOnly, securePort);
+ return Objects.hashCode(enabled, secureTrafficOnly, securePort, certificate, privateKey, intermediateCertificate);
}
@Override
@@ -90,12 +116,16 @@ public class SSLTermination {
SSLTermination that = SSLTermination.class.cast(obj);
return Objects.equal(this.enabled, that.enabled) && Objects.equal(this.secureTrafficOnly, that.secureTrafficOnly)
- && Objects.equal(this.securePort, that.securePort);
+ && Objects.equal(this.securePort, that.securePort) && Objects.equal(this.certificate, that.certificate)
+ && Objects.equal(this.privateKey, that.privateKey)
+ && Objects.equal(this.intermediateCertificate, that.intermediateCertificate);
}
protected ToStringHelper string() {
- return Objects.toStringHelper(this).add("enabled", enabled).add("secureTrafficOnly", secureTrafficOnly)
- .add("securePort", securePort);
+ return Objects.toStringHelper(this).omitNullValues().add("enabled", enabled)
+ .add("secureTrafficOnly", secureTrafficOnly).add("securePort", securePort)
+ .add("certificate", certificate.orNull()).add("privateKey", privateKey.orNull())
+ .add("intermediateCertificate", intermediateCertificate.orNull());
}
@Override
@@ -107,38 +137,92 @@ public class SSLTermination {
private boolean enabled;
private boolean secureTrafficOnly;
private int securePort;
+ private String certificate;
+ private String privateKey;
+ private String intermediateCertificate;
- /**
- * @see SSLTermination#getEnabled()
+ /**
+ * Required. Determines if the load balancer is enabled to terminate SSL traffic.
+ *
+ * If enabled = false, the load balancer will retain its specified SSL attributes, but will not terminate SSL traffic.
*/
public Builder enabled(boolean enabled) {
this.enabled = enabled;
return this;
}
- /**
- * @see SSLTermination#getSecureTrafficOnly()
+ /**
+ * Required. Determines if the load balancer may accept only secure traffic.
+ *
+ * If secureTrafficOnly = true, the load balancer will not accept non-secure traffic.
*/
public Builder secureTrafficOnly(boolean secureTrafficOnly) {
this.secureTrafficOnly = secureTrafficOnly;
return this;
}
- /**
- * @see SSLTermination#getSecurePort()
+ /**
+ * Required. The port on which the SSL termination load balancer will listen for secure traffic.
+ *
+ * The securePort must be unique to the existing LB protocol/port combination. For example, port 443.
*/
public Builder securePort(int securePort) {
this.securePort = securePort;
return this;
}
+ /**
+ * Required. The certificate used for SSL termination.
+ *
+ * The certificate is validated and verified against the key and intermediate certificate if provided.
+ *
+ * All requests to SSL termination require the key/certificates to be in "proper" format, meaning that all raw
+ * line feed characters should be wrapped in a newline character. So if the user pastes in the key from a
+ * mykey.key file, it will not properly handle the field. For example, use string.replaceAll("\n", "\\n").
+ */
+ public Builder certificate(String certificate) {
+ this.certificate = certificate;
+ return this;
+ }
+
+ /**
+ * Required. The private key for the SSL certificate.
+ *
+ * The private key is validated and verified against the provided certificate(s).
+ *
+ * @see SSLTermination#certificate(String)
+ */
+ public Builder privatekey(String privateKey) {
+ this.privateKey = privateKey;
+ return this;
+ }
+
+ /**
+ * Optional only when configuring Intermediate SSL Termination. The user's intermediate certificate used for SSL
+ * termination.
+ *
+ * The intermediate certificate is validated and verified against the key and certificate credentials provided.
+ *
+ * A user may only provide an intermediateCertificate when accompanied by a certificate, private key, and
+ * securePort. It may not be added to an existing SSL configuration as a single attribute in a future request.
+ *
+ * @see SSLTermination#certificate(String)
+ */
+ public Builder intermediateCertificate(String intermediateCertificate) {
+ this.intermediateCertificate = intermediateCertificate;
+ return this;
+ }
+
public SSLTermination build() {
- return new SSLTermination(enabled, secureTrafficOnly, securePort);
+ return new SSLTermination(enabled, secureTrafficOnly, securePort, certificate, privateKey,
+ intermediateCertificate);
}
public Builder from(SSLTermination in) {
return this.enabled(in.getEnabled()).secureTrafficOnly(in.getSecureTrafficOnly())
- .securePort(in.getSecurePort());
+ .securePort(in.getSecurePort()).certificate(in.getCertificate().orNull())
+ .privatekey(in.getPrivateKey().orNull())
+ .intermediateCertificate(in.getIntermediateCertificate().orNull());
}
}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApi.java
index c6cc266a81..3ec0bf56fa 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApi.java
@@ -48,7 +48,7 @@ public interface HealthMonitorApi {
/**
* Remove health monitor.
*
- * @return true on a successful removal, false if the connection throttle was not found
+ * @return true on a successful removal, false if the health monitor was not found
*/
boolean remove();
}
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApi.java
new file mode 100644
index 0000000000..6ce7b2cb2b
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApi.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudloadbalancers.features;
+
+import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination;
+
+/**
+ * The SSL Termination feature allows a load balancer user to terminate SSL traffic at the load balancer layer versus
+ * at the web server layer. A user may choose to configure SSL Termination using a key and an SSL certificate or an
+ * (Intermediate) SSL certificate.
+ *
+ * When SSL Termination is configured on a load balancer, a secure shadow server is created that listens only for
+ * secure traffic on a user-specified port. This shadow server is only visible to and manageable by the system.
+ * Existing or updated attributes on a load balancer with SSL Termination will also apply to its shadow server.
+ * For example, if Connection Logging is enabled on an SSL load balancer, it will also be enabled on the shadow server
+ * and Cloud Files logs will contain log files for both.
+ *
+ * Notes
+ *
+ * - SSL Termination may only be configured on load balancers with non-secure protocols. For example, SSL Termination
+ * can be applied to an HTTP load balancer, but not to an HTTPS load balancer.
+ * - SSL-terminated load balancers decrypt the traffic at the traffic manager and pass unencrypted traffic to the
+ * back-end node. Because of this, the customer's back-end nodes don't know what protocol the client requested.
+ * Therefore the X-Forwarded-Proto (XFP) header has been added for identifying the originating protocol of an HTTP
+ * request as "http" or "https" depending on what protocol the client requested.
+ * - Not every service will return certificates in the proper order. Please verify that your chain of certificates
+ * matches that of walking up the chain from the domain to the CA root.
+ *
+ *
+ * Warning
+ *
+ * - If SSL is enabled on a load balancer that is configured with nodes that are NOT in the same datacenter, then
+ * decrypted traffic will be sent in clear text over the public internet to the external node(s) and will no longer
+ * be secure.
+ *
+ *
+ * @see SSLTerminationAsyncApi
+ * @author Everett Toews
+ */
+public interface SSLTerminationApi {
+ /**
+ * Create or update SSL termination.
+ *
+ * The following attributes may be updated without overwriting a load balancer's existing SSL certificate and key
+ * specifications:
+ *
+ * - enabled
+ * - secureTrafficOnly
+ * - securePort
+ *
+ * These configurable attributes must be provided (individually or grouped) in a request without specifying any
+ * certificate/key combination if a user does not want the system to overwrite the existing SSL certificate/key
+ * configuration.
+ *
+ * If a user wants to replace the existing SSL configuration, a new certificate, privatekey, and securePort
+ * combination must be provided instead of, or in addition to, the optional/editable attributes.
+ */
+ void createOrUpdate(SSLTermination healthMonitor);
+
+ /**
+ * Get SSL termination info.
+ */
+ SSLTermination get();
+
+ /**
+ * Remove SSL termination.
+ *
+ * @return true on a successful removal, false if the SSL termination was not found
+ */
+ boolean remove();
+}
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationAsyncApi.java
new file mode 100644
index 0000000000..caf51515c9
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationAsyncApi.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudloadbalancers.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
+ *
+ *
+ * @see SSLTerminationApi
+ * @author Everett Toews
+ */
+@RequestFilters(AuthenticateRequest.class)
+public interface SSLTerminationAsyncApi {
+
+ /**
+ * @see SSLTerminationApi#createOrUpdate(SSLTermination)
+ */
+ @Named("ssltermination:create")
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(VoidOnNotFoundOr404.class)
+ @Path("/ssltermination")
+ ListenableFuture createOrUpdate(@WrapWith("sslTermination") SSLTermination sslTermination);
+
+ /**
+ * @see SSLTerminationApi#get()
+ */
+ @Named("ssltermination:get")
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @SelectJson("sslTermination")
+ @Fallback(NullOnNotFoundOr404.class)
+ @Path("/ssltermination")
+ ListenableFuture get();
+
+ /**
+ * @see SSLTerminationApi#remove()
+ */
+ @Named("ssltermination:remove")
+ @DELETE
+ @Fallback(FalseOnNotFoundOr422.class)
+ @Path("/ssltermination")
+ @Consumes("*/*")
+ ListenableFuture remove();
+}
diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiLiveTest.java
index eeac6f0e17..3c78f002e1 100644
--- a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiLiveTest.java
+++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiLiveTest.java
@@ -55,7 +55,7 @@ public class HealthMonitorApiLiveTest extends BaseCloudLoadBalancersApiLiveTest
}
@Test(dependsOnMethods = "testCreateLoadBalancer")
- public void testCreateAndGetConnectionThrottling() throws Exception {
+ public void testCreateAndGetHealthMonitor() throws Exception {
clbApi.getHealthMonitorApiForZoneAndLoadBalancer(zone, lb.getId()).createOrUpdate(
HealthMonitorApiExpectTest.getConnectHealthMonitor());
assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
@@ -66,7 +66,7 @@ public class HealthMonitorApiLiveTest extends BaseCloudLoadBalancersApiLiveTest
assertEquals(healthMonitor, HealthMonitorApiExpectTest.getConnectHealthMonitor());
}
- @Test(dependsOnMethods = "testCreateAndGetConnectionThrottling")
+ @Test(dependsOnMethods = "testCreateAndGetHealthMonitor")
public void testRemoveAndGetHealthMonitor() throws Exception {
assertTrue(clbApi.getHealthMonitorApiForZoneAndLoadBalancer(zone, lb.getId()).remove());
assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiExpectTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiExpectTest.java
new file mode 100644
index 0000000000..98a90d4bd0
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiExpectTest.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudloadbalancers.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNull;
+
+import java.io.IOException;
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersApi;
+import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination;
+import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancerApiExpectTest;
+import org.jclouds.util.Strings2;
+import org.testng.annotations.Test;
+
+/**
+ * @author Everett Toews
+ */
+@Test(groups = "unit")
+public class SSLTerminationApiExpectTest extends BaseCloudLoadBalancerApiExpectTest {
+
+ public void testGetSSLTermination() throws IOException {
+ URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/ssltermination");
+ SSLTerminationApi api = requestsSendResponses(
+ rackspaceAuthWithUsernameAndApiKey,
+ responseWithAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ssltermination-get.json")).build()
+ ).getSSLTerminationApiForZoneAndLoadBalancer("DFW", 2000);
+
+ SSLTermination sslTermination = api.get();
+ assertEquals(sslTermination, getSSLTermination());
+ }
+
+ public void testGetDeletedSSLTermination() {
+ URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/ssltermination");
+ SSLTerminationApi api = requestsSendResponses(
+ rackspaceAuthWithUsernameAndApiKey,
+ responseWithAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getSSLTerminationApiForZoneAndLoadBalancer("DFW", 2000);
+
+ SSLTermination sslTermination = api.get();
+ assertNull(sslTermination);
+ }
+
+ public void testCreateSSLTermination() throws IOException {
+ URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/ssltermination");
+ SSLTerminationApi api = requestsSendResponses(
+ rackspaceAuthWithUsernameAndApiKey,
+ responseWithAccess,
+ authenticatedGET()
+ .method("PUT")
+ .endpoint(endpoint)
+ .payload(payloadFromResourceWithContentType("/ssltermination-create.json", MediaType.APPLICATION_JSON))
+ .build(),
+ HttpResponse.builder().statusCode(200).build()
+ ).getSSLTerminationApiForZoneAndLoadBalancer("DFW", 2000);
+
+ api.createOrUpdate(getSSLTermination());
+ }
+
+ public void testRemoveSSLTermination() {
+ URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/ssltermination");
+ SSLTerminationApi api = requestsSendResponses(
+ rackspaceAuthWithUsernameAndApiKey,
+ responseWithAccess,
+ authenticatedGET().method("DELETE").endpoint(endpoint).replaceHeader("Accept", MediaType.WILDCARD).build(),
+ HttpResponse.builder().statusCode(200).build()
+ ).getSSLTerminationApiForZoneAndLoadBalancer("DFW", 2000);
+
+ assertTrue(api.remove());
+ }
+
+ public static SSLTermination getSSLTermination() throws IOException {
+ String certificate = Strings2.toStringAndClose(
+ SSLTerminationApiExpectTest.class.getResourceAsStream("/ssltermination-certificate.txt"));
+ String privateKey = Strings2.toStringAndClose(
+ SSLTerminationApiExpectTest.class.getResourceAsStream("/ssltermination-privatekey.txt"));
+ String intermediateCertificate = Strings2.toStringAndClose(
+ SSLTerminationApiExpectTest.class.getResourceAsStream("/ssltermination-intermediatecertificate.txt"));
+
+ SSLTermination sslTermination = SSLTermination.builder()
+ .enabled(true)
+ .secureTrafficOnly(false)
+ .securePort(443)
+ .certificate(certificate)
+ .privatekey(privateKey)
+ .intermediateCertificate(intermediateCertificate)
+ .build();
+
+ return sslTermination;
+ }
+}
diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiLiveTest.java
new file mode 100644
index 0000000000..a7260ceb37
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/SSLTerminationApiLiveTest.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudloadbalancers.features;
+
+import static org.jclouds.rackspace.cloudloadbalancers.predicates.LoadBalancerPredicates.awaitAvailable;
+import static org.jclouds.rackspace.cloudloadbalancers.predicates.LoadBalancerPredicates.awaitDeleted;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination;
+import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer;
+import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancerRequest;
+import org.jclouds.rackspace.cloudloadbalancers.domain.NodeRequest;
+import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP.Type;
+import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancersApiLiveTest;
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Everett Toews
+ */
+@Test(groups = "live", singleThreaded = true, testName = "SSLTerminationApiLiveTest")
+public class SSLTerminationApiLiveTest extends BaseCloudLoadBalancersApiLiveTest {
+ private LoadBalancer lb;
+ private String zone;
+
+ public void testCreateLoadBalancer() {
+ NodeRequest nodeRequest = NodeRequest.builder().address("192.168.1.1").port(8080).build();
+ LoadBalancerRequest lbRequest = LoadBalancerRequest.builder()
+ .name(prefix+"-jclouds").protocol("HTTP").port(80).virtualIPType(Type.PUBLIC).node(nodeRequest).build();
+
+ zone = Iterables.getFirst(clbApi.getConfiguredZones(), null);
+ lb = clbApi.getLoadBalancerApiForZone(zone).create(lbRequest);
+
+ assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
+ }
+
+ @Test(dependsOnMethods = "testCreateLoadBalancer")
+ public void testCreateAndGetSSLTermination() throws Exception {
+ clbApi.getSSLTerminationApiForZoneAndLoadBalancer(zone, lb.getId()).createOrUpdate(
+ SSLTerminationApiExpectTest.getSSLTermination());
+ assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
+
+ SSLTermination sslTermination =
+ clbApi.getSSLTerminationApiForZoneAndLoadBalancer(zone, lb.getId()).get();
+
+ assertEquals(sslTermination, SSLTerminationApiExpectTest.getSSLTermination());
+ }
+
+ @Test(dependsOnMethods = "testCreateAndGetSSLTermination")
+ public void testRemoveAndGetSSLTermination() throws Exception {
+ assertTrue(clbApi.getSSLTerminationApiForZoneAndLoadBalancer(zone, lb.getId()).remove());
+ assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
+
+ SSLTermination sslTermination =
+ clbApi.getSSLTerminationApiForZoneAndLoadBalancer(zone, lb.getId()).get();
+
+ assertNull(sslTermination);
+ }
+
+ @Override
+ @AfterGroups(groups = "live")
+ protected void tearDownContext() {
+ assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
+ clbApi.getLoadBalancerApiForZone(zone).remove(lb.getId());
+ assertTrue(awaitDeleted(clbApi.getLoadBalancerApiForZone(zone)).apply(lb));
+ super.tearDownContext();
+ }
+}
diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-certificate.txt b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-certificate.txt
new file mode 100644
index 0000000000..0f3500c88c
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-certificate.txt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR
+tI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg
+YON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN
+Ium/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF
+AAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe
+RhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5
+Kz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-create.json b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-create.json
new file mode 100644
index 0000000000..511a6bfd01
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-create.json
@@ -0,0 +1 @@
+{"sslTermination":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\nVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\ncyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG\nA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0\nIFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR\ntI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg\nYON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN\nIum/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF\nAAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe\nRhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5\nKz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==\n-----END CERTIFICATE-----","enabled":true,"secureTrafficOnly":false,"privatekey":"-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDDohG0j8xB1A2wdPZS1QhdRt+7/u7EqooiVsToGPn6VkW9RKuR\nMVGqCOBQAOnagVRgxGBg43wcS/QfMk4G6NqNR3LWxZCIPKSG2WwxDYpOeFhLtwEz\nv3wOGm3YrNb+JQvNNc0i6b8KMJzuDWXTHEX0K/M9t0KfShvAx3Wh5yYelwIDAQAB\nAoGAdKCD6Z7oaD4gwxeXWZ5C1EjSTOMYOQpqOzp7PNrW/BS+kq0DkxVR2Apen5NL\n1sXPJbkss9YqQTxOluKIfboHv7J9mUSOisUnFVmjD3l5dik3vAPgIybr7aQvfVbF\ns93N/WiTICLTwGHOjyYPttCxdKKW1noL5S8Pcni7F1TnlxECQQDunLeBNmtRK8lh\nwG6FTNMtJSPYXhfhDQfLZj74ITC8sgd0a2Co6AK6v6JADTXujo+HJi6Bo9eqQ49F\nmom+hXfjAkEA0eOVDQZ4XcWLGfhB/B5mUmHC0m+JAsds1slr+2B8mCGcaAsynPd0\nj068seY3qsJuguO5OUzati8RQWWSNzu0vQJAIkHLsrheZfP0YJ1hALBL7UJUyB6S\nLRRS1yfhyHvzZFPm8BbudLGCms8iezGqWYqMHqojqScdsmsqqaKLPhgpYwJAW1AH\nqIMIGsO2oLXA/066dVzSxXqAwRTB5S/8KoDvs7/rq9gzTNbbfv1iWoMt9LxiF8+6\n5ZLqFBimCS2HT0BKgQJAEDONaHND9mRLRaSAvh5zXM86FPPbjg9xjSufO6+ZnGwI\nN5jdN55nrwoA1K4RvDc2tVGo+0EvvU/tmnNKLwEU2Q==\n-----END RSA PRIVATE KEY-----","intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\nVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\ncyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG\nA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0\nIFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR\ntI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg\nYON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN\nIum/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF\nAAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe\nRhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5\nKz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==\n-----END CERTIFICATE-----","securePort":443}}
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-get.json b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-get.json
new file mode 100644
index 0000000000..b89b9c49d2
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-get.json
@@ -0,0 +1,10 @@
+{
+ "sslTermination": {
+ "certificate": "-----BEGIN CERTIFICATE-----\nMIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\nVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\ncyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG\nA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0\nIFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR\ntI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg\nYON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN\nIum/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF\nAAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe\nRhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5\nKz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==\n-----END CERTIFICATE-----",
+ "enabled": true,
+ "secureTrafficOnly": false,
+ "privatekey": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDDohG0j8xB1A2wdPZS1QhdRt+7/u7EqooiVsToGPn6VkW9RKuR\nMVGqCOBQAOnagVRgxGBg43wcS/QfMk4G6NqNR3LWxZCIPKSG2WwxDYpOeFhLtwEz\nv3wOGm3YrNb+JQvNNc0i6b8KMJzuDWXTHEX0K/M9t0KfShvAx3Wh5yYelwIDAQAB\nAoGAdKCD6Z7oaD4gwxeXWZ5C1EjSTOMYOQpqOzp7PNrW/BS+kq0DkxVR2Apen5NL\n1sXPJbkss9YqQTxOluKIfboHv7J9mUSOisUnFVmjD3l5dik3vAPgIybr7aQvfVbF\ns93N/WiTICLTwGHOjyYPttCxdKKW1noL5S8Pcni7F1TnlxECQQDunLeBNmtRK8lh\nwG6FTNMtJSPYXhfhDQfLZj74ITC8sgd0a2Co6AK6v6JADTXujo+HJi6Bo9eqQ49F\nmom+hXfjAkEA0eOVDQZ4XcWLGfhB/B5mUmHC0m+JAsds1slr+2B8mCGcaAsynPd0\nj068seY3qsJuguO5OUzati8RQWWSNzu0vQJAIkHLsrheZfP0YJ1hALBL7UJUyB6S\nLRRS1yfhyHvzZFPm8BbudLGCms8iezGqWYqMHqojqScdsmsqqaKLPhgpYwJAW1AH\nqIMIGsO2oLXA/066dVzSxXqAwRTB5S/8KoDvs7/rq9gzTNbbfv1iWoMt9LxiF8+6\n5ZLqFBimCS2HT0BKgQJAEDONaHND9mRLRaSAvh5zXM86FPPbjg9xjSufO6+ZnGwI\nN5jdN55nrwoA1K4RvDc2tVGo+0EvvU/tmnNKLwEU2Q==\n-----END RSA PRIVATE KEY-----",
+ "intermediateCertificate": "-----BEGIN CERTIFICATE-----\nMIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\nVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\ncyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG\nA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0\nIFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR\ntI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg\nYON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN\nIum/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF\nAAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe\nRhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5\nKz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==\n-----END CERTIFICATE-----",
+ "securePort": 443
+ }
+}
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-intermediatecertificate.txt b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-intermediatecertificate.txt
new file mode 100644
index 0000000000..0f3500c88c
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-intermediatecertificate.txt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICATCCAWoCCQCvn3QIv4NQODANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTEzMDEwMzIxNTMyMloXDTE0MDEwMzIxNTMyMlowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw6IR
+tI/MQdQNsHT2UtUIXUbfu/7uxKqKIlbE6Bj5+lZFvUSrkTFRqgjgUADp2oFUYMRg
+YON8HEv0HzJOBujajUdy1sWQiDykhtlsMQ2KTnhYS7cBM798Dhpt2KzW/iULzTXN
+Ium/CjCc7g1l0xxF9CvzPbdCn0obwMd1oecmHpcCAwEAATANBgkqhkiG9w0BAQUF
+AAOBgQAn3gwe8XBCz7mnEJ+qexcqCwXn3vJt2gdrMEWyW8SGI6FW3X01pJZYDuPe
+RhN3aaWzYDB7yKEKvvrWAL0ovcjmc/lbRY0dvX2/SS4UWg4B3Z5rbCK3CemOx4D5
+Kz6inaEpLLrCmMBqIlOHTsFyB5Tv/SlCP22eS9C91MsoIJtRKQ==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-privatekey.txt b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-privatekey.txt
new file mode 100644
index 0000000000..0bd4cbf055
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/test/resources/ssltermination-privatekey.txt
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDDohG0j8xB1A2wdPZS1QhdRt+7/u7EqooiVsToGPn6VkW9RKuR
+MVGqCOBQAOnagVRgxGBg43wcS/QfMk4G6NqNR3LWxZCIPKSG2WwxDYpOeFhLtwEz
+v3wOGm3YrNb+JQvNNc0i6b8KMJzuDWXTHEX0K/M9t0KfShvAx3Wh5yYelwIDAQAB
+AoGAdKCD6Z7oaD4gwxeXWZ5C1EjSTOMYOQpqOzp7PNrW/BS+kq0DkxVR2Apen5NL
+1sXPJbkss9YqQTxOluKIfboHv7J9mUSOisUnFVmjD3l5dik3vAPgIybr7aQvfVbF
+s93N/WiTICLTwGHOjyYPttCxdKKW1noL5S8Pcni7F1TnlxECQQDunLeBNmtRK8lh
+wG6FTNMtJSPYXhfhDQfLZj74ITC8sgd0a2Co6AK6v6JADTXujo+HJi6Bo9eqQ49F
+mom+hXfjAkEA0eOVDQZ4XcWLGfhB/B5mUmHC0m+JAsds1slr+2B8mCGcaAsynPd0
+j068seY3qsJuguO5OUzati8RQWWSNzu0vQJAIkHLsrheZfP0YJ1hALBL7UJUyB6S
+LRRS1yfhyHvzZFPm8BbudLGCms8iezGqWYqMHqojqScdsmsqqaKLPhgpYwJAW1AH
+qIMIGsO2oLXA/066dVzSxXqAwRTB5S/8KoDvs7/rq9gzTNbbfv1iWoMt9LxiF8+6
+5ZLqFBimCS2HT0BKgQJAEDONaHND9mRLRaSAvh5zXM86FPPbjg9xjSufO6+ZnGwI
+N5jdN55nrwoA1K4RvDc2tVGo+0EvvU/tmnNKLwEU2Q==
+-----END RSA PRIVATE KEY-----
\ No newline at end of file