本文目录导读:

- ⚠️ 重要安全警告
- 场景一:清理用户
~/.ssh/目录下未使用的SSH密钥对 - 场景二:清理云服务商(AWS/Azure/GCP)中未使用的密钥对
- 场景三:清理应用程序或数据库中的过期API密钥
- 场景四:清理系统密钥环(GPG/PGP密钥)
- 通用自动化策略(推荐)
- 快速自动化计划任务示例(Cron)
- 最后建议
自动化清理未使用的密钥(如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
最后建议
- 先硬编码白名单:在脚本中加入
WHITE_LIST(如admin_key,deploy_key),绝对不要删除这些密钥。 - 分阶段执行:先用
--dry-run运行一段时间,确认无误后再开启自动删除。 - 监控反馈:清理后检查关键服务日志,确保没有因密钥缺失导致认证失败。
如果提供具体密钥类型(如 Kubernetes Secret、TLS证书等)和环境细节,可以给出更针对性的脚本。