Fabric authentication with kerberos - python

I'm trying to write a fabric function that puts a script on a remote host and runs it as root. I don't have the root password to login to the machine, nor am I a sudoer, but I do have a root principle in kerberos. Typically, I can connect to a machine as root with the following:
kinit username/root
(enter root principle pass)
ssh root#host
Connecting in this manner I'm not prompted for a password when ssh'ing to the host.
So I want to emulate this process using fabric. To do so I assumed the following,
kinit user/root
fab task1 task2 --user=root
Unfortunately fabric prompts me for a password, while I do not have the root password, I can't supply this. Fabric will not let me pass a null for the password as far as I can tell. Any ideas?

Looks like Fabric doesn't support Kerberos authentication. If I remember correctly paramiko library doesn't support it either and Fabric uses paramiko (not sure), so it doesn't have corresponding support.
You should go and ask here:
http://docs.fabfile.org/en/1.4.1/index.html#getting-help
May be use IRC channel so as to get quick response.
Regards,

There is an open pull request for support of Kerberos in Fabric and it looks like it's working and is almost ready to be merged:
https://github.com/fabric/fabric/pull/1261

Fabric 2.6.0 supports gssapi through paramiko (03/2022). You'll also need to install python-gssapi.
You just need to pass connect_kwargs to __init__():
class GSSConnection(Connection):
def __init__(self, host):
connect_kwargs = dict(
gss_auth=True,
gss_deleg_creds=True,
gss_kex=True,
)
super().__init__(host, connect_kwargs=connect_kwargs)

Related

Connecting to particular port inside a switch using python

Please find the below scenario:
I have one switch IP
For that switch multiple devices connected to multiple port numbers
Manually we will login to the switch with credentials
will give particular port number and click on enter two times
Then it will ask credentials of that particular device
After entering that credentials it will allow to login to that device.
Then we will give some commands.
Please help me on python code for this scenario
Try using pexpect module.
Install pexpect by pip install pexpect
Algorithm
1) Spawn a pexpect child by child = pexpect.spawn('ssh user#switch-ip') or pexpect.spawn('telnet switch-ip') or the protocol you use to login to the switch.
2) Then expect the prompt of the terminal(of the switch) like this child.expect("#")
3) Now you can run commands using child.sendline("your command here")
Do step 3 as many times as you would do manually. Now you can generalize the script by passing values as arguments. And everything will be done automatically.
More about pexpect here.
And here are few examples in that same website.
This should automate your scenario pretty easily.

Passwordless SSH using paramiko

Issue : I'm a noob with Paramiko, trying to run some commands from a python script (on personal machine) on a remote server. The remote server doesn't need a password to connect to.
For example, if I do
root#[IPaddress] on my Mac, I'm successfully able to connect to the remote server via MacbookPro terminal.
However, I'm trying to do this inside a Python script using Paramiko, and no matter what I do, I get an Authentication error or No Authentication methods available.
I went through Paramiko AuthenticationException issue but the answers there are vague for me to implement without significant experience with Paramiko. Help?
This is my code:
import paramiko
import os
from paramiko import SSHClient
#Borrowed from the linked post
class SSHClient_noauth(SSHClient):
def _auth(self, username, *args):
self._transport.auth_none(username)
return
#How do I implement?
ssh = SSHClient()
sshc = SSHClient_noauth()._auth(username="root") #Where's the ssh obj passed?
sshc.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sshc.connect("10.xxx.xxx.xxx")
Well, not to let the negative vote bog me down.
Tried doing sshc.connect(remoteIP, username=username, password="") and it worked. In case someone has been stuck for over an hour or two trying to get this working, especially for work, you might want to try putting in a "" instead of None.

Running consecutive commands with python fabric module

