[AWS SSO版] Session Manager で特定の EC2 のみアクセスできるよう制限する

前回はIAM、今回はSSO
2022.02.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ちゃだいん(@chazuke4649)です。

前回に続き、今度は AWS SSO で、Session Manager で特定の EC2 のみアクセスできるよう制限してみます。

前回はこちらをご覧ください。

Session Manager で特定の EC2 のみアクセスできるよう制限する [ AWS IAM 編 ] | DevelopersIO

前提

  • AdministratorAccess の権限を持つAWS SSOユーザーが対象のEC2インスタンスに対して、Session Managerをすでに使用できる状態(=Session Managerが利用可能な設定が完了している状態)とします。
  • 制限対象はすでに作成済みのAWS SSOユーザー
  • デフォルトのIAMポリシーとして、アクセス権限セットに ReadOnlyAccessを付与し、参照はできる状態とする
  • 設定は管理者ユーザーが全て行う
  • Organizationsによるマルチアカウント環境で、実際にEC2が稼働しておりSession Managerを使うのはメンバーアカウント上
  • AWS SSOのIDストアは外部のIdPを使用せず、AWS SSOのIDストアを使用する

基本的には前回同様、以下公式ドキュメントのIAMポリシーサンプルを参考にします。

Session Manager の追加サンプル IAM ポリシー - AWS Systems Manager

また、AWS SSOにてABAC(属性ベースのアクセスコントロール)も行うので、以下配下のドキュメントも参考にします。

属性ベースのアクセス制御-AWSシングルサインオン

先にテスト結果

前回記事をご覧ください。

1.タグを使用するパターン(定数・固定)

例 2: タグに基づいてアクセスを制限 - AWS Systems Manager

上記公式ドキュメントのサンプルベースであり、前回でいう2.です。 ポリシーに記載したタグがリソースにある場合のみ許可します。

ssm:StartSession だけであればABACの設定は不要ですが、ssm:TerminateSession にてAWS SSOユーザーのユーザー名を連携させて、終了できるセッションIDを制限したいので、ABACの設定も行います。

アクセス制御の属性を有効にして設定します-AWSシングルサインオン

手順

  • AWS SSOでABACを有効化する
  • ABAC設定にて、指定のユーザー属性を追加する
  • 以下インラインポリシーを対象のAWS SSOユーザーが使用するアクセス権限セットにアタッチする
  • 対象のメンバーアカウントにIAMロールのプロビジョニングを行う(すでに作成済みの場合は更新する)

まず、AWS SSOでAttributes for access control(≒ABAC)を有効化します。

すると、ABACで使用するユーザー属性を入力できるようになるので、そこで以下の通り入力します。

  • Key: ssousername ※任意のキーでOK
  • Value: ${path:userName}

Value側は以下を参考に入力します。今回のUsernameは下図の通り候補に出てきました。 属性マッピング-AWSシングルサインオン

※ちなみに、今回は元々ユーザー属性に存在する username を使用するので、SSOユーザー側に新しくユーザー属性を追加する必要はありません。

そして、以下ポリシーをインラインポリシーとしてアクセス権限セットにアタッチし、対象のメンバーアカウントにプロビジョニングすればOKです。

{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Action": [
              "ssm:StartSession"
          ],
          "Resource": [
              "arn:aws:ec2:*:*:instance/*"
          ],
          "Condition": {
              "StringEquals": {
                  "ssm:ResourceTag/Project": [
                      "Apple"
                  ]
              }
          }
      },
      {
          "Effect": "Allow",
          "Action": [
              "ssm:TerminateSession",
              "ssm:ResumeSession"
          ],
          "Resource": [
            "arn:aws:ssm:*:*:session/$${aws:PrincipalTag/ssousername}-*"
          ]
      }
  ]
}

補足

  • Project: apple タグがアタッチされたインスタンスしかセッションを開始できない
  • Prefixが自分のユーザー名の既存セッションしか終了・再開できない

