How to make a sudo command using Paramiko - python

I am having some problems with commands that have sudo using paramiko
f.ex sudo apt-get update
here is my code:
try:
import paramiko
except:
try:
import paramiko
except:
print "There was an error with the paramiko module"
cmd = "sudo apt-get update"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect("ip",username="lexel",password="password")
print "succesfully conected"
except:
print "There was an Error conecting"
stdin, stdout, stderr = ssh.exec_command(cmd)
stdin.write('password\n')
stdin.flush()
print stderr.readlines()
print stdout.readlines()
This is a quick code. I know that I need to add sys.exit(1) and all that but this is just to demostration
I used this for reference:
Jessenoller.com

Fabric has sudo command. It uses Paramico for ssh connections. Your code would be:
#fabfile.py
from fabric.api import run, sudo
def update():
"""Run `sudo apt-get update`.
lorem ipsum
"""
sudo("apt-get update")
def hostname():
"""Run `hostname`"""
run("hostname")
Usage:
$ fab update -H example.com
[example.com] Executing task 'update'
[example.com] sudo: apt-get update
...snip...
[example.com] out: Reading package lists... Done
[example.com] out:
Done.
Disconnecting from example.com... done.
$ fab --display update
Displaying detailed information for task 'update':
Run `sudo apt-get update`.
lorem ipsum
$ fab --list
Available commands:
hostname Run `hostname`
update Run `sudo apt-get update`.
From the docs:
In addition to use via the fab tool, Fabric’s components may be
imported into other Python code, providing a Pythonic interface to the
SSH protocol suite at a higher level than that provided by e.g.
Paramiko (which Fabric itself leverages.)

I was having the same problem, and I fix with this:
In your sudo file, just add this:
Defaults:your_username !requiretty
or remove Defaults requiretty.
Also make sure your user have permission to run the command with sudo.

Related

How fabric work with 'sudo su user'

My request is simple:
ssh to a remote server with user0
switch user to user1 using: 'sudo su user1'
list all items in current folder
My expected code:
def startRedis():
run('sudo su - user1')
print(run('ls'))
However, it ends with out: user1#server:~$
And waiting for my interactive command forever, never executing the second line. It seems sudo su opened a new shell.
Can anyone help solving this simple task?
You can set sudo_user property in env. this way fabric will switch user to the desired user.
Official doc: http://docs.fabfile.org/
Password for switching user can be specified in the env. itself to avoid getting a prompt when the method is invoked.
fabfile.py
from fabric.api import env, sudo
env.sudo_user='user1'
env.password = '***'
def list_items():
sudo('ls')
Run below command & specify the hosts after -H
fab -H host1 list_items

remotely executing multiple shell commands including "df -h" using root user in python

I want to do the following thing :
if condition:
cmd="ssh machine1 && sudo su - && df -h PathThatRequiresRootPriv | grep ..."
proc = subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,env=os.environ)
(out_space,err) = proc.communicate()
if err:
print err
log.warning('%s',err)
exit(1)
But i am clearly missing something because the program doesn't do anything.
Thank you for your help in advance.
You are building commands in the form cmd1 && cmd2 && cmd3. The 3 commands are executed one at a time on the local machine unless one of them return false. And from your title it is not what you expect... And the construct sudo su - will act the same and expect its commands from its own standard input and not from the next command.
The correct way here would be:
if condition:
loc_cmd="ssh machine1"
remcmd="sudo -i 'df -h PathThatRequiresRootPriv | grep ...'"
proc = subprocess.Popen(loc_cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,env=os.environ)
(out_space,err) = proc.communicate(rem_cmd)
Say differently, you should only execute ssh on the local machine, pass sudo -i to the remote as a request to execute a command after simulating an initial login, and finally pass the pipeline as the parameter to sudo.
You must look fabric - if you want use python
or ansible
in fabric you can do different things on remote server like this:
from fabric.api import *
def check_disk_space(username, passw='none'):
host = '%s#%s' % (env.user, env.host)
env.passwords[host] = 'rootPass'
# run from user
run('df -h')
# run from sudo
sudo('df -h')
host='anyuser#10.10.10.101'
execute(check_disk_space, hosts=[host], username='anyuser', passw='')
Both support 'become' methods for execute remote commands through sudo

fabric difference sudo() run('sudo cmd')