I am writing an application that interacts with numerous systems, specifically with switches,
i am trying to implement a function that will enable me to retreive logs from a specific switch using Fabric (python)
in a real session to the switch i would need to first run "enable" (and press enter key) and then run "debug generate dump" command.
using fabric.operations.run() i can only issue one command at a time,
using fabric.operations.open_shell() is not an option since i need to parse the output and also close the connection once it finishes.
Can someone assist on this?
THANKS!!
Here is an example of the code:
def getSwitchLog(self, host, port, username, password):
env.host_string = "%s:%s" % (host, port)
env.user = username
env.password = password
command = 'enable \r debug generate dump'
run(command, shell=cli, pty=True, combine_stderr=True, timeout=120)
shell=cli - because the switch does not run bash and 'cli' is the appropriate value in this case
\r should have sent "enter" key essentially sending 1. enable 2. enter 3. debug generate dump
this method works if i switch run with open_shell
but it seems run ignores \r
I was able to achieve what i need using:
command = 'sshpass -p admin ssh admin#switchIP cli \"enable\" \"show version\"'
fabric.api.local(command, capture=True, shell=None)
however this method is not robust as fabric.api.run() and also requires the running node to have sshpass installed
This is an example of the output from the switch CLI as the commands entered interactively (keyboard) without fabric
[standalone: master] > enable
[standalone: master] # debug generate dump
[standalone: master] # debug generate dump Generated dump sysdump-SX6036-1-20130630-104051.tgz
[standalone: master] #
thanks.
So working with a session state isn't something Fabric does. Every call is a new session. There are some other project that try and get around this, one being fexpect, but since you're attempting to query a switch I don't believe that will work. Since fexpect (last i knew) uploads a expect script which it then runs to the remote machine.
What you might have better luck with though is pxssh from the pexpect module. It allows ssh+expect like work simple enough. It's outside Fabric, but more likely to work for you right out of the gate I think.
work with robot-framework based on 'paramiko'. It has more simple API (write/read_unitl/read_all) to interact with your switch shell.
http://robotframework.org/SSHLibrary/latest/SSHLibrary.html

Fabric - How to supply ssh password dynamically

I am trying to use Fabric ,Django and Celery together to do operations on a remote host.
And in my case the remote host is going to be dynamic.
I guess the use of Django and Celery is irrelevant , the question can be narrowed down to
how to supply SSH password dynamically while using Fabric alone.
I found this piece of code which shows how to do this with Django and Celery.
from fabric.api import hosts
from celery import task
#task()
def remote_celery_task():
username, host = get_host_details()
host_string = "%s#%s" % (username, host)
#hosts(host_string)
def fab_task():
run("ls")
execute(fab_task)
But what it doesnt tell is how to dynamically pass SSH passwords to Fabric.
I understand that supplying password this way isnt good security wise, but I am willing to sacrifice security at the moment.
Update
I got it working when I changed the code to
#hosts(host_string)
def my_fab_task():
env.password = testhost.SSH_password # is this the correct way ? its working for me
run("ls")
Skip worrying about the password and just do ssh keygens. Share the keys between the hosts you will be connecting to and you can do passwordless ssh operations on the remote hosts.

How can I listen for and report server (SSH) connections via a Python script?

I am a bit new to Python, but an experienced programmer. I am writing a Python 2.7 script which should be started by a Linux server at boot. The purpose is to send, via various mediums, notification(s) when a user connects to the server.
My problem has to do with the actual listening. How can I make the module see when a user connects (via SSH, or whatever) to the server? Some quick pseudocode:
# When a connection is made
# Send an email
# Send a text message
# Send notification to server output
# Etc...
I'd like to include some details in the notification, like username, IP, connection time, last connection, a cute custom connection message, whatever. Any protips on how to do those things best is appreciated as well, but I'm sure I can figure this out elsewhere.
Thanks in advance for any guidance!
If your sshd is using syslog, you could configure syslog to send the auth facility to a named pipe, then write a Python script to read the FIFO. Here's an example that uses bash.
Or, like sblom said, you could tail /var/log/auth.log in a Python script. Either way, you should get lines like this:
Mar 29 19:58:13 mybox sshd[13914]: Accepted password for jtg from 192.168.0.20 port 51538 ssh2
pam_python will allow you to write a PAM module that can notify of authentication attempts on any service that uses PAM.

Categories

Resources