概要
最初に紹介した記事
notwodaily.hatenablog.com
および、前回作ったテストアプリ
notwodaily.hatenablog.com
から一転して、本命のアプリを制作します。ここまで得た知識+αを総動員してその集大成を見せるときが来ました。大まかな図はdraw.ioで作りました。
IAM Role準備
ユーザー作成
ここでは開発者ということでdeveloperとでもします。
以下でdevelopersグループを作成してそこにユーザを紐付けて、作成。
作成が終わったら、実際にS3やDynamoDBで操作ができるか、適当に触って確認してみましょう。
グループ作成
ダイアログでグループ名をdevelopersにします。Roleは
- IAMFullAccess
- AWSCertificateManagerFullAccess
- AmazonS3FullAccess
- CloudFrontFullAccess
- AmazonDynamoDBFullAccess
- AWSLambdaFullAccess
- AmazonAPIGatewayAdministrator
- AWSKeyManagementServicePowerUser
- AmazonRoute53FullAccess
- AmazonRoute53DomainsFullAccess
にチェックを入れて確認。最大10個までしか作れないので、一度設定して不要になったら権限を一部放棄しても問題ないです。アタッチ、デタッチは何度でも出来ますので。
これでもまだ権限的に相当強いですが、細かく設定するのが単に面倒なだけで。。本来は必要最小限にとどめたほうが良いのは言うまでもないです。
IAM Roleでログイン
上記まではroot相当の権限で操作していたはずですので、一旦ログアウトして、さっき作ったroleでログインし直します。
やり方は少し長くなるので別記事にまとめました。
notwodaily.hatenablog.com
Lambda関数作成に必要です。先にAPI名だけ用意します。
ここでのAPI名は制作するアプリ名としてちゃんとしたものをつけてあげましょう。
実データ配置(S3)
S3に必要なファイルを配置します。具体的にはLambda関数用のファイル(.py)をZIPで、他HTML/CSS/JavaScript/Image/Text(mail)をそれぞれ配置します。今回はこの方法で行きます。
その他、Lambda関数用ファイル(.py)と依存ライブラリをZIPにして別途LambdaへアップロードしてS3へPUTする方法もあります。
それについては
dev.classmethod.jp
の解説を見れば分かりやすいです。
バケットを作成してLambda関数用ZIPファイルを配備し、プロパティを覗いた例です。
S3へは直接アクセスさせずにCloudFrontを介する構成にしているので、ここでは公開後にプロパティのURLを叩いてもAccess Deniedエラーになります。
S3へのPOSTアクセス
これは禁止されているっぽく、実際にアクセスしてもMethodNotAllowedエラーが出ます。CORS設定してようが拒否られます。
stackoverflow.com
なのでPOSTしたいけどどうしてもS3のオブジェクトが欲しいって時はapi gateway経由で取得すると良い。
デフォルトでは設定がありませんがキャッシュが効いており、JSなど更新しても反映されるまでに時間がかかりすぎます。invalidationというのを使うらしい...
CloudFrontのDistributionsから該当のdistributionを選び、Invalidationsタブをクリックして、Create Invalidation
ここでパスを設定すればまとめてキャッシュを削除できます。毎回ここで消さないといけないのが面倒っちゃ面倒ですが。。
よく編集するJS, HTML, CSSは頻繁にアップすることになるので、まとめて
/js/*
/css/*
/*.html
などして消せるようにしておくと楽です。
テーブル用意
DynamoDBにテーブルを用意します。データ構造を設計時に考えておくべきです。
セッションの永続化のためのテーブルを用意することも出来ますが、今回は単純な申込みフォームを用意するだけなので手を出しません。
noSQLなので複雑なオブジェクトも保存可能。だからこそあまり自由に作りすぎて後で階層が深すぎて取り出しに苦労する、なんてマヌケなことにならないように注意。
Lambda関数作成
必要なLambda関数を作成してAPIから叩けるようにします。
早速作ります。blueprintはBlank Functionを選択して最低限作ってもいいですが予めS3やDynamoDBを使うとわかっているので、それ用のblueprintを利用して書き換えたほうが楽でしょう。
runtimeをPython2.7に変更し、filterにとdynamodbと入れて出て来るmicroservice-http-endpoint-pythonを選択してNext。
API name:事前に作成したAPIの名前
Deployment stage:prod(最初のデプロイでは他にステージがないので選択出来ません)
Security:Open with access key(keyは未設定ですが、後でAPIコンソールで編集します)
Name:実際に作るアプリに関する分かりやすい、愛のある名前をつけてあげましょう。
Description:どんな機能なのかを書いたらいいと思います。
Runtime:Python2.7
Lambda function code
Code entry type:Upload a file from Amazon S3
S3 link URL:別でS3に配備したLambda関数用ファイル(.py)のパス(https://s3.amazonaws.com/作成したバケット名/ファイル名)
Lambda function handler and role
Handler:APIからLambda関数がコールされたときのエントリポイント。これの名前.pyがLambda関数のファイル名です。デフォルトのままでもいいです。こだわりがなければね。
Role:Create new role from template(s)
Role name:必要なroleは勝手に追加されていくので、ここではfunction名を決めるときの様に愛のある名前を!
HandlerはPythonのコード上ではデフォルトで
def lambda_handler(event, context):
となっている部分のことです。
ほかはデフォルトのままで。
Lambda関数はアップロード後にLambdaコンソール(画面)から修正できます。
Lambda関数作成後にエラーが出たら?
Create Function後は何かエラーが有る場合は下画像のようなwarningが出ます。
Trigger作成に失敗しましたと言っています。Lambda関数作成時にTriggerにAPI Gatewayを指定したうえで、TriggerにまだAPIにリソースを追加していないからですね。メソッドをAPIのリソース直下に作成まで終わったらLambdaコンソール上でTriggerタブ→Add triggerからAPI Gatewayを追加すればOKです。さっきと同じ設定でいきましょう。すると作成したリソース直下に新たにANYメソッドが出来ているはずです。
IAM role違いによるエラー!?
後でAPI Gatewayを編集していくとわかりますが、Lambdaでは独自のIAMロールを用いるので、api gateway経由でPOSTすると
The role defined for the function cannot be assumed by Lambda
とか怒られるので、Lambda側で開発に用いているIAMユーザを許可させてやる必要があります。そこで、
dev.classmethod.jp
の
リソースベースのポリシー
の部分から下に倣うと出来ます。一緒にやってしまおう。
今回は予約フォームのために必要なAPIを準備します。
API名だけは先に用意してあるので、その中身を埋める作業です。まずルートリソース直下にリソースを作成します。次にそのリソース直下にメソッドを作成します。メソッドはLambda関数のTrigger設定時にANYが作成されているはずです。が、これは使いません。自分で新たにGETなりPOSTなり作成します。
dev.classmethod.jp
の通りの設定で大丈夫です(一部UIが異なりますが)。
ただし
docs.aws.amazon.com
にある通り、一度デプロイした後に出来るので、ここではまだ作らず先にデプロイまで進めたほうがいいですね。先に作成だけして無効にしておいてもいいですが。
CORS設定
後述するformとの連携のため(主にjqueryとAPIの連携)、APIのCORS設定は必須です。
CORS設定は
qiita.com
とかを参考に。
はじめにAPIを作る時にCORS設定を同時に有効にしていなくても、後でリソースを選択してアクション→CORSの有効化、とすれば設定できます。しかもこちらならヘッダ情報も自動でつけてくれて大変便利!
統合リクエストのテンプレートマッピングも忘れずに。ここでどういう形式でLambdaにデータを渡すかを定義します。これがないとせっかくAjaxから渡したデータがlambda_handlerのeventに空で渡ってしまいます。
テンプレートマッピングは公式ドキュメントを参考に。
フォーム作成
S3の実データ配置の一部ではありますが、制作するフォームについて補足します。
フォームの作りは
qiita.com
を参考にしました。API Gatewayへのアクセスは、すべてAjaxで行います。事前にgateway側でCORS設定をしておき、テンプレートマッピングも用意する必要があります。S3の項目で書きましたが、formを作成したとしてもmethodはgetのみです。で、
~~.on('click', function() {
location.href="次画面のリンク";
}
みたいなことやれば出来ますが、かなりゴリ押し感もしますね。S3がただのストレージなので仕方ないといえば仕方ないのですが。
メール送信
SESの設定をします。それ用にドメインを持つ必要がありますが、
この辺は下記記事に別途まとめました。
notwodaily.hatenablog.com
ここまでで一通り完成です。とは言え、勿論まだ改善の余地だらけだし、正直これで無料期間終了したら月いくらになるのか計算もしてません。セキュリティ的にここがまずい、とか探せば出そうなのでこれを真似して作るなら注意。
作ってみてわかったこと
- とてもweb初心者には無理
- 言語そのものよりもインフラ、サーバ構築の知識が必要
- これ専用の学習コストは相当高い。Lambdaは利用できる言語にも縛られるので、すべてをAWS構築にする必要はないかもしれない。→今ではRubyやC#も利用できるし、今後も追加されていくはずなので自由度は高くなる。
- 記事を書きながらだと理解が速い→おそらく正確に書くことが求められるから分からないところは調べざるを得なくなるので。
といった具合です。独自の用語を覚えたりどれとどれが組み合わせられるのか、その仕様までまず理解するところから始まります。何もwebを知らない初心者からすればただの迷宮です。
初年度無料は確かに魅力としてはでかいしスペックをほとんど気にせず使えるのはありがたいんですが、多機能なサービスには複雑さが伴うことは避けられないといえます。無理してこれを使うくらいなら、規模が小さいうちはサーバも全部自前で用意してCentOS7(本記事執筆時点での最新Ver)を入れるとか得意な言語によっては無料のサービス(Rubyが出来るならHeroku)があるのでそれをまず試してみるのもあり。
筆者自身この日までAWSド初心者でしたが、これで大凡の仕組みというか制作のキモくらいはわかったつもりです。これで堂々とAWS使えますって言える(;´∀`)