Properly set the permissions in the ~/.ssh folder

When writing the ~/.ssh/authorized_keys file in a script that is being
run as sudo, the file is created with the root owner, instead of the
user defined by the node credentials. File ownership should be enforced
to make sure the right owner is alwaays set.
This commit is contained in:
Ignasi Barrera 2016-06-16 23:32:07 +02:00
parent 04c2394a10
commit 179ed3b2f6
20 changed files with 128 additions and 52 deletions

View File

@ -47,7 +47,6 @@ import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
@ -89,8 +88,6 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
install(new ComputeServiceTimeoutsModule());
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
}).to(CreateSshClientOncePortIsListeningOnNode.class);
bind(new TypeLiteral<Function<TemplateOptions, Statement>>() {
}).to(TemplateOptionsToStatement.class);
bind(LoginCredentials.class).annotatedWith(Names.named("image")).toProvider(
GetLoginForProviderFromPropertiesAndStoreCredentialsOrReturnNull.class);

View File

@ -22,6 +22,7 @@ import java.util.List;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.scriptbuilder.InitScript;
import org.jclouds.scriptbuilder.domain.Statement;
@ -29,17 +30,20 @@ import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.statements.ssh.AuthorizeRSAPublicKeys;
import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
@Singleton
public class TemplateOptionsToStatement implements Function<TemplateOptions, Statement> {
public class InstallKeysAndRunScript implements NodeAndTemplateOptionsToStatement {
@Override
public Statement apply(TemplateOptions options) {
public Statement apply(NodeMetadata node, TemplateOptions options) {
String user = options.getLoginUser();
if (user == null && node.getCredentials() != null) {
user = node.getCredentials().getUser();
}
List<Statement> bootstrap = newArrayList();
if (options.getPublicKey() != null)
bootstrap.add(new AuthorizeRSAPublicKeys(ImmutableSet.of(options.getPublicKey())));
bootstrap.add(new AuthorizeRSAPublicKeys(ImmutableSet.of(options.getPublicKey()), user));
if (options.getRunScript() != null)
bootstrap.add(options.getRunScript());
if (options.getPrivateKey() != null)

View File

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.functions;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.inject.ImplementedBy;
/**
* Returns the statement to be executed on the node.
*/
@ImplementedBy(InstallKeysAndRunScript.class)
public interface NodeAndTemplateOptionsToStatement {
/**
* Returns the script that has to be executed in the given node.
*
* @return The script to be executed or <code>null</code> if no script needs
* to be run.
*/
@Nullable
Statement apply(NodeMetadata node, TemplateOptions options);
}

View File

@ -14,29 +14,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.digitalocean2.compute.functions;
package org.jclouds.compute.functions;
import javax.inject.Singleton;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.scriptbuilder.InitScript;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
import com.google.common.collect.ImmutableList;
/**
* Convert the template options into a statement, but ignoring the public key.
* Convert the node and template options into a statement, but ignoring the
* public key.
* <p>
* The {@link org.jclouds.DigitalOcean2ComputeServiceAdapter.compute.strategy.DigitalOceanComputeServiceAdapter} already takes care of
* installing it using the {@link org.jclouds.digitalocean.features.KeyPairApi}.
* Providers that can install the public key using their API should bind this
* strategy to avoid an unnecessary SSH connection to manually upload it.
*/
@Singleton
public class TemplateOptionsToStatementWithoutPublicKey extends TemplateOptionsToStatement {
public class NodeAndTemplateOptionsToStatementWithoutPublicKey implements NodeAndTemplateOptionsToStatement {
@Override
public Statement apply(TemplateOptions options) {
public Statement apply(NodeMetadata node, TemplateOptions options) {
ImmutableList.Builder<Statement> builder = ImmutableList.builder();
if (options.getRunScript() != null) {
builder.add(options.getRunScript());
@ -55,5 +57,4 @@ public class TemplateOptionsToStatementWithoutPublicKey extends TemplateOptionsT
return null;
}
}

View File

@ -34,6 +34,7 @@ import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.util.OpenSocketFinder;
@ -66,7 +67,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
private final OpenSocketFinder openSocketFinder;
@Nullable
private final Statement statement;
private final NodeAndTemplateOptionsToStatement nodeAndTemplateOptionsToStatement;
private final TemplateOptions options;
private AtomicReference<NodeMetadata> node;
private final Set<NodeMetadata> goodNodes;
@ -78,13 +79,13 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
@AssistedInject
public CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
@Named(TIMEOUT_NODE_RUNNING) Function<AtomicReference<NodeMetadata>, AtomicReference<NodeMetadata>> pollNodeRunning,
OpenSocketFinder openSocketFinder, Function<TemplateOptions, Statement> templateOptionsToStatement,
OpenSocketFinder openSocketFinder, NodeAndTemplateOptionsToStatement nodeAndTemplateOptionsToStatement,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, @Assisted TemplateOptions options,
@Assisted AtomicReference<NodeMetadata> node, @Assisted Set<NodeMetadata> goodNodes,
@Assisted Map<NodeMetadata, Exception> badNodes,
@Assisted Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
this.statement = checkNotNull(templateOptionsToStatement, "templateOptionsToStatement").apply(
checkNotNull(options, "options"));
this.nodeAndTemplateOptionsToStatement = checkNotNull(nodeAndTemplateOptionsToStatement,
"nodeAndTemplateOptionsToStatement");
this.pollNodeRunning = checkNotNull(pollNodeRunning, "pollNodeRunning");
this.initScriptRunnerFactory = checkNotNull(initScriptRunnerFactory, "initScriptRunnerFactory");
this.openSocketFinder = checkNotNull(openSocketFinder, "openSocketFinder");
@ -99,11 +100,11 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
public CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
@Named(TIMEOUT_NODE_RUNNING) Function<AtomicReference<NodeMetadata>, AtomicReference<NodeMetadata>> pollNodeRunning,
GetNodeMetadataStrategy getNode, OpenSocketFinder openSocketFinder,
Function<TemplateOptions, Statement> templateOptionsToStatement,
NodeAndTemplateOptionsToStatement nodeAndTemplateOptionsToStatement,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, @Assisted TemplateOptions options,
@Assisted Set<NodeMetadata> goodNodes, @Assisted Map<NodeMetadata, Exception> badNodes,
@Assisted Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
this(pollNodeRunning, openSocketFinder, templateOptionsToStatement, initScriptRunnerFactory, options,
this(pollNodeRunning, openSocketFinder, nodeAndTemplateOptionsToStatement, initScriptRunnerFactory, options,
new AtomicReference<NodeMetadata>(null), goodNodes, badNodes, customizationResponses);
}
@ -115,6 +116,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Cal
try {
if (options.shouldBlockUntilRunning()) {
pollNodeRunning.apply(node);
Statement statement = nodeAndTemplateOptionsToStatement.apply(node.get(), options);
if (statement != null) {
RunScriptOnNode runner = initScriptRunnerFactory.create(node.get(), statement, options, badNodes).call();
if (runner != null) {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.digitalocean2.compute.functions;
package org.jclouds.compute.functions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -31,18 +31,17 @@ import org.jclouds.ssh.SshKeys;
import org.testng.annotations.Test;
/**
* Unit tests for the {@link TemplateOptionsToStatementWithoutPublicKey} class.
* Unit tests for the {@link NodeAndTemplateOptionsToStatementWithoutPublicKey} class.
*/
@Test(groups = "unit", testName = "TemplateOptionsToStatementWithoutPublicKeyTest")
public class TemplateOptionsToStatementWithoutPublicKeyTest {
@Test(groups = "unit", testName = "NodeAndTemplateOptionsToStatementWithoutPublicKeyTest")
public class NodeAndTemplateOptionsToStatementWithoutPublicKeyTest {
@Test
public void testPublicKeyDoesNotGenerateAuthorizePublicKeyStatementIfOnlyPublicKeyOptionsConfigured() {
Map<String, String> keys = SshKeys.generate();
TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public"));
TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
assertNull(function.apply(options));
NodeAndTemplateOptionsToStatementWithoutPublicKey function = new NodeAndTemplateOptionsToStatementWithoutPublicKey();
assertNull(function.apply(null, options));
}
@Test
@ -50,8 +49,8 @@ public class TemplateOptionsToStatementWithoutPublicKeyTest {
Map<String, String> keys = SshKeys.generate();
TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public")).runScript("uptime");
TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
Statement statement = function.apply(options);
NodeAndTemplateOptionsToStatementWithoutPublicKey function = new NodeAndTemplateOptionsToStatementWithoutPublicKey();
Statement statement = function.apply(null, options);
assertEquals(statement.render(OsFamily.UNIX), "uptime\n");
}
@ -62,8 +61,8 @@ public class TemplateOptionsToStatementWithoutPublicKeyTest {
TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public"))
.installPrivateKey(keys.get("private")).runScript("uptime");
TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
Statement statement = function.apply(options);
NodeAndTemplateOptionsToStatementWithoutPublicKey function = new NodeAndTemplateOptionsToStatementWithoutPublicKey();
Statement statement = function.apply(null, options);
assertTrue(statement instanceof StatementList);
StatementList statements = (StatementList) statement;

View File

@ -32,7 +32,8 @@ import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
import org.jclouds.compute.functions.InstallKeysAndRunScript;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.util.OpenSocketFinder;
import org.jclouds.scriptbuilder.domain.Statement;
@ -53,7 +54,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
public void testBreakOnIllegalStateExceptionDuringPollNode() {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory = createMock(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class);
OpenSocketFinder openSocketFinder = createMock(OpenSocketFinder.class);
Function<TemplateOptions, Statement> templateOptionsToStatement = new TemplateOptionsToStatement();
NodeAndTemplateOptionsToStatement nodeAndTemplateOptionsToStatement = new InstallKeysAndRunScript();
@SuppressWarnings("unused")
Statement statement = null;
TemplateOptions options = new TemplateOptions();
@ -79,7 +80,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
// run
AtomicReference<NodeMetadata> atomicNode = Atomics.newReference(pendingNode);
new CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(pollNodeRunning, openSocketFinder,
templateOptionsToStatement, initScriptRunnerFactory, options, atomicNode, goodNodes, badNodes,
nodeAndTemplateOptionsToStatement, initScriptRunnerFactory, options, atomicNode, goodNodes, badNodes,
customizationResponses).apply(atomicNode);
assertEquals(goodNodes.size(), 0);
@ -95,7 +96,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
int portTimeoutSecs = 2;
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory = createMock(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class);
OpenSocketFinder openSocketFinder = createMock(OpenSocketFinder.class);
Function<TemplateOptions, Statement> templateOptionsToStatement = new TemplateOptionsToStatement();
NodeAndTemplateOptionsToStatement nodeAndTemplateOptionsToStatement = new InstallKeysAndRunScript();
TemplateOptions options = new TemplateOptions().blockOnPort(22, portTimeoutSecs);
Set<NodeMetadata> goodNodes = Sets.newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
@ -124,7 +125,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
// run
AtomicReference<NodeMetadata> atomicNode = Atomics.newReference(pendingNode);
new CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(pollNodeRunning, openSocketFinder,
templateOptionsToStatement, initScriptRunnerFactory, options, atomicNode, goodNodes, badNodes,
nodeAndTemplateOptionsToStatement, initScriptRunnerFactory, options, atomicNode, goodNodes, badNodes,
customizationResponses).apply(atomicNode);
assertEquals(goodNodes.size(), 0);

View File

@ -219,6 +219,7 @@ END_OF_JCLOUDS_SCRIPT
publicKey
END_OF_JCLOUDS_FILE
chmod 600 /home/users/defaultAdminUsername/.ssh/authorized_keys
chown -R defaultAdminUsername /home/users/defaultAdminUsername/.ssh
chown -R defaultAdminUsername /home/users/defaultAdminUsername
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -219,6 +219,7 @@ END_OF_JCLOUDS_SCRIPT
publicKey
END_OF_JCLOUDS_FILE
chmod 600 /home/users/web/.ssh/authorized_keys
chown -R web /home/users/web/.ssh
chown -R web /home/users/web
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -100,6 +100,7 @@ END_OF_JCLOUDS_SCRIPT
publicKey
END_OF_JCLOUDS_FILE
chmod 600 /over/ridden/foo/.ssh/authorized_keys
chown -R foo /over/ridden/foo/.ssh
chown -R foo /over/ridden/foo
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -32,7 +32,8 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
@ -45,7 +46,6 @@ import org.jclouds.digitalocean2.compute.functions.DropletToNodeMetadata;
import org.jclouds.digitalocean2.compute.functions.ImageInRegionToImage;
import org.jclouds.digitalocean2.compute.functions.RegionToLocation;
import org.jclouds.digitalocean2.compute.functions.SizeToHardware;
import org.jclouds.digitalocean2.compute.functions.TemplateOptionsToStatementWithoutPublicKey;
import org.jclouds.digitalocean2.compute.internal.ImageInRegion;
import org.jclouds.digitalocean2.compute.options.DigitalOcean2TemplateOptions;
import org.jclouds.digitalocean2.compute.strategy.CreateKeyPairsThenCreateNodes;
@ -91,7 +91,7 @@ public class DigitalOcean2ComputeServiceContextModule extends
bind(CreateNodesInGroupThenAddToSet.class).to(CreateKeyPairsThenCreateNodes.class);
bind(TemplateOptions.class).to(DigitalOcean2TemplateOptions.class);
bind(TemplateOptionsToStatement.class).to(TemplateOptionsToStatementWithoutPublicKey.class);
bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
bind(new TypeLiteral<ImageExtension>() {
}).to(DigitalOcean2ImageExtension.class);

View File

@ -231,7 +231,7 @@ public class UserAdd implements Statement {
if (!authorizeRSAPublicKeys.isEmpty() || installRSAPrivateKey != null) {
String sshDir = homeDir + "{fs}.ssh";
if (!authorizeRSAPublicKeys.isEmpty())
statements.add(new AuthorizeRSAPublicKeys(sshDir, authorizeRSAPublicKeys));
statements.add(new AuthorizeRSAPublicKeys(sshDir, authorizeRSAPublicKeys, login));
if (installRSAPrivateKey != null)
statements.add(new InstallRSAPrivateKey(sshDir, installRSAPrivateKey));
}

View File

@ -22,6 +22,7 @@ import static org.jclouds.scriptbuilder.domain.Statements.exec;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
@ -34,14 +35,20 @@ import com.google.common.collect.ImmutableList.Builder;
public class AuthorizeRSAPublicKeys implements Statement {
private final String sshDir;
private final List<String> publicKeys;
private final String owner;
public AuthorizeRSAPublicKeys(Iterable<String> publicKeys) {
this("~/.ssh", publicKeys);
this("~/.ssh", publicKeys, null);
}
public AuthorizeRSAPublicKeys(Iterable<String> publicKeys, @Nullable String owner) {
this("~/.ssh", publicKeys, owner);
}
public AuthorizeRSAPublicKeys(String sshDir, Iterable<String> publicKeys) {
public AuthorizeRSAPublicKeys(String sshDir, Iterable<String> publicKeys, @Nullable String owner) {
this.sshDir = checkNotNull(sshDir, "sshDir");
this.publicKeys = ImmutableList.copyOf(checkNotNull(publicKeys, "publicKeys"));
this.owner = owner;
}
@Override
@ -59,6 +66,9 @@ public class AuthorizeRSAPublicKeys implements Statement {
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));
if (owner != null) {
statements.add(exec(String.format("chown -R %s %s", owner, sshDir)));
}
return new StatementList(statements.build()).render(family);
}
}

View File

@ -70,7 +70,7 @@ public class UserAddTest {
public void testWithSshAuthorizedKeyUNIX() {
assertEquals(
UserAdd.builder().login("me").authorizeRSAPublicKey("rsapublickey").build().render(OsFamily.UNIX),
"mkdir -p /home/users\nchmod 0755 /home/users\nuseradd -c me -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\ncat >> /home/users/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n\trsapublickey\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/authorized_keys\nchown -R me /home/users/me\n");
"mkdir -p /home/users\nchmod 0755 /home/users\nuseradd -c me -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\ncat >> /home/users/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n\trsapublickey\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/authorized_keys\nchown -R me /home/users/me/.ssh\nchown -R me /home/users/me\n");
}
public void testWithSshInstalledKeyUNIX() {

View File

@ -27,6 +27,17 @@ import com.google.common.collect.ImmutableSet;
public class AuthorizeRSAPublicKeyTest {
public void testAuthorizeRSAPublicKeyUNIXCurrentUser() {
assertEquals(
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB"), "jclouds").render(OsFamily.UNIX),
"mkdir -p ~/.ssh\n" +
"cat >> ~/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n" +
"\tssh-dss AAAAB\n" +
"END_OF_JCLOUDS_FILE\n" +
"chmod 600 ~/.ssh/authorized_keys\n" +
"chown -R jclouds ~/.ssh\n");
}
public void testAuthorizeRSAPublicKeyUNIXNoOwner() {
assertEquals(
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.UNIX),
"mkdir -p ~/.ssh\n" +
@ -38,29 +49,31 @@ public class AuthorizeRSAPublicKeyTest {
public void testAuthorizeRSAPublicKeyUNIXCurrentUserWith2Keys() {
assertEquals(
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD")).render(OsFamily.UNIX),
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD"), "jclouds").render(OsFamily.UNIX),
"mkdir -p ~/.ssh\n" +
"cat >> ~/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n" +
"\tssh-dss AAAAB\n" +
"\t\n" +
"\tssh-dss CCCCD\n" +
"END_OF_JCLOUDS_FILE\n" +
"chmod 600 ~/.ssh/authorized_keys\n");
"chmod 600 ~/.ssh/authorized_keys\n" +
"chown -R jclouds ~/.ssh\n");
}
public void testAuthorizeRSAPublicKeyUNIXSpecifiedDir() {
assertEquals(
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.UNIX),
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB"), "jclouds").render(OsFamily.UNIX),
"mkdir -p /home/me/.ssh\n" +
"cat >> /home/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n" +
"\tssh-dss AAAAB\n" +
"END_OF_JCLOUDS_FILE\n" +
"chmod 600 /home/me/.ssh/authorized_keys\n");
"chmod 600 /home/me/.ssh/authorized_keys\n" +
"chown -R jclouds /home/me/.ssh\n");
}
public void testAuthorizeRSAPublicKeyUNIXSpecifiedDirWith2Keys() {
assertEquals(
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD"))
new AuthorizeRSAPublicKeys("/home/me/.ssh", ImmutableSet.of("ssh-dss AAAAB", "ssh-dss CCCCD"), "jclouds")
.render(OsFamily.UNIX),
"mkdir -p /home/me/.ssh\n" +
"cat >> /home/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n" +
@ -68,11 +81,12 @@ public class AuthorizeRSAPublicKeyTest {
"\t\n" +
"\tssh-dss CCCCD\n" +
"END_OF_JCLOUDS_FILE\n" +
"chmod 600 /home/me/.ssh/authorized_keys\n");
"chmod 600 /home/me/.ssh/authorized_keys\n" +
"chown -R jclouds /home/me/.ssh\n");
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testAuthorizeRSAPublicKeyWINDOWS() {
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB")).render(OsFamily.WINDOWS);
new AuthorizeRSAPublicKeys(ImmutableSet.of("ssh-dss AAAAB"), "jclouds").render(OsFamily.WINDOWS);
}
}

View File

@ -15,6 +15,7 @@ cat >> /home/users/defaultAdminUsername/.ssh/authorized_keys <<'END_OF_FILE'
publicKey
END_OF_FILE
chmod 600 /home/users/defaultAdminUsername/.ssh/authorized_keys
chown -R defaultAdminUsername /home/users/defaultAdminUsername/.ssh
chown -R defaultAdminUsername /home/users/defaultAdminUsername
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -14,6 +14,7 @@ cat >> /over/ridden/foo/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'
fooPublicKey
END_OF_JCLOUDS_FILE
chmod 600 /over/ridden/foo/.ssh/authorized_keys
chown -R foo /over/ridden/foo/.ssh
chown -R foo /over/ridden/foo
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -14,6 +14,7 @@ cat >> /over/ridden/foo/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'
fooPublicKey
END_OF_JCLOUDS_FILE
chmod 600 /over/ridden/foo/.ssh/authorized_keys
chown -R foo /over/ridden/foo/.ssh
chown -R foo /over/ridden/foo
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no

View File

@ -6,6 +6,7 @@ cat >> /home/users/defaultAdminUsername/.ssh/authorized_keys <<-'END_OF_JCLOUDS_
publicKey
END_OF_JCLOUDS_FILE
chmod 600 /home/users/defaultAdminUsername/.ssh/authorized_keys
chown -R defaultAdminUsername /home/users/defaultAdminUsername/.ssh
mkdir -p /home/users/defaultAdminUsername/.ssh
rm /home/users/defaultAdminUsername/.ssh/id_rsa
cat >> /home/users/defaultAdminUsername/.ssh/id_rsa <<-'END_OF_JCLOUDS_FILE'

View File

@ -14,6 +14,7 @@ cat >> /home/users/defaultAdminUsername/.ssh/authorized_keys <<-'END_OF_JCLOUDS_
publicKey
END_OF_JCLOUDS_FILE
chmod 600 /home/users/defaultAdminUsername/.ssh/authorized_keys
chown -R defaultAdminUsername /home/users/defaultAdminUsername/.ssh
chown -R defaultAdminUsername /home/users/defaultAdminUsername
exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
PermitRootLogin no