Skip to content

feat: セキュリティ強化(管理API監査ログ + レートリミット) #46

@Inlet-back

Description

@Inlet-back

目的

ADR 005/006で指摘されたセキュリティリスクに対処し、本番運用時の安全性を確保する。

背景

ADR指摘事項

  • ADR 005: OAuth トークン暗号化戦略でキーローテーション未対応を指摘
  • ADR 006: 管理用API認証設計で監査ログ欠如・ブルートフォース対策なしを指摘

現状

  • Issue #31でOAuthAccountテーブル・管理API実装完了
  • Fernetによるトークン暗号化は実装済み
  • 本番環境デプロイ前にセキュリティ強化が必須

セキュリティリスク

🔴 P0(緊急): 管理API監査ログ欠如

  • リスク: 誰がいつ管理APIを実行したか記録されない
  • 影響範囲: ランク改ざん・不正操作の追跡不可能
  • 対策: ログ出力実装(10分)

🟡 P1(重要): ブルートフォース攻撃対策なし

  • リスク: ADMIN_API_KEYへの総当たり攻撃
  • 影響範囲: 管理API不正実行のリスク
  • 対策: レートリミット(slowapi)実装(20分)

🟡 P1(重要): 暗号化キー管理ドキュメント不足

  • リスク: キーの誤った管理・Git誤コミット
  • 影響範囲: 全OAuthトークンの漏洩
  • 対策: .env.exampleにセキュリティ警告追記(5分)

🟢 P2(将来): キーローテーション未対応

  • リスク: キー変更時に全トークン無効化
  • 影響範囲: 全ユーザーの再OAuth認証が必要
  • 対策: encryption_versionカラム追加(Phase 2)

実装内容

1. 管理API監査ログ(P0)

実装箇所: backend/app/api/admin.py

import logging
from fastapi import Request

logger = logging.getLogger(__name__)

@admin_app.post("/fix-user-ranks")
def fix_user_ranks(db: Session, request: Request, _: None = Depends(verify_admin_key)):
    logger.warning(
        f"ADMIN: fix-user-ranks executed from {request.client.host} "
        f"at {datetime.now(timezone.utc).isoformat()}"
    )
    # 実装

効果:

  • 誰がいつ管理APIを実行したか記録
  • セキュリティインシデント時の追跡可能

2. レートリミット実装(P1)

実装箇所: backend/app/api/admin.py

# 依存追加
poetry add slowapi
from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)

@admin_app.post("/fix-user-ranks")
@limiter.limit("5/hour")  # 1時間に5回まで
def fix_user_ranks(...):
    ...

効果:

  • ブルートフォース攻撃防止
  • ADMIN_API_KEY漏洩時の被害軽減

3. 暗号化キー管理ドキュメント(P1)

実装箇所: backend/.env.example

# OAuth Token Encryption (REQUIRED in production)
# Generate: openssl rand -base64 44
# NEVER commit this key to Git
ENCRYPTION_KEY=your-secret-key-here

# Admin API Authentication (REQUIRED in production)
# Generate: openssl rand -base64 48
# Share securely with team members only
ADMIN_API_KEY=your-admin-key-here

# ⚠️ Security Notes:
# 1. ENCRYPTION_KEY rotation will invalidate all existing OAuth tokens
# 2. Use AWS Secrets Manager or similar in production
# 3. Never expose these keys in logs or error messages

効果:

  • キー管理のベストプラクティス明示
  • チームメンバーへの注意喚起

4. キーローテーション設計(P2 - Future)

実装箇所: backend/app/models/oauth_account.py

class OAuthAccount(Base):
    # 現在
    access_token = Column(String, nullable=False)

    # 提案
    encryption_version = Column(Integer, default=1, nullable=False)
    # キーバージョン管理で複数世代のキーで復号試行可能に

効果:

  • キーローテーション時の段階的移行が可能
  • 既存トークンを無効化せずにキー更新

実装タスク

P0(即時実施)

  • 管理API監査ログ追加(10分)

P1(次PR)

  • slowapi依存追加(5分)
  • レートリミット実装(15分)
  • .env.example更新(5分)

P2(Phase 2)

  • キーローテーション設計ドキュメント作成(30分)

テスト要件

単体テスト

  • 管理APIログ出力確認(WARNING level)
  • レートリミット動作確認(6回連続リクエスト → 429エラー)

手動検証

  • .env.exampleの変数がすべて有効か確認
  • ログフォーマットが監査に十分な情報を含むか確認

セキュリティ考慮

  • ログ出力: ログレベルWARNING以上で監視システムに連携可能
  • レートリミット: IPアドレスベースで攻撃者単位での制限が可能
  • キー管理: .env.exampleに警告を明記し、誤コミット防止
  • キーローテーション: Phase 2対応、現時点では手動運用

完了条件(DoD)

  • 管理APIの実行がログに記録される(IP・タイムスタンプ含む)
  • レートリミットが正しく動作する(1時間5回超過時に429エラー)
  • .env.exampleにセキュリティ警告が記載される
  • キーローテーション設計が文書化される(ADR or README)

依存

次のステップ(後続Issue)

  • Phase 2: キーローテーション機能実装
  • Phase 2: 管理者テーブル追加(RBAC対応)
  • Phase 2: Admin操作の詳細ログ(変更前後の値記録)

参考資料

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions