ALB + Lambdaでお手軽3分ベーシック認証

## 概要

ALBのリスナールールの変更とLambdaの追加でベーシック認証を行います。

ベーシック認証の処理の流れとしては以下となります。

- ALBで`Authorization`ヘッダーを検証する
- 認証OKであれば、正規のターゲットグループに転送する
- 認証NGであれば、Lambdaをターゲットとするターゲットグループに転送する
- Lambdaではベーシック認証を要求するレスポンスを返す(なお、ALBからのヘルスチェックに対しては`200`を返すようにします)

## 1. Lambda関数の作成

まず、ALBが存在するリージョンで、Lambda関数を作成します。

- `一から作成`を選択
- 関数名を入力(今回は`BasicAuth`とします)
- ランタイムは`Node.js 12.x`を選択
- 実行ロールは`基本的な Lambda アクセス権限で新しいロールを作成`を選択
- VPCは特に何も選択しない
- `関数の作成`ボタンを押下

![Lambda関数の作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/ed63e1ff-c116-c2d3-8e73-a3b7b28d4f19.png)

- `index.js`に以下のコードを貼り付けて、`Deploy`ボタンを押下

`Authorization`ヘッダーの検証はALBで実施するため、コード中には検証処理はありません。

```js
exports.handler = async (event, context) => {
    const headers = event.headers || {};
    
    // ALB Health check
    if (headers['user-agent'] === 'ELB-HealthChecker/2.0') {
        return {
            statusCode: 200,
            statusDescription: '200 OK',
            isBase64Encoded: false,
            headers: {
                'Content-Type': 'text/html'
            }
        };
    }

    return {
        statusCode: 401,
        statusDescription: '401 Unauthorized',
        body: 'Unauthorized',
        isBase64Encoded: false,
        headers: {
            'WWW-Authenticate': 'Basic',
            'Content-Type': 'text/html'
        }
    };
};
```

![コードの貼り付けとDeployボタン押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/ae0980e5-0972-2414-e3a9-3204224ce36b.png)

## 2. ターゲットグループの作成

先ほどのLambda関数をターゲットとするターゲットグループを作成します。

### 2.1. 基本的な設定等

- ターゲットタイプに`Lambda関数`を選択
- ターゲットグループ名を入力(今回は`basic-auth`とします)
- ヘルスチェックの有効化を`チェック`
- `次へ`ボタンを押下

![ターゲットグループの作成1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/a7a6e304-3bd3-d758-3191-f77de12881b0.png)

### 2.2. ターゲットの登録

- 先ほど作ったLambda関数を選択
- `ターゲットグループの作成`ボタンを押下

![ターゲットグループの作成2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/a078913c-1239-a7da-22f0-0f97294dd3c6.png)

## 3. ALBのリスナールールの編集

### 3.1. ルールの表示/編集

- ALBの`リスナー`タブを選択し、`ルールの表示/編集`を押下

![ルールの表示/編集](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/acf221b8-74ba-b672-b84f-309f0c9b0bf5.png)

### 3.2. ルールの挿入

- 画面上部の`+`ボタンを押下
- `ルールの挿入`を押下
- `IF`の箇所で`HTTPヘッダーを選択
    - ヘッダーに`Authorization`を入力
    - 値に`Basic {ID:パスワードをBase64エンコードした値}`を入力(`Basic`の次にスペースを入れること)
    - Base64エンコード方法は以下を参照(IDが`hogehoge`, パスワードが`fugafuga`の場合)

```console
$ echo -n 'hogehoge:fugafuga' | base64
aG9nZWhvZ2U6ZnVnYWZ1Z2E=
```

- `THEN`の箇所で、転送先として正規のターゲットグループを選択
- `保存`ボタンを押下

![ルールの挿入](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/0458fb86-5149-cfe7-b74f-f891422170ca.png)

### 3.3. 最後のルールの転送先をLambda関数にする

- 画面上部のペンのアイコンを押下
- 最後のルールの左側に表示されているペンのアイコンを押下
- `THEN`に表示されているペンのアイコンを押下
- 転送先として先ほど作成したターゲットグループを選択
- `更新`ボタンを押下

![最後のルールの転送先をLambda関数にする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/43185762-e466-e05d-6c12-af8051bf2b0a.png)

## 4. ベーシック認証の表示確認

以上の設定を終えて目的のサイトにアクセスすると、ベーシック認証がかかるようになります🎉

![ベーシック認証の表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/9ebec3ce-74c8-7374-512b-c4b7d47b96be.png)

## 参考

- [Application Load BalancerとAWS Lambdaでベーシック認証をかけたコンテンツを作成する | Developers.IO](https://dev.classmethod.jp/articles/reinvent2018-alb-and-aws-lambda-basic-auth/)