AWS Config × Conformance Pack × Aggregator 管理架構
說明 AWS Config Rule、Conformance Pack 與 Aggregator 的觀念、部署組合、參考架構與操作 SOP。
TL;DR
- Config Rules
- 一項合規檢查的基本單位
- 可以使用 AWS managed / Custom Lambda / Custom Guard 三種
- Custom Lambda:直接寫 Lambda 來做裡面的檢查
- Custom Guard:使用 Guard custom policy syntax 來寫檢查規則
- Conformance pack
- 使用規則
- 一個 conformance pack 可以有很多條 config rules
- 不能在 conformance pack 裡面宣告 lambda,只能引用現有的 lambda arn
- Conformance Pack 格式是特化的 CloudFormation yaml,裡面只能放 config rule 和 remediation config
- Conformance pack 部署方式
- 每帳號自建:需在各個帳號裡執行 aws_config_conformance_pack API
- Org-level push:僅需在 mgmt / delegated admin 帳號內執行 aws_config_organization_conformance_pack API,AWS 會自動用 CloudFormation StackSets 推到 org 內所有 member
- 使用規則
- Aggregator
- Org-level 或 Account-level 檢視 conformance pack 的檢查結果,前者顯示整個組織下的所有帳號、後者自行決定要檢視的帳號
- 看到的會是 by conformance pack 的檢查結果,因此若有針對不同應用架構的多種規則也可以使用 conformance pack 來區分
1. AWS Config 基礎觀念
AWS Config 做兩件事:
- 紀錄資源配置(Configuration Recording):把帳號內指定 resource type 的當前狀態序列化成 Configuration Item(CI),每次資源變動都存一份。
- 評估合規(Rule Evaluation):對 CI 或帳號整體狀態套用 rule,產出 COMPLIANT / NON_COMPLIANT / NOT_APPLICABLE / INSUFFICIENT_DATA 四種結果。
核心元件
| 元件 | 說明 |
|---|---|
| Configuration Recorder | 定義要記錄哪些 resource type 的 CI;每個帳號 × region 最多一個 |
| Delivery Channel | 把 CI 打包送到 S3(+ optional SNS / CloudWatch),與 Recorder 一對一 |
| Configuration Item(CI) | 資源在某個時間點的 JSON 快照,是 rule 評估的原料 |
| Config Rule | 對 CI 或帳號狀態的合規判斷邏輯 |
| Conformance Pack | 一組 Rule + 選用的 Remediation,以「單一單位」部署/管理 |
| Aggregator | 跨帳號、跨 region 匯總所有 rule 評估結果的唯讀視圖 |
Configuration Item 支援度
當你要寫一條 rule 檢查某個資源時,會撞到兩個獨立的問題:
- **這個 resource type 有 CI 嗎? **(resource-type-level) Config 對每個 AWS 服務的 resource type 逐一支援,不是自動全包。例如 AWS::S3::Bucket 有支援,但 AOSS 的 Security Policy、AgentCore 的 Runtime / Memory 都沒有 — Config 不會為這些資源產生 CI 物件。
- **假設 CI 存在,要檢查的欄位在 CI schema 內嗎? **(field-level) 即使 resource 有 CI,AWS 也不見得把每個屬性都塞進 CI schema。典型例子:VPCEndpoint 有 CI,但 CI 不記錄 policyDocument;KMS Key 有 CI,但 CI 只記 metadata + rotation status,不記 key policy JSON。
實例:
| Resource | Config 有 CI? | 要檢查的欄位 / 他是否在 CI schema 內 |
|---|---|---|
| AWS::EC2::VPCEndpoint | ✅ | policyDocument,但 CI schema 裡沒有 ❌ |
| AWS::KMS::Key | ✅ | key policy,CI 只有 metadata + rotation ❌ |
| AWS::EC2::RouteTable | ✅ | routes.gatewayId / natGatewayId,都在 CI ✅ |
| AWS::S3::Bucket | ✅ | bucket policy、encryption 都有在 CI schema 裡 ✅ |
| AOSS Security Policy | ❌ | — |
| AgentCore Runtime / Memory | ❌ | — |
完整 CI schema 見 AWS Config resource schema GitHub。
這兩個層次會決定「一條 custom rule 可以用什麼機制實作」,而且對三種 rule 類型的 bind 方式不一樣 — 見第 2 節。
2. Config Rule 三種類型
| 類型 | 由誰執行 | 何時觸發 | 部署 |
|---|---|---|---|
| Managed Rule | AWS 內部 | 依 rule 定義,configuration-change / periodic 都支援 | 只需引用 SourceIdentifier(如 S3_BUCKET_SSL_REQUESTS_ONLY) |
| Custom Lambda | Lambda function | 兩種都可 | 需先部署 Lambda,再把 ARN 寫入 rule 的 SourceIdentifier |
| Custom Policy(Guard) | Config 服務內部的 Guard runtime | configuration-change 為主 | Guard DSL 直接寫在 PolicyText,inline 在 rule 定義內 |
兩種觸發模式
- configuration-change:CI 改變時觸發,即時但只對「有 CI」的資源
- periodic:每 1/3/6/12/24 小時跑一次,呼叫控制面 API 拉資料
沒有 CI 的資源只能走 periodic(因為 CI 事件源不存在);有 CI 的資源兩種都行。
選型決策
Managed rule 存在?
├─ 有 → Managed Rule
└─ 沒有 → 要檢查的資源欄位在 CI schema 內?
├─ 有 → Guard 或 Custom Lambda 皆可
└─ 沒有 → Custom Lambda periodic
Guard vs Custom Lambda 的取捨
當要檢查的欄位在 CI schema 內,兩種都能寫,選哪個看團隊狀況:
| 選 Guard 的理由 | 選 Custom Lambda 的理由 |
|---|---|
| Rule 完整寫在 pack YAML 內,不用維護 Lambda code | 已經有 dispatcher Lambda 在跑,加一條 rule 只需新增 handler + HANDLERS map 一行 |
| 免掉 IAM role / Lambda function / CW Log Group 的維運成本 | 團隊熟悉 Python,不想學 Guard DSL |
| 邏輯純粹是 CI 欄位結構比對(沒有跨資源查詢) | 邏輯可能會演進到需要跨資源查詢或呼叫外部 API |
實務上規模化後兩派都常見。如果專案已經 commit 到 Lambda dispatcher 模式,新 rule 用 Lambda 的邊際成本比 Guard 低;如果從零開始,Guard 省下整套 Lambda 基礎建設。
3. Conformance Pack 的本質
Conformance Pack 本質上是一個 受限的 CloudFormation template,只允許兩種 resource type:
- AWS::Config::ConfigRule
- AWS::Config::RemediationConfiguration
Template 大小上限 51,200 bytes。以 CloudFormation stack 形式在後台跑,stack 名稱是 awsconfigconforms-<pack-name>,由 Config 服務自動管理。
Pack 建立時 AWS 會自動產一個 delivery bucket 叫 awsconfigconforms-<accountId>-<random>,用來存 pack 內部的 CFN 中繼檔;也可以自己指定 bucket。
Organization Level 的 Conformance Pack 可以直接把檢查推送到 linked account 中
一個常見誤解:Pack 不能包裝 Lambda
Custom Lambda rule 需要 Lambda function 已經存在;Lambda 不能直接寫在 pack template 裡(因為 AWS::Lambda::Function 不在允許清單內)。
這帶來一個關鍵限制:如果 pack 有 Custom Lambda rule,Lambda 必須另外用 Terraform / CloudFormation / SAM / 手動部署,pack 只是引用 ARN。
Custom vs Managed Conformance Pack
- Managed Conformance Pack:AWS 提供的合規範本(如 CIS、HIPAA、PCI),template 內容 AWS 寫好,挑需要的套用即可
- Custom Conformance Pack:自己寫的 YAML template,可以混用 Managed Rule / Custom Policy / Custom Lambda
4. Aggregator vs 跨帳號 Push 機制
Aggregator 啟用後,可以看到被允許的各個帳號中,Conformance pack 的檢查結果。
Aggregator 儀表板上看到的 pack 名稱,是 member 帳號本地存在的 pack 資源,aggregator 把結果拉過來顯示;pack 可能是 member 自己 apply 的,也可能是被 org push 進去的,aggregator 認 pack 資源本身,不認來源。
Aggregator Sources
| Source 類型 | 涵蓋範圍 | 加減帳號時 | 需要什麼權限 |
|---|---|---|---|
| Account-based | 手動列 account IDs + regions;每個 member 需要 aws_config_aggregate_authorization 授權 | 手改清單 + 授權 | 每 member 一份 authorization |
| Organization-based | 整個 org(或指定 OU)自動涵蓋 | Org 加減帳號自動反映 | Aggregator 端一個 IAM role,member 端零維護 |
兩種都純唯讀,差別只在「怎麼決定要匯總哪些帳號」。
部署方式與匯總方式的四種組合
兩軸完全獨立,可以任意組合:
| 部署方式(push side) | 匯總方式(read side) | 適用情境 |
|---|---|---|
| 每帳號自建 pack(TF apply per account) | Org aggregator | 帳號透過 account customization 或 IaC pipeline 開帳,想要 per-account rollout 節奏、豁免容易做 |
| 每帳號自建 pack | Account aggregator | 初期或跨 org 情境,匯總範圍手動維護 |
| Org Conformance Pack push(StackSets) | Org aggregator | 帳號數多、rule 版本統一,最 hands-off |
| Org Conformance Pack push | Account aggregator | 少見;推送給整個 org,只看一部分 |
建議採取的組合:每帳號自建 pack + Org aggregator
多數企業治理情境下推薦這個組合,理由:
- rollout 節奏可控:新版 pack 可以先在 canary 帳號 apply、觀察一週,再擴散;org pack push 是一次全推
- 豁免容易:某帳號有特殊情況要臨時關 rule 或改參數,直接改該帳號的 IaC 即可;org pack push 要嘛全套用、要嘛整個排除該帳號
- 與 account customization 天然對齊:如果帳號本來就有 per-account IaC(AFT、Account Factory 等),多一個 pack module 沒有額外操作成本
- 匯總視圖仍統一:Aggregator 只做 read-side 匯總,不受部署方式影響,依然一個儀表板看全部帳號
什麼時候該考慮改成 org pack push?
- 帳號數增長到「不想再逐個 apply」的規模
- Rule 版本要求全 org 同步(不接受任何帳號落後版本)
- 沒有 per-account IaC pipeline,不想為了單一 pack 建立整套帳號級部署基建
從「每帳號自建」搬到「org pack push」的變更成本不大 — pack YAML 內容不動,只是把 aws_config_conformance_pack 換成 aws_config_organization_conformance_pack,搬到 delegated admin 帳號的 state 內。
Delegated Administrator
Aggregator 建議放在 Delegated Admin 帳號(通常是 Audit / Security),原因:
- Management Account 儘量少直接 apply 資源,降低 blast radius
- Config Delegated Admin 是官方支援的委派模型
- Audit 帳號本來就是合規團隊 daily 進出的地方,權限模型天然對齊
前置條件(在 mgmt 帳號一次性做):
aws organizations enable-aws-service-access \
--service-principal config.amazonaws.com
aws organizations enable-aws-service-access \
--service-principal config-multiaccountsetup.amazonaws.com
aws organizations register-delegated-administrator \
--account-id <audit-account-id> \
--service-principal config.amazonaws.com
5. 參考架構(Reference Architecture)
以下為「每帳號自建 pack + Org aggregator + Custom Lambda rule 混用」的參考架構圖。
flowchart TB
subgraph mgmt["Management Account (payer / mgmt)"]
setup["一次性設定 (不寫 Terraform)<br/>• enable-aws-service-access<br/> (config + config-multiaccountsetup)<br/>• register-delegated-administrator"]
end
subgraph admin["Config Delegated Admin 帳號 (通常 = Audit / Security)"]
agg["Configuration Aggregator<br/>organization aggregation source<br/>regions = [目標 region 清單]<br/><i>(console / CLI 手動設定)</i>"]
api["操作介面<br/>• AWS Config console → Aggregators<br/>• describe-aggregate-compliance-* API"]
end
subgraph member["Member 帳號 (N 個,每個獨立 IaC state)"]
rec["Configuration Recorder<br/>+ Delivery Channel"]
lam["Dispatcher Lambda + IAM + CloudWatch Logs<br/>handler: rule_id 分派到平鋪函式"]
pack["Conformance Pack<br/>• Managed Rules<br/>• Custom Policy Rules<br/>• Custom Lambda Rules<br/>→ SourceIdentifier = 本帳號 Lambda"]
lam -->|Lambda ARN| pack
end
mgmt -->|委派| admin
member -.->|唯讀匯總結果<br/>member → aggregator| admin
三個關鍵設計決定
| 決策 | 建議做法 | 理由 |
|---|---|---|
| Rule 部署粒度 | 收攏成 單一 Conformance Pack | 版本化、加減規則、部署撤除都以「pack」為單位;不需一條條 apply |
| Custom Lambda 部署位置 | 本帳號而非 delegated admin | Custom Lambda rule 只能引用同帳號同 region 的 Lambda ARN;in-account 也免了跨帳號 AssumeRole 的複雜度 |
| Module 拆分 | Lambda 一個 module,Pack 一個 module | Pack template 無法包 Lambda;拆點選在 infra vs rule 邊界,rule 迭代不動 infra |
多條 Custom Lambda rule 的組織方式
常見的兩種做法:
- 每條 rule 一個 Lambda:code 隔離最徹底,但 IAM role / Log Group / permission 數量會 × N
- 共用一支 dispatcher Lambda + rule_id 分派:handler 平鋪為 .py 檔,以 input_parameters.rule_id 分派到對應 handler。加新 rule 只需寫 handler + 加 HANDLERS map 對應 + 加 rule YAML
當 rule 數超過三條、且都用 periodic ScheduledNotification 模式(呼叫控制面 API 拉資料),建議走 dispatcher 模式 — 維運成本明顯低於逐個 Lambda。
6. 優缺點與適用邊界
優點
- Rule 生命週期集中管理 加規則、改規則、下架規則都改一個 YAML,配合 Terraform 部署後所有帳號自動同步。
- 無跨帳號權限依賴 每個帳號完全自足:Recorder / Rule / Lambda / IAM 都在同一帳號內。Lambda 不需要跨帳號 AssumeRole。
- 合規視野一致 Aggregator 提供單一儀表板,describe-aggregate-* API 讓稽核團隊一次撈全 org 的 non-compliant 資源。
- 版本化 + 可追溯 Pack YAML 存在 Git,規則變更走 PR review;規則 rollout / rollback 由 Terraform state 掌握。
- Managed / Guard / Lambda 三種混用彈性 對每一條 rule 都能挑最合適的實作方式,不會被單一機制綁死。
缺點與限制
- Pack template 硬限制 51,200 bytes 規則多到幾十條時可能要拆多個 pack。
- Custom Lambda 需要在每個帳號部署一份 雖然 IaC 自動化,但相比「集中一支 Lambda 跨帳號評估」,IAM role / CW LG / Lambda function 的數量會 × N。Lambda 本身 pay-per-invoke,成本影響通常很小。
- Guard 能力受 CI schema 限制 Policy JSON、非 CI 資源都用不了 Guard,只能退到 Lambda。這是 AWS 平台限制,無法繞。
- Managed rule 依賴 CI recording 若 Recorder 沒起來 / delivery channel 沒設,Managed rule 全部會停在 INSUFFICIENT_DATA。Custom Lambda periodic rule 不受此影響。
- Periodic rule 有評估延遲 MaximumExecutionFrequency 最短 1 小時,最長 24 小時。違規到偵測有 window;需要更即時要改 SCP 或事件驅動架構。
- Pack template 內只能放 rule / remediation Lambda / IAM role / CW Log Group 這些都得靠 IaC 另建,pack 本身沒辦法自帶。
什麼情境該用這個架構
適合:
- 有明確合規清單且會版本化管理
- 帳號數在幾十到幾百之間
- 有明確 Delegated Admin 帳號承接稽核責任
不適合:
- Rule 只有兩三條 → 直接建 config rule 就好,不用打包
- 沒有 org 結構(單帳號)→ Aggregator 意義不大,直接看本帳號 Config console 即可
- 需要跨組織審計(不同 payer)→ 需要別的方案(例如把資料匯到 Security Data Lake)
7. 操作 SOP
7.1 首次啟用整個架構
以下步驟按執行帳號分組。
A. Management Account(一次性)
# 開 Organizations 對 Config service 的信任
aws organizations enable-aws-service-access \
--service-principal config.amazonaws.com
aws organizations enable-aws-service-access \
--service-principal config-multiaccountsetup.amazonaws.com
# 委派 Audit 帳號為 Config admin
aws organizations register-delegated-administrator \
--account-id <audit-account-id> \
--service-principal config.amazonaws.com
aws organizations register-delegated-administrator \
--account-id <audit-account-id> \
--service-principal config-multiaccountsetup.amazonaws.com
B. Config Delegated Admin 帳號(一次性,console 或 CLI)
# 建 aggregator(涵蓋整個 org × 指定 region)
aws configservice put-configuration-aggregator \
--configuration-aggregator-name <aggregator-name> \
--organization-aggregation-source '{
"RoleArn": "arn:aws:iam::<admin-account-id>:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig",
"AllAwsRegions": false,
"AwsRegions": ["<region-1>", "<region-2>"]
}'
或走 console:AWS Config → Aggregators → Create,選 Add my organization,選 region,取名。
C. 每個 Member 帳號(Terraform / CloudFormation / etc.)
參考 module 結構:兩個 module 串接,以 output/input 傳 Lambda ARN。
module "config_infra" {
source = "<path>/config-infra" # Recorder + Delivery Channel + Lambda dispatcher
# 若 CT / LZ 已有 recorder,不重建
manage_config_recorder = false
}
module "config_pack" {
source = "<path>/config-conformance-pack" # Pack YAML + rule
evaluator_lambda_arn = module.config_infra.evaluator_lambda_arn
}
Apply 完成後:
- Recorder / Delivery Channel 就緒
- Dispatcher Lambda 存在
- Conformance Pack 建立成功
- 至下一輪 evaluation cycle 後 rule 開始產生合規結果
- Aggregator 端可看到本帳號的結果
7.2 手動觸發評估(不等 periodic 週期)
# 對某一條 rule 立即評估
aws configservice start-config-rules-evaluation \
--config-rule-names <rule-name>
# 一次觸發本帳號所有指定前綴的 rule
aws configservice describe-config-rules \
--query "ConfigRules[?starts_with(ConfigRuleName, '<prefix>')].ConfigRuleName" \
--output text | tr '\t' '\n' | while read r; do
aws configservice start-config-rules-evaluation --config-rule-names "$r"
done
7.3 查詢合規結果
本帳號視角
# 整個 pack 的合規統計
aws configservice describe-conformance-pack-compliance \
--conformance-pack-name <pack-name>
# 撈 non-compliant 資源細節
aws configservice get-conformance-pack-compliance-details \
--conformance-pack-name <pack-name> \
--filters ComplianceType=NON_COMPLIANT
跨帳號視角(從 Aggregator 帳號)
AGG=<aggregator-name>
# 所有 rule 的跨帳號合規統計
aws configservice describe-aggregate-compliance-by-config-rules \
--configuration-aggregator-name $AGG
# 特定 rule 在特定 member 的 non-compliant 資源
aws configservice get-aggregate-compliance-details-by-config-rule \
--configuration-aggregator-name $AGG \
--config-rule-name <rule-name> \
--account-id <member-id> \
--aws-region <region> \
--compliance-type NON_COMPLIANT
7.4 加一條新 Rule
主要決策:
- AWS 有現成的 Managed rule 嗎? 有 → 用 Managed;沒有 → 走 Custom Lambda
- (補充) 若 rule 邏輯純粹是 CI 欄位比對、且團隊不想維護 Lambda:考慮 Guard
加 Managed rule(只動 Pack module)
NewManagedCheck:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: <rule-name>
Description: "描述"
Source:
Owner: AWS
SourceIdentifier: <MANAGED_RULE_IDENTIFIER>
加 Guard rule(只動 Pack module)
NewGuardCheck:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: <rule-name>
Source:
Owner: CUSTOM_POLICY
SourceDetails:
- EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
CustomPolicyDetails:
PolicyRuntime: guard-2.x.x
PolicyText: |
rule my_check when
resourceType == "AWS::XX::YY"
{
configuration.someField == "expected"
}
Scope:
ComplianceResourceTypes:
- AWS::XX::YY
加 Custom Lambda rule(要動 Lambda module + Pack module)
四步驟:
-
Lambda module 內新增 handler .py,實作:
def evaluate(session, invoking_event: dict, rule_parameters: dict) -> list: return [{ "ComplianceResourceType": "AWS::XX::YY", "ComplianceResourceId": "id", "ComplianceType": "COMPLIANT" | "NON_COMPLIANT" | "NOT_APPLICABLE", "Annotation": "reason"[:256], }] -
Dispatcher main.py 的 HANDLERS map 加對應:
HANDLERS = {..., "XXX": xxx.evaluate} -
若 handler 呼叫新的 AWS API,Lambda 的 IAM policy 加對應 action
-
Pack YAML 加 rule:
XxxRule: Type: AWS::Config::ConfigRule Properties: ConfigRuleName: <rule-name> Source: Owner: CUSTOM_LAMBDA SourceIdentifier: <dispatcher-lambda-arn> SourceDetails: - EventSource: aws.config MessageType: ScheduledNotification MaximumExecutionFrequency: TwentyFour_Hours InputParameters: '{"rule_id": "XXX"}' -
Apply(IaC 工具會依相依序處理 Lambda 更新 → pack 更新)
7.5 撤除
一個 member 帳號的完整下架順序:
# Member 帳號:反向 destroy(pack → Config infra)
# IaC 工具應能依相依序自動處理;強制順序時可 -target
# Delegated Admin 帳號:如要下架 aggregator
aws configservice delete-configuration-aggregator \
--configuration-aggregator-name <aggregator-name>
# Management Account:如要撤 Delegated Admin
aws organizations deregister-delegated-administrator \
--account-id <audit-account-id> \
--service-principal config.amazonaws.com
8. 延伸閱讀
- AWS Config Conformance Packs 官方文件
- Creating AWS Config Custom Policy Rules(Guard)
- AWS Config Resource Schema(哪些 CI 欄位有記錄)
- AWS CloudFormation Guard User Guide
- Configuration Aggregator 官方文件
- Organization Config Rules(push side)
- Organization Conformance Packs(push side)
- put-conformance-pack CLI reference