AWS SSOのIAM RoleからAssume RoleできるIAM Roleを作成する

2021.07.31

AWS SSOを使う時、ユーザーは各アカウントにできたIAM RoleにAssume Roleすることで各アカウントで操作ができるようになります。

sso-switchrole-double-1 このあたりについての詳細は以下を御覧ください。

AWS SSOを図解してみた | DevelopersIO

さて今回は、AWS SSOユーザーがAssume RoleするためのIAM Role、この特定のRoleからさらにAssume Roleできる別アカウントのIAM Roleを作成したいと思います。

sso-switchrole-double-2

以下は、このRoleの信頼ポリシー(=Assume Roleできるエンティティを定義するポリシー)をどのように設定するか、という話です。

ガバガバで設定する

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::(AccountAのID):root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

上記のようにPrincipal句で(AccountID):rootと設定すると、そのアカウント内の全てのIAMエンティティからのAssume Roleが許可されます。AWS SSOのロールもその対象内ですのでAssume Roleが可能です。

が、今回許可したいのはAWS SSOの特定のロール一つだけです。他の全てエンティティにもAssume Roleを許可してしまうのはセキュリティリスクがあります。というわけで許可対象を絞る方法を以降の段で模索します。

失敗例: Principal句で絞る

まず最初に考えられる方法はPrincipal句の設定をもっと絞る方法です。ですが先にお伝えすると、この方法は今回はうまくいきませんでした。

詳細を説明します。前述の通り、AWS SSOの特定のロールのみをAssume Roleの対象としたいです。ですので、そのようなARNをPrincipal句に書けば良いです。RoleのARNは以下要素で構成されます。

  • arn:aws:iam::(AccountAのID):role/(パス(あれば))(ロール名)

SSOで作成されるロールには/aws-reserved/sso.amazonaws.com/(リージョンID)/というパスが設定されます。なお、SSOを米国東部 (バージニア北部)=us-east-1で設定している場合は(リージョンID)/は不要です。

ARNを固定できない

上記ARN構成要素のうち、今回の場合ロール名が固定できません。なぜかというとAWS SSOのアクセス権限セットの割り当てで作成されるIAM Roleの名前はAWSReservedSSO_(アクセス権限セット名)_(英字小文字と数字の組み合わせのランダムな文字列)となります。例えばアクセス権限セットの名前がAdministratorAccessなのであれば、作成されるIAM Roleの名前はAWSReservedSSO_AdministratorAccess_dcd926ba31da45ecなどになります。このランダムな文字列込みのARNを書いてしまえば良いのですが、今回はIaCで汎用的に対象のRoleを作成したかったので、アカウント毎に異なる値を記述するのは避けたかったです。

固定できないならワイルドカードを使えばいいじゃない

上記理由で今回の場合ARNを固定することができません。ではワイルドカードを使ってもう少し曖昧に指定すれば?と考えました。具体的にはPrincipal句に以下のように書くということです。 

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::(AccountAのID):role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_AdministratorAccess_*"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ですがこれはエラーになります。どうやらPrincipal句でIAM RoleのARNの一部にワイルドカードを使うことはできないようです。

これはなぜかというと、Principal句でIAM RoleのARNを書くと、そのARNはポリシーを保存するときにロールの一意のプリンシパル ID に変換されるからです。故にワイルドカードのような曖昧な書き方はできず、かつ存在しないRoleのARNを書くこともできません。これはロール削除して再作成することにより、誰かがそのロールの特権をエスカレートするリスクを緩和することを目的としています。

この点(=Principal句でIAM RoleのARNの一部にワイルドカードを使うことはできない)について公式のソースを見つけることができませんでした。が、IAMユーザーについては以下に記載されているので、Roleに関してもそうだと判断しました。

成功例: Condition句で絞る

Principal句で絞り込むのは無理そうでしたので諦めます。代わりにCondition句での実現を試みました。aws:PrincipalArnというグローバル条件コンテキストキーを発見したのでこちらを使うことで要件を実現できました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::(AccountAのID):root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnLike": {
          "aws:PrincipalArn": "arn:aws:iam::(AccountAのID):role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_AdministratorAccess_*"
        }
      }
    }
  ]
}

まとめ

AWS SSOのロールからのみAssume RoleできるIAM Roleの信頼ポリシーの書き方についてレポートしました。Principal句でIAM UserやIAM RoleのARNを指定する際にワイルドカードを使うことができないことがわかりました。ワイルドカードを使いたい場合は、Principal句は (AccountID):rootと広く設定した上で、Condition句でaws:PrincipalArnを使うことで実現できることがわかりました。