データベース技術調査ブログ

LinuxやPostgreSQL、Oracleデータベース、AWSの知識をアウトプットしていきます

【AWS/CloudFront/S3/Cognito】静的ウェブサイトにCognitoの認証をつけたい(dbt)

タイトルの内容に入る前になぜこのようなことをしたいかという背景を少し語ります。
最近DWHをいかにアジャイルに構築して運用していくかについて考えています。商用のツールを使えばいいアプローチはいくらでもありますが、この手のツールはとても高価なイメージがあります。

そこで目に入ってきたのがdbt (data build tool) というOSSです。
dev.classmethod.jp
dbtというツールはいくつもいい点があるのですが、一番好きななのはドキュメントを自動生成してくれるというところにあります。


dbtはOSSCLI版とSaaS版があります。
www.getdbt.com

チーム版は開発ユーザ当たり50$/月ということで、そこまでお高くはない気がしますが、そもそもあまりクラウドサービスをがっつり使うことに抵抗があったりする場合もあるなと思ったりします。(そんな抵抗ない場合は使う一択な気がします。)
また、コンテナで動かすようにするとしてELTなのでdbtを動かすコンテナ自体に高い性能が要らないので、dbt CLIをセルフサービスで運用するとランニングコストも抑えられたりする可能性もあります。



ただその場合にdbtのドキュメントをどうホスティングしていくかという課題があります。

幸いなことに静的ウェブサイトホスティングで4つのファイルを配置するだけで完結するのでいくつもの選択肢があります。よくあるのはNetlifyなどもありますね。(無料ですし)
ただ、ここでもまた課題があります。このドキュメントは結構な設計情報なので、そのまま公開することはできません。認証をかける必要が出てきます。(静的ウェブサイトサービスはBasic認証をかけたりできますが、開発環境を公開する前の保護みたいなもので、あまりにも脆弱な気がします。それで満足できる場合もありますが…)




そこで、私はdbtをセルフサービスで運用する際の安全な静的ウェブサイトホスティング方法について調べました。




が、しかし…





そんな情報は落ちてませんでした(´-ω-`)





なので、ここにまとめます(^^♪
車輪の再発明はしません!これを組み合わせたらできるよという備忘録程度のものです。)

アーキテクチャについて

このブログの仕組みを丸々利用します!
aws.amazon.com


仕組みはブログを読んでください!(一応日本語で簡単な流れを整理しておくので、詳しくは原文翻訳して理解して下さい)

①ユーザはCloudFrontのドメインに対してブラウザでアクセスします。
②CloudFrontはまず最初に認証をしているかどうかをチェックするためのLambda@Edgeをコールします。
③認証していない場合はCognitoの認証画面にリダイレクトします。
④Cognitoで認証が完了すると/parseauthにリダイレクトするようにします。(認証コードも一緒に送ります。)
⑤CloudFrontがLambda@Edgeを呼び出してCognitoとJWTの情報を交換するようにします。(※JWTは認証トークンです。https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/
⑥JWTをCookiesに保持した状態で再びCloudFrontに対してリクエストを投げます。
⑦今度はJWTがあるのでCloudFrontはちゃんとS3へのアクセスをしてクライアントに静的サイトのindex.htmlを返却します。


CloudFrontとLambda@Edgeってこんなことできるんですね。すごく勉強になりました。



しかもこの複雑そうな仕組みをSAMテンプレートを利用して簡単にデプロイできちゃう時代です。いい時代ですね。



デプロイする際のオプションはいくつかあるのですが、今回は検証メインだったので、コンソールからSAMテンプレートをデプロイする方法で検証しました。

デプロイ時の注意点

いくつかSAMテンプレートのパラメータをいじります。
・EmailAddress:検証なのでユーザを作ってもらいます。
・EnableSPAMode:falseにして静的サイトホストモードにします。
・HttpHeaders:{} にします。(このIssue(https://github.com/aws-samples/cloudfront-authorization-at-edge/issues/73)を参照して設定変更。CSP※が邪魔するので止めちゃいます。ちなみにこの件はさわり程度にREADME.mdに記載されていました。見逃していてちょっと詰まってました…たぶんもう少しちゃんと一部だけ修正する方が正しいはずなのですが、一旦動かすだけならこれでいいです。)
・RewritePathWithTrailingSlashToIndex:trueに変更(しなくてもいいかも)


※CSPについて:コンテンツセキュリティポリシー (CSP) - HTTP | MDN


CI/CDパイプラインを追加

サンプルでデプロイされるS3に関してはユーザ側で置き換えることができます。
今回はCodePipelineでCI/CDパイプラインを作る想定でドキュメントを管理するCodeCommitのリポジトリを作成してS3にデプロイする仕組みまで用意します。

CodePipelineでS3にデプロイする手順に関しては以下を参照してもらって、今回はCodeCommitに配置するファイルだけ解説して終わります。
docs.aws.amazon.com

デプロイするファイルたち

dbtのディレクトリ構成のプロジェクト内の「target/」ディレクトリ内の以下のファイルが対象です。
・index.html
・catalog.json
・manifest.json
・run_results.json



S3にデプロイまでできれば、あとは変更するたびにドキュメントを生成しなおしてgitにpushするスクリプトを組んでおけばCI/CDパイプラインが動いてドキュメントが生成されます。
ユーザの管理はCognitoのマネジメントコンソールから実行できます。(AWS CLIとかで楽もできるはず)


ちょっと気を付けること

us-east-1にデプロイされるので注意するくらいかな


最後に

CloudFrontとかLambda@Edgeとかはあまり触ったことなかったのでいい機会になりました。これからもいろいろインプットしていきたいと思います!(^^)!