19.4.9 任务编排的审计与可追溯性

本节聚焦任务编排的审计与可追溯性,目标是在自动化执行中实现“可查、可证、可回放”。审计范围覆盖编排设计、审批流转、执行过程、变更结果与回滚记录,并确保跨系统链路可关联。核心审计对象包括:作业模板版本、参数输入与来源、触发方式、执行人/系统身份、目标资源清单、执行步骤时间线、输出日志与证据、异常与重试策略、审批链路与时间戳。

文章图片

审计数据模型需要统一字段并贯穿平台。示例以 MySQL 作为审计库,支持任务与节点级别追踪,配合证据链与哈希校验提升不可篡改性。

-- /opt/ops/schema/audit.sql
CREATE DATABASE IF NOT EXISTS ops_audit DEFAULT CHARSET utf8mb4;
USE ops_audit;

CREATE TABLE task_instance (
  task_id        VARCHAR(64) PRIMARY KEY,
  flow_version   VARCHAR(32) NOT NULL,
  trace_id       VARCHAR(64) NOT NULL,
  trigger_type   ENUM('manual','schedule','event') NOT NULL,
  operator       VARCHAR(64) NOT NULL,
  approve_chain  JSON,
  start_time     DATETIME,
  end_time       DATETIME,
  result         ENUM('success','failed','partial') NOT NULL,
  output_digest  CHAR(64) NOT NULL,
  evidence_url   VARCHAR(255)
);

CREATE TABLE task_node (
  node_id        VARCHAR(64) PRIMARY KEY,
  task_id        VARCHAR(64) NOT NULL,
  step_name      VARCHAR(128) NOT NULL,
  target         VARCHAR(128) NOT NULL,
  command_sha    CHAR(64) NOT NULL,
  exit_code      INT NOT NULL,
  stdout_digest  CHAR(64),
  stderr_digest  CHAR(64),
  start_time     DATETIME,
  end_time       DATETIME,
  retry_count    INT DEFAULT 0,
  FOREIGN KEY (task_id) REFERENCES task_instance(task_id)
);

CREATE TABLE audit_chain (
  seq_id         BIGINT AUTO_INCREMENT PRIMARY KEY,
  task_id        VARCHAR(64) NOT NULL,
  payload_json   JSON NOT NULL,
  prev_hash      CHAR(64) NOT NULL,
  curr_hash      CHAR(64) NOT NULL,
  created_at     DATETIME NOT NULL
);

示例:任务执行时写入审计链,生成全局 trace_id,并对每条记录进行 hash 链接,保证可回放与完整性校验。

# /opt/ops/bin/audit_append.sh
#!/usr/bin/env bash
set -euo pipefail

TASK_ID="task-20240101-0001"
TRACE_ID="$(uuidgen | tr -d '-')"
PAYLOAD='{"step":"deploy_nginx","target":"10.0.1.12","operator":"svc_ops","result":"success"}'

# 读取上一条 hash
PREV_HASH=$(mysql -N -s -e "SELECT curr_hash FROM ops_audit.audit_chain ORDER BY seq_id DESC LIMIT 1;" | awk '{print $1}')
PREV_HASH=${PREV_HASH:-"0"}

# 计算当前 hash(payload+prev_hash)
CURR_HASH=$(printf "%s%s" "$PAYLOAD" "$PREV_HASH" | sha256sum | awk '{print $1}')

# 写入审计链
mysql -e "INSERT INTO ops_audit.audit_chain(task_id,payload_json,prev_hash,curr_hash,created_at)
VALUES('$TASK_ID','$PAYLOAD','$PREV_HASH','$CURR_HASH',NOW());"

echo "trace_id=$TRACE_ID curr_hash=$CURR_HASH"

预期效果:执行脚本后,audit_chain 表新增一条记录,prev_hash 指向上一条记录的 curr_hash

# 执行示例
bash /opt/ops/bin/audit_append.sh
# 输出示例:
# trace_id=3c8f... curr_hash=8fd2...

安装与采集建议:在执行节点启用系统审计(auditd)捕获关键二进制与配置变更,配合 rsyslog 输出到审计库或对象存储。

# 安装 auditd
sudo yum -y install audit || sudo apt-get -y install auditd
sudo systemctl enable --now auditd

# 定义审计规则:监控编排执行器与关键配置
cat <<'EOF' | sudo tee /etc/audit/rules.d/ops.rules
-w /opt/ops/runner -p x -k ops_exec
-w /etc/nginx/nginx.conf -p wa -k ops_conf
EOF

# 重新加载规则
sudo augenrules --load

# 查询审计事件
sudo ausearch -k ops_exec -ts today

命令解释:
- -w 监控路径;-p x/wa 表示执行/写入与属性变更;
- -k 关键字标签,便于检索;
- ausearch 可按关键字与时间窗口查询审计记录。

回放示例:根据任务 ID 查询节点执行明细,配合对象存储证据恢复过程。

-- 查询任务实例与节点时间线
SELECT t.task_id, t.trace_id, t.operator, n.step_name, n.target, n.exit_code, n.start_time, n.end_time
FROM ops_audit.task_instance t
JOIN ops_audit.task_node n ON t.task_id = n.task_id
WHERE t.task_id = 'task-20240101-0001'
ORDER BY n.start_time ASC;

排错要点:
1. 无审计日志:检查 auditd 服务状态与规则加载(systemctl status auditdaugenrules --check)。
2. 时间线错乱:统一 NTP 时间基准(timedatectl),避免跨系统时间漂移。
3. hash 校验失败:确认写入顺序、是否有并发插入导致链断裂;必要时按 seq_id 回放核对。
4. 追踪链断裂:确保 trace_id 在编排引擎、执行器与审计采集器之间透传。

练习:
1. 基于示例表结构,增加 approval 表记录审批意见与时间戳,并写一条审批记录。
2. 编写脚本为每次执行生成 trace_id,并在日志中输出并入库。
3. 设计一个“高危操作”规则:当命令包含 rm -rf 时,要求双人审批并记录审批链。