インフラエンジニアが一切コードを書かずにWebサーバーに認証機能を実装した話
コンニチハ、千葉です。
AWSのサービスを組み合わせれば、独自の認証基盤を構築できます。例えば、WordPressを限定的に公開する、Apache、 Nginx、カスタムWebアプリなどなど、簡単に認証をかけたい場合、ベーシック認証は昔から利用されてきました。ただし、これはスケーラビリティや運用面でどうしてもつらい場面がでてきます。
そこで、ALBに素敵すぎる組み込みの認証機能が追加されたのでこちらを利用し、コードを一切書かずに認証を導入します。また、OIDCなど認証プロトコルに対応していますが、今回はシンプルにCognitoのユーザープールを利用し、ユーザー管理自体もCognitoに任せます。
要件
今回の想定する要件です。
- Nginxを社内ユーザーのみに公開
- スタンドアローンのユーザープールを用意(AD、OICD、SAMLなどによる連携なしで、独自でユーザーを管理)
- ユーザーは管理者が追加する(社内ユーザーだけのアクセスを想定)
- パスワード忘れたとかはユーザーでリセットできる
構成
こんな感じです。シンプルです。ALBへのアクセス時に、Cognitoと連携して認証を行います。認証されてないユーザーは、Cognitoのログイン画面にリダイレクトされ、ログインできればALB配下のEC2上のコンテンツにアクセスできるようになります。
やってみた
Cognitoユーザープールの作成
ユーザープールを作成します。今回は、外部連携なしで管理者がユーザーを登録していくことを想定しています。
プール名を入力し、ステップに従って設定するをクリックします。
今回は、一般的にEメールを想定した認証を選択します。必須の属性を指定できますが、今回はシンプルにメールアドレス+パスワードだけあればいいので特にチェックせずに進みます。
今回は、勝手にユーザーを作成せずに、管理者がユーザーを追加する運用にします。「管理者のみユーザーの作成を許可する」を選択します。他のパラメータはセキュリティポリシーにより設定しましょう。
MFAを有効にすると、セキュリティを向上できますが、今回はオフにします。また、ユーザーのメール検証を有効にします。これは、パスワード忘れた時にユーザーが自身でパスワードリセットできるようにするために必須です。あとはSMS用のIAMロールを作成します。
Eメール検証時のメッセージ、ユーザー招待メッセージ(管理者がユーザー登録時に送付される)を設定します。これを設定しないと、何のサービスか不明で、受け取ったユーザーは混乱するので設定しておきましょう。また、送信メールアドレスをカスタマイズできますが今回は社内用のためデフォルトのままいきます。
今回はタグ設定はしないので、そのまま次に進みます。
セキュリティ強化として、ユーザーが利用しているデバイスを追跡できますが今回は利用しないのでいいえを選択し、次に進みます。
クライアントを追加します。クライアントは、今回はALBになります。ALBはクライアントとして今回作成したユーザープールを利用します。ALBがCognito連携できるようにクライアントシークレットを発行します。ALBはシークレットキーを利用し、Cognitoにアクセスします。
クライアントが作成されました。次のステップに進みます。
認証に関する挙動をLambdaを利用してカスタマイズできます。今回の要件としては不要なのでスキップします。
設定内容を確認し、プールを作成します。
これで、Cognitoユーザープールが作成できました。
アプリクライアントの設定
作成したクライアントアプリの設定を行います。具体的には、クライアントアプリがどのIDプロバイダ(Congnitoユーザープールなのか、はたまた外部のOIDCなのか)を利用するか、認証後のコールバックのURL、利用するOAuth 2.0のフロー、スコープを設定します。前提知識としてOAuth 2.0が必要になりますが、ちょっと調べてみてください。私が読んだ情報は末尾の参考にまとめてます。
IDプロバイダは、先ほど作成したCongnitoユーザープールを指定します。コールバックURLには https://<ELBに設定するドメイン>/oauth2/idpresponse
を入力します。OAuthの認証フローは複数ありますが、ALBの場合はAuthorization code grantを選択し、スコープはopenidを選択します。
ドメイン名の設定
Congnitoで利用するドメインを設定します。このドメインは、ログイン画面やパスワード変更などでアクセスで利用されます。自分が所有するドメインも設定できますが、今回はCognitoドメインを利用します。
ユーザーを発行する
テストで利用するユーザーを発行しましょう。大量のユーザーを登録する場合はCSVでのインポートのも可能です。今回は、手動で1アカウントを発行してみます。
ユーザー名、Eメールにメールアドレスを入力します。本来のフローですと、Eメール検証を行いますが、事前に知っているメールアドレスを登録するので、Eメール検証をスキップします。 また、ユーザーにユーザー追加したよメールを送信するために、「招待を送信しますか?」にチェックを入れます。仮パスワードも入力しましょう。
ユーザーを追加すると、追加したメールアドレスに登録したよメールが届きます。文面はカスタマイズできるので、適宜カスタマイズしましょう。
ALBの作成
Cognito側の設定が完了したので、ALB側の設定をします。 前提としてALBを作成し、リスナーにはHTTPSを作成しておきます。証明書にはACMを利用しました。また、ターゲットとしてEC2(Nginx)を登録しておきます。
リスナーに認証の設定をします。
アクションで認証を追加します。
作成したCongnitoユーザープール とアプリクライアントを指定し、保存します。
ALB側の設定は以上です。
動作確認
Webへのアクセス
設定が完了しました。実際にALBにアクセスしてみましょう。ログインが表示されました。
ログインすると、初回なのでパスワード変更を促されます。
新しいパスワードを入力すると、EC2上のNginx画面が表示されました!問題なくログインできました。
最後に
一切コードを書かずに、ユーザー認証機能を追加できました。OpenID Connectの知識が必要だったりしますが、慣れてしまえば結構簡単に設定できました。ALB + Cognito最強です。