code-server に Kiro CLI と Kiro Crew を同居させ Amazon Cognito で MFA 認証をさせる – アーキテクチャ編

こんにちは、広野です。
以前、code-server を nginx で HTTPS 化して Amazon Cognito で MFA 認証をさせる構成を紹介しました。

本記事では、同じ Amazon EC2 インスタンス上で AI エージェントの Kiro CLI と Kiro Crew を立ち上げる構成を紹介します。アーキテクチャ編です。続編で実装について紹介します。

前回記事からの主な変更点

  • 同じ EC2 インスタンスに、AI エージェントの Kiro CLI と Kiro Crew を同居させました。
  • Kiro Crew のダッシュボードにも、code-server と同じように Amazon Cognito の MFA 認証を実装しました。
  • OS 内のソフトウェアのインストールとセットアップを、EC2 の UserData から AWS Systems Manager (SSM) ドキュメントにカテゴリ分けして移したものがあります。これにより、必要なセットアップだけを選んで実行できるようになります。

背景

  • AWS Cloud9 のような Web IDE を AWS 上に作りたいと考えていました。現時点では、code-server を Amazon EC2 に立てるのが最適と考えました。個人用環境または研修用環境なので、コンテナのような本格的な構成は過剰です。
  • AI コーディングエージェントも入れたいと考えました。CLI ベースの Kiro CLI と、ブラウザで表示する Kiro Crew の両方を、同じインスタンスで動かしたいです。
  • code-server も Kiro Crew も、デフォルトは HTTP で公開され、ユーザー認証の仕組みも弱く、そのままでは実用的ではありません。認証は厳格にしたく、特に MFA は必須です。AWS を使用するなら Amazon Cognito が最初の選択肢です。
  • ALB をかぶせれば HTTPS 化はできますが、個人用インスタンスのためだけに使用するのは過剰です。Amazon CloudFront は Distribution と EC2 インスタンス間の通信を S3 オリジンの OAC のようには厳格にアクセス制限できないので、逆に不安要素が追加されます。そのため、code-server をホストする EC2 インスタンス単体で HTTPS 化する必要がありました。
  • HTTPS 化に自己署名証明書は使用できません。自己署名証明書のサイトにはアクセスできないネットワーク環境があるためです。使用するドメインは Amazon Route 53 パブリックホストゾーンに登録し、証明書は Let’s Encrypt で作成します。ACM で作成した証明書は高額なため、今回の用途には過剰です。
  • 以前の構成では、ソフトウェアのインストールを EC2 の UserData に全部書いていました。これだと、UserData 内のスクリプトでエラーが発生したときに、やり直しがききません。UserData には 16KB のサイズ上限もあります。そこで、OS 内のセットアップを SSM ドキュメントに移し、選択および再実行を可能にしました。

