unwound dependencies relating to ssh keys and crypt

This commit is contained in:
Adrian Cole 2013-01-13 11:48:13 -08:00
parent 6a8ac673aa
commit 3ac6f475e7
44 changed files with 360 additions and 330 deletions

View File

@ -29,13 +29,13 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
import org.jclouds.cloudstack.options.ListSSHKeyPairsOptions;
import org.jclouds.crypto.SshKeys;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import com.google.common.reflect.Invokable;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.ssh.SshKeys;
import org.testng.annotations.Test;
import com.google.common.base.Functions;

View File

@ -27,9 +27,9 @@ import java.net.URI;
import org.jclouds.cloudstack.CloudStackContext;
import org.jclouds.cloudstack.domain.SshKeyPair;
import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
import org.jclouds.crypto.SshKeys;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.ssh.SshKeys;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;

View File

@ -27,7 +27,7 @@ import java.util.Set;
import org.jclouds.cloudstack.domain.SshKeyPair;
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.BeforeMethod;
import org.testng.annotations.Test;

View File

@ -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.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

View File

@ -20,8 +20,8 @@ package org.jclouds.ec2.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.crypto.SshKeys;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.ssh.SshKeys;
/**
*

View File

@ -22,9 +22,9 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import org.jclouds.crypto.SshKeys;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.ssh.SshKeys;
import org.testng.annotations.Test;
/**

View File

@ -30,9 +30,9 @@ import java.util.SortedSet;
import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.crypto.SshKeys;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.openstack.nova.ec2.NovaEC2ApiMetadata;
import org.jclouds.ssh.SshKeys;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

View File

@ -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.checkNotNull;
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
import java.util.List;
import java.util.Map;

View File

@ -26,9 +26,9 @@ import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.crypto.SshKeys;
import org.jclouds.domain.Credentials;
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.functions.CreateUniqueKeyPair;
import org.jclouds.trmk.vcloud_0_8.compute.options.TerremarkVCloudTemplateOptions;

View File

@ -24,8 +24,8 @@ import java.io.InputStream;
import java.net.URI;
import java.net.UnknownHostException;
import org.jclouds.crypto.SshKeys;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.ssh.SshKeys;
import org.jclouds.trmk.vcloud_0_8.domain.KeyPair;
import org.testng.annotations.Test;

View File

@ -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;
}
}
}

View File

@ -61,6 +61,7 @@ import org.jclouds.location.Provider;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
@ -85,6 +86,7 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
@Override
protected void configure() {
bind(AdminAccess.Configuration.class).to(AdminAccessConfiguration.class);
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
}).to(CreateSshClientOncePortIsListeningOnNode.class);

View File

@ -62,7 +62,7 @@
*/
package org.jclouds.crypto;
package org.jclouds.compute.functions;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

View File

