見出し画像

【AWS】Fn::Sub とポリシー変数を使用して IAM ポリシーを定義する。【CloudFormation】

こんばんは。横浜事業所の えんどぅ です。
業務で IAM リソースを作成する機会があり、せっかくなので CloudFormation を利用して作成しようとしたのですが、まんまと躓きました…。
今回は、CloudFormation テンプレートで Fn::Sub とポリシー変数を使用して IAM ポリシーを定義する方法について確認しましたので、共有します。

AWS CloudFormation とは?


AWS CloudFormation とは「テンプレート」と呼ばれる JSON または YAML 形式のテキストファイルに記述した AWS リソースの構築や設定を自動で行ってくれる AWS サービスです。

構築したいリソースをテンプレートとして 1 度記述しておけば、リソースの複製・再構築・管理等が容易になります。
いちいちマネジメントコンソール上で一つ一つ設定を入力する必要なく、CloudFormation の API を叩くだけで複数のリソースをまとめて制御できます。

例えば、50 の IAM ポリシーを作成するシーンを考えてみます。
マネジメントコンソール上で IAM ポリシーの設定値を一つ一つ入力して、作成して、IAM ポリシー名を間違えたらほぼ全く同じ設定値を再度一つ一つ入力して、再作成して、それを 50 回繰り返して…。

やってられっかぁぁぁぁ!!と叫んでしまいそうです。

CloudFormation テンプレートを利用すれば、共通部分はコピー & ペーストして繰り返し作業を削減できたり、設定変更時は対象項目だけ変更すれば良くなったりと、作業効率をかなり向上できます。

YAML

...
Resources:
  Policy1:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'Policy1'
      PolicyDocument:
        Version: '2012-10-17'
...
  Policy2:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'Policy2'
      PolicyDocument:
        Version: '2012-10-17'
...

参考: AWS CloudFormation の概要

Fn::Sub とは?


Fn::Sub とは、CloudFormation テンプレートに組み込まれている関数の 1 つです。
文字列中に設定した変数を、テンプレート評価時に指定した値に置換します。

例えば複数の AWS アカウントで利用される可能性のある、テンプレートを作成するシーンを考えてみます。
テンプレート内で特定の AWS アカウント ID を記述すると、場合によっては他の AWS アカウントで同じテンプレートを使用する際にエラーが発生してしまいます。
そのため同様の AWS リソースを構築したい場合でも、AWS アカウント毎にテンプレートを作成する必要があります。

YAML

...
Resources:
  Policy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'DemoPolicyVariables'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Action: 'iam:ChangePassword'
            Resource: 'arn:aws:iam::123456789012:user/user1'    # AWS アカウント ID だけ違う。 
...

YAML

...
Resources:
  Policy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'DemoPolicyVariables'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Action: 'iam:ChangePassword'
            Resource: 'arn:aws:iam::234567890123:user/user1'    # AWS アカウント ID だけ違う。
...


やってられっかぁぁぁぁ!!!と絶叫してしまいそうです。

Fn::Sub を使用して AWS アカウント ID を指定する部分を変数化する事で、テンプレートを使用する AWS アカウント ID に置換されて評価されるため、1 つのテンプレートを複数の AWS アカウントで使い回す事ができます。

YAML

...
Resources:
  Policy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'DemoPolicyVariables'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Action: 'iam:ChangePassword'
            Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:user/user1'    # ${AWS::AccountId} 部分が AWS アカウント ID に置換される。
...

組み込み関数には、Fn::Sub 以外にも種類があり、それぞれ使用方法が異なります。
詳細は公式ドキュメントを参照してください。

ポリシー変数とは?


ポリシー変数とは、IAM ポリシーに設定できる「プレースホルダー」です。
特定の値を事前に設定しておくのではなく、ポリシーの評価時に動的に値を設定する事ができます。

例えば、100 の IAM ユーザーに「自分のパスワードのみを変更できる」という IAM ポリシーをアタッチするシーンを考えてみます。
ポリシー変数を使用しない場合、各 IAM ユーザー用の IAM ポリシーを作成する必要があります。

JSON

...
  "Effect": "Allow",
  "Action": "iam:ChangePassword",
  "Resource": "arn:aws:iam::123456789012:user/user1"    ← IAM ユーザー名だけ違う。
...

JSON

...
  "Effect": "Allow",
  "Action": "iam:ChangePassword",
  "Resource": "arn:aws:iam::123456789012:user/user2"    ← IAM ユーザー名だけ違う。
...

やってられっかぁぁぁぁ!!!!と発狂してしまいそうです。

IAM ユーザー名を表すポリシー変数を使用すれば、ポリシー変数部分が IAM ポリシーをアタッチした IAM ユーザー名に置換されて評価されるため、1 つの IAM ポリシーを複数の IAM ユーザーで使い回す事ができます。

JSON

...
  "Effect": "Allow",
  "Action": "iam:ChangePassword",
  "Resource": "arn:aws:iam::123456789012:user/${aws:username}"    ← ${aws:username} 部分が IAM ユーザー名に置換される。
...

ポリシー変数には、 IAM ユーザー名を表すもの以外にも種類があります。
詳細は公式ドキュメントを参照してください。

テンプレートで IAM ポリシーを定義して作成する


まずは、 CloudFormation テンプレートで Fn::Sub とポリシー変数を使用して IAM ポリシーを定義します。
IAM ポリシー定義の構文は公式リファレンスを参照してください。

YAML

AWSTemplateFormatVersion: '2010-09-09'
Description: 'IAM resources.'
Resources:
  Policy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: 'DemoPolicyVariables'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: 'Allow'
            Action: 'iam:ChangePassword'
            Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:user/${!aws:username}'    # ココ

CloudFormation の CreateStack API を叩きます。

無事、ポリシー変数を使用した IAM ポリシーを作成できました!

ミソは「${!aws:username}」の「${」の直後にある「!」です!
この記述により、CloudFormation 実行時に「${!...}」の部分を「${...}」として設定してくれます。
公式ドキュメントにもちゃんと記載がありました。

Fn::Sub
USD 記号と中括弧 (${}) をそのまま書き込むには、最初の中括弧の後に感嘆符 (!) を追加します (${!Literal} など)。CloudFormation は、このテキストを ${Literal} として解決します。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html#w4ab1c33c28c64b7

ちなみに、この「!」が無いとエラーになりますので、気をつけましょう。

Shell

An error occurred (ValidationError) when calling the CreateStack operation: Template format error: Unresolved resource dependencies [aws:username] in the Resources block of the template

まとめ

今回は、CloudFormation テンプレートで Fn::Sub とポリシー変数を使用して IAM ポリシーを定義する方法について、確認しました。
CloudFormation を利用すれば AWS リソースの管理がとても楽になるので、こうした細かな仕様も少しずつ把握して、効果的に活用していきましょう〜。

ALHについて知る



↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓


↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓


↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓




みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!