7

使用pexpect自动认证快速登陆中控机、服务器

 2 years ago
source link: https://chegva.com/4414.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用pexpect自动认证快速登陆中控机、服务器

    自动认证快速登陆中控机,服务器

   Python pexpect、click库,谷歌双因素认证使用

可以使用脚本做中控机认证,或者进入交互模式登陆中控机,服务器,无需每次输入登陆密码和谷歌验证码。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# create by anzhihe 20210513
import click
import pexpect
import pyotp
import struct, fcntl, sys, signal
import termios
def sigwinch_passthrough (sig, data):
"""设置合适的终端窗口大小
This returns the window size of the child tty.
The return value is a tuple of (rows, cols).
"""
if not global_pexpect_instance:
return
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912 # Assume
= struct.pack('HHHH'0000)
= struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
# print(a[0],a[1])
global_pexpect_instance.setwinsize(a[0],a[1])
def get_auth_token(secret):
"""获取谷歌认证码"""
totp = pyotp.TOTP(secret)
return totp.now()
def login_relay(child, secret, interact):
"""登陆中控机"""
index = child.expect(["Verification code", pexpect.EOF, pexpect.TIMEOUT])
if index in (02):
token = get_auth_token(secret)
child.sendline(token)
index = child.expect(["relay", pexpect.EOF, pexpect.TIMEOUT])
if (index == 0):
click.echo(click.style('认证成功:)', fg='blue'))
# 取消标准输出,否则会导致每个字符重复显示两遍
child.logfile_read = None
if interact:
# 在中控机上执行指定命令,登陆到指定服务器
child.sendline('ssh anzhihe@machine')
click.clear() # 清屏
child.interact() # 将控制权交给用户
else:
child.close()
elif index == 1:
click.echo(click.style('认证失败:(', fg='red'))
child.close()
CONTEXT_SETTINGS = dict(help_option_names = ['-h''--help'])
@click.command(context_settings = CONTEXT_SETTINGS)
@click.option('--username''-u', required=Truetype=strhelp='username', default='anzhihe')
@click.option('--password','-p', required=Truetype=strhelp='password', default='passwd')
@click.option('--secret''-s', required=Truetype=strhelp='secret', default='google_auth_key')
@click.option('--interact''-i', is_flag=Truehelp='进入交互模式', default=False)
def login(username: str, password: str, secret: str, interact: bool):
"""连接中控机"""
child = pexpect.spawn('ssh %s@relay' % username, timeout=3)
global global_pexpect_instance
global_pexpect_instance = child
sigwinch_passthrough(1,2)
## debug模式
#child.logfile = open("logfile.txt", 'wb')
#child.logfile_read = sys.stdout.buffer
# 重定向输出到stdout,不包含输入的密码
if interact:
child.logfile_read = sys.stdout.buffer
# 开始匹配
index = child.expect(["id_rsa""code""relay", pexpect.EOF, pexpect.TIMEOUT])
if index == 0:
child.sendline(password)
login_relay(child, secret, interact)
elif index == 1:
login_relay(child, secret, interact)
elif index == 2:
click.echo(click.style('亲,已经认证过了哦~', fg='green'))
child.logfile_read = None
if interact:
child.sendline('ssh anzhihe@machine')
click.clear()
child.interact()
else:
child.close()
if __name__ == '__main__':
login()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK