Streamlitを使ったPythonアプリに認証を付けてAWSにデプロイする
はじめに
Streamlitというライブラリを使ったPythonアプリをAWSにデプロイする手順についてわかりやすくまとめてくださっている、ありがたい記事があります。
上記記事の通りにデプロイしたあと、次のステップとして以下が挙げられていたので取り組んでみました。
- Route 53などで独自ドメインを取得し、ACMの証明書をALBに設定してHTTPSで暗号化通信できるようにする。
- Cognitoで認証機能を導入して、セキュリティグループによるソースIP制限を不要にする。
上記に取り組むことでセキュリティが強化され、社内の方にも使っていただけるようになると思いました。
概要
作成するアーキテクチャ
複数のユーザーが共通のメールアドレスとパスワードでアプリにログインできるようにします。

作業環境
端末:Macbook(Appleシリコン)
ブラウザ:Google Chrome
コードエディター:VS Code
Python:3.9以降のバージョン
前提
上記記事まで作成が完了している状態でした。
また、次の「手順」に進む前に、ドメインの購入とRoute53へドメインの登録が必要です。
Route53でドメイン購入・登録する手順はこちらが参考になると思います(最も安くて年間で3ドルかかるみたい)。
今回僕は、弊社のAWSのサンドボックス環境内に自由に使えるドメインが用意されていたため、それを使いました。
(AWSを自由に使えることに魅力を感じて入社されたいと思っていただいた方は、ぜひ弊社の採用サイトからご応募ください!)
手順
1. ACMでの証明書発行
検索バーにACMと入力し、AWS Certificate Managerの画面に遷移後、証明書をリクエストを選びます。


デフォルトで次へ。

Pythonアプリにアクセスする際のドメインを記載して、リクエストを押下します。
完全修飾ドメイン名:bsc.取得したドメイン

証明書IDを押下します。

Route53でレコードを作成を押下後、デフォルトのままレコードを作成を押下します。

Route53の画面に移動し、ホストゾーン>取得したドメイン名と押下していきます。
上記で指定した完全修飾ドメイン名をレコード名に含み、タイプがCNAMEとあるレコードが追加されていれば、ここまでOKです。

2. ALBの証明書の設定
検索バーにloadと入力してロードバランサーを押下し、EC2のロードバランサーの画面に移動します。
bsc>リスナーの追加と押下していきます。
以下の通り設定し、追加を押下します。
- プロトコル:
HTTPS,443 - アクションルーティング:ターゲットグループへ転送
- ターゲットグループ:
bsc - 証明書の取得先:
ACMから - 証明書(ACMから):
bsc.取得したドメイン名

ALB(bsc)のリスナーとルールにHTTPS:443の行が追加されます。
次に、ALB(bsc)のリスナーとルールの画面から、HTTP://80にチェックを入れ、リスナーの管理>リスナーの編集と押下していきます。
以下の通り設定し、変更内容の保存を押下します。
- アクションのルーティング:
URLにリダイレクト - プロトコル:
HTTPS,443
これは、http://bsc.取得したドメイン名でアクセスしてもhttps://bsc.取得したドメイン名にリダイレクトするための設定になります。

次に、ALB(bsc)の画面でリスナーとルールからセキュリティにタブを切り替えて、bsc-sg-albのセキュリティグループIDを押下します。
画面遷移後、インバウンドルールを編集を押下します。

ルールを追加を押下し、以下の通り設定後、ルールを保存を押下します。
- タイプ:
HTTPS - ソース:
マイIP
3. Route53でのドメインとALBの関連付け
Rote53の画面に移動し、ホストゾーン>取得したドメイン名と押下していきます。
レコードを作成を押下します。

シンプルルーティングを押下して次へ。
※ここで下記画面になっていない場合は、ウィザードに切り替えるを押下すると同様の画面になると思います。

シンプルなレコードを定義を押下します。

以下の通り設定してシンプルなレコードを定義を押下します。
- レコード名:
bsc - レコードタイプ:
A - IPv4アドレスと一部のAWSリソースに〜 - 値/トラフィックのルーティング先
- Application Load BalancerとClassic Load Balancerへのエイリアス
- アジアパシフィック(東京)
- 上記記事で作成したALBのものを選択
上記で完全修飾ドメイン名をレコード名とし、タイプがAとあるレコードが追加されていれば、ここまでOKです。

これでWebブラウザから、https://bsc.取得したドメイン名またはhttp://bsc.取得したドメイン名でアクセスすると、アプリ画面が表示されると思います。

4. Cognitoの設定
検索バーにcognitoと入力してCognitoを押下し、Cognitoの画面に移動します。
ユーザープール>ユーザープルを作成と押下していきます。

以下の通り設定し、ユーザーディレクトリを押下する。
- アプリケーションタイプ:
従来のウェブアプリケーション - アプリケーションに名前を付ける:
bsc - サインイン識別子のオプション:
メールアドレス - リターンURL:
https://bsc.取得したドメイン名/oauth2/idpresponse
概要に移動を押下する。
ユーザープールの概要画面に遷移したら名前変更を押下して、ユーザープール名をbscに変更します。

ユーザープールの概要画面左のメニューから認証>サインアップと押下していきます。
セルフサービスのサインアップで編集を押下し、自己登録を有効化のチェックを外すことで、ユーザーが自らアカウントに登録できないようにします。
ユーザープールの概要画面左のメニューからユーザー管理>ユーザー>ユーザーを作成と押下していきます。
以下の通り設定し、ユーザーを作成を押下します。
- 招待メッセージ:
招待を送信しない - Eメールアドレス:任意のもの。実在しないものでも可。
- 仮パスワード:パスワードの設定
- パスワード:任意のもの。
EC2のロードバランサーの画面に移動し、bscを押下します。リスナーとルールのHTTPS:443にチェックを入れ、リスナーの管理>リスナーの編集を押下します。
以下の通り設定し、変更内容の保存を押下します。
- OpenID または Amazon Cognito を使用する:チェックを入れる
- アイデンティティプロバイダー:
Amazon Cognito - ユーザープール:
bsc - ユーザープールドメイン:自動選択
- アプリケーションクライアント:
bsc
https://bsc.取得したドメイン名にWebブラウザからアクセスすると認証画面が表示されます。上記で設定したメールアドレスとパスワードでログインし、Pythonアプリの画面が表示されます。

ALB(bsc)の画面でリスナーとルールからセキュリティにタブを切り替えて、bsc-sg-albのセキュリティグループIDを押下します。
画面遷移後、インバウンドルールを編集を押下します。
ソースをAnywhere-IPv4にして保存すると、他の人もアクセスできるようになります。

おわりに
ここまでご覧いただきありがとうございました。
何か問題のある設定があれば優しく教えてください。
参考
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion
こんにちは
今年からAWSに触り始め社内用にRAGを構築してみたいと思い、こちらのブログを閲覧させていただきました。
AWS初心者なりに実装を進めているのですが、初めに記載しているQiitaで既に詰まってしまい可能であれば何かアドバイスをいただけると幸いです。
手順通りにAWSにデプロイを行い、ALB経由でアプリを起動した際にWebSocketエラーが発生してしまいます。
やはりIPの直叩きではなく、T-KNDさんの様にドメイン名を取得しなければいけないのでしょうか?
@mikanbako13 さん
記事の閲覧とコメント、ありがとうございます!!
ドメインを取得しなくても、引用しているQiita記事の内容は進められるかなと思います!
まずは、上記のQiita記事に沿ってデプロイしてマイIPの直叩きでアプリを表示できるかまでをご確認いただいた方が良い気がしますね!
ご返信ありがとうございます!
やはりそうなのですね、、、
websocketの部分がどうしても上手く動作していないようです。
もろもろ設定いじくりまわして試しているのですがダメでそうです。
出来ればコンテナ化したかったのですが、EC2も視野に入れてやってみます。