《云端安全守护者:深入解析阿里云域名证书管理脚本ListUserCertificateOrder_from_aliyun.py》

本文旨在详细介绍一款基于阿里云API的Python脚本——ListUserCertificateOrder_from_aliyun.py,该脚本用于查询和管理阿里云账户下的域名证书信息。将从脚本的安装、配置、功能使用以及版本迭代优化等方面进行深入剖析,帮助读者掌握如何高效地利用该脚本进行证书管理,确保域名安全。


v1.0.1版本(基于SDK开发)

该版本实现了基本的功能需求,即通过阿里云SDK获取账户下所有的域名证书信息并打印出来

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 脚本名称: ListUserCertificateOrder_from_aliyun_v1.0.1.py
# 用法: /usr/bin/python3 /data/python/ListUserCertificateOrder_from_aliyun_v1.0.1.py > /var/log/ListUserCertificateOrder_from_aliyun_v1.0.1.py.log 2>&1 
# 作者: 朱鹏飞(Richard) <zhupengfei@xxx.com>
# 日期: 2024年9月24日 14:03
# 最近更新:2024年9月24日 16:18
# SDK 安装命令:pip3 install alibabacloud_cas20200407==2.0.1
# 注意事项:
#   - 在 Alibaba Cloud Linux 3.2104 LTS 64位 系统上可能会遇到 ModuleNotFoundError: No module named 'multidict' 问题
#   - 解决方式:pip3 install multidict && pip3 install typing_extensions && pip3 install attrs && pip3 install yarl && pip3 install async_timeout && pip3 install idna_ssl  && pip3 install aiosignal && pip3 install charset_normalizer && pip3 install aiohttp

import os
import sys
import configparser  # 用于读取ini配置文件文件,官方推荐的是读取环境变量信息,为方便我封装容器调用,这里我读取配置文件

from typing import List

