暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Terraform+Flask+钉钉实现审批流程

耶喝运维 2020-06-28
1468

Terraform 的实现方式

如果只是用命令去创建最终的机器,并不是我想要的东西,我需要把Terraform封装好模块后,跟一个审批工具进行结合,在后端处理创建的过程,我这边选择的实现方式是flask+vue+Terraform+钉钉审批  
网页的功能就是查询谁什么时间开了什么资源这一个功能  
后端只要把钉钉的消息拿到后入库,之后执行Terraform模块,这样就可以把运维手动申请云上资源的工作释放了,变成了审批流

基本概念

首先了解钉钉回调我们要知道几个概念

corpid          # 企业钉钉id
secret          # 企业钉钉密码
agentid         # 微应用id
appkey          # 微应用秘钥
appsecret       # 微应用密码
aes_key         # 随机字符加密使用

corpid与secret通过 https://open-dev.dingtalk.com 基本信息中查看  
agentid、appkey、appsecret我们需要自己创建一个微应用之后拿到对应的值,在应用开发中创建  
aes_key 随机生成一个字符加密使用

钉钉的通信方式

我们与钉钉的通信方式有两种

  • Http通信

  • 回调通信

先说第一种,就是发送http 请求例如 get post put 去查询,修改钉钉里的一些信息,这种显然不符合我的预期,我更希望由钉钉主动发送给我一些消息,所以我看到了第二种回调通信,
由我跟钉钉创建一次三次握手的安全方式,之后钉钉把我想查看的信息发送给我,这样我们就可以实现我们上面说到的一些功能了

钉钉的回调方式

我感觉钉钉借鉴了tcp 的三次握手的协议吧。首先我像钉钉发送一个消息,然后钉钉回给我一个加密的信息,我把他解密之后返回一个success 后,钉钉就跟我建立了连接,之后就会给我的后端推送我想看到的消息

注意:回调地址必须为https

钉钉的加密

在跟钉钉进行回调通信的时候,我们所有的信息都是通过加密传输的,上个python3解密加密的例子---之前不知道从哪个帖子看到的

#!/usr/bin/env python
# -*-coding:utf-8-*-
"""
Author : Yehe
date   : 2020/1/14 16:56
role   : 钉钉加密解密
"""


from random import choice
from Crypto.Cipher import AES
import io
import base64
import binascii
import hashlib
import string
import struct


class DingTalkCrypto:
    def __init__(self, encodingAesKey, key):
        self.encodingAesKey = encodingAesKey
        self.key = key
        self.aesKey = base64.b64decode(self.encodingAesKey + '=')

    def encrypt(self, content):
        """
        加密
        """

        msg_len = self.length(content)
        content = self.generateRandomKey(16) + msg_len.decode() + content + self.key
        contentEncode = self.pks7encode(content)
        iv = self.aesKey[:16]
        aesEncode = AES.new(self.aesKey, AES.MODE_CBC, iv)
        aesEncrypt = aesEncode.encrypt(contentEncode)
        return base64.b64encode(aesEncrypt).decode().replace('\n''')

    def length(self, content):
        """
        将msg_len转为符合要求的四位字节长度
        """

        l = len(content)
        return struct.pack('>l', l)

    def pks7encode(self, content):
        """
        安装 PKCS#7 标准填充字符串
        """

        l = len(content)
        output = io.StringIO()
        val = 32 - (l % 32)
        for _ in range(val):
            output.write('%02x' % val)
        return bytes(content, 'utf-8') + binascii.unhexlify(output.getvalue())

    def pks7decode(self, content):
        nl = len(content)
        val = int(binascii.hexlify(content[-1].encode()), 16)
        if val > 32:
            raise ValueError('Input is not padded or padding is corrupt')
        l = nl - val
        return content[:l]

    def decrypt(self, content):
        """
        解密数据
        """

        # 钉钉返回的消息体
        content = base64.b64decode(content)
        iv = self.aesKey[:16]  # 初始向量
        aesDecode = AES.new(self.aesKey, AES.MODE_CBC, iv)
        decodeRes = aesDecode.decrypt(content)[20:].decode().replace(self.key, '')
        # 获取去除初始向量,四位msg长度以及尾部corpid
        return self.pks7decode(decodeRes)

    def generateRandomKey(self, size,
                          chars=string.ascii_letters + string.ascii_lowercase + string.ascii_uppercase + string.digits)
:

        """
        生成加密所需要的随机字符串
        """

        return ''.join(choice(chars) for i in range(size))

    def generateSignature(self, nonce, timestamp, token, msg_encrypt):
        """
        生成签名
        """

        signList = ''.join(sorted([nonce, timestamp, token, msg_encrypt])).encode()
        return hashlib.sha1(signList).hexdigest()

我们使用这个方法就可以和钉钉建立回调了,之后就是设计审批模板,只要保证审批的流程是Terraform最终需要获取的数据,当我们拿到数据后,把他存到数据库中(为后期查询方便做准备)附上两个图片
数据库结构  

审批结构  

庆祝一下工作又少了

文章转载自耶喝运维,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论