ポイントとしては、ユーザー属性 usernamessousername というタグキーでプリンシパルタグとしてセッション情報に保存し、アクション実行時に上記ハイライト箇所の条件に使用されるようになる点です。

プリンシパルタグを渡せているかどうかの確認としては、ログイン先アカウントのCloudTrailのイベント履歴にてEvent nameをAssumeRoleWithSAML で検索します。すると、AWS SSO経由でスイッチロールした際のAPIログの requestParametersの中にプリンシパルタグが確認できます。

...
    "requestParameters": {
        "sAMLAssertionID": "_4623f98d-8afb-4be6-93bc-9fc2ac8c1ba0",
        "roleSessionName": "TestUserB",
        "principalTags": {
            "ssousername": "TestUserB" ## プリンシパルタグをセッションタグとして渡せている状態
        },
...

AWS SSOのABACについて詳しくは以下公式ブログをどうぞ。

新機能 — AWS Single Sign-On による属性ベースのアクセスコントロール | Amazon Web Services ブログ

また、セッションタグについてはこちら。

AWSSTSでのセッションタグの受け渡し-AWSIdentity and Access Management

2.タグを使用するパターン(変数・ABAC)

ssm:StartSession の条件にもABACで渡される動的なプリンシパルタグを使用する柔軟なパターンです。今回は AWS SSOユーザーの属性にある cost center を使用してみます。

手順

  • AWS SSOでABACを有効化する
  • AWS SSOユーザー画面にてユーザー属性の値を追加する
  • ABAC設定にて、指定のユーザー属性を追加する
  • 以下インラインポリシーを対象のAWS SSOユーザーが使用するアクセス権限セットにアタッチする
  • 対象のメンバーアカウントにIAMロールのプロビジョニングを行う(すでに作成済みの場合は更新する)

増える手順としては、太字の項目のみとなります。

下図の通り、SSOユーザー画面にて、ユーザー属性の Cost centerOrange` と追加します。

ABAC設定画面にて、新たに渡す属性として以下を追加します。

  • Key: costcenter
  • Value: ${path:enterprise.costCenter}

そして、以下ポリシーをインラインポリシーとしてアクセス権限セットにアタッチし、対象のメンバーアカウントにプロビジョニングします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:StartSession"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/costcenter": "${aws:PrincipalTag/costcenter}"
                }
            },
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ec2:*:*:instance/*"
            ]
        },
        {
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:PrincipalTag/ssousername}-*"
            ]
        }
    ]
}

対象のメンバーアカウント側に管理者権限でログインし、EC2インスタンスのタグに以下を付与します。

  • Key: costcenter
  • Value: Orange

※画像では orange ですが、これでは失敗しました。以下の通りEC2はタグの大文字・小文字が区別されるので注意です。

タグのキーと値は大文字と小文字が区別されます。 引用元)Amazon EC2 リソースのタグ付け - Amazon Elastic Compute Cloud

補足

  • SSOユーザー属性の costcenter の値と、ECインスタンスの costcenter タグの値が一致したインスタンスしかセッションを開始できない(ABAC)
  • Prefixが自分のユーザー名の既存セッションしか終了・再開できない
  • JSONハイライト箇所が ssm:ResorceTag から aws:ResourceTag に変更している点が要注意

AWS SSO デフォルトのIDストアの属性項目は限定的ではありますが、今回の方法で柔軟なABACが実現可能です。

おまけ

costcenter 属性以外も試してみました。以下は usertype を使用するパターンです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:StartSession"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/usertype": "${aws:PrincipalTag/usertype}"
                }
            },
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ec2:*:*:instance/*"
            ]
        },
        {
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:PrincipalTag/ssousername}-*"
            ]
        }
    ]
}

終わりに

それぞれ制限方法には一長一短あります。要件を考慮し最適な手法を選択していきましょう。

それではこの辺で。ちゃだいん(@chazuke4649)でした。