Chalice を使ってみるなかで調べた小ネタ3点

## 1. 静的ファイルを Lambda 関数に含める方法

- シナリオ: 簡単な設定ファイル (YAML, JSONなど) を Lambda 関数内で読み込むファイルとして扱いたい。
- 問題: `app.py` と同じディレクトリに `env.yml` を置いたが、 `chalice deploy` してもファイルがアップロードされなかった
- 解決策: chalice プロジェクトの下に chalicelib というディレクトリを作って、そこにファイルを置く。 以下のtreeの結果を参照。
    - 使うときは `filepath = os.path.join(os.path.dirname(__file__), 'chalicelib', 'env.yml')` などのように読み込ませて解決。
    - [公式マニュアルでも同様のことが示されている](https://chalice.readthedocs.io/en/latest/topics/multifile.html)

```bash
$ tree -a .
.
├── .chalice
│   └── config.json
├── .gitignore
├── app.py
├── chalicelib
│   └── env.yml
└── requirements.txt
```

なお、chaliceでデプロイをする場合、Linux/Mac などの場合はファイルのパーミッションをそのまま受け継ぐ。 そのため、例えば `750` などのファイルをデプロイした場合、そのファイルを読もうとすると実行時に Permission Denied となってしまうため注意。

- [同様の事例](https://stackoverflow.com/questions/46076543/permission-denied-after-uploading-aws-lambda-python-zip-from-s3) 。アップロード時に作った zip file を展開するときにおそらく保存時のパーミッションをそのまま展開していることが原因。


## 2. IAM Policy が自動生成されない / 自分でPolicyを設定する方法

- シナリオ: Chalice の便利な機能の１つにIAM Policyの自動生成がある。 これは、Lambda 内で boto3 ライブラリを使ってAWSリソースにアクセスしている場合、それを自動的に判断してIAM Policyを動的に自動生成してくれる機能である。
- 問題: なぜか自分のプログラムではこの自動生成・付与を行ってくれなかった。

調べてみると、**boto3.client を利用したプログラムのみ自動生成の対象** であるのが原因だった。 boto3 には resource を使う方法もあるのだが、こちらを使った場合ですらIAMの自動生成の対象にならない。 自分のプログラムは全て boto3.resource を利用していた。 

そのため、IAM Policy を自動生成するため、 **Chaliceでboto3を使うときは常に `boto3.client` を利用する** というのは１つの指針になり得る。
逆に、既存のIAM Roleを利用したい、自分でPolicyの記述内容を管理したい、というケースの場合は `.chalice/config.json` 内で `autogen_policy` を無効にする。 例えば以下の通り。

```json:.chalice/config.jsonから抜粋
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "autogen_policy": false
    }
  }
```

これを無効にした場合、デフォルトでは `.chalice` 内の `policy-<stage name>.json` (この場合は policy-dev.json) を読み込む。 別名を指定したい場合は `iam_policy_file` でファイル名を指定する。 [より詳細な説明はこちら](https://chalice.readthedocs.io/en/latest/topics/configfile.html)

```json:.chalice/policy-dev.jsonにはRole内でのアクセス権限を書いていけばよい
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:*"
      ],
      "Resource": [
        "*"
      ],
      "Sid": "xxxx-xxxx-xxxx-xxxx-1234"
    },
    {
        "Effect": "Allow",
        "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Resource": "arn:aws:logs:*:*:*",
        "Sid": "xxxx-xxxx-xxxx-xxxx-1235"
    }
  ]
}

```

外部のライブラリなどを使いたい場合、boto3.resource を利用する場合はこちらを採用することになるだろう。 IAM権限の関係から、そもそもIAMの操作権限がない場合などはIAM Role ARNを指定して付与することもできる (`iam_role_arn`) 。 

client しか IAM Policy の自動生成にならないという記述は、例えば [AWS BlackBelt シリーズでの説明](https://d1.awsstatic.com/webinars/jp/pdf/services/20190619_AWS-BlackBeltOnlineSeminar_DiveDeepIntoAWSChalice.pdf) とか [この記事よりもはるかに詳しい説明](https://michimani.net/post/aws-about-auto-generate-iam-policy-in-chalice/)とかで見つけることはできたが、公式ドキュメント内でこの記述を見つけられなかった。 あっても良いはずなのだが……


## 3. CORS対応

- シナリオ: ブラウザから ajax で API Gateway - Lambda をコールし、レスポンスを取得したい
- 問題: ブラウザから ajax でアクセスしたら CORS が原因ではじかれる。 `chalice local` で稼働させている場合も同様。

ユースケースに合わせた CORS の設定をすることになるのだが、もうこれはそのまま [公式を読んでもらう方が早い](https://chalice.readthedocs.io/en/latest/quickstart.html#tutorial-cors-support) ぐらい説明が充実している。

概略としては `chalice.CORSConfig` のインスタンスに適当な設定をした後、`@app.route(path, cors=config)` のようにデコレータ内の `cors` に対して設定を渡してやればあとはよしなにしてくれる。