@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.crypto;
package org.jclouds.ssh;
import java.util.Map;
import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* 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.Preconditions.checkArgument;
@ -48,6 +48,8 @@ import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Map;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.io.InputSuppliers;
import com.google.common.annotations.Beta;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.ssh;
package org.jclouds.ssh.config;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.crypto;
package org.jclouds.ssh.internal;
import static com.google.common.base.Preconditions.checkNotNull;
@ -25,10 +25,14 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.crypto.Crypto;
import org.jclouds.ssh.SshKeyPairGenerator;
import org.jclouds.ssh.SshKeys;
import com.google.inject.Inject;
@Singleton
class RsaSshKeyPairGenerator implements SshKeyPairGenerator {
public class RsaSshKeyPairGenerator implements SshKeyPairGenerator {
private final Crypto crypto;
private final SecureRandom secureRandom;

View File

@ -32,6 +32,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.easymock.IArgumentMatcher;
import org.jclouds.compute.config.AdminAccessConfiguration;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
@ -42,8 +43,6 @@ import org.jclouds.io.Payload;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
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.util.Strings2;
import org.testng.annotations.Test;
@ -104,31 +103,23 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
@Override
protected Module getSshModule() {
return new AbstractModule() {
@Override
protected void configure() {
bind(AdminAccess.Configuration.class).toInstance(new Configuration() {
@Override
bind(AdminAccessConfiguration.class).toInstance(new AdminAccessConfiguration() {
public Supplier<String> defaultAdminUsername() {
return Suppliers.ofInstance("defaultAdminUsername");
}
@Override
public Supplier<Map<String, String>> defaultAdminSshKeys() {
return Suppliers.<Map<String, String>> ofInstance(ImmutableMap.of("public", "publicKey", "private",
Pems.PRIVATE_PKCS1_MARKER));
}
@Override
public Function<String, String> cryptFunction() {
return new Function<String, String>() {
@Override
public String apply(String input) {
return String.format("crypt(%s)", input);
}
};
}

View File

@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.crypto;
package org.jclouds.compute.functions;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.functions.Sha512Crypt;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

View File

@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.crypto;
package org.jclouds.ssh;
import static org.jclouds.crypto.SshKeys.fingerprint;
import static org.jclouds.crypto.SshKeys.generate;
import static org.jclouds.crypto.SshKeys.privateKeyHasFingerprint;
import static org.jclouds.crypto.SshKeys.privateKeyHasSha1;
import static org.jclouds.crypto.SshKeys.privateKeyMatchesPublicKey;
import static org.jclouds.crypto.SshKeys.publicKeySpecFromOpenSSH;
import static org.jclouds.ssh.SshKeys.fingerprint;
import static org.jclouds.ssh.SshKeys.generate;
import static org.jclouds.ssh.SshKeys.privateKeyHasFingerprint;
import static org.jclouds.ssh.SshKeys.privateKeyHasSha1;
import static org.jclouds.ssh.SshKeys.privateKeyMatchesPublicKey;
import static org.jclouds.ssh.SshKeys.publicKeySpecFromOpenSSH;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -35,7 +35,9 @@ import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Map;
import org.jclouds.crypto.Pems;
import org.jclouds.io.Payloads;
import org.jclouds.ssh.SshKeys;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.crypto;
package org.jclouds.ssh.config;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@ -37,7 +37,11 @@ import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
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.Test;

View File

@ -19,6 +19,9 @@
package org.jclouds.rest.internal;
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.concurrent.ExecutionException;
@ -39,6 +42,8 @@ import com.google.common.base.Optional;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
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;
public class BlockOnFuture implements Function<ListenableFuture<?>, Result> {
@ -77,20 +82,40 @@ public class BlockOnFuture implements Function<ListenableFuture<?>, Result> {
try {
if (timeoutNanos.isPresent()) {
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 {
logger.debug(">> blocking on %s", future);
return Result.success(future.get());
return Result.success(getUninterruptibly(future));
}
} catch (ExecutionException e) {
return Result.fail(e.getCause());
} catch (InterruptedException e) {
return Result.fail(e); // TODO: should we kill the future?
throw propagateCause(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)
private Optional<Long> timeoutInNanos(Invokable<?, ?> invoked, Map<String, Long> timeouts) {
String className = enclosingType.getRawType().getSimpleName();

View File

@ -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.hash.Hashing.md5;
import static com.google.common.io.BaseEncoding.base16;
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;

View File

@ -24,8 +24,8 @@ import org.jclouds.Constants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.ssh.ConfiguresSshClient;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.config.ConfiguresSshClient;
import org.jclouds.ssh.jsch.JschSshClient;
import com.google.common.net.HostAndPort;

View File

@ -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.hash.Hashing.md5;
import static com.google.common.io.BaseEncoding.base16;
import static org.jclouds.crypto.SshKeys.fingerprintPrivateKey;
import static org.jclouds.crypto.SshKeys.sha1PrivateKey;
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
import java.io.Closeable;
import java.io.FilterInputStream;

View File

@ -24,8 +24,8 @@ import org.jclouds.Constants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.ssh.ConfiguresSshClient;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.config.ConfiguresSshClient;
import org.jclouds.sshj.SshjSshClient;
import com.google.common.net.HostAndPort;

View File

@ -28,12 +28,12 @@ import javax.inject.Singleton;
import org.jclouds.compute.functions.GroupNamingConvention;
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.compute.internal.KeyAndPrivateKey;
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
import org.jclouds.joyent.cloudapi.v6_5.domain.datacenterscoped.DatacenterAndName;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshKeyPairGenerator;
import com.google.common.cache.CacheLoader;
import com.google.inject.Inject;

View File

@ -28,7 +28,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.crypto.SshKeyPairGenerator;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
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.PackageApiExpectTest;
import org.jclouds.location.reference.LocationConstants;
import org.jclouds.ssh.SshKeyPairGenerator;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;

View File

@ -31,12 +31,12 @@ import java.util.Map;
import org.jclouds.compute.functions.GroupNamingConvention;
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.compute.internal.KeyAndPrivateKey;
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.features.KeyApi;
import org.jclouds.ssh.SshKeyPairGenerator;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

View File

@ -22,10 +22,10 @@ import static org.testng.Assert.assertEquals;
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.features.KeyApi;
import org.jclouds.joyent.cloudapi.v6_5.internal.BaseJoyentCloudApiLiveTest;
import org.jclouds.ssh.SshKeys;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

View File

@ -27,7 +27,6 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.crypto.SshKeys;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.joyent.cloudapi.v6_5.domain.Key;
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.RetryablePredicate;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshKeys;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.util.InetAddresses2;
import org.testng.annotations.AfterGroups;

View File

@ -38,9 +38,9 @@ import java.net.URISyntaxException;
import java.util.Map;
import java.util.Set;
import org.jclouds.crypto.SshKeys;
import org.jclouds.io.Payloads;
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.domain.Checks;
import org.jclouds.vcloud.director.v1_5.domain.File;

View File

@ -19,7 +19,7 @@
package org.jclouds.aws.ec2.functions;
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.inject.Inject;

View File

@ -22,7 +22,7 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
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 org.jclouds.aws.ec2.AWSEC2Client;

View File

@ -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.Preconditions.checkArgument;
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.IOException;
import java.util.Map;
import org.jclouds.crypto.Sha512Crypt;
import org.jclouds.domain.Credentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.statements.ssh.SshStatements;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
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.inject.ImplementedBy;
/**
* 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
*/
public class AdminAccess implements Statement {
public static AdminAccess.Builder builder() {
public static Builder builder() {
return new Builder();
}
public static AdminAccess.Builder builder(Function<String, String> cryptFunction) {
return new Builder(cryptFunction);
}
public static AdminAccess standard() {
return new Builder().build();
}
@ImplementedBy(DefaultConfiguration.class)
public static interface Configuration {
Supplier<String> defaultAdminUsername();
@ -98,16 +93,7 @@ public class AdminAccess implements Statement {
}
public static class Builder {
private final Function<String, String> cryptFunction;
public Builder() {
this(Sha512Crypt.function());
}
public Builder(Function<String, String> cryptFunction) {
this.cryptFunction = cryptFunction;
}
private Function<String, String> cryptFunction;
private String adminUsername;
private String adminFullName;
private String adminHome;
@ -123,86 +109,91 @@ public class AdminAccess implements Statement {
private boolean installAdminPrivateKey = false;
private boolean resetLoginPassword = true;
public AdminAccess.Builder adminUsername(String adminUsername) {
this.adminUsername = adminUsername;
public Builder cryptFunction(Function<String, String> cryptFunction) {
this.cryptFunction = cryptFunction;
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;
return this;
}
public AdminAccess.Builder adminHome(String adminHome) {
public Builder adminHome(String adminHome) {
this.adminHome = adminHome;
return this;
}
public AdminAccess.Builder adminPassword(String adminPassword) {
public Builder adminPassword(String adminPassword) {
this.adminPassword = adminPassword;
return this;
}
public AdminAccess.Builder loginPassword(String loginPassword) {
public Builder loginPassword(String loginPassword) {
this.loginPassword = loginPassword;
return this;
}
public AdminAccess.Builder lockSsh(boolean lockSsh) {
public Builder lockSsh(boolean lockSsh) {
this.lockSsh = lockSsh;
return this;
}
public AdminAccess.Builder resetLoginPassword(boolean resetLoginPassword) {
public Builder resetLoginPassword(boolean resetLoginPassword) {
this.resetLoginPassword = resetLoginPassword;
return this;
}
public AdminAccess.Builder authorizeAdminPublicKey(boolean authorizeAdminPublicKey) {
public Builder authorizeAdminPublicKey(boolean authorizeAdminPublicKey) {
this.authorizeAdminPublicKey = authorizeAdminPublicKey;
return this;
}
public AdminAccess.Builder installAdminPrivateKey(boolean installAdminPrivateKey) {
public Builder installAdminPrivateKey(boolean installAdminPrivateKey) {
this.installAdminPrivateKey = installAdminPrivateKey;
return this;
}
public AdminAccess.Builder grantSudoToAdminUser(boolean grantSudoToAdminUser) {
public Builder grantSudoToAdminUser(boolean grantSudoToAdminUser) {
this.grantSudoToAdminUser = grantSudoToAdminUser;
return this;
}
public AdminAccess.Builder adminPublicKey(File adminPublicKey) {
public Builder adminPublicKey(File adminPublicKey) {
this.adminPublicKeyFile = adminPublicKey;
this.adminPublicKey = null;
return this;
}
public AdminAccess.Builder adminPublicKey(String adminPublicKey) {
public Builder adminPublicKey(String adminPublicKey) {
this.adminPublicKey = adminPublicKey;
this.adminPublicKeyFile = null;
return this;
}
public AdminAccess.Builder adminPrivateKey(File adminPrivateKey) {
public Builder adminPrivateKey(File adminPrivateKey) {
this.adminPrivateKeyFile = adminPrivateKey;
this.adminPrivateKey = null;
return this;
}
public AdminAccess.Builder adminPrivateKey(String adminPrivateKey) {
public Builder adminPrivateKey(String adminPrivateKey) {
this.adminPrivateKey = adminPrivateKey;
this.adminPrivateKeyFile = null;
return this;
}
public AdminAccess.Builder from(AdminAccessBuilderSpec spec) {
public Builder from(AdminAccessBuilderSpec spec) {
return spec.copyTo(this);
}
public AdminAccess.Builder from(String spec) {
public Builder from(String spec) {
return from(AdminAccessBuilderSpec.parse(spec));
}
@ -222,7 +213,7 @@ public class AdminAccess implements Statement {
lockSsh, grantSudoToAdminUser, authorizeAdminPublicKey, installAdminPrivateKey, resetLoginPassword,
cryptFunction);
} catch (IOException e) {
throw Throwables.propagate(e);
throw propagate(e);
}
}
}
@ -379,7 +370,8 @@ public class AdminAccess implements Statement {
}
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
.defaultAdminUsername().get());
builder.adminFullName(config.getAdminFullName() != null ? config.getAdminFullName() : builder.adminUsername);
@ -407,14 +399,10 @@ public class AdminAccess implements Statement {
checkNotNull(family, "family");
if (family == OsFamily.WINDOWS)
throw new UnsupportedOperationException("windows not yet implemented");
checkArgument(!"root".equals(config.getAdminUsername()), "cannot create admin user 'root'; " +
"ensure jclouds is not running as root, or specify an explicit non-root username in AdminAccess");
if (Iterables.any(
Lists.newArrayList(config.getAdminUsername(), config.getAdminPassword(), config.getAdminPublicKey(),
config.getAdminPrivateKey(), config.getLoginPassword()), Predicates.isNull()))
init(new DefaultConfiguration());
checkNotNull(config.getAdminUsername(), "adminUsername");
checkState(
!any(newArrayList(config.getAdminUsername(), config.getAdminPassword(), config.getAdminPublicKey(),
config.getAdminPrivateKey(), config.getLoginPassword()), isNull()), "please call init() first");
checkNotRoot(config.getAdminUsername());
checkNotNull(config.getAdminPassword(), "adminPassword");
checkNotNull(config.getAdminPublicKey(), "adminPublicKey");
checkNotNull(config.getAdminPrivateKey(), "adminPrivateKey");
@ -435,16 +423,21 @@ public class AdminAccess implements Statement {
statements.add(SudoStatements.createWheel());
userBuilder.group("wheel");
}
statements.add(userBuilder.build().cryptFunction(config.getCryptFunction()));
statements.add(userBuilder.cryptFunction(config.getCryptFunction()).build());
if (config.shouldLockSsh())
statements.add(SshStatements.lockSshd());
statements.add(lockSshd());
if (config.shouldResetLoginPassword()) {
statements.add(ShadowStatements.resetLoginUserPasswordTo(config.getLoginPassword()).cryptFunction(
config.getCryptFunction()));
statements.add(resetLoginUserPasswordTo(config.getCryptFunction(), config.getLoginPassword()));
}
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
public String toString() {
StringBuilder builder2 = new StringBuilder();
@ -453,6 +446,4 @@ public class AdminAccess implements Statement {
.append(shouldGrantSudoToAdminUser()).append("]");
return builder2.toString();
}
}

View File

@ -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;
}
}

View File

@ -23,17 +23,12 @@ import static com.google.common.base.Throwables.propagate;
import static java.lang.String.format;
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.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
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
@ -43,20 +38,12 @@ import com.google.inject.Inject;
*/
public class ReplaceShadowPasswordEntry implements Statement {
private final Function<String, String> cryptFunction;
private final String login;
private final String password;
private Function<String, String> cryptFunction = Sha512Crypt.function();
@Inject(optional = true)
@Named("CRYPT")
@VisibleForTesting
ReplaceShadowPasswordEntry cryptFunction(Function<String, String> cryptFunction) {
this.cryptFunction = cryptFunction;
return this;
}
public ReplaceShadowPasswordEntry(String login, String password) {
public ReplaceShadowPasswordEntry(Function<String, String> cryptFunction, String login, String password) {
this.cryptFunction = checkNotNull(cryptFunction, "cryptFunction");
this.login = checkNotNull(login, "login");
this.password = checkNotNull(password, "password");
}

View File

@ -18,6 +18,8 @@
*/
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 ReplaceShadowPasswordEntryOfLoginUser(String password) {
super("${SUDO_USER:=${USER}}", password);
public ReplaceShadowPasswordEntryOfLoginUser(Function<String, String> cryptFunction, String password) {
super(cryptFunction, "${SUDO_USER:=${USER}}", password);
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.scriptbuilder.statements.login;
import com.google.common.base.Function;
/**
* Statements used to manipulate the shadow file
@ -27,10 +28,10 @@ package org.jclouds.scriptbuilder.statements.login;
public class ShadowStatements {
/**
* note must be run as root, and will either reset the root password, or
* whoever sudoed to root.
* note must be run as root, and will either reset the root password, or whoever sudoed to root.
*/
public static ReplaceShadowPasswordEntryOfLoginUser resetLoginUserPasswordTo(String password) {
return new ReplaceShadowPasswordEntryOfLoginUser(password);
public static ReplaceShadowPasswordEntryOfLoginUser resetLoginUserPasswordTo(Function<String, String> cryptFunction,
String password) {
return new ReplaceShadowPasswordEntryOfLoginUser(cryptFunction, password);
}
}

View File

@ -18,17 +18,11 @@
*/
package org.jclouds.scriptbuilder.statements.login;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
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 static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.OsFamily;
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.InstallRSAPrivateKey;
import javax.inject.Named;
import java.util.List;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
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;
/**
* 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 {
private Function<String, String> cryptFunction;
private String defaultHome = "/home/users";
private String home;
private String login;
@ -70,6 +68,14 @@ public class UserAdd implements Statement {
private String shell = "/bin/bash";
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`.
*/
@ -132,20 +138,26 @@ public class UserAdd implements Statement {
this.fullName = fullName;
return this;
}
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,
List<String> authorizeRSAPublicKeys, String defaultHome, String shell) {
this(login, groups, password, installRSAPrivateKey, authorizeRSAPublicKeys, null, defaultHome, shell, login);
public UserAdd(Function<String, String> cryptFunction, String login, List<String> groups, @Nullable String password,
@Nullable String installRSAPrivateKey, List<String> authorizeRSAPublicKeys, String defaultHome, String shell) {
this(cryptFunction, login, groups, password, installRSAPrivateKey, authorizeRSAPublicKeys, null, defaultHome,
shell, login);
}
public UserAdd(String login, List<String> groups, @Nullable String password, @Nullable String installRSAPrivateKey,
List<String> authorizeRSAPublicKeys, @Nullable String home, String defaultHome, String shell, String fullName) {
public UserAdd(Function<String, String> cryptFunction, String login, List<String> groups, @Nullable String password,
@Nullable String installRSAPrivateKey, List<String> authorizeRSAPublicKeys, @Nullable String home,
String defaultHome, String shell, String fullName) {
this.login = checkNotNull(login, "login");
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.installRSAPrivateKey = installRSAPrivateKey;
this.authorizeRSAPublicKeys = ImmutableList
@ -156,6 +168,7 @@ public class UserAdd implements Statement {
this.fullName = fullName;
}
private final Function<String, String> cryptFunction;
private final String home;
private final String defaultHome;
private final String login;
@ -166,16 +179,6 @@ public class UserAdd implements Statement {
private final String shell;
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
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();

View File

@ -19,7 +19,6 @@
package org.jclouds.scriptbuilder.statements.login;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
@ -50,10 +49,9 @@ public class AdminAccessTest {
try {
assertEquals(
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
.adminPublicKey("fooPublicKey").adminUsername("foo")
.adminHome("/over/ridden/foo").build()
.adminPublicKey("fooPublicKey").adminUsername("foo").adminHome("/over/ridden/foo").build()
.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));
} finally {
TestConfiguration.INSTANCE.reset();
@ -66,8 +64,7 @@ public class AdminAccessTest {
assertEquals(
AdminAccess.builder().adminPassword("bar").adminPrivateKey("fooPrivateKey")
.adminPublicKey("fooPublicKey").adminUsername("foo").adminFullName("JClouds Foo")
.adminHome("/over/ridden/foo").build()
.init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
.adminHome("/over/ridden/foo").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
Resources.toString(Resources.getResource("test_adminaccess_params_and_fullname.sh"), Charsets.UTF_8));
} finally {
@ -75,7 +72,6 @@ public class AdminAccessTest {
}
}
public void testOnlyInstallUserUNIX() throws IOException {
TestConfiguration.INSTANCE.reset();
try {
@ -83,20 +79,19 @@ public class AdminAccessTest {
AdminAccess.builder().grantSudoToAdminUser(false).authorizeAdminPublicKey(true)
.installAdminPrivateKey(true).lockSsh(false).resetLoginPassword(false).build()
.init(TestConfiguration.INSTANCE).render(OsFamily.UNIX),
Resources.toString(Resources.getResource("test_adminaccess_plainuser.sh"), Charsets.UTF_8));
Resources.toString(Resources.getResource("test_adminaccess_plainuser.sh"), Charsets.UTF_8));
} finally {
TestConfiguration.INSTANCE.reset();
}
}
@Test(expectedExceptions = UnsupportedOperationException.class)
@Test(expectedExceptions = UnsupportedOperationException.class, expectedExceptionsMessageRegExp = "windows not yet implemented")
public void testCreateWheelWindowsNotSupported() {
AdminAccess.standard().init(TestConfiguration.INSTANCE).render(OsFamily.WINDOWS);
}
@Test(expectedExceptions = IllegalArgumentException.class)
// for issue 682
public void testRootNotAllowed() throws IOException {
@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")
public void testRootNotAllowed() {
TestConfiguration.INSTANCE.reset();
try {
AdminAccess.builder().adminUsername("root").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX);
@ -105,12 +100,13 @@ public class AdminAccessTest {
}
}
@Test(expectedExceptions = NullPointerException.class)
public void testFamilyRequiredAllowed() throws IOException {
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "family")
public void testFamilyRequiredAllowed() {
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();
// before rendered, holder is empty
assertEquals(access.config.getAdminUsername(), null);
@ -119,20 +115,6 @@ public class AdminAccessTest {
assertEquals(access.config.getAdminPrivateKey(), null);
assertEquals(access.config.getLoginPassword(), null);
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
}
}
}

View File

@ -18,24 +18,34 @@
*/
package org.jclouds.scriptbuilder.statements.login;
import static org.testng.Assert.assertEquals;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ReplaceShadowPasswordEntryOfLoginUserTest {
Function<String, String> crypt = new Function<String, String>() {
public String apply(String in) {
assertEquals(in, "password");
return "CRYPT";
}
};
public void testWithPasswordUNIX() {
String cmd = new ReplaceShadowPasswordEntryOfLoginUser("bar").render(OsFamily.UNIX);
assert cmd.startsWith("awk -v user=^${SUDO_USER:=${USER}}: -v password='$6$") : cmd;
String cmd = new ReplaceShadowPasswordEntryOfLoginUser(crypt, "password").render(OsFamily.UNIX);
assert cmd.startsWith("awk -v user=^${SUDO_USER:=${USER}}: -v password='CRYPT") : 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;
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testAddUserWindowsNotSupported() {
new ReplaceShadowPasswordEntryOfLoginUser("password").render(OsFamily.WINDOWS);
new ReplaceShadowPasswordEntryOfLoginUser(crypt, "password").render(OsFamily.WINDOWS);
}
}

View File

@ -18,24 +18,34 @@
*/
package org.jclouds.scriptbuilder.statements.login;
import static org.testng.Assert.*;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ReplaceShadowPasswordEntryTest {
Function<String, String> crypt = new Function<String, String>() {
public String apply(String in) {
assertEquals(in, "password");
return "CRYPT";
}
};
public void testWithPasswordUNIX() {
String userAdd = new ReplaceShadowPasswordEntry("foo", "bar").render(OsFamily.UNIX);
assert userAdd.startsWith("awk -v user=^foo: -v password='$6$") : userAdd;
String userAdd = new ReplaceShadowPasswordEntry(crypt, "foo", "password").render(OsFamily.UNIX);
assert userAdd.startsWith("awk -v user=^foo: -v password='CRYPT") : 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;
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testAddUserWindowsNotSupported() {
new ReplaceShadowPasswordEntry("user", "password").render(OsFamily.WINDOWS);
new ReplaceShadowPasswordEntry(crypt, "user", "password").render(OsFamily.WINDOWS);
}
}

View File

@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.testng.annotations.Test;
import com.google.common.base.Function;
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");
}
Function<String, String> crypt = new Function<String, String>() {
public String apply(String in) {
assertEquals(in, "password");
return "CRYPT";
}
};
public void testWithPasswordUNIX() {
String userAdd = UserAdd.builder().login("me").password("foo").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;
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 'CRYPT'") : userAdd;
assert userAdd.endsWith("' me\nchown -R me /home/users/me\n") : userAdd;
}