【初心者向け】LambdaからS3へファイルをアップロードする

## はじめに
これまでMicrosoft Azureを触ってきましたが、転職に伴いAWSの知識が必要になったため、最低限の基本知識をキャッチアップすべく、自己学習を始めました。今回はさらに理解を深める目的で学習した内容をアウトプットします。初心者向けの内容となっておりますので、温かい目で見て頂ければ幸いです。

## ポイント
今回はAWSのサービスを知ることが一番の目的であったため、最小労力でできるだけシンプルに作ることを意識しました。ローカルの環境構築などは一切不要で、AWSのコンソール上ですべて完結する手順となります。(12ヵ月無料枠の環境を利用)

## 利用するAWSサービス
 - Lambda (Python3.13)
 - S3
 - IAM

## 実践手順

### S3にバケットを用意する
コンソール上でS3を選択し、ファイルをアップロードする格納先を作成します。バケット名はグローバルで一意な名前である必要があります。バケット名以外はデフォルトでOKです。<br>※「パブリックアクセスをすべてブロック」がオンになっていることが大事なポイントです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/6470ad02-4a79-d7b4-e266-b80f05e9e583.png)

これでS3側の設定は完了です。

### IAMロールを作成する
AWSではサービス間のアクセスを可能とするために、権限を付与する必要があります。権限の作成や管理はIAMというサービスを使って実施します。

1. ユースケースを選択する
IAMからロールを選択し、新規にロールを作成します。今回は、LambdaからS3へのアクセスを許可するロールを作成するため、ユースケースには「Lambda」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/3e13460e-4cc6-b469-6955-f4923aff753e.png)

1. ポリシーを追加する
ロールにアタッチするポリシーを追加します。S3にファイルをアップロードする権限が必要なため、「AmazonS3FullAccess」を選択します。<br>※今回は最小労力で構築するため事前に用意されているAWSの管理ポリシーを使用しましたが、アップロードのみの操作や特定のバケットを対象としたポリシーを独自に作成して付与することでセキュリティ性が向上します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/02710fff-187f-8fab-4a80-888b94e092fd.png)

1. ロールを作成する
ロール名を入力し、ロールを作成します。作成したロールは後述のLambda関数で利用するため、分かりやすい名前にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/6a0c9882-d3e4-0dc6-305e-243e5173d548.png)

これでIAMロールの作成は完了です。

### Lambda関数の作成
1. 関数を作成する
今回はPythonでプログラムを書くため、ランタイムは「python 3.13」を選択します。<br>関数名はプログラムの内容がイメージしやすい名前にします。<br>ロールは後で設定するので、ここではデフォルトのままとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/555ce4ba-cd6d-2707-d7cf-abc321ab7ca7.png)

1. タイムアウト時間を設定する
設定タブの「一般設定」からタイムアウト時間を設定します。デフォルトの仕様が3秒であるため、必要な時間に変更します。今回は10秒に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/e7c620ae-14e0-8946-3c30-39cc3ea0c718.png)

1. 実行ロールを設定する
S3へのアクセスに必要なロールを付与します。前述で作成したIAMロールをリストから選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/6000b302-9b5e-eb81-0458-7eb2cffa00d9.png)

1. 環境変数を設定する
設定タブの「環境変数」を選択し、プログラムから参照する変数を定義します。今回はアップロード先となるS3のバケット名とアップロードするファイル名を定義します。<br>※必須ではないです。後述するコード上に直接記載する場合は、本手順は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/70497973-d287-fe99-3d14-7cfacb49a312.png)


### コードの作成と実行
S3へファイルをアップロードするコードをLambdaのエディタ上で書いていきます。以下はサンプルコードです。<br>※今回コードの説明は割愛しますが、pythonからAWSのサービスを操作する便利なライブラリが「boto3」になります。Lambdaにはデフォルトでboto3がインストールされているため、そのまま利用することができます。

#### サンプルコード
```
import boto3
import os

def lambda_handler(event, context):
    # S3バケット名と保存するファイル名を環境変数から取得
    s3_bucket_name = os.environ['bucket_name']
    s3_file_name = os.environ['file_name']
    
    # テキストデータを定義
    text_data = "S3へファイルをアップロードするテスト"

    # 一時ディレクトリにファイルを作成 
    temp_file_path = f"/tmp/{s3_file_name}"
    with open(temp_file_path, "w", encoding="utf-8") as file:
        file.write(text_data)

    # S3クライアントを作成してファイルをアップロード
    s3 = boto3.client('s3')
    try:
        s3.upload_file(temp_file_path, s3_bucket_name, s3_file_name)
        return {
            'statusCode': 200,
            'body': f"ファイル '{s3_file_name}' が S3 バケット '{s3_bucket_name}' に正常にアップロードされました。"
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': f"エラーが発生しました: {str(e)}"
        }
```

1. デプロイ
Deployボタンを押下して、作成したコードをLambdaにデプロイします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/51366b13-2743-47d8-d0ef-5974c571637b.png)
以下のメッセージが画面上に表示されたら、デプロイは正常に完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/fd88b501-55b6-636e-8042-fb20484411a8.png)

1. テスト
テストタブより、「テスト」ボタンを押下しコードを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/023082f3-b5be-0dde-e49b-51a33ab3274f.png)

1. 実行結果
Lambdaの関数が正常に動作したことを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/38c17dac-f08c-2022-e3d1-069234a8bf3a.png)
S3の指定したバケット内にファイルが出力されていることも確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/65436c3f-665f-611f-bb38-993d5dac9a86.png)

## おわりに
初めてAWSを触った所感ですが、参考となる文献や情報が多く比較的容易にやりたいことを実現できました。また、GUIや操作感もエンジニアライクな仕様となっており、理解しやすかった印象です。第一歩として、主要なサービスかつ超シンプルな仕組みを構築しましたが、今後さらに拡張したり他のサービスと組み合わせてみたり、いろいろトライしていこうと思います。