Issue 543: added ability to reset default login user's password

This commit is contained in:
Adrian Cole 2011-05-01 12:52:50 -04:00
parent 4b879402fd
commit 0c3a0ac7ee
20 changed files with 269 additions and 20 deletions

View File

@ -133,7 +133,7 @@ public class ScriptBuilder implements Statement {
new Function<Statement, Iterable<String>>() {
@Override
public Iterable<String> apply(Statement from) {
return from.functionDependecies(osFamily);
return from.functionDependencies(osFamily);
}
}));
List<String> unresolvedFunctions = Lists.newArrayList(dependentFunctions);
@ -144,7 +144,7 @@ public class ScriptBuilder implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableSet.<String> of();
}
}

View File

@ -64,7 +64,7 @@ public class AppendFile implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}

View File

@ -87,7 +87,7 @@ public class Call implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of(function);
}
}

View File

@ -69,7 +69,7 @@ public class CreateRunScript implements Statement {
"echo title {title}>>{file}\r\n");
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}
@ -96,7 +96,7 @@ public class CreateRunScript implements Statement {
"echo set {export}={value}>>{file}\r\n");
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}
@ -122,7 +122,7 @@ public class CreateRunScript implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}

View File

@ -46,7 +46,7 @@ public class InterpretableStatement implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}

View File

@ -45,7 +45,7 @@ public class Kill implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}
}

View File

@ -24,7 +24,7 @@ package org.jclouds.scriptbuilder.domain;
* @author Adrian Cole
*/
public interface Statement {
Iterable<String> functionDependecies(OsFamily family);
Iterable<String> functionDependencies(OsFamily family);
String render(OsFamily family);
}

View File

@ -51,10 +51,10 @@ public class StatementList implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
List<String> functions = Lists.newArrayList();
for (Statement statement : statements) {
Iterables.addAll(functions, statement.functionDependecies(family));
Iterables.addAll(functions, statement.functionDependencies(family));
}
return functions;
}

View File

@ -44,7 +44,7 @@ public class Statements {
return new Statement() {
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}

View File

@ -126,10 +126,10 @@ public class SwitchArg implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
List<String> functions = Lists.newArrayList();
for (Statement statement : valueToActions.values()) {
Iterables.addAll(functions, statement.functionDependecies(family));
Iterables.addAll(functions, statement.functionDependencies(family));
}
return functions;
}

View File

@ -0,0 +1,98 @@
/**
*
* 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 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.util.Sha512Crypt;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
/**
*
* @author Adrian Cole
*/
public class ReplaceShadowPasswordEntry implements Statement {
private final String login;
private final String password;
public ReplaceShadowPasswordEntry(String login, String password) {
this.login = checkNotNull(login, "login");
this.password = checkNotNull(password, "password");
}
@Override
public Iterable<String> functionDependencies(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");
try {
String shadowPasswordEntry = Sha512Crypt.makeShadowLine(password, null, new JCECrypto());
String shadowFile = "/etc/shadow";
Statement replaceEntryInTempFile = Statements
.exec(String
.format(
"awk -v user=^%1$s: -v password='%2$s' 'BEGIN { FS=OFS=\":\" } $0 ~ user { $2 = password } 1' %3$s >%3$s.%1$s",
login, shadowPasswordEntry, shadowFile));
Statement replaceShadowFile = Statements.exec(String.format("test -f %2$s.%1$s && mv %2$s.%1$s %2$s", login,
shadowFile));
return new StatementList(ImmutableList.of(replaceEntryInTempFile, replaceShadowFile)).render(family);
} catch (Exception e) {
Throwables.propagate(e);
return null;
}
}
@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;
ReplaceShadowPasswordEntry other = (ReplaceShadowPasswordEntry) obj;
if (login == null) {
if (other.login != null)
return false;
} else if (!login.equals(other.login))
return false;
return true;
}
}

View File

@ -0,0 +1,32 @@
/**
*
* 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;
/**
*
* @author Adrian Cole
*/
public class ReplaceShadowPasswordEntryOfLoginUser extends ReplaceShadowPasswordEntry {
public ReplaceShadowPasswordEntryOfLoginUser(String password) {
super("${SUDO_USER:=${USER}}", password);
}
}

View File

@ -0,0 +1,37 @@
/**
*
* 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 to manipulate the shadow file
*
* @author Adrian Cole
*/
public class ShadowStatements {
/**
* note must be run as root, and will either reset the root password, or
* whoever sudoed to root.
*/
public static Statement resetLoginUserPasswordTo(String password) {
return new ReplaceShadowPasswordEntryOfLoginUser(password);
}
}

View File

@ -52,7 +52,7 @@ public class Sudoers implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}
}

View File

@ -128,7 +128,7 @@ public class UserAdd implements Statement {
private final String shell;
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}

View File

@ -52,7 +52,7 @@ public class AuthorizeRSAPublicKeys implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}

View File

@ -50,7 +50,7 @@ public class InstallRSAPrivateKey implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}

View File

@ -54,7 +54,7 @@ public class SshdConfig implements Statement {
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableList.of();
}
}

View File

@ -0,0 +1,41 @@
/**
*
* 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.OsFamily;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ReplaceShadowPasswordEntryOfLoginUserTest {
public void testWithPasswordUNIX() {
String cmd = new ReplaceShadowPasswordEntryOfLoginUser("bar").render(OsFamily.UNIX);
assert cmd.startsWith("awk -v user=^${SUDO_USER:=${USER}}: -v password='$6$") : 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);
}
}

View File

@ -0,0 +1,41 @@
/**
*
* 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.OsFamily;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ReplaceShadowPasswordEntryTest {
public void testWithPasswordUNIX() {
String userAdd = new ReplaceShadowPasswordEntry("foo", "bar").render(OsFamily.UNIX);
assert userAdd.startsWith("awk -v user=^foo: -v password='$6$") : 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);
}
}