なるべく安く楽に運用したいJAWSDAYS2024ティザーサイトの話

この記事は [AWS Community Builders Advent Calendar 2023 シリーズ2](https://qiita.com/advent-calendar/2023/aws-community-builders) の19日目の記事となります。

## はじめに

こんにちは。JAWS DAYS 2024の実行委員をやっています、米澤です。
当初はサイト構築＋コンテンツ企画をやる予定だったのですが、気付けばスポンサー様のQA対応/申し込み管理であったり、CFX周りの準備をしていたりと、例の如く ~~実行委員長にこき使われて（これはプロレスです）~~ 何でも屋をやっています。

さて、今回の記事では先日オープンした[JAWSDAYS2024ティザーサイト](https://jawsdays2024.jaws-ug.jp/)の裏側について記載したいと思います。

## 構成オーバービュー
早速本題ですが、JAWSDAYS2024のティザーサイトは下記のような構成で運用しています。

![Screenshot 2023-12-19 at 1.42.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290494/89456d43-d47d-f6ba-41e1-1538b3398414.png)

フロントエンドのフレームワークには[Next.js](https://nextjs.org/)を、UI周りは[ChakraUI](https://chakra-ui.com/)を採用しており、SSG(Static Site Generation)でS3バケットに静的ファイルを
配置しています。なお、ChakraUIはレスポンシブ対応が非常に簡単で、ストレスなくPC版/SP版の構築ができました。ティザーサイト、スマホ閲覧にも対応してますので、ぜひ御覧ください。
（実は、アクセス比率が PC:SP=4:6 だったりと、SPユーザーが結構多いです。やってて良かったレスポンシブ）

また、バックエンド部分(API-GW、Lambda、DynamoDB)はCDK on TypeScriptしており、フロント部分のNext.jsと型定義を共用するためにMonorepoにてリポジトリを構成しています。

実はティザーサイト、頻繁に微修正をかけているということもあり、CI/CDも整備してGitHub Actionsでデプロイ周りの作業はすべてパイプライン化しています。
今回はリリース用のブランチ（Dev環境/Prod環境）にマージコミットを入れると、デプロイ先環境(Dev/Prod)/フロントエンド/バックエンド に応じて自動的にビルド〜デプロイが走るようになっています。

## 工夫したところ
ここからは、ティザーサイトを運用するに当たって工夫しているポイントを記載します。

### 米澤SPOF問題の回避
ティザーサイトには、DynamoDBをデータソースとして情報を表示するページとして下記の2つがあります。
- [Homeページ>News](https://jawsdays2024.jaws-ug.jp/)：参加者向けNewsやURLリンクを掲載
- [FAQページ](https://jawsdays2024.jaws-ug.jp/faq/)：運営に寄せられた問い合わせを掲載

NewsやFAQを掲載するためには、JAWSDAYS2024用に払い出されたアカウントにログインしてDynamoDBにレコードをInsertする必要があります。
現状、アカウントにアクセスできる運営メンバーは米澤1人であるため、万が一米澤が趣味の格闘技で両腕骨折してしまった場合、いろいろと詰んでしまいます。
また、JAWSDAYS2022でも多くのNewsが掲載されていたことを踏まえ、JAWSDAYS2024運営メンバーがセルフサービスでニュース情報を 登録/削除/修正 できるようにするべしと考え、News/FAQ管理ページを別途作成しています。
IAM Identity Centerでアカウントに入ってDynamoDBにレコードを登録してね、という運用でも回らないことはないと思うのですが、やはりJSONの生データ登録や、（諸事情があって）複数環境が混在しているアカウント内リソースの操作は中々に心理的ハードルが高いものです。
下記画像のようなインタフェースを別途用意することで、環境間の越境操作防止（CognitoやLambdaにアタッチしているIAMロールの権限で制御）も実現できますし、なにより、運営メンバーのオペレーションがより簡単になったのではないかなと思います。
（構成オーバービューには記載していませんが、この仕組みを実現するためにCognitoを利用したAPI保護や[AmplifyのUIライブラリ](https://ui.docs.amplify.aws/react)を利用しています。）

![Screenshot 2023-12-19 at 2.19.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290494/888116d9-2f5d-9b5f-ebfc-0d086359b808.png)


### GitHub Actions ↔ AWS環境の繋ぎ込み
GitHub Actions経由でCDKリソースやS3バケットの中身を操作したい！となると、真っ先に思い浮かぶ繋ぎ込み方式が「アクセスキー」ではないでしょうか？
しかし、よく鍛錬されたAWS Builderであれば、アクセスキーと聞くとゾッとしてしまうのではないでしょうか？
個人的な思いとして、「VPCゼロ、EC2ゼロ、アクセスキーゼロ」を掲げていたこともあり、何か上手いやり口はないか？と模索していたところ、[configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials)なる良さげなソリューションを発見しました。

configure-aws-credentialsを使うことで、GitHubをIdPとして設定し、IAMロールに紐づく一時認証情報をGitHub Actionsに引き渡すことができるという素晴らしいヤツです。
また、[サンプルのCFnテンプレート](https://github.com/aws-actions/configure-aws-credentials?tab=readme-ov-file#sample-iam-oidc-cloudformation-template)も掲載してくれているという優しさ、これは使うしか無い。

上記のCFnをカスタマイズ（デプロイに必要な権限をアタッチ）し、デプロイ先のAWSアカウント上にCFnスタックを構築した上で、GitHub Actionsのワークフロー内で下記のようなstepを記載することで、IAMロールから一時クレデンシャルを取得し、AWSアカウントにアクセスすることができます。

```yaml
jobs:
  deploy:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/XXXX-ROLE
          aws-region: ap-northeast-1

      - name: Get Caller Identity
        run: aws sts get-caller-identity
```

フロントエンド関係のパイプラインでは下記のようなAWSリソース操作を組み込んでおり、リリース用ブランチにマージした後は基本的に放置しておけば、最新版のWEBサイトが自動的にデプロイされる仕組みとなっています。
- E2Eテスト結果のアーティファクトをS3に格納
- ビルドしたNext.jsの静的コンテンツのS3配置
- CloudFrontのキャッシュ削除

## ハマったポイント

ティザーサイト構築当初、とても頭を悩ませたポイントがあります。
そう、SCPです。
JAWSDAYS2024のアカウントはJAWS-UGのOrganizationsから払い出してもらったLinkedアカウントを利用しています。このLinkedアカウントが属するOUにSCPがアタッチされており、非常に悩まされました。

ティザーサイトではCloudFrontのオリジンとしてS3とAPI-GWを設定しています。
CloudFrontの1つ目のオリジンにS3バケットを設定した後、2つ目のオリジンにAPI-GWを設定しようとしてコンソールを操作していたところ、**何故かオリジンに設定できるAPI-GWが1つも存在しない**という事象に遭遇しました。

![Screenshot 2023-12-19 at 3.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290494/dba8b7a5-170b-4344-6c5b-35bf0830535a.png)

特にコンソール上にAccess Denyといったアラートも表示されていなかったこともあり、事象の切り分けに非常に時間をかけてしまいました。

ざっと思い出せる、事象切り分けのためにやっていたことは下記のような内容です。
- バックエンドのスタックを再デプロイしてみる
- CloudFrontをもう一度作り直す
- 同一アカウント、別リージョンにスタックをデプロイしてみる
- 自身に割り当てられているIAMロールの確認
- CloudTrailでDenyされているアクションの確認
- 別アカウントにデプロイしてみる

試行錯誤したところ、別アカウントだと上記の事象が確認できなかったので、SCPでDenyされているのでは？という仮説に至り、SCPがアタッチされていないOUにアカウントを移動してもらい、無事構築が完了しました。
（LinkedアカウントではアタッチされているSCPを確認することができないのでこれもまたハマりを加速させていました）

2021年に[こんなアップデート](https://aws.amazon.com/jp/about-aws/whats-new/2021/11/aws-identity-access-management-efficient-troubleshoot-error/)がありましたが、これ、もっとサービスを拡充してほしいと心から思っています。

個人的な教訓として、明らかにおかしい挙動になった際は、安直ですが「SCPを疑って騒いでみる」が一番手っ取り早いような気がします。笑

![Screenshot 2023-12-19 at 3.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290494/351174df-95b9-b790-09f4-66fb326c3d4b.png)

**2023/12/23追記**
本事象の原因に関するAdvent CalendarをCommunity Builderの木美さんが記載してくださいました。
ぜひご覧ください！

https://imiky.hatenablog.com/entry/2023/12/22/184449

## まとめ
上記以外にも工夫ポイントが色々あったりするのですが、どうしても長くなってしまうので、またどこかのJAWSでお話できればと思います。
ちなみに、タイトルにも記載している「安く」という観点ですが、構築して2ヶ月ほど経過していますが、毎月トータルで約\\$2.5というお小遣い価格で運用しています。内訳はConfigが約\\$1.6、Route53が\\$0.5となっているので、アプリケーションは\\$1もかかっていません。
圧倒的コスパ！サーバレス最高！！

## お知らせ
12/22より、企業サポーター様の募集が開始となります。
池袋をハイジャックしたい皆様、ぜひご応募お待ちしております！
https://jawsdays2024.jaws-ug.jp/supporter/company/