from alibabacloud_cas20200407.client import Client as cas20200407Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_cas20200407 import models as cas_20200407_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def load_config_from_ini(file_path: str) -> dict:
        """
        读取ini配置文件然后加载
        :param file_path: ini配置文件路径
        :return: 包含配置项的字典
        """
        config = configparser.RawConfigParser()
        config.read(file_path)
        return {
            'ALIBABA_CLOUD_ACCESS_KEY_ID': config.get('it_zpf_w', 'ALIBABA_CLOUD_ACCESS_KEY_ID'),
            'ALIBABA_CLOUD_ACCESS_KEY_SECRET': config.get('it_zpf_w', 'ALIBABA_CLOUD_ACCESS_KEY_SECRET')
        }

    @staticmethod
    def create_client() -> cas20200407Client:
        """
        使用AK&SK初始化账号Client
        @return: Client
        @throws Exception
        """
        config_data = Sample.load_config_from_ini('/data/app/aliyun/aksk.ini')  # 从ini文件读取配置
        print(f"Access Key ID: {config_data['ALIBABA_CLOUD_ACCESS_KEY_ID']}")
        print(f"Access Key Secret: {config_data['ALIBABA_CLOUD_ACCESS_KEY_SECRET']}")

        config = open_api_models.Config(
            access_key_id=config_data['ALIBABA_CLOUD_ACCESS_KEY_ID'],
            access_key_secret=config_data['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
        )
        config.endpoint = 'cas.aliyuncs.com'
        return cas20200407Client(config)

    @staticmethod
    def main(args: List[str]) -> None:
        client = Sample.create_client()
        list_user_certificate_order_request = cas_20200407_models.ListUserCertificateOrderRequest(
            order_type='CERT'
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = client.list_user_certificate_order_with_options(list_user_certificate_order_request, runtime)
            print("Response:", response)
        except Exception as error:
            print("Error:", error.message)
            print("Recommend:", error.data.get("Recommend"))
            UtilClient.assert_as_string(error.message)

    @staticmethod
    async def main_async(args: List[str]) -> None:
        client = Sample.create_client()
        list_user_certificate_order_request = cas_20200407_models.ListUserCertificateOrderRequest(
            order_type='CERT'
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = await client.list_user_certificate_order_with_options_async(list_user_certificate_order_request, runtime)
            print("Response:", response)
        except Exception as error:
            print("Error:", error.message)
            print("Recommend:", error.data.get("Recommend"))
            UtilClient.assert_as_string(error.message)

if __name__ == '__main__':
    Sample.main(sys.argv[1:])

执行效果:

[root@Dev-RockyLinux9-Area1-Shanghai python]# python3 ListUserCertificateOrder_from_aliyun_v1.0.1.py

解析:
导入模块:引入了os、sys、configparser等模块,以及阿里云SDK的相关模块。
配置读取:通过load_config_from_ini函数从INI文件中读取阿里云账户的Access Key ID和Access Key Secret。
初始化客户端:create_client函数使用读取到的配置信息创建阿里云SDK客户端。
主函数:main函数调用SDK的list_user_certificate_order_with_options方法,列出所有查询到的域名证书信息。主函数:main函数调用SDK的list_user_certificate_order_with_options方法,列出所有查询到的域名证书信息。


v1.0.2版本(核心代码):

此版本增加了密钥掩码功能,提高了安全性,并且能够提取响应数据中的SANs和到期日期,增强了用户体验

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 脚本名称: ListUserCertificateOrder_from_aliyun_v1.0.2.py
# 用法: /usr/bin/python3 /data/python/ListUserCertificateOrder_from_aliyun_v1.0.2.py > /var/log/ListUserCertificateOrder_from_aliyun_v1.0.2.py.log 2>&1 
# 作者: 朱鹏飞(Richard) <zhupengfei@xxx.com>
# 日期: 2024年9月24日 14:03
# 最近更新:2024年9月25日 10:09
# SDK 安装命令:pip3 install alibabacloud_cas20200407==2.0.1
# 注意事项:
#   - 在 Alibaba Cloud Linux 3.2104 LTS 64位 系统上可能会遇到 ModuleNotFoundError: No module named 'multidict' 问题
#   - 解决方式:pip3 install multidict && pip3 install typing_extensions && pip3 install attrs && pip3 install yarl && pip3 install async_timeout && pip3 install idna_ssl  && pip3 install aiosignal && pip3 install charset_normalizer && pip3 install aiohttp
...
def mask_key(key: str) -> str:
    if len(key) < 6:
        return key
    masked_key = key[:3] + '*' * (len(key) - 6) + key[-3:]
    return masked_key

def main(args: List[str]) -> None:
    client = Sample.create_client()
    list_user_certificate_order_request = cas_20200407_models.ListUserCertificateOrderRequest(order_type='CERT')
    runtime = util_models.RuntimeOptions()
    try:
        response = client.list_user_certificate_order_with_options(list_user_certificate_order_request, runtime)
        certificate_order_list = response.body.certificate_order_list
        Sample.print_sans_and_end_dates(certificate_order_list)
    except Exception as error:
        print("Error:", str(error))
        if hasattr(error, 'data') and error.data is not None:
            print("Recommend:", error.data.get("Recommend"))
        else:
            print("No additional data available")
        UtilClient.assert_as_string(str(error))

def print_sans_and_end_dates(certificate_list):
    for certificate in certificate_list:
        sans = certificate.sans if certificate.sans else ''
        end_date = certificate.end_date if certificate.end_date else ''
        print(f'Sans: {sans}, End Date: {end_date}')
...

执行效果:

[root@Dev-RockyLinux9-Area1-Shanghai python]# python3 ListUserCertificateOrder_from_aliyun_v1.0.2.py
Access Key ID: LTA******************mgu
Access Key Secret: m8Y************************cjA


v1.0.3版本(核心代码):

最新版本不仅继续提升了安全性,还加入了证书到期天数计算及通知功能,实现了自动化监控和预警

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 脚本名称: ListUserCertificateOrder_from_aliyun_v1.0.3.py
# 用法: /usr/bin/python3 /data/python/ListUserCertificateOrder_from_aliyun_v1.0.3.py > /var/log/ListUserCertificateOrder_from_aliyun_v1.0.3.py.log 2>&1 
# 作者: 朱鹏飞(Richard) <zhupengfei@xxx.com>
# 日期: 2024年9月24日 14:03
# 最近更新:2024年9月27日 11:18
# SDK 安装命令:pip3 install alibabacloud_cas20200407==2.0.1
# 注意事项:
#   - 在 Alibaba Cloud Linux 3.2104 LTS 64位 系统上可能会遇到 ModuleNotFoundError: No module named 'multidict' 问题
#   - 解决方式:pip3 install multidict && pip3 install typing_extensions && pip3 install attrs && pip3 install yarl && pip3 install async_timeout && pip3 install idna_ssl  && pip3 install aiosignal && pip3 install charset_normalizer && pip3 install aiohttp
...
def calculate_days_until_expiry(end_date_str: str) -> int:
    end_date = datetime.strptime(end_date_str, '%Y-%m-%d')
    today = datetime.today()
    days_until_expiry = (end_date - today).days
    return days_until_expiry

def print_sans_and_end_dates(certificate_list) -> str:
    output = "| Sans | End Date | Days Until Expiry |\n"
    output += "|------|----------|------------------|\n"
    for certificate in certificate_list:
        sans = certificate.sans if certificate.sans else ''
        end_date = certificate.end_date if certificate.end_date else ''
        days_until_expiry = Sample.calculate_days_until_expiry(end_date)

        if days_until_expiry < 90:
            output += f"| **{sans}** | **{end_date}** | **<font color=\"red\">{days_until_expiry}</font>** |\n"
        else:
            output += f"| {sans} | {end_date} | {days_until_expiry} |\n"
    return output

def send_notification(message: str):
    webhook_url = "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
    headers = {'Content-Type': 'application/json'}
    payload = {
        "msg_type": "interactive",
        "card": {
            "config": {
                "wide_screen_mode": True
            },
            "elements": [
                {
                    "tag": "div",
                    "text": {
                        "content": message,
                        "tag": "lark_md"
                    }
                }
            ],
            "header": {
                "template": "blue",
                "title": {
                    "content": "xxx Certificate Details | xxx 域名证书检测提醒",
                    "tag": "plain_text"
                }
            }
        }
    }
    response = requests.post(webhook_url, json=payload, headers=headers)
    if response.status_code == 200:
        print("Notification sent successfully.")
    else:
        print(f"Failed to send notification. Status code: {response.status_code}")
...

效果:

[root@Dev-RockyLinux9-Area1-Shanghai python]# python3 ListUserCertificateOrder_from_aliyun_v1.0.3py
Access Key ID: LTA******************mgu
Access Key Secret: m8Y************************cjA
Notification sent successfully.

解析:
到期天数计算:新增calculate_days_until_expiry函数,计算证书到期天数。
格式化输出:优化print_sans_and_end_dates函数,将证书信息格式化为Markdown表格,便于查看。
飞书告警:新增send_notification函数,将证书信息发送到飞书群聊,实现实时监控和告警。


通过上述三个版本的迭代,ListUserCertificateOrder_from_aliyun.py脚本在功能性和易用性方面得到了显著提升,成为了阿里云账户证书管理的有效工具。特别是v1.0.2版引入了密钥掩码机制,增强了安全性;而v1.0.3版则进一步实现了自动化监控和告警功能,极大地便利了运维人员的工作。

上一篇
下一篇