Python修改paramiko模块开发运维审计保垒机

需求:

1、保垒机有一个公共账号,所有人都是用这个账号登陆保垒机,root用户只能由堡垒机管理员有权限可以登陆

2、公共账号登陆保垒机->选择主机组->选择主机->选择你的普通用户->输入你的后端服务器的密码登陆

3、登陆的后端服务器所操作过的命令要记录到文件

拓扑图:

第三方模块paramiko下载

paramiko-1.10.1.tar.gz http://pan.baidu.com/s/1hrWzg7y

paramiko源码包远程演示(未修改源码)

修改parpakio源码

主要修改paramiko这两个脚本文件,解压paramiko后,进去解压出来的目录把这两个文件单独拷出来到一个文件下

- demo.py

- interactive.py

目录和文件介绍

[[email protected] tmp]# tree

.

├── hosts_user

│   ├── qqandroid.txt       #qqandroid服的ip

│   ├── qqios.txt         #qqios服的ip

│   └── users.txt         #有权限登陆的用户

├── record_comm

│   └── record.txt           #记录用户操作过的命令文件

└── script

├── demo.py             #主程序文件

├── interactive.py        #被调用的记录用户操作过的命令的脚本

└── zj.py              #登陆菜脚本

3 directories, 7 files

修改interactive.py脚本(标红色的为我修改过的内容)

#coding:utf-8

import socket

import sys

import time

# windows does not have termios...

try:

import termios

import tty

has_termios = True

except ImportError:

has_termios = False

def interactive_shell(chan):

if has_termios:

posix_shell(chan)

else:

windows_shell(chan)

def posix_shell(chan):

import select

oldtty = termios.tcgetattr(sys.stdin)

f=file(‘/tmp/record_comm/record.txt‘,‘ab+‘)   #把命令追加进此文件

try:

tty.setraw(sys.stdin.fileno())

tty.setcbreak(sys.stdin.fileno())

chan.settimeout(0.0)

records = []   #定义一个空列表

while True:

r, w, e = select.select([chan, sys.stdin], [], [])

if chan in r:

try:

x = chan.recv(1024)

if len(x) == 0:

print ‘\r\n*** EOF\r\n‘,

break

sys.stdout.write(x)

sys.stdout.flush()

except socket.timeout:

pass

if sys.stdin in r:          #屏幕接收

x = sys.stdin.read(1)    #每次只接收一个字符

records.append(x)

if x == ‘\r‘:         #每个命令输完回车都有一个\r

c_time = time.strftime(‘%Y-%m-%d %H:%M:%S‘)

cmd = ‘‘.join(records).replace(‘\r‘,‘\n‘)#\r win换行,\n Linux的换行

log = ‘%s   %s‘ %(c_time,cmd)

f.write(log)

f.flush()

records = []

if len(x) == 0:

break

chan.send(x)

finally:

termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

f.close()

# thanks to Mike Looijmans for this code

def windows_shell(chan):

import threading

sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")

def writeall(sock):

while True:

data = sock.recv(256)

if not data:

sys.stdout.write(‘\r\n*** EOF ***\r\n\r\n‘)

sys.stdout.flush()

break

sys.stdout.write(data)

sys.stdout.flush()

writer = threading.Thread(target=writeall, args=(chan,))

writer.start()

try:

while True:

d = sys.stdin.read(1)

if not d:

break

chan.send(d)

except EOFError:

# user hit ^Z or F6

pass

编写zj.py(登陆菜单)脚本

[[email protected] script]# cat zj.py

#!/usr/bin/python

#coding:utf-8

import os

def hosts_group():

os.system(‘clear‘)

print ‘‘‘

【主机组列表】

1、qqandroid组

2、qqios组

‘‘‘

global x_1

x_1 = raw_input( ‘请输入你要选择的主机组编号:‘)

def hosts():

global lines

if x_1 == ‘1‘:

os.system(‘clear‘)

print ‘‘‘

【qqandiod主机组列表】

1、qqandroid1服

2、qqandroid2服

3、返回上一页

‘‘‘

x_21 = raw_input( ‘请输入你要登陆的服务器编号:‘)

