Slide 1

Slide 1 text

IaC を使いたくないけど ポリシー管理をどうにかしたい [誰でもOK] AWS GameDay @ JAWS-UG DE&I (November 24, 2025) Speaker : @kazzpapa3 / JAWS-UG 神戸

Slide 2

Slide 2 text

Biography { "Bio": { "Name": "ICHINO Kazuaki a.k.a. kazzpapa3", "Organization": "A certain AWS partner company", "Role": "Technical Support Engineer", "Favorite AWS Services": [ "AWS CLI", "AWS CloudTrail" ], "Less Favorite AWS Service (as a Support Engineer)": [ "AWS Billing (請求ロジックが難解すぎる)" ], "Personal Interest": "初音ミク", "Socials": { "Twitter/X": "@kazzpapa3", "LinkedIn": "https://www.linkedin.com/in/kazzpapa3/" } } }

Slide 3

Slide 3 text

みなさん、ポリシーの管理してますか @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 3 / 26

Slide 4

Slide 4 text

おおまかな背景や概要 ロールとしてリセラーのテクニカルサポートエンジニアをしています ただリセールアカウントの提供仕様を管理する部門でもあります 今日はこちらの話 いくつかある提供仕様の中で細かい差分が多い 大部分は共通するものの、 細かい差分によりポリシーが乱立する 共通する部分のアップデートをあちこちでする必要がある こういう点をちょっと困っている、という話 あと個人的には JSON は人類には早すぎる と思っています @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 4 / 26

Slide 5

Slide 5 text

実際に使っているものではないですが、差分の例 基本はケース起票してほしくないが、一部では OK みたいな ただしそれ以外はリセラーとして許容できないので共通で Deny … 5 / 26

Slide 6

Slide 6 text

実際に使っているものではないですが、差分の例 メンバーアカウントの root が弊社管理 or 顧客管理 6 / 26

Slide 7

Slide 7 text

前述のような差分が IAM ポリシーにも SCP にも存在している 管理アカウントを一部利用可能にする、Control Tower を使っている、 など条件に合わせて複数のポリシーが存在する ただし、基本的にリセラーとして許容できない部分は同じではあるの で、共通する部分は多い 基本的な部分で改定が必要な AWS アップデートがあった場合に、それ ぞれのポリシードキュメントの該当箇所を等しく直す必要がある @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 7 / 26

Slide 8

Slide 8 text

イメージとしては以下のような感じ Sid-01 Sid-01 Sid-02 Sid-02 Sid-03 Sid-03 Sid-04 Condition-01 Condition-01 Sid-04 Condition-01 Sid-05 Sid-05 Sid-06 Condition-02 Sid-06 Condition-02 Policy-A Policy-B 四角で表現しているのが Sid ごとや Condition ごとのひとかたまり 水色部分が共通する部分、色を変えている部分が双方で異なる部分 8 / 26

Slide 9

Slide 9 text

ちょっと模索してみた w/元 Amazon Q Developer for CLI @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 9 / 26

Slide 10

Slide 10 text

パーツ(モジュール)化できないか Sid ごとにパーツやモジュールのように切り出せないか 部品のように仕立てておいて、必要なものを必要なときに組み合わせて ポリシーを作るような感じで管理できないか @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 10 / 26

Slide 11

Slide 11 text

こんな感じのイメージ Sid-06 Sid-06 Policy-A Policy-B Sid-01 Sid-02 Sid-03 Condition-01 Sid-04 Condition-01 Sid-05 Condition-02 Sid-01 Sid-02 Sid-03 Sid-04 Condition-01 Sid-05 Sid-06 Condition-02 Sid-01 Sid-04 Condition-01 Sid-02 Sid-03 Sid-03 Sid-05 Sid-05 Condition-02 Condition-02 + + 11 / 26

Slide 12

Slide 12 text

やってみた @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 12 / 26

Slide 13

Slide 13 text

ポリシーは YAML で書く VersionDeclaration.yaml 念の為、Version 部分も部品として切り出し # IAM JSON policy elements の Version のみを切り出している # Version の改訂があった場合に見直しが必要 # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html Version: "2012-10-17" Statement: @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 13 / 26

Slide 14

Slide 14 text

ポリシーは YAML で書く BasicRestrictionAsResaler.yaml( support:* を Deny) - Sid: BasicRestrictionAsResaler Effect: Deny Action: - support:* # 処理の概要: AWS Support 利用の禁止 # 緩和の可否: サポートケース起票はしちゃダメ - supportplans:* # 処理の概要: サポートプランのすべての禁止 # 緩和の可否: サポートプランは変えちゃダメ - tax:* # 処理の概要: 税設定 のすべての禁止 # 緩和の可否: 日本国内の税設定にしないと処理として困っちゃう # すべてリソースに対する禁止 Resource: '*' 14 / 26

Slide 15

Slide 15 text

ポリシーは YAML で書く BasicRestrictionAsResalerForResold.yaml( support:* は許容) - Sid: BasicRestrictionAsResalerForResold Effect: Deny Action: - supportplans:* # 処理の概要: サポートプランのすべての禁止 # 緩和の可否: サポートプランは変えちゃダメ - tax:* # 処理の概要: 税設定 のすべての禁止 # 緩和の可否: 日本国内の税設定にしないと処理として困っちゃう # すべてリソースに対する禁止 Resource: '*' 15 / 26

Slide 16

Slide 16 text

YAML で書いたものを yq コマンドで寄せ集める BasicRestrictionAsResaler( support:* を Deny) を使う時 IAMPolicyRestrictionForCustomer.yaml、 RestrictionToAWSOrganizatioinsAsResaler.yaml は共通パーツと 仮定する yq eval-all ' select(fileIndex == 0) | .Statement = [ (load("IAMPolicyRestrictionForCustomer.yaml") | .[0]), (load("BasicRestrictionAsResaler.yaml") | .[0]), # ここだけ違う (load("RestrictionToAWSOrganizatioinsAsResaler.yaml") | .[0]) ] ' VersionDeclaration.yaml > foo.yaml @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 16 / 26

Slide 17

Slide 17 text

YAML で書いたものを yq コマンドで寄せ集める BasicRestrictionAsResalerForResold( support:* は許容) を使う時 IAMPolicyRestrictionForCustomer.yaml、 RestrictionToAWSOrganizatioinsAsResaler.yaml は共通パーツと 仮定する yq eval-all ' select(fileIndex == 0) | .Statement = [ (load("IAMPolicyRestrictionForCustomer.yaml") | .[0]), (load("BasicRestrictionAsResalerForResold.yaml") | .[0]), # ここだけ違う (load("RestrictionToAWSOrganizatioinsAsResaler.yaml") | .[0]) ] ' VersionDeclaration.yaml > bar.yaml @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 17 / 26

Slide 18

Slide 18 text

できたもの(この段階ではまだ YAML) # IAM JSON policy elements の Version のみを切り出している # Version の改訂があった場合に見直しが必要 # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_version.html Version: "2012-10-17" Statement: 〜中略〜 - Sid: BasicRestrictionAsResaler Effect: Deny Action: - support:* # 処理の概要: AWS Support 利用の禁止 # 緩和の可否: サポートケース起票はしちゃダメ - supportplans:* # 処理の概要: サポートプランのすべての禁止 # 緩和の可否: サポートプランは変えちゃダメ - tax:* # 処理の概要: 税設定 のすべての禁止 # 緩和の可否: 日本国内の税設定にしないと処理として困っちゃう # すべてリソースに対する禁止 Resource: '*' 〜以下略〜 18 / 26

Slide 19

Slide 19 text

処理の概要 yq コマンドでやっていることは以下のような感じ 1. eval-all: 複数ファイルを扱うモード 2. select(fileIndex == 0): 最初のファイル(VersionDeclaration.yaml)のみを選択 3. .Statement = [...]: Statementフィールドに配列を代入 - load("IAMPolicyRestrictionForCustomer.yaml") | .[0] - ファイルを読み込み、最初の要素を取得 - load("BasicRestrictionAsResaler.yaml") | .[0] - 同様に読み込み - load("RestrictionToAWSOrganizatioinsAsResaler.yaml") | .[0] - 同様に読み込み 4. VersionDeclaration.yaml: ベースとなるファイル(Version情報を含む) 5. > foo.yaml: 結果を出力 @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 19 / 26

Slide 20

Slide 20 text

この後 JSON 化 yq -o=json foo.yaml > foo.json cat foo.json { "Version": "2012-10-17", "Statement": [ 〜中略〜 { "Sid": "BasicRestrictionAsResaler", "Effect": "Deny", "Action": [ "support:*", "supportplans:*", "tax:*" ], "Resource": "*" }, 〜以下略〜 } 20 / 26

Slide 21

Slide 21 text

あとは妥当性を確認するなど、お好みで aws accessanalyzer validate-policy \ --policy-type IDENTITY_POLICY \ --policy-document file://foo.json { "findings": [] } accessanalyzer validate-policy サブコマンドの実行結果として、 findings が空の状態で返却されればポリシードキュメントとして問題が ない @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 21 / 26

Slide 22

Slide 22 text

やってみた感想 目論見どおり、パーツ化できそうな手応えは感じている 各パーツの改訂があったときに、修正しパーツを commit する 裏で GitHub Actions が動き JSON のポリシードキュメント化す る、などすれば良さそうかな?と思っている YAML にすることでコメントを記載できるようになった JSON のポリシードキュメントの場合「なぜ Deny」しているのかが わからず、Know Why が残しやすい副次的なメリットも生まれそう (やっぱり JSON は人類には早すぎたんだと思われる) @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 22 / 26

Slide 23

Slide 23 text

おわりに 「IaC を使いたくないけど」としたものの CloudFormation などを使 いたくないわけではない 4 桁を超える管理アカウントに対して、それぞれが内包するポリシーを 修正する 変更セットの実行の方がオーバーヘッドが大きそう、と現段 階では考えているだけ ポリシー名やロール名はほぼ変更しない、かつ、存在していない状態 はないと断定できるので、一括で書き換えるスクリプトを流す方が良 い、という判断です もっといいやり方があるんじゃない、などお話できたらうれしい です @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 23 / 26

Slide 24

Slide 24 text

ちょっと告知 @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 24 / 26

Slide 25

Slide 25 text

次回、IoT 専門支部とのコラボ! 12月12日(金)19:30〜 @三宮 目黒と繋いで 2 拠点開催 +オンラインも! JAWS-UG 大阪とかぶったのが悔やまれるー ぜひ神戸にもお越しくださいー @kazzpapa3 / #jawsugdei #jawsug #ashibinaa 25 / 26

Slide 26

Slide 26 text

Share your lessons. Thank you.