アーキテクチャ

  • ユーザーは、ブラウザから HTTPS で code-server または Kiro Crew にアクセスしようとします。code-server 用と Kiro Crew 用の 2つの URL (FQDN) を用意します。例えば codeserver-example-dev-client01.example.com と kirocrew-example-dev-client01.example.com です。この 2つは Route 53 パブリックホストゾーンに登録されていて、どちらも同じ EC2 インスタンスの Elastic IP アドレスを指す A レコードになっています。それぞれの FQDN に対して、Let’s Encrypt の SSL 証明書を発行し、nginx に登録しています。
  • 安全のため、EC2 インスタンスは、セキュリティグループで指定したグローバル IP アドレス以外からの通信を受け付けないようにしています。
  • HTTPS 通信は nginx が受け取り、SSL を終端します。以降、EC2 内部の通信は暗号化されません。
  • nginx は、アクセスされた URL (server_name) で、code-server 向けか Kiro Crew 向けかを振り分けます。Kiro Crew を code-server のサブパス (code-server のプロキシ機能) で公開せず、専用の FQDN にしているのは、Kiro Crew のフロントエンドがアセットや API のパスを絶対パスで固定しており、サブパスでは動かなかったためです。
  • nginx は、ユーザーが認証済みかどうかを確認するために oauth2-proxy に問い合わせます。認証済みであれば、ユーザーと code-server (または Kiro Crew) を通信させます。認証済みでなければ、認証が必要である旨の画面を返します。
  • ログイン済みでないユーザーは、案内に従って Amazon Cognito マネージドログインの画面で認証 (MFA 込み) を行います。必要に応じてセルフサインアップをします。ログインが正常に完了すると、Cognito マネージドログインは、あらかじめ指定されたコールバック URL (oauth2-proxy の所定のパス) に画面をリダイレクトします。このとき、ブラウザは Cookie に認証済みの情報を持った状態になります。
  • 認証済みのブラウザがリダイレクトされると、nginx 経由で oauth2-proxy が認証状況をチェックし、トークンを取得します。
  • アプリが Cognito ユーザープールと認証の通信をするには、アプリケーションクライアントが必要です。今回の設計では、EC2 インスタンス 1台につき、アプリケーションクライアントを 1つにしています。アプリケーションクライアントにはクライアントシークレットを持たせられ、シークレットを知っているクライアントでないと認証できません。シークレットはその EC2 インスタンスしか知らないので、他のデバイスが同じアプリケーションクライアント経由で認証しようとしても拒否されます。
  • アプリケーションクライアントにはクォータがあり、デフォルトでは 1ユーザープールあたり 1,000 個まで作れます。つまり、管理できる EC2 インスタンスは 1,000 台が上限ですが、本記事の用途では支障ないです。
  • ここまでの設計ですと、Cognito に登録されたユーザーは全員、任意の EC2 インスタンスにログインできてしまいます。今回は個人用環境なので、あらかじめ指定した自分のメールアドレスがユーザーの属性になければ認証を通さないようにします。Cognito ユーザープールの email 属性を、oauth2-proxy の認証チェックの過程で照合します。指定したメールアドレス以外の認証であれば、403 Forbidden 画面が表示されます。
  • code-server と Kiro Crew は、同じ Cognito ユーザープールとアプリケーションクライアントを使いますが、oauth2-proxy は 2つ動かします (code-server 用と Kiro Crew 用)。これは、既存の code-server の認証に手を入れずに Kiro Crew を追加できるようにするためです。Cookie 名を分けているので、2つは独立して動きます。そのため、code-server にログインした後に Kiro Crew へアクセスすると、Cognito のログインが改めて必要になります。
  • Kiro Crew には、dashboard.url の設定が必要です。Kiro Crew は DNS リバインディング対策として Host ヘッダを検査し、許可するホスト名を dashboard.url の設定から導きます。未設定だと localhost 系しか許可されず、独自ドメインでアクセスすると Host header not allowed. (403) になります。dashboard.url に Kiro Crew 用の URL を設定して解決します。
  • Kiro Crew だけは、Cognito 認証に加えて、もう 1段階の認証があります。Kiro Crew 自身が持つトークン認証です。これは外すことができませんでした。Kiro Crew はシェルや AWS CLI を実行できるため、万一 EC2 の内部から直接ダッシュボードのポート (127.0.0.1:5476) にアクセスされた場合に備えた防御です。
  • Kiro Crew のトークンは、EC2 上で kirocrew token コマンドを実行すると得られます。出力された URL (トークン付き) を使ってダッシュボード画面にアクセスします。トークンの有効期限はデフォルトで 20 時間です。Kiro Crew のサービスを再起動すると以前のトークンは無効になるので、取得し直すことになります。1日の継続利用であれば支障ないです。

画面紹介

実際の操作は、以下のようになります。

code-server の URL にブラウザでアクセスすると、まず oauth2-proxy の画面が表示されます。ボタンを押して進みます。

画面が Amazon Cognito マネージドログインにリダイレクトされます。画面デザインはデフォルトです。許可されたメールドメインであれば、セルフサインアップも可能です。

MFA ワンタイムパスワードの入力も求められます。
ログインに成功すると、code-server が表示されます。Kiro CLI はこのターミナルで使用します。
Kiro Crew の URL にアクセスする場合は、code-server で kirocrew token コマンドを実行します。Kiro Crew 画面のトークン入り URL が2つ表示されます。
[ec2-user@ip-192-168-xxx-xxx kiro]$ kirocrew token
http://localhost:5476?token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


https://kirocrew-example-dev-client01.example.com/?token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[ec2-user@ip-192-168-xxx-xxx kiro]$
2つ目の URL にアクセスすると、Kiro Crew の画面が表示されます。Cognito のログインも再度必要になります。

実装の流れ

今回の構成は、3つの AWS CloudFormation テンプレートに分けてデプロイします。

詳細は続編記事で説明します。ここではざっくりとしたデプロイ内容を箇条書きにします。

  • Cognito テンプレート (アカウント共通。1回だけデプロイ)
    • Amazon Cognito ユーザープール
    • Amazon Cognito セルフサインアップ用 Lambda 関数
    • 管理者通知用 Amazon SNS トピック
  • SSM ドキュメントテンプレート (アカウント共通。1回だけデプロイ)
    • SSM ドキュメント 6種類
  • EC2 インスタンステンプレート (開発者ごとにデプロイ)
    • EC2 インスタンス
    • Elastic IP アドレス
    • セキュリティグループ
    • IAM ロール
    • Route 53 レコード
    • Cognito アプリケーションクライアント
    • CloudWatch Logs ロググループ

続編記事

続編記事が完成しだい、こちらにリンクを貼ります。

まとめ

いかがでしたでしょうか。

本記事では、アーキテクチャとその設計思想、背景などを説明いたしました。他にも転用できるナレッジがあると思います。

本記事が皆様のお役に立てれば幸いです。

×
タイトルとURLをコピーしました