動作分析システム MFA導入手順書(Cognito + Angular + Django)
動作分析システム MFA導入手順書(Cognito + Angular + Django)
1. 目的
本手順書では、既存のRedmine認証を廃止し、
AWS Cognito を使用した多要素認証(MFA)へ移行する。
対象システム:
-
フロントエンド:Angular
-
API:Django REST Framework
-
DB:Amazon RDS MySQL
-
実行基盤:EC2 + Docker
-
コンテナ管理:ECR
導入後の認証方式:
-
Cognito Hosted UI
-
MFA(TOTP)
-
JWT認証
-
Bearer Token認証
2. システム構成
@startuml
actor User
rectangle "Browser" {
component "Angular" as FE
}
rectangle "AWS" {
component "ALB" as ALB
component "Cognito\nMFA(TOTP)" as Cognito
rectangle "EC2" {
component "Angular Container" as FEC
component "Django API Container" as API
}
database "RDS MySQL" as RDS
component "Secrets Manager" as Secrets
component "SSM Parameter Store" as SSM
component "CloudWatch Logs" as Logs
}
User --> FE
FE --> Cognito : Login
Cognito --> FE : JWT
FE --> API : Bearer JWT
API --> Cognito : JWT Verify
API --> RDS
API --> Secrets
API --> Logs
@enduml
3. セキュリティ設計
3.1 実施するセキュリティ対策
| 項目 | 内容 |
|---|---|
| MFA | TOTPを必須化 |
| HTTPS | ALBでTLS終端 |
| JWT検証 | issuer / audience / exp検証 |
| DB保護 | RDSをPrivate Subnet配置 |
| SSH禁止 | Session Manager利用 |
| 秘密情報 | Secrets Manager利用 |
| 監査ログ | CloudWatch / CloudTrail |
| Docker | ECR Image Scan有効化 |
4. AWS事前準備
4.1 Secrets Manager作成
保存する情報:
{
"DJANGO_SECRET_KEY": "xxxxxxxx",
"DB_HOST": "xxxxx",
"DB_NAME": "motion_analysis_db",
"DB_USER": "admin",
"DB_PASSWORD": "xxxxxxxx"
}
作成手順:
-
AWS Consoleへログイン
-
Secrets Manager
-
「新しいシークレットを保存」
-
「その他のシークレット」
-
JSON入力
-
名前:
motion-analysis/prod/app-secrets
4.2 Cognito User Pool作成
作成手順
-
Cognito
-
「User Pool作成」
-
サインイン方式:
email
-
MFA:
必須
-
MFAタイプ:
Authenticator App
-
App Client作成
許可するFlow:
Authorization Code Grant
PKCE:
有効
注意
以下は禁止:
Implicit Flow
理由:
トークン漏洩リスクが高いため
5. Angular実装
5.1 ライブラリ導入
npm install angular-oauth2-oidc
5.2 auth.config.ts
import { AuthConfig } from 'angular-oauth2-oidc';
export const authConfig: AuthConfig = {
issuer:
'https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxx',
redirectUri: window.location.origin + '/auth/callback',
clientId: 'xxxxxxxx',
responseType: 'code',
scope: 'openid email profile',
strictDiscoveryDocumentValidation: false,
};
5.3 auth.service.ts
import { Injectable } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { authConfig } from './auth.config';
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private oauthService: OAuthService) {
this.oauthService.configure(authConfig);
this.oauthService.loadDiscoveryDocumentAndTryLogin();
}
login(): void {
this.oauthService.initCodeFlow();
}
logout(): void {
this.oauthService.logOut();
}
getToken(): string {
return this.oauthService.getAccessToken();
}
}
5.4 Token保存ルール
禁止:
localStorageへ長期保存
推奨:
sessionStorage
理由:
XSS被害時の漏洩リスク低減
6. Django実装
6.1 ライブラリ
pip install PyJWT cryptography requests djangorestframework boto3
6.2 環境変数
APP_SECRET_NAME=motion-analysis/prod/app-secrets
COGNITO_REGION=ap-northeast-1
COGNITO_USER_POOL_ID=xxxx
COGNITO_APP_CLIENT_ID=xxxx
6.3 Secrets取得
import json
import boto3
import os
def get_secret():
client = boto3.client("secretsmanager")
response = client.get_secret_value(
SecretId=os.environ["APP_SECRET_NAME"]
)
return json.loads(response["SecretString"])
SECRET = get_secret()
6.4 JWT検証
payload = jwt.decode(
token,
public_key,
algorithms=["RS256"],
audience=settings.COGNITO_APP_CLIENT_ID,
issuer=issuer,
)
必須検証:
| 項目 | 必須 |
|---|---|
| signature | ○ |
| issuer | ○ |
| audience | ○ |
| exp | ○ |
| token_use | ○ |
7. Dockerセキュリティ
7.1 Dockerfile
禁止:
FROM python:latest
推奨:
FROM python:3.12-slim
理由:
latestは予期しない更新が入るため
7.2 rootユーザー禁止
RUN useradd -m appuser
USER appuser
8. EC2セキュリティ
SSH禁止
SecurityGroup:
22番ポート閉鎖
接続方法:
SSM Session Manager
9. RDSセキュリティ
禁止:
Public Access = true
必須:
Private Subnet
10. CloudWatchログ
出力対象:
-
ログイン成功
-
ログイン失敗
-
MFA失敗
-
権限拒否
-
JWT検証失敗
11. Redmine移行
移行方針
Redmine認証は段階的に停止
手順
Step1
Redmineユーザー一覧取得
Step2
Cognitoへユーザー登録
Step3
初回ログイン時にMFA登録
Step4
JWT認証へ切替
Step5
Redmine認証停止
12. 動作確認
確認項目
| 項目 | OK条件 |
|---|---|
| ログイン | MFA成功 |
| JWT | APIアクセス成功 |
| 無効JWT | 401 |
| 権限不足 | 403 |
| DB接続 | 正常 |
| CloudWatch | ログ出力あり |
13. 障害対応
Cognito障害
対応:
管理者緊急アカウントを用意
JWTエラー
確認:
issuer
audience
token_use
14. 本番リリースチェック
| 項目 | 状態 |
|---|---|
| MFA必須化 | □ |
| HTTPS | □ |
| SSH閉鎖 | □ |
| Secrets Manager利用 | □ |
| JWT検証 | □ |
| CloudTrail有効 | □ |
| WAF有効 | □ |
| ECR Scan有効 | □ |
15. やってはいけないこと
禁止事項:
Client SecretをGitへPush
JWTをlocalStorageへ保存
latestタグ利用
Public RDS
SSH開放
秘密情報をコード直書き