AWS Application Composer を試す

# 初めに
AWS Application Composerとは、AWSのアーキテクチャをグラフィカルに構築できるサービスです。(2022/12 時点でプレビュー)
主にサーバレスアーキテクチャを視覚的に構築できます。

詳しくは以下を参照。

https://aws.amazon.com/jp/application-composer/

# 試してみる
S3にオブジェクトがputされたことを検知し、Lambdaを実行する仕組みを作ってみます。
![application_composer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/2cabc8ca-64ff-b883-019a-394a23c19f2f.png)


([S3のイベント通知設定][link-1]でLambdaを宛先にすることでLambdaを実行することもできるのですが、EventBridgeを挟んでいます。)


## プロジェクトの作成
マネコンから「AWS Application Composer」へアクセスし、「Create Project」からプロジェクトを作成します。
ローカルに適当にフォルダを作成し、「Local file system connection mode」をconnectedとしました。
(ローカルのファイルと同期が行える機能です。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/98bc5bcf-c70e-5392-5297-1f4f9cd1f0cd.png)


## アーキテクティング
Resourceからドラッグ&ドロップでCanvasに配置することでアーキテクティングが行えます。
今回利用するS3, EventBridge, lambdaを配置します。
この時に、EventBridge RuleとLambda Functionの間を線でつなぐと、EventBridge RuleのTargetにLambdaを登録することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/bc719c45-8551-2fcb-4baf-18e7266aaf5a.png)



次に、イベントパターンを登録します。
EventRuleのdetailsを開き、Event patternを修正します。
イベント検知するバケット名ですが、template.ymlを確認すると`!Sub ${AWS::StackName}-bucket-${AWS::AccountId}`の名前で作成されるようなので、こちらを利用しています。
![スクリーンショット 2022-12-28 115253.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/c1a6c4ef-a4c7-3efd-6a92-c2e8462bb33f.png)


```yaml:eventpattern.yml
source:
  - aws.s3
detail-type:
  - 'Object Created'
detail:
    bucket:
        name:
            - !Sub ${AWS::StackName}-bucket-${AWS::AccountId}
```

最後にS3バケットの通知設定を行います。
この設定はApplication Composerのキャンバスからは行えないので、Templateを直接修正します。

<details><summary>テンプレートの修正</summary><div>

```diff_yaml:template.yml
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${AWS::StackName}-bucket-${AWS::AccountId}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: aws:kms
              KMSMasterKeyID: alias/aws/s3
      PublicAccessBlockConfiguration:
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
+      NotificationConfiguration: 
+        EventBridgeConfigurations:
+          EventBridgeEnabled: true
  BucketBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument:
        Id: RequireEncryptionInTransit
        Version: '2012-10-17'
        Statement:
          - Principal: '*'
            Action: '*'
            Effect: Deny
            Resource:
              - !GetAtt Bucket.Arn
              - !Sub ${Bucket.Arn}/*
            Condition:
              Bool:
                aws:SecureTransport: 'false'
  EventRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.s3
        detail-type:
          - AWS API Call via CloudTrail
        detail:
          eventSource:
            - s3.amazonaws.com
          eventName:
            - PutObject
          requestParameters:
            bucketName:
              - !Sub ${AWS::StackName}-bucket-${AWS::AccountId}
      Targets:
        - Id: !Ref Function
          Arn: !GetAtt Function.Arn
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: Function
      CodeUri: src/Function
      Handler: index.handler
      Runtime: nodejs18.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${Function}
  EventRuleToFunctionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt Function.Arn
      Principal: !Sub events.${AWS::URLSuffix}
      SourceArn: !GetAtt EventRule.Arn
Transform: AWS::Serverless-2016-10-31
```
</div></details>

## デプロイ

AWS SAMを用いてデプロイを行います。
ローカルのプロジェクトフォルダに移動して
```shell
$ sam build
$ sam deploy --guided
```

でcfnスタックが作成されデプロイが完了します。

## 確認
S3にファイルをアップロードすると
![スクリーンショット 2022-12-28 153956.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/769613c7-28c5-05b5-a4d4-9f8c99fc6a33.png)

Lambdaが実行されることを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/259a4ae6-87f9-b9fa-b57b-501f1635ed93.png)

# 所感
グラフィカルに作成した構成図がそのままTemplateになり、ローカルのファイルと同期ができる点は非常に使い勝手が良いと思います。GUIで編集→AWS SAMでそのままデプロイという流れが斬新でした。
ただ対応サービスが少ないことや、細かい設定を行う場合はTemplateを直接編集する必要があるなど痒いところに手が届かない点があるかなと思います。


<!-- link -->
[link-1]:https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/NotificationHowTo.html