mirror of https://github.com/apache/jclouds.git
Issue 473: created new function to add a user, and supporting sudoers and shadow logic
This commit is contained in:
parent
9388f8b5ca
commit
4b879402fd
|
@ -57,4 +57,6 @@ public interface Crypto {
|
|||
|
||||
MessageDigest sha256();
|
||||
|
||||
MessageDigest sha512();
|
||||
|
||||
}
|
|
@ -73,7 +73,8 @@ public class JCECrypto implements Crypto {
|
|||
|
||||
public final static String MD5 = "MD5";
|
||||
public final static String SHA1 = "SHA1";
|
||||
public final static String SHA256 = "SHA256";
|
||||
public final static String SHA256 = "SHA-256";
|
||||
public final static String SHA512 = "SHA-512";
|
||||
|
||||
@Override
|
||||
public MessageDigest md5() {
|
||||
|
@ -98,7 +99,16 @@ public class JCECrypto implements Crypto {
|
|||
try {
|
||||
return digest(SHA256);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("SHA256 must be supported", e);
|
||||
throw new IllegalStateException(SHA256 + " must be supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageDigest sha512() {
|
||||
try {
|
||||
return digest(SHA512);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException(SHA512 + " must be supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ import com.google.inject.Injector;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "performance", sequential = true, timeOut = 2 * 60 * 1000, testName = "CryptoTest")
|
||||
public class CryptoTest extends PerformanceTest {
|
||||
|
||||
|
@ -122,4 +122,15 @@ public class CryptoTest extends PerformanceTest {
|
|||
assertEquals(hexMD5Digest, b64);
|
||||
}
|
||||
|
||||
public void testSHA1() {
|
||||
crypto.sha1();
|
||||
}
|
||||
|
||||
public void testSHA256() {
|
||||
crypto.sha256();
|
||||
}
|
||||
|
||||
public void testSHA512() {
|
||||
crypto.sha512();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,15 +36,10 @@
|
|||
<jclouds.test.listener></jclouds.test.listener>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>r09</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>1.3.9</version>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -19,37 +19,21 @@
|
|||
package org.jclouds.scriptbuilder.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
|
||||
import java.util.Collections;
|
||||
import org.jclouds.scriptbuilder.statements.ssh.AuthorizeRSAPublicKeys;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see AuthorizeRSAPublicKeys
|
||||
*/
|
||||
public class AuthorizeRSAPublicKey implements Statement {
|
||||
|
||||
private final String publicKey;
|
||||
@Deprecated
|
||||
public class AuthorizeRSAPublicKey extends AuthorizeRSAPublicKeys {
|
||||
|
||||
public AuthorizeRSAPublicKey(String publicKey) {
|
||||
this.publicKey = checkNotNull(publicKey, "publicKey");
|
||||
super(ImmutableSet.of(checkNotNull(publicKey, "publicKey")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
return new StatementList(ImmutableList.of(exec("{md} ~/.ssh"), appendFile("~/.ssh/authorized_keys", Splitter.on('\n')
|
||||
.split(publicKey)), exec("chmod 600 ~/.ssh/authorized_keys"))).render(family);
|
||||
}
|
||||
}
|
|
@ -18,39 +18,15 @@
|
|||
*/
|
||||
package org.jclouds.scriptbuilder.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.rm;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class InstallRSAPrivateKey implements Statement {
|
||||
|
||||
private final String privateKey;
|
||||
@Deprecated
|
||||
public class InstallRSAPrivateKey extends org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey {
|
||||
|
||||
public InstallRSAPrivateKey(String privateKey) {
|
||||
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||
super(privateKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
return new StatementList(ImmutableList.of(exec("{md} ~/.ssh"), rm("~/.ssh/id_rsa"), appendFile("~/.ssh/id_rsa", Splitter.on('\n')
|
||||
.split(privateKey)), exec("chmod 600 ~/.ssh/id_rsa"))).render(family);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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 org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
/**
|
||||
* Statements used in sudo control
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class SudoStatements {
|
||||
|
||||
/**
|
||||
* create new sudoers file with the wheel group authorized to all commands without a password
|
||||
*/
|
||||
public static Statement createWheel() {
|
||||
return new Sudoers();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
/**
|
||||
* Control /etc/sudoers
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Beta
|
||||
public class Sudoers implements Statement {
|
||||
private static final String sudoers = "/etc/sudoers";
|
||||
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
Builder<Statement> statements = ImmutableList.<Statement> builder();
|
||||
statements.add(exec("{rm} " + sudoers));
|
||||
statements.add(appendFile(sudoers, ImmutableSet.of("root ALL = (ALL) ALL", "%wheel ALL = (ALL) NOPASSWD:ALL")));
|
||||
statements.add(exec("chmod 0440 " + sudoers));
|
||||
return new StatementList(statements.build()).render(family);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.encryption.internal.JCECrypto;
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.scriptbuilder.statements.ssh.AuthorizeRSAPublicKeys;
|
||||
import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
|
||||
import org.jclouds.scriptbuilder.util.Sha512Crypt;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class UserAdd implements Statement {
|
||||
public static UserAdd.Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String defaultHome = "/home/users";
|
||||
private String login;
|
||||
private String password;
|
||||
private String RSAPrivateKey;
|
||||
private List<String> groups = Lists.newArrayList();
|
||||
private List<String> authorizeRSAPublicKeys = Lists.newArrayList();
|
||||
private String shell = "/bin/bash";
|
||||
|
||||
public UserAdd.Builder defaultHome(String defaultHome) {
|
||||
this.defaultHome = defaultHome;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder login(String login) {
|
||||
this.login = login;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder password(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder group(String group) {
|
||||
this.groups.add(checkNotNull(group, "group"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder groups(Iterable<String> groups) {
|
||||
this.groups = ImmutableList.<String> copyOf(checkNotNull(groups, "groups"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder installRSAPrivateKey(String RSAPrivateKey) {
|
||||
this.RSAPrivateKey = RSAPrivateKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder authorizeRSAPublicKey(String RSAPublicKey) {
|
||||
this.authorizeRSAPublicKeys.add(checkNotNull(RSAPublicKey, "RSAPublicKey"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder authorizeRSAPublicKeys(Iterable<String> RSAPublicKeys) {
|
||||
this.authorizeRSAPublicKeys = ImmutableList.<String> copyOf(checkNotNull(RSAPublicKeys, "RSAPublicKeys"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd.Builder shell(String shell) {
|
||||
this.shell = shell;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAdd build() {
|
||||
return new UserAdd(login, groups, password, RSAPrivateKey, authorizeRSAPublicKeys, defaultHome, shell);
|
||||
}
|
||||
}
|
||||
|
||||
public UserAdd(String login, List<String> groups, @Nullable String password, @Nullable String installRSAPrivateKey,
|
||||
List<String> authorizeRSAPublicKeys, String defaultHome, String shell) {
|
||||
this.login = checkNotNull(login, "login");
|
||||
this.password = password;
|
||||
this.groups = ImmutableList.copyOf(checkNotNull(groups, "groups"));
|
||||
this.installRSAPrivateKey = installRSAPrivateKey;
|
||||
this.authorizeRSAPublicKeys = ImmutableList
|
||||
.copyOf(checkNotNull(authorizeRSAPublicKeys, "authorizeRSAPublicKeys"));
|
||||
this.defaultHome = checkNotNull(defaultHome, "defaultHome");
|
||||
this.shell = checkNotNull(shell, "shell");
|
||||
}
|
||||
|
||||
private final String defaultHome;
|
||||
private final String login;
|
||||
private final List<String> groups;
|
||||
private final String password;
|
||||
private final String installRSAPrivateKey;
|
||||
private final List<String> authorizeRSAPublicKeys;
|
||||
private final String shell;
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
String homeDir = defaultHome + "{fs}" + login;
|
||||
ImmutableList.Builder<Statement> statements = ImmutableList.<Statement> builder();
|
||||
statements.add(Statements.exec("{md} " + homeDir));
|
||||
|
||||
ImmutableMap.Builder<String, String> userAddOptions = ImmutableMap.<String, String> builder();
|
||||
userAddOptions.put("-s", shell);
|
||||
if (groups.size() > 0) {
|
||||
for (String group : groups)
|
||||
statements.add(Statements.exec("groupadd -f " + group));
|
||||
|
||||
List<String> groups = Lists.newArrayList(this.groups);
|
||||
String primaryGroup = groups.remove(0);
|
||||
userAddOptions.put("-g", primaryGroup);
|
||||
if (groups.size() > 0)
|
||||
userAddOptions.put("-G", Joiner.on(',').join(groups));
|
||||
|
||||
}
|
||||
userAddOptions.put("-d", homeDir);
|
||||
if (password != null) {
|
||||
try {
|
||||
userAddOptions.put("-p", "'" + Sha512Crypt.makeShadowLine(password, null, new JCECrypto()) + "'");
|
||||
} catch (Exception e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
String options = Joiner.on(' ').withKeyValueSeparator(" ").join(userAddOptions.build());
|
||||
|
||||
statements.add(Statements.exec(String.format("useradd %s %s", options, login)));
|
||||
|
||||
if (authorizeRSAPublicKeys.size() > 0 || installRSAPrivateKey != null) {
|
||||
String sshDir = homeDir + "{fs}.ssh";
|
||||
if (authorizeRSAPublicKeys.size() > 0)
|
||||
statements.add(new AuthorizeRSAPublicKeys(sshDir, authorizeRSAPublicKeys));
|
||||
if (installRSAPrivateKey != null)
|
||||
statements.add(new InstallRSAPrivateKey(sshDir, installRSAPrivateKey));
|
||||
}
|
||||
statements.add(Statements.exec(String.format("chown -R %s %s", login, homeDir)));
|
||||
return new StatementList(statements.build()).render(family);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((login == null) ? 0 : login.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
UserAdd other = (UserAdd) obj;
|
||||
if (login == null) {
|
||||
if (other.login != null)
|
||||
return false;
|
||||
} else if (!login.equals(other.login))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class AuthorizeRSAPublicKeys implements Statement {
|
||||
private final String sshDir;
|
||||
private final List<String> publicKeys;
|
||||
|
||||
public AuthorizeRSAPublicKeys(Iterable<String> publicKeys) {
|
||||
this("~/.ssh", publicKeys);
|
||||
}
|
||||
|
||||
public AuthorizeRSAPublicKeys(String sshDir, Iterable<String> publicKeys) {
|
||||
this.sshDir = checkNotNull(sshDir, "sshDir");
|
||||
this.publicKeys = ImmutableList.copyOf(checkNotNull(publicKeys, "publicKeys"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
Builder<Statement> statements = ImmutableList.<Statement> builder();
|
||||
statements.add(exec("mkdir -p " + sshDir));
|
||||
String authorizedKeys = sshDir + "{fs}authorized_keys";
|
||||
statements.add(appendFile(authorizedKeys, Splitter.on('\n').split(Joiner.on("\n\n").join(publicKeys))));
|
||||
statements.add(exec("chmod 600 " + authorizedKeys));
|
||||
return new StatementList(statements.build()).render(family);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class InstallRSAPrivateKey implements Statement {
|
||||
private final String sshDir;
|
||||
private final String privateKey;
|
||||
|
||||
public InstallRSAPrivateKey(String privateKey) {
|
||||
this("~/.ssh", privateKey);
|
||||
}
|
||||
|
||||
public InstallRSAPrivateKey(String sshDir, String privateKey) {
|
||||
this.sshDir = checkNotNull(sshDir, "sshDir");
|
||||
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render(OsFamily family) {
|
||||
checkNotNull(family, "family");
|
||||
if (family == OsFamily.WINDOWS)
|
||||
throw new UnsupportedOperationException("windows not yet implemented");
|
||||
Builder<Statement> statements = ImmutableList.<Statement> builder();
|
||||
statements.add(exec("{md} " + sshDir));
|
||||
String idRsa = sshDir + "{fs}id_rsa";
|
||||
statements.add(exec("{rm} " + idRsa));
|
||||
statements.add(appendFile(idRsa, Splitter.on('\n').split(privateKey)));
|
||||
statements.add(exec("chmod 600 " + idRsa));
|
||||
return new StatementList(statements.build()).render(family);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Statements used in ssh control
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class SshStatements {
|
||||
|
||||
/**
|
||||
* lock sshd down so root cannot login, and password auth is disabled,
|
||||
*/
|
||||
public static Statement lockSshd() {
|
||||
return sshdConfig(ImmutableMap.of("PasswordAuthentication","no", "PermitRootLogin","no"));
|
||||
}
|
||||
|
||||
public static Statement sshdConfig(Map<String, String> params) {
|
||||
return new SshdConfig(params);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Control sshd_config
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class SshdConfig implements Statement {
|
||||
private static final String sshdConfig = "/etc/ssh/sshd_config";
|
||||
|
||||
private final Map<String, String> params;
|
||||
|
||||
public SshdConfig(Map<String, String> params) {
|
||||
this.params = checkNotNull(params, "params");
|
||||
}
|
||||
|
||||
public String render(OsFamily family) {
|
||||
String linesToPrepend = Joiner.on('\n').withKeyValueSeparator(" ").join(params);
|
||||
Statement prependSshdConfig = exec(String.format(
|
||||
"exec 3<> %1$s && awk -v TEXT=\"%2$s\n\" 'BEGIN {print TEXT}{print}' %1$s >&3", sshdConfig,
|
||||
linesToPrepend));
|
||||
Statement reloadSshdConfig = exec("/etc/init.d/sshd reload||/etc/init.d/ssh reload");
|
||||
return newStatementList(prependSshdConfig, reloadSshdConfig).render(family);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> functionDependecies(OsFamily family) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
Sha512Crypt.java
|
||||
|
||||
Created: 18 December 2007
|
||||
Last Changed By: $Author: broccol $
|
||||
Version: $Revision: 7692 $
|
||||
Last Mod Date: $Date: 2007-12-30 01:55:31 -0600 (Sun, 30 Dec 2007) $
|
||||
|
||||
Java Port By: James Ratcliff, falazar@arlut.utexas.edu
|
||||
|
||||
This class implements the new generation, scalable, SHA512-based
|
||||
Unix 'crypt' algorithm developed by a group of engineers from Red
|
||||
Hat, Sun, IBM, and HP for common use in the Unix and Linux
|
||||
/etc/shadow files.
|
||||
|
||||
The Linux glibc library (starting at version 2.7) includes support
|
||||
for validating passwords hashed using this algorithm.
|
||||
|
||||
The algorithm itself was released into the Public Domain by Ulrich
|
||||
Drepper <drepper@redhat.com>. A discussion of the rationale and
|
||||
development of this algorithm is at
|
||||
|
||||
http://people.redhat.com/drepper/sha-crypt.html
|
||||
|
||||
and the specification and a sample C language implementation is at
|
||||
|
||||
http://people.redhat.com/drepper/SHA-crypt.txt
|
||||
|
||||
This Java Port is
|
||||
|
||||
Copyright (c) 2008 The University of Texas at Austin.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary form are permitted
|
||||
provided that distributions retain this entire copyright notice
|
||||
and comment. Neither the name of the University nor the names of
|
||||
its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE.
|
||||
|
||||
*/
|
||||
|
||||
package org.jclouds.scriptbuilder.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.crypto.Crypto;
|
||||
|
||||
/**
|
||||
* This class defines a method,
|
||||
* {@link Sha512Crypt#Sha512_crypt(java.lang.String, java.lang.String, int) Sha512_crypt()}, which
|
||||
* takes a password and a salt string and generates a Sha512 encrypted password entry.
|
||||
*
|
||||
* This class implements the new generation, scalable, SHA512-based Unix 'crypt' algorithm developed
|
||||
* by a group of engineers from Red Hat, Sun, IBM, and HP for common use in the Unix and Linux
|
||||
* /etc/shadow files.
|
||||
*
|
||||
* The Linux glibc library (starting at version 2.7) includes support for validating passwords
|
||||
* hashed using this algorithm.
|
||||
*
|
||||
* The algorithm itself was released into the Public Domain by Ulrich Drepper
|
||||
* <drepper@redhat.com>. A discussion of the rationale and development of this algorithm is at
|
||||
*
|
||||
* http://people.redhat.com/drepper/sha-crypt.html
|
||||
*
|
||||
* and the specification and a sample C language implementation is at
|
||||
*
|
||||
* http://people.redhat.com/drepper/SHA-crypt.txt
|
||||
*/
|
||||
public class Sha512Crypt {
|
||||
static private final String sha512_salt_prefix = "$6$";
|
||||
static private final String sha512_rounds_prefix = "rounds=";
|
||||
static private final int SALT_LEN_MAX = 16;
|
||||
static private final int ROUNDS_DEFAULT = 5000;
|
||||
static private final int ROUNDS_MIN = 1000;
|
||||
static private final int ROUNDS_MAX = 999999999;
|
||||
static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||
static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
/**
|
||||
* This method actually generates an Sha512 crypted password hash from a plaintext password and a
|
||||
* salt.
|
||||
*
|
||||
* <p>
|
||||
* The resulting string will be in the form '$6$<rounds=n>$<salt>$<hashed mess>
|
||||
* </p>
|
||||
*
|
||||
* @param password
|
||||
* Plaintext password
|
||||
*
|
||||
* @param shadowPrefix
|
||||
* An encoded salt/rounds which will be consulted to determine the salt and round
|
||||
* count, if not null
|
||||
*
|
||||
* @return The Sha512 Unix Crypt hash text for the password
|
||||
*/
|
||||
public static String makeShadowLine(String password, @Nullable String shadowPrefix, Crypto crypto) {
|
||||
MessageDigest ctx = crypto.sha512();
|
||||
MessageDigest alt_ctx = crypto.sha512();
|
||||
|
||||
byte[] alt_result;
|
||||
byte[] temp_result;
|
||||
byte[] p_bytes = null;
|
||||
byte[] s_bytes = null;
|
||||
int cnt, cnt2;
|
||||
int rounds = ROUNDS_DEFAULT; // Default number of rounds.
|
||||
StringBuffer buffer;
|
||||
|
||||
/* -- */
|
||||
|
||||
if (shadowPrefix != null) {
|
||||
if (shadowPrefix.startsWith(sha512_salt_prefix)) {
|
||||
shadowPrefix = shadowPrefix.substring(sha512_salt_prefix.length());
|
||||
}
|
||||
|
||||
if (shadowPrefix.startsWith(sha512_rounds_prefix)) {
|
||||
String num = shadowPrefix.substring(sha512_rounds_prefix.length(), shadowPrefix.indexOf('$'));
|
||||
int srounds = Integer.valueOf(num).intValue();
|
||||
shadowPrefix = shadowPrefix.substring(shadowPrefix.indexOf('$') + 1);
|
||||
rounds = Math.max(ROUNDS_MIN, Math.min(srounds, ROUNDS_MAX));
|
||||
}
|
||||
|
||||
if (shadowPrefix.length() > SALT_LEN_MAX) {
|
||||
shadowPrefix = shadowPrefix.substring(0, SALT_LEN_MAX);
|
||||
}
|
||||
} else {
|
||||
java.util.Random randgen = new java.util.Random();
|
||||
StringBuffer saltBuf = new StringBuffer();
|
||||
|
||||
while (saltBuf.length() < 16) {
|
||||
int index = (int) (randgen.nextFloat() * SALTCHARS.length());
|
||||
saltBuf.append(SALTCHARS.substring(index, index + 1));
|
||||
}
|
||||
|
||||
shadowPrefix = saltBuf.toString();
|
||||
}
|
||||
|
||||
byte[] key = password.getBytes();
|
||||
byte[] salts = shadowPrefix.getBytes();
|
||||
|
||||
ctx.reset();
|
||||
ctx.update(key, 0, key.length);
|
||||
ctx.update(salts, 0, salts.length);
|
||||
|
||||
alt_ctx.reset();
|
||||
alt_ctx.update(key, 0, key.length);
|
||||
alt_ctx.update(salts, 0, salts.length);
|
||||
alt_ctx.update(key, 0, key.length);
|
||||
|
||||
alt_result = alt_ctx.digest();
|
||||
|
||||
for (cnt = key.length; cnt > 64; cnt -= 64) {
|
||||
ctx.update(alt_result, 0, 64);
|
||||
}
|
||||
|
||||
ctx.update(alt_result, 0, cnt);
|
||||
|
||||
for (cnt = key.length; cnt > 0; cnt >>= 1) {
|
||||
if ((cnt & 1) != 0) {
|
||||
ctx.update(alt_result, 0, 64);
|
||||
} else {
|
||||
ctx.update(key, 0, key.length);
|
||||
}
|
||||
}
|
||||
|
||||
alt_result = ctx.digest();
|
||||
|
||||
alt_ctx.reset();
|
||||
|
||||
for (cnt = 0; cnt < key.length; ++cnt) {
|
||||
alt_ctx.update(key, 0, key.length);
|
||||
}
|
||||
|
||||
temp_result = alt_ctx.digest();
|
||||
|
||||
p_bytes = new byte[key.length];
|
||||
|
||||
for (cnt2 = 0, cnt = p_bytes.length; cnt >= 64; cnt -= 64) {
|
||||
System.arraycopy(temp_result, 0, p_bytes, cnt2, 64);
|
||||
cnt2 += 64;
|
||||
}
|
||||
|
||||
System.arraycopy(temp_result, 0, p_bytes, cnt2, cnt);
|
||||
|
||||
alt_ctx.reset();
|
||||
|
||||
for (cnt = 0; cnt < 16 + (alt_result[0] & 0xFF); ++cnt) {
|
||||
alt_ctx.update(salts, 0, salts.length);
|
||||
}
|
||||
|
||||
temp_result = alt_ctx.digest();
|
||||
|
||||
s_bytes = new byte[salts.length];
|
||||
|
||||
for (cnt2 = 0, cnt = s_bytes.length; cnt >= 64; cnt -= 64) {
|
||||
System.arraycopy(temp_result, 0, s_bytes, cnt2, 64);
|
||||
cnt2 += 64;
|
||||
}
|
||||
|
||||
System.arraycopy(temp_result, 0, s_bytes, cnt2, cnt);
|
||||
|
||||
/*
|
||||
* Repeatedly run the collected hash value through SHA512 to burn CPU cycles.
|
||||
*/
|
||||
|
||||
for (cnt = 0; cnt < rounds; ++cnt) {
|
||||
ctx.reset();
|
||||
|
||||
if ((cnt & 1) != 0) {
|
||||
ctx.update(p_bytes, 0, key.length);
|
||||
} else {
|
||||
ctx.update(alt_result, 0, 64);
|
||||
}
|
||||
|
||||
if (cnt % 3 != 0) {
|
||||
ctx.update(s_bytes, 0, salts.length);
|
||||
}
|
||||
|
||||
if (cnt % 7 != 0) {
|
||||
ctx.update(p_bytes, 0, key.length);
|
||||
}
|
||||
|
||||
if ((cnt & 1) != 0) {
|
||||
ctx.update(alt_result, 0, 64);
|
||||
} else {
|
||||
ctx.update(p_bytes, 0, key.length);
|
||||
}
|
||||
|
||||
alt_result = ctx.digest();
|
||||
}
|
||||
|
||||
buffer = new StringBuffer(sha512_salt_prefix);
|
||||
|
||||
if (rounds != 5000) {
|
||||
buffer.append(sha512_rounds_prefix);
|
||||
buffer.append(rounds);
|
||||
buffer.append("$");
|
||||
}
|
||||
|
||||
buffer.append(shadowPrefix);
|
||||
buffer.append("$");
|
||||
|
||||
buffer.append(b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4));
|
||||
buffer.append(b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4));
|
||||
buffer.append(b64_from_24bit((byte) 0x00, (byte) 0x00, alt_result[63], 2));
|
||||
|
||||
/*
|
||||
* Clear the buffer for the intermediate result so that people attaching to processes or
|
||||
* reading core dumps cannot get any information.
|
||||
*/
|
||||
|
||||
ctx.reset();
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static final String b64_from_24bit(byte B2, byte B1, byte B0, int size) {
|
||||
int v = ((((int) B2) & 0xFF) << 16) | ((((int) B1) & 0xFF) << 8) | ((int) B0 & 0xff);
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
while (--size >= 0) {
|
||||
result.append(itoa64.charAt((int) (v & 0x3f)));
|
||||
v >>>= 6;
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,27 +16,27 @@
|
|||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.scriptbuilder.domain;
|
||||
package org.jclouds.scriptbuilder.statements.login;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class AuthorizeRSAPublicKeyTest {
|
||||
public class SudoStatementsTest {
|
||||
|
||||
AuthorizeRSAPublicKey auth = new AuthorizeRSAPublicKey("ssh-dss AAAAB");
|
||||
|
||||
public void testAuthorizeRSAPublicKeyUNIX() {
|
||||
public void testCreateWheelUNIX() {
|
||||
assertEquals(
|
||||
auth.render(OsFamily.UNIX),
|
||||
"mkdir -p ~/.ssh\ncat >> ~/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\nEND_OF_FILE\nchmod 600 ~/.ssh/authorized_keys\n"); }
|
||||
SudoStatements.createWheel().render(OsFamily.UNIX),
|
||||
"rm /etc/sudoers\ncat >> /etc/sudoers <<'END_OF_FILE'\nroot ALL = (ALL) ALL\n%wheel ALL = (ALL) NOPASSWD:ALL\nEND_OF_FILE\nchmod 0440 /etc/sudoers\n");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testAuthorizeRSAPublicKeyWINDOWS() {
|
||||
auth.render(OsFamily.WINDOWS);
|
||||
public void testCreateWheelWindowsNotSupported() {
|
||||
SudoStatements.createWheel().render(OsFamily.WINDOWS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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 org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class UserAddTest {
|
||||
|
||||
public void testUNIX() {
|
||||
assertEquals(UserAdd.builder().login("me").build().render(OsFamily.UNIX),
|
||||
"mkdir -p /home/users/me\nuseradd -s /bin/bash -d /home/users/me me\nchown -R me /home/users/me\n");
|
||||
}
|
||||
|
||||
public void testWithBaseUNIX() {
|
||||
assertEquals(UserAdd.builder().login("me").defaultHome("/export/home").build().render(OsFamily.UNIX),
|
||||
"mkdir -p /export/home/me\nuseradd -s /bin/bash -d /export/home/me me\nchown -R me /export/home/me\n");
|
||||
}
|
||||
|
||||
public void testWithGroupUNIX() {
|
||||
assertEquals(UserAdd.builder().login("me").group("wheel").build().render(OsFamily.UNIX),
|
||||
"mkdir -p /home/users/me\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -d /home/users/me me\nchown -R me /home/users/me\n");
|
||||
}
|
||||
|
||||
public void testWithGroupsUNIX() {
|
||||
assertEquals(UserAdd.builder().login("me").groups(ImmutableList.of("wheel", "candy")).build().render(
|
||||
OsFamily.UNIX),
|
||||
"mkdir -p /home/users/me\ngroupadd -f wheel\ngroupadd -f candy\nuseradd -s /bin/bash -g wheel -G candy -d /home/users/me me\nchown -R me /home/users/me\n");
|
||||
}
|
||||
|
||||
public void testWithPasswordUNIX() {
|
||||
String userAdd = UserAdd.builder().login("me").password("foo").group("wheel").build().render(OsFamily.UNIX);
|
||||
assert userAdd.startsWith("mkdir -p /home/users/me\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -d /home/users/me -p '$6$") : userAdd;
|
||||
assert userAdd.endsWith("' me\nchown -R me /home/users/me\n") : userAdd;
|
||||
}
|
||||
|
||||
public void testWithSshAuthorizedKeyUNIX() {
|
||||
assertEquals(
|
||||
UserAdd.builder().login("me").authorizeRSAPublicKey("rsapublickey").build().render(OsFamily.UNIX),
|
||||
"mkdir -p /home/users/me\nuseradd -s /bin/bash -d /home/users/me me\nmkdir -p /home/users/me/.ssh\ncat >> /home/users/me/.ssh/authorized_keys <<'END_OF_FILE'\nrsapublickey\nEND_OF_FILE\nchmod 600 /home/users/me/.ssh/authorized_keys\nchown -R me /home/users/me\n");
|
||||
}
|
||||
|
||||
public void testWithSshInstalledKeyUNIX() {
|
||||
assertEquals(
|
||||
UserAdd.builder().login("me").installRSAPrivateKey("rsaprivate").build().render(OsFamily.UNIX),
|
||||
"mkdir -p /home/users/me\nuseradd -s /bin/bash -d /home/users/me me\nmkdir -p /home/users/me/.ssh\nrm /home/users/me/.ssh/id_rsa\ncat >> /home/users/me/.ssh/id_rsa <<'END_OF_FILE'\nrsaprivate\nEND_OF_FILE\nchmod 600 /home/users/me/.ssh/id_rsa\nchown -R me /home/users/me\n");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testAddUserWindowsNotSupported() {
|
||||
UserAdd.builder().login("me").build().render(OsFamily.WINDOWS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class AuthorizeRSAPublicKeyTest {
|
||||
|
||||
public void testAuthorizeRSAPublicKeyUNIXCurrentUser() {
|
||||
assertEquals(
|
||||
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.UNIX),
|
||||
"mkdir -p ~/.ssh\ncat >> ~/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\nEND_OF_FILE\nchmod 600 ~/.ssh/authorized_keys\n");
|
||||
}
|
||||
|
||||
public void testAuthorizeRSAPublicKeyUNIXCurrentUserWith2Keys() {
|
||||
assertEquals(
|
||||
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD")).render(OsFamily.UNIX),
|
||||
"mkdir -p ~/.ssh\ncat >> ~/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\n\nssh-dss CCCCD\nEND_OF_FILE\nchmod 600 ~/.ssh/authorized_keys\n");
|
||||
}
|
||||
|
||||
public void testAuthorizeRSAPublicKeyUNIXSpecifiedDir() {
|
||||
assertEquals(
|
||||
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.UNIX),
|
||||
"mkdir -p /home/me/.ssh\ncat >> /home/me/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\nEND_OF_FILE\nchmod 600 /home/me/.ssh/authorized_keys\n");
|
||||
}
|
||||
|
||||
public void testAuthorizeRSAPublicKeyUNIXSpecifiedDirWith2Keys() {
|
||||
assertEquals(
|
||||
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD"))
|
||||
.render(OsFamily.UNIX),
|
||||
"mkdir -p /home/me/.ssh\ncat >> /home/me/.ssh/authorized_keys <<'END_OF_FILE'\nssh-dss AAAAB\n\nssh-dss CCCCD\nEND_OF_FILE\nchmod 600 /home/me/.ssh/authorized_keys\n");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testAuthorizeRSAPublicKeyWINDOWS() {
|
||||
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.WINDOWS);
|
||||
}
|
||||
}
|
|
@ -16,10 +16,11 @@
|
|||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.scriptbuilder.domain;
|
||||
package org.jclouds.scriptbuilder.statements.ssh;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -28,16 +29,23 @@ import org.testng.annotations.Test;
|
|||
@Test(groups = "unit")
|
||||
public class InstallRSAPrivateKeyTest {
|
||||
|
||||
InstallRSAPrivateKey key = new InstallRSAPrivateKey("-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
public void testInstallRSAPrivateKeyUNIX() {
|
||||
public void testInstallRSAPrivateKeyUNIXCurrentUser() {
|
||||
assertEquals(
|
||||
key.render(OsFamily.UNIX),
|
||||
new InstallRSAPrivateKey("-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n")
|
||||
.render(OsFamily.UNIX),
|
||||
"mkdir -p ~/.ssh\nrm ~/.ssh/id_rsa\ncat >> ~/.ssh/id_rsa <<'END_OF_FILE'\n-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n\nEND_OF_FILE\nchmod 600 ~/.ssh/id_rsa\n");
|
||||
}
|
||||
|
||||
public void testInstallRSAPrivateKeyUNIXSpecifiedHome() {
|
||||
assertEquals(
|
||||
new InstallRSAPrivateKey("/home/me/.ssh", "-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n")
|
||||
.render(OsFamily.UNIX),
|
||||
"mkdir -p /home/me/.ssh\nrm /home/me/.ssh/id_rsa\ncat >> /home/me/.ssh/id_rsa <<'END_OF_FILE'\n-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n\nEND_OF_FILE\nchmod 600 /home/me/.ssh/id_rsa\n");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testInstallRSAPrivateKeyWINDOWS() {
|
||||
key.render(OsFamily.WINDOWS);
|
||||
new InstallRSAPrivateKey("-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----\n")
|
||||
.render(OsFamily.WINDOWS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.ssh;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.scriptbuilder.statements.ssh.SshStatements;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class SshStatementsTest {
|
||||
|
||||
public void testLockSshdUNIX() {
|
||||
assertEquals(SshStatements.lockSshd().render(OsFamily.UNIX), new StringBuilder().append(
|
||||
"exec 3<> /etc/ssh/sshd_config && awk -v TEXT=\"")//
|
||||
.append("PasswordAuthentication no").append("\n")//
|
||||
.append("PermitRootLogin no").append("\n")//
|
||||
.append("\" 'BEGIN {print TEXT}{print}' /etc/ssh/sshd_config >&3").append("\n")//
|
||||
.append("/etc/init.d/sshd reload||/etc/init.d/ssh reload").append("\n").toString());
|
||||
}
|
||||
|
||||
public void testSshdConfigUNIX() {
|
||||
assertEquals(SshStatements.sshdConfig(ImmutableMap.of("AddressFamily", "inet6")).render(OsFamily.UNIX),
|
||||
new StringBuilder().append("exec 3<> /etc/ssh/sshd_config && awk -v TEXT=\"")//
|
||||
.append("AddressFamily inet6").append("\n")//
|
||||
.append("\" 'BEGIN {print TEXT}{print}' /etc/ssh/sshd_config >&3").append("\n")//
|
||||
.append("/etc/init.d/sshd reload||/etc/init.d/ssh reload").append("\n").toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.util;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class Sha512CryptTest {
|
||||
|
||||
protected Crypto crypto;
|
||||
|
||||
@BeforeTest
|
||||
protected void createCrypto() {
|
||||
Injector i = Guice.createInjector();
|
||||
crypto = i.getInstance(Crypto.class);
|
||||
}
|
||||
|
||||
public final static Object[][] TEST_DATA = {
|
||||
{ "Hello world!", "$6$saltstring",
|
||||
"$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1" },
|
||||
{
|
||||
"Hello world!",
|
||||
"$6$rounds=10000$saltstringsaltstring",
|
||||
"$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sbHbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
|
||||
{ "This is just a test", "$6$rounds=5000$toolongsaltstring",
|
||||
"$6$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQzQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
|
||||
{
|
||||
"a very much longer text to encrypt. This one even stretches over morethan one line.",
|
||||
"$6$rounds=1400$anotherlongsaltstring",
|
||||
"$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wPvMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
|
||||
|
||||
{
|
||||
"a short string",
|
||||
"$6$rounds=123456$asaltof16chars..",
|
||||
"$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwcelCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
|
||||
{ "the minimum number is still observed", "$6$rounds=10$roundstoolow",
|
||||
"$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." } };
|
||||
|
||||
@DataProvider(name = "data")
|
||||
public Object[][] createData1() {
|
||||
return TEST_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate our implementation using test data from Ulrich Drepper's C implementation.
|
||||
*/
|
||||
@Test(dataProvider = "data")
|
||||
public void testMakeCryptedPasswordHash(String password, String salt, String expected) {
|
||||
assertEquals(Sha512Crypt.makeShadowLine(password, salt, crypto), expected);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue