自动化脚本如何清理未使用密钥

wen 实用脚本 24

本文目录导读:

自动化脚本如何清理未使用密钥

  1. ⚠️ 重要安全警告
  2. 场景一:清理用户~/.ssh/目录下未使用的SSH密钥对
  3. 场景二:清理云服务商(AWS/Azure/GCP)中未使用的密钥对
  4. 场景三:清理应用程序或数据库中的过期API密钥
  5. 场景四:清理系统密钥环(GPG/PGP密钥)
  6. 通用自动化策略(推荐)
  7. 快速自动化计划任务示例(Cron)
  8. 最后建议

自动化清理未使用的密钥(如SSH密钥、API密钥、加密密钥等)需要分场景进行,因为不同系统的密钥存储位置和管理方式差异很大,以下提供几种常见场景的自动化脚本思路及示例,请根据实际环境调整。


⚠️ 重要安全警告

  • 备份:清理前务必对密钥库或配置文件进行完整备份。
  • 测试环境:先在非生产环境充分测试。
  • 最小权限:确保脚本运行账号仅具备读取和清理所需的最小权限。

清理用户~/.ssh/目录下未使用的SSH密钥对

原理:检查私钥文件是否被authorized_keys引用,或检查known_hosts中是否包含对应公钥指纹。

脚本:clean_ssh_keys.sh

#!/bin/bash
# 清理 ~/.ssh/ 中未被 authorized_keys 或 known_hosts 引用的私钥
SSH_DIR="$HOME/.ssh"
AUTH_KEYS="$SSH_DIR/authorized_keys"
KNOWN_HOSTS="$SSH_DIR/known_hosts"
BACKUP_DIR="$SSH_DIR/backup_$(date +%Y%m%d%H%M%S)"
# 只处理常见的私钥文件模式
PRIVATE_KEY_PATTERNS="id_rsa id_ecdsa id_ed25519 id_dsa id_ecdsa_sk id_ed25519_sk"
mkdir -p "$BACKUP_DIR"
for key in $PRIVATE_KEY_PATTERNS; do
    priv="$SSH_DIR/$key"
    pub="$SSH_DIR/$key.pub"
    if [ -f "$priv" ]; then
        # 提取公钥指纹
        if [ -f "$pub" ]; then
            fingerprint=$(ssh-keygen -lf "$pub" 2>/dev/null | awk '{print $2}')
        else
            # 从私钥提取公钥再计算指纹
            fingerprint=$(ssh-keygen -y -f "$priv" 2>/dev/null | ssh-keygen -lf /dev/stdin 2>/dev/null | awk '{print $2}')
        fi
        if [ -n "$fingerprint" ]; then
            # 检查指纹是否在 authorized_keys 或 known_hosts 中
            if grep -q "$fingerprint" "$AUTH_KEYS" 2>/dev/null || grep -q "$fingerprint" "$KNOWN_HOSTS" 2>/dev/null; then
                echo "[保留] $key (指纹: $fingerprint)"
            else
                echo "[未使用] $key (指纹: $fingerprint)"
                # 备份并删除
                cp "$priv" "$BACKUP_DIR/" && cp "$pub" "$BACKUP_DIR/" 2>/dev/null
                rm -f "$priv" "$pub"
                echo "  已移至 $BACKUP_DIR"
            fi
        else
            echo "[警告] 无法读取 $key 的指纹,跳过"
        fi
    fi
done
echo "清理完成,备份文件位于: $BACKUP_DIR"

清理云服务商(AWS/Azure/GCP)中未使用的密钥对

AWS EC2 密钥对 为例(原理:检查密钥对是否与任何 EC2 实例关联)。

脚本:clean_aws_keys.py(需安装 boto3

#!/usr/bin/env python3
import boto3
import sys
def clean_unused_key_pairs():
    ec2 = boto3.client('ec2')
    # 获取所有密钥对
    key_pairs = ec2.describe_key_pairs()['KeyPairs']
    # 获取所有正在使用的密钥对名称(从实例中获取)
    instances = ec2.describe_instances(Filters=[{'Name': 'key-name', 'Values': ['*']}])
    used_keys = set()
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            if 'KeyName' in instance:
                used_keys.add(instance['KeyName'])
    # 找出未使用的密钥对
    unused_keys = [kp for kp in key_pairs if kp['KeyName'] not in used_keys]
    if not unused_keys:
        print("没有未使用的密钥对。")
        return
    print("以下密钥对未被任何 EC2 实例使用:")
    for kp in unused_keys:
        print(f"  - {kp['KeyName']} (创建时间: {kp.get('CreateTime', 'N/A')})")
    # 确认删除
    confirm = input("是否删除以上所有未使用密钥对? (yes/no): ")
    if confirm.lower() == 'yes':
        for kp in unused_keys:
            try:
                ec2.delete_key_pair(KeyName=kp['KeyName'])
                print(f"已删除: {kp['KeyName']}")
            except Exception as e:
                print(f"删除 {kp['KeyName']} 失败: {e}", file=sys.stderr)
    else:
        print("取消操作。")
if __name__ == "__main__":
    clean_unused_key_pairs()

清理应用程序或数据库中的过期API密钥

示例:清理 MySQL 中90天未使用的API密钥表

-- 创建清理存储过程
DELIMITER //
CREATE PROCEDURE CleanUnusedApiKeys()
BEGIN
    DECLARE deleted_count INT;
    -- 假设表结构: api_keys (id, api_key, last_used_at, created_at)
    DELETE FROM api_keys 
    WHERE (last_used_at IS NULL AND created_at < NOW() - INTERVAL 90 DAY)
       OR (last_used_at IS NOT NULL AND last_used_at < NOW() - INTERVAL 90 DAY);
    SET deleted_count = ROW_COUNT();
    SELECT CONCAT('已删除 ', deleted_count, ' 个未使用API密钥。') AS result;
END //
DELIMITER ;
-- 调用存储过程
CALL CleanUnusedApiKeys();
-- 查看结果
SELECT * FROM api_keys WHERE last_used_at IS NULL OR last_used_at < NOW() - INTERVAL 90 DAY;

清理系统密钥环(GPG/PGP密钥)

脚本:clean_gpg_keys.sh(清理所有无关联私钥的过期公钥)

#!/bin/bash
# 清理 GPG 中已过期且无关联私钥的公钥
gpg --list-keys --keyid-format LONG | grep -E "^pub|^uid|^sub" | while read line; do
    if echo "$line" | grep -q "^pub"; then
        # 提取密钥ID和过期信息
        keyid=$(echo "$line" | awk '{print $2}' | cut -d'/' -f2)
        expiry=$(echo "$line" | grep -oP "\[expires: \K[^\]]+")
        if [ -n "$expiry" ] && date -d "$expiry" +%s >/dev/null 2>&1; then
            expiry_ts=$(date -d "$expiry" +%s)
            now_ts=$(date +%s)
            if [ $expiry_ts -lt $now_ts ]; then
                # 检查是否有对应的私钥
                if ! gpg --list-secret-keys $keyid >/dev/null 2>&1; then
                    echo "过期公钥(无对应私钥): $keyid"
                    gpg --batch --yes --delete-key $keyid 2>/dev/null && echo "  已删除"
                else
                    echo "过期公钥(仍有私钥): $keyid (跳过)"
                fi
            fi
        fi
    fi
done

通用自动化策略(推荐)

阶段 动作 工具/方法
发现 扫描所有密钥存储位置 find, boto3, Azure CLI, gcloud
关联分析 检查密钥是否被任何资源引用 系统日志、资源属性、数据库最后使用时间
标记 生成未使用密钥报告 CSV/JSON/HTML 报告
确认 人工或自动确认删除 邮件审批/Slack通知
清理 执行删除,保留备份 rm -f, API调用, SQL DELETE
审计 记录操作日志 写入 syslog 或审计数据库

快速自动化计划任务示例(Cron)

# 每天凌晨2点运行SSH密钥清理(仅报告,不删除)
0 2 * * * /home/admin/scripts/clean_ssh_keys.sh --dry-run >> /var/log/key_cleanup.log 2>&1
# 每周一凌晨3点运行AWS密钥清理(自动删除)
0 3 * * 1 python3 /home/admin/scripts/clean_aws_keys.py --auto-delete >> /var/log/key_cleanup.log 2>&1

最后建议

  1. 先硬编码白名单:在脚本中加入 WHITE_LIST(如 admin_key, deploy_key),绝对不要删除这些密钥。
  2. 分阶段执行:先用 --dry-run 运行一段时间,确认无误后再开启自动删除。
  3. 监控反馈:清理后检查关键服务日志,确保没有因密钥缺失导致认证失败。

如果提供具体密钥类型(如 Kubernetes Secret、TLS证书等)和环境细节,可以给出更针对性的脚本。

抱歉,评论功能暂时关闭!