f = file(‘/tmp/hosts_user/qqandroid.txt‘)

for line in f.readlines():

line = line.strip(‘\n‘).split(‘ ‘)

if line[0] == x_21:

lines = line[1]

if x_21 == ‘3‘:

os.system(‘/usr/bin/python /tmp/script/demo.py‘)

else:

os.system(‘clear‘)

print ‘‘‘

【qqios主机组列表】

1、qqios1服

2、qqios2服

3、返回上一页

‘‘‘

x_22 = raw_input( ‘请输入你要登陆的服务器:‘)

f = file(‘/tmp/hosts_user/qqios.txt‘)

for line in f.readlines():

line = line.strip(‘\n‘).split(‘ ‘)

if line[0] == x_22:

lines = line[1]

if x_22 == ‘3‘:

os.system(‘/usr/bin/python /tmp/script/demo.py‘)

def yh():

os.system(‘clear‘)

print ‘‘‘

【用户列表】

1、wsyht

2、jenkins

3、peter

4、返回首页

‘‘‘

xyh = raw_input( ‘请输入你要登陆的用户编号:‘)

global youruser

f = file(‘/tmp/hosts_user/users.txt‘)

for line in f.readlines():

line = line.strip(‘\n‘)

line = line.split(‘ ‘)

if line[0] == xyh:

youruser = line[1]

if xyh == ‘4‘:

os.system(‘/usr/bin/python /tmp/script/demo.py‘)

修改paramiko脚本(标红色的为我修改过的内容)

cat /tmp/script/demo.py

#!/usr/bin/env python

import base64

from binascii import hexlify

import getpass

import os

import select

import socket

import sys

import threading

import time

import traceback

import paramiko

import interactive

import zj

def agent_auth(transport, username):

"""

Attempt to authenticate to the given transport using any of the private

keys available from an SSH agent.

"""

agent = paramiko.Agent()

agent_keys = agent.get_keys()

if len(agent_keys) == 0:

return

for key in agent_keys:

print ‘Trying ssh-agent key %s‘ % hexlify(key.get_fingerprint()),

try:

transport.auth_publickey(username, key)

print ‘... success!‘

return

except paramiko.SSHException:

print ‘... nope.‘

def manual_auth(username, hostname):

default_auth = ‘p‘

auth = raw_input(‘Auth by (p)assword, (r)sa key, or (d)ss key? [%s] ‘ % default_auth)

if len(auth) == 0:

auth = default_auth

if auth == ‘r‘:

default_path = os.path.join(os.environ[‘HOME‘], ‘.ssh‘, ‘id_rsa‘)

path = raw_input(‘RSA key [%s]: ‘ % default_path)

if len(path) == 0:

path = default_path

try:

key = paramiko.RSAKey.from_private_key_file(path)

except paramiko.PasswordRequiredException:

password = getpass.getpass(‘RSA key password: ‘)

key = paramiko.RSAKey.from_private_key_file(path, password)

t.auth_publickey(username, key)

elif auth == ‘d‘:

default_path = os.path.join(os.environ[‘HOME‘], ‘.ssh‘, ‘id_dsa‘)

path = raw_input(‘DSS key [%s]: ‘ % default_path)

if len(path) == 0:

path = default_path

try:

key = paramiko.DSSKey.from_private_key_file(path)

except paramiko.PasswordRequiredException:

password = getpass.getpass(‘DSS key password: ‘)

key = paramiko.DSSKey.from_private_key_file(path, password)

t.auth_publickey(username, key)

else:

pw = getpass.getpass(‘Password for %[email protected]%s: ‘ % (username, hostname))

t.auth_password(username, pw)

# setup logging

paramiko.util.log_to_file(‘demo.log‘)

username = ‘‘

if len(sys.argv) > 1:

hostname = sys.argv[1]

if hostname.find(‘@‘) >= 0:

username, hostname = hostname.split(‘@‘)

else:

zj.hosts_group()

zj.hosts()

#hostname = raw_input(‘Hostname: ‘)

hostname = zj.lines

if len(hostname) == 0:

print ‘*** Hostname required.‘

sys.exit(1)

port = 22

