自动化脚本如何清理未使用API令牌

wen 实用脚本 20

API安全必修课:如何用自动化脚本精准清理未使用的API令牌

📖 目录导读

  1. 为什么未使用的API令牌是定时炸弹?(风险分析)
  2. 清理前的审计清单:你需要收集哪些信息?
  3. 高效自动化脚本实战:Python+GitHub API 示例
  4. 常见问题问答(FAQ)
  5. 持续治理:防止令牌堆积的4条策略

为什么未使用的API令牌是定时炸弹?

在企业DevOps实践中,开发者往往因为快速迭代而创建大量API令牌(Token)。据Cloudflare 2023年安全报告显示,超过62%的企业存在有效期超180天的僵尸令牌,这些被遗忘的凭证是内部威胁与外部攻击的首要切入点——攻击者一旦通过旧代码仓库、日志泄漏或员工设备获取令牌,即可绕过所有认证机制直达核心数据。

自动化脚本如何清理未使用API令牌

用户痛点场景:某SaaS公司因未清理测试环境的旧令牌,导致攻击者利用泄漏的GitHub Personal Access Token克隆了整个私有仓库,损失估值达200万美元,自动化脚本清理不仅是为了合规(如SOC2、PCI-DSS),更是防御性安全的底层守门人。


清理前的审计清单

在写脚本前,必须回答三个核心问题:

  1. 令牌的元数据来源是什么?

    • 是否存储于代码仓库的环境变量(如.env)?
    • 是否通过CI/CD系统(如Jenkins、GitHub Actions)自动注入?
  2. 判断“未使用”的合理阈值是多少?

    • 建议统一采用90天无API调用作为基准(可参考AWS IAM的未使用凭证策略)。
  3. 谁拥有删除权限?

    • 必须确保脚本不会误删正在生效的生产令牌,建议建立双人复核机制:脚本仅生成候选清单,人工确认后执行。

高效自动化脚本实战:Python+GitHub API 示例

以下脚本将从GitHub组织仓库中扫描所有Personal Access Tokens(classic),识别并标记超过90天未更新的令牌,生成CSV报告供管理员确认删除。

import requests
from datetime import datetime, timedelta
import csv
# 核心配置
ORG_NAME = "your-org"
GITHUB_TOKEN = "ghp_your_admin_token"  # 需具有org:admin权限
BASE_URL = "https://api.github.com"
THRESHOLD_DAYS = 90
def get_all_tokens():
    """获取组织内所有活跃令牌"""
    headers = {"Authorization": f"token {GITHUB_TOKEN}", "Accept": "application/vnd.github.v3+json"}
    url = f"{BASE_URL}/orgs/{ORG_NAME}/tokens"
    tokens = []
    while url:
        resp = requests.get(url, headers=headers)
        if resp.status_code != 200:
            print(f"API调用失败: {resp.status_code}")
            break
        tokens.extend(resp.json())
        url = resp.links.get('next', {}).get('url')  # 处理分页
    return tokens
def filter_stale_tokens(tokens):
    """筛选出超过阈值的未使用令牌"""
    cutoff = datetime.utcnow() - timedelta(days=THRESHOLD_DAYS)
    stale = []
    for token in tokens:
        # 假设API返回字段包含 last_used_at
        last_used = token.get("last_used_at")
        if not last_used:
            continue
        last_used_date = datetime.strptime(last_used, "%Y-%m-%dT%H:%M:%SZ")
        if last_used_date < cutoff:
            stale.append({
                "id": token["id"],
                "name": token.get("name", "unnamed"),
                "last_used": last_used,
                "expires_at": token.get("expires_at"),
                "permissions": token.get("scopes", []),
            })
    return stale
def generate_report(stale_tokens):
    """输出CSV报告"""
    with open("stale_tokens_report.csv", "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=["id", "name", "last_used", "expires_at", "permissions"])
        writer.writeheader()
        writer.writerows(stale_tokens)
    print(f"已生成报告:共发现 {len(stale_tokens)} 个僵尸令牌。")
if __name__ == "__main__":
    tokens = get_all_tokens()
    stale = filter_stale_tokens(tokens)
    generate_report(stale)

脚本关键说明

  • 分页处理:根据GitHub API文档,令牌列表可能超过单页响应大小,必须处理next链接。
  • 安全设计:脚本仅生成报告,不执行自动删除,管理员需审核CSV后,调用DELETE /orgs/{org}/tokens/{token_id}手动操作。
  • 适应扩展:若使用AWS Secret Manager或HashiCorp Vault,只需替换数据源层逻辑,核心过滤算法可复用。

常见问题问答(FAQ)

Q1:如何确保不会误删正在使用的令牌?

A:采用“两步走”策略:
1)脚本基于API调用日志(如CloudTrail、GitHub Audit Log)判断“最后一次使用时间”,而非令牌是否被代码引用。
2)先导出候选清单,由团队主管在灰度环境(非生产)执行删除测试,观察24小时无故障后,再批量处理。

Q2:对于通过IAM角色生成的临时凭证(如AWS STS),需要清理吗?

A:临时凭证由AWS自动轮转,但根用户访问密钥(AWS Access Keys)依然需要监控,建议统一将“最后使用时间大于60天”的IAM密钥标记为旋转(Rotate),可参考:

aws iam list-access-keys --user-name <user> | jq '.AccessKeyMetadata[] | select(.Status=="Active")'

Q3:如果令牌存储在多个应用的环境变量中,如何追踪?

A:引入凭据管理系统

  • 开源方案:使用Vault的vault kv get -format=json扫描所有挂载路径。
  • SaaS方案:GitHub Secrets默认支持创建时自动生成指纹,可配合gh secret list命令导出。
    关键:所有令牌必须带有元数据标签(如purpose=production),脚本以此为依据设置排除规则。

Q4:脚本执行频率如何设定?

A:建议每月运行一次审计脚本,同时结合以下事件驱动:

  • 每次员工离职时,自动触发令牌清单扫描。
  • 每次安全警报(如已泄漏凭证检测)后,立即全量扫描。

持续治理:防止令牌堆积的4条策略

  1. 生命周期强制策略
    所有新创建的令牌必须在API中设置expires_at(如GitHub Enterprise支持),脚本拒绝接受无过期时间的令牌。

  2. 分层扫描触发器

    • 自动扫描:CI/CD流程中集成actionlint,当代码仓库出现tokenpassword等关键字时立即标记。
    • 定时扫描:使用cron的weekly-cleanup任务运行上述Python脚本。
  3. 黑名单+白名单
    在脚本配置文件中定义EXEMPTED_TOKENS(如用于CI的令牌),确保审计跳过已知有效凭证。

    EXEMPTED_TOKENS = ["token-id-ci-system", "token-id-monitoring-agent"]
  4. 失败安全(Fail Safe)
    脚本应输出JSON格式的审计日志到S3或日志管理服务,一旦发现异常(如单次扫描发现超过20%令牌未使用),自动触发Slack/钉钉通知。


自动化清理不是一个一次性的“扫除”动作,而是嵌入到组织安全策略中的持续合规循环,从上述脚本出发,你可以逐步扩展至多云环境(AWS/Azure/GCP)、CI/CD工具链,甚至Kubernetes的Secrets过期管理,安全始于对每一行“凭据代码”的问责。

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