mirror of https://github.com/apache/jclouds.git
Merge pull request #349 from andreisavu/windows-passwords
Support retrieving and decrypting the Administrator password of EC2 Windows instances
This commit is contained in:
commit
db53c00748
|
@ -83,6 +83,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-bouncycastle</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.jclouds.ec2.compute.functions.CredentialsForInstance;
|
||||||
import org.jclouds.ec2.compute.functions.LoadPublicIpForInstanceOrNull;
|
import org.jclouds.ec2.compute.functions.LoadPublicIpForInstanceOrNull;
|
||||||
import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
|
import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
|
||||||
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
|
import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedData;
|
||||||
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.jclouds.ec2.compute.predicates.SecurityGroupPresent;
|
import org.jclouds.ec2.compute.predicates.SecurityGroupPresent;
|
||||||
|
@ -110,6 +111,7 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
bind(new TypeLiteral<ComputeServiceContext>() {
|
bind(new TypeLiteral<ComputeServiceContext>() {
|
||||||
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
|
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
|
||||||
}).in(Scopes.SINGLETON);
|
}).in(Scopes.SINGLETON);
|
||||||
|
bind(WindowsLoginCredentialsFromEncryptedData.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* 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.ec2.compute.domain;
|
||||||
|
|
||||||
|
import org.jclouds.ec2.domain.PasswordData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An encrypted Windows Administrator password, and the private key that can decrypt it.
|
||||||
|
*
|
||||||
|
* @author Richard Downer
|
||||||
|
*/
|
||||||
|
public class PasswordDataAndPrivateKey {
|
||||||
|
|
||||||
|
private final PasswordData passwordData;
|
||||||
|
private final String privateKey;
|
||||||
|
|
||||||
|
public PasswordDataAndPrivateKey(PasswordData passwordData, String privateKey) {
|
||||||
|
this.passwordData = passwordData;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordData getPasswordData() {
|
||||||
|
return passwordData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,6 +86,7 @@ public class EC2ImageParser implements Function<org.jclouds.ec2.domain.Image, Im
|
||||||
ImageBuilder builder = new ImageBuilder();
|
ImageBuilder builder = new ImageBuilder();
|
||||||
builder.providerId(from.getId());
|
builder.providerId(from.getId());
|
||||||
builder.id(from.getRegion() + "/" + from.getId());
|
builder.id(from.getRegion() + "/" + from.getId());
|
||||||
|
builder.name(from.getName());
|
||||||
builder.description(from.getDescription() != null ? from.getDescription() : from.getImageLocation());
|
builder.description(from.getDescription() != null ? from.getDescription() : from.getImageLocation());
|
||||||
builder.userMetadata(ImmutableMap.<String, String> builder().put("owner", from.getImageOwnerId()).put(
|
builder.userMetadata(ImmutableMap.<String, String> builder().put("owner", from.getImageOwnerId()).put(
|
||||||
"rootDeviceType", from.getRootDeviceType().value()).put("virtualizationType",
|
"rootDeviceType", from.getRootDeviceType().value()).put("virtualizationType",
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* 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.ec2.compute.functions;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
|
import org.jclouds.domain.LoginCredentials;
|
||||||
|
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
|
||||||
|
import org.jclouds.encryption.internal.Base64;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an encrypted Windows Administrator password and the decryption key, return a LoginCredentials instance.
|
||||||
|
*
|
||||||
|
* @author Richard Downer
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class WindowsLoginCredentialsFromEncryptedData implements Function<PasswordDataAndPrivateKey, LoginCredentials> {
|
||||||
|
|
||||||
|
private final Crypto crypto;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public WindowsLoginCredentialsFromEncryptedData(Crypto crypto) {
|
||||||
|
this.crypto = crypto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginCredentials apply(@Nullable PasswordDataAndPrivateKey dataAndKey) {
|
||||||
|
if(dataAndKey == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
KeySpec keySpec = Pems.privateKeySpec(dataAndKey.getPrivateKey());
|
||||||
|
KeyFactory kf = crypto.rsaKeyFactory();
|
||||||
|
PrivateKey privKey = kf.generatePrivate(keySpec);
|
||||||
|
|
||||||
|
Cipher cipher = crypto.cipher("RSA/NONE/PKCS1Padding");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privKey);
|
||||||
|
byte[] cipherText = Base64.decode(dataAndKey.getPasswordData().getPasswordData());
|
||||||
|
byte[] plainText = cipher.doFinal(cipherText);
|
||||||
|
String password = new String(plainText, Charset.forName("ASCII"));
|
||||||
|
|
||||||
|
return LoginCredentials.builder()
|
||||||
|
.user("Administrator")
|
||||||
|
.password(password)
|
||||||
|
.noPrivateKey()
|
||||||
|
.build();
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/**
|
||||||
|
* 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.ec2.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the encrypted Windows Administrator password for an instance.
|
||||||
|
*
|
||||||
|
* @author Richard Downer
|
||||||
|
*/
|
||||||
|
public class PasswordData {
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private String requestId;
|
||||||
|
private String instanceId;
|
||||||
|
private Date timestamp;
|
||||||
|
private String passwordData;
|
||||||
|
|
||||||
|
private Builder() {}
|
||||||
|
|
||||||
|
public Builder requestId(String requestId) {
|
||||||
|
this.requestId = requestId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder instanceId(String instanceId) {
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder timestamp(Date timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder passwordData(String passwordData) {
|
||||||
|
this.passwordData = passwordData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordData build() {
|
||||||
|
return new PasswordData(requestId, instanceId, timestamp, passwordData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String requestId;
|
||||||
|
private String instanceId;
|
||||||
|
private Date timestamp;
|
||||||
|
private String passwordData;
|
||||||
|
|
||||||
|
public PasswordData(String requestId, String instanceId, Date timestamp, String passwordData) {
|
||||||
|
this.requestId = requestId;
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.passwordData = passwordData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestId() {
|
||||||
|
return requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordData() {
|
||||||
|
return passwordData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
PasswordData that = (PasswordData) o;
|
||||||
|
|
||||||
|
if (instanceId != null ? !instanceId.equals(that.instanceId) : that.instanceId != null) return false;
|
||||||
|
if (passwordData != null ? !passwordData.equals(that.passwordData) : that.passwordData != null) return false;
|
||||||
|
if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) return false;
|
||||||
|
if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = requestId != null ? requestId.hashCode() : 0;
|
||||||
|
result = 31 * result + (instanceId != null ? instanceId.hashCode() : 0);
|
||||||
|
result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0);
|
||||||
|
result = 31 * result + (passwordData != null ? passwordData.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PasswordData{" +
|
||||||
|
"requestId='" + requestId + '\'' +
|
||||||
|
", instanceId='" + instanceId + '\'' +
|
||||||
|
", timestamp=" + timestamp +
|
||||||
|
", passwordData='" + passwordData + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ import static org.jclouds.aws.reference.FormParameters.VERSION;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.ec2.domain.PasswordData;
|
||||||
|
import org.jclouds.ec2.xml.GetPasswordDataResponseHandler;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
|
@ -96,4 +98,15 @@ public interface WindowsAsyncClient {
|
||||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
@BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
|
@BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see WindowsClient#getPasswordDataInRegion
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@FormParams(keys = ACTION, values = "GetPasswordData")
|
||||||
|
@XMLResponseParser(GetPasswordDataResponseHandler.class)
|
||||||
|
ListenableFuture<PasswordData> getPasswordData(
|
||||||
|
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||||
|
@FormParam("InstanceId") String instanceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ec2.services;
|
package org.jclouds.ec2.services;
|
||||||
|
|
||||||
import java.util.Set;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import java.util.concurrent.TimeUnit;
|
import org.jclouds.ec2.domain.BundleTask;
|
||||||
|
import org.jclouds.ec2.domain.PasswordData;
|
||||||
|
import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.ec2.domain.BundleTask;
|
import java.util.Set;
|
||||||
import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.jclouds.concurrent.Timeout;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides windows services for EC2. For more information, refer to the Amazon
|
* Provides windows services for EC2. For more information, refer to the Amazon
|
||||||
|
@ -109,4 +109,14 @@ public interface WindowsClient {
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<BundleTask> describeBundleTasksInRegion(@Nullable String region, String... bundleTaskIds);
|
Set<BundleTask> describeBundleTasksInRegion(@Nullable String region, String... bundleTaskIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Retrieves the encrypted administrator password for the instances running Windows.
|
||||||
|
*
|
||||||
|
* @param region The region where the instance is based
|
||||||
|
* @param instanceId The ID of the instance to query
|
||||||
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetPasswordData.html" />
|
||||||
|
*/
|
||||||
|
PasswordData getPasswordDataInRegion(@Nullable String region, String instanceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* 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.ec2.xml;
|
||||||
|
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.ec2.domain.PasswordData;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Richard Downer
|
||||||
|
*/
|
||||||
|
public class GetPasswordDataResponseHandler extends ParseSax.HandlerWithResult<PasswordData> {
|
||||||
|
|
||||||
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
private PasswordData.Builder builder = PasswordData.builder();
|
||||||
|
@Inject protected DateService dateService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordData getResult() {
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endElement(String uri, String name, String qName) {
|
||||||
|
if (qName.equals("requestId")) {
|
||||||
|
builder.requestId(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("instanceId")) {
|
||||||
|
builder.instanceId(currentText.toString().trim());
|
||||||
|
} else if (qName.equals("timestamp")) {
|
||||||
|
builder.timestamp(dateService.iso8601DateParse(currentText.toString().trim()));
|
||||||
|
} else if (qName.equals("passwordData")) {
|
||||||
|
builder.passwordData(currentText.toString().trim());
|
||||||
|
}
|
||||||
|
currentText = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
currentText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -61,16 +61,16 @@ public class EC2ImageParserTest {
|
||||||
assertEquals(Iterables.get(result, 0), new ImageBuilder().operatingSystem(
|
assertEquals(Iterables.get(result, 0), new ImageBuilder().operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
|
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
|
||||||
"137112412989/amzn-ami-0.9.7-beta.i386-ebs").is64Bit(false).build()).description("Amazon")
|
"137112412989/amzn-ami-0.9.7-beta.i386-ebs").is64Bit(false).build()).description("Amazon")
|
||||||
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-82e4b5c7").providerId(
|
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-82e4b5c7").name("amzn-ami-0.9.7-beta.i386-ebs")
|
||||||
"ami-82e4b5c7").location(defaultLocation).userMetadata(
|
.providerId("ami-82e4b5c7").location(defaultLocation).userMetadata(
|
||||||
ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
||||||
|
|
||||||
assertEquals(Iterables.get(result, 3), new ImageBuilder().operatingSystem(
|
assertEquals(Iterables.get(result, 3), new ImageBuilder().operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
|
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).arch("paravirtual").version("").description(
|
||||||
"amzn-ami-us-west-1/amzn-ami-0.9.7-beta.x86_64.manifest.xml").is64Bit(true).build())
|
"amzn-ami-us-west-1/amzn-ami-0.9.7-beta.x86_64.manifest.xml").is64Bit(true).build())
|
||||||
.description("Amazon Linux AMI x86_64 S3").defaultCredentials(new LoginCredentials("ec2-user", false)).id(
|
.description("Amazon Linux AMI x86_64 S3").defaultCredentials(new LoginCredentials("ec2-user", false)).id(
|
||||||
"us-east-1/ami-f2e4b5b7").providerId("ami-f2e4b5b7").location(defaultLocation).userMetadata(
|
"us-east-1/ami-f2e4b5b7").providerId("ami-f2e4b5b7").name("amzn-ami-0.9.7-beta.x86_64-S3").location(defaultLocation)
|
||||||
ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
.userMetadata(ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description(
|
static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description(
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* 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.ec2.compute.functions;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.domain.LoginCredentials;
|
||||||
|
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
|
||||||
|
import org.jclouds.ec2.domain.PasswordData;
|
||||||
|
import org.jclouds.encryption.bouncycastle.BouncyCastleCrypto;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Richard Downer
|
||||||
|
*/
|
||||||
|
public class WindowsLoginCredentialsFromEncryptedDataTest {
|
||||||
|
|
||||||
|
private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" +
|
||||||
|
"MIIEowIBAAKCAQEAmN6GOSMnyGNWN19ETBh11tJB5OGs3Dps8kPWqAhF9RyL/mKwkW26vH+h/5Z5\n" +
|
||||||
|
"cA5T80pK72kNnXObFaMHNoX3lavrc6yXF+8F3f1tlFX2Z+iB1pYXz1oBPqT6oOmc2XzcsJuJRakd\n" +
|
||||||
|
"zwRwHDaqljpaW7+TZlxhMa1DmUkD/HHMxDCK8jbUIZDc6BZSrnj2uPwHwW737NRE4aC3fcu4LMwf\n" +
|
||||||
|
"b2VotbNGNiAnNmrb/vtIIGkFE8NYEMpiz0WYTWX4eVKpJImv1PR6G1fMLSvudJs0ARObuLDvuonn\n" +
|
||||||
|
"SCFFdkibrwMKYbHVGGh6FoY1Vy0sqI55dgQU1kSNouiDgOGxgx+TIwIDAQABAoIBAHCS/nk5QGS7\n" +
|
||||||
|
"cpRYXa1EHhNSxx/MaUXM6MoH1x3q6cm1egqdlrWh/vAtdZkIsOkqQ/xX65Me493dcomegwNN6KOZ\n" +
|
||||||
|
"9Uw7/xCq/sEZjga8vzaJ7IOgCGy0NVJyn/a70rv+zW5pO8/G2KLI+95rC3iSBFSoYd3xjcnNdIh/\n" +
|
||||||
|
"UqYnD8oxYpKmf7418pMPsBrkglkFlbVBPiDXdpoSziqSN6uWQG4Yh0WR87aElhM9JJW50Hh6h7g5\n" +
|
||||||
|
"OvgCBzS8G+KXCjqimk108+/ed5Nl6VhPAf79yCVZUueKBhaf2r0Kkyxg7M/Y+LJwcoUusIP7Cv7G\n" +
|
||||||
|
"xyzG2vi21prWRCm2sVCUDyQy5qECgYEA92jGVAaB3OGEUIXn7eVE3U3FQH37XcJMGsHqBIzDG13p\n" +
|
||||||
|
"C97HdN21rwRkz+G2eAsIxA+p9BsO7dSmtKC60kl6iMRgltS3W7xoC37N9BtjhpciHcLg8c70oyDx\n" +
|
||||||
|
"qHiLKuDi90mZ1FPmWupO4FJnGEB3evHUKZSpTrVVMzt+tyEn/psCgYEAni1hrYoMkQgN3sEC3CKB\n" +
|
||||||
|
"0jQkrOMvY219B8Tdf9LXSuP6z9POagDBDhkeT3xn8rAOmOfVGHYdO0CvPqmAkmXhf+g+OREdecQa\n" +
|
||||||
|
"uY0FmvcTt+Dx0c6pRZmm5AhvUVXFXqONsSg79iviXbUy5Hik0k5HTs5E6B4obrh5W+xfMTUXghkC\n" +
|
||||||
|
"gYBn92uAW8uumkYT4HF6EuJBbTD6zPYYjFGW3O4OQ2ip02jfSBrhDVoP1fTXNq6K+3gPi9WLcuNv\n" +
|
||||||
|
"JfF37iMTwzTuzDcaqwDyV9YRHpRFhEzqfhAkGYSVmLZM5scmWKGCv0YhTJiMFUWz5sqGkZopIs4S\n" +
|
||||||
|
"qBTT9FjBbooDIXk6U4CPCQKBgFdVBxEhnz6UC9RpDIMuKi88yuMJrChhUx7u+ryQVH3s0ZXdg6HT\n" +
|
||||||
|
"OMPn6mxIa7v6qJSTq3wN+qW0WQ1n2Kz7wz0zpOctI/EO7RJ1YhrlP+XONLV6PMtIwnQ0lAF8MbTG\n" +
|
||||||
|
"6HxfknugTyMd4DN0yMu0nHpOOI1P2VMIVzkBkK1CevBBAoGBALROGR7a+eijHdp0/A0chfUoBmud\n" +
|
||||||
|
"/TsUt+0g/vf1p69rMt6DqEGMgMtp2jIRnwvLElS7gVqnCTEclxNU/0rCXR+V7ImJm8J4f0ff8m0Y\n" +
|
||||||
|
"Fir9nfCYStszo25NvLFfynS9d/aoBuvqGJaiQyNXiyBJ4MaxxFYagzAWTnDX+kzTlkZ2\n" +
|
||||||
|
"-----END RSA PRIVATE KEY-----";
|
||||||
|
private static final String ENCRYPTED_PASSWORD = "gO1oMoIjjIifv2iqcfIKiQD7ziOTVXsuaBJFEQrZdb8uJH/LsAiJXZeGKEeXlHl/oMoR3HEIoYuHxl+p5iHdrpP889RmxWBDGOWC5iTUzK6CRa5mFmF1I5Lpt7v2YeVoQWihSM8B19BEdBdY1svQp9nyhPB4AqLDrY28x/OrmRh/qYq953i6Y4Z8c76OHqqGcUYM4ePysRlcizSgQjdkEDmKC10Ak3OFRRx3/LqYsFIMiOHeg47APg+UANNTyRiTIia5FDhSeHJzaeYCBRQ7UYH0z2rg4cX3YjOz/MoznjHiaaN4MO+5N3v84VawnqwKOvlwPyI2bmz0+9Tr6DKzqA==";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApply() throws Exception {
|
||||||
|
Crypto crypto = new BouncyCastleCrypto();
|
||||||
|
WindowsLoginCredentialsFromEncryptedData f = new WindowsLoginCredentialsFromEncryptedData(crypto);
|
||||||
|
|
||||||
|
PasswordData passwordData = PasswordData.builder().passwordData(ENCRYPTED_PASSWORD).build();
|
||||||
|
|
||||||
|
LoginCredentials credentials = f.apply(new PasswordDataAndPrivateKey(passwordData, PRIVATE_KEY));
|
||||||
|
|
||||||
|
assertEquals(credentials.getUser(), "Administrator");
|
||||||
|
assertEquals(credentials.getPassword(), "u4.y9mb;nR.");
|
||||||
|
assertFalse(credentials.getOptionalPrivateKey().isPresent());
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,19 +18,44 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ec2.services;
|
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.BaseVersionedServiceLiveTest;
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
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.EC2AsyncClient;
|
||||||
import org.jclouds.ec2.EC2Client;
|
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.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import javax.annotation.Nullable;
|
||||||
import com.google.inject.Module;
|
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}
|
* Tests behavior of {@code WindowsClient}
|
||||||
|
@ -43,19 +68,30 @@ public class WindowsClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
provider = "ec2";
|
provider = "ec2";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ComputeService computeService;
|
||||||
private WindowsClient client;
|
private WindowsClient client;
|
||||||
private static final String DEFAULT_INSTANCE = "i-TODO";
|
private static final String DEFAULT_INSTANCE = "i-TODO";
|
||||||
private static final String DEFAULT_BUCKET = "TODO";
|
private static final String DEFAULT_BUCKET = "TODO";
|
||||||
|
|
||||||
private RestContext<EC2Client, EC2AsyncClient> context;
|
private RestContext<EC2Client, EC2AsyncClient> 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" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
setupCredentials();
|
setupCredentials();
|
||||||
Properties overrides = setupProperties();
|
Properties overrides = setupProperties();
|
||||||
context = new ComputeServiceContextFactory().createContext(provider,
|
overrides.put(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "206029621532"); /* Amazon Owner ID */
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
|
ComputeServiceContext serviceContext = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider,
|
||||||
|
ImmutableSet.<Module>of(new Log4JLoggingModule(), new BouncyCastleCryptoModule()), overrides);
|
||||||
|
computeService = serviceContext.getComputeService();
|
||||||
|
context = serviceContext.getProviderSpecificContext();
|
||||||
client = context.getApi().getWindowsServices();
|
client = context.getApi().getWindowsServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,4 +118,52 @@ public class WindowsClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
public void testDescribeBundleTasksInRegion() {
|
public void testDescribeBundleTasksInRegion() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPasswordDataInRegion() 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<String> passwordReady = new Predicate<String>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable String s) {
|
||||||
|
if (Strings.isNullOrEmpty(s)) return false;
|
||||||
|
PasswordData data = client.getPasswordDataInRegion(null, s);
|
||||||
|
if (data == null) return false;
|
||||||
|
return !Strings.isNullOrEmpty(data.getPasswordData());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RetryablePredicate<String> passwordReadyRetryable = new RetryablePredicate<String>(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.getPasswordDataInRegion(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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,9 @@ import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
|
||||||
import org.jclouds.encryption.internal.JCECrypto;
|
import org.jclouds.encryption.internal.JCECrypto;
|
||||||
|
|
||||||
|
@ -61,4 +63,6 @@ public interface Crypto {
|
||||||
|
|
||||||
MessageDigest sha512();
|
MessageDigest sha512();
|
||||||
|
|
||||||
|
Cipher cipher(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException;
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,7 +28,10 @@ import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -86,6 +89,11 @@ public class JCECrypto implements Crypto {
|
||||||
return provider == null ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, provider);
|
return provider == null ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cipher cipher(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {
|
||||||
|
return provider == null ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, provider);
|
||||||
|
}
|
||||||
|
|
||||||
public final static String MD5 = "MD5";
|
public final static String MD5 = "MD5";
|
||||||
public final static String SHA1 = "SHA1";
|
public final static String SHA1 = "SHA1";
|
||||||
public final static String SHA256 = "SHA-256";
|
public final static String SHA256 = "SHA-256";
|
||||||
|
|
|
@ -18,11 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.compute.strategy;
|
package org.jclouds.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
import java.util.Map;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import java.util.Set;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.inject.Guice;
|
||||||
import org.jclouds.compute.config.BaseComputeServiceContextModule;
|
import org.jclouds.compute.config.BaseComputeServiceContextModule;
|
||||||
import org.jclouds.compute.domain.ImageBuilder;
|
import org.jclouds.compute.domain.ImageBuilder;
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
@ -40,14 +43,10 @@ import org.jclouds.json.Json;
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import java.util.Map;
|
||||||
import com.google.common.base.Suppliers;
|
import java.util.Set;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import static org.testng.Assert.assertEquals;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -68,7 +67,12 @@ public class AWSEC2ImageParserTest {
|
||||||
.description("ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml")
|
.description("ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml")
|
||||||
.defaultCredentials(new LoginCredentials("ubuntu", false)).id("us-east-1/ami-7e28ca17")
|
.defaultCredentials(new LoginCredentials("ubuntu", false)).id("us-east-1/ami-7e28ca17")
|
||||||
.providerId("ami-7e28ca17").location(defaultLocation).version("20091130")
|
.providerId("ami-7e28ca17").location(defaultLocation).version("20091130")
|
||||||
.userMetadata(ImmutableMap.of("owner", "099720109477", "rootDeviceType", "instance-store")).build());
|
.userMetadata(ImmutableMap.of(
|
||||||
|
"owner", "099720109477",
|
||||||
|
"rootDeviceType", "instance-store",
|
||||||
|
"virtualizationType", "paravirtual",
|
||||||
|
"hypervisor", "xen"))
|
||||||
|
.build());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Iterables.get(result, 4),
|
Iterables.get(result, 4),
|
||||||
|
@ -84,6 +88,7 @@ public class AWSEC2ImageParserTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Iterables.get(result, 6),
|
Iterables.get(result, 6),
|
||||||
new ImageBuilder()
|
new ImageBuilder()
|
||||||
|
.name("ebs/ubuntu-images/ubuntu-lucid-10.04-i386-server-20100827")
|
||||||
.operatingSystem(
|
.operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.UBUNTU).arch("paravirtual").version("10.04")
|
new OperatingSystem.Builder().family(OsFamily.UBUNTU).arch("paravirtual").version("10.04")
|
||||||
.description("099720109477/ebs/ubuntu-images/ubuntu-lucid-10.04-i386-server-20100827")
|
.description("099720109477/ebs/ubuntu-images/ubuntu-lucid-10.04-i386-server-20100827")
|
||||||
|
@ -91,7 +96,12 @@ public class AWSEC2ImageParserTest {
|
||||||
.description("099720109477/ebs/ubuntu-images/ubuntu-lucid-10.04-i386-server-20100827")
|
.description("099720109477/ebs/ubuntu-images/ubuntu-lucid-10.04-i386-server-20100827")
|
||||||
.defaultCredentials(new LoginCredentials("ubuntu", false)).id("us-east-1/ami-10f3a255")
|
.defaultCredentials(new LoginCredentials("ubuntu", false)).id("us-east-1/ami-10f3a255")
|
||||||
.providerId("ami-10f3a255").location(defaultLocation).version("20100827")
|
.providerId("ami-10f3a255").location(defaultLocation).version("20100827")
|
||||||
.userMetadata(ImmutableMap.of("owner", "099720109477", "rootDeviceType", "ebs")).build());
|
.userMetadata(ImmutableMap.of(
|
||||||
|
"owner", "099720109477",
|
||||||
|
"rootDeviceType", "ebs",
|
||||||
|
"virtualizationType", "paravirtual",
|
||||||
|
"hypervisor", "xen"))
|
||||||
|
.build());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +130,19 @@ public class AWSEC2ImageParserTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Iterables.get(result, 0),
|
Iterables.get(result, 0),
|
||||||
new ImageBuilder()
|
new ImageBuilder()
|
||||||
|
.name("EC2 CentOS 5.4 HVM AMI")
|
||||||
.operatingSystem(
|
.operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.CENTOS).arch("hvm").version("5.4")
|
new OperatingSystem.Builder().family(OsFamily.CENTOS).arch("hvm").version("5.4")
|
||||||
.description("amazon/EC2 CentOS 5.4 HVM AMI").is64Bit(true).build())
|
.description("amazon/EC2 CentOS 5.4 HVM AMI").is64Bit(true).build())
|
||||||
.description("EC2 CentOS 5.4 HVM AMI")
|
.description("EC2 CentOS 5.4 HVM AMI")
|
||||||
.defaultCredentials(new LoginCredentials("root", false)).id("us-east-1/ami-7ea24a17")
|
.defaultCredentials(new LoginCredentials("root", false)).id("us-east-1/ami-7ea24a17")
|
||||||
.providerId("ami-7ea24a17").location(defaultLocation)
|
.providerId("ami-7ea24a17").location(defaultLocation)
|
||||||
.userMetadata(ImmutableMap.of("owner", "206029621532", "rootDeviceType", "ebs")).build());
|
.userMetadata(ImmutableMap.of(
|
||||||
|
"owner", "206029621532",
|
||||||
|
"rootDeviceType", "ebs",
|
||||||
|
"virtualizationType", "hvm",
|
||||||
|
"hypervisor", "xen"))
|
||||||
|
.build());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,11 +163,11 @@ public class AWSEC2ImageParserTest {
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new Gson().toJson(Iterables.get(result, 1)),
|
new Gson().toJson(Iterables.get(result, 1)),
|
||||||
"{\"operatingSystem\":{\"family\":\"UBUNTU\",\"arch\":\"paravirtual\",\"version\":\"9.10\",\"description\":\"411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"is64Bit\":true},\"version\":\"4.5.3_EBS_Alpha\",\"description\":\"RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"defaultCredentials\":{\"authenticateSudo\":false,\"identity\":\"root\"},\"id\":\"us-east-1/ami-c19db6b5\",\"type\":\"IMAGE\",\"tags\":[],\"providerId\":\"ami-c19db6b5\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\",\"iso3166Codes\":[],\"metadata\":{}},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\",\"virtualizationType\":\"paravirtual\",\"hypervisor\":\"xen\"}}");
|
"{\"operatingSystem\":{\"family\":\"UBUNTU\",\"arch\":\"paravirtual\",\"version\":\"9.10\",\"description\":\"411009282317/RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"is64Bit\":true},\"version\":\"4.5.3_EBS_Alpha\",\"description\":\"RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"defaultCredentials\":{\"authenticateSudo\":false,\"identity\":\"root\"},\"id\":\"us-east-1/ami-c19db6b5\",\"type\":\"IMAGE\",\"tags\":[],\"providerId\":\"ami-c19db6b5\",\"name\":\"RightImage_Ubuntu_9.10_x64_v4.5.3_EBS_Alpha\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\",\"iso3166Codes\":[],\"metadata\":{}},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\",\"virtualizationType\":\"paravirtual\",\"hypervisor\":\"xen\"}}");
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new Gson().toJson(Iterables.get(result, 2)),
|
new Gson().toJson(Iterables.get(result, 2)),
|
||||||
"{\"operatingSystem\":{\"family\":\"WINDOWS\",\"arch\":\"hvm\",\"version\":\"2003\",\"description\":\"411009282317/RightImage Windows_2003_i386_v5.4.3\",\"is64Bit\":false},\"version\":\"5.4.3\",\"description\":\"Built by RightScale\",\"defaultCredentials\":{\"authenticateSudo\":false,\"identity\":\"root\"},\"id\":\"us-east-1/ami-710c2605\",\"type\":\"IMAGE\",\"tags\":[],\"providerId\":\"ami-710c2605\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\",\"iso3166Codes\":[],\"metadata\":{}},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\",\"virtualizationType\":\"hvm\",\"hypervisor\":\"xen\"}}");
|
"{\"operatingSystem\":{\"family\":\"WINDOWS\",\"arch\":\"hvm\",\"version\":\"2003\",\"description\":\"411009282317/RightImage Windows_2003_i386_v5.4.3\",\"is64Bit\":false},\"version\":\"5.4.3\",\"description\":\"Built by RightScale\",\"defaultCredentials\":{\"authenticateSudo\":false,\"identity\":\"root\"},\"id\":\"us-east-1/ami-710c2605\",\"type\":\"IMAGE\",\"tags\":[],\"providerId\":\"ami-710c2605\",\"name\":\"RightImage Windows_2003_i386_v5.4.3\",\"location\":{\"scope\":\"REGION\",\"id\":\"us-east-1\",\"description\":\"us-east-1\",\"iso3166Codes\":[],\"metadata\":{}},\"userMetadata\":{\"owner\":\"411009282317\",\"rootDeviceType\":\"ebs\",\"virtualizationType\":\"hvm\",\"hypervisor\":\"xen\"}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseAmznImage() {
|
public void testParseAmznImage() {
|
||||||
|
@ -161,17 +177,24 @@ public class AWSEC2ImageParserTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Iterables.get(result, 0),
|
Iterables.get(result, 0),
|
||||||
new ImageBuilder()
|
new ImageBuilder()
|
||||||
|
.name("amzn-ami-0.9.7-beta.i386-ebs")
|
||||||
.operatingSystem(
|
.operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.AMZN_LINUX).arch("paravirtual")
|
new OperatingSystem.Builder().family(OsFamily.AMZN_LINUX).arch("paravirtual")
|
||||||
.version("0.9.7-beta").description("137112412989/amzn-ami-0.9.7-beta.i386-ebs")
|
.version("0.9.7-beta").description("137112412989/amzn-ami-0.9.7-beta.i386-ebs")
|
||||||
.is64Bit(false).build()).description("Amazon")
|
.is64Bit(false).build()).description("Amazon")
|
||||||
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-82e4b5c7")
|
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-82e4b5c7")
|
||||||
.providerId("ami-82e4b5c7").location(defaultLocation).version("0.9.7-beta")
|
.providerId("ami-82e4b5c7").location(defaultLocation).version("0.9.7-beta")
|
||||||
.userMetadata(ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
.userMetadata(ImmutableMap.of(
|
||||||
|
"owner", "137112412989",
|
||||||
|
"rootDeviceType", "ebs",
|
||||||
|
"virtualizationType", "paravirtual",
|
||||||
|
"hypervisor", "xen"))
|
||||||
|
.build());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Iterables.get(result, 3),
|
Iterables.get(result, 3),
|
||||||
new ImageBuilder()
|
new ImageBuilder()
|
||||||
|
.name("amzn-ami-0.9.7-beta.x86_64-S3")
|
||||||
.operatingSystem(
|
.operatingSystem(
|
||||||
new OperatingSystem.Builder().family(OsFamily.AMZN_LINUX).arch("paravirtual")
|
new OperatingSystem.Builder().family(OsFamily.AMZN_LINUX).arch("paravirtual")
|
||||||
.version("0.9.7-beta")
|
.version("0.9.7-beta")
|
||||||
|
@ -179,7 +202,12 @@ public class AWSEC2ImageParserTest {
|
||||||
.build()).description("Amazon Linux AMI x86_64 S3")
|
.build()).description("Amazon Linux AMI x86_64 S3")
|
||||||
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-f2e4b5b7")
|
.defaultCredentials(new LoginCredentials("ec2-user", false)).id("us-east-1/ami-f2e4b5b7")
|
||||||
.providerId("ami-f2e4b5b7").location(defaultLocation).version("0.9.7-beta")
|
.providerId("ami-f2e4b5b7").location(defaultLocation).version("0.9.7-beta")
|
||||||
.userMetadata(ImmutableMap.of("owner", "137112412989", "rootDeviceType", "ebs")).build());
|
.userMetadata(ImmutableMap.of(
|
||||||
|
"owner", "137112412989",
|
||||||
|
"rootDeviceType", "ebs",
|
||||||
|
"virtualizationType", "paravirtual",
|
||||||
|
"hypervisor", "xen"))
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1")
|
static Location defaultLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1")
|
||||||
|
|
Loading…
Reference in New Issue