if hostname.find(‘:‘) >= 0:

hostname, portstr = hostname.split(‘:‘)

port = int(portstr)

# now connect

try:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect((hostname, port))

except Exception, e:

print ‘*** Connect failed: ‘ + str(e)

traceback.print_exc()

sys.exit(1)

try:

t = paramiko.Transport(sock)

try:

t.start_client()

except paramiko.SSHException:

print ‘*** SSH negotiation failed.‘

sys.exit(1)

try:

keys = paramiko.util.load_host_keys(os.path.expanduser(‘~/.ssh/known_hosts‘))

except IOError:

try:

keys = paramiko.util.load_host_keys(os.path.expanduser(‘~/ssh/known_hosts‘))

except IOError:

print ‘*** Unable to open host keys file‘

keys = {}

# check server‘s host key -- this is important.

key = t.get_remote_server_key()

if not keys.has_key(hostname):

print ‘*** WARNING: Unknown host key!‘

elif not keys[hostname].has_key(key.get_name()):

print ‘*** WARNING: Unknown host key!‘

elif keys[hostname][key.get_name()] != key:

print ‘*** WARNING: Host key has changed!!!‘

sys.exit(1)

else:

print ‘*** Host key OK.‘

# get username

if username == ‘‘:

default_username = getpass.getuser()

#username = raw_input(‘Username [%s]: ‘ % default_username)

zj.yh()

username = zj.youruser

if len(username) == 0:

username = default_username

agent_auth(t, username)

if not t.is_authenticated():

manual_auth(username, hostname)

if not t.is_authenticated():

print ‘*** Authentication failed. :(‘

t.close()

sys.exit(1)

chan = t.open_session()

chan.get_pty()

chan.invoke_shell()

print ‘*** Here we go!‘

print

f = file(‘/tmp/record_comm/record.txt‘,‘ab+‘)

sj = time.strftime(‘%c‘)

f.write(‘\n‘)

f.write(username + ‘ ‘+ ‘login:‘ + ‘ ‘ + sj + ‘ ‘ + ‘from‘ + ‘ ‘ + ‘192.168.200.10‘ + ‘\n‘)

f.close()

interactive.interactive_shell(chan)

f = file(‘record.txt‘,‘ab+‘)

f.write(username + ‘ ‘+ ‘exit:‘ + ‘ ‘ + sj  + ‘\n‘)

chan.close()

except Exception, e:

print ‘*** Caught exception: ‘ + str(e.__class__) + ‘: ‘ + str(e)

traceback.print_exc()

try:

t.close()

except:

pass

sys.exit(1)

登陆后端的IP和用户(标红色为一会要登陆的用户和IP)

[[email protected] tmp]# cat hosts_user/qqandroid.txt

1 192.168.200.10

2 192.168.200.20

3 192.168.200.30

[[email protected] tmp]# cat hosts_user/qqios.txt

1 192.168.200.11

2 192.168.200.21

3 192.168.200.31

[[email protected] tmp]# cat hosts_user/users.txt

1 wsyht

2 jenkins

3 peter

准备用户环境

在192.168.200.11后端服务机器添加一个普通账户wsyht,并设置好密码作为登陆服务器之用,生产环境应该用ssh+key,我这里演示就不用了,后端服务器不允许root用户登陆

保垒机添加一个公共用户gg123,在gg123的家目录.bashrc最下面添加以下两行代码

[[email protected] tmp]# tail -2 /home/gg123/.bashrc

/usr/bin/python /tmp/script/demo.py   #公共用户登陆则执行跳板脚本,脚本停止则注销用户,除了保垒机管理员可以登陆保垒机,普通用户不允许登陆该机器

login

记录命令文件的目录(该目录普通用户要有可写权限,不然用户登陆后端务器所操作的命令无法记录下来,我这里直接给他设777)

保垒机IP:192.168.200.10

后端服务器IP:192.168.200.11

登陆演示:


保垒机管理员(root)登陆查看用户操作过的命令


时间: 2024-11-06 19:43:26

Python修改paramiko模块开发运维审计保垒机的相关文章

Python中paramiko模块在linux运维中应用

python的paramiko模块可以实现ssh客户端的功能,使用起来也比较简单.但是当服务器非常多的时候,每台服务器上执行完全相同的简单操作,也会花费大量的时间. 下载模块:paramiko.tar.gz使用tar解压后在cd到目录下最后使用rpm安装 rpm -ivh * import paramiko //导入paramiko模块host='192.168.x.xx' //需要远程管理的主机ip ssh=paramiko.SSHClient() //相当于点开xshellssh.set_m

Django开发运维后台(二):建立模型与更新数据

上一篇文章我已经新建了一个SaAdmin的APP,现在开始在这APP下面来code 1.修改setting.py的数据库连接: DATABASES = {     'default': {         'ENGINE':'django.db.backends.mysql',         'NAME': 'QjshAdmin',         'USER': 'root',         'PASSWORD': 'lihuipeng',         'HOST': 'localho

20款开发运维必备的顶级工具

开发运维工具与软件开发领域的最佳实践密切相关,也与必要的规范密切相关.在整个开发生命周期涉及到一大批新旧工具,从规划.编码.测试.发布到监控.本文介绍你应该考虑添加到工具箱中的20种开发运维工具,供大家参考. 开发运维是那些还没有得到明确定义,就流传开来的科技时髦词之一.这种情况时不时出现,某个好的概念问世后,人们还无法实际上解释它为何物,就趋之若鹜. 所以,考虑到开发运维本身在大家的头脑中还是一片模糊,开发运维工具怎么样呢? 有必要说清一点:开发运维是开发和运维的混合体,因为它代表了开发实践方

Python之paramiko模块和SQL连接API

堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接: import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.con

PHP开发运维管理系统笔记

开发运维管理系统采用ThinkPHP框架+mysql进行开发. 框架配置 return array(     //'配置项'=>'配置值'     'SHOW_PAGE_TRACE' => true,     //允许访问的控制器     'MODULE_ALLOW_LIST' => array('Home'),     //默认控制器     'DEFAULT_MODULE' => 'Home',     //URL模式     'URL_MODEL' => 2,     

(视频)《快速创建网站》 4.1 为啥造软件不同于造汽车,为啥是软件就一定会有Bug - 构建开发运维一体化(DevOps)

本文是<快速创建网站>系列的第9篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文.访问本系列目录,请点击:http://anb.io/blog/tag/wordpress-on-azure/ 1. 网站管理平台WordPress和云计算平台Azure简介 (6分钟视频 )2.1 在Azure上创建网站及网站运行机制 (13分钟视频)2.2 域名绑定操作和Azure负载均衡机制 (12分钟视频)2.3 WordPress 初始化和网站管理功能 (11分钟视频)3

使用python的Paramiko模块登陆SSH

paramiko是用Python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. python的paramiko模块可以方便的实现ssh登录,并执行命令. 1. paramiko模块安装 1.1安装pycrypto库 下载地址请戳这里:http://download.csdn.net/detail/oatnehc/8825715: pycrypto库的主页在这里:https://www.dlitz.net/software/pycrypto/ pycrypto库

6. 开发运维常见问题

#开发运维常见问题 fork操作 同步操作 与内存量息息相关:内存越大,耗时越长(与机器类型有关) info:latest_fork_usec 改善fork 有限使用物理机或高校支持fork操作的虚拟化技术 控制Redis实例最大可用内存:maxmemory 合理配置linux内存分配策略:vm.overcommit_memory=1 降低fork频率:例如放宽AOF重写自动触发时机,不必要的全量复制 ##子进程开销和优化 cpu 开销:RDb和AOF文件生成,属于CPU密集型 优化:不做CPU

分享老男孩自动化开发运维Python12期

本套教程共L33天,完整版!!! 目录: L001-老男孩教育-Python12期VIP视频-18节 0001-开课介绍.mp40002-同学互相介绍.mp40003-python简史介绍.mp40004-python3的新特性.mp40005-开发工具ide介绍.mp40006-helloworld程序.mp40007-变量与赋值.mp40008-用户交互.mp40009-条件判断与缩进.mp40010-循环控制.mp40011-循环次数限制.mp40012-常用数据类型.mp40013-字符