前提
- LambdaについてはServerlessFrameworkを使用
- IP制限の掛かったサービスにWebhook的にLambdaから通知を送りたかった
- SESのバウンス通知
- 動画変換完了後の通知など(うちの会社ではよくあるパターン)
課題
- これまではどうしていたかというと
- IP制限の掛かっていないCloudFrontディストリビューションを作成
- 上記のディストリビューションに対してドメインを振る(
webhook.xx.com
等) - アプリケーション側の該当のパス以下(
/webhooks/hoge
等)にベーシック認証を設定 - Lambdaから上記のパスに通知
ペイン(辛み)
- (ベーシック認証は掛けるものの)野ざらしになったWebhookディストリビューションを作ることになること
- ドメインも別途発行する必要があること
- クライアントによっては発行まで色々やり取り発生するし時間かかるしめんどくさい
- 同時にSSLの設定等も増えるのでとにかくめんどくさい
解決策
- 今回下記の流れで面倒くささが解消されました
- LambdaをVPC内に作っちゃう
- Lambdaを配置したPrivateサブネットに繋がったNATゲートウェイのIPをWAFに追加する
- LambdaからメインのCloudFrontのURLを叩けるように書き換える
ゲイン(ハッピーになったこと)
- IP制限を掛けている範囲内でアプリケーションが完結したこと
- クライアントにドメインの追加申請をするという申し訳ない事態を防げたこと
- VPC内にLambdaを作成するという新たな知見を得ることができたこと
- 他にも同様の構成で悩んでいた人たちのちょっとした悩みを解消できたこと
解決策(解説)
LambdaをVPC内に作っちゃう
ServerlessFrameworkを使うとめちゃ簡単にできちゃいます。下記の通りserverless.yml
のprovider
に設置するサブネットとセキュリティグループを設定するだけ。
# serverless.yml
provider:
name: aws
runtime: ruby2.5
region: ap-northeast-1
stage: ${opt:stage, 'development'}
# 以下を追加
vpc:
securityGroupIds:
- sg-xxxxxx
subnetIds:
- subnet-yyyyyy
- subnet-zzzzzz
ちなみに私の場合は、複数の環境にまたいで管理をしているので実際はこんな感じで設定しています。
# serverless.yml
provider:
name: aws
runtime: ruby2.5
region: ap-northeast-1
stage: ${opt:stage, 'development'}
vpc: ${self:custom.vpc.${self:provider.stage}}
custom:
vpc: ${file(./vpc.yml)}
# vpc.yml
development:
securityGroupIds:
- sg-xxxxxx
subnetIds:
- subnet-yyyyyy
- subnet-zzzzzz
staging:
securityGroupIds:
- sg-aaaaaa
subnetIds:
- subnet-bbbbbb
- subnet-cccccc
production:
securityGroupIds:
- sg-dddddd
subnetIds:
- subnet-eeeeee
- subnet-ffffff
微妙なハマリポイント
ちなみに一見、下記のようにVPC内でLambdaを実行するためのポリシーを設定しないとだめなように思いますが、むしろ下記を設定するとエラーが発生します。
# serverless.yml
provider:
name: aws
runtime: ruby2.5
region: ap-northeast-1
stage: ${opt:stage, 'development'}
vpc:
securityGroupIds:
- sg-xxxxxx
subnetIds:
- subnet-yyyyyy
- subnet-zzzzzz
# 下記を追加すると動かない
iamManagedPolicies:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Serverless Error ---------------------------------------
An error occurred: IamRoleLambdaExecution - Property ManagedPolicyArns contains duplicate values..
Get Support --------------------------------------------
どうやらserverless.yml
にvpc
の設定を行ったことでServerlessFramework自身がよしなにAWSLambdaVPCAccessExecutionRole
相当のポリシーを実行ロールに付与してくれるようで(実際に追加されてました)、「それと同じポリシーは追加できないよー」的な感じで怒っているようです。よしな力高いのは良いけど分かりづらいw
ということで、これによりLambdaをVPC内に作成することができました。あとはプロジェクトによって方針はまちまちだと思うので、うまい具合にやってもらえたらと思います。
以上、LambdaをVPC内に作ってハッピーになった話、でした。