0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS】CDKのgrantメソッドで権限を簡単に設定する

0
Posted at

はじめに

CDKではgrantメソッドを利用することで、リソースに必要なアクセス許可を簡単に定義することができます。
個人的にCloudFormationでリソースを作成する際は、リソースの権限周りの設定にかなり時間を要していました。
grantメソッドを利用することで、必要なポリシーが自動的に生成されて対象のIAMロールへ付与されるため、権限設定を簡単に定義することができます。

実際に使用してみる

今回はLambdaとS3を作成して、検証します。
S3の読み書きを行うLambdaをデプロイし、grantメソッドの有無でどのような挙動となるか確認します。

grantメソッドなし

まずは、grantメソッドなしでLambdaとS3を作成します。
CDKのコードは以下のように作成しました。

lib/projectname-stack.ts
import * as cdk from "aws-cdk-lib/core";
import { Construct } from "constructs";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as lambda from "aws-cdk-lib/aws-lambda";

export class CdkServerlessSiteStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, "Bucket", {
      autoDeleteObjects: true,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    const handler = new lambda.Function(this, "Handler", {
      runtime: lambda.Runtime.PYTHON_3_14,
      handler: "index.lambda_handler",
      code: lambda.Code.fromAsset("lambda/"),
      environment: {
        BUCKET_NAME: bucket.bucketName,
      },
    });
  }
}

Lambdaのコードは下記です。
eventで渡されるパラメータによって、リスト or アップロードを行うようにしています。

lambda/index.py
import boto3
import json
import os

s3_client = boto3.client('s3')

def lambda_handler(event, context):
    bucket_name = os.environ.get("BUCKET_NAME")
    action = event.get("action")

    if action == "List":
        response = s3_client.list_objects_v2(Bucket=bucket_name)
        objects = []
        for obj in response.get('Contents', []):
            objects.append(obj['Key'])
        return {
            'statusCode': 200,
            'body': json.dumps(objects)
        }
    
    if action == "Upload":
        file_name = event.get("file_name")
        file_content = event.get("file_content")
        s3_client.put_object(Bucket=bucket_name, Key=file_name, Body=file_content)
        return {
            'statusCode': 200,
            'body': json.dumps(f"File {file_name} uploaded successfully.")
        }

コードの準備ができたら、CDKをデプロイし、Lambda関数を実行してみます。

$ npx cdk deploy

作成されたS3バケットに適当なファイルを格納し、Lambda関数でListのテストをします。
image.png

CDKで権限未設定のため、期待通りエラーとなりました。

AccessDenied: An error occurred (AccessDenied) when calling the ListObjectsV2 operation

コンソール上でも、LambdaにはCloudWatch Logsへの権限しか設定されていないことが確認できます。
image.png

grantメソッドあり(read)

CDKのコードでgrantメソッドを追加して検証します。
下記のように1行追加しただけで権限の設定が完了します。
CloudFormationで同じような設定を入れようとするとまあまあの記述量が必要なので、とても楽です。

lib/projectname-stack.ts
// ...省略

    const handler = new lambda.Function(this, "Handler", {
      runtime: lambda.Runtime.PYTHON_3_14,
      handler: "index.lambda_handler",
      code: lambda.Code.fromAsset("lambda/"),
      environment: {
        BUCKET_NAME: bucket.bucketName,
      },
    });

    bucket.grants.read(handler); //追加
  }
}

デプロイする前にcdk diffコマンドで差分を確認してみます。
readを設定したため、参照関連の権限が設定されることがわかります。
リソースも対象のS3バケットに限定したりとCDKの方でよしなに権限を設定してくれます。

$ npx cdk diff
...

Stack CdkServerlessSiteStack
IAM Statement Changes
┌───┬──────────────────────┬────────┬──────────────────────┬────────────────────────┬───────────┐
│   │ Resource             │ Effect │ Action               │ Principal              │ Condition │
├───┼──────────────────────┼────────┼──────────────────────┼────────────────────────┼───────────┤
│ + │ ${Bucket.Arn}        │ Allow  │ s3:GetBucket*        │ AWS:${Handler/ServiceR │           │
│   │ ${Bucket.Arn}/*      │        │ s3:GetObject*        │ ole}                   │           │
│   │                      │        │ s3:List*             │                        │           │
└───┴──────────────────────┴────────┴──────────────────────┴────────────────────────┴───────────┘

それでは、再度デプロイを行い、Lambdaのテストを実施します。

$ npx cdk deploy

Lambda関数で先ほどと同様にテストを行うと成功しました。
事前に格納した work.txt が一覧として表示されているので、期待通りの動作です。
image.png

続いて、アップロードのテストを行います。
イベントとして、action: Upload, file_name: <ファイル名>, file_content: <ファイルの中身>を指定した上で、テストを実行します。
image.png

今回はCDKでreadのみ設定したため、uploadは期待通りエラーとなりました。

AccessDenied: An error occurred (AccessDenied) when calling the PutObject operation

grantメソッドあり(read/write)

書き込み権限を追加で付与する場合は、grantメソッドを変更するのみで対応できます。

lib/projectname-stack.ts
// ...省略

    bucket.grants.readWrite(handler); // readWriteに変更
  }
}

この状態で、cdk diffを実行すると差分は以下の通りとなります。
参照系に加えて、オブジェクトの書き込みや削除も可能となります。

$ npx cdk diff
...

Stack CdkServerlessSiteStack
IAM Statement Changes
┌───┬──────────────────────┬────────┬──────────────────────┬────────────────────────┬───────────┐
│   │ Resource             │ Effect │ Action               │ Principal              │ Condition │
├───┼──────────────────────┼────────┼──────────────────────┼────────────────────────┼───────────┤
│ - │ ${Bucket.Arn}        │ Allow  │ s3:GetBucket*        │ AWS:${Handler/ServiceR │           │
│   │ ${Bucket.Arn}/*      │        │ s3:GetObject*        │ ole}                   │           │
│   │                      │        │ s3:List*             │                        │           │
├───┼──────────────────────┼────────┼──────────────────────┼────────────────────────┼───────────┤
│ + │ ${Bucket.Arn}        │ Allow  │ s3:Abort*            │ AWS:${Handler/ServiceR │           │
│   │ ${Bucket.Arn}/*      │        │ s3:DeleteObject*     │ ole}                   │           │
│   │                      │        │ s3:GetBucket*        │                        │           │
│   │                      │        │ s3:GetObject*        │                        │           │
│   │                      │        │ s3:List*             │                        │           │
│   │                      │        │ s3:PutObject         │                        │           │
│   │                      │        │ s3:PutObjectLegalHol │                        │           │
│   │                      │        │ d                    │                        │           │
│   │                      │        │ s3:PutObjectRetentio │                        │           │
│   │                      │        │ n                    │                        │           │
│   │                      │        │ s3:PutObjectTagging  │                        │           │
│   │                      │        │ s3:PutObjectVersionT │                        │           │
│   │                      │        │ agging               │                        │           │
└───┴──────────────────────┴────────┴──────────────────────┴────────────────────────┴───────────┘
...

再度cdk deployを行い、Lambda関数のテストを実施します。

$ npx cdk deploy

Lambda関数で先ほどと同様にアップロードのテストを行うと成功しました。
image.png

S3バケットを確認すると、指定したファイル名でオブジェクトが作成されていることが確認できます。
image.png

お片付け

今回作成したリソースはcdk destroyで削除しておきます。
即座に環境の作成/削除ができる点も便利です。(この点は他のIaCサービスも同様ですが…)

$ npx cdk destroy

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?