pfrederiksen/cloudnecromancer

GitHub: pfrederiksen/cloudnecromancer

通过回放 CloudTrail 事件重建任意历史时间点的 AWS 基础设施状态快照,支持多格式导出和差异对比。

Stars: 0 | Forks: 0

# CloudNecromancer 通过回放 CloudTrail 事件来重建时间点 AWS 基础设施快照。 给定任意历史时间戳,CloudNecromancer 可以复活那一刻存在的所有资源 —— EC2 实例、IAM 角色、S3 存储桶、Lambda 函数、安全组、VPC、RDS 数据库等 —— 这些均基于存储在 CloudTrail 中的创建/修改/删除事件链。 ``` ░░░░░░░░░░░░░░░░░░░░░░░░░░ ░ ☠ CloudNecromancer ☠ ░ ░░░░░░░░░░░░░░░░░░░░░░░░░░ Raising the dead since 2026 ``` ## 使用场景 - **事件响应** — “违规事件发生前凌晨 3 点正在运行的是什么?” - **合规审计** — 任意过去日期的时间点清单 - **事后时间线** — 完整的基础设施状态重建 - **偏差分析** — 比较两个时间戳以查看变化 ## 安装 ### Homebrew (macOS / Linux) ``` brew tap pfrederiksen/tap brew install cloudnecromancer ``` ### 从发布二进制文件 从 [Releases](https://github.com/pfrederiksen/cloudnecromancer/releases) 下载适用于您平台的最新版本。 | 平台 | 架构 | |----------|-------------| | macOS | Intel (amd64), Apple Silicon (arm64) | | Linux | amd64 | ### 从源码 ``` go install github.com/pfrederiksen/cloudnecromancer@latest ``` ### 本地构建 ``` git clone https://github.com/pfrederiksen/cloudnecromancer.git cd cloudnecromancer make build # 位于 ./bin/cloudnecromancer 的 Binary ``` ## 快速开始 ``` # 1. 获取 CloudTrail 事件到本地数据库 cloudnecromancer fetch \ --account-id 123456789012 \ --regions us-east-1,us-west-2 \ --start 2026-01-01T00:00:00Z \ --end 2026-03-01T00:00:00Z # 2. 在特定时间点复活基础设施 cloudnecromancer resurrect --at 2026-02-15T03:00:00Z # 3. 比较两个时间点 cloudnecromancer diff \ --from 2026-01-01T00:00:00Z \ --to 2026-02-15T03:00:00Z ``` ## 命令 ### `fetch` — 将 CloudTrail 事件拉取到本地 DB ``` cloudnecromancer fetch \ --account-id 123456789012 \ --region us-east-1 \ --start 2026-01-01T00:00:00Z \ --end 2026-03-01T00:00:00Z \ [--regions us-east-1,us-west-2,eu-west-1] \ [--profile my-aws-profile] \ [--db ./necromancer.db] ``` 跨一个或多个区域并发获取 CloudTrail 管理事件,并将其存储在本地 DuckDB 数据库中。事件通过事件 ID 进行去重,因此重新运行获取重叠时间范围的数据是安全的。 **示例输出:** ``` ░░░░░░░░░░░░░░░░░░░░░░░░░░ ░ ☠ CloudNecromancer ☠ ░ ░░░░░░░░░░░░░░░░░░░░░░░░░░ Raising the dead since 2026 Fetching CloudTrail events... us-east-1 ████████████████████████████████ 100% | 12,847 events us-west-2 ████████████████████████████████ 100% | 3,291 events Summary: Events fetched: 16,138 Services: ec2, iam, s3, lambda, rds Date range: 2026-01-01 to 2026-03-01 Database: ./necromancer.db (24 MB) ``` ### `resurrect` — 重建某个时间点的基础设施 ``` cloudnecromancer resurrect \ --at 2026-02-15T03:00:00Z \ [--services ec2,iam,s3] \ [--region us-east-1] \ [--format json|terraform|cloudformation|cdk|pulumi|ocsf|csv] \ [--output ./snapshot.json] \ [--include-dead] \ [--ritual] \ [--db ./necromancer.db] ``` 回放给定时间戳之前的所有事件并重建每个资源的状态。`--ritual` 标志会添加一个带有“RAISING THE DEAD...”打字机效果的动画 ASCII 骷髅。 **示例 JSON 输出** (`--format json`): ``` { "timestamp": "2026-02-15T03:00:00Z", "account_id": "123456789012", "regions": ["us-east-1", "us-west-2"], "resources": { "ec2:instance": [ { "resource_id": "i-0abc123def456789", "state": "running", "attributes": { "instance_type": "t3.medium", "image_id": "ami-0abcdef1234567890", "vpc_id": "vpc-0123456789abcdef0", "subnet_id": "subnet-0123456789abcdef0" }, "created_at": "2026-01-10T14:22:00Z", "last_modified": "2026-02-01T09:15:00Z" } ], "iam:role": [ { "resource_id": "WebAppRole", "state": "active", "attributes": { "attached_policies": [ "arn:aws:iam::123456789012:policy/S3ReadOnly", "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess" ] }, "created_at": "2026-01-05T10:00:00Z", "last_modified": "2026-01-20T16:30:00Z" } ], "s3:bucket": [ { "resource_id": "prod-data-lake-2026", "state": "active", "attributes": { "versioning": "Enabled", "public_access_block": true }, "created_at": "2026-01-02T08:00:00Z", "last_modified": "2026-01-15T12:00:00Z" } ] }, "summary": { "total_resources": 47, "by_service": { "ec2": 23, "iam": 12, "s3": 5, "lambda": 4, "rds": 3 }, "by_state": { "active": 42, "running": 5 } } } ``` **示例 HCL 输出** (`--format hcl`): ``` # 已重建 — 应用前请验证 # 由 CloudNecromancer 于 2026-02-15T03:00:00Z 生成 import { to = aws_instance.i_0abc123def456789 id = "i-0abc123def456789" } resource "aws_instance" "i_0abc123def456789" { instance_type = "t3.medium" ami = "ami-0abcdef1234567890" subnet_id = "subnet-0123456789abcdef0" } import { to = aws_iam_role.WebAppRole id = "WebAppRole" } resource "aws_iam_role" "WebAppRole" { } import { to = aws_s3_bucket.prod_data_lake_2026 id = "prod-data-lake-2026" } resource "aws_s3_bucket" "prod_data_lake_2026" { } ``` **示例 CloudFormation 输出** (`--format cloudformation`): ``` { "AWSTemplateFormatVersion": "2010-09-09", "Description": "Reconstructed by CloudNecromancer at 2026-02-15T03:00:00Z -- verify before deploying", "Resources": { "Ec2Instancei0abc123def456789": { "Type": "AWS::EC2::Instance", "Properties": { "InstanceType": "t3.medium", "ImageId": "ami-0abcdef1234567890", "SubnetId": "subnet-0123456789abcdef0" } }, "S3Bucketproddatalake2026": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": "prod-data-lake-2026" } } } } ``` **示例 CDK 输出** (`--format cdk`): ``` // RECONSTRUCTED -- verify before deploying // Generated by CloudNecromancer at 2026-02-15T03:00:00Z import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as s3 from 'aws-cdk-lib/aws-s3'; import { Construct } from 'constructs'; export class CloudNecromancerStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new ec2.CfnInstance(this, "i-0abc123def456789", { instanceType: "t3.medium", imageId: "ami-0abcdef1234567890", subnetId: "subnet-0123456789abcdef0", }); new s3.CfnBucket(this, "prod-data-lake-2026", { bucketName: "prod-data-lake-2026", }); } } ``` **示例 Pulumi 输出** (`--format pulumi`): ``` // RECONSTRUCTED -- verify before deploying // Generated by CloudNecromancer at 2026-02-15T03:00:00Z import * as aws from "@pulumi/aws"; const i_0abc123def456789 = new aws.ec2.Instance("i-0abc123def456789", { instanceType: "t3.medium", ami: "ami-0abcdef1234567890", subnetId: "subnet-0123456789abcdef0", }); const prod_data_lake_2026 = new aws.s3.Bucket("prod-data-lake-2026", { bucket: "prod-data-lake-2026", }); ``` **示例 CSV 输出** (`--format csv`): ``` resource_id,resource_type,service,state,region,account_id,created_at,last_modified,snapshot_timestamp,attributes_json i-0abc123def456789,instance,ec2,running,us-east-1,123456789012,2026-01-10T14:22:00Z,2026-02-01T09:15:00Z,2026-02-15T03:00:00Z,"{""instance_type"":""t3.medium""}" WebAppRole,role,iam,active,us-east-1,123456789012,2026-01-05T10:00:00Z,2026-01-20T16:30:00Z,2026-02-15T03:00:00Z,"{""attached_policies"":[""arn:aws:iam::123456789012:policy/S3ReadOnly""]}" ``` ### `diff` — 比较两个时间戳之间的基础设施 ``` cloudnecromancer diff \ --from 2026-01-01T00:00:00Z \ --to 2026-02-15T03:00:00Z \ [--format table|json] \ [--db ./necromancer.db] ``` 生成两个时间戳的快照并报告变化。 **示例输出**(默认表格格式): ``` ░░░░░░░░░░░░░░░░░░░░░░░░░░ ░ ☠ CloudNecromancer ☠ ░ ░░░░░░░░░░░░░░░░░░░░░░░░░░ Raising the dead since 2026 Diff: 2026-01-01T00:00:00Z → 2026-02-15T03:00:00Z + ADDED (12 resources) + ec2:instance i-0abc123def456789 t3.medium us-east-1 + ec2:instance i-0def456789abc123 t3.large us-west-2 + s3:bucket prod-data-lake-2026 us-east-1 + lambda:function process-orders python3.12 us-east-1 ... - REMOVED (3 resources) - ec2:instance i-0old999888777666 t2.micro us-east-1 - iam:role LegacyAdminRole us-east-1 - s3:bucket temp-migration-2025 us-east-1 ~ MODIFIED (8 resources) ~ iam:role WebAppRole us-east-1 attached_policies: +arn:aws:iam::123456789012:policy/S3ReadOnly ~ ec2:security_group sg-0123456789abcdef0 us-east-1 ingress: +0.0.0.0/0:443 ``` ### `export` — 重新导出现有快照 ``` cloudnecromancer export \ --input ./snapshot.json \ --format hcl \ --output ./snapshot.tf ``` ### `info` — 显示数据库统计信息 ``` cloudnecromancer info [--db ./necromancer.db] ``` **示例输出:** ``` Database: ./necromancer.db Events: 16,138 Date range: 2026-01-01T00:00:00Z to 2026-03-01T00:00:00Z Services: ec2, iam, s3, lambda, rds Regions: us-east-1, us-west-2 Size: 24 MB ``` ## 全局标志 | 标志 | 默认值 | 描述 | |------|---------|-------------| | `--db` | `./necromancer.db` | DuckDB 数据库文件路径 | | `--profile` | *(默认链)* | 要使用的 AWS profile | | `--quiet` | `false` | 抑制横幅和非必要输出 | | `--verbose` | `false` | 启用详细日志记录 | ## AWS 权限 CloudNecromancer 需要对 CloudTrail 的只读访问权限。有关最小 IAM 策略,请参阅 [AWS_PERMISSIONS.md](AWS_PERMISSIONS.md)。 简要版本: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudtrail:LookupEvents", "cloudtrail:GetTrailStatus", "cloudtrail:DescribeTrails" ], "Resource": "*" } ] } ``` 凭证通过标准 AWS SDK 凭证链解析:环境变量、`~/.aws/credentials`、IAM 实例角色等。 ## 输出格式 | 格式 | 标志 | 描述 | |--------|------|-------------| | JSON | `--format json` | 包含嵌套资源属性的完整快照 | | Terraform | `--format terraform` | 可导入 Terraform 的 HCL,包含 `import` + `resource` 块(别名:`hcl`,`tf`) | | CloudFormation | `--format cloudformation` | AWS CloudFormation JSON 模板(别名:`cfn`) | | CDK | `--format cdk` | 使用 L1 constructs 的 AWS CDK TypeScript stack | | Pulumi | `--format pulumi` | 使用 `@pulumi/aws` 的 Pulumi TypeScript 程序 | | OCSF | `--format ocsf` | OCSF Inventory Info 事件 (class_uid 5001),换行符分隔的 JSON | | CSV | `--format csv` | Splunk lookup table 格式 | ### 在 Splunk 中使用 CSV 将 CSV 输出作为 Splunk lookup table 上传,然后与 CloudTrail 日志关联: ``` | inputlookup cloudnecromancer_lookup.csv | join resource_id [search index=cloudtrail earliest=-30d] ``` ## 支持的服务 (23) | 服务 | 资源 | 创建 | 更新 | 删除 | |---------|-----------|--------|--------|--------| | EC2 | instances, VPCs, subnets, security groups, IGWs | Yes | Yes | Yes | | IAM | roles, users, policies | Yes | Yes | Yes | | S3 | buckets, policies, versioning, public access | Yes | Yes | Yes | | Lambda | functions | Yes | Yes | Yes | | RDS | instances, clusters | Yes | Yes | Yes | | ELB | load balancers, target groups, listeners | Yes | Yes | Yes | | ECS | clusters, services, task definitions | Yes | Yes | Yes | | EKS | clusters, nodegroups | Yes | Yes | Yes | | KMS | keys, aliases, rotation | Yes | Yes | Yes | | Secrets Manager | secrets, rotation, restore | Yes | Yes | Yes | | CloudWatch Logs | log groups, log streams, retention | Yes | Yes | Yes | | DynamoDB | tables, global tables | Yes | Yes | Yes | | SNS | topics, subscriptions | Yes | Yes | Yes | | SQS | queues, queue attributes | Yes | Yes | Yes | | API Gateway | REST APIs, HTTP APIs, stages | Yes | Yes | Yes | | Route 53 | hosted zones, record sets | Yes | Yes | Yes | | ECR | repositories, lifecycle policies, scanning | Yes | Yes | Yes | | ElastiCache | clusters, replication groups | Yes | Yes | Yes | | WAF v2 | web ACLs, rule groups, IP sets | Yes | Yes | Yes | | GuardDuty | detectors, filters | Yes | Yes | Yes | | CloudFront | distributions, origin access controls | Yes | Yes | Yes | | EBS | volumes, snapshots | Yes | Yes | Yes | | SSM | documents, parameters, maintenance windows | Yes | Yes | Yes | ## 工作原理 1. **Fetch (获取)** — CloudNecromancer 通过 `LookupEvents` 拉取 CloudTrail 管理事件,并将其存储在嵌入式 DuckDB 数据库中。多区域获取并发运行。 2. **Parse (解析)** — 每个 CloudTrail 事件通过服务特定的解析器(在启动时注册)进行路由,该解析器提取 `ResourceDelta`:操作(创建/更新/删除)、资源 ID 和相关属性。 3. **Replay (回放)** — 为了重建时间 T 的状态,引擎查询 T 之前的所有事件(按时间顺序排列)并将每个增量应用到内存中的资源映射。创建即插入,更新即合并属性,删除即将资源标记为已终止。 4. **Export (导出)** — 最终快照以请求的格式序列化。 ## 开发 ``` make build # Build binary to ./bin/cloudnecromancer make test # Run all tests make lint # Run golangci-lint make snapshot # Build cross-platform binaries (GoReleaser) ``` ### 添加新的服务解析器 1. 创建 `internal/parser/services/myservice.go` 2. 实现 `Parser` 接口 3. 在 `init()` 中使用 `parser.Register(&MyServiceParser{})` 注册 4. 将测试 fixtures 添加到 `testdata/` 5. 在 `internal/parser/services/myservice_test.go` 中添加表驱动测试 ### 添加新的导出器 1. 创建 `internal/export/myformat.go` 2. 实现 `Exporter` 接口 (`Export(snapshot, writer) error`) 3. 在 `internal/export/exporter.go` 的 `GetExporter()` 中注册 4. 在 `internal/export/export_test.go` 中添加测试 5. 更新 `cmd/resurrect.go` 和 `cmd/export.go` 中的 `--format` 标志描述 ## 许可证 MIT
标签:AWS, CloudTrail, DPI, EC2, EVTX分析, Go, HTTP/HTTPS抓包, IaC, IAM, Lambda, RDS, Ruby工具, S3, VPC, Web报告查看器, 事件回放, 云资源管理, 偏差分析, 历史记录, 基础设施重建, 态势感知, 数字取证, 文档结构分析, 日志审计, 时间点快照, 网络安全审计, 自动化脚本, 足迹分析