I'm wondering what is the difference between the function sudo() and the function run('sudo -u user smth')
On the doc there is :
sudo is identical in every way to run, except that it will always wrap
the given command in a call to the sudo program to provide superuser
privileges.
But a few time, sudo('cmd') prompt me a password, but if I switch with run('sudo cmd') it works without prompting me anything. Is there anything that change between the two ? (I remember someone on SO saying that sudo and run(sudo cmd) are not for the same use, but I can't find it back)
I found these two difference.
1: Fabric maintains an in-memory password
2: sudo accepts additional user and group arguments
First, fabric would get password from cache when using sudo(), then you do not need to enter password. But if you use run('sudo cmd'), you need to enter password for each 'sudo cmd'.
Second, if you want to execute a command not under root but other user group like www, you just need to set env.sudo_user = 'www' or sudo('cmd', user='www'). The first would execute each sudo() under www, the second would execute this single cmd under www. But you need to edit to run("sudo -u 'www' cmd") when use run() command.
from fabric.api import sudo, run, env
env.hosts = ['host_ip',]
env.user = 'user_name'
env.sudo_user = 'sudo_user'
def test_1():
run('sudo pwd')
def test_2():
sudo('pwd')
$ fab -I --show=debug test_1 test_2
Initial value for env.password: # enter password
Commands to run: test_1, test_2
Parallel tasks now using pool size of 1
[ip_address] Executing task 'test_1'
[ip_address] run: /bin/bash -l -c "sudo pwd"
[ip_address] out: [sudo] password for billy: # needs to enter password here
[ip_address] out: /home/billy
[ip_address] out:
Parallel tasks now using pool size of 1
[ip_address] Executing task 'test_2'
[ip_address] sudo: sudo -S -p 'sudo password:' -u "root" /bin/bash -l -c "pwd"
[ip_address] out: sudo password: # only prompt, do not need enter password
[ip_address] out: /home/billy
[ip_address] out:
Done.
Disconnecting from ip_address... done.
Since Fabric 2, you can invoke sudo via run(), which will prompt for the password unless you use the auto-responder, details here. Note that the sudo command usually caches the password remotely, so next invocations of sudo during the same connection will not prompt for password.
However, the Fabric sudo() helper makes using sudo much easier, details here. You need to ensure that the sudo.password configuration value is filled in (via config object, config file, environment variable, or --prompt-for-sudo-password). Here's how I do it with the keyring module:
from fabric import task
import keyring
#task
def restart_apache(connection):
# set the password with keyring.set_password('some-host', 'some-user', 'passwd')
connection.config.sudo.password = keyring.get_password(connection.host, 'some-user')
connection.sudo('service apache2 restart')

Python - Using Fabric with Sudo

I'm pretty new to python and fabric and I am trying to do a simple code where I can get the output on two hosts that uses sudo, although I keep getting an error.... Can anyone help me out with what I might be missing ?
My code:
from fabric.api import *
from getpass import getpass
from fabric.decorators import runs_once
env.hosts = ['host1','host2']
env.port = '22'
env.user = 'username'
env.password="password"
def sudo_dsmc(cmd):
sudo("-l")
When I run: fab sudo_dsmc:"-1" :
MacBookPRO:PYTHON username$ fab sudo_dsmc:"-l"
[host1] Executing task 'sudo_dsmc'
[host1] sudo: -l
[host1] out: sudo password:
[host1] out: Sorry, user username is not allowed to execute '/bin/bash -l -c - l' as root on host1.
[host1] out:
Fatal error: sudo() received nonzero return code 1 while executing!
Requested: -l
Executed: sudo -S -p 'sudo password:' /bin/bash -l -c "-l"
Aborting.
Disconnecting from host1... done.
Although I can run the apt-get update with my below function fine without any errors:
def sudo_command(cmd):
sudo("apt-get update")
# run like: fab sudo_command:"apt-get-update"
It looks like your sudoers file is preventing you from running that command as sudo. Check your /etc/sudoers file and read the sudo documentation.
Also "-l" isn't a valid command. sudo takes -l as an optional flag (which lists commands allowed by the user). But Fabric's sudo appears to be taking unknown strings and routing them through /bin/bash instead of using them directly as sudo command parameters.

how to run sudo command in paramiko module in python scripts in remote machine

My scenario is I need to login to a remote machine and then do a sudo to another account like (sudo su anotheract) and then run the other required command.
But I am able to successfully connect to remote machine using below script. But the scripts hangs in the line where I am executing the sudo command(sudo su anotheract)
Can you please help me find the fix for this code?
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
ssh.connect(hostname='XX.XXX.XX.XX',port=22, username='myname',password='XXXXX')
ssh.exec_command=("sudo su anotheract")
stdout,stdin,stderr=ssh.exec_command("java -jar /usr/share/XXX/LogR.jar")
print stdout.readlines()
One (not very safe) way to do it is to pipe the password in. The caveat is that the user that you are using to connect to the box using paramiko should have sudo rights.
For example:
supass = 'some_pass'
stdout, stdin, stderr = ssh.exec_command('echo %s | sudo -S anotheract' % supass)
Again, this is not a very safe implementation but gets the job done in a jiffy.
import pxssh
ssh = pxssh.pxssh()
ssh.login('host', 'user', 'password')
ssh.sendline("sudo su anotheract")
ssh.prompt('yourrootpassword')
And in paramiko on most linux systems you cant do sudo commands thats because sudo expect commands from tty and then it isnt raise exception, but you can try method invokeshell, but I used paramiko many years ago I dont remember what was been wrong with it. If you want send various commands on shell you could use pxssh.
It can hangen because sudo waits for password. Try to add NOPASSWD: statement to the /etc/sudoers.
user ALL = NOPASSWD: /bin/true
Also it is impossible to change user using su and then continue do to something after su is finished. When su is finished, you are back to your original shell of the original user.
So you need to run all commands with sudo:
stdout,stdin,stderr = ssh.exec_command=("sudo -u anotheract java -jar /usr/share/XXX/LogR.jar")

Categories

Resources