Rex icon indicating copy to clipboard operation
Rex copied to clipboard

sudo TRUE; - code gets stuck

Open szabgab opened this issue 10 years ago • 15 comments

When I set sudo TRUE; running rex got stuck. Using -d I fund that the problem is this command

sudo  -p '' -S sh -c "LC_ALL=C ; export LC_ALL; which perl "

being stuck. (It does not even ask for password, probably because of the -p '')

All this because I was trying to restrict the command the user can execute using sudo. I can, of course, add sudo to the individual commands I execute, but I am not sure if this behaviour is correct. shouldn't sudo TRUE; mean every user-generated command is executed with sudo? Why are the internal Rex-commands executed with sudo?

szabgab avatar Nov 02 '14 16:11 szabgab

Hi,

indeed, if sudo TRUE is set, every command gets executed with sudo, not only the commands the user wants to execute in a task.

If you only want to execute some commands with sudo you can do the following:

user "someuser";
sudo_password "the-sudo-password-if-there-is-one";

task "mytask", group => "myserver", sub {
  sudo sub {
    run "execute with sudo";
    pkg "vim-enhanced", ensure => "present"; # also executes with sudo
  };
};

But for sudo, rex is always executing the sudo command with /bin/sh. So currently it is not possible to limit the commands that can be executed with sudo.

