自动化脚本如何清理未使用客户端ID

wen 实用脚本 26

本文目录导读:

自动化脚本如何清理未使用客户端ID

  1. 方案一:基于数据库的客户端ID清理(通用SQL + Shell脚本)
  2. 方案二:基于日志分析(ELK/Grafana + Python)
  3. 方案三:Kubernetes环境清理过期的ServiceAccount/Token
  4. 安全与最佳实践

针对“自动化脚本清理未使用客户端ID”的需求,需要明确“客户端ID”的上下文(如OAuth2客户端、数据库中的设备Token、容器中的Pod、或API密钥等),以下是通用的清理思路及脚本模板,适用于Web服务、OAuth2、物联网设备等场景。

核心清理逻辑

  1. 定义“未使用”:基于上次活跃时间(Last Active)、无API调用天数、或未关联有效用户。
  2. 查询候选ID:从系统日志、数据库或认证服务中提取。
  3. 执行清理:软删除(标记失效)或硬删除(移除记录)。
  4. 备份与验证:清理前导出列表,清理后检查服务健康。

基于数据库的客户端ID清理(通用SQL + Shell脚本)

场景:客户端ID存储在关系型数据库中(如MySQL/PostgreSQL),且有last_used_atstatus字段。

识别90天未使用的客户端

-- 假设表名为 'oauth_clients'
SELECT client_id, client_name, last_used_at
FROM oauth_clients
WHERE last_used_at < NOW() - INTERVAL 90 DAY
   OR last_used_at IS NULL;  -- 从未使用过

自动化清理脚本(Bash)

#!/bin/bash
# clean_unused_clients.sh
DB_HOST="localhost"
DB_USER="admin"
DB_PASS="securepass"
DB_NAME="auth_db"
DRY_RUN=${1:-false}  # 默认非干运行:传入"true"则只打印不删除
# 备份旧ID
BACKUP_FILE="/tmp/cleaned_client_ids_$(date +%Y%m%d_%H%M%S).csv"
echo "Backing up clients to $BACKUP_FILE"
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e \
"SELECT client_id, client_secret, created_at, last_used_at INTO OUTFILE '$BACKUP_FILE'
 FIELDS TERMINATED BY ',' ENCLOSED BY '\"'
 FROM oauth_clients 
 WHERE last_used_at < NOW() - INTERVAL 90 DAY" 2>/dev/null
if [ "$DRY_RUN" = true ]; then
    echo "[DRY-RUN] Would delete the following clients:"
    mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e \
    "SELECT client_id, last_used_at FROM oauth_clients WHERE last_used_at < NOW() - INTERVAL 90 DAY"
else
    # 执行软删除(建议先软删除,保留恢复可能)
    mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e \
    "UPDATE oauth_clients SET status='disabled', disabled_at=NOW() 
     WHERE last_used_at < NOW() - INTERVAL 90 DAY AND status='active'"
    # 或者硬删除(谨慎使用)
    # mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e \
    # "DELETE FROM oauth_clients WHERE last_used_at < NOW() - INTERVAL 90 DAY"
    echo "[INFO] Cleanup completed. Disabled $(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -N -e \
    "SELECT COUNT(*) FROM oauth_clients WHERE status='disabled' AND disabled_at > NOW() - INTERVAL 1 MINUTE") clients."
fi

基于日志分析(ELK/Grafana + Python)

场景:客户端ID由微服务或API Gateway记录访问日志,无直接时间戳字段。

Python脚本:分析Nginx/AWS CloudWatch日志

#!/usr/bin/env python3
"""
clean_orphan_clients.py
从API访问日志中提取最近90天活跃的client_id,反向标记未出现的ID。
"""
import re
from datetime import datetime, timedelta
import redis
import requests
# 配置
LOG_FILE = '/var/log/nginx/api_access.log'  # 或从Kafka/CloudWatch读取
REDIS_CLIENTS_KEY = 'active_clients:recent_90d'
API_DELETE_URL = 'https://api.example.com/admin/clients/{client_id}/disable'
# 1. 解析日志,收集活跃ID
active_ids = set()
with open(LOG_FILE, 'r') as f:
    for line in f:
        # 假设日志格式: [timestamp] client_id=xxx ... 
        match = re.search(r'client_id=([a-zA-Z0-9_-]+)', line)
        if match:
            active_ids.add(match.group(1))
# 2. 查询数据库/Redis中所有ID,找出差集
all_ids = redis_client.smembers('all_client_ids')  # 假设预存在Redis
unused_ids = [cid for cid in all_ids if cid not in active_ids]
# 3. 执行清理
for client_id in unused_ids:
    print(f"Disabling client_id: {client_id}")
    resp = requests.post(API_DELETE_URL.format(client_id=client_id), 
                        headers={'Authorization': 'Bearer admin-token'})
    if resp.status_code != 200:
        print(f"Failed to disable {client_id}")

Kubernetes环境清理过期的ServiceAccount/Token

场景:Kubernetes集群中存在大量未使用的ServiceAccount或绑定的Secret。

Bash脚本:清理有Tombstone的过期Token

#!/bin/bash
# clean_unused_sa_tokens.sh
K8S_NAMESPACE="default"
DAYS_OLD=90
# 获取所有ServiceAccount(排除系统组件)
echo "Listing ServiceAccounts older than $DAYS_OLD days..."
kubectl get sa --all-namespaces -o json | jq -r \
  '.items[] | select(.metadata.creationTimestamp < (now - 86400*'$DAYS_OLD' | strftime("%Y-%m-%dT%H:%M:%SZ"))) 
   | "\(.metadata.namespace) \(.metadata.name)"' | while read ns sa; do
  # 检查该SA是否被Pod引用
  POD_COUNT=$(kubectl get pods -n $ns -o json | jq -r \
    "[.items[] | select(.spec.serviceAccountName==\"$sa\")] | length")
  if [ "$POD_COUNT" -eq 0 ]; then
    echo "Deleting unused SA: $ns/$sa"
    # kubectl delete sa -n $ns $sa  # 如需删除取消注释
  fi
done

安全与最佳实践

  1. 永远使用干运行模式:在脚本中添加 --dry-run 参数,第一次执行仅打印受影响ID。
  2. 软删除优先:将状态设为 disabled,保留7-30天观察期,确认无影响后硬删除。
  3. 速率限制:清理操作可能会触发告警或性能问题,建议批量处理(每次100条)。
  4. 通知与审计:清理前发送邮件/RocketChat通知,清理后记录日志到ELK。

示例:企业级清理脚本结构

# clean_clients_pipeline.yml
stages:
  - name: audit
    action: select_unused_ids  # 查询并生成CSV
  - name: validate
    action: check_impact         # 检查这些ID是否关联生产流量
  - name: disable                # 软禁用
    action: update_status
    params:
     new_status: "pending_delete"
  - name: final_delete           # 30天后硬删除
    action: delete_records
    schedule: "0 0 1 * *"      # 每月1号执行

根据你的具体技术栈:

  • 若用Keycloak/Auth0:调用管理API批量删除(如 GET /clients?lastUsedBefore=...)。
  • 若用JWT:只需撤销JWT的签发权限,无需物理删除客户端ID。
  • 若用IoT设备:检查设备心跳,连续30天无心跳直接删除注册信息。

你可以根据实际系统选择对应片段,或进一步提供细节(如数据库类型、日志格式),以便我给出更精确的代码。

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