知识参鉴:Mr.7
堡垒机实现原理
堡垒机中用于与客户端与服务端交互的过程是由paramiko模块来实现,paramiko提供了客户端与服务器的功能
1、paramiko-SSHClient
SSHClient用于在客户端远程连接服务端进行操作,实现基础的远程命令。
(1)基于用户名密码:
#!/usr/bin/env python
# coding:utf-8
__author__ = "King"
import paramiko
# 定义一个SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接主机
ssh.connect(hostname='10.0.7.4', port=2369, username='tom', password='xxx')
# 执行命令
stdin, stdout ,stderr = ssh.exec_command('ls')
# 返回内容
result = stdout.read()
print result
# 关闭连接
ssh.close()
#!/usr/bin/env python # coding:utf-8 __author__ = "King" import paramiko transport = paramiko.Transport(('10.0.7.4', 2369)) transport.connect(username='tom', password='xxx') ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') print stdout.read() transport.close()
(2)基于公钥私钥:
#!/usr/bin/env python
# coding:utf-8
__author__ = "King"
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/king/.ssh/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='10.0.7.4', port=2369, username='tom', key=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('who')
# 获取命令结果
result = stdout.read()
print result
# 关闭连接
ssh.close()
#!/usr/bin/env python # coding:utf-8 __author__ = "King" import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/tom/.ssh/id_rsa') transport = paramiko.Transport(('10.0.7.4', 2369)) transport.connect(username='tom', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('who') transport.close()
2、paramiko-SFTPClient
SFTPClient用于连接远服务器上传下载文件
(1)基于用户名密码:
#!/usr/bin/env python
# coding:utf-8
__author__ = "King"
import paramiko
transport = paramiko.Transport(('10.0.7.4', 2369))
transport.connect(username='tom', password='xxx')
sftp = paramiko.SFTPClient.from_transport(transport)
"""
:argument:(cls, t, window_size=None, max_packet_size=None)
Create an SFTP client channel from an open `.Transport`.
"""
# 将本地的1212.jpg 上传到服务端
sftp.put('/data/1212.jgp', '/home/tom/')
# 将服务端的1212.jpg下载到本地
sftp.get('/home/tom/1212.jpg', '/data1')
transport.close()
(2)基于公钥私钥:
#!/usr/bin/env python
# coding:utf-8
__author__ = "King"
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/king/.ssh/id_rsa')
transport = paramiko.Transport(('10.0.7.4', 2369))
transport.connect(username='tom', pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
"""
:argument:(cls, t, window_size=None, max_packet_size=None)
Create an SFTP client channel from an open `.Transport`.
"""
# 将本地的1212.jpg 上传到服务端
sftp.put('/data/1212.jgp', '/home/tom/')
# 将服务端的1212.jpg下载到本地
sftp.get('/home/tom/1212.jpg', '/data1')
transport.close()
(3)应用实例
#!/usr/bin/env python
# coding:utf-8
__author__ = "king"
import paramiko
import uuid
class UPfile(object):
def __init__(self):
self.host = '10.0.7.4'
self.port = 2369
self.username = 'tom'
self.pwd = 'xxx'
self.__k = None
def create_file(self):
file_name = str(uuid.uuid4())
with open(file_name,'w') as f:
f.write('hello girls')
return file_name
def run(self):
self.connect()
self.upload()
# self.rename()
self.close()
def connect(self):
transport = paramiko.Transport((self.host,self.port))
transport.connect(username=self.username,password=self.pwd)
self.__transport = transport
def close(self):
self.__transport.close()
def upload(self):
# 连接,上传
file_name = self.create_file()
sftp = paramiko.SFTPClient.from_transport(self.__transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(file_name, '/home/tom/file.py')
def rename(self):
ssh = paramiko.SSHClient()
ssh._transport = self.__transport
# 执行命令
stdin, stdout, stderr = ssh.exec_command('mv /home/tom/file.py /home/tom/.py')
# 获取命令结果
result = stdout.read()
ha = UPfile()
ha.run()
Mysql数据库的基本操作
python 的 mysql 模块安装,用于操作mysql数据库
linux:
yum install MySQL-python
window:
http://files.cnblogs.com/files/wupeiqi/py-mysql-win.zip
1、SQL的基础操作
(1)数据库安装
# 0.1 下载
wget https:// downloads.mariadb.com/archives/mysql-5.5/mysql-5.5.32-linux2.6-x86_64.tar.gz
# 0.2 创建用户及用户组
groupadd -r mysql
useradd -r -g mysql -M -s /sbin/nologin mysql
# 0.3 创建数据目录并设定目录权限
mkdir -p /app/mysql_data/
chown -R mysql.mysql /app/mysql_data/
# 0.4 解压安装包到指定目录
tar zxvf mysql-5.5.32-linux2.6-x86_64.tar.gz -C /app
ln -sv /app/mysql-5.5.32-linux2.6-x86_64/ /app/mysql
chown -R mysql.mysql /app/mysql-5.5.32-linux2.6-x86_64/
# 0.5 初始化配置文件
cd /app/mysql
./scripts/mysql_install_db --user=mysql --basedir=/app/mysql --datadir=/app/mysql_data
# 0.6 复制启动文件与配置文件
cp support-files/mysql.server /etc/init.d/mysqld
cp support-files/my-small.cnf /etc/my.cnf
# 0.7 添加到环境变量
echo "PATH=/app/mysql/bin:$PATH" >> /etc/profile
tail -1 /etc/profile
source /etc/profile
# 0.8 启停服务
/etc/init.d/mysqld start|stop
chkconfig --level 35 mysqld on
(2)数据库操作
mysql> show databases;
mysql> use test;
mysql> create database test;
mysql> drop database test;
(3)数据表操作
mysql> show tables;
mysql> 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 "-"
);
mysql> drop table students;
# or
CREATE TABLE `www_x` (
`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`)
) ;
(4)数据操作
mysql> insert into test.students(name,sex,age,tel) values('tom','man',18,'88881234')
mysql> delete from test.students where id =2;
mysql> update test.students set name = 'sb' where id =1;
mysql> select name,age from test.students
(5)其它知识点
主键 ( primary key )
能够唯一标识表中某一行的属性或属性组。一个表只能有一个主键,但可以有多个候选索引。主键常常与外键构成参照完整性约束,防止出现数据不一致。主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。
外键(foreign key)
是用于建立和加强两个表数据之间的链接的一列或多列。外键约束主要用来维护两个表之间数据的一致性。简言之,表的外键就是另一表的主键,外键将两表联系起来。一般情况下,要删除一张表中的主键必须首先要确保其它表中的没有相同外键(即该表中的主键没有一个外键和它相关联)。
索引 ( index )
是用来快速地寻找那些具有特定值的记录。主要是为了检索的方便,是为了加快访问速度, 按一定的规则创建的,一般起到排序作用。所谓唯一性索引,这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。
总结:
主键一定是唯一性索引,唯一性索引并不一定就是主键。
一个表中可以有多个唯一性索引,但只能有一个主键。
主键列不允许空值,而唯一性索引列允许空值。
主键可以被其他字段作外键引用,而索引不能作为外键引用。
内联接
典型的联接运算,使用像 = 或 <> 之类的比较运算符。
包括相等联接和自然联接。
内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。例如,检索 students和courses表中学生标识号相同的所有行。外联接
外联接可以是左向外联接、右向外联接或完整外部联接。
在 FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:
LEFT JOIN或LEFT OUTER JOIN
左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
RIGHT JOIN 或 RIGHT OUTER JOIN
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
FULL JOIN 或 FULL OUTER JOIN
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。交叉联接
交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉联接也称作笛卡尔积。
FROM 子句中的表或视图可通过内联接或完整外部联接按任意顺序指定;但是,用左或右向外联接指定表或视图时,表或视图的顺序很重要。
2、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)查询数据
# ############################## 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()
reCount = cur.execute('select Name,Address from UserInfo')
nRet = cur.fetchall()
cur.close()
conn.close()
print reCount
print nRet
for i in nRet:
print i[0],i[1]
堡垒机的实现过程
1、思路
(1)堡垒机在架构中的位置与作用
堡垒机在企业应用中是可ssh登录到堡垒保护的内部网络中的入口,它表面的作用如同小区的保卫科,出入者登记,但深层的作用还可以是物业,指定哪片地是你可以胡作非为的。
它在可实现用户跳板登录到真实服务器,可作用户权限、审计控制,可记录用户操作过程
(2)可实现的功能点
流程应该是这样的:
1、管理员创建用户,分配用户可登录的主机或主机组、分配用户可执行的sudo权限
2、用户登录跳板机,查看可操作的主机,登录可操作的主机,上传下载文件,退出
3、用户登录主机,可执行授予的权限
(3)别人家是怎么实现的
crazyeye : 作者:alex,用户体验为负数,我喜欢docker版
jumpserver : 作者:一堆小心眼的程序员,我在群了提出了改进意见,第二天就把我给删了,难道我说错了….
2、实现过程
..