LESSON 30分

ストーリー

高橋アーキテクト
セキュリティインシデントが起きたとき、最初に確認するのは何だと思う?

高橋アーキテクトが問いかけました。

あなた
ログ…ですか?
高橋アーキテクト
正解だ。でも、必要な情報がログに残っていなければ、何が起きたのかすら分からない。監査ログは”事後に何が起きたかを追跡する”ための生命線だ

監査ログとは

監査ログ(Audit Log)は、システム上で行われた重要な操作を記録するログです。「いつ、誰が、何を、どこから、どうしたか」を追跡可能にします。

監査ログに記録すべきイベント

カテゴリイベント例
認証ログイン成功/失敗、ログアウト、MFA検証、パスワード変更
認可アクセス拒否、権限変更、ロール変更
データアクセス機密データの参照、ダウンロード、エクスポート
データ変更作成、更新、削除(特に機密データ)
管理操作ユーザー作成/削除、設定変更、デプロイ
セキュリティイベントレートリミット超過、不正なトークン使用、IP ブロック

監査ログの設計

// 監査ログのスキーマ
interface AuditLogEntry {
  // 識別情報
  id: string;                   // UUID
  timestamp: string;            // ISO 8601
  traceId: string;              // リクエスト追跡ID

  // アクター情報
  actor: {
    type: "user" | "service" | "system";
    id: string;
    role: string;
    tenantId?: string;
  };

  // アクション情報
  action: {
    type: string;               // "user.login", "order.create" 等
    category: "authentication" | "authorization" | "data_access" |
              "data_mutation" | "admin" | "security";
    result: "success" | "failure" | "denied";
  };

  // リソース情報
  resource: {
    type: string;               // "user", "order" 等
    id: string;
    attributes?: Record<string, unknown>;
  };

  // コンテキスト情報
  context: {
    ipAddress: string;
    userAgent: string;
    requestId: string;
    sessionId?: string;
    geoLocation?: string;
  };

  // 変更内容(データ変更の場合)
  changes?: {
    before: Record<string, unknown>;
    after: Record<string, unknown>;
  };
}

// 監査ログサービス
class AuditLogger {
  constructor(private store: AuditStore) {}

  async log(entry: Omit<AuditLogEntry, "id" | "timestamp">): Promise<void> {
    const fullEntry: AuditLogEntry = {
      ...entry,
      id: crypto.randomUUID(),
      timestamp: new Date().toISOString(),
    };

    // 書き込み専用ストレージに保存(削除不可)
    await this.store.append(fullEntry);

    // Critical イベントはリアルタイムアラート
    if (this.isCritical(fullEntry)) {
      await this.sendAlert(fullEntry);
    }
  }

  private isCritical(entry: AuditLogEntry): boolean {
    return (
      entry.action.category === "security" ||
      (entry.action.category === "authentication" && entry.action.result === "failure") ||
      entry.action.type.includes("delete") ||
      entry.action.type.includes("role.change")
    );
  }

  private async sendAlert(entry: AuditLogEntry): Promise<void> {
    await alertService.notify({
      severity: "high",
      message: `Security event: ${entry.action.type} by ${entry.actor.id}`,
      details: entry,
    });
  }
}

ログに記録してはいけない情報

記録禁止理由
パスワード平文のパスワードは絶対にログに残さない
クレジットカード番号PCI DSS違反
アクセストークントークン漏洩のリスク
個人情報の生データGDPR/個人情報保護法違反
シークレットAPIキー等の機密情報
// ログサニタイザー
const sanitizeForLog = (data: Record<string, unknown>): Record<string, unknown> => {
  const sensitiveFields = [
    "password", "token", "secret", "apiKey", "creditCard",
    "ssn", "accessToken", "refreshToken",
  ];

  const sanitized = { ...data };
  for (const field of sensitiveFields) {
    if (sanitized[field]) {
      sanitized[field] = "[REDACTED]";
    }
  }

  // メールアドレスはマスキング
  if (typeof sanitized.email === "string") {
    const [local, domain] = (sanitized.email as string).split("@");
    sanitized.email = `${local[0]}***@${domain}`;
  }

  return sanitized;
};

ログの保存と保護

// ログの保存設計
interface LogStorageConfig {
  // 書き込み専用(WORM: Write Once Read Many)
  immutable: true;

  // 暗号化
  encryptionAtRest: true;
  encryptionKey: "AWS KMS";

  // 保存期間
  retention: {
    hot: "30日",     // すぐに検索可能(CloudWatch Logs)
    warm: "90日",    // 低コストストレージ(S3 Standard-IA)
    cold: "3年",     // アーカイブ(S3 Glacier)
  };

  // アクセス制御
  access: {
    write: ["application-service"],
    read: ["security-team", "compliance-team"],
    delete: [], // 誰も削除できない
  };
}

不正検知のためのログ分析

// 不審なパターンの検出ルール
const detectionRules = [
  {
    name: "ブルートフォース検知",
    condition: "同一IPから5分間に10回以上のログイン失敗",
    action: "IPブロック + アラート",
  },
  {
    name: "異常な時間帯のアクセス",
    condition: "深夜2-5時の管理者操作",
    action: "追加認証要求 + アラート",
  },
  {
    name: "大量データダウンロード",
    condition: "1時間に1000件以上のデータエクスポート",
    action: "アカウント一時停止 + アラート",
  },
  {
    name: "権限昇格の試行",
    condition: "認可拒否が連続5回以上",
    action: "セッション無効化 + アラート",
  },
];

まとめ

ポイント内容
監査ログいつ・誰が・何を・どこから・どうしたかを記録
記録対象認証、認可、データアクセス、管理操作
記録禁止パスワード、トークン、カード番号等
保護書き込み専用、暗号化、アクセス制限

チェックリスト

  • 監査ログに記録すべきイベントを把握した
  • 監査ログのスキーマ設計を理解した
  • ログに記録してはいけない情報を把握した
  • 不正検知のためのログ分析パターンを理解した

次のステップへ

次は演習です。ここまで学んだDevSecOpsの知識を使って、セキュリティパイプラインを設計しましょう。


推定読了時間: 30分