Workload Identity連携で、GCP操作するLambdaをAWS SAMで作成

# はじめに
AWSからGCPの操作がセキュアにできるWorkload Identity連携を、AWS SAMを使って作成したLambdaから行った内容を記事にしました。

# やったこと

## GCP側
以前の記事をそのままやっています。

https://qiita.com/a_b_/items/f30b85be4f44ed1f620c#gcp%E5%81%B4

こちらで作られたファイルをそのまま使います。

## AWS側

### Cloud9

#### 環境
AWS SAMを実行するので、ボリュームは50GB程度あるといいです。
以前記事にした内容と同じ環境でやっています。

https://qiita.com/a_b_/items/6b02e08ecacdd21524c2#%E7%92%B0%E5%A2%83

#### 設定
ローカルでテストを行う際に、Cloud9からGCPにアクセスできるよう、EC2にIAMロールを付けます。
前回の記事と同様です。

https://qiita.com/a_b_/items/102dfa252761eceab528#cloud9%E8%A8%AD%E5%AE%9A

注意ですが、このIAMロールのままデプロイするのであれば、その権限も付与しておく必要があります。

### フォルダ構成・ファイル
Clooud9上にフォルダやファイルを配置していきます。

```
sample-a2g
├── functions
│   ├── clientLibraryConfig-awstogcp.json
│   ├── function.py
│   └── requirements.txt
└── template.yaml
```
- `clientLibraryConfig-awstogcp.json`はGCPで作った認証ファイルです


```python:functions/function.py
from google.cloud import storage

def lambda_handler(event, context):

  storage_client = storage.Client()
  buckets = list(storage_client.list_buckets())
  print(buckets)
  return {
      'statusCode': 200
  }
```
用いるライブラリは`requirements.txt`に記載します。
```text:functions/requirements.txt
google-cloud-storage
```

テンプレートファイルは以下です。Lambdaが書き込むCloudWatchロググループも一緒に作っています

```yaml:template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda Function

Parameters:
    LambdaFunctionName:
        Type: String
        Default: "testfunctiona2g"

Resources:
  FunctionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "for-lambdafunction-${LambdaFunctionName}"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/service-role/'
      Policies:
        # CloudWatch
        - PolicyName: write-cloudwatchlogs
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: 
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:*"

  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${LambdaFunctionName}
      RetentionInDays: 3653

  TargetFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Role: !GetAtt FunctionRole.Arn
      CodeUri: functions/
      Handler: function.lambda_handler
      Runtime: python3.9
      Environment:
        Variables:
          GOOGLE_APPLICATION_CREDENTIALS: "clientLibraryConfig-awstogcp.json"
          GCLOUD_PROJECT: "hogehoge-pj"
```
- LambdaのIAMロールは、GCPが実行できるものにしてください
    - 今回は、AWSの全てのIAMロールを実行できるようにしているので、任意のIAMロールが付いていればOKになります
- GCPに接続するために必要な環境変数は最後の4行で設定しています。


# コードから直接実行

以前の記事と同様に`launch.json`を編集します。

https://qiita.com/a_b_/items/6b02e08ecacdd21524c2#%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8B%E3%82%89%E7%9B%B4%E6%8E%A5%E5%AE%9F%E8%A1%8C

実行する際の設定は以下になります。

```json:launch.json
{
    "configurations": [
        {
            "type": "aws-sam",
            "request": "direct-invoke",
            "name": "test-a2g",
            "invokeTarget": {
                "target": "code",
                "projectRoot": "sample-a2g/functions",
                "lambdaHandler": "function.lambda_handler"
            },
            "lambda": {
                "runtime": "python3.9",
                "payload": {},
                "environmentVariables": {
                    "GOOGLE_APPLICATION_CREDENTIALS": "clientLibraryConfig-awstogcp.json",
                    "GCLOUD_PROJECT": "hogehoge-pj"
                }
            }
        }
    ]
}
```
- 環境変数は`lambda - environmentVariables`の中に記述します。

実行し、成功するとコンソールにバケット一覧が出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/fd45d1b7-4442-26b1-6e50-56cb919904ef.png)


# Lambdaデプロイ

デプロイの方法も以下の記事を参考にしてください。

https://qiita.com/a_b_/items/6b02e08ecacdd21524c2#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4

# Lambdaのテスト

作成されたLambdaをコンソールから開き、[テスト]タブの「テスト」ボタンをクリックすることで動かすことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/24c607dc-f7cd-53fd-18b6-ec8db3b9618a.png)

成功すると、ログ出力の場所にGCPの指定したプロジェクトのバケット名が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/0a8d187b-51b4-93f2-8a1a-0df4eacf5f0f.png)

# おわりに
今回はWorkload Identity連携を使ったセキュアなGCP連携を、AWS SAMで実現してみました。
日本語対応したOCRはAWSにはないためGCPのを用いようと思っていたので、今回のを発展させLambdaでGCPのVison APIを呼び出す関数を作っておく方法に使おうと考えています。