blackwell-systems/gcp-iam-emulator
GitHub: blackwell-systems/gcp-iam-emulator
本地GCP IAM策略引擎,用于在无需云凭证的情况下进行确定性授权测试和CI/CD集成。
Stars: 1 | Forks: 0
# GCP IAM 模拟器
[](https://github.com/blackwell-systems)
[](https://pkg.go.dev/github.com/blackwell-systems/gcp-iam-emulator)
[](https://go.dev/)
[](LICENSE)
这是 **Blackwell 本地 IAM 控制平面**的核心组件。它负责评估 IAM 策略,并向服务模拟器(Secret Manager、KMS)指示是允许还是拒绝请求。
与模拟器(允许一切)或观察器(事后记录)不同,它会在请求到达数据平面之前**主动执行**策略。
## 快速示例
```
# policy.yaml - 正确定义测试所需内容
roles:
roles/custom.ciRunner:
permissions:
- secretmanager.secrets.get
- secretmanager.versions.access
- cloudkms.cryptoKeys.encrypt
groups:
developers:
members:
- user:alice@example.com
- user:bob@example.com
projects:
test-project:
bindings:
- role: roles/viewer
members:
- group:developers
- role: roles/custom.ciRunner
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
condition:
expression: 'resource.name.startsWith("projects/test-project/secrets/prod-")'
title: "CI limited to production secrets"
```
```
# 从严格模式开始(默认 - 捕获配置错误)
server --config policy.yaml --trace
# HTTP REST API
server --config policy.yaml --http-port 8081
# 配置更改时热重载
server --config policy.yaml --watch
```
**结果:** 与您的策略匹配的本地 IAM 决策、授权逻辑的离线测试、无需 GCP 凭证的 CI 就绪。
## 使用模式
**独立运行** - 作为策略引擎独立运行:
```
server --config policy.yaml
# 单个 IAM 服务器,用于自定义模拟器
```
**统一生态系统** - 与 [gcp-emulator](https://github.com/blackwell-systems/gcp-emulator) 一起使用,在单个进程中进行统一的多服务测试:
```
go install github.com/blackwell-systems/gcp-emulator/cmd/gcp-emulator@latest
gcp-emulator --policy policy.yaml --iam-mode strict
# IAM + Secret Manager + KMS + Eventarc
# 单个进程,单个端口,单个策略文件
```
**选择独立模式进行自定义集成,选择 gcp-emulator 获取完整的 GCP 模拟器栈。**
## 如何提供主体
模拟器需要知道**谁**在发出每个请求。通过元数据/标头提供身份:
### gRPC 元数据(Go SDK 示例)
```
import "google.golang.org/grpc/metadata"
// Inject principal identity
md := metadata.Pairs("x-emulator-principal", "serviceAccount:ci@project.iam.gserviceaccount.com")
ctx = metadata.NewOutgoingContext(context.Background(), md)
// Now use ctx for API calls - emulator sees the principal
client.GetSecretVersion(ctx, &secretmanagerpb.GetSecretVersionRequest{...})
```
### HTTP 标头(REST API / curl)
```
curl -X POST http://localhost:8081/v1/projects/test/secrets/api-key:testIamPermissions \
-H "X-Emulator-Principal: serviceAccount:ci@project.iam.gserviceaccount.com" \
-H "Content-Type: application/json" \
-d '{"permissions": ["secretmanager.secrets.get"]}'
```
### 支持的主体格式
- **服务账号:** `serviceAccount:name@project.iam.gserviceaccount.com`
- **用户:** `user:alice@example.com`
- **群组:** `group:eng-team@example.com`(在 policy.yaml 中定义群组)
- **所有已认证用户:** `allAuthenticatedUsers`
- **公开:** `allUsers`
### 与模拟器集成
与 Secret Manager / KMS 模拟器一起使用时,数据平面模拟器会自动将主体转发到 IAM 控制平面:
```
// Your test code sets principal once
ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs(
"x-emulator-principal", "serviceAccount:ci@test.iam.gserviceaccount.com",
))
// Secret Manager emulator forwards principal to IAM emulator automatically
client.AccessSecretVersion(ctx, &secretmanagerpb.AccessSecretVersionRequest{...})
// ↓ Internally: IAM checks if ci@test.iam can secretmanager.versions.access
```
**无需额外配置** - 模拟器生态系统会自动处理主体传播.
## 架构 — 控制平面位置
```
┌─────────────────────────────────────────┐
│ Your Application Code │
│ (GCP client libraries) │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ DATA PLANES │
│ • Secret Manager Emulator │
│ • KMS Emulator │
│ • (Future: Tasks, Pub/Sub, Storage) │
│ │
│ Each checks IAM before data access │
└────────────────┬────────────────────────┘
│
│ CheckPermission(principal, resource, permission)
▼
┌─────────────────────────────────────────┐
│ CONTROL PLANE (THIS REPO) │◄── You are here
│ IAM Emulator — Policy Engine │
│ │
│ Evaluates: │
│ • Role bindings │
│ • Group memberships │
│ • Conditional policies (CEL) │
│ • Resource-level policy evaluation │
│ │
│ Returns: Allow / Deny │
└─────────────────────────────────────────┘
```
**这是执行边界。** 请求在数据访问之前在此处进行授权。
| 方法 | 示例 | 时机 | 行为 |
|----------|---------|------|----------|
| 模拟器 | 标准模拟器 | 从不 | 始终允许 |
| 观察器 | 执行后分析 | 之后 | 记录您使用的 |
| **控制平面** | **Blackwell IAM** | **之前** | **拒绝未授权** |
## 确定性一致性(CI/CD 杀手级功能)
**真实 GCP IAM 的问题:**
GCP IAM 是**最终一致**的。当您创建或更新策略绑定时:
- 更改可能需要 **1-60 秒** 才能在全球传播
- 您的测试变得**不稳定**(有时通过,有时失败)
- CI/CD 管道出现**随机失败**,无法复现
**Blackwell 的优势:**
此模拟器是**强一致**的。策略更改:
- **即时**(0ms 传播延迟)
- **确定性**(相同输入 = 相同输出,每次都是)
- **可重复**(运行测试 1000 次,获得相同结果)
| 维度 | 真实 GCP IAM | Blackwell IAM 模拟器 |
|-----------|--------------|------------------------|
| **一致性模型** | 最终一致 | 强一致 |
| **传播延迟** | 1-60 秒 | 0ms(即时) |
| **测试不稳定性** | 高(依赖时序) | 零(确定性) |
| **CI/CD 可靠性** | 不可预测 | 完全可重复 |
| **网络依赖** | 需要 | 无 |
| **每次测试运行成本** | API 费用 | 免费(本地) |
## 这是什么(不是什么)
**GCP IAM 模拟器是一个用于测试云授权逻辑的确定性本地策略引擎。**
**范围说明:** 此模拟器是用于 CI 测试的确定性 IAMPolicy 引擎。它不尝试实现完整的 Google Cloud IAM 对等(组织/文件夹层级、拒绝策略、完整 CEL)。
它不是 Google Cloud IAM 的完整重新实现,也不尝试完美保真。
相反,它提供:
- **确定性权限评估** - 在本地测试"谁可以访问什么"(在您 policy.yaml 定义的权限范围内)
- **严格的离线策略建模** - 无需 GCP 凭证或网络
- **可组合的认证层** - 本地 GCP 模拟器生态系统的基础
**用户定义自己的权限范围。模拟器执行它。**
**目标:** 在 CI 中捕获授权错误(缺失权限、错误角色、配置错误的主体)。
**非目标:** 镜像 Google IAM 的每个边缘情况。如果您的测试在本地通过但在真实 GCP 中失败,请优化您的自定义角色定义。
**内置角色是有意精简的。模拟器通过自定义角色可以实现无限可能。**
## 为什么此 IAM 模拟器使用精选权限(有意为之)
此 IAM 模拟器特意限定用于**授权测试**,而非全面的 IAM 复制。我们建模了一小部分内置角色(基元 + Secret Manager + KMS)加上无限的自定义角色定义,以捕获实际上会导致生产故障的错误:缺失权限、错误的角色分配和配置错误的主体。这种精选优先的方法捕获了 95% 的真实世界授权错误,同时保持 hermetic 执行(无需 GCP 凭证)、确定性行为(0ms 传播延迟 vs 真实 GCP 的 1-60s),以及零维护负担(无需跟踪 GCP 不断演变的角色目录)。如果您需要测试其他 GCP 服务或权限,请在 `policy.yaml` 中将它们显式定义为自定义角色 — 这种显式方法更简单、更可靠,并避免了全面 IAM 模拟中常见的目录陈旧问题。我们优化的是**重要的授权失败**,而非理论上的 IAM 完整性。
## 功能
- **完整的 IAMPolicy API 表面** - SetIamPolicy、GetIamPolicy、TestIamPermissions(gRPC + REST)
- **确定性权限评估** - 明确的角色→权限定义(内置引导角色 + YAML 定义的自定义角色)
- **条件绑定** - 支持 CEL 表达式的基于资源的访问控制
- **群组支持** - 定义可重用的群组和嵌套成员资格(1 级)
- **策略 Schema v3** - 完全支持 etag、version、auditConfigs、conditions
- **增强的跟踪模式** - JSON 输出、详细日志、持续时间指标
- **自定义角色** - 在 YAML 中定义任何 GCP 权限(可扩展,非硬编码)
- **精简的内置核心** - 基元角色 + Secret Manager + KMS(仅引导)
- **无需 GCP 凭证** - 完全离线工作,无需认证
- **快速且轻量** - 内存存储,毫秒级启动
- **线程安全** - 具有适当同步的并发访问
- **与模拟器集成** - 可与 gcp-secret-manager-emulator、gcp-kms-emulator 配合使用
## 支持的操作
### IAM 策略管理
- `SetIamPolicy` - 在任何资源上设置 IAM 策略
- `GetIamPolicy` - 检索资源的 IAM 策略
- `TestIamPermissions` - 检查授予了哪些权限
### 内置角色(引导集)
模拟器包含**一小部分**内置角色,可立即使用。对于生产测试,请在 YAML 中定义自定义角色。
**基元角色:**
- `roles/owner` - 完全访问所有资源
- `roles/editor` - 读写访问(无 IAM 管理,无删除)
- `roles/viewer` - 只读访问
**Secret Manager 角色:**
- `roles/secretmanager.admin` - 完整的密钥管理
- `roles/secretmanager.secretAccessor` - 仅读取密钥值
- `roles/secretmanager.secretVersionManager` - 管理版本
**KMS 角色:**
- `roles/cloudkms.admin` - 完整的 KMS 管理
- `roles/cloudkms.cryptoKeyEncrypterDecrypter` - 仅加解密
- `roles/cloudkms.viewer` - 只读 KMS 访问
**总计:** 10 个内置角色,26 个权限
**需要更多服务?** 在 YAML 中定义自定义角色 - 请参阅下面的[自定义角色](#custom-roles-v040)部分。
## 快速开始
### 安装
```
go install github.com/blackwell-systems/gcp-iam-emulator/cmd/server@latest
```
### 运行服务器
**基本:**
```
# 默认端口 8080 启动
server
# 自定义端口
server --port 9090
```
**带策略配置(推荐用于 CI):**
```
# 从 YAML 加载策略
server --config policy.yaml
# 启用跟踪模式进行调试
server --config policy.yaml --trace
# 启用 HTTP REST API
server --config policy.yaml --http-port 8081
# 启用详细跟踪并输出 JSON
server --config policy.yaml --explain --trace-output trace.json
# 文件更改时热重载策略
server --config policy.yaml --watch
```
**Docker:**
```
# 使用挂载配置运行
docker run -p 8080:8080 -v $(pwd)/policy.yaml:/policy.yaml \
ghcr.io/blackwell-systems/gcp-iam-emulator:latest --config /policy.yaml
# 使用跟踪模式运行
docker run -p 8080:8080 \
ghcr.io/blackwell-systems/gcp-iam-emulator:latest --trace
```
### 示例策略配置
创建 `policy.yaml`:
```
# 为测试环境定义自定义角色
roles:
roles/custom.dataReader:
permissions:
- bigquery.datasets.get
- bigquery.tables.list
projects:
test-project:
bindings:
- role: roles/owner
members:
- user:admin@example.com
- role: roles/custom.dataReader
members:
- user:analyst@example.com
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
resources:
secrets/db-password:
bindings:
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:app@test-project.iam.gserviceaccount.com
```
**注意:** 模拟器包含基元 + Secret Manager + KMS 的内置角色。对于其他 GCP 服务,请如上所示定义自定义角色。
### 与 GCP SDK 一起使用
**带主体注入的 Go 客户端:**
```
package main
import (
"context"
iampb "google.golang.org/genproto/googleapis/iam/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)
func main() {
ctx := context.Background()
conn, _ := grpc.NewClient(
"localhost:8080",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
defer conn.Close()
client := iampb.NewIAMPolicyClient(conn)
// Inject principal identity via metadata
md := metadata.Pairs("x-emulator-principal", "serviceAccount:ci@test-project.iam.gserviceaccount.com")
ctx = metadata.NewOutgoingContext(ctx, md)
// Test permissions (checks if this principal has access)
resp, _ := client.TestIamPermissions(ctx, &iampb.TestIamPermissionsRequest{
Resource: "projects/test-project/secrets/db-password",
Permissions: []string{
"secretmanager.versions.access",
"secretmanager.secrets.delete",
},
})
// resp.Permissions = ["secretmanager.versions.access"]
// (delete denied - secretAccessor role doesn't include it)
}
```
**动态设置策略(无配置文件):**
```
// Set policy via API
policy := &iampb.Policy{
Bindings: []*iampb.Binding{
{
Role: "roles/secretmanager.secretAccessor",
Members: []string{
"serviceAccount:ci@my-project.iam.gserviceaccount.com",
},
},
},
}
client.SetIamPolicy(ctx, &iampb.SetIamPolicyRequest{
Resource: "projects/my-project/secrets/my-secret",
Policy: policy,
})
```
## 用例
- **CI/CD 管道** - 用于 hermetic 测试的即插即用 IAM,无需 GCP 凭证
- **策略开发** - 通过即时反馈在本地迭代 IAM 策略
- **安全测试** - 在生产前验证"谁可以访问什么"
- **权限调试** - 跟踪模式解释为何允许/拒绝访问
- **集成测试** - 与 Secret Manager + KMS 模拟器的真实权限评估
- **降低成本** - 在开发期间避免 GCP API 费用
## CI/CD 集成
### GitHub Actions
```
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
iam-emulator:
image: ghcr.io/blackwell-systems/gcp-iam-emulator:latest
ports:
- 8080:8080
options: --mount type=bind,source=${{ github.workspace }}/policy.yaml,target=/policy.yaml
args: --config /policy.yaml --trace
steps:
- uses: actions/checkout@v4
- name: Run integration tests
env:
IAM_EMULATOR_HOST: localhost:8080
run: |
go test ./...
```
### Docker Compose
**完整的 GCP 模拟器栈:**
```
# docker-compose.yml
services:
iam:
image: ghcr.io/blackwell-systems/gcp-iam-emulator:latest
ports:
- "8080:8080"
volumes:
- ./policy.yaml:/policy.yaml
command: --config /policy.yaml --trace
secret-manager:
image: ghcr.io/blackwell-systems/gcp-secret-manager-emulator:latest
environment:
IAM_EMULATOR_HOST: iam:8080
ports:
- "9090:9090"
depends_on:
- iam
kms:
image: ghcr.io/blackwell-systems/gcp-kms-emulator:latest
environment:
IAM_EMULATOR_HOST: iam:8080
ports:
- "9091:9090"
depends_on:
- iam
```
**运行:**
```
docker-compose up
# 测试连接到 localhost:8080 (IAM)、localhost:9090 (Secret Manager)、localhost:9091 (KMS)
```
## 跟踪模式
启用跟踪模式以调试授权决策:
```
server --config policy.yaml --trace
```
**示例输出:**
```
2026/01/26 10:30:15 GCP IAM Emulator v0.2.0
2026/01/26 10:30:15 Loading policy config from policy.yaml
2026/01/26 10:30:15 Loaded 3 policies from config
2026/01/26 10:30:15 Trace mode: ENABLED (authz decisions will be logged)
2026/01/26 10:30:15 Server ready - listening on :8080
level=INFO msg="authz decision" decision=ALLOW principal=serviceAccount:ci@test.iam.gserviceaccount.com resource=projects/test/secrets/api-key permission=secretmanager.versions.access reason="matched binding: role=roles/secretmanager.secretAccessor member=serviceAccount:ci@test.iam.gserviceaccount.com"
level=INFO msg="authz decision" decision=DENY principal=user:dev@example.com resource=projects/test/secrets/db-password permission=secretmanager.secrets.delete reason="no matching binding found for principal"
```
**使用跟踪模式来:**
- 理解为何访问被拒绝
- 调试策略继承
- 验证主体匹配
- 在本地测试中审计授权决策
**增强的跟踪模式(v0.3.0+):**
```
# 使用 --explain 进行详细日志
server --config policy.yaml --explain
# JSON 输出到文件
server --config policy.yaml --trace-output trace.json
```
**JSON 跟踪格式:**
```
{
"time":"2026-01-26T10:30:15Z",
"level":"INFO",
"msg":"permission_check",
"resource":"projects/test/secrets/api-key",
"principal":"serviceAccount:ci@test.iam.gserviceaccount.com",
"allowed_permissions":["secretmanager.versions.access"],
"duration_ms":2,
"timestamp":"2026-01-26T10:30:15Z"
}
```
## 授权跟踪
结构化日志记录 IAM 决策,用于调试、审计和测试。
### 启用跟踪
```
# 将结构化跟踪输出到文件
IAM_TRACE_OUTPUT=./authz-trace.jsonl ./server --config policy.yaml
# 或输出到 stdout 用于调试
IAM_TRACE_OUTPUT=stdout ./server --config policy.yaml
```
### 用例
**调试权限拒绝:**
```
# 查看访问被拒绝的确切原因
cat authz-trace.jsonl | jq 'select(.decision.outcome=="DENY")'
# 输出显示 principal、resource、permission 和原因
```
**审计测试覆盖率:**
```
# 列出测试实际使用的所有权限
cat authz-trace.jsonl | jq -r '.action.permission' | sort -u
# 查看测试了哪些 principal
cat authz-trace.jsonl | jq -r '.actor.principal' | sort -u
```
**验证策略更改:**
```
# 策略更改前
IAM_TRACE_OUTPUT=./before.jsonl go test ./...
# 策略更改后
IAM_TRACE_OUTPUT=./after.jsonl go test ./...
# 比较结果(检测回归)
diff <(jq -r '.decision.outcome' before.jsonl | sort) \
<(jq -r '.decision.outcome' after.jsonl | sort)
```
**CI/CD 合规性:**
```
# 证明 CI 仅访问了允许的资源
cat ci-audit.jsonl | \
jq -r 'select(.decision.outcome=="ALLOW") | .target.resource' | \
grep -v "projects/prod/" && echo "❌ Unauthorized access" || echo "✅ Compliant"
```
### 跟踪事件 Schema
每个跟踪事件都是一行 JSON,包含:
- **Actor:** `actor.principal`(谁)
- **Target:** `target.resource`(什么)
- **Action:** `action.permission`(哪个权限)
- **Decision:** `decision.outcome`(ALLOW 或 DENY)
- **Reason:** `decision.reason`(原因)
- **Timing:** `decision.latency_ms`(性能)
**示例事件:**
```
{"schema_version":"1.0","event_type":"authz_check","timestamp":"2026-01-28T10:15:23.483Z","actor":{"principal":"user:alice@example.com"},"target":{"resource":"projects/test/secrets/db-password"},"action":{"permission":"secretmanager.secrets.get"},"decision":{"outcome":"ALLOW","reason":"binding_match","latency_ms":3}}
```
请参阅 `gcp-emulator-auth/pkg/trace` 了解完整的 schema 定义。
## v0.3.0 功能
### 条件绑定
使用 CEL 表达式根据资源属性限制访问:
```
projects:
test-project:
bindings:
# CI can only access production secrets
- role: roles/secretmanager.secretAccessor
members:
- serviceAccount:ci@test-project.iam.gserviceaccount.com
condition:
expression: 'resource.name.startsWith("projects/test-project/secrets/prod-")'
title: "Production secrets only"
description: "CI service account restricted to production secrets"
# Time-based access
- role: roles/cloudkms.cryptoKeyEncrypterDecrypter
members:
- serviceAccount:temp-access@test-project.iam.gserviceaccount.com
condition:
expression: 'request.time < timestamp("2026-12-31T23:59:59Z")'
title: "Temporary access"
```
**支持的 CEL 表达式:**
- `resource.name.startsWith("prefix")` - 匹配资源名称前缀
- `resource.type == "SECRET"` - 匹配资源类型(SECRET、CRYPTO_KEY、KEY_RING)
- `request.time < timestamp("2026-12-31T00:00:00Z")` - 基于时间的访问
### 群组支持
定义可重用的群组以减少重复:
```
groups:
developers:
members:
- user:alice@example.com
- user:bob@example.com
- serviceAccount:dev-bot@test-project.iam.gserviceaccount.com
operators:
members:
- user:ops@example.com
- group:oncall # Nested groups (1 level supported)
oncall:
members:
- user:charlie@example.com
- user:diana@example.com
projects:
test-project:
bindings:
- role: roles/viewer
members:
- group:developers # Reference group
```
### REST API
所有 IAM 操作的 HTTP REST 网关:
```
# 使用 REST API
server --config policy.yaml --http-port 8081
```
**示例请求:**
```
# 设置 IAM 策略
curl -X POST http://localhost:8081/v1/projects/test-project:setIamPolicy \
-H "Content-Type: application/json" \
-d '{
"policy": {
"bindings": [{
"role": "roles/viewer",
"members": ["user:dev@example.com"]
}]
}
}'
# 获取 IAM 策略
curl http://localhost:8081/v1/projects/test-project:getIamPolicy
# 测试权限
curl -X POST http://localhost:8081/v1/projects/test-project/secrets/api-key:testIamPermissions \
-H "Content-Type: application/json" \
-H "X-Emulator-Principal: serviceAccount:ci@test.iam.gserviceaccount.com" \
-d '{
"permissions": [
"secretmanager.versions.access",
"secretmanager.secrets.delete"
]
}'
```
**响应:**
```
{
"permissions": ["secretmanager.versions.access"]
}
```
### 策略 Schema v3
完全支持 IAM Policy v3 功能:
- **etag** - 基于 SHA256 的乐观并发控制
- **version** - 策略格式版本(1=基本,3=带条件)
- **auditConfigs** - 审计日志配置
- **bindings[].condition** - 条件角色绑定
### 自定义角色(v0.4.0)
为您自己的任何 GCP 服务定义角色到权限的映射:
```
roles:
roles/custom.dataReader:
permissions:
- bigquery.datasets.get
- bigquery.tables.list
- bigquery.tables.getData
roles/custom.pubsubPublisher:
permissions:
- pubsub.topics.publish
- pubsub.topics.get
roles/custom.storageAdmin:
permissions:
- storage.buckets.create
- storage.buckets.delete
- storage.objects.create
- storage.objects.delete
projects:
test-project:
bindings:
- role: roles/custom.dataReader
members:
- user:analyst@example.com
```
**功能:**
- **可扩展** - 为任何 GCP 服务定义权限
- **覆盖内置角色** - 自定义角色优先
- **默认严格模式** - 未知角色被拒绝(捕获配置错误)
- **兼容模式可用** - 使用 `--allow-unknown-roles` 的通配符回退
- `roles/secretmanager.customRole` → 授予 `secretmanager.*`
- `roles/cloudkms.encryptOnly` → 授予 `cloudkms.*`
**为什么这很重要:**
- GCP 有数千个权限 - 硬编码不可扩展
- 每个测试环境需要不同的权限
- 保持模拟器离线、确定性和 CI 友好
**模式:**
**严格模式(默认,推荐):**
```
server --config policy.yaml
```
- 未知角色 → **拒绝**
- 自定义角色 → 允许
- 内置角色 → 允许
- **捕获错误**:如果您使用未定义的角色,测试将失败
**兼容模式(不那么严格):**
```
server --config policy.yaml --allow-unknown-roles
```
- 未知角色 → **通配符匹配**(如果服务前缀匹配)
- 更宽松,但可能隐藏错误
- 用于迁移现有测试时
**决策顺序:**
1. 自定义角色(最高优先级)
2. 内置角色(基元 + Secret Manager + KMS)
3. 通配符匹配(仅在兼容模式)
4. 拒绝(严格模式默认)
## 架构
**内存策略存储**,具有线程安全的并发访问。**简单的权限引擎**,将角色映射到权限。**资源级策略**(MVP 中无组织/文件夹层级)。**不铸造 token**(仅策略评估)。
## 路线图
**未来考虑:**
**角色包(可选的便利):**
- 可选的导入包,如 `packs/pubsub.yaml`、`packs/bigquery.yaml`
- 用户仅导入他们需要的
- 社区维护,非模拟器硬编码
- 示例:`roles: !include packs/storage.yaml`
**不计划:**
- 大型内置权限数据库(造成维护噩梦)
- 与 GCP IAM API 自动同步(增加网络依赖)
- 完美的 GCP IAM 保真度(不是目标)
**策略:** 保持模拟器**专注和可持续**。用户通过自定义角色定义他们需要的。内置集保持精简(仅基元 + Secret Manager + KMS)。
请参阅 [ROADMAP.md](docs/ROADMAP.md) 了解完整详情。
## 与 GCP IAM 的 API 对等
### 已实现的内容
**方法:**
- `SetIamPolicy` - 完整实现
- `GetIamPolicy` - 完整实现
- `TestIamPermissions` - 完整实现,带主体匹配
**策略字段:**
- `bindings[]` - 带成员的角色分配
- `role` - IAM 角色字符串
- `members[]` - 主体标识符
- `version` - 策略格式版本(1=基本,3=条件)
- `etag` - 基于 SHA256 的乐观并发控制
- `auditConfigs[]` - 审计日志配置
- `bindings[].condition` - 条件角色绑定(CEL 表达式)
**功能:**
- 通过 gRPC 元数据注入主体
- 资源层级策略继承
- 自定义角色(可扩展到任何 GCP 服务)
- 条件绑定(CEL 表达式)
- 群组支持(嵌套,1 级)
- REST API 网关(HTTP/JSON)
- 增强的跟踪模式(JSON 输出、持续时间指标)
- 严格模式(默认拒绝未知角色)
### 限制
- 无组织/文件夹层级(项目是根)
- 无服务账号或 token 铸造
- 无审计日志执行(接受 auditConfigs 但不执行)
- CEL 表达式:仅基本子集(startsWith、类型相等、时间比较)
**当前范围:** 用于与模拟器进行 CI/CD 测试的核心 IAM 策略操作
## 项目状态
作为战略"基石"认证层提取,以支持完整的 GCP 模拟器生态系统测试。
## 免责声明
此项目不隶属于 Google LLC 或 Google Cloud Platform,未经其认可或赞助。"Google Cloud"、"IAM"及相关商标是 Google LLC 的财产。这是用于测试和开发目的的独立开源实现。
## 维护者
由 **Dayna Blackwell** 维护 — Blackwell Systems 创始人,构建云原生开发的参考基础设施。
[GitHub](https://github.com/blackwell-systems) · [LinkedIn](https://linkedin.com/in/dayna-blackwell) · [Blog](https://blog.blackwell-systems.com)
## 商标
**Blackwell Systems™** 和 **Blackwell Systems 标志**是 Dayna Blackwell 的商标。您可以使用"Blackwell Systems"名称来指代此项目,但不得以暗示认可或官方关联的方式使用该名称或标志,除非事先获得书面许可。使用指南请参阅 [BRAND.md](BRAND.md)。
## 相关项目
- [**gcp-emulator**](https://github.com/blackwell-systems/gcp-emulator) - 统一单进程运行时(IAM + Secret Manager + KMS + Eventarc)
- [CP Secret Manager 模拟器](https://github.com/blackwell-systems/gcp-secret-manager-emulator) - IAM 强制的 Secret Manager 数据平面
- [GCP KMS 模拟器](https://github.com/blackwell-systems/gcp-kms-emulator) - IAM 强制的 KMS 数据平面
- [GCP Eventarc 模拟器](https://github.com/blackwell-systems/gcp-eventarc-emulator) - IAM 强制的 Eventarc 数据平面
- [gcp-emulator-auth](https://github.com/blackwell-systems/gcp-emulator-auth) - 强制代理库(守护者)
## 谁在使用这个?
如果您正在使用此 IAM 模拟器 — 在 CI 中、本地或测试框架中 — 我很乐意了解您如何使用它。
- **您捕获了什么授权错误?**(缺失绑定、错误的角色定义、条件策略问题)
- **您如何定义角色?**(主要是内置、主要是自定义 YAML、混合)
- **您的设置是什么?**(独立策略引擎、与数据平面模拟器编排、自定义集成)
- **还有什么摩擦?**(policy.yaml 复杂性、跟踪模式集成、缺失的 GCP 角色等效)
打开 issue、开始讨论或直接联系:
📬 dayna@blackwell-systems.com
这有助于塑造路线图,并确保项目与实际需求保持一致。
## 许可证
Apache License 2.0 - 详情请参阅 [LICENSE](LICENSE)。
标签:EVTX分析, GCP, Go, IAM, Python工具, Ruby工具, SOC Prime, Streamlit, Web报告查看器, 安全测试, 开发工具, 授权测试, 攻击性安全, 无凭证测试, 日志审计, 本地开发, 权限管理, 模型越狱, 策略即代码, 策略模拟, 聊天机器人安全, 角色管理, 访问控制, 请求拦截