3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS CDK (Python)】 CDKスタックでS3にファイルをアップロードする方法

Last updated at Posted at 2023-06-16

はじめに

本記事は、私自身の備忘録を兼ねてAWS CDKをこれから始める方の一助になればと思い、AWS CDKの使い方等をまとめたものです。
今回は、AWS CDKを実行する際にスタックの中でS3にファイルをアップロードする方法を確認しています。
なお、本記事は私自身の経験を基に記載していますが、間違いがあったらすみません。

CDKでS3にファイルをアップロードしたい状況

主にzipにまとめたソース、ライブラリからLambda Functionを作成する際ですが、CDKスタックの実行でファイルをS3にアップロードしたくなることがあります。また、S3で静的webページをホスティングする際もCDKで直接S3にファイルをアップロードしたくなる状況かもしれませんね。
通常のリソースタイプでは、S3へのアップロードはできませんので、こういった場合にアップロードする方法を確認します。

環境

本記事は以下の環境を使用して記載しています。

  • AWS Cloud9
  • AWS CDK:2.80.0
  • Python: 3.10.11
  • Node.js: 16.20.0

また、以下の記事に基づいてAWS CDKの環境を作成しています。

CDKスタックでS3にファイルをアップロードする方法

では、本題のS3にファイルをアップロードする方法を確認します。今回は、S3バケットを作成し、そのS3バケットにCloud9のローカルファイルをアップロードするCDKスタックを作成したいと思います。
アップロードするためには、aws_cdk.aws_s3_deploymentを使用します。
まず、準備として、アップロードするファイルを以下のように用意します。

(.venv) user_name:~/environment/cdk-app (master) $ tree ./upload-test/
./upload-test/
└── upload-dir
    └── upload-file.txt

1 directory, 1 file
(.venv) user_name:~/environment/cdk-app (master) $ cat ./upload-test/upload-dir/upload-file.txt 
test file.

アップロードするファイルの準備ができたので、スタックのプログラムを作成します。S3バケットの作成とそのS3バケットにアップロードするaws_s3_deploymentの処理を以下のように記述しました。
1点注意点として、file_pathに指定可能なのは、ディレクトリかzipファイルになります。zipでないファイルを直接指定はできません。ここでは、ディレクトリを指定しました。

cdk_app/cdk_app_stack.py
from aws_cdk import (
    Stack,
    aws_s3_deployment as s3deploy,
    aws_s3 as s3,
    RemovalPolicy
)
from constructs import Construct
import random, string

class CdkAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        s3bucket = s3.Bucket(
            self,
            "MyS3Bucket",
            bucket_name = "cdk-test-bucket-yyyymmdd",
            versioned=True,
            removal_policy=RemovalPolicy.DESTROY
        )

        file_path = "./upload-test/upload-dir/"

        s3_deploy = s3deploy.BucketDeployment(
            self,
            "FileUploadS3",
            sources=[s3deploy.Source.asset(file_path)],
            destination_bucket=s3bucket,
        )

この状態でデプロイします。

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy

✨  Synthesis time: 18.38s

(中略)
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬───────────────────────────────────────────────────────┬────────┬───────────────────────────────────────────────────────┬────────────────────────────────────────────────────────┬───────────┐
│   │ Resource                                              │ Effect │ Action                                                │ Principal                                              │ Condition │
├───┼───────────────────────────────────────────────────────┼────────┼───────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┼───────────┤
│ + │ ${Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC │ Allow  │ sts:AssumeRole                                        │ Service:lambda.amazonaws.com                           │           │
│   │ 9EB8756C/ServiceRole.Arn}                             │        │                                                       │                                                        │           │
├───┼───────────────────────────────────────────────────────┼────────┼───────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┼───────────┤
│ + │ ${MyS3Bucket.Arn}                                     │ Allow  │ s3:Abort*                                             │ AWS:${Custom::CDKBucketDeployment8693BB64968944B69AAFB │           │
│   │ ${MyS3Bucket.Arn}/*                                   │        │ s3:DeleteObject*                                      │ 0CC9EB8756C/ServiceRole}                               │           │
│   │                                                       │        │ s3:GetBucket*                                         │                                                        │           │
│   │                                                       │        │ s3:GetObject*                                         │                                                        │           │
│   │                                                       │        │ s3:List*                                              │                                                        │           │
│   │                                                       │        │ s3:PutObject                                          │                                                        │           │
│   │                                                       │        │ s3:PutObjectLegalHold                                 │                                                        │           │
│   │                                                       │        │ s3:PutObjectRetention                                 │                                                        │           │
│   │                                                       │        │ s3:PutObjectTagging                                   │                                                        │           │
│   │                                                       │        │ s3:PutObjectVersionTagging                            │                                                        │           │
├───┼───────────────────────────────────────────────────────┼────────┼───────────────────────────────────────────────────────┼────────────────────────────────────────────────────────┼───────────┤
│ + │ arn:${AWS::Partition}:s3:::{"Fn::Sub":"cdk-hnb659fds- │ Allow  │ s3:GetBucket*                                         │ AWS:${Custom::CDKBucketDeployment8693BB64968944B69AAFB │           │
│   │ assets-${AWS::AccountId}-${AWS::Region}"}             │        │ s3:GetObject*                                         │ 0CC9EB8756C/ServiceRole}                               │           │
│   │ arn:${AWS::Partition}:s3:::{"Fn::Sub":"cdk-hnb659fds- │        │ s3:List*                                              │                                                        │           │
│   │ assets-${AWS::AccountId}-${AWS::Region}"}/*           │        │                                                       │                                                        │           │
└───┴───────────────────────────────────────────────────────┴────────┴───────────────────────────────────────────────────────┴────────────────────────────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬────────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                                                                   │ Managed Policy ARN                                                             │
├───┼────────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴────────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(中略)

Do you wish to deploy these changes (y/n)? y
CdkAppStack: deploying... [1/1]
CdkAppStack: creating CloudFormation changeset...

 ✅  CdkAppStack

✨  Deployment time: 127.91s

Stack ARN:
(中略)

✨  Total time: 146.29s

cdk deployするとなぜか記載してないIAMロールを作成して良いか確認されます。合成されたCloudFormation Templateを確認すると解りますが、IAMロールだけでなく、Lambda Functionも作成されます。aws_s3_deploymentは、実体としてはLambda Functionのようですね。
では、S3バケットを確認してみます。
アップロードされていることが分かります。
image.png

image.png

次にzipファイルのアップロードを確認してみます。(一度cdk destroyしてます。)
以下のようにzipファイルを準備しました。

(.venv) user_name:~/environment/cdk-app (master) $ tree ./upload-test/
./upload-test/
└── upload-dir
    └── upload-file.zip

1 directory, 1 file
(.venv) user_name:~/environment/cdk-app (master) $ unzip -l ./upload-test/upload-dir/upload-file.zip 
Archive:  ./upload-test/upload-dir/upload-file.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       11  06-06-2023 12:26   upload-file.txt
---------                     -------
       11                     1 file

この状態でデプロイします。(コードは変更してません。=file_pathの指定はディレクトリ)

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy

S3バケットを確認すると、zipファイルがアップロードされていることが分かります。
image.png

image.png

今度は、コードは変更してfile_pathの指定をディレクトリではなく、zipファイルを直接指定してみます。

cdk_app/cdk_app_stack.py
from aws_cdk import (
    Stack,
    aws_s3_deployment as s3deploy,
    aws_s3 as s3,
    RemovalPolicy
)
from constructs import Construct
import random, string

class CdkAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        s3bucket = s3.Bucket(
            self,
            "MyS3Bucket",
            bucket_name = "cdk-test-bucket-yyyymmdd",
            versioned=True,
            removal_policy=RemovalPolicy.DESTROY
        )

        # ↓↓ zipファイルを直接指定するように変更
        file_path = "./upload-test/upload-dir/upload-file.zip"

        s3_deploy = s3deploy.BucketDeployment(
            self,
            "FileUploadS3",
            sources=[s3deploy.Source.asset(file_path)],
            destination_bucket=s3bucket,
        )

デプロイしてS3バケットを確認します。

(.venv) user_name:~/environment/cdk-app (master) $ cdk deploy

image.png

zipファイルが展開されてS3バケットにアップロードされていることが分かります。このようにzipファイルを直接指定する場合とディレクトリを指定する場合で、S3へのアップロードのされ方が異なるので、注意が必要ですね。Lambda Functionを作成する場合はディレクトリを指定するなど、用途に応じて制御する必要がありそうです。

まとめ

AWS CDKでデプロイの際にS3にファイルをアップロードする方法を確認しました。手動操作を挟むことなく一連の流れとしてファイルアップロード→Lambda Functionの作成などが行えるのは助かりますね。
最後まで読んでいただいてありがとうございます。
少しでも参考になれば幸いです。

参考文献

3
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?