mirror of https://github.com/apache/jclouds.git
unwound dependencies relating to ssh keys and crypt
This commit is contained in:
parent
6a8ac673aa
commit
3ac6f475e7
|
@ -29,13 +29,13 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||||
import org.jclouds.cloudstack.filters.QuerySigner;
|
import org.jclouds.cloudstack.filters.QuerySigner;
|
||||||
import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
|
import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
|
||||||
import org.jclouds.cloudstack.options.ListSSHKeyPairsOptions;
|
import org.jclouds.cloudstack.options.ListSSHKeyPairsOptions;
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
|
||||||
import org.jclouds.functions.IdentityFunction;
|
import org.jclouds.functions.IdentityFunction;
|
||||||
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
||||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Functions;
|
import com.google.common.base.Functions;
|
||||||
|
|
|
@ -27,9 +27,9 @@ import java.net.URI;
|
||||||
import org.jclouds.cloudstack.CloudStackContext;
|
import org.jclouds.cloudstack.CloudStackContext;
|
||||||
import org.jclouds.cloudstack.domain.SshKeyPair;
|
import org.jclouds.cloudstack.domain.SshKeyPair;
|
||||||
import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
|
import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.domain.SshKeyPair;
|
import org.jclouds.cloudstack.domain.SshKeyPair;
|
||||||
import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
|
import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
|
||||||
import org.jclouds.crypto.SshKeys;
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.testng.annotations.AfterMethod;
|
import org.testng.annotations.AfterMethod;
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
|
@ -21,8 +21,8 @@ package org.jclouds.ec2.compute.strategy;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
|
||||||
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
|
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
|
@ -20,8 +20,8 @@ package org.jclouds.ec2.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,9 +22,9 @@ import static org.testng.Assert.assertEquals;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,9 +30,9 @@ import java.util.SortedSet;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeTestUtils;
|
import org.jclouds.compute.ComputeTestUtils;
|
||||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.openstack.nova.ec2.NovaEC2ApiMetadata;
|
import org.jclouds.openstack.nova.ec2.NovaEC2ApiMetadata;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ package org.jclouds.openstack.nova.v2_0.compute.strategy;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
@ -26,9 +26,9 @@ import java.util.Map;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.trmk.vcloud_0_8.compute.domain.OrgAndName;
|
import org.jclouds.trmk.vcloud_0_8.compute.domain.OrgAndName;
|
||||||
import org.jclouds.trmk.vcloud_0_8.compute.functions.CreateUniqueKeyPair;
|
import org.jclouds.trmk.vcloud_0_8.compute.functions.CreateUniqueKeyPair;
|
||||||
import org.jclouds.trmk.vcloud_0_8.compute.options.TerremarkVCloudTemplateOptions;
|
import org.jclouds.trmk.vcloud_0_8.compute.options.TerremarkVCloudTemplateOptions;
|
||||||
|
|
|
@ -24,8 +24,8 @@ import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.http.functions.BaseHandlerTest;
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.trmk.vcloud_0_8.domain.KeyPair;
|
import org.jclouds.trmk.vcloud_0_8.domain.KeyPair;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/**
|
||||||
|
* 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.compute.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Charsets.UTF_8;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.config.AdminAccessConfiguration.Default;
|
||||||
|
import org.jclouds.compute.functions.Sha512Crypt;
|
||||||
|
import org.jclouds.scriptbuilder.statements.login.AdminAccess.Configuration;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ImplementedBy(Default.class)
|
||||||
|
public interface AdminAccessConfiguration extends Configuration {
|
||||||
|
@Singleton
|
||||||
|
static class Default implements AdminAccessConfiguration {
|
||||||
|
|
||||||
|
private final Supplier<String> defaultAdminUsername = Suppliers.ofInstance(System.getProperty("user.name"));
|
||||||
|
private final Supplier<Map<String, String>> defaultAdminSshKeys = new Supplier<Map<String, String>>() {
|
||||||
|
public Map<String, String> get() {
|
||||||
|
try {
|
||||||
|
return ImmutableMap.of("public",
|
||||||
|
Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa.pub"), UTF_8), "private",
|
||||||
|
Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa"), UTF_8));
|
||||||
|
} catch (IOException e) {
|
||||||
|
return SshKeys.generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cheap, lightweight, low-security password generator.
|
||||||
|
*
|
||||||
|
* @see <a href=
|
||||||
|
* "http://www.java-forums.org/java-lang/7355-how-create-lightweight-low-security-password-generator.html" />
|
||||||
|
*/
|
||||||
|
enum PasswordGenerator implements Supplier<String> {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
/** Minimum length for a decent password */
|
||||||
|
public static final int MIN_LENGTH = 10;
|
||||||
|
|
||||||
|
/** The random number generator. */
|
||||||
|
protected static final SecureRandom r = new SecureRandom();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set of characters that is valid. Must be printable, memorable, and "won't break HTML" (i.e., not ' <', '>',
|
||||||
|
* '&', '=', ...). or break shell commands (i.e., not ' <', '>', '$', '!', ...). I, L and O are good to leave
|
||||||
|
* out, as are numeric zero and one.
|
||||||
|
*/
|
||||||
|
public static final char[] goodChar = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q',
|
||||||
|
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N',
|
||||||
|
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-',
|
||||||
|
'@', };
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < MIN_LENGTH; i++) {
|
||||||
|
sb.append(goodChar[r.nextInt(goodChar.length)]);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Function<String, String> cryptFunction = Sha512Crypt.function();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<String> defaultAdminUsername() {
|
||||||
|
return defaultAdminUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<Map<String, String>> defaultAdminSshKeys() {
|
||||||
|
return defaultAdminSshKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<String> passwordGenerator() {
|
||||||
|
return PasswordGenerator.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<String, String> cryptFunction() {
|
||||||
|
return cryptFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,7 @@ import org.jclouds.location.Provider;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -85,6 +86,7 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
bind(AdminAccess.Configuration.class).to(AdminAccessConfiguration.class);
|
||||||
install(new ComputeServiceTimeoutsModule());
|
install(new ComputeServiceTimeoutsModule());
|
||||||
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
|
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
|
||||||
}).to(CreateSshClientOncePortIsListeningOnNode.class);
|
}).to(CreateSshClientOncePortIsListeningOnNode.class);
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.compute.functions;
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
|
@ -16,10 +16,12 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.ssh;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.ssh;
|
||||||
|
|
||||||
import static com.google.common.base.Joiner.on;
|
import static com.google.common.base.Joiner.on;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
@ -48,6 +48,8 @@ import java.security.spec.RSAPrivateCrtKeySpec;
|
||||||
import java.security.spec.RSAPublicKeySpec;
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
import org.jclouds.io.InputSuppliers;
|
import org.jclouds.io.InputSuppliers;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ssh;
|
package org.jclouds.ssh.config;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.ssh.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
@ -25,10 +25,14 @@ import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.ssh.SshKeyPairGenerator;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class RsaSshKeyPairGenerator implements SshKeyPairGenerator {
|
public class RsaSshKeyPairGenerator implements SshKeyPairGenerator {
|
||||||
private final Crypto crypto;
|
private final Crypto crypto;
|
||||||
private final SecureRandom secureRandom;
|
private final SecureRandom secureRandom;
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.easymock.IArgumentMatcher;
|
import org.easymock.IArgumentMatcher;
|
||||||
|
import org.jclouds.compute.config.AdminAccessConfiguration;
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||||
|
@ -42,8 +43,6 @@ import org.jclouds.io.Payload;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.predicates.SocketOpen;
|
import org.jclouds.predicates.SocketOpen;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
|
|
||||||
import org.jclouds.scriptbuilder.statements.login.AdminAccess.Configuration;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -104,31 +103,23 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
@Override
|
@Override
|
||||||
protected Module getSshModule() {
|
protected Module getSshModule() {
|
||||||
return new AbstractModule() {
|
return new AbstractModule() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(AdminAccess.Configuration.class).toInstance(new Configuration() {
|
bind(AdminAccessConfiguration.class).toInstance(new AdminAccessConfiguration() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<String> defaultAdminUsername() {
|
public Supplier<String> defaultAdminUsername() {
|
||||||
return Suppliers.ofInstance("defaultAdminUsername");
|
return Suppliers.ofInstance("defaultAdminUsername");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<Map<String, String>> defaultAdminSshKeys() {
|
public Supplier<Map<String, String>> defaultAdminSshKeys() {
|
||||||
return Suppliers.<Map<String, String>> ofInstance(ImmutableMap.of("public", "publicKey", "private",
|
return Suppliers.<Map<String, String>> ofInstance(ImmutableMap.of("public", "publicKey", "private",
|
||||||
Pems.PRIVATE_PKCS1_MARKER));
|
Pems.PRIVATE_PKCS1_MARKER));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<String, String> cryptFunction() {
|
public Function<String, String> cryptFunction() {
|
||||||
return new Function<String, String>() {
|
return new Function<String, String>() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public String apply(String input) {
|
public String apply(String input) {
|
||||||
return String.format("crypt(%s)", input);
|
return String.format("crypt(%s)", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.compute.functions;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.compute.functions.Sha512Crypt;
|
||||||
import org.testng.annotations.DataProvider;
|
import org.testng.annotations.DataProvider;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.ssh;
|
||||||
|
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprint;
|
import static org.jclouds.ssh.SshKeys.fingerprint;
|
||||||
import static org.jclouds.crypto.SshKeys.generate;
|
import static org.jclouds.ssh.SshKeys.generate;
|
||||||
import static org.jclouds.crypto.SshKeys.privateKeyHasFingerprint;
|
import static org.jclouds.ssh.SshKeys.privateKeyHasFingerprint;
|
||||||
import static org.jclouds.crypto.SshKeys.privateKeyHasSha1;
|
import static org.jclouds.ssh.SshKeys.privateKeyHasSha1;
|
||||||
import static org.jclouds.crypto.SshKeys.privateKeyMatchesPublicKey;
|
import static org.jclouds.ssh.SshKeys.privateKeyMatchesPublicKey;
|
||||||
import static org.jclouds.crypto.SshKeys.publicKeySpecFromOpenSSH;
|
import static org.jclouds.ssh.SshKeys.publicKeySpecFromOpenSSH;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -35,7 +35,9 @@ import java.security.spec.RSAPrivateCrtKeySpec;
|
||||||
import java.security.spec.RSAPublicKeySpec;
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.crypto;
|
package org.jclouds.ssh.config;
|
||||||
|
|
||||||
import static org.easymock.EasyMock.createMock;
|
import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
|
@ -37,7 +37,11 @@ import java.security.SecureRandom;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.Crypto;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
|
import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
package org.jclouds.rest.internal;
|
package org.jclouds.rest.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Optional.fromNullable;
|
import static com.google.common.base.Optional.fromNullable;
|
||||||
|
import static com.google.common.collect.ObjectArrays.concat;
|
||||||
|
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
|
||||||
|
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -39,6 +42,8 @@ import com.google.common.base.Optional;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
import com.google.common.util.concurrent.UncheckedTimeoutException;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
public class BlockOnFuture implements Function<ListenableFuture<?>, Result> {
|
public class BlockOnFuture implements Function<ListenableFuture<?>, Result> {
|
||||||
|
@ -77,20 +82,40 @@ public class BlockOnFuture implements Function<ListenableFuture<?>, Result> {
|
||||||
try {
|
try {
|
||||||
if (timeoutNanos.isPresent()) {
|
if (timeoutNanos.isPresent()) {
|
||||||
logger.debug(">> blocking on %s for %s", future, timeoutNanos);
|
logger.debug(">> blocking on %s for %s", future, timeoutNanos);
|
||||||
return Result.success(future.get(timeoutNanos.get(), TimeUnit.NANOSECONDS));
|
return Result.success(getUninterruptibly(future, timeoutNanos.get(), NANOSECONDS));
|
||||||
} else {
|
} else {
|
||||||
logger.debug(">> blocking on %s", future);
|
logger.debug(">> blocking on %s", future);
|
||||||
return Result.success(future.get());
|
return Result.success(getUninterruptibly(future));
|
||||||
}
|
}
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
return Result.fail(e.getCause());
|
throw propagateCause(e);
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return Result.fail(e); // TODO: should we kill the future?
|
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
return Result.fail(e);
|
future.cancel(true);
|
||||||
|
throw new UncheckedTimeoutException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static RuntimeException propagateCause(Exception e) {
|
||||||
|
Throwable cause = e.getCause();
|
||||||
|
if (cause == null) {
|
||||||
|
UncheckedExecutionException unchecked = new UncheckedExecutionException(e.getMessage()) {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
};
|
||||||
|
unchecked.setStackTrace(e.getStackTrace());
|
||||||
|
throw unchecked;
|
||||||
|
}
|
||||||
|
StackTraceElement[] combined = concat(cause.getStackTrace(), e.getStackTrace(), StackTraceElement.class);
|
||||||
|
cause.setStackTrace(combined);
|
||||||
|
if (cause instanceof RuntimeException) {
|
||||||
|
throw (RuntimeException) cause;
|
||||||
|
}
|
||||||
|
if (cause instanceof Error) {
|
||||||
|
throw (Error) cause;
|
||||||
|
}
|
||||||
|
// The cause is a weird kind of Throwable, so throw the outer exception.
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
// override timeout by values configured in properties(in ms)
|
// override timeout by values configured in properties(in ms)
|
||||||
private Optional<Long> timeoutInNanos(Invokable<?, ?> invoked, Map<String, Long> timeouts) {
|
private Optional<Long> timeoutInNanos(Invokable<?, ?> invoked, Map<String, Long> timeouts) {
|
||||||
String className = enclosingType.getRawType().getSimpleName();
|
String className = enclosingType.getRawType().getSimpleName();
|
||||||
|
|
|
@ -28,8 +28,8 @@ import static com.google.common.base.Throwables.getCausalChain;
|
||||||
import static com.google.common.collect.Iterables.any;
|
import static com.google.common.collect.Iterables.any;
|
||||||
import static com.google.common.hash.Hashing.md5;
|
import static com.google.common.hash.Hashing.md5;
|
||||||
import static com.google.common.io.BaseEncoding.base16;
|
import static com.google.common.io.BaseEncoding.base16;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
|
||||||
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
|
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.ssh.ConfiguresSshClient;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.config.ConfiguresSshClient;
|
||||||
import org.jclouds.ssh.jsch.JschSshClient;
|
import org.jclouds.ssh.jsch.JschSshClient;
|
||||||
|
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
|
|
@ -28,8 +28,8 @@ import static com.google.common.base.Throwables.getCausalChain;
|
||||||
import static com.google.common.collect.Iterables.any;
|
import static com.google.common.collect.Iterables.any;
|
||||||
import static com.google.common.hash.Hashing.md5;
|
import static com.google.common.hash.Hashing.md5;
|
||||||
import static com.google.common.io.BaseEncoding.base16;
|
import static com.google.common.io.BaseEncoding.base16;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
|
||||||
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
|
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.ssh.ConfiguresSshClient;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.config.ConfiguresSshClient;
|
||||||
import org.jclouds.sshj.SshjSshClient;
|
import org.jclouds.sshj.SshjSshClient;
|
||||||
|
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
|
|
@ -28,12 +28,12 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.crypto.SshKeyPairGenerator;
|
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.JoyentCloudApi;
|
import org.jclouds.joyent.cloudapi.v6_5.JoyentCloudApi;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.KeyAndPrivateKey;
|
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.KeyAndPrivateKey;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.datacenterscoped.DatacenterAndName;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.datacenterscoped.DatacenterAndName;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.ssh.SshKeyPairGenerator;
|
||||||
|
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
|
@ -28,7 +28,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.crypto.SshKeyPairGenerator;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.BaseJoyentCloudComputeServiceExpectTest;
|
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.BaseJoyentCloudComputeServiceExpectTest;
|
||||||
|
@ -37,6 +36,7 @@ import org.jclouds.joyent.cloudapi.v6_5.features.DatasetApiExpectTest;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.features.MachineApiExpectTest;
|
import org.jclouds.joyent.cloudapi.v6_5.features.MachineApiExpectTest;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.features.PackageApiExpectTest;
|
import org.jclouds.joyent.cloudapi.v6_5.features.PackageApiExpectTest;
|
||||||
import org.jclouds.location.reference.LocationConstants;
|
import org.jclouds.location.reference.LocationConstants;
|
||||||
|
import org.jclouds.ssh.SshKeyPairGenerator;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
|
|
@ -31,12 +31,12 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||||
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
|
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
|
||||||
import org.jclouds.crypto.SshKeyPairGenerator;
|
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.JoyentCloudApi;
|
import org.jclouds.joyent.cloudapi.v6_5.JoyentCloudApi;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.KeyAndPrivateKey;
|
import org.jclouds.joyent.cloudapi.v6_5.compute.internal.KeyAndPrivateKey;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.datacenterscoped.DatacenterAndName;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.datacenterscoped.DatacenterAndName;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.features.KeyApi;
|
import org.jclouds.joyent.cloudapi.v6_5.features.KeyApi;
|
||||||
|
import org.jclouds.ssh.SshKeyPairGenerator;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.features.KeyApi;
|
import org.jclouds.joyent.cloudapi.v6_5.features.KeyApi;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.internal.BaseJoyentCloudApiLiveTest;
|
import org.jclouds.joyent.cloudapi.v6_5.internal.BaseJoyentCloudApiLiveTest;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
|
||||||
import org.jclouds.joyent.cloudapi.v6_5.domain.Machine;
|
import org.jclouds.joyent.cloudapi.v6_5.domain.Machine;
|
||||||
|
@ -37,6 +36,7 @@ import org.jclouds.joyent.cloudapi.v6_5.reference.Metadata;
|
||||||
import org.jclouds.predicates.InetSocketAddressConnect;
|
import org.jclouds.predicates.InetSocketAddressConnect;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
import org.jclouds.util.InetAddresses2;
|
import org.jclouds.util.InetAddresses2;
|
||||||
import org.testng.annotations.AfterGroups;
|
import org.testng.annotations.AfterGroups;
|
||||||
|
|
|
@ -38,9 +38,9 @@ import java.net.URISyntaxException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.json.Json;
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.ssh.SshKeys;
|
||||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||||
import org.jclouds.vcloud.director.v1_5.domain.Checks;
|
import org.jclouds.vcloud.director.v1_5.domain.Checks;
|
||||||
import org.jclouds.vcloud.director.v1_5.domain.File;
|
import org.jclouds.vcloud.director.v1_5.domain.File;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.jclouds.aws.ec2.functions;
|
package org.jclouds.aws.ec2.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPublicKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPublicKey;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
|
@ -22,7 +22,7 @@ import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.jclouds.crypto.SshKeys.fingerprintPublicKey;
|
import static org.jclouds.ssh.SshKeys.fingerprintPublicKey;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||||
|
|
|
@ -21,30 +21,30 @@ package org.jclouds.scriptbuilder.statements.login;
|
||||||
import static com.google.common.base.Charsets.UTF_8;
|
import static com.google.common.base.Charsets.UTF_8;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static com.google.common.base.Predicates.isNull;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static org.jclouds.scriptbuilder.statements.login.ShadowStatements.resetLoginUserPasswordTo;
|
||||||
|
import static org.jclouds.scriptbuilder.statements.ssh.SshStatements.lockSshd;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.crypto.Sha512Crypt;
|
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||||
import org.jclouds.scriptbuilder.statements.ssh.SshStatements;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicates;
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.ImplementedBy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the administrative access to a node. By default, it will perform the following:
|
* Controls the administrative access to a node. By default, it will perform the following:
|
||||||
|
@ -74,19 +74,14 @@ import com.google.inject.ImplementedBy;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class AdminAccess implements Statement {
|
public class AdminAccess implements Statement {
|
||||||
public static AdminAccess.Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AdminAccess.Builder builder(Function<String, String> cryptFunction) {
|
|
||||||
return new Builder(cryptFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AdminAccess standard() {
|
public static AdminAccess standard() {
|
||||||
return new Builder().build();
|
return new Builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ImplementedBy(DefaultConfiguration.class)
|
|
||||||
public static interface Configuration {
|
public static interface Configuration {
|
||||||
Supplier<String> defaultAdminUsername();
|
Supplier<String> defaultAdminUsername();
|
||||||
|
|
||||||
|
@ -98,16 +93,7 @@ public class AdminAccess implements Statement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private final Function<String, String> cryptFunction;
|
private Function<String, String> cryptFunction;
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
this(Sha512Crypt.function());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(Function<String, String> cryptFunction) {
|
|
||||||
this.cryptFunction = cryptFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String adminUsername;
|
private String adminUsername;
|
||||||
private String adminFullName;
|
private String adminFullName;
|
||||||
private String adminHome;
|
private String adminHome;
|
||||||
|
@ -123,86 +109,91 @@ public class AdminAccess implements Statement {
|
||||||
private boolean installAdminPrivateKey = false;
|
private boolean installAdminPrivateKey = false;
|
||||||
private boolean resetLoginPassword = true;
|
private boolean resetLoginPassword = true;
|
||||||
|
|
||||||
public AdminAccess.Builder adminUsername(String adminUsername) {
|
public Builder cryptFunction(Function<String, String> cryptFunction) {
|
||||||
this.adminUsername = adminUsername;
|
this.cryptFunction = cryptFunction;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminFullName(String adminFullName) {
|
public Builder adminUsername(String adminUsername) {
|
||||||
|
this.adminUsername = checkNotRoot(adminUsername);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder adminFullName(String adminFullName) {
|
||||||
this.adminFullName = adminFullName;
|
this.adminFullName = adminFullName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AdminAccess.Builder adminHome(String adminHome) {
|
public Builder adminHome(String adminHome) {
|
||||||
this.adminHome = adminHome;
|
this.adminHome = adminHome;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminPassword(String adminPassword) {
|
public Builder adminPassword(String adminPassword) {
|
||||||
this.adminPassword = adminPassword;
|
this.adminPassword = adminPassword;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder loginPassword(String loginPassword) {
|
public Builder loginPassword(String loginPassword) {
|
||||||
this.loginPassword = loginPassword;
|
this.loginPassword = loginPassword;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder lockSsh(boolean lockSsh) {
|
public Builder lockSsh(boolean lockSsh) {
|
||||||
this.lockSsh = lockSsh;
|
this.lockSsh = lockSsh;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder resetLoginPassword(boolean resetLoginPassword) {
|
public Builder resetLoginPassword(boolean resetLoginPassword) {
|
||||||
this.resetLoginPassword = resetLoginPassword;
|
this.resetLoginPassword = resetLoginPassword;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder authorizeAdminPublicKey(boolean authorizeAdminPublicKey) {
|
public Builder authorizeAdminPublicKey(boolean authorizeAdminPublicKey) {
|
||||||
this.authorizeAdminPublicKey = authorizeAdminPublicKey;
|
this.authorizeAdminPublicKey = authorizeAdminPublicKey;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder installAdminPrivateKey(boolean installAdminPrivateKey) {
|
public Builder installAdminPrivateKey(boolean installAdminPrivateKey) {
|
||||||
this.installAdminPrivateKey = installAdminPrivateKey;
|
this.installAdminPrivateKey = installAdminPrivateKey;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder grantSudoToAdminUser(boolean grantSudoToAdminUser) {
|
public Builder grantSudoToAdminUser(boolean grantSudoToAdminUser) {
|
||||||
this.grantSudoToAdminUser = grantSudoToAdminUser;
|
this.grantSudoToAdminUser = grantSudoToAdminUser;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminPublicKey(File adminPublicKey) {
|
public Builder adminPublicKey(File adminPublicKey) {
|
||||||
this.adminPublicKeyFile = adminPublicKey;
|
this.adminPublicKeyFile = adminPublicKey;
|
||||||
this.adminPublicKey = null;
|
this.adminPublicKey = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminPublicKey(String adminPublicKey) {
|
public Builder adminPublicKey(String adminPublicKey) {
|
||||||
this.adminPublicKey = adminPublicKey;
|
this.adminPublicKey = adminPublicKey;
|
||||||
this.adminPublicKeyFile = null;
|
this.adminPublicKeyFile = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminPrivateKey(File adminPrivateKey) {
|
public Builder adminPrivateKey(File adminPrivateKey) {
|
||||||
this.adminPrivateKeyFile = adminPrivateKey;
|
this.adminPrivateKeyFile = adminPrivateKey;
|
||||||
this.adminPrivateKey = null;
|
this.adminPrivateKey = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder adminPrivateKey(String adminPrivateKey) {
|
public Builder adminPrivateKey(String adminPrivateKey) {
|
||||||
this.adminPrivateKey = adminPrivateKey;
|
this.adminPrivateKey = adminPrivateKey;
|
||||||
this.adminPrivateKeyFile = null;
|
this.adminPrivateKeyFile = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder from(AdminAccessBuilderSpec spec) {
|
public Builder from(AdminAccessBuilderSpec spec) {
|
||||||
return spec.copyTo(this);
|
return spec.copyTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess.Builder from(String spec) {
|
public Builder from(String spec) {
|
||||||
return from(AdminAccessBuilderSpec.parse(spec));
|
return from(AdminAccessBuilderSpec.parse(spec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +213,7 @@ public class AdminAccess implements Statement {
|
||||||
lockSsh, grantSudoToAdminUser, authorizeAdminPublicKey, installAdminPrivateKey, resetLoginPassword,
|
lockSsh, grantSudoToAdminUser, authorizeAdminPublicKey, installAdminPrivateKey, resetLoginPassword,
|
||||||
cryptFunction);
|
cryptFunction);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw Throwables.propagate(e);
|
throw propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +370,8 @@ public class AdminAccess implements Statement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminAccess init(Configuration configuration) {
|
public AdminAccess init(Configuration configuration) {
|
||||||
Builder builder = AdminAccess.builder(configuration.cryptFunction());
|
Builder builder = AdminAccess.builder();
|
||||||
|
builder.cryptFunction(config.getCryptFunction() != null ? config.getCryptFunction() : configuration.cryptFunction());
|
||||||
builder.adminUsername(config.getAdminUsername() != null ? config.getAdminUsername() : configuration
|
builder.adminUsername(config.getAdminUsername() != null ? config.getAdminUsername() : configuration
|
||||||
.defaultAdminUsername().get());
|
.defaultAdminUsername().get());
|
||||||
builder.adminFullName(config.getAdminFullName() != null ? config.getAdminFullName() : builder.adminUsername);
|
builder.adminFullName(config.getAdminFullName() != null ? config.getAdminFullName() : builder.adminUsername);
|
||||||
|
@ -407,14 +399,10 @@ public class AdminAccess implements Statement {
|
||||||
checkNotNull(family, "family");
|
checkNotNull(family, "family");
|
||||||
if (family == OsFamily.WINDOWS)
|
if (family == OsFamily.WINDOWS)
|
||||||
throw new UnsupportedOperationException("windows not yet implemented");
|
throw new UnsupportedOperationException("windows not yet implemented");
|
||||||
checkArgument(!"root".equals(config.getAdminUsername()), "cannot create admin user 'root'; " +
|
checkState(
|
||||||
"ensure jclouds is not running as root, or specify an explicit non-root username in AdminAccess");
|
!any(newArrayList(config.getAdminUsername(), config.getAdminPassword(), config.getAdminPublicKey(),
|
||||||
if (Iterables.any(
|
config.getAdminPrivateKey(), config.getLoginPassword()), isNull()), "please call init() first");
|
||||||
Lists.newArrayList(config.getAdminUsername(), config.getAdminPassword(), config.getAdminPublicKey(),
|
checkNotRoot(config.getAdminUsername());
|
||||||
config.getAdminPrivateKey(), config.getLoginPassword()), Predicates.isNull()))
|
|
||||||
init(new DefaultConfiguration());
|
|
||||||
|
|
||||||
checkNotNull(config.getAdminUsername(), "adminUsername");
|
|
||||||
checkNotNull(config.getAdminPassword(), "adminPassword");
|
checkNotNull(config.getAdminPassword(), "adminPassword");
|
||||||
checkNotNull(config.getAdminPublicKey(), "adminPublicKey");
|
checkNotNull(config.getAdminPublicKey(), "adminPublicKey");
|
||||||
checkNotNull(config.getAdminPrivateKey(), "adminPrivateKey");
|
checkNotNull(config.getAdminPrivateKey(), "adminPrivateKey");
|
||||||
|
@ -435,16 +423,21 @@ public class AdminAccess implements Statement {
|
||||||
statements.add(SudoStatements.createWheel());
|
statements.add(SudoStatements.createWheel());
|
||||||
userBuilder.group("wheel");
|
userBuilder.group("wheel");
|
||||||
}
|
}
|
||||||
statements.add(userBuilder.build().cryptFunction(config.getCryptFunction()));
|
statements.add(userBuilder.cryptFunction(config.getCryptFunction()).build());
|
||||||
if (config.shouldLockSsh())
|
if (config.shouldLockSsh())
|
||||||
statements.add(SshStatements.lockSshd());
|
statements.add(lockSshd());
|
||||||
if (config.shouldResetLoginPassword()) {
|
if (config.shouldResetLoginPassword()) {
|
||||||
statements.add(ShadowStatements.resetLoginUserPasswordTo(config.getLoginPassword()).cryptFunction(
|
statements.add(resetLoginUserPasswordTo(config.getCryptFunction(), config.getLoginPassword()));
|
||||||
config.getCryptFunction()));
|
|
||||||
}
|
}
|
||||||
return new StatementList(statements.build()).render(family);
|
return new StatementList(statements.build()).render(family);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String checkNotRoot(String user) {
|
||||||
|
checkArgument(!"root".equals(checkNotNull(user, "adminUsername")), "cannot create admin user 'root'; "
|
||||||
|
+ "ensure jclouds is not running as root, or specify an explicit non-root username in AdminAccess");
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder builder2 = new StringBuilder();
|
StringBuilder builder2 = new StringBuilder();
|
||||||
|
@ -453,6 +446,4 @@ public class AdminAccess implements Statement {
|
||||||
.append(shouldGrantSudoToAdminUser()).append("]");
|
.append(shouldGrantSudoToAdminUser()).append("]");
|
||||||
return builder2.toString();
|
return builder2.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.scriptbuilder.statements.login;
|
|
||||||
|
|
||||||
import static com.google.common.base.Charsets.UTF_8;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.crypto.Sha512Crypt;
|
|
||||||
import org.jclouds.crypto.SshKeys;
|
|
||||||
import org.jclouds.scriptbuilder.statements.login.AdminAccess.Configuration;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.common.base.Suppliers;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Singleton
|
|
||||||
public class DefaultConfiguration implements Configuration {
|
|
||||||
|
|
||||||
private final Supplier<String> defaultAdminUsername = Suppliers.ofInstance(System.getProperty("user.name"));
|
|
||||||
private final Supplier<Map<String, String>> defaultAdminSshKeys = new Supplier<Map<String, String>>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> get() {
|
|
||||||
try {
|
|
||||||
return ImmutableMap.of(
|
|
||||||
"public", Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa.pub"), UTF_8),
|
|
||||||
"private", Files.toString(new File(System.getProperty("user.home") + "/.ssh/id_rsa"), UTF_8));
|
|
||||||
} catch (IOException e) {
|
|
||||||
return SshKeys.generate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cheap, lightweight, low-security password generator.
|
|
||||||
*
|
|
||||||
* @see <a href=
|
|
||||||
* "http://www.java-forums.org/java-lang/7355-how-create-lightweight-low-security-password-generator.html" />
|
|
||||||
*/
|
|
||||||
public enum PasswordGenerator implements Supplier<String> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/** Minimum length for a decent password */
|
|
||||||
public static final int MIN_LENGTH = 10;
|
|
||||||
|
|
||||||
/** The random number generator. */
|
|
||||||
protected static final SecureRandom r = new SecureRandom();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set of characters that is valid. Must be printable, memorable, and "won't break HTML" (i.e., not ' <', '>',
|
|
||||||
* '&', '=', ...). or break shell commands (i.e., not ' <', '>', '$', '!', ...). I, L and O are good to leave out,
|
|
||||||
* as are numeric zero and one.
|
|
||||||
*/
|
|
||||||
public static final char[] goodChar = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q',
|
|
||||||
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N',
|
|
||||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-',
|
|
||||||
'@', };
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < MIN_LENGTH; i++) {
|
|
||||||
sb.append(goodChar[r.nextInt(goodChar.length)]);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Function<String, String> cryptFunction = Sha512Crypt.function();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<String> defaultAdminUsername() {
|
|
||||||
return defaultAdminUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<Map<String, String>> defaultAdminSshKeys() {
|
|
||||||
return defaultAdminSshKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Supplier<String> passwordGenerator() {
|
|
||||||
return PasswordGenerator.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<String, String> cryptFunction() {
|
|
||||||
return cryptFunction;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,17 +23,12 @@ import static com.google.common.base.Throwables.propagate;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||||
|
|
||||||
import javax.inject.Named;
|
|
||||||
|
|
||||||
import org.jclouds.crypto.Sha512Crypt;
|
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the password entry for a user in the shadow file, using SHA-512
|
* Replaces the password entry for a user in the shadow file, using SHA-512
|
||||||
|
@ -43,20 +38,12 @@ import com.google.inject.Inject;
|
||||||
*/
|
*/
|
||||||
public class ReplaceShadowPasswordEntry implements Statement {
|
public class ReplaceShadowPasswordEntry implements Statement {
|
||||||
|
|
||||||
|
private final Function<String, String> cryptFunction;
|
||||||
private final String login;
|
private final String login;
|
||||||
private final String password;
|
private final String password;
|
||||||
|
|
||||||
private Function<String, String> cryptFunction = Sha512Crypt.function();
|
public ReplaceShadowPasswordEntry(Function<String, String> cryptFunction, String login, String password) {
|
||||||
|
this.cryptFunction = checkNotNull(cryptFunction, "cryptFunction");
|
||||||
@Inject(optional = true)
|
|
||||||
@Named("CRYPT")
|
|
||||||
@VisibleForTesting
|
|
||||||
ReplaceShadowPasswordEntry cryptFunction(Function<String, String> cryptFunction) {
|
|
||||||
this.cryptFunction = cryptFunction;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReplaceShadowPasswordEntry(String login, String password) {
|
|
||||||
this.login = checkNotNull(login, "login");
|
this.login = checkNotNull(login, "login");
|
||||||
this.password = checkNotNull(password, "password");
|
this.password = checkNotNull(password, "password");
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -25,8 +27,8 @@ package org.jclouds.scriptbuilder.statements.login;
|
||||||
*/
|
*/
|
||||||
public class ReplaceShadowPasswordEntryOfLoginUser extends ReplaceShadowPasswordEntry {
|
public class ReplaceShadowPasswordEntryOfLoginUser extends ReplaceShadowPasswordEntry {
|
||||||
|
|
||||||
public ReplaceShadowPasswordEntryOfLoginUser(String password) {
|
public ReplaceShadowPasswordEntryOfLoginUser(Function<String, String> cryptFunction, String password) {
|
||||||
super("${SUDO_USER:=${USER}}", password);
|
super(cryptFunction, "${SUDO_USER:=${USER}}", password);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statements used to manipulate the shadow file
|
* Statements used to manipulate the shadow file
|
||||||
|
@ -27,10 +28,10 @@ package org.jclouds.scriptbuilder.statements.login;
|
||||||
public class ShadowStatements {
|
public class ShadowStatements {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* note must be run as root, and will either reset the root password, or
|
* note must be run as root, and will either reset the root password, or whoever sudoed to root.
|
||||||
* whoever sudoed to root.
|
|
||||||
*/
|
*/
|
||||||
public static ReplaceShadowPasswordEntryOfLoginUser resetLoginUserPasswordTo(String password) {
|
public static ReplaceShadowPasswordEntryOfLoginUser resetLoginUserPasswordTo(Function<String, String> cryptFunction,
|
||||||
return new ReplaceShadowPasswordEntryOfLoginUser(password);
|
String password) {
|
||||||
|
return new ReplaceShadowPasswordEntryOfLoginUser(cryptFunction, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import static com.google.common.base.Objects.equal;
|
||||||
import com.google.common.base.Function;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.common.base.Objects;
|
import java.util.List;
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import org.jclouds.crypto.Sha512Crypt;
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
@ -37,11 +31,14 @@ import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
import org.jclouds.scriptbuilder.statements.ssh.AuthorizeRSAPublicKeys;
|
import org.jclouds.scriptbuilder.statements.ssh.AuthorizeRSAPublicKeys;
|
||||||
import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
|
import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import com.google.common.base.Function;
|
||||||
import java.util.List;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import static com.google.common.base.Objects.equal;
|
import com.google.common.base.Strings;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a statement that will add a given user to a machine ("login"), with optional
|
* Creates a statement that will add a given user to a machine ("login"), with optional
|
||||||
|
@ -60,6 +57,7 @@ public class UserAdd implements Statement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
private Function<String, String> cryptFunction;
|
||||||
private String defaultHome = "/home/users";
|
private String defaultHome = "/home/users";
|
||||||
private String home;
|
private String home;
|
||||||
private String login;
|
private String login;
|
||||||
|
@ -70,6 +68,14 @@ public class UserAdd implements Statement {
|
||||||
private String shell = "/bin/bash";
|
private String shell = "/bin/bash";
|
||||||
private String fullName;
|
private String fullName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.compute.functions.Sha512Crypt
|
||||||
|
*/
|
||||||
|
public Builder cryptFunction(Function<String, String> cryptFunction) {
|
||||||
|
this.cryptFunction = cryptFunction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See --home in `man useradd`.
|
* See --home in `man useradd`.
|
||||||
*/
|
*/
|
||||||
|
@ -132,20 +138,26 @@ public class UserAdd implements Statement {
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAdd build() {
|
public UserAdd build() {
|
||||||
return new UserAdd(login, groups, password, RSAPrivateKey, authorizeRSAPublicKeys, home, defaultHome, shell, fullName);
|
return new UserAdd(cryptFunction, login, groups, password, RSAPrivateKey, authorizeRSAPublicKeys, home,
|
||||||
|
defaultHome, shell, fullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAdd(String login, List<String> groups, @Nullable String password, @Nullable String installRSAPrivateKey,
|
public UserAdd(Function<String, String> cryptFunction, String login, List<String> groups, @Nullable String password,
|
||||||
List<String> authorizeRSAPublicKeys, String defaultHome, String shell) {
|
@Nullable String installRSAPrivateKey, List<String> authorizeRSAPublicKeys, String defaultHome, String shell) {
|
||||||
this(login, groups, password, installRSAPrivateKey, authorizeRSAPublicKeys, null, defaultHome, shell, login);
|
this(cryptFunction, login, groups, password, installRSAPrivateKey, authorizeRSAPublicKeys, null, defaultHome,
|
||||||
|
shell, login);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAdd(String login, List<String> groups, @Nullable String password, @Nullable String installRSAPrivateKey,
|
public UserAdd(Function<String, String> cryptFunction, String login, List<String> groups, @Nullable String password,
|
||||||
List<String> authorizeRSAPublicKeys, @Nullable String home, String defaultHome, String shell, String fullName) {
|
@Nullable String installRSAPrivateKey, List<String> authorizeRSAPublicKeys, @Nullable String home,
|
||||||
|
String defaultHome, String shell, String fullName) {
|
||||||
this.login = checkNotNull(login, "login");
|
this.login = checkNotNull(login, "login");
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.cryptFunction = password == null ? null : checkNotNull(cryptFunction,
|
||||||
|
"cryptFunction must be set! ex. org.jclouds.compute.functions.Sha512Crypt.INSTANCE");
|
||||||
this.groups = ImmutableList.copyOf(checkNotNull(groups, "groups"));
|
this.groups = ImmutableList.copyOf(checkNotNull(groups, "groups"));
|
||||||
this.installRSAPrivateKey = installRSAPrivateKey;
|
this.installRSAPrivateKey = installRSAPrivateKey;
|
||||||
this.authorizeRSAPublicKeys = ImmutableList
|
this.authorizeRSAPublicKeys = ImmutableList
|
||||||
|
@ -156,6 +168,7 @@ public class UserAdd implements Statement {
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Function<String, String> cryptFunction;
|
||||||
private final String home;
|
private final String home;
|
||||||
private final String defaultHome;
|
private final String defaultHome;
|
||||||
private final String login;
|
private final String login;
|
||||||
|
@ -166,16 +179,6 @@ public class UserAdd implements Statement {
|
||||||
private final String shell;
|
private final String shell;
|
||||||
private final String fullName;
|
private final String fullName;
|
||||||
|
|
||||||
private Function<String, String> cryptFunction = Sha512Crypt.function();
|
|
||||||
|
|
||||||
@Inject(optional = true)
|
|
||||||
@Named("CRYPT")
|
|
||||||
@VisibleForTesting
|
|
||||||
UserAdd cryptFunction(Function<String, String> cryptFunction) {
|
|
||||||
this.cryptFunction = cryptFunction;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<String> functionDependencies(OsFamily family) {
|
public Iterable<String> functionDependencies(OsFamily family) {
|
||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -50,8 +49,7 @@ public class AdminAccessTest {
|
||||||
try {
|
try {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
|
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
|
||||||
.adminPublicKey("fooPublicKey").adminUsername("foo")
|
.adminPublicKey("fooPublicKey").adminUsername("foo").adminHome("/over/ridden/foo").build()
|
||||||
.adminHome("/over/ridden/foo").build()
|
|
||||||
.init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
|
.init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
|
||||||
Resources.toString(Resources.getResource("test_adminaccess_params.sh"), Charsets.UTF_8));
|
Resources.toString(Resources.getResource("test_adminaccess_params.sh"), Charsets.UTF_8));
|
||||||
|
|
||||||
|
@ -66,8 +64,7 @@ public class AdminAccessTest {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
|
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
|
||||||
.adminPublicKey("fooPublicKey").adminUsername("foo").adminFullName("JClouds Foo")
|
.adminPublicKey("fooPublicKey").adminUsername("foo").adminFullName("JClouds Foo")
|
||||||
.adminHome("/over/ridden/foo").build()
|
.adminHome("/over/ridden/foo").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
|
||||||
.init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
|
|
||||||
Resources.toString(Resources.getResource("test_adminaccess_params_and_fullname.sh"), Charsets.UTF_8));
|
Resources.toString(Resources.getResource("test_adminaccess_params_and_fullname.sh"), Charsets.UTF_8));
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -75,7 +72,6 @@ public class AdminAccessTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testOnlyInstallUserUNIX() throws IOException {
|
public void testOnlyInstallUserUNIX() throws IOException {
|
||||||
TestConfiguration.INSTANCE.reset();
|
TestConfiguration.INSTANCE.reset();
|
||||||
try {
|
try {
|
||||||
|
@ -89,14 +85,13 @@ public class AdminAccessTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
@Test(expectedExceptions = UnsupportedOperationException.class, expectedExceptionsMessageRegExp = "windows not yet implemented")
|
||||||
public void testCreateWheelWindowsNotSupported() {
|
public void testCreateWheelWindowsNotSupported() {
|
||||||
AdminAccess.standard().init(TestConfiguration.INSTANCE).render(OsFamily.WINDOWS);
|
AdminAccess.standard().init(TestConfiguration.INSTANCE).render(OsFamily.WINDOWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "cannot create admin user 'root'; ensure jclouds is not running as root, or specify an explicit non-root username in AdminAccess")
|
||||||
// for issue 682
|
public void testRootNotAllowed() {
|
||||||
public void testRootNotAllowed() throws IOException {
|
|
||||||
TestConfiguration.INSTANCE.reset();
|
TestConfiguration.INSTANCE.reset();
|
||||||
try {
|
try {
|
||||||
AdminAccess.builder().adminUsername("root").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX);
|
AdminAccess.builder().adminUsername("root").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX);
|
||||||
|
@ -105,12 +100,13 @@ public class AdminAccessTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = NullPointerException.class)
|
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "family")
|
||||||
public void testFamilyRequiredAllowed() throws IOException {
|
public void testFamilyRequiredAllowed() {
|
||||||
AdminAccess.standard().render(null);
|
AdminAccess.standard().render(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWhenUninitializedLazyInitWithDefaultConfiguration() throws IOException {
|
@Test(expectedExceptions = IllegalStateException.class, expectedExceptionsMessageRegExp = "please call init\\(\\) first")
|
||||||
|
public void testIllegalStateExceptionUnlessCalledInit() {
|
||||||
AdminAccess access = AdminAccess.standard();
|
AdminAccess access = AdminAccess.standard();
|
||||||
// before rendered, holder is empty
|
// before rendered, holder is empty
|
||||||
assertEquals(access.config.getAdminUsername(), null);
|
assertEquals(access.config.getAdminUsername(), null);
|
||||||
|
@ -119,20 +115,6 @@ public class AdminAccessTest {
|
||||||
assertEquals(access.config.getAdminPrivateKey(), null);
|
assertEquals(access.config.getAdminPrivateKey(), null);
|
||||||
assertEquals(access.config.getLoginPassword(), null);
|
assertEquals(access.config.getLoginPassword(), null);
|
||||||
access.render(OsFamily.UNIX);
|
access.render(OsFamily.UNIX);
|
||||||
// DefaultConfiguration
|
|
||||||
try {
|
|
||||||
assertEquals(access.config.getAdminUsername(), System.getProperty("user.name"));
|
|
||||||
assertNotNull(access.config.getAdminPassword());
|
|
||||||
assertNotNull(access.config.getAdminPublicKey());
|
|
||||||
assertNotNull(access.config.getAdminPrivateKey());
|
|
||||||
assertNotNull(access.config.getLoginPassword());
|
|
||||||
} catch (AssertionError e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// we are catching throwables here, in case the test runner doesn't
|
|
||||||
// have ssh keys setup
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,24 +18,34 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit")
|
||||||
public class ReplaceShadowPasswordEntryOfLoginUserTest {
|
public class ReplaceShadowPasswordEntryOfLoginUserTest {
|
||||||
|
Function<String, String> crypt = new Function<String, String>() {
|
||||||
|
public String apply(String in) {
|
||||||
|
assertEquals(in, "password");
|
||||||
|
return "CRYPT";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void testWithPasswordUNIX() {
|
public void testWithPasswordUNIX() {
|
||||||
String cmd = new ReplaceShadowPasswordEntryOfLoginUser("bar").render(OsFamily.UNIX);
|
String cmd = new ReplaceShadowPasswordEntryOfLoginUser(crypt, "password").render(OsFamily.UNIX);
|
||||||
assert cmd.startsWith("awk -v user=^${SUDO_USER:=${USER}}: -v password='$6$") : cmd;
|
assert cmd.startsWith("awk -v user=^${SUDO_USER:=${USER}}: -v password='CRYPT") : cmd;
|
||||||
assert cmd
|
assert cmd
|
||||||
.endsWith("' 'BEGIN { FS=OFS=\":\" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.${SUDO_USER:=${USER}}\ntest -f /etc/shadow.${SUDO_USER:=${USER}} && mv /etc/shadow.${SUDO_USER:=${USER}} /etc/shadow\n") : cmd;
|
.endsWith("' 'BEGIN { FS=OFS=\":\" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.${SUDO_USER:=${USER}}\ntest -f /etc/shadow.${SUDO_USER:=${USER}} && mv /etc/shadow.${SUDO_USER:=${USER}} /etc/shadow\n") : cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||||
public void testAddUserWindowsNotSupported() {
|
public void testAddUserWindowsNotSupported() {
|
||||||
new ReplaceShadowPasswordEntryOfLoginUser("password").render(OsFamily.WINDOWS);
|
new ReplaceShadowPasswordEntryOfLoginUser(crypt, "password").render(OsFamily.WINDOWS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,24 +18,34 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.scriptbuilder.statements.login;
|
package org.jclouds.scriptbuilder.statements.login;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit")
|
||||||
public class ReplaceShadowPasswordEntryTest {
|
public class ReplaceShadowPasswordEntryTest {
|
||||||
|
Function<String, String> crypt = new Function<String, String>() {
|
||||||
|
public String apply(String in) {
|
||||||
|
assertEquals(in, "password");
|
||||||
|
return "CRYPT";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void testWithPasswordUNIX() {
|
public void testWithPasswordUNIX() {
|
||||||
String userAdd = new ReplaceShadowPasswordEntry("foo", "bar").render(OsFamily.UNIX);
|
String userAdd = new ReplaceShadowPasswordEntry(crypt, "foo", "password").render(OsFamily.UNIX);
|
||||||
assert userAdd.startsWith("awk -v user=^foo: -v password='$6$") : userAdd;
|
assert userAdd.startsWith("awk -v user=^foo: -v password='CRYPT") : userAdd;
|
||||||
assert userAdd
|
assert userAdd
|
||||||
.endsWith("' 'BEGIN { FS=OFS=\":\" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.foo\ntest -f /etc/shadow.foo && mv /etc/shadow.foo /etc/shadow\n") : userAdd;
|
.endsWith("' 'BEGIN { FS=OFS=\":\" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.foo\ntest -f /etc/shadow.foo && mv /etc/shadow.foo /etc/shadow\n") : userAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||||
public void testAddUserWindowsNotSupported() {
|
public void testAddUserWindowsNotSupported() {
|
||||||
new ReplaceShadowPasswordEntry("user", "password").render(OsFamily.WINDOWS);
|
new ReplaceShadowPasswordEntry(crypt, "user", "password").render(OsFamily.WINDOWS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,9 +59,16 @@ public class UserAddTest {
|
||||||
"mkdir -p /home/users\ngroupadd -f wheel\ngroupadd -f candy\nuseradd -c me -s /bin/bash -g wheel -G candy -m -d /home/users/me me\nchown -R me /home/users/me\n");
|
"mkdir -p /home/users\ngroupadd -f wheel\ngroupadd -f candy\nuseradd -c me -s /bin/bash -g wheel -G candy -m -d /home/users/me me\nchown -R me /home/users/me\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Function<String, String> crypt = new Function<String, String>() {
|
||||||
|
public String apply(String in) {
|
||||||
|
assertEquals(in, "password");
|
||||||
|
return "CRYPT";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void testWithPasswordUNIX() {
|
public void testWithPasswordUNIX() {
|
||||||
String userAdd = UserAdd.builder().login("me").password("foo").group("wheel").build().render(OsFamily.UNIX);
|
String userAdd = UserAdd.builder().cryptFunction(crypt).login("me").password("password").group("wheel").build().render(OsFamily.UNIX);
|
||||||
assert userAdd.startsWith("mkdir -p /home/users\ngroupadd -f wheel\nuseradd -c me -s /bin/bash -g wheel -m -d /home/users/me -p '$6$") : userAdd;
|
assert userAdd.startsWith("mkdir -p /home/users\ngroupadd -f wheel\nuseradd -c me -s /bin/bash -g wheel -m -d /home/users/me -p 'CRYPT'") : userAdd;
|
||||||
assert userAdd.endsWith("' me\nchown -R me /home/users/me\n") : userAdd;
|
assert userAdd.endsWith("' me\nchown -R me /home/users/me\n") : userAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue