概要
- AWS AmplifyのアプリケーションにBasic認証をつけたい
検討した選択肢
- Option A: AWS Amplify Access Control(環境変数)
- Option B: AWS Amplify Access Control(CfnParameter)
- Option C: Next.js Middleware による認証
- Option D: CloudFront Functions による認証
- Option E: Amazon Cognito による認証
選択肢を図にすると以下のようになる。
CloudFront Functionsが使えればBasic認証に加えて、その他の細かい設定も可能だったのだが、AmplifyのCloudFrontにはCloudFront Functionsは使えないらしい。
AmplifyのAccess Controlを使う
Next.jsのMiddleware、Cognitoを使った認証もできるが、できるだけユーザー側で認証をかけたいので用意されているAmplifyのAccess Controlを使う。
Access Controlは追加料金の記載がないので無料と考えられる。(Basic認証で弾いたリクエスト数に応じた従量課金が発生するかは不明)
CDKで実装する
以下の2つを考える。
- Option A: AWS Amplify Access Control(環境変数)
- Option B: AWS Amplify Access Control(CfnParameter)
パスワードという機密情報を扱うため、パラメータストアやSecrets Managerから呼び出すのが筋だが、L1コンストラクタのため平文でしか指定できない。
環境変数を使用してもBasic認証の情報を設定するとテンプレートに平文で保存されてしまう。
ちなみにaws-amplify-alphaではSecrets Managerにパスワードを生成して使用できるらしい。
alphaはバージョンアップの際にコードが変わるので今回は使用しなかった。
https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_aws-amplify-alpha.BasicAuthProps.html
環境変数を使う
以下のようなコードであれば環境変数経由でユーザー名とパスワードを指定できるので、これらの認証情報は(適切に管理していれば)問題ないはず。
const username = process.env.BASIC_AUTH_USERNAME;
const password = process.env.BASIC_AUTH_PASSWORD;
basicAuthConfig = {
enableBasicAuth: true, username, password
}
しかし上のコードで生成されるテンプレートには平文で埋め込まれてしまう。
Resources:
MyApp:
Type: AWS::Amplify::App
Properties:
BasicAuthConfig:
Username: "user" # ← 平文でテンプレートに保存
Password: "password" # ← 平文でテンプレートに保存
CfnParameterを使う
CfnParameterのnoEchoプロパティをtrueにするとパラメータ値をマスクすることができる。
const usernameParam = new cdk.CfnParameter(this, 'BasicAuthUsername', {
type: 'String',
description: 'BASIC_AUTH_USERNAME',
noEcho: true
})
const passwordParam = new cdk.CfnParameter(this, 'BasicAuthPassword', {
type: 'String',
description: 'BASIC_AUTH_PASSWORD',
noEcho: true
})
basicAuthConfig = {
enableBasicAuth: true,
username: usernameParam.valueAsString,
password: passwordParam.valueAsString
}
}
テンプレートで以下のように表現される。
Resources:
MyApp:
Type: AWS::Amplify::App
Properties:
BasicAuthConfig:
Password: !Ref BasicAuthPassword
Username: !Ref BasicAuthUsername
Parameters:
BasicAuthUsername:
Type: String
Description: BASIC_AUTH_USERNAME
NoEcho: true
BasicAuthPassword:
Type: String
Description: BASIC_AUTH_PASSWORD
NoEcho: true
CDKコマンド実行時は、以下のようにparametersオプションを設定する必要がある。
cdk deploy --parameters BasicAuthUsername=$BASIC_AUTH_USERNAME \
--parameters BasicAuthPassword=$BASIC_AUTH_PASSWORD
設定忘れ防止のため、これらの値が未指定だったらbasicAuthConfigの指定をしないようif文を仕込んでおいたほうがいい。
// cdk.jsonにBasic認証を使用するかのフラグを設定する
const useFrontBasicAuth = this.node.tryGetContext('useFrontBasicAuth') || false
// 環境変数から値を読み込む
const username = process.env.BASIC_AUTH_USERNAME
const password = process.env.BASIC_AUTH_PASSWORD
let basicAuthConfig
if (useFrontBasicAuth && username && password) {
const usernameParam = new cdk.CfnParameter(this, 'BasicAuthUsername', {
type: 'String',
description: 'BASIC_AUTH_USERNAME',
noEcho: true
})
const passwordParam = new cdk.CfnParameter(this, 'BasicAuthPassword', {
type: 'String',
description: 'BASIC_AUTH_PASSWORD',
noEcho: true
})
basicAuthConfig = {
enableBasicAuth: true,
username: usernameParam.valueAsString,
password: passwordParam.valueAsString
}
}