Connecting to particular port inside a switch using python - 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.

Related

How can you Interact and log in to the physical steam client using Python?

In summary; I want to be able to interact with a non-logged in steam client and log it in, and I dont want to use some type of Windows only interaction. I don't mean the SteamCLI, or logging into steam using the steam library for python. I mean directly interacting with the steam client in some way and physically logging in.
When using SteamCLI and other modules I've noticed it just logs you into their session instead of the client session that you get from physically logging into steam.
for example:
from steam.client import SteamClient
x = SteamClient()
x.login(username=, password=)
Doesn't actually log you in, since it is its own client.
I need this because I have made a script that can connect me to servers and figure out who's on it, and it relies on you being logged in to said client.
Is there any modules/libraries that will allow me to do this? and if pywinauto is the one I should use, are there any guides you know of so I can interact with said application in a good way, even on linux.
So here is what I ended up doing:
First you get a dummy display. I used this https://askubuntu.com/questions/453109/add-fake-display-when-no-monitor-is-plugged-in
After that you create the config (https://askubuntu.com/a/463000) and start up the display.
Next I created a systemd unit to launch steam using command line
[Unit]
Description=example systemd service unit file.
[Service]
User=root
Environment=XAUTHORITY=/var/run/lightdm/root/:0
Environment=DISPLAY=:0
ExecStart=/bin/bash /root/start.sh
[Install]
WantedBy=multi-user.target
(you probably shouldn't be using root for this, but its the easiest way I found to always have perms to the XAUTHORITY env, so you can login to the display)
Here is what /root/start.sh looks like
#!/bin/sh
export DISPLAY=:0
export XAUTHORITY=/var/run/lightdm/root/:0
export PATH="$PATH:/usr/games"
steam -login username_goes_here password_goes_here steam_guard_code
Note that you may not need to do the export DISPLAY and export XAUTHORITY twice. I haven't tested it.
This should just work™, it will log in, but it will ask for a steam guard code, so what you should do is attempt to start the service, receive the code through email, then append it after password.
As for doing this in python, as I said originally. you can probably use it to call start.sh, implementing command line arguments for steam code. You need these arguments because I haven't found a way for it to trust the computer you use, so it might be beneficial to implement python IMAP for reading the codes sent to the email which owns the account and using said arguments.
Theoretical Section
Please note this whole section is untested, but intended to answer my original question.
Heres what a python file might look like (very roughly)
def start_steam(code=""):
# Assuming start.sh includes reading variables from cmd line (my example didnt)
proc = subprocess.Popen(["/bin/bash", "start.sh", code])
# This function would probably just interact iwth an IMAP server to retrieve an email sent by steam support with the code. If its not found within a certain range of time, it would theoretically just stop looking
steam_guard_code = do_something_to_find_steam_guard_code_email(timeout=30)
if code:
proc.terminate()
start_steam(code=code)
else:
# proc should continue to run in the background, until restart, that means this script should ALSO run on startup, or until there isnt a PID detected for steam
with open("/var/run/steam.pid", "w") as f:
f.write(process.pid)
exit()
this python script would have to be run by systemd, it would be a forking process, and PIDfile would have to be specified by systemd (I think) so that it can be monitored.
edit: this solution has become even more theoretical, since it is not possible to pass steam guard code to steam -login username password. You would need to disable steam guard.

Secure serial port for particular python application

I have a python application("App1") that uses serial port /dev/ttyUSB0. This application is running as Linux service. It is running very well as it is perfectly automated for the task that I need it to perform. However, I have recently came to realize that sometimes I accidentally use the same serial port for another python application that I am developing which causes unwanted interference with "App1".
I did try to lock down "App1" as follows:
ser=serial.Serial(PORT, BAUDRATE)
fcntl.lockf(ser, fcntl.LOCK_EX | fcntl.LOCK_NB)
However, for other applications I sometimes unknowingly using
ser=serial.Serial(PORT, BAUDRATE)
without checking for ser.isOpen()
In order to prevent this I was wondering during the times I work on other applications, is there a way for ser=serial.Serial(PORT, BAUDRATE) to notify me that the serial port is already in use when I try to access it?
A solution I came up with is to create a cronjob that runs forever which essentially checks the following:
fuser -k /dev/ttyUSB0 #to get the PID of activated services that uses /dev/ttyUSB0
pkill -f <PID of second application shown in output above> #kill the application belonging to the second PID given by the above command
The above would ensure that whenever two applications use the same serial port, the second PID will get killed(I am aware there are some leaks in this logic). What do you guys think? If this is not a good solution, is there any way for ser=serial.Serial(PORT, BAUDRATE) to notify me that /dev/ttyUSB0 is already in use when I try to access it or do I need to implement the logic at driver level? Any help would be highly appreciated!
I think the simpler thing to do there is to create a different user for the "stable process", and use plain file permissions to give that user exclusive access to /dev/ttyUSB0.
With Unix groups and still plain permissions, that other process can still access any other resource it needs that would be under your main user - so it should be plain simple
If you are not aware of them, check the documentation for the commands chown and chmod.

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 authentication with kerberos

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)

Python telnetlib determining different login prompts

I've written a python script that can log into multiple devices sequentially by reading a csv file listing the different IP addresses. From there it outputs a file for each device with the content from a few commands that are passed to the devices via the script. So I've come pretty far. A problem I'm running into is that sometimes the script hangs. And that is because some devices have different software revisions and do not support certain commands that are being passed to them. The difference I'm focusing on is the prompt after log in. For example, logging into device type A has a command prompt of xyz#. Device type B has a command type abc:. It's the same manufacturer, just a different model and/or software rev. Depending on the command prompt I know the commands I can run on that device without the script hanging up. So what I need to be able to do is after a successful login, depending on the command prompt I get run a set of specific commands.
I can post some of my code if that would help but what I'm really looking to find out is if this is even possible. And if so, so pointers. A few suggestions on what I might try. After working with Python for a few months I know there has to be a way to do this. I usually don't post because I can work through others' posts and develop a working solution. But I've been working on this a bit and haven't been able to piece it together so looking I'm for an assist.
-Shane
EDIT
At this point I'm still unable to write code the would determine the command prompt. Well at least while the telnet session is up. I can telnet in, run some commands and close the session. I can then write the results to a file. And from there read the file to determine the prompt. But ideally I'd like to be able to open a telnet session, run a command to determine the prompt while the session is still open, read it while the session is up and then based on the prompt run specific commands.
The issue seems to be with not being able to read any command output while the telnet session is still up. The session has to close and then write all output to a file. Then read the file to determine the command prompt, determine which commands to run based on the prompt, then open a new telnet session and run those commands.
Should I accept the fact that I have to close the telnet session, write the data to a file, read it to determine prompt and then loop back through the login part of the script again? Or am I missing something? Not sure if I'm bring clear in my description.
I would implement the commands using a common interface and then use a dictionary to retrieve them when I know what system I am connected to:
# command set for system xyz#
def copy1(src, dest):
pass
def list1():
pass
# command set for system abc:
def copy2(src, dest):
pass
def list2():
pass
cmdDict = {
# prompt command set
'xyz#': [copy1, list1],
'abc:' [copy2, list2],
}
...
# guess the right commands from the prompt we have read
copyCommand = cmdDict[detected_prompt][0]
listCommand = cmdDict[detected_prompt][1]
...
# proceed normally
listCommand()
copyCommand(f1, g1)
copyCommand(f2, g2)

Categories

Resources