Frank的学习之路

Day_27_CMDB_2_总结_信息存储和API验证

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

     启动文件后,在djangoadim后台配置数据:用户表-用户组表-业务线表-机房表-资产表-服务器表   

     业务线/产品线

     微博:

         -微博资讯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)

返回顶部