サイトのAPI図鑑B版
掲載情報が正確でない可能性があります。
セキュリティ・コンプライアンス

API監査ログ・アクセスログの設計と実装ガイド【コンプライアンス・異常検知】

APIの監査ログ・アクセスログの設計原則、Node.js・Python・NGINXでの実装方法、ElasticsearchやCloudWatchへのログ転送・異常アクセス検知・コンプライアンス対応を解説します。

#監査ログ#アクセスログ#コンプライアンス#異常検知

APIログの種類と目的

APIのログには主に以下の種類があります:

  • アクセスログ:誰がいつどのAPIを呼んだかの記録
  • 監査ログ:重要な操作(データ変更・権限変更・設定変更)の記録
  • エラーログ:エラー・例外の記録
  • パフォーマンスログ:レスポンスタイム・スループットの記録

構造化ログの実装(Node.js)

import winston from 'winston';

// 構造化ログの設定
const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'access.log' })
  ]
});

// APIアクセスログミドルウェア
const accessLogger = (req, res, next) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    logger.info('api_access', {
      timestamp: new Date().toISOString(),
      method: req.method,
      path: req.path,
      query: req.query,
      status: res.statusCode,
      duration_ms: duration,
      user_id: req.user?.id || null,
      client_ip: req.headers['x-forwarded-for']?.split(',')[0] || req.ip,
      user_agent: req.headers['user-agent'],
      request_id: req.headers['x-request-id'] || req.id,
      api_key_id: req.apiKey?.id || null
    });
  });
  
  next();
};

監査ログの実装(重要操作の記録)

// 重要な操作を監査ログに記録
const auditLog = async ({
  userId,
  action,
  resourceType,
  resourceId,
  oldValue,
  newValue,
  ipAddress,
  result
}) => {
  await db.auditLogs.create({
    data: {
      userId,
      action,         // 'USER_ROLE_UPDATE', 'PAYMENT_CREATED', etc.
      resourceType,   // 'User', 'Order', 'Product', etc.
      resourceId,
      oldValue: JSON.stringify(oldValue), // 変更前の値
      newValue: JSON.stringify(newValue), // 変更後の値
      ipAddress,
      result,         // 'success' | 'failure'
      timestamp: new Date()
    }
  });
};

// ユーザーロール変更時
app.put('/api/users/:id/role', authenticate, authorize('admin'), async (req, res) => {
  const oldUser = await db.users.findUnique({ where: { id: req.params.id } });
  const updated = await db.users.update({
    where: { id: req.params.id },
    data: { role: req.body.role }
  });
  
  await auditLog({
    userId: req.user.id,
    action: 'USER_ROLE_UPDATE',
    resourceType: 'User',
    resourceId: req.params.id,
    oldValue: { role: oldUser.role },
    newValue: { role: req.body.role },
    ipAddress: req.ip,
    result: 'success'
  });
  
  res.json(updated);
});

ログの集中管理(ELKスタック)

// Logstashへのログ転送設定(Winstonのlogstash transport)
import Logstash from 'winston-logstash-transport';

logger.add(new Logstash({
  host: process.env.LOGSTASH_HOST,
  port: 5044,
  ssl_enable: true
}));

// ElasticsearchへのAPIアクセスログの転送で
// Kibanaでリアルタイムダッシュボードと異常検知を実現

異常アクセス検知のルール例

  • 同一IPから5分間に1000回以上のリクエスト → ブルートフォース攻撃の可能性
  • 認証失敗が連続10回 → アカウント攻撃の可能性
  • 深夜の管理APIアクセス → 不審なアクセス
  • 短時間での大量データエクスポート → データ窃取の可能性
  • 普段とは異なる国からのアクセス → アカウント侵害の可能性

まとめ

APIの監査ログは不正アクセスの検知・コンプライアンス対応・インシデント調査に不可欠です。構造化ログ(JSON形式)を採用し、ELKスタックやAWS CloudWatchに集中管理することで、異常検知・アラート・ログ分析が可能になります。個人情報・機密情報をログに含めないよう設計し、適切な保存期間を設定してください。

よくある質問

Q.監査ログに含めるべき情報は何ですか?

誰が(ユーザーID・IPアドレス)・いつ(タイムスタンプ・タイムゾーン)・何を(HTTPメソッド・エンドポイント・操作内容)・どんな結果(ステータスコード)・詳細(対象リソースID・変更内容)を記録します。個人情報やパスワードなどの機密データはログに含めないよう注意します。

Q.ログの保存期間はどのくらいにすべきですか?

法令・コンプライアンス要件によりますが、一般的には3ヶ月〜1年が多いです。PCI DSS準拠の場合は1年以上(3ヶ月間はすぐに参照可能な状態)が必要です。GDPRでは個人データが含まれるログは必要最小限の期間のみ保存する原則があります。

Q.ログ改ざん防止の方法はありますか?

ログを外部の書き込み専用ストレージ(CloudWatch Logs・Elasticsearch・S3等)にリアルタイムで転送することで改ざんリスクを低減できます。ハッシュチェーン(各ログエントリが前のエントリのハッシュを含む)で改ざん検知を実装することもできます。

関連記事