There is a feature flag called: sudo_without_sh (http://www.rexify.org/howtos/backward_compatibility.html). With this enabled it is possible to limit the commands, but this will prevent some commands to work correctly (especially file editing).

krimdomu avatar Nov 02 '14 18:11 krimdomu

What we can do, to prevent freezing, we can add a timeout to the which perl command, so that we can detect if sudo needs a password, and then we can display a proper error message.

krimdomu avatar Nov 02 '14 18:11 krimdomu

Such timeout would be great for every command. Not just the internal Rex commands. If the length of the timeout was user configurable, that would be probably even better. Oh I just saw I got a response to a related question I asked on the mailing list: https://groups.google.com/forum/#!topic/rex-users/TT9dwfFvxfE

szabgab avatar Nov 03 '14 06:11 szabgab

There's also a timeout setting for "the ssh connection and other network related stuff", described on this page. Nevertheless the timeout option for run needs to be included in the documentation (and we need to fix the searchbox, thanks for reporting @szabgab! ;)

At the same time, I would prefer to determine whether sudo needs a password in a different way. If there is something that directly checks for it, that would be the best option IMHO (unfortunately nothing like this comes to my mind instantly). As a second option we could try detecting the password prompt, and if there's no sudo_password specified, then we could throw an error about it.

Or if we would like to wait for something to timeout, it might be a good idea to run something very simple that is as closely related to the issue as possible, like sudo -l or sudo -v (i.e. to check if sudo itself times out, not the command it tries to run).

We might only need to run this check when there's no sudo_password specified but sudo is turned on.

ferki avatar Nov 03 '14 07:11 ferki

In the pass_auth cases, we can also try and fallback to use the user's password as sudo_password first, when it is not specified directly.

ferki avatar Nov 03 '14 09:11 ferki

user "someuser";

sudo_password "the-sudo-password-if-there-is-one";

task "mytask", group => "myserver", sub { sudo sub { run "execute with sudo"; pkg "vim-enhanced", ensure => "present"; # also executes with sudo }; };

But for sudo, rex is always executing the sudo command with /bin/sh. So currently it is not possible to limit the commands that can be executed with sudo.

do you mean every sudo will use sh?

even if I write run "sudo command" ?

szabgab avatar Nov 03 '14 12:11 szabgab

@szabgab no, if you use the "run" command, it will execute it the way you write it.

run "sudo id";

Will result in something like:

PATH=/bin/:/usr/bin:/and/some/other/paths/considered/safe sudo id

krimdomu avatar Nov 03 '14 13:11 krimdomu

No way, this is not working. I'm trying

desc "Install git";
task "git", group => "fiware", sub {
    run "sudo apt-get install git";
};

and it still gets stuck. Also whatever has been mentioned above.

JJ avatar Nov 30 '14 11:11 JJ

@JJ

Could you please paste the output of rex -d git?

But please remove all passwords and other secret things from the output.

Thanks

krimdomu avatar Nov 30 '14 12:11 krimdomu

[2014-11-30 12:34:58] DEBUG - Command Line Parameters [2014-11-30 12:34:58] DEBUG - d = 1

[2014-11-30 12:34:58] DEBUG - Rexfile exists [2014-11-30 12:34:58] DEBUG - Checking Rexfile Syntax... [2014-11-30 12:34:58] DEBUG - Found Rexfile.lock [2014-11-30 12:34:58] DEBUG - Found stale lock file. Removing it. [2014-11-30 12:34:58] DEBUG - Creating lock-file (Rexfile.lock) [2014-11-30 12:34:58] DEBUG - Including/Parsing Rexfile [2014-11-30 12:34:58] DEBUG - Registering task: Rex::CLI::git [2014-11-30 12:34:58] DEBUG - Creating new distribution class of type: Base [2014-11-30 12:34:58] DEBUG - new distribution class of type Rex::TaskList::Base created. [2014-11-30 12:34:58] DEBUG - Creating task: git [2014-11-30 12:34:58] DEBUG - Registering task: Rex::CLI::docker [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Creating task: docker [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] WARN - Task docker already exists. Overwriting... [2014-11-30 12:34:58] DEBUG - Creating task: docker [2014-11-30 12:34:58] DEBUG - eval your Rexfile. [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Initializing Logger from parameters found in Rexfile [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Running task: git [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] DEBUG - Returning existing distribution class of type: Rex::TaskList::Base [2014-11-30 12:34:58] INFO - Running task git on 130.206.127.211 [2014-11-30 12:34:58] DEBUG - $VAR1 = '';

[2014-11-30 12:34:58] DEBUG - $VAR1 = { 'auth_type' => 'pass', 'public_key' => undef, 'sudo_password' => '', 'sudo' => 0, 'port' => undef,

      'user' => 'jjmerelo',
      'private_key' => undef
    };

[2014-11-30 12:34:58] DEBUG - Using Net::SSH2 for connection [2014-11-30 12:34:58] DEBUG - Using user: jjmerelo [2014-11-30 12:34:58] DEBUG - Using password: *********** [2014-11-30 12:34:58] INFO - Connecting to 130.206.127.211:22 (jjmerelo) [2014-11-30 12:34:58] DEBUG - Current Error-Code: 0 [2014-11-30 12:34:58] INFO - Connected to 130.206.127.211, trying to authenticate. [2014-11-30 12:34:58] DEBUG - Using password authentication. [2014-11-30 12:35:09] INFO - Successfully authenticated on 130.206.127.211. [2014-11-30 12:35:09] DEBUG - Executing: which perl [2014-11-30 12:35:09] DEBUG - Shell/Bash: Got options: [2014-11-30 12:35:09] DEBUG - $VAR1 = {};

[2014-11-30 12:35:09] DEBUG - SSH/executing: LC_ALL=C ; export LC_ALL; which perl [2014-11-30 12:35:09] DEBUG - /usr/bin/perl

[2014-11-30 12:35:09] DEBUG - Executing git [2014-11-30 12:35:09] DEBUG - Executing: sudo apt-get install git [2014-11-30 12:35:10] DEBUG - Shell/Bash: Got options: [2014-11-30 12:35:10] DEBUG - $VAR1 = { 'auto_die' => undef };

[2014-11-30 12:35:10] DEBUG - SSH/executing: LC_ALL=C ; export LC_ALL; PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/pkg/bin:/usr/pkg/sbin; export PATH; sudo apt-get install git

JJ avatar Nov 30 '14 12:11 JJ

@JJ

could you please try to run "sudo apt-get -y install";.

It seems that the command is waiting for some input.

You can also use the pkg() command to install packages:

desc "Install git";
task "git", group => "fiware", sub {
    sudo sub {
        pkg "git", ensure => 'present';
    };
};

krimdomu avatar Nov 30 '14 18:11 krimdomu

Tried that, and

install "git";

Same problem.

JJ avatar Nov 30 '14 18:11 JJ

@JJ

if you login manually via ssh and run sudo apt-get install -y git does it ask for a password?

krimdomu avatar Nov 30 '14 20:11 krimdomu

I ran into this problem with sudo (on a mac) where it would hang and then was fixed by opening a new bash process. Here is what happened with me:

  1. ran a task with a command as sudo without providing sudo_passowrd
  2. rex hangs (as expected). Ctrl-c to exit.
  3. add sudo_password the_password_here to Rexfile.
  4. run rex command again
  5. rex still hangs
  6. open new bash process.
  7. run rex command again
  8. it works!

sdondley avatar Apr 16 '20 17:04 sdondley

To refresh my earlier comment above, there are quite a few options related to this topic.

Ideally we would be able to determine if sudo needs password or not:

  • if there's a way to determine in advance whether sudo would ask for a password or not (without actually prompting for it), let's use that and either abort or prompt for it interactively
  • otherwise, let's try to detect the output if it prompts for the password, and if there's no sudo_password set, fail with an error (current use of sudo -p might need to be changed; also using Expect wouldn't work on Windows, so would be nice to find some other way)
  • alternatively, let's first call something that is sudo only, like sudo -l or especially sudo -v and let it time out in the worst case - then let it fail with a nice message, or handle some fallback

Alternatively we could try detect potentially weird use cases before the first sudo command is called:

  • if there's no sudo_password specified but sudo is turned on, let's issue a warning/error, prompt for password (optionally with an "I know what I'm doing, I don't need no sudo password" setting that overrides this check)
  • if pass_auth is specified, we can also try and fallback to use the user's password as sudo_password first, when the latter is not specified directly

ferki avatar Oct 01 '20 10:10 ferki