2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
ここからは、(AWS CDKとNext.jsとStripeの)Topicsについてバッとしゃべっていこうと思います。まずはセットアップ方法です。そこからStripeなどのAPIキーの管理方法、設定のカスタマイズについて2種類ほど紹介していこうと思います。
(スライドを示して)セットアップ方法です。Next.jsとAWS CDK、どちらもcreateもしくはinitコマンドを設定して、アプリをプロジェクトのディレクトリごと作成する仕組みです。
どちらもすでにファイルが設置されていて、Gitで管理されているディレクトリの中に展開できないものなので、Next.jsでcreate-next-appでセットアップした後か、cdk initでCDKのセットアップをした後に、もう片方のリソースを持ってくる必要があります。
(スライドを示して)右側にコマンドを書いていますが、このあたりはハッシュタグ「#jawsug」「#cdkconf」でスライドを公開しているので、読み切れなかった方はそれぞれのPCで見てください。個人的な感触としては、CDKのほうがファイル数が少ないので、後から手動で追加しやすいかなと思います。
CDKとNext.jsです。Next.jsのディレクトリの中にCDKのディレクトリを入れて、その中でpackage.jsonを配置しようとして、CDK側がNext.jsのリソースにアクセスできないとエラーを出してきたりするので、モノレポにする必要があるかと思っています。
(スライドを示して)もし1つのpackage.jsonの中で両方管理したいと思っている方は、右側のサンプルのようにライブラリのインストールなどはまとめて行い、CDK関連のリソースはCDKディレクトリを切って、binファイルとstackファイルのそれぞれを用意してやるようなイメージがよいかなと思います。
Serverless Next.jsの特徴は、Next.js側のコードをほぼ触らないので、CDKをやめて「App Runnerに行こうとかVercelに戻ろう」となった場合、もしくはAmplifyなどに移りたい場合は、CDKのスタックを消してCDKのディレクトリを消せばそれで終わりという、持ち運びのしやすさなどもかなり特徴かなと思っています。
それから、「手動で紹介しているやり方は面倒くさいな」という方は、cdk initした後、ファイルだけ持ってくるやり方ももちろんできるので、この後の変更内容などを見ながら参考にしてもらえればと思います。
(スライドを示して)変更内容です。まずtsconfigを分けています。CompilerOptionsのmoduleの部分で、Next.jsとCDKでそれぞれ設定してほしいものが別々になっているので、Next.jsのものをCDKに使おうとする、またはその逆にしようとすると、ビルドにエラーが出ます。そのため、分けてやる必要があります。
分けた後、今度はcdk.jsonの中に実行するコマンドが書かれているのですが、このts-nodeにCDK用のtsconfigを読ませてやる必要があるので、--projectで、tsconfig.cdk.jsonを渡します。
あとはbinファイルのパス、ファイル名が変わっている場合は、それらも変更する必要があります。
CDKの定義は先ほど紹介したものとほぼ同じです。
あと、これは今回の例じゃなくても必要ですが、binファイルで、Serverless Next.jsが用意しているBuilderというクラスを使ってCDKのスタック、Appをラップする必要があります。
これは何をしているかというと、CDKでビルドやデプロイなどをする前に、Next.jsのアプリをビルドしてAWSにデプロイするためのビルドのアーティファクトを、Next.js側で先に内部側で生成しています。
これをやらないと、Next.jsでビルドをローカルでやらないとできないなどの不都合が出てくるので、忘れずに設定するようにしてください。
(スライドを示して)設定した後、ローカルでアプリを試したい場合は、Next.js側のコマンドでNext.jsをローカルで動かせばOKですし、AWSにデプロイしたくなったらCDKコマンドでデプロイなどをすれば、それで使えるようになります。
続いて、Secrets Managerの話です。Serverless Next.jsで、なおかつStripeなどの外部のSaaSを使う場合の話になりますが、特にStripeに関しては、フロントエンド用の公開可能キーとシークレットAPIキーという2つがデフォルトで用意されています。シークレットAPIキーは、サーバー側で利用するキーです。
これは顧客情報やサブスクリプションのデータや、(漏洩などしたら)かなりまずい情報にもアクセスできるキーなので、Gitでコミットすることはもちろんのこと、AWSのシークレットと同じように、かなり厳重に扱う必要があります。
公開可能キーは名前のごとくフロントエンドで使われる前提になっていて、カードのトークン化をしたらそのトークンが自分のアカウントに送られるだけなので、持っていかれることもなく、改ざんされることもないので、コミットしてもいいです。
テストと本番の切り分けの時に必要になるので、コミットではなくても、envファイルなどにホストしてもいいかなとは思います。
もし、厳重に管理されたい方は、Stripeはカスタマイズ可能なシークレットAPIキー相当である、「どのリソースにアクセスできて、これにはアクセスさせない」という設定ができ、ユーザーごとに発行できる制限付きキーもあるので、こちらを使うのもよいかと思います。(キーは)3種類ありますが、特にシークレットAPIキーは、最低限AWSを利用している場合でも安全に管理する必要があります。
あとはServerless Next.jsを使った場合、デプロイ先のランタイムは実行環境がLambda@Edgeになってしまうので、そもそも環境変数で埋め込めません。
(スライドを示して)そのため、原則としておすすめするのはSecrets Managerを使うことです。ただ、こちらはAPI呼び出しに対する課金になるので、もしかするとビジネスの規模によっては、ローカルでもバンバン叩かれ始めるとしんどいと思われる方もいるかもしれません。
コスト面が厳しい場合は代替案として、先ほど紹介した制限付きのキーで万が一漏れても被害が最小限になるようにした上で、Secrets ManagerのParameter StoreでSecure Stringを使ってホストするやり方もあるかなと思います。
コードベタ打ちであったり、なにかしらの環境変数で開発者それぞれのPCにAPIキーをばらまくやり方よりは、Secrets ManagerかSystems Managerを使ってやるほうがよいかなと思います。もちろんSystems Managerでも使えますが、安全性、監査を考えるとSecrets Managerのほうがよいかと思います。
(スライドを示して)Secrets Managerへのアクセスを設定して行う場合は、CDKでPolicyStatementを追加する必要があります。PolicyStatementの書き方は通常どおりのCDKの書き方でできますが、NextJSLambdaEdgeでできるものとして、プロパティとして複数のLambda@Edgeが登録されています。
Secrets ManagerにアクセスしたいLambda@Edgeに対して、それぞれaddToRolePolicyを設定する必要があるので、もし設定したのにエラーが出ている場合は、ここに載っているコード以外のLambda@EdgeでaddToRolePolicyを設定する必要がある可能性もあるので、そこは注意してください。
あとは、呼び出し側もSecretsManagerのインスタンスを立てて、getSecretValueとしてやるだけです。
(スライドを示して)CloudFrontのキャッシュ設定カスタマイズも、先ほどと同じように戻り値の中にnextLambdaCachePolicyがあるので、ここに対してCDKでCachePolicyを書くと、独自のCachePolicyを上書きできます。
これ以外にも、いろいろなプロパティがこの戻り値の中に入っているので、TypeScriptもしくはJavaの型付き言語であれば型の定義をかけることで、どういうものがあるか、どういうものが上書きできるかを追いかけられると思います。
ただ、一部だけ上書きしたいとなると、チェーンがけっこう長くなったり、もしくはreadOnlyが付いていると書けなくなるかもしれないので、使う場合は全部手で書くぐらいのつもりで始めたほうが「やはりできませんでした」という事態にはなりにくいかなと思います。
型定義を読むのがしんどい方は、cdk synthでCloudFormationのスタックをYAMLで吐き出してそちらを読むという手や、デプロイして設定を見るやり方もできるので、試してみてください。
もちろんAmplifyでもけっこうできることはあるので、このあたりも比較対象、比較検討の項目に挙げるといいかなとは思います。
最後にACM(AWS Certificate Manager)の設定です。先ほどのは戻り値を上書きするやり方をしていましたが、ドメインに関する設定や、内部でログをするのか、キャッシュヘッダーについてなど、ある程度Serverless Next.jsをリリースしているチームが想定しているものは、Constructの第3引数で上書きできます。
ただ、withLoggingやwhiteListedHeadersでかなりシンプルに、書きやすいようになっている半面、CloudFormationがどう変わるのかは、コードを追ってみるか、synthもしくはdeployしてみないとわからない部分にはなってきます。
実際に導入する前は、テスト環境などを用意して、どういうふうに変わるのかを一度検証したほうが安全かなと思います。
というところで、まとめです。CDKを使うとNext.jsのアプリとAWSがかなり連携しやすくなるし、App Runner、Amplifyと、加えてCDKという選択肢も入ることで、かなり柔軟性もできるかなと思います。ただ、Serverless Next.jsでCDKを使った場合は、Lambda@Edgeがかなりの数登場してくるので、ここについてだけは要注意です。
だから、CDKを使ってAWSをフルフルに使いたい場合はServerless Next.jsですが、「ちょっとそういうのはうちのチームに厳しいな」という場合は、Amplifyを検討したり、そもそもAWSを使わないならVercelを使う選択肢もあります。
ただ、AWSに関しては、始めることもやめることもしやすいのはServerless Next.jsだと思うので、このあたりを使ってAWSのリソースをガンガン使う開発をやっていくといいのではないかなと思います。以上です。ありがとうございました。
吉田真吾氏(以下、吉田):ありがとうございました。
新居田晃史氏(以下、新居田):ありがとうございました。
吉田:Lambda@Edgeに載せた時、ある程度スケーラビリティがあったり、いろいろなところからアクセスする時に、性能的な面はどうなんですか?
岡本:使っている印象としては、「ああ、Lambda@Edge使っているな」みたいな感じはないというか、「Next.jsのアプリだな」という感じなので、そんなに気にならないかとは思います。
吉田:逆に言うと、ギュンギュンに速くなる感覚も別にそんなにない感じですか?
岡本:個人で使っているだけなので、そう(感じるの)かもしれないですね。ただ、理論上は「Edge LocationでNext.jsが動く」という考え方で、東京に置いたApp RunnerでNext.js動かしているところに対して、USからアクセスすることを考えると、Lambda@Edgeのほうが早いかなとは思います。
吉田:なるほど。100ミリセカンド、200ミリセカンドみたいなターンアラウンドタイムを気にするところがあればというところはありますよね。
岡本:そうですね。
吉田:なるほど。新居田さん、質問は来ていますか?
新居田:そうですね。「Next.jsとCDKは同時に使いたい」という背景を聞き逃してしまった人もいるようなので、もう1回そのあたりのモチベート的なところを聞かせてもらえるといいかなと思います。
岡本:そうですね。もう身も蓋もありませんが、CDKを使いたかった時に手元にNext.jsがあったということです。個人でWebサイトを作ったりしているのですが、確かAmplifyだとキャッシュの設定かなにかでやりたいことができなくて、ほかの方法を探した時にServerless Next.jsが出てきて、調べてみるとCDKでできるから、「じゃあCDKを試してみよう」と始めたという背景です。
新居田:ありがとうございます。やれる手段を探した時に行きついたという感じですね。
岡本:そうですね。あとは、個人的には全部コードで管理したい派なので、Amplify Consoleはあまり使いたくなかったということもあります。
吉田:なるほど。ちなみにNext.jsのいろいろな機能をフルで使うとしたら、先ほどのLambda@Edgeに載せる機能的なLambdaは4種類で十分ですか?
岡本:自分がコードを読んだ範囲では、4つで行けているみたいです。できるだけNext.jsをそのままで動かしたいという思いがあるのかなと個人的には思っています。
ただ、画像の最適化や、アプリ側でやるキャッシュの再生成みたいなバッチ的なジョブに関しては裏側でできないので、それぞれ専用のLambdaを作ります。APIに関しても、たぶん分けたほうがいい理由がなにかしらあって分けたんだと思います。
分かれると逆に管理が面倒くさいし、あまり増えることはないのではないかなと思います。
吉田:了解です。藤井さんはいかがですか?
藤井貴昭氏(以下、藤井):私も「ふんふん」と聞かせていただきました。ありがとうございます。
岡本:いえいえ。しゃべりたい内容をひたすらしゃべってしまって(笑)。
(一同笑)
吉田:(これまでの話と)関係ないけれど、Stripeの各種機能を操作可能なAPIキーと、アカウント側のAPIキーと合わせて使わないと復号できない、合わせ鍵のようなAPIキーの考え方というか、使い分けにはけっこう需要がありますよね。
岡本:ありますね。
吉田:メチャクチャいいよね。そういう実装になっていると、絶対にフロントから使いやすいよね。
岡本:そうなんですよね。ただあれは、たまにごっちゃにされるので、サンプルの書き方はムチャクチャ気を使います。
吉田:間違ってもサーバー上のデータ全部を開けられるキーを書いてはダメと。
岡本:一応、StripeのAPI側もシークレットAPIキーを欲しいところに公開可能キーを入れる、もしくは逆をしたら、エラーメッセージで「お前、キー違うぞ」とは言ってきます。
ですが、環境変数に設定する時の名前を間違えたり、間違えてコミットしてしまったら、IAMと一緒で気づいた時に再生成すればいいです。
吉田:桁数とかも一緒?
岡本:長さは数えたことはないのですが、だいたい同じですね。ただプレフィックスが違います。
吉田:なるほど。パッと見て、「危なっ!」みたいなのはわりとありますか?
岡本:公開可能とシークレット、あと本番とテストとあるので、コピーして貼り付ける時に初めの5文字は絶対に確認します。
吉田:Stripeを使う人はCDKは関係ないですが、そういうところも注意しましょう(笑)。
岡本:本当はこの話も含めて、もっといろいろな話もできたらいいなと思ったのですが、今回はNext.jsに寄り過ぎてしまいました。
吉田:また機会を作りましょう。
岡本:ぜひよろしくお願いします。
吉田:今日はありがとうございました。
岡本:ありがとうございました。
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05