switch to different user using fabric
Asked Answered
S

2

11

I recently started looking at fabric for remote deployment. I need to switch to a diff user (from the one that I login as) and am not able to figure it out. Is it even possible, if so how? My current user doesnt have sudo permissions.

I tried changing following environment variables

env.sudo_prefix = "su newUser -c "
env.sudo_prompt = "Password:"

But fabric does not wait for password input for 'newUser' and fails.

out: Password: 
[[email protected]] out: su: incorrect password

Fatal error: sudo() received nonzero return code 1 while executing!

Requested: touch x
Executed: su newUser -c  -u "root"  /bin/bash -l -c "cd /home/oldUser/upgrade && touch x"

Aborting.
Disconnecting from [email protected]... done.

Update:

As J.F. Sebastian suggested, su newUser -c works, but it prompts password for every command for every server, which kind of defeats the purpose of automation. Is there any way in Fabric to pass in same value based on prompt (in this case, its always Password:)

Sse answered 28/9, 2012 at 14:0 Comment(10)
have you tried sudo('su newuser')Tangleberry
yes, I did. Problem is that oldUser is not a sudoer, so any sudo command fails with [out: oldUser is not in the sudoers file. This incident will be reported.]Sse
that would have been most logical option to try, but unfortunately no :(Sse
the docs say that it should work without any customization i.e., run('su newuser -c command') works as expected. What is your fabric version?Tangleberry
Yes, only problem with this command is that it prompts for password for every run command per server (Fabric cant store this as password). Which in a way defeats the purpose of the script.Sse
have you tried env.password in addition to your env.sudo_*? Though fabric uses -S in default sudo prefix i.e., it passes the password via stdin therefore su might not work if it reads the password from a tty directly.Tangleberry
env.password is for initial login. I am using it currently.Sse
the docs say that it is also used for sudoTangleberry
That is correct, sudo is for current user and hence same password would work. In case of su, its a diff user and hence diff password would be needed. There is no other placeholder for that.Sse
could you change env.password temporarily: with settings(password=newuser_password): sudo(command)?Tangleberry
S
11

Thanks J F Sebastian, There were couple of catches.

  1. Fabric makes connections lazily, so I had to make a dummy connection before invoking su to avoid context switch.
  2. Pwd need to be stored in global scope and so that it can be reused. Fabric doesnt put it in cache for overridden su command.

Here is what ended up doing. Its working.

pwd = None
@hosts('myhost.com')
def test():
    with cd('/home/oldUser/upgrade'):
        run('ls')  #This is to connect aggressively (instead of lazily)
        global pwd  #Change the scope of pwd
        if pwd is None:
            pwd = getpass.getpass('enter password for newUser')

        execute(su, pwd, 'newUser', 'touch x')  
        run ('ls')
        execute(su, pwd, 'newUser', 'rm x') 
        run ('ls')

def su(pwd, user, command):
    with settings(
        password= "%s" % pwd,
        sudo_prefix="su %s -c " % user,
        sudo_prompt="Password:"
        ):
        sudo(command)
Sse answered 28/9, 2012 at 22:58 Comment(0)
T
7

If you can't ssh as newuser and can't use sudo(command, user='newuser'):

import getpass # just for demonstration
from fabric.api import sudo, settings

def su(user, command):
    with settings(password=getpass.getpass('enter password for %s: ' % user),
                  sudo_prefix="su %s -c " % user,
                  sudo_prompt="Password:"):
        sudo(command)
Tangleberry answered 28/9, 2012 at 18:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.