【OCI クラウド移行ガイド】 AWS Lambda を OCI Functionsへ移行してみた（その4:LambdaからOCI Object Storageを扱う編）


(その1:Hello World編はこちら）
https://qiita.com/araidon/items/6ae7067efe92ecaec776

(その2:S3 put編はこちら)
https://qiita.com/araidon/items/56d7942dbd19ec1c1e87

(その2:OCIからAWSサービスを扱う編はこちら)
https://qiita.com/araidon/items/fbe7bab007195b5f9c38

# OCIクラウド移行ガイドとは

オンプレミスやAWSなど、複数のプラットフォームからOracle Cloud Infrastructureへの移行プロジェクトに取り組んでいるクラウドエンジニア（@araidon,@kazunishi,@yama6）による、OCI移行手順をまとめたシリーズ記事です。
各回、サンプルワークロードから対象サービスを取り上げ、移行手順をガイドいたします。
まとめ記事は以下になります。

https://qiita.com/yama6/items/b197c0fe3ec75eb02637

# 移行するサービス：AWS Lambda

今回、移行対象とするのはAWS Lambdaです。
例えばOCIに移行することが難しいAWSサービスに対して、AWS Lambdaからではなく、
OCI Functionsから利用します。

今回は、AWS LambdaからOCI Object Storageを扱います。

<イメージ画像>

# 前提条件
- 言語はPythonとします
- AWSのアカウントは作成済みとします
- OCIのアカウントは作成済みとします
    - アカウントの管理者権限を有している

# OCIのS3互換APIとは
OCIのObject Storage がAmazon S3のAPIと互換性を持つように設計されたAPIです。
これにより、既存のS3クライアントやツールを使用して、OCIのObject Storageにアクセスすることができます。

## 主な特徴
- 互換性
 Amazon S3のAPIと互換性があるため、既存のS3クライアントやツールをそのまま使用できます。
- シームレスな移行
既存のS3ベースのアプリケーションをOCIに移行する際に、コードの変更を最小限に抑えることができます。
- セキュリティ
OCIのセキュリティ機能（IAM、暗号化など）を活用しながら、S3互換APIを使用できます。

# 1. 準備
## 1-1(OCI)Object Storageを扱う権限ユーザの顧客秘密キーを作成

1. OCIコンソール右上ユーザーアイコンから、[ユーザー設定]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/01433a69-5851-1909-cf80-c2b9efdb90d2.png)

2. 左下リソースの[顧客秘密キー]を選択し、[秘密キーの生成]を選択
![CleanShot 2024-12-01 at 08.23.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/202bb3e6-f616-1388-c9a3-eb9a9605b964.png)

3. 秘密キーの生成にて、任意の名前を入力し、[秘密キーの生成]を選択
![CleanShot 2024-12-01 at 08.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/408a6551-6afe-9769-9768-e2647e8d99b9.png)

4. 生成された秘密キーをコピー、どこかにメモしておく
![CleanShot 2024-12-01 at 08.26.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/8edcfe1d-a97e-bd5c-8e53-d39598038c81.png)

5. 生成後の[アクセス・キー]もコピー、どこかにメモしておく
![CleanShot 2024-12-01 at 08.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/35e261cc-6e6b-4a21-1132-721be3b27126.png)

## 1-2(OCI)オブジェクト・ストレージ・ネームスペースを確認
:::note info
■オブジェクト・ストレージ・ネームスペースとは
テナント名とは別に、OCIテナントに一意に割り当てられる識別子です。
オブジェクトストレージ内のバケットやオブジェクトを一意に識別するために使用されます。
:::

1. OCIコンソール右上ユーザーアイコンから、[テナンシ:(テナント名)]を選択
![CleanShot 2024-12-01 at 08.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/da5ef793-181a-6eab-f68c-d6b0b3f5b3aa.png)

2. 画面右側の[オブジェクト・ストレージ・ネームスペース]を確認し、どこかにメモしておく
![CleanShot 2024-12-01 at 08.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/772a12aa-92ed-225d-6ade-047040b732ae.png)


## 1-3(OCI)対象のコンパートメントを指定する
:::note warn
S3互換APIを利用する際に、テナントのコンパートメントは1つだけの制約があります。
複数のコンパートメントを扱うことができないのは十分に留意する必要があります。
:::

1. OCIコンソール右上ユーザーアイコンから、[テナンシ:(テナント名)]を選択
![CleanShot 2024-12-01 at 08.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/da5ef793-181a-6eab-f68c-d6b0b3f5b3aa.png)

2. 画面上部の[オブジェクト・ストレージ設定の編集]を選択
![CleanShot 2024-12-01 at 08.32.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/43cb9f5d-2522-a4cc-105d-487839bcf6b9.png)

3. [Amazon S3互換APIで指定されたコンパートメント]部分を、対象のコンパートメントに変更し、[保存]を選択
![CleanShot 2024-12-01 at 08.34.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/72e2c140-88a3-a629-66e8-543b43fc15d4.png)

4. 保存後に、対象のコンパートメントが選ばれていることを確認
![CleanShot 2024-12-01 at 08.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/13ea612b-68dd-4584-4ed6-8c35fb9d1576.png)


# 2. 実装
## 2-1(AWS)対象のLambdaに、環境変数を指定する
AWSにて、作成したLambdaの構成に、アクセスキー、シークレットキー、namespace、リージョンを登録します。
|キー|値|
|-|-|
|OCI_SECRET_ACCESS_KEY|(OCIで作成したシークレットアクセスキー)|
|OCI_ACCESS_KEY_ID|(OCIで作成したアクセスキー)|
|REGION_NAME|(アクセスするOCIリージョン)|
|NAMESPACE|(OCIのテナントに割当てられたnamespace)|

![CleanShot 2024-12-01 at 10.45.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/5d385299-e0ea-d0c9-6724-2dd354bd6689.png)


```python: AWS LambdaからBoto3でOCIのObject Storageを扱う
import boto3
import os

def lambda_handler(event, context):
    # Lambdaの環境変数から変数取得
    access_key_id     = os.getenv('OCI_ACCESS_KEY_ID')     # OCIのアクセスキー
    secret_access_key = os.getenv('OCI_SECRET_ACCESS_KEY') # OCIのシークレットアクセスキー
    namespace         = os.getenv('NAMESPACE')             # OCIのテナントに割当てられたnamespace
    region_name       = os.getenv('REGION_NAME')           # OCIのリージョン名
    
    # boto3を利用して、S3オブジェクトを作成
    s3 = boto3.resource(
        's3',
        aws_access_key_id=access_key_id,
        aws_secret_access_key=secret_access_key,
        region_name=region_name, # Region name here that matches the endpoint
        endpoint_url="https://" + namespace + ".compat.objectstorage." + region_name + ".oraclecloud.com"
    )

    # S3バケット一覧を取得して表示
    print("■OCIバケット一覧")
    for bucket in s3.buckets.all():
        print(bucket.name)
    
    # 特定のバケットを指定して、オブジェクト一覧を取得して表示
    oci_bucket_name = "oci_bucket_fromaws" # 特定のバケット名を指定

    print("■OCIオブジェクト一覧")
    bucket = s3.Bucket(oci_bucket_name)
    for obj in bucket.objects.all():
        print(obj.key)

```

# 3. 検証
上記Lambadaの実行結果ログ
```
Status: Succeeded
Test Event Name: test_s3compatibilityapi

Response:
null

Function Logs:
START RequestId: 0c2d88df-249b-42b3-a060-2269074a329b Version: $LATEST
■OCIバケット一覧
oci_bucket_fromaws
■OCIオブジェクト一覧
computer_cloud_system.png
END RequestId: 0c2d88df-249b-42b3-a060-2269074a329b
REPORT RequestId: 0c2d88df-249b-42b3-a060-2269074a329b	Duration: 3753.55 ms	Billed Duration: 3754 ms	Memory Size: 128 MB	Max Memory Used: 85 MB	Init Duration: 326.19 ms

Request ID: 0c2d88df-249b-42b3-a060-2269074a329b
```

■実際のOCIのバケット一覧
![CleanShot 2024-12-01 at 10.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/de863e28-e66b-9e9b-8b26-2cd205c28ca2.png)

■実際のOCIのバケット内のオブジェクト一覧
![CleanShot 2024-12-01 at 10.30.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/5e777c48-8c2d-0403-37a8-185dc0b3870e.png)


# まとめ
意外と簡単に実装できることがわかると思います。
OCI側でキーの発行などシークレットキーとアクセスキーを発行して、LambdaでBoto3を利用するだけです。

# 参考

https://docs.oracle.com/ja-jp/iaas/Content/Object/Tasks/s3compatibleapi.htm

https://speakerdeck.com/oracle4engineer/ociobuziekutosutorezi-s3hu-huan-apifalseli-yong

https://boto3.amazonaws.com/v1/documentation/api/latest/index.html

https://docs.aws.amazon.com/ja_jp/pythonsdk/