AWS Organizations の SCP クォータが倍増したので実際に10個アタッチと10,240文字ポリシーを試してみた
2026年5月15日、AWS Organizations の SCP クォータ引き上げが発表されました。
今回のアップデートによる主な変更点です。
| 項目 | 旧 | 新 |
|---|---|---|
| 1ターゲット(ルート/OU/アカウント)あたりSCPアタッチ数 | 5 | 10 |
| SCPポリシーサイズ | 5,120文字 | 10,240文字 |
アタッチ数とポリシーサイズがそれぞれ2倍になりました。AWS Organizations はグローバルサービスのため、このクォータ変更は利用者側のアクションなしで利用可能になります。個別リージョンでの設定変更は不要です。
FullAWSAccess をデフォルトのまま残した場合、旧上限では残り4つしかカスタムSCPを追加できませんでした。新上限10になったことで、以下のようにポリシーを用途別に分離した管理が可能になりました。
| SCP | 内容 |
|---|---|
| FullAWSAccess | デフォルトでアタッチされる SCP。Deny リスト運用を想定 |
| リージョン制限 | 許可リージョン以外を Deny |
| IP制限 | 社内ネットワーク以外からの操作を Deny |
| ガードレール(IAM) | IAMロール削除・変更の防止 |
| ガードレール(CloudTrail) | CloudTrail 無効化の防止 |
| ガードレール(S3) | S3 パブリックアクセスの防止 |
| ガードレール(EC2) | 特定インスタンスタイプの制限 |
| ガードレール(Organizations) | Organization 離脱の防止 |
| コスト制御 | 高額サービスの利用制限 |
旧上限では「リージョン制限とガードレールを1つのSCPにまとめる」といった妥協が必要でしたが、新上限では用途ごとに1SCP=1責務で管理でき、変更時の影響範囲も明確になります。
検証1: アタッチ数上限
テスト用の空OUを作成し、FullAWSAccess(自動アタッチ)に加えてダミーSCPを順次アタッチしました。アタッチ数だけを検証したかったため、権限制限を追加しない Allow * のダミーSCPを使用しました。
| テスト | 内容 | 結果 |
|---|---|---|
| 旧上限超え | FullAWSAccess + 6個 = 合計7個 | ✅ 成功 |
| 新上限到達 | FullAWSAccess + 9個 = 合計10個 | ✅ 成功 |
| 新上限超え | 11個目のアタッチ試行 | ❌ エラー |
10個アタッチに成功した状態の list-policies-for-target 出力です。
aws organizations list-policies-for-target \
--target-id ou-xxxx-xxxxxxxx \
--filter SERVICE_CONTROL_POLICY \
--region us-east-1
{
"Policies": [
{"Id": "p-FullAWSAccess", "Name": "FullAWSAccess"},
{"Id": "p-abc00001", "Name": "SCP-QuotaTest-01"},
{"Id": "p-abc00002", "Name": "SCP-QuotaTest-02"},
{"Id": "p-abc00003", "Name": "SCP-QuotaTest-03"},
{"Id": "p-abc00004", "Name": "SCP-QuotaTest-04"},
{"Id": "p-abc00005", "Name": "SCP-QuotaTest-05"},
{"Id": "p-abc00006", "Name": "SCP-QuotaTest-06"},
{"Id": "p-abc00007", "Name": "SCP-QuotaTest-07"},
{"Id": "p-abc00008", "Name": "SCP-QuotaTest-08"},
{"Id": "p-abc00009", "Name": "SCP-QuotaTest-09"}
]
}
11個目のアタッチを試みると、以下のエラーが返されました。
An error occurred (ConstraintViolationException) when calling the AttachPolicy operation:
You have attached the maximum number of policies to the specified target.
Additional error details:
Reason: MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED
継承で適用されるポリシーはアタッチ数にカウントされません。上位OUにアタッチされたポリシーは継承で評価されますが、子OUのアタッチ数枠は消費しません(直接アタッチのみカウント)。
IaC 実行時の原因切り分けでは、人間向けのメッセージ本文よりも Reason コードで判定する方が確実です。アタッチ数超過は MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED、後述のサイズ超過は POLICY_CONTENT_LIMIT_EXCEEDED です。
検証2: ポリシーサイズ上限
IP制限のSCPで多数の拠点CIDRを列挙するユースケースを想定し、Condition.NotIpAddress.aws:SourceIp にCIDRを大量に並べて文字数を調整しました。
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyUnlessFromApprovedIPs",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"10.0.0.0/24",
"10.0.1.0/24",
"10.0.2.0/24",
...(中略、全体で 650 CIDRs)...
"10.2.137.0/24"
]
}
}
}]
}
今回の検証データでは、新上限で約650個の CIDR まで収められました。実際に収まる数は CIDR 文字列の長さやポリシー構造によって変わります。
ASCII のみで構成した compact JSON を wc -c でバイト数を計測しました(ASCII のみのため文字数と一致します。公式ドキュメントの表記は "characters")。
| テスト | ポリシーサイズ | 結果 |
|---|---|---|
| 上限以内 | 10,236文字(650 CIDRs) | ✅ 成功 |
| 上限超過 | 10,252文字(651 CIDRs) | ❌ エラー |
上限超過時のエラーです。
An error occurred (ConstraintViolationException) when calling the CreatePolicy operation:
You have exceeded the maximum policy size.
Additional error details:
Reason: POLICY_CONTENT_LIMIT_EXCEEDED
検証3: ホワイトスペースの扱い
公式ドキュメントには、コンソールではホワイトスペースが自動除去され、CLI/SDKではそのまま保存されると記載されています。今回は CLI で保存した場合に、ホワイトスペースがサイズに含まれることを確認しました。
マネジメントコンソールでは、保存時に JSON 要素間の余分なホワイトスペースが自動除去されるため、これらはサイズに含まれません。一方、CLI/SDK では送信したポリシー本文がそのまま扱われるため、改行やインデントもサイズに含まれます。
| 保存方法 | ポリシーサイズ(CLI送信時) | 結果 |
|---|---|---|
| CLI pretty-print | 17,359文字(※compact換算では9,448文字で上限以内) | ❌ 送信時の文字数17,359がそのままカウントされ上限超過 |
| CLI pretty-print | 5,950文字(compact換算3,239文字) | ✅ 成功、ホワイトスペース保持を確認 |
compact に変換すれば上限以内に収まるポリシーでも、pretty-print のまま CLI で保存するとサイズ超過エラーになりました。describe-policy で取得してもインデントや改行がそのまま保持されていることを確認しました。CLI で SCP を管理する場合は compact JSON(jq -c 等)で保存することを推奨します。
再現手順
以下のスクリプトで、アタッチ数上限とポリシーサイズ上限の検証を再現できます。Organizations 管理アカウントの認証情報と、SCPが有効化された Organization が必要です。検証用の空 OU を作成して実行してください。本番アカウントが所属する OU では実行しないでください。
スクリプトでは 10,240 文字以下に収まる上限付近のポリシーを生成します。本文中の文字数は検証時の実測値です。
test-scp-quota.sh(クリックで展開)
#!/bin/bash
# AWS Organizations SCP クォータ引き上げ検証スクリプト
# 前提: Organizations 管理アカウントの認証情報、python3
# 実行: ./test-scp-quota.sh
set -euo pipefail
REGION="us-east-1"
SCP_CONTENT='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'
GREEN='\033[0;32m'; RED='\033[0;31m'; NC='\033[0m'
pass() { echo -e "${GREEN}✅ PASS${NC}: $1"; }
fail() { echo -e "${RED}❌ FAIL${NC}: $1"; }
ROOT_ID=$(aws organizations list-roots --region "$REGION" --query 'Roots[0].Id' --output text)
echo "=== Part 1: アタッチ数上限テスト ==="
OU_ID=$(aws organizations create-organizational-unit \
--parent-id "$ROOT_ID" --name "SCP-Quota-Test" \
--region "$REGION" --query 'OrganizationalUnit.Id' --output text)
POLICY_IDS=()
for i in $(seq -w 1 10); do
PID=$(aws organizations create-policy \
--name "SCP-QuotaTest-${i}" --description "Quota test ${i}" \
--type SERVICE_CONTROL_POLICY --content "$SCP_CONTENT" \
--region "$REGION" --query 'Policy.PolicySummary.Id' --output text)
POLICY_IDS+=("$PID")
sleep 1
done
for i in $(seq 0 5); do
aws organizations attach-policy --policy-id "${POLICY_IDS[$i]}" --target-id "$OU_ID" --region "$REGION"
sleep 1
done
COUNT=$(aws organizations list-policies-for-target --target-id "$OU_ID" \
--filter SERVICE_CONTROL_POLICY --region "$REGION" --query 'length(Policies)' --output text)
[ "$COUNT" -eq 7 ] && pass "旧上限超え: ${COUNT}個" || fail "期待7個、実際${COUNT}個"
for i in $(seq 6 8); do
aws organizations attach-policy --policy-id "${POLICY_IDS[$i]}" --target-id "$OU_ID" --region "$REGION"
sleep 1
done
COUNT=$(aws organizations list-policies-for-target --target-id "$OU_ID" \
--filter SERVICE_CONTROL_POLICY --region "$REGION" --query 'length(Policies)' --output text)
[ "$COUNT" -eq 10 ] && pass "新上限到達: ${COUNT}個" || fail "期待10個、実際${COUNT}個"
if ERROR=$(aws organizations attach-policy --policy-id "${POLICY_IDS[9]}" \
--target-id "$OU_ID" --region "$REGION" 2>&1); then
fail "11個目がエラーにならなかった"
else
echo "$ERROR" | grep -q "MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED" && \
pass "11個目でエラー: MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED" || fail "$ERROR"
fi
echo "=== クリーンアップ ==="
for PID in "${POLICY_IDS[@]}"; do
aws organizations detach-policy --policy-id "$PID" --target-id "$OU_ID" --region "$REGION" 2>/dev/null || true
sleep 0.5
aws organizations delete-policy --policy-id "$PID" --region "$REGION"
sleep 0.5
done
aws organizations delete-organizational-unit --organizational-unit-id "$OU_ID" --region "$REGION"
echo "=== Part 2: ポリシーサイズ上限テスト ==="
python3 -c "
import json
cidrs = [f'10.{i}.{j}.0/24' for i in range(50) for j in range(256)]
policy = {'Version':'2012-10-17','Statement':[{'Sid':'Test','Effect':'Deny','Action':'*','Resource':'*','Condition':{'NotIpAddress':{'aws:SourceIp':cidrs}}}]}
compact = json.dumps(policy, separators=(',',':'))
while len(compact) > 10240:
cidrs.pop()
policy['Statement'][0]['Condition']['NotIpAddress']['aws:SourceIp'] = cidrs
compact = json.dumps(policy, separators=(',',':'))
with open('/tmp/scp-max.json','w') as f: f.write(compact)
cidrs.append(f'10.{len(cidrs)//256}.{len(cidrs)%256}.0/24')
policy['Statement'][0]['Condition']['NotIpAddress']['aws:SourceIp'] = cidrs
with open('/tmp/scp-over.json','w') as f: f.write(json.dumps(policy, separators=(',',':')))
print(f'Max: {len(compact)} chars ({len(cidrs)-1} CIDRs), Over: {len(json.dumps(policy, separators=(chr(44),chr(58))))} chars ({len(cidrs)} CIDRs)')
"
if PID=$(aws organizations create-policy --name "SCP-SizeTest-Max" --description "Size test" \
--type SERVICE_CONTROL_POLICY --content file:///tmp/scp-max.json \
--region "$REGION" --query 'Policy.PolicySummary.Id' --output text 2>&1); then
pass "上限以内のポリシー作成成功"
aws organizations delete-policy --policy-id "$PID" --region "$REGION"
else
fail "$PID"
fi
if ERROR=$(aws organizations create-policy --name "SCP-SizeTest-Over" --description "Size test over" \
--type SERVICE_CONTROL_POLICY --content file:///tmp/scp-over.json \
--region "$REGION" 2>&1); then
fail "上限超過がエラーにならなかった"
else
echo "$ERROR" | grep -q "POLICY_CONTENT_LIMIT_EXCEEDED" && \
pass "上限超過でエラー: POLICY_CONTENT_LIMIT_EXCEEDED" || fail "$ERROR"
fi
echo "=== 全検証完了 ==="
まとめ
SCPのアタッチ上限とポリシーサイズがそれぞれ2倍になりました。既存のSCP設定への影響はなく、AWS Organizations はグローバルサービスのため利用者側のアクションなしで新しいクォータを利用できます。用途別にSCPを分離した設計がしやすくなり、ポリシーサイズの制約も緩和されました。ただしCLI/SDKで管理している場合はホワイトスペースがそのまま文字数にカウントされるため、compact JSONで保存することを推奨します。







