diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/AdminAccess.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/AdminAccess.java
index fad467c49f..c7c0bd4233 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/AdminAccess.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/AdminAccess.java
@@ -35,6 +35,7 @@ import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.statements.ssh.SshStatements;
import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
@@ -46,17 +47,26 @@ import com.google.inject.ImplementedBy;
* Controls the administrative access to a node. By default, it will perform the following:
*
*
- * - setup a new admin user which folks should use as opposed to the built-in vcloud account
- *
- * - associate a random password to account
- *
- * - securely ( use sha 512 on client side and literally rewrite the shadow entry, rather than
- * pass password to OS in a script )
+ * - setup a new admin user which folks should use as opposed to any built-in account
+ *
+ * - associate a random (or given) password to that account
+ *
+ * - securely (using sha 512 on client side and literally rewriting the shadow entry,
+ * rather than sending password plaintext to OS in a script)
+ * - but note password access is often blocked in any case, see below
+ *
+ * - associate the users' ssh public key with the account for login
+ * - associate it with the os group wheel
+ *
+ * - set up sudoers for password-less access to root for this user (shouldGrantSudo)
+ *
+ * - creating os group wheel and assigning the new admin user to it
+ * - create (overwriting) sudoers file to grant root access for wheel members
+ *
+ * - reset password for the user logging in (e.g. root, because root password is
+ * sometimes known to the provider), securely and randomly as described above (resetLoginPassword)
+ * - lockdown sshd_config for no root login, nor passwords allowed (lockSsh)
*
- * - associate the users' ssh public key with the account for login
-
- * associate it with the os group wheel
- create os group wheel
- add sudoers
- * for nopassword access to root by group wheel
- reset root password securely
-
- * lockdown sshd_config for no root login, nor passwords allowed
*
* @author Adrian Cole
*/
@@ -335,6 +345,8 @@ public class AdminAccess implements Statement {
if (family == OsFamily.WINDOWS)
throw new UnsupportedOperationException("windows not yet implemented");
checkNotNull(config.getAdminUsername(), "adminUsername");
+ Preconditions.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");
checkNotNull(config.getAdminPassword(), "adminPassword");
checkNotNull(config.getAdminPublicKey(), "adminPublicKey");
checkNotNull(config.getAdminPrivateKey(), "adminPrivateKey");
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/DefaultConfiguration.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/DefaultConfiguration.java
index 76e6f22d08..4d0e6410d8 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/DefaultConfiguration.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/DefaultConfiguration.java
@@ -51,9 +51,9 @@ public class DefaultConfiguration implements Configuration {
@Override
public Map 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));
+ 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();
}
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
index ce71168fd0..5fd68fbaa2 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
@@ -43,6 +43,13 @@ import com.google.common.collect.Lists;
import com.google.inject.Inject;
/**
+ * Creates a statement that will add a given user to a machine ("login"), with optional
+ * password, groups, private key, and authorized keys.
+ *
+ * This is supported on most *nix environments. Not currently supported on Windows.
+ *
+ * Note that some places where this is used may have stricter requirements on the parameters
+ * (for example {@link AdminAccess} requires password and keys).
*
* @author Adrian Cole
*/
@@ -65,11 +72,13 @@ public class UserAdd implements Statement {
return this;
}
+ /** the username of the user to add (not the login to use when performing the add) */
public UserAdd.Builder login(String login) {
this.login = login;
return this;
}
+ /** the password to add for the user (not the password to use when logging in to perform the add) */
public UserAdd.Builder password(String password) {
this.password = password;
return this;
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/AdminAccessTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/AdminAccessTest.java
index 17496c6fb8..c3c599293b 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/AdminAccessTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/AdminAccessTest.java
@@ -76,4 +76,16 @@ public class AdminAccessTest {
public void testCreateWheelWindowsNotSupported() {
AdminAccess.standard().init(TestConfiguration.INSTANCE).render(OsFamily.WINDOWS);
}
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ //for issue 682
+ public void testRootNotAllowed() throws IOException {
+ TestConfiguration.INSTANCE.reset();
+ try {
+ AdminAccess.builder().adminUsername("root").build().init(TestConfiguration.INSTANCE).render(OsFamily.UNIX);
+ } finally {
+ TestConfiguration.INSTANCE.reset();
+ }
+ }
+
}