Automating switching from regular user to root with subprocess in python

Question:

I am trying to execute a cmd that is being read from the PostgreSQL db. I can manually switch to root, then switch to the postgre user and access the information I desire.

The problem is when I run this it just hangs and nothing happens.

I have a root password and you will need this when switching from the current user. But I am not prompted to enter it.

How can I get this not to hang and the password will be prompted?

The code below does just 'ls' for simplicity.

Code:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist

      

Update one:

I can't seem to use any library where a dose won't ship with python 2.7 on Linux SUSE. I just need to execute the command and exit.

Update two:

I am unable to run the script as root as I need to do other tasks that require me not to be root.

Update three:

As per LeBarton's suggestions, I have a script to log into root, although the ls command is never run as root, it runs as the user I was originally. When I run the command, I am prompted for the root password and go from "@host" to "host", which cannot execute any command other than exit. When I exit all commands the execution of which is output.

I don't want to store the user's password in code like LeBarton has. How can I execute the command as root and go back and continue the rest of the script without getting stuck on new users and you will need to type "exit".

"stderr = subprocess.STDOUT" was apparently causing it to hang.

code:

if __name__ == '__main__':
    def subprocess_cmd(command):
        process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
        proc_stdout = process.communicate()[0].strip()
        print proc_stdout

    subprocess_cmd('echo a; su - root; ls; cd;ls;')

...continue with rest of script where I execute commands as original user 

      

Answer:

Thanks to the troika for his excellent answer.

I achieved what I decided to do with the following code:

if __name__ == '__main__':
    def subprocess_cmd(command):
        process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=False)
        proc_stdout = process.communicate()[0].strip()
        print proc_stdout

    subprocess_cmd(['su','-','root','-c','su -s /bin/sh  postgres -c \'psql -U msa ..........])

      

I just needed to execute the command that I was running as root after -c. So now it switches to the postgres user and finds the data it needs after returning root to normal users after.

+3


source to share


3 answers


You don't understand what it is doing su

. su

creates a privileged subprocess; it does not change the privileges of your current process. The commands afterwards su

will be executed upon completion su

with your normal privileges.

Instead, you want to pass a parameter -c

to specify the commands that you want to run with elevated privileges. (See also the su

man page
.)

popen_cmd_shell('su -c ls - root')

      

sudo

was specifically designed to simplify this sort of thing, so you should probably use that instead.

Scripting access to privileged commands is a sticky topic. One common approach is to have your team perform a privileged operation and then drop its privileges. From both a security and design perspective, this approach tends to oversimplify the overall logic. You have to make sure that your privileged code is as simple and short as possible - no parsing in the privileged section, for example.



Once privileged code is properly tested, validated, and frozen, providing a script with the required privileges should be straightforward (although many organizations are paranoid and basically fail to establish a workable policy for this sort of thing).

Regardless of which approach you take, you should definitely avoid anything with shell=True

in any security-sensitive context, and instead pass any external commands as a list rather than as a single line.

popen_cmd_shell(['su', '-c', 'ls', '-', 'root'])

      

(Maybe rename the function as well, since you don't specifically want a wrapper. Obviously, change the function to indicate too shell=False

.)

Again, these security considerations have to do with whether you are escalating with delete privileges or requesting privilege escalation via su

or sudo

.

+3


source


Your team is

su - root; ls;

      

The shell interprets this as

"su -root; ls;"

      

You probably don't have an executable with this exact name with spaces.



Try to split it into a list with

['su', '-', 'root', ';', 'ls', ';' ]

      

EDIT

stdout=subprocess.PIPE,

causes the program to hang. If you are trying to pass a password, use process.communicate('root password')

.

+1


source


Do you just want to access PostgreSQL database? If so, you don't need to use the command line at all ...

The psycopg2 python library will allow you to send commands to the PostgreSQL server, for more details on this: https://wiki.postgresql.org/wiki/Psycopg2_Tutorial

However, I recommend ORMs like SQLAlchemy, they make communicating with the database a trivial task.

0


source







All Articles