Fabric: How to implement "sudo su -" call?

Created on 29 Oct 2013  ·  9Comments  ·  Source: fabric/fabric

Is it any way to imitate "sudo su - user_name" command and then execute commands I needed?

Tried run and sudo and unfortunately there is no way to make it. Please help

Most helpful comment

@polusok @kusnier I'm working with similar restrictions. you can try passing in your commands this way.

run('echo "whoami" | sudo su - username')

All 9 comments

Is the '-' important in what you are trying to do ? ( eg. invoke a login ) or are you just trying to run a command as a different user other than the current user and root?

If the affect of login is not important then you can do the following...

sudo("mkdir /var/www/new_docroot", user="www-data")

or

   with settings(sudo_user='mysql'):
            sudo("whoami") # prints 'mysql'

or if login is important (hacky way) you could do this I guess...

   sudo("su - usernaeme -c 'command to be run'")

Yes - is important for me. I need to implement

  • log to server with my credentials
  • in shell login as another user with specific permission and configured environment
  • execute command

Please notice that I do have only my account password and I don't have password for those user in step 2 therefore I need to connect thru

sudo su - user_name

Unfortunately, I can't use it as it's prohibitted due to my permissions

sudo("su - usernaeme -c 'command to be run'")
Sorry, user user_name is not allowed to execute '/usr/bin/su - another_user -c pwd' as root on server.

Any other suggestions?

@polusok: Have you found any workaround? I have the same problem. I can only use sudo su - jboss to become jboss user.

@polusok @kusnier I'm working with similar restrictions. you can try passing in your commands this way.

run('echo "whoami" | sudo su - username')

npalrecha, that does appear to work but prompts for the password on each command. Is there really no way to just sudo su - user and run all subsequent commands as that user?

I had the same issue... If you can get the /etc/sudoers file changed, that's probably the easiest solution. Your line probably reads username host = ALL but should read username host = (ALL) ALL.

Here is my workaround for those who can't.
Note that doing sudo(command, user="otheruser") with these solutions will not work.

class Sudosu:
    def __init__(self, user):
        self.user = user

    def __enter__(self):
        self.old_sudo_prefix = env.sudo_prefix
        self.old_sudo_user, env.sudo_user = env.sudo_user, self.user
        env.sudo_prefix = "sudo -S -p '%(sudo_prompt)s' su - %(sudo_user)s -c"

    def __exit__(self, a, b, c):
        env.sudo_prefix = self.old_sudo_prefix
        env.sudo_user = self.old_sudo_user

Use that like...

@task
def test():
    with Sudosu(user=username):
        sudo("whoami")

Alternatively, as a decorator...

def sudosu(user):                                                                        
    def wrap(f):                                                                         
        def inner(*args, **kwargs):                                                      
            old_sudo_prefix = env.sudo_prefix                                            
            old_sudo_user, env.sudo_user = env.sudo_user, user                           
            env.sudo_prefix = "sudo -S -p '%(sudo_prompt)s' su - %(sudo_user)s -c"       

            f(*args, **kwargs)                                                           

            env.sudo_prefix = old_sudo_prefix                                            
            env.sudo_user = old_sudo_user                                                
        inner.__name__ = f.__name__                                                      
        return inner                                                                     
    return wrap                                                                          

Use that like...

@task
@sudosu("username")
def whoami():
    sudo("whoami")

or...

sudo = sudosu("username")(sudo)

@task
def whoami():  
    sudo("whoami")

Whichever way you feel like. My preference is as the context.

Of course, you could just set env.sudo_prefix, but you will need to reset it if you want to do a normal sudo.

Juchiu, I had high hopes but that did not work for me. I basically get the same error that fabric alone was giving. I am on Red Hat Enterprise Linux Server release 5.4 (Tikanga). Npalrecha's solution works it's just not elegant of course.

Error:
Sorry, user xxxx is not allowed to execute '/bin/su - yyyy -c -u
yyyy /bin/bash -l -c whoami' as root on myserver.com.com.

Executed: sudo -S -p 'sudo password:' su - yyyy -c -u "yyyy" /bin/bash -l -c "whoami"

It seems as though it is still trying to pass -u yyyy to sudo. I believe that when you are making your sudo() call, you are still passing in user as a kwarg.

But your error message is interesting, as it seems as though you might not be allowed in sudo to execute su with certain arguments, esp since you are allowed to sudo su - yyyy normally.

FWIW, the arguments didn't seem to make sense to me, but I figured out what was weird.
Sudo seems to have tried to execute the command su - yyyy -c -u "yyyy" /bin/bash -l -c "whoami". Su then seems to try to execute -u "achuser" /bin/bash -l -c "whoami", but is only running whoami because it thinks -c was passed multiple times, and it just takes the last one. I would probably try to avoid having this happen.

This is more mailing list fodder than an actual issue with fabric - going to close as such.

Was this page helpful?
0 / 5 - 0 ratings