ECSからLambdaを実行するときに必要なIAMロール

# やりたいこと
ECS TaskからLambdaを呼び出したい。

ECSとそれに付与するIAMロールはCloudFormationで定義しているが、IAMロールが正しいところに対して設定できていないとエラーが発生する。

#### エラーの例
`message:Unable to locate credentials`

# 環境
- 起動タイプ
    - Fargate
- OS
    - linux(alpine)

# 書き方
詳細については後述

```sample.yml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ecs-tasks.amazonaws.com
            Action:
              - sts:AssumeRole
      RoleName: TaskRoleNameHoge

  RolePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: TaskRolePolicyNameHoge
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: Hoge
            Effect: Allow
            Action:
              - lambda:InvokeFunction
            Resource: 
              - <実行したいLambdaのArn>
      Roles:
        - TaskRoleNameHoge

  TaskDefinition:
      ExecutionRoleArn: ecsTaskExecutionRole
      TaskRoleArn : !Ref TaskRole

    　<その他TaskDefinition省略>

```

# ExecutionRoleとTaskRoleとTargetRoleの違い
TaskDefinitionの中でRoleを指定するところは

- ExecutionRoleArn
- TaskRoleArn

がある。

さらにECSタスクにスケジュール設定する場合は

- Targets: RoleArn

もある。

このどこにLambda実行ポリシーをつければいいかわかっていなかったためにかなり迷走したので本記事を書いた。
（まず前提として [このあたり](https://qiita.com/NewGyu/items/9597ed2eda763bd504d7#%E6%A6%82%E5%BF%B5%E5%9B%B3) が混乱していたのも迷走の一因）

結論としては上記のsampleに書いた通り、TaskRoleArnに指定すれば良い。
それはそれとしてExecutionRoleとTaskRoleとTargetsRoleはどう違うのか。

イメージはこんなかんじ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210788/8e9e8284-013d-2a08-4000-30a060a62530.png)


## ExecutionRole
Amazon ECSコンテナエージェント、あるいはFargateエージェントにAWS APIの呼び出しを代行する権限を付与するタスク実行ロール。
目的やサービスごとに複数のタスク実行ロールを持つことができる。

Fargateを利用しているのであれば、主にコンテナイメージをプルし、コンテナログを Amazon CloudWatch に出力する権限が付与されていれば良い。
ECSコンソール初回実行に `ecsTaskExecutionRole` というRoleが自動生成されるので、基本のpolicyとなる `AmazonECSTaskExecutionRolePolicy` などを必要に応じてアタッチして使うと良い。

また [このようにECSへSSMから機密情報を受け渡す](https://qiita.com/sr-mtmt/items/9e486404cd21f86e66aa) 場合には、ここにssmへの権限もアタッチしておく必要がある。

コンテナインスタンス上で実行されているコンテナは、コンテナインスタンスプロファイルに供給された資格情報にアクセスすることはできないため、ここは最小限の権限にとどめたほうが良い。

参考：[開発者ガイド　Amazon ECS タスク実行 IAM ロール](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_execution_IAM_role.html)

## TaskRole
ECSタスクの実体となるコンテナに AWS API を呼び出す許可を与えるIAMロールのARN。
AWSのクレデンシャルを作成してコンテナに配布したり、EC2インスタンスのロールを使用する代わりに、ECSのタスク定義やRunTask APIの操作にIAMロールを関連付けることができる。

このロールを使ってタスクのコンテナ内のアプリケーションは、AWS SDKやCLIを使用して、認可されたAWSサービスへのAPIリクエストを行うことができる。

だから今回の「ECS TaskからLambdaを呼び出したい」のためには、ここにLambda実行権限を付与すれば良い。

参考：[開発者ガイド タスク用の IAM ロール](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-iam-roles.html)

## AWS::Events::Rule Targets配下のRole
ルールがトリガーされたときに、そのターゲットに使用されるIAMロールのARN。
1つのルールが複数のターゲットをトリガーする場合、ターゲットごとに異なるIAMロールを使用することができる。

別のアカウントのイベントバスをターゲットとして設定していて、そのアカウントがアカウントIDによって直接ではなく組織を介してアカウントに権限を付与している場合は、このパラメータで適切な権限を持つRoleArnをここに指定する必要がある。

参考：[ユーザーガイド　AWS::Events::Rule Target](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-events-rule-target.html)


# 参考
- [AWS IAMポリシーを理解する](https://dev.classmethod.jp/articles/aws-iam-policy/)
- [ユーザーガイド　AWS::ECS::TaskDefinition](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html)
- [「それコンテナにする意味あんの？」迷える子羊に捧げるコンテナ環境徹底比較 #cmdevio2019](https://dev.classmethod.jp/articles/cmdevio2019-container/)