实现目的:通过运维机器人自动获取MFA,不需要找人扫码

将MFA绑定的图片转换成Code,这一步需要手动保存到本地.env环境变量中,后续程序启动后就不需要再绑定了
AliYun_ACCOUNT_MFA_KEY= GetDecryptToken(os.environ['AliYun_ACCOUNT_MFA_KEY'])
JDCloud_ACCOUNT_MFA_KEY = GetDecryptToken(os.environ['JDCloud_ACCOUNT_MFA_KEY'])

def Decode_QR_Code(image_path):
    img = Image.open(image_path)
    decoded_objects = decode(img)
 
    for obj in decoded_objects:
        print('Type : ', obj.type)
        print('Data : ', obj.data.decode('utf-8'))

# Decode_QR_Code('./secret.jpeg')

class GoogleAuthenticatorClient:
    def __init__(self, secret_key=None):
        self.secret_key = secret_key
    
    def create_secret(self, key_length):
        self.secret_key = pyotp.random_base32(key_length)
        return self.secret_key
    
    def create_secret_qrcode(self, secret_key, name=None, issuer_name=None):
        data = pyotp.totp.TOTP(secret_key).provisioning_uri(name=name, issuer_name=issuer_name)
        qr = QRCode(
            version=1,
            error_correction=constants.ERROR_CORRECT_L,
            box_size=6,
            border=4, )
        qr.add_data(data)
        qr.make(fit=True)
        img = qr.make_image()
        img.save('./secret.jpeg')
        buf = BytesIO()
        img.save(buf, "JPEG", quality=70)
        buf_str = buf.getvalue()
        buf_str = base64.b64encode(buf_str)
        return buf_str

    def verify_2fa_code(self, secret_key, code):
        totp = pyotp.TOTP(secret_key)
        verify_flag = totp.verify(code)
        return verify_flag

def Send_Cloud_MFA(erp=None,group_id=None,account=None):
    if account == "aliyun":
        mfa_key = AliYun_ACCOUNT_MFA_KEY
    elif account == "jdcloud":
        mfa_key = JDCloud_ACCOUNT_MFA_KEY
    
    google_auth_client = GoogleAuthenticatorClient(secret_key=mfa_key)
    current_time = int(time.time())
    interval_time = current_time // 30 * 30
    current_totp = pyotp.TOTP(google_auth_client.secret_key)
    current_code = current_totp.at(interval_time)
    remaining_time = 30 - (current_time - interval_time) % 30

    if remaining_time < 15:
        next_interval_time = interval_time + 30
        next_code = current_totp.at(next_interval_time)
        msg = f"【MFA口令】{account} 动态口令是:{current_code},剩余有效期{remaining_time}秒!即将过期,下一次口令是:{next_code}"
    else:
        msg = f"【MFA口令】{account} 动态口令是:{current_code},剩余有效期{remaining_time}秒!"

    BotSendMessage(erp=erp,group_id=group_id,msg=msg)