cmdb 这类项目的资产入库等操作,当agent 与server 端通过api 进行数据交互时,为了安全采取了两项安全措施:1、server 端需要对agent 端进行身份验证(避免有冒充agent 请况);2、当agent 采集数据提交到server 端过程需要对数据加密,数据传输到agent 端时再数据解密(防止数据传输过程被截取,泄露数据)。

api 身份认证

认证原理

server 与 agent保存相同的字符串密钥,agent 通过密钥生成签名值,把数据与签名值发送给server 端,server 根据自己的配置文件保存的密钥生成签名值与agent 端签名值比对,两者一致则认证通过否则失败。

安全加强(只针对数据传输中签名被截取安全隐患,暂不考虑server与agent 本地保存的字符串密钥安全隐患)

签名值一次性

agent 每次发送过来的签名值都会被server 记录,每次发送的签名值如果已经使用过则认证失败(防止传输中被截取后黑客可以永久使用被截取的签名密钥来认证)

动态生成签名

由于“签名值一次性”所以签名密钥必须动态生成,每次用不同的密钥。agent 每次生成签名前生成一个时间值,把时间与保存的字符串密钥组合在一起再生成一个签名值。签名值变成了动态。

签名超时设置

agent 每次发送签名与生成签名的时间到server ,server 端接收时会再本段生成一个时间,将两个时间值比较,当时间差超过10s ,则认证失败。(“签名值一次性”中对认证过的签名值记录在了字典中以{"client_time":"签名密钥"}形式存储,为了避免此字典无线增大占用内存,所以会对字典中的时间判断,超过10s 的数据进行删除,但是删除的签名数据再有相同的签名数据来认证时就不能通过“签名一次性”来排除了,所以“签名超时设置”解决了此问题)

 代码

agent 端

import requests
import time
import hashlib


def gen_sign(ctime):
    key = "uiakjsdfasjdf898"                                 #此字符串在server端也保存一份   
    val = "%s|%s" %(key,ctime)                           #加入时间,动态生成签名密钥
    obj = hashlib.md5()                                        #生成一个对象
    obj.update(val.encode('utf-8'))                        #md5只能对字节形式的数据进行加密
    return obj.hexdigest()

ctime = int(time.time()*1000)                              #*1000单位变ms,int 转化为整数(去掉小数点后的数字,而不是四舍五入)
result = requests.post(
    url = 'http://127.0.0.1:8000/api/test/',              #注意路径结尾一定更要以/结尾
    params = {'sign':gen_sign(ctime),'ctime':ctime} #相当于在url = 'http://.../?key="alskdjflskdfjkjk"',也就是在url中以get形式发送数据
)
print(result.url,result.text)

#认证逻辑:agent 把签名密钥与生成签名密钥的时间一并发送到server端,server 端通过自身保存的key与agent 的时间生成签名值,两个签名比对进行认证
View Code

相关文章: