yy16ki’s diary


スポンサードリンク

AWS CLIでAssumeRoleとPassRoleする

AWS IAMにおける,AssumeRole・PassRoleの利用についての備忘録的な記事になります.

AWS IAM

IAMは,各種リソースへのアクセスを安全にコントロールするために使用されるサービスです.

AssumeRole

AssumeRole は,AWSのリソースが,IAMロールを引き受けることを表します.

PassRole

PassRole は、 AWSのリソースに IAMロールを渡す(パスする)ことを表します.

今回やりたいこと

本記事では,下図の内容をCLIで実施しながら,AssumeRole・PassRoleの挙動を確認します.

やりたいこと

①:開発用のIAMユーザー(dev-user)を作成し検証
②:dev-userがEC2を作成できるような一時権限を取得
③:dev-userでEC2を作成し,EC2にS3読み取りの権限を付与する

②では,dev-userがIAM ロールに設定された権限(EC2作成権限)を引き受けます.
③では,dev-userがEC2にIAMロールに設定された権限(S3読み取り権限)を付与します.(同時にEC2は,S3読み取り権限を引き受けることになります.)

AssumeRole

作業用のIAMユーザーを作成

まずは管理者権限を持つユーザーにて,今回の作業用IAMユーザーを作成します.
ユーザー名はdev-userとします.現時点では何の権限もありません.

#ユーザーの作成
aws iam create-user \
    --user-name dev-user \
    --path "/blog/dev/"

#Arnの確認
aws iam list-users \
  --path-prefix "/blog/dev/" \
  --query 'Users[].Arn' \
  --output text

IAMロールを作成

dev-userが引き受けることになる,IAMロール(EC2作成権限)を作成します.

TRUST_FILE='./trust-ec2-create-role.json'
cat << EOF > ${TRUST_FILE}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXX:user/blog/dev/dev-user"
      }
    }
  ]
}
EOF

#Roleの作成
aws iam create-role \
  --role-name ec2-create-role \
  --assume-role-policy-document file://trust-ec2-create-role.json \
  --path "/blog/dev/"

信頼関係のActionに,AssumeRoleが出てきます.
PrincipalにIAMユーザー(dev-user)のArnを指定することで,dev-userがこのIAMロールを引き受けることができるようになります.
※ユーザー名で指定する方法の場合、上記のように信頼関係の設定のみで,ユーザーにもIAMロールを引き受ける権限(sts:AssumeRole)が許可されます.アカウントの場合,ユーザーのポリシーの設定も必要となります.

dev.classmethod.jp

上記で作成したIAMロールにアタッチするポリシーを作成します.EC2を作成できればよいので,ec2:RunInstancesを許可します.
また,後ほどEC2にロールを付与する(PassRole)ために,事前にec2:AssociateIamInstanceProfile ec2:ReplaceIamInstanceProfileAssociationも許可しておきます.

POLICY_FILE='./policy-ec2-create.json'
cat << EOF > ${POLICY_FILE}
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "",
          "Effect": "Allow",
          "Action": [
              "ec2:RunInstances",
              "ec2:AssociateIamInstanceProfile",
              "ec2:ReplaceIamInstanceProfileAssociation"
            ],
          "Resource": "*"
      }
  ]
}
EOF

#policyを作成
aws iam create-policy \
    --policy-name policy-ec2-create \
    --policy-document file://policy-ec2-create.json

下記のコマンドで,ロールにポリシーをアタッチします.

#ポリシーのArnを取得
POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \
    --output text) && echo ${POLICY_ARN}

#ロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ec2-create-role \
    --policy-arn ${POLICY_ARN}

これで,dev-userはEC2を作成する権限を引き受ける準備ができました. 以降,dev-userで作業するために,dev-userのアクセスキーを発行しておきます.

aws iam create-access-key --user-name dev-user

AssumeRoleの実施

dev-userに切り替え,何もしていない状態で,EC2インスタンスを立ち上げる下記のコマンドを実行してみます.

aws ec2 run-instances \
   --image-id ami-0fe23c115c3ba9bac \
   --count 1 \
   --instance-type t2.micro \
   --associate-public-ip-address

現時点では,権限がないため,エラーとなります.

An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation.

EC2作成用のロールを引き受けます.(AssumeRoleします)
aws stsコマンドを使用し,対象のIAMロールのArnにEC2作成用のロールArnを指定します.

 aws sts assume-role \
  --role-arn "arn:aws:iam::XXXXX:role/blog/dev/ec2-create-role" \
  --role-session-name temp-session \
  --duration-second 900  

実行すると,下記のように一時的なクレデンシャルを取得できます.

{
    "Credentials": {
        "AccessKeyId": "XXX",
        "SecretAccessKey": "XXX",
        "SessionToken": "XXX",
        "Expiration": "2022-07-02T08:41:21+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXXXXXX:temp-session",
        "Arn": "arn:aws:sts::XXXXX:assumed-role/ec2-create-role/temp-session"
    }
}

環境変数AWS_ACCESS_KEYAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENを上記で取得したものに置き換えることで一時的な認証情報で作業します.
変更が適用されているかどうかは,下記のコマンドで作業中のプロファイルすることで判断できます.

aws sts get-caller-identity
{
    "UserId": "XXXXXXXXXXXXXXX",
    "Account": "XXXXX",
    "Arn": "arn:aws:iam::XXXXX:user/dev-user"
}

この状態で,上記のaws ec2 run-instancesを実行するとEC2インスタンスを起動することができます.

PassRole

作成したEC2インスタンスには,他のリソースを操作する権限はないので,EC2からaws s3 lsとしても権限不足によるエラーとなります.
EC2からS3バケットを読み取ることができるように,dev-userからEC2にIAMロールを付与します.
dev-userで上記のIAMロールをAssumeRoleした状態で,下記のコマンドを実行します.

aws ec2 associate-iam-instance-profile \
     --instance-id i-03f95fdd292ae52b4 \
     --iam-instance-profile Name=s3readInstanceProfile

コマンドでは,作成済みの(※作成手順は記事最後に記載)インスタンスプロファイルを,先程作成したEC2に紐づけていますが,このコマンドの実行結果はエラーになります.dev-userには,EC2インスタンスにIAMロールを渡す(PassRoleする)権限がないためです.
※この場合,厳密にはインスタンスプロファイルに紐づいたIAMロールを渡そうとしています.

公式ドキュメントを確認しておきます.
下記の通り,EC2にIAMロールを付与するには,PassRoleが必要なことがわかります.
dev-userが引き受けた,EC2作成用のIAMロールに,ec2:RunInstances以外の許可を与えたのはこのためです.

IAM ロールを持つインスタンスの起動、および既存インスタンスへの IAM ロールのアタッチと置換を許可するには、以下の API アクション を実行するためのアクセス許可を付与します。

  • iam:PassRole
  • ec2:AssociateIamInstanceProfile
  • ec2:ReplaceIamInstanceProfileAssociation

docs.aws.amazon.com

PassRole可能なIAMロールを作成

この作業は管理者権限を持つIAMユーザーで実施しています.
EC2作成用のIAMロールのポリシーを変更し,PassRole付きのポリシーとします.ActionPassRoleのResourceに,S3への読み取り権を持つIAMロール(※事前作成済み.作成方法は記事先後に記載.)を指定することで,このポリシーを付与されたリソースは,他のリソースにS3アクセスの権限をPassできるようになります.

TRUST_POLICY_FILE='./policy-ec2-create.json'
cat << EOF > ${TRUST_POLICY_FILE}
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "",
          "Effect": "Allow",
          "Action": [
              "ec2:RunInstances",
              "ec2:AssociateIamInstanceProfile",
              "ec2:ReplaceIamInstanceProfileAssociation",
            ],
          "Resource": "*"
      },
      {
          "Effect": "Allow",
          "Action": "iam:PassRole",
          "Resource":  "arn:aws:iam::XXXXX:role/s3read"
      }
  ]
}
EOF

#先に作成したポリシーを作り直すために,一旦IAMロールからdetach
POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \
    --output text) && echo ${POLICY_ARN}

aws iam detach-role-policy \
  --role-name ec2-create-role \
  --policy-arn ${POLICY_ARN}

#PassRoleの権限がないポリシーを削除
aws iam delete-policy --policy-arn ${POLICY_ARN}

#PassRoleの権限があるポリシーを作成
aws iam create-policy \
    --policy-name policy-ec2-create \
    --policy-document file://policy-ec2-create.json

#新しく作成したポリシーのArnを取得
POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \
    --output text) && echo ${POLICY_ARN}

#ec2 create roleにPassRole可能なポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ec2-create-role \
    --policy-arn ${POLICY_ARN}

PassRoleを実施

ここから,dev-userで作業します.
dev-userにて,PassRoleの権限を付与したEC2作成用のIAMロールを引き受けます.

#dev-userで実施
aws sts assume-role \
  --role-arn "arn:aws:iam::XXXXX:role/blog/dev/ec2-create-role" \
  --role-session-name temp-session \
  --duration-second 900

作成済みのEC2に,先程のIAMロールでは,エラーとなった下記のコマンドを実行し,S3読み取り権限を持つインスタンスプロファイルを紐づけます.

aws ec2 associate-iam-instance-profile \
     --instance-id i-03f95fdd292ae52b4 \
     --iam-instance-profile Name=s3readInstanceProfile
{
    "IamInstanceProfileAssociation": {
        "AssociationId": "iip-assoc-01c1886db23b64937",
        "InstanceId": "i-0d8012d6a3f4abf80",
        "IamInstanceProfile": {
            "Arn": "arn:aws:iam::XXXXX:instance-profile/s3readInstanceProfile",
            "Id": "XXXXXXXXXXX"
        },
        "State": "associating"
    }
}

PassRoleの権限を付与したことで,問題無く実行できるようになります.
EC2からもS3の読み取りができるようになります.

まとめ

個人的に,AssumeRoleと特にPassRoleのイメージがあまりわかなかったのですが,CLIを通して細かく設定していくことで,基本的でありながらセキュリティの観点では,理解必須の機能であることを再認識できました.今回は以上になります.

(※)S3読み取り権限を持つインスタンスプロファイルの作成

EC2に付与するS3読み取り可能なIAMロールの作成手順です.
※この作業は管理者権限を持つユーザーで実行しています.

TRUST_POLICY_FILE='./ec2-role-trust-policy.json'
cat << EOF > ${TRUST_POLICY_FILE}
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": { "Service": "ec2.amazonaws.com"},
        "Action": "sts:AssumeRole"
      }
    ]
  }
EOF

#IAMロールの作成
aws iam create-role \
    --role-name s3read \
    --assume-role-policy-document file://ec2-role-trust-policy.json

#IAMポリシーのArnを取得
POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`AmazonS3ReadOnlyAccess`)].Arn' \
    --output text) && echo ${POLICY_ARN}

#IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name s3read \
    --policy-arn ${POLICY_ARN}

インスタンスプロファイルにIAMロールを紐づけます.

#インスタンスプロファイルを作成
aws iam create-instance-profile \
    --instance-profile-name s3readInstanceProfile

#インスタンスプロファイルとIAMロールを紐づけ
aws iam add-role-to-instance-profile \
    --role-name s3read \
    --instance-profile-name s3readInstanceProfile

スポンサードリンク