Skip to content
Browse files
Fix SoftwareProcess.dontRequireTtyForSudo
- it doesn't directly edit /etc/sudoers
- uses visudo to verify the prepared file
- added integration test
  • Loading branch information
ygy committed Nov 26, 2015
1 parent b03f77e commit af36c7f77621a428179646210302080f766b89c1
Showing 3 changed files with 62 additions and 1 deletion.
@@ -36,6 +36,7 @@
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.core.task.BasicExecutionContext;
import org.apache.brooklyn.util.core.task.ssh.SshTasks;
import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
@@ -72,6 +73,7 @@ public class BashCommandsIntegrationTest {
private File sourceNonExistantFile;
private File sourceFile1;
private File sourceFile2;
private File tmpSudoersFile;
private String sourceNonExistantFileUrl;
private String sourceFileUrl1;
private String sourceFileUrl2;
@@ -108,6 +110,11 @@ public void setUp() throws Exception {
Files.write("mylocal1".getBytes(), localRepoEntityFile);

tmpSudoersFile = Os.newTempFile(getClass(), "sudoers" + Identifiers.makeRandomId(8));

String sudoers = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/ssh/test_sudoers");
Files.write(sudoers.getBytes(), tmpSudoersFile);

loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();

@@ -117,11 +124,33 @@ public void tearDown() throws Exception {
if (sourceFile2 != null) sourceFile2.delete();
if (destFile != null) destFile.delete();
if (localRepoEntityFile != null) localRepoEntityFile.delete();
if (tmpSudoersFile != null) tmpSudoersFile.delete();
if (localRepoEntityBasePath != null) FileUtils.deleteDirectory(localRepoEntityBasePath);
if (loc != null) loc.close();
if (mgmt != null) Entities.destroyAll(mgmt);

public void testRemoveRequireTtyFromSudoersFile() throws Exception {
String cmds = BashCommands.dontRequireTtyForSudo();

ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ByteArrayOutputStream errStream = new ByteArrayOutputStream();

String cmdsWithReplacedSudoersName = Strings.replaceAllNonRegex(cmds, "/etc/sudoers", tmpSudoersFile.getAbsolutePath());
int exitcode = loc.execCommands(ImmutableMap.of("out", outStream, "err", errStream), "removeRequireTtyFromSudoersFile", ImmutableList.of(cmdsWithReplacedSudoersName));

String outstr = new String(outStream.toByteArray());
String errstr = new String(errStream.toByteArray());

assertEquals(0, exitcode);

// visudo returns "parsed OK"
assertTrue(outstr.contains("parsed OK"), "out="+outstr+"; err="+errstr);
assertTrue(errstr.isEmpty(), "out="+outstr+"; err="+errstr);

public void testSudo() throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
@@ -0,0 +1,24 @@
# 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
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Defaults specification

# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
# You have to run "ssh -t hostname sudo <cmd>".
Defaults requiretty
@@ -162,7 +162,15 @@ public static String executeCommandThenAsUserTeeOutputToFile(String commandWhose
* (having a tty for sudo seems like another case of imaginary security which is just irritating.
* like water restrictions at airport security.) */
public static String dontRequireTtyForSudo() {
return ifFileExistsElse0("/etc/sudoers", sudo("sed -i.brooklyn.bak 's/.*requiretty.*/#brooklyn-removed-require-tty/' /etc/sudoers"));
String sudoersFileName = "/etc/sudoers";

// Visudo's quiet mode (-q) is not enabled. visudo's output is used for diagnostic purposes
return ifFileExistsElse0(sudoersFileName,
sudo(format("cp %1$s %1$s.tmp", sudoersFileName)),
sudo(format("sed -i.brooklyn.bak 's/.*requiretty.*/#brooklyn-removed-require-tty/' %1$s.tmp", sudoersFileName)),
sudo(format("visudo -c -f %1$s.tmp", sudoersFileName)),
sudo(format("mv %1$s.tmp %1$s", sudoersFileName))));

/** generates ~/.ssh/id_rsa if that file does not exist */

0 comments on commit af36c7f

Please sign in to comment.