madsnotes

堡垒机知识储备

开发堡垒机之前,先来学习Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作。

paramiko模块使用介绍

http://www.cnblogs.com/madsnotes/articles/5537947.html

堡垒机实现

实现思路:

堡垒机执行流程:

  1. 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
  2. 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
  3. 用户选择服务器,并自动登陆
  4. 执行操作并同时将用户操作记录

注:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/wupeiqi/menu.py

 

堡垒机实现过程:

第一步:实现用户登录

import getpass
 
user = raw_input(\'username:\')
pwd = getpass.getpass(\'password\')
if user == \'alex\' and pwd == \'123\':
    print \'登陆成功\'
else:
    print \'登陆失败\'

第二步:根据登录的用户名获取拥有权限的服务器列表

dic = {
    \'alex\': [
        \'172.16.103.189\',
        \'c10.puppet.com\',
        \'c11.puppet.com\',
    ],
    \'eric\': [
        \'c100.puppet.com\',
    ]
}
 
host_list = dic[\'alex\']
 
print \'please select:\'
for index, item in enumerate(host_list, 1):
    print index, item
 
inp = raw_input(\'your select (No):\')
inp = int(inp)
hostname = host_list[inp-1]
port = 22

第三步:根据用户名及私钥登录服务器

import paramiko
import sys
import os
import socket
import select
import getpass
 
tran = paramiko.Transport((\'10.211.55.4\', 22,))
tran.start_client()
tran.auth_password(\'wupeiqi\', \'123\')
 
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
#########
# 利用sys.stdin,肆意妄为执行操作
# 用户在终端输入内容,并将内容发送至远程服务器
# 远程服务器执行命令,并将结果返回
# 用户终端显示内容
#########
 
chan.close()
tran.close()

 

import paramiko
import sys
import os
import socket
import select
import getpass
from paramiko.py3compat import u
 
tran = paramiko.Transport((\'10.211.55.4\', 22,))
tran.start_client()
tran.auth_password(\'wupeiqi\', \'123\')
 
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
while True:
    # 监视用户输入和服务器返回数据
    # sys.stdin 处理用户输入
    # chan 是之前创建的通道,用于接收服务器返回信息
    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    if chan in readable:
        try:
            x = u(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 readable:
        inp = sys.stdin.readline()
        chan.sendall(inp)
 
chan.close()
tran.close()
肆意妄为(一)
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import paramiko
import sys
import os
import socket
import select
import getpass
from paramiko.py3compat import u


default_username = getpass.getuser()
username = input(\'Username [%s]: \' % default_username)
if len(username) == 0:
    username = default_username


hostname = input(\'Hostname: \')
if len(hostname) == 0:
    print(\'*** Hostname required.\')
    sys.exit(1)

tran = paramiko.Transport((hostname, 22,))
tran.start_client()

default_auth = "p"
auth = input(\'Auth by (p)assword or (r)sa 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 = 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)
    tran.auth_publickey(username, key)
else:
    pw = getpass.getpass(\'Password for %s@%s: \' % (username, hostname))
    tran.auth_password(username, pw)



# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()

while True:
    # 监视用户输入和服务器返回数据
    # sys.stdin 处理用户输入
    # chan 是之前创建的通道,用于接收服务器返回信息
    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    if chan in readable:
        try:
            x = u(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 readable:
        inp = sys.stdin.readline()
        chan.sendall(inp)

chan.close()
tran.close()
完整示例(一)Python3.x

 

import paramiko
import sys
import os
import socket
import select
import getpass
import termios
import tty
from paramiko.py3compat import u
 
tran = paramiko.Transport((\'10.211.55.4\', 22,))
tran.start_client()
tran.auth_password(\'wupeiqi\', \'123\')
 
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
 
# 获取原tty属性
oldtty = termios.tcgetattr(sys.stdin)
try:
    # 为tty设置新属性
    # 默认当前tty设备属性:
    #   输入一行回车,执行
    #   CTRL+C 进程退出,遇到特殊字符,特殊处理。
 
    # 这是为原始模式,不认识所有特殊符号
    # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
    tty.setraw(sys.stdin.fileno())
    chan.settimeout(0.0)
 
    while True:
        # 监视 用户输入 和 远程服务器返回数据(socket)
        # 阻塞,直到句柄可读
        r, w, e = select.select([chan, sys.stdin], [], [], 1)
        if chan in r:
            try:
                x = u(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)
            if len(x) == 0:
                break
            chan.send(x)
 
finally:
    # 重新设置终端属性
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
 
 
chan.close()
tran.close()
肆意妄为(二)
import paramiko
import sys
import os
import socket
import select
import getpass
import termios
import tty
from paramiko.py3compat import u


default_username = getpass.getuser()
username = input(\'Username [%s]: \' % default_username)
if len(username) == 0:
    username = default_username


hostname = input(\'Hostname: \')
if len(hostname) == 0:
    print(\'*** Hostname required.\')
    sys.exit(1)

tran = paramiko.Transport((hostname, 22,))
tran.start_client()

default_auth = "p"
auth = input(\'Auth by (p)assword or (r)sa 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 = 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)
    tran.auth_publickey(username, key)
else:
    pw = getpass.getpass(\'Password for %s@%s: \' % (username, hostname))
    tran.auth_password(username, pw)

# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()


# 获取原tty属性
oldtty = termios.tcgetattr(sys.stdin)
try:
    # 为tty设置新属性
    # 默认当前tty设备属性:
    #   输入一行回车,执行
    #   CTRL+C 进程退出,遇到特殊字符,特殊处理。

    # 这是为原始模式,不认识所有特殊符号
    # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
    tty.setraw(sys.stdin.fileno())
    chan.settimeout(0.0)

    while True:
        # 监视 用户输入 和 远程服务器返回数据(socket)
        # 阻塞,直到句柄可读
        r, w, e = select.select([chan, sys.stdin], [], [], 1)
        if chan in r:
            try:
                x = u(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)
            if len(x) == 0:
                break
            chan.send(x)

finally:
    # 重新设置终端属性
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)


chan.close()
tran.close()
完整示例(二)Python3.x

 

import paramiko
import sys
import os
import socket
import getpass

from paramiko.py3compat import u

# 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)
    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        chan.settimeout(0.0)
        log = open(\'handle.log\', \'a+\', encoding=\'utf-8\')
        flag = False
        temp_list = []
        while True:
            r, w, e = select.select([chan, sys.stdin], [], [])
            if chan in r:
                try:
                    x = u(chan.recv(1024))
                    if len(x) == 0:
                        sys.stdout.write(\'\r\n*** EOF\r\n\')
                        break
                    if flag:
                        if x.startswith(\'\r\n\'):
                            pass
                        else:
                            temp_list.append(x)
                        flag = False
                    sys.stdout.write(x)
                    sys.stdout.flush()
                except socket.timeout:
                    pass
            if sys.stdin in r:
                x = sys.stdin.read(1)
                import json

                if len(x) == 0:
                    break

                if x == \'\t\':
                    flag = True
                else:
                    temp_list.append(x)
                if x == \'\r\':
                    log.write(\'\'.join(temp_list))
                    log.flush()
                    temp_list.clear()
                chan.send(x)

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


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


def run():
    tran = paramiko.Transport((\'10.211.55.4\', 22,))
    tran.start_client()
    tran.auth_password(\'wupeiqi\', \'123\')

    # 打开一个通道
    chan = tran.open_session()
    # 获取一个终端
    chan.get_pty()
    # 激活器
    chan.invoke_shell()

    interactive_shell(chan)

    chan.close()
    tran.close()


if __name__ == \'__main__\':
    run()
打死不改版本

 

import paramiko
import sys
import os
import socket
import getpass

from paramiko.py3compat import u

# 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)
    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        chan.settimeout(0.0)
        log = open(\'handle.log\', \'a+\', encoding=\'utf-8\')
        flag = False
        temp_list = []
        while True:
            r, w, e = select.select([chan, sys.stdin], [], [])
            if chan in r:
                try:
                    x = u(chan.recv(1024))
                    if len(x) == 0:
                        sys.stdout.write(\'\r\n*** EOF\r\n\')
                        break
                    if flag:
                        if x.startswith(\'\r\n\'):
                            pass
                        else:
                            temp_list.append(x)
                        flag = False
                    sys.stdout.write(x)
                    sys.stdout.flush()
                except socket.timeout:
                    pass
            if sys.stdin in r:
                x = sys.stdin.read(1)
                import json

                if len(x) == 0:
                    break

                if x == \'\t\':
                    flag = True
                else:
                    temp_list.append(x)
                if x == \'\r\':
                    log.write(\'\'.join(temp_list))
                    log.flush()
                    temp_list.clear()
                chan.send(x)

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


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


def run():
    default_username = getpass.getuser()
    username = input(\'Username [%s]: \' % default_username)
    if len(username) == 0:
        username = default_username


    hostname = input(\'Hostname: \')
    if len(hostname) == 0:
        print(\'*** Hostname required.\')
        sys.exit(1)

    tran = paramiko.Transport((hostname, 22,))
    tran.start_client()

    default_auth = "p"
    auth = input(\'Auth by (p)assword or (r)sa 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 = 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)
        tran.auth_publickey(username, key)
    else:
        pw = getpass.getpass(\'Password for %s@%s: \' % (username, hostname))
        tran.auth_password(username, pw)

    # 打开一个通道
    chan = tran.open_session()
    # 获取一个终端
    chan.get_pty()
    # 激活器
    chan.invoke_shell()

    interactive_shell(chan)

    chan.close()
    tran.close()


if __name__ == \'__main__\':
    run()
终极

更多参见:paramoko源码 https://github.com/paramiko/paramiko 

Alex堡垒机:http://www.cnblogs.com/alex3714/articles/5286889.html

作业:运维堡垒机开发

1、堡垒机程序部署(堡垒机程序包,安装脚本)
  区分版本Python2.7 Python2.6 Python3.x(能做到Python版本兼容)
2、堡垒机功能
  审计功能(记录用户登录及相关操作)
  权限管理(用户可以查看到拥有权限的主机列表,并拥有权限进行相应操作)
  确保除了堡垒机管理员之外,所有其它人对堡垒机本身无任何操作权限,只有一个登录跳转功能
  确保用户的操作纪录不能被用户自己以任何方式获取到并篡改(记录到数据库)
  每个用户登录堡垒机后,只需要选择具体要访问的设置,就连接上了,不需要再输入目标机器的访问密码
       允许用户对不同的目标设备有不同的访问权限,例:
             对10.0.2.34 有mysql 用户的权限
             对192.168.3.22 有root用户的权限
             对172.33.24.55 没任何权限
       分组管理,即可以对设置进行分组,允许用户访问某组机器,但对组里的不同机器依然有不同的访问权限

数据库操作

Python操作MySQL的模块安装

linux:
    yum install MySQL-python
 
window:
    https://sourceforge.net/projects/mysql-python/

SQL基本操作

1、数据库操作

show databases;
use [databasename];
create database  [name];

2、数据库表操作

show tables;
 
create table students
    (
        id int  not null auto_increment primary key,
        name char(8) not null,
        sex char(4) not null,
        age tinyint unsigned not null,
        tel char(13) null default "-"
    );

CREATE TABLE `wb_blog` (
    `id` smallint(8) unsigned NOT NULL,
    `catid` smallint(5) unsigned NOT NULL DEFAULT \'0\',
    `title` varchar(80) NOT NULL DEFAULT \'\',
    `content` text NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `catename` (`catid`)
) ;

3、数据操作

# 插入数据
insert into students(name,sex,age,tel) values(\'alex\',\'man\',18,\'151515151\')

# 删除数据
delete from students where id =2;

# 更新数据
update students set name = \'sb\' where id =1;

# 查询数据
select * from students

4、其他

主键、外键、左右连接

Python MySQL API

1、插入数据

import MySQLdb
  
conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')
  
cur = conn.cursor()
  
reCount = cur.execute(\'insert into UserInfo(Name,Address) values(%s,%s)\',(\'alex\',\'usa\'))
# reCount = cur.execute(\'insert into UserInfo(Name,Address) values(%(id)s, %(name)s)\',{\'id\':12345,\'name\':\'wupeiqi\'})
  
conn.commit()
  
cur.close()
conn.close()
  
print reCount
案例一:插入单条数据
import MySQLdb

conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')

cur = conn.cursor()

li =[
     (\'alex\',\'usa\'),
     (\'sb\',\'usa\'),
]
reCount = cur.executemany(\'insert into UserInfo(Name,Address) values(%s,%s)\',li)

conn.commit()
cur.close()
conn.close()

print reCount
案例二:批量插入数据

2、删除数据

import MySQLdb
 
conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')
 
cur = conn.cursor()
 
reCount = cur.execute(\'delete from UserInfo\')
 
conn.commit()
 
cur.close()
conn.close()
 
print reCount
删除数据

3、修改数据

import MySQLdb
 
conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')
 
cur = conn.cursor()
 
reCount = cur.execute(\'update UserInfo set Name = %s\',(\'alin\',))
 
conn.commit()
cur.close()
conn.close()
 
print reCount
修改数据

4、查询数据

# ############################## fetchone/fetchmany(num)  ##############################
 
import MySQLdb
 
conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')
cur = conn.cursor()
 
reCount = cur.execute(\'select * from UserInfo\')
 
print cur.fetchone()
print cur.fetchone()
cur.scroll(-1,mode=\'relative\')
print cur.fetchone()
print cur.fetchone()
cur.scroll(0,mode=\'absolute\')
print cur.fetchone()
print cur.fetchone()
 
cur.close()
conn.close()
 
print reCount
 
 
 
# ############################## fetchall  ##############################
 
import MySQLdb
 
conn = MySQLdb.connect(host=\'127.0.0.1\',user=\'root\',passwd=\'1234\',db=\'mydb\')
#cur = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor)
cur = conn.cursor()
 
查询数据

 

分类:

技术点:

相关文章: