LoginSignup
1
1

【データ基盤構築/AWS】IAMのPassRoleで権限を渡すこととロールにポリシーアタッチして権限を渡すことの違い

Posted at

今回の課題

以下の前回の記事の機能を実装する際に、権限まわりでエラーが発生してしまったので解決した方法を記録する。
また、一応は解決できたが、解決できた理由がイマイチ理解できていなかったため、色々調査することにした。

発生した問題を解決する

前提

使用している権限

  • Lambdaにはpractice-Lambda-RDStoS3-role-idais11pというロールで権限が渡されている。
    • S3にアクセスや操作をできるようにするための権限(s3:GetObjects3:DeleteObjectなど)を持ったポリシーをアタッチしている。
    • こちらのロールの信頼されたエンティティは以下となっている。(Lambda実行時にAssumeRoleによって、ロールが所持しているポリシーの権限をLambdaが使える)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

使用しているLambdaのコード

前回の記事から引用した、下記のLambdaコードを実行する。

import json
import boto3
import time
from botocore.client import ClientError
from datetime import datetime

rds = boto3.client('rds')
s3 = boto3.resource('s3')

S3_BUCKET_NAME="s3bucket" # 出力先のS3バケット名
S3_OBJECT_NAME="s3object" #出力先のS3オブジェクト
IAM_ROLE_ARN="arn:aws:iam::************:role/s3OperationsRole" # S3にエクスポートする際に使用するロールのARN
KMS_KEY_ID="arn:aws:kms:ap-northeast-1:************:key/31b0e6b4-54a8-4b32-97c3-98e3ff4412be" # 作成したKMSキーのARN


# create_snapshot()を呼び出せば、[prefix-YYYY-mm-dd-HH-MM]というスナップショットの作成が始まるように定義    
def create_snapshot(prefix, instanceid):
    newsnapshotid = "-".join([prefix, datetime.now().strftime("%Y-%m-%d-%H-%M")])
    rds.create_db_snapshot(
        DBSnapshotIdentifier=newsnapshotid,
        DBInstanceIdentifier=instanceid
    )
    
# check_snapshot_created()を呼び出すと、RDSのStatusが「available」になるまで待機する関数
# lambda_handler()にて、create_snapshot()と同時に呼び出すことで、スナップショットを作成可能な状態まで待ってスナップショット作成の処理が走るように定義している。
def check_snapshot_created(prefix, instanceid):
    snapshots = rds.describe_db_snapshots(DBInstanceIdentifier=instanceid)['DBSnapshots']
    # RDSのStatusが「available」でなければ、20秒間待機して、check_snapshot_createdをもう一度呼び出すということを繰り返す。
    for snapshot in snapshots:
        if snapshot['Status'] != "available":
            time.sleep(20)
            check_snapshot_created(prefix, instanceid)
            
def export_snapshot(prefix, instanceid):
    # rdsのスナップショットの情報を`snapshots`に入れる
    snapshots = rds.describe_db_snapshots(DBInstanceIdentifier=instanceid, SnapshotType='manual')['DBSnapshots']
    # snapshotが新しい順にソートして、`snapshots`に入れる
    snapshots = sorted(snapshots, key=lambda x: x['SnapshotCreateTime'], reverse=True)
    # 一番新しいスナップショットを`snapshot`に入れる
    snapshot = snapshots[0]
    newsnapshotid = "-".join([prefix, datetime.now().strftime("%Y-%m-%d-%H-%M")])

    # 一番新しいスナップショットをS3にエクスポートする
    response = rds.start_export_task(
        ExportTaskIdentifier=newsnapshotid,
        SourceArn=snapshot['DBSnapshotArn'],
        S3BucketName=S3_BUCKET_NAME,
        S3Prefix=S3_OBJECT_NAME,
        IamRoleArn=IAM_ROLE_ARN,
        KmsKeyId=KMS_KEY_ID,
        )
    return(response)
    
            
def lambda_handler(event, context):
    bucket = S3.Bucket("s3bucket")
    snapshot_prefix = 'mysnapshot'
    instance = 's3object'

    # スナップショットを作成
    create_snapshot(snapshot_prefix, instance)
    # スナップショットが作成可能な状態になるまで待機
    check_snapshot_created(snapshot_prefix, instance)
    
    # s3のオブジェクトを削除
    bucket.objects.filter(Prefix=S3_OBJECT_NAME).delete()
    export_snapshot(snapshot_prefix, instance)

発生したエラーの内容

Lambdaを実行すると、以下のエラーが発生してしまう。

"errorMessage": "An error occurred (AccessDenied) when calling the StartExportTask operation: User: arn:aws:sts::************:assumed-role/practice-Lambda-RDStoS3-role-idais11p/practice-lambda-PracticeLambda-R5dbYPSxzWpG
is not authorized to perform: iam:PassRole on resource: arn:aws:iam::334616138474:role/yamaguchi-practice-s3OperationsRole because no identity-based policy allows the iam:PassRole action",

StartExportTaskを実行しようとしたが、
arn:aws:iam::334616138474:role/yamaguchi-practice-s3OperationsRoleiam:PassRole権限がないため、StartExportTaskが実行できなかったとのこと。

解決策

エラーに記載されている通り、
practice-Lambda-RDStoS3-role-idais11pロールに、
以下の権限を付与したポリシーを持たせることで、エラーを解決することができた。

※以下のarn:aws:iam::************:role/practice-s3OperationsRoleというのは、S3を操作するための権限(s3:GetObjects3:DeleteObject)のポリシーを持たせたロールのこと。

{
    "Version": "2012-10-17",
    "Statement": [
            {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::************:role/practice-s3OperationsRole"
            }
    ]
}

以上で、発生した問題を無事解決することができたのだが、
どうして解決することができたのかしっかりできなかった...。

本題:なぜ解決できたのか理解する。

どうして上記のような対応で解決できたのか腑に落ちなかったため調査してみた。

理解できなかった点

以下の点が、理由が理解できなかった。

前提に記載の通り、LambdaからS3へのアクセスや操作をするための権限はLambdaに対して、既に付与しているにも関わらず、
StartExportTaskを実行するには、iam:PassRoleでS3にアクセスするための権限をpractice-Lambda-RDStoS3-role-idais11pロールに対してパスするように
というエラーが発生した。

知識の勉強

まずは基礎知識をしっかり学んだ。

sts:AssumeRoleについて

IAMロールを引き受けるためのアクションのこと。

信頼されたエンティティにてAssumeRoleを使うことで、
Resourceに定義しているAWSサービス実行時に、ロールにアタッチしてあるポリシーの権限を一時的に引き受けることができるようになる。

例えば、この記事の一番上に記載の信頼されたエンティティでいうと、
上記の信頼されたエンティティが定義されたロールが所持しているポリシーの権限がLambdaを実行するときに、使用することができるようになるイメージ。

iam:PassRoleについて

AWSリソースにIAMロールをパスして、IAMロールの使用を許可する権限。

AWSリソースは、他のAWSサービスと連携するためにIAMロールを必要とする。
iam:PassRole権限を持つユーザーやロールは、Lambda関数などのAWSサービスに必要なIAMロールを引き渡すことができる。

試行錯誤して分かったこと

基礎知識を学習してもイマイチ腑に落ちないので、
LambdaやIAMを操作してみることにした。

試行錯誤したこと

  • practice-Lambda-RDStoS3-role-idais11pロールから、S3を操作するための権限ポリシーを除去して、Lambdaのコードを実行してみた。
    • すると、Lambdaコードのbucket.objects.filter(Prefix=S3_OBJECT_NAME).delete()の部分でエラーが発生した。
    • 一方StartExportTask関数の処理は動いて、スナップショットの作成は行われていた。

分かったこと

試行錯誤をしてみて以下のことがわかった。

  • Lambdaのdelete()などのコードでS3を操作実行するときは、
    practice-Lambda-RDStoS3-role-idais11pロールにs3:DeleteObjectなどの、S3バケットを操作するためのポリシーを持たせる必要がある。

  • StartExportTaskを実行するときは、
    StartExportTask内のパラメータでarn:aws:iam::************:role/practice-s3OperationsRoleロールのARN自体を使用する必要がある。
    そのため、こちらの場合はS3を操作するためのポリシーをロールアタッチするのではなく、iam:PassRolearn:aws:iam::************:role/practice-s3OperationsRoleロール自体をパスして使えるようにする必要があった。

まとめ

Lambdaに対して、S3を操作するための権限をiam:PassRoleでロールを渡す必要があるのは、
Lambdaのコード内でS3を操作するための権限を持つロールのARN自体を使用してS3を操作する場合だということが分かった。

Lambdaに対して、S3を操作するための権限をIAMポリシーで渡す必要があるのは、
Lambda内でdelete()などのコードを使ってS3を操作する場合だということが分かった。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1