【1】. 做CMDB目的、方法和涉及到问题
【2】.CMDB采集数据唯一标识
【3】. ssh/salt并发执行采集数据
【4】.将数据入库
【5】.API验证
【1】. 做CMDB目的、方法和涉及到问题:
1.为什么要做CMDB?
之前是使用excel表格来做资产统计,但是记录的变更日志的时候,资产信息的不是很准确
目标:让资产收集变的自动化
2.CMDB的架构是什么?
-资产采集
-API
-web展示系统
3.你负责项目的哪一块?
-资产采集
-agent模式:
优点:速度快
确定:每台机器都需要部署
场景:机器比较多的时候
-ssh类的模式
优点:不用部署
确定:速度慢
场景:机器比较少的情况
-saltstack模式
优点:速度快
确定:每台机器都需要安装salt
场景:已经部署了saltstack软件,或者想要部署的
采用的思想:
高内聚低耦合
-参考django的配置文件的设置
-面向对象的反射,实现了资产采集插件的可插拔
4.遇到了哪些问题?
技术问题永远不是问题
沟通才是问题的根本
-和产品经理的沟通
-返回字段有问题
-标准流程
唯一标识
【2】.CMDB采集数据唯一标识
唯一标识
-使用sn号做唯一标识:
问题:虚拟机和物理机共享一个sn号
-使用hostname作为唯一标识
问题:
1.可以随意改变
2.会重复
标准流程:
1.装机完成后,打开CMDBweb界面,给一个唯一的hostname
2.继续录入机房信息,机架号,几层
3.需要把CMDB采集代码(autoclient),放到服务器的某一个目录
4.运行,收集资产
5.将hostname写入文件中(c1.com)
然后以后,以文件中的hostname为准
ssh/salt不需要上面配置,因为中控机如果找不到这台主机,也就无法登陆收集到信息
2.1-autoclient-config-settings.py
添加下面参数:
CERT_PATH=os.path.join(BASEDIR,'config','cert')
2.2-autoclient-src-client.py
添加下面参数:
class Agent(Base): def execute(self): res = Plugins().execute() hostname = res['basic']['data']['hostname'] certname = open(settings.CERT_PATH, 'r', encoding='utf-8').read().strip() if not certname: with open(settings.CERT_PATH, 'w', encoding='utf-8') as fp: fp.write(hostname) else: res['basic']['data']['hostname'] = certname for k, v in res.items(): print(k, v) self.post_inf(res)
【3】. ssh/salt并发执行采集数据
ssh/salt的问题
拿到主机名顺序的执行
解决问题:
并发
进程池或者线程池
python2:
线程池:无
进程池:有
python3:
线程池:有
进程池:有
线程池使用举例:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def task(i): time.sleep(1) print(i) p=ThreadPoolExecutor(10) for i in range(100): p.submit(task,i)
3.1-autoclient-src-client.py
添加下面参数:
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
class SSHSalt(Base): def get_hostname(self): host_list = requests.get(settings.API) # [10.0.0.1,10.0.0.2] return host_list def __run(self,hostname): res = Plugins(hostname).execute() self.post_inf(res) def execute(self): p=ThreadPoolExecutor(10) for hostname in settings.get_hostname(): p.submit(self.__run,hostname)
命令解释:
uname
cat /etc/issue 版本
hostname 主机名
dmidecode 收集主板信息
cat /proc/cpuinfo 收集cpu信息
Megacli 收集raid磁盘信息
【4】.将数据入库
在autoserver服务配置进行数据处理
1.-autoserver\urls.py 下面打开配置url('admin/', admin.site.urls),后台添加数据
2.-autoserver\settings.py 下面添加下面配置 INSTALLED_APPS = ['api','backend','repos']
3.-autoserver\settings.py 下面添加下面配置数据库 DATABASES
4.-repos-__init__.py 在下面配置调用数据库
import pymysql
pymysql.install_as_MySQLdb()
5.通过makemigrations建立ORM关系数据库,配置文件在models.py
启动文件后,在django的adim后台配置数据:用户表-用户组表-业务线表-机房表-资产表-服务器表
业务线/产品线
微博:
-微博资讯100
-信息流200
【5】.API验证
1.设置静态token:
缺点
2.设置动态Token:
缺点:和静态token一样
上述两个方案,都是容易配黑客获取token
3.维护一个列表:
dict={k,v}
测试字典删除值:
api_dic={
"k1":'v1',
"k2":'v2',
"k3":'v3',
}
# print(api_dic)
# print(list(api_dic.keys()))
for k in list(api_dic.keys()):
if "k1"==k:
del api_dic[k]
print(api_dic)
【5.1】.第一种方式 静态token
def asset(request):
if request.method == 'GET':
server_token = "ngfdngkmgfdsmgffnkdgnrtjkewngrt"
client_token =
request.META.get('HTTP_TOKEN')
####### 第一种方式 静态token
client_token = request.META.get('HTTP_TOKEN')
if client_token != server_token:
return HttpResponse('非法Token')
return HttpResponse('非常重要的数据')
测试静态token方法:
-config-settings.py
API="http://127.0.0.1:8020/api/asset/"
TOKEN="abcd"
normal.py
from lib.conf.config import settings
import requests
#a.设置一个静态的TOKEN
res=requests.get(settings.API,headers={'TOKEN':settings.TOKEN})
print(res.text)
【5.2】.第二种方式 动态TOKEN
def asset(request):
if request.method
== 'GET':
server_token = "ngfdngkmgfdsmgffnkdgnrtjkewngrt"
client_token = request.META.get('HTTP_TOKEN')
####### 第二种方式 动态TOKEN
clinet_md5_token, client_time = client_token.split('|')
tmp = '%s|%s' %
(server_token, client_time)
m = hashlib.md5()
m.update(bytes(tmp, encoding='utf8'))
server_md5_token = m.hexdigest()
if server_md5_token
!= clinet_md5_token:
return HttpResponse('小伙子, 是不是篡改了数据')
return HttpResponse('非常重要的数据')
测试动态token方法:
-config-settings.py
API="http://127.0.0.1:8020/api/asset/"
TOKEN="abcd"
normal.py
from lib.conf.config import settings
import requests
#b.设置生成一个动态的token
client_time=time.time()
tmp="%s|%s" %(settings.TOKEN,client_time)
m=hashlib.md5()
m.update(bytes(tmp,encoding='utf8'))
res=m.hexdigest()
client_token="%s|%s" %(res,client_time)
print(client_token)
res=requests.get(settings.API,headers={'TOKEN':client_token})
print(res.text)
【5.3】.第三种方式:防止TOKEN重复利用
def asset(request):
if request.method
== 'GET':
server_token = "ngfdngkmgfdsmgffnkdgnrtjkewngrt"
client_token = request.META.get('HTTP_TOKEN')
server_time = time.time()
clinet_md5_token, client_time =
client_token.split('|')
client_time = float(client_time)
if server_time
- client_time > 50:
return HttpResponse('[第一关] 小伙子, 超时了')
tmp = '%s|%s' %
(server_token, client_time)
m = hashlib.md5()
m.update(bytes(tmp, encoding='utf8'))
server_md5_token = m.hexdigest()
if server_md5_token
!= clinet_md5_token:
return HttpResponse('[第二关]小伙子, 是不是篡改了数据')
"""
api_dict = {
#
"b17140eac377c153944e1b00b5122c22|1548492540.4952028" :
"1548492550.4952028"
}
"""
for k in list(api_dict.keys()):
if time.time()
> api_dict[k]:
del api_dict[k]
if client_token in api_dict:
return HttpResponse('[第三关] 已经别人使用了')
else:
# set client_token
clinet_time 10
api_dict[client_token] = client_time + 10
return HttpResponse('非常重要的数据')
测试TOKEN重复利用方法:
-config-settings.py
API="http://127.0.0.1:8020/api/asset/"
TOKEN="abcd"
normal.py
from lib.conf.config import settings import requests
client_time=time.time() tmp="%s|%s" %(settings.TOKEN,client_time) m=hashlib.md5() m.update(bytes(tmp,encoding='utf8')) res=m.hexdigest() client_token="%s|%s" %(res,client_time) print(client_token) res=requests.get(settings.API,headers={'TOKEN':client_token}) print(res.text)
8081d59e9e23b29cd95a93a3207b1eed|1551253206.992303
Hack.py
import requests
res=requests.get('http://127.0.0.1:8020/api/asset/',headers={'TOKEN':" 8081d59e9e23b29cd95a93a3207b1eed|1551253206.992303"})
print(res.text)