diff --git a/apis/ec2/pom.xml b/apis/ec2/pom.xml
index ccaffbf752..24e64f9bcc 100644
--- a/apis/ec2/pom.xml
+++ b/apis/ec2/pom.xml
@@ -83,6 +83,12 @@
${project.version}
test
+
+ org.jclouds.driver
+ jclouds-bouncycastle
+ ${project.version}
+ test
+
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java
index a11244ec77..2b7f57fce4 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java
@@ -18,19 +18,52 @@
*/
package org.jclouds.ec2.services;
-import java.util.Properties;
-
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.Module;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.EC2AsyncClient;
import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2ContextBuilder;
+import org.jclouds.ec2.EC2PropertiesBuilder;
+import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
+import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedData;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.domain.PasswordData;
+import org.jclouds.ec2.reference.EC2Constants;
+import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
+import org.jclouds.logging.Logger;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
+import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
+import javax.annotation.Nullable;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
/**
* Tests behavior of {@code WindowsClient}
@@ -43,19 +76,30 @@ public class WindowsClientLiveTest extends BaseVersionedServiceLiveTest {
provider = "ec2";
}
+ private ComputeService computeService;
private WindowsClient client;
private static final String DEFAULT_INSTANCE = "i-TODO";
private static final String DEFAULT_BUCKET = "TODO";
private RestContext context;
+ @Override
+ public Properties setupRestProperties() {
+ Properties rest = super.setupRestProperties();
+ rest.put("ec2.contextbuilder", EC2ContextBuilder.class.getName());
+ rest.put("ec2.propertiesbuilder", EC2PropertiesBuilder.class.getName());
+ return rest;
+ }
@BeforeGroups(groups = { "live" })
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
- context = new ComputeServiceContextFactory().createContext(provider,
- ImmutableSet. of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
+ overrides.put(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "206029621532");
+ ComputeServiceContext serviceContext = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider,
+ ImmutableSet.of(new Log4JLoggingModule(), new BouncyCastleCryptoModule()), overrides);
+ computeService = serviceContext.getComputeService();
+ context = serviceContext.getProviderSpecificContext();
client = context.getApi().getWindowsServices();
}
@@ -82,4 +126,52 @@ public class WindowsClientLiveTest extends BaseVersionedServiceLiveTest {
public void testDescribeBundleTasksInRegion() {
}
+
+ @Test
+ public void testGetPasswordData() throws Exception {
+
+ // Spin up a new node. Make sure to open the RDP port 3389
+ Template template = computeService.templateBuilder()
+ .osFamily(OsFamily.WINDOWS)
+ .os64Bit(true)
+ .imageNameMatches("Windows-2008R2-SP1-English-Base-")
+ .hardwareId(InstanceType.M1_LARGE)
+ .options(TemplateOptions.Builder.inboundPorts(3389))
+ .build();
+ Set extends NodeMetadata> nodes = computeService.createNodesInGroup("test", 1, template);
+ NodeMetadata node = Iterables.getOnlyElement(nodes);
+
+ boolean shutdown = true;
+ try {
+
+ // The Administrator password will take some time before it is ready - Amazon says sometimes 15 minutes.
+ // So we create a predicate that tests if the password is ready, and wrap it in a retryable predicate.
+ Predicate passwordReady = new Predicate() {
+ @Override
+ public boolean apply(@Nullable String s) {
+ if (Strings.isNullOrEmpty(s)) return false;
+ PasswordData data = client.getPasswordData(null, s);
+ if (data == null) return false;
+ return !Strings.isNullOrEmpty(data.getPasswordData());
+ }
+ };
+ RetryablePredicate passwordReadyRetryable = new RetryablePredicate(passwordReady, 600, 10, TimeUnit.SECONDS);
+ assertTrue(passwordReadyRetryable.apply(node.getProviderId()));
+
+ // Now pull together Amazon's encrypted password blob, and the private key that jclouds generated
+ PasswordDataAndPrivateKey dataAndKey = new PasswordDataAndPrivateKey(
+ client.getPasswordData(null, node.getProviderId()),
+ node.getCredentials().getPrivateKey());
+
+ // And apply it to the decryption function
+ WindowsLoginCredentialsFromEncryptedData f = context.getUtils().getInjector().getInstance(WindowsLoginCredentialsFromEncryptedData.class);
+ LoginCredentials credentials = f.apply(dataAndKey);
+
+ assertEquals(credentials.getUser(), "Administrator");
+ assertFalse(Strings.isNullOrEmpty(credentials.getPassword()));
+ } finally {
+ computeService.destroyNode(node.getId());
+ }
+ }
+
}