Skip to content

監査ログ設計

1. 概要

業務委託メンバーの操作を適切に記録・監視し、不正アクセスや情報漏洩を早期に検知するための監査ログ設計書。GitLabの標準監査ログに加え、アプリケーション層での補完ログを定義する。

2. 記録対象の操作一覧

2.1 認証・アカウント操作

カテゴリ操作重要度説明
認証ログイン成功INFOユーザーログイン
認証ログイン失敗WARNパスワード誤り、アカウントロック
認証ログアウトINFO明示的ログアウト
認証2FA設定変更WARN二要素認証の有効化/無効化
認証Personal Access Token作成WARNトークン発行
認証SSH鍵追加/削除WARN鍵の変更

2.2 リポジトリ操作

カテゴリ操作重要度説明
Gitgit cloneINFOリポジトリクローン
Gitgit pushINFOコードプッシュ
Gitgit pull/fetchLOWコード取得
Gitforce pushCRITICAL強制プッシュ(Protected Branchで禁止)
Branchブランチ作成INFO新規ブランチ
Branchブランチ削除WARNブランチ削除

2.3 Issue・MR操作

カテゴリ操作重要度説明
IssueIssue閲覧LOWIssueページアクセス
IssueIssue取得(API)INFOAPI経由でのIssue一覧取得
IssueIssueコメント追加INFOコメント投稿
IssueIssue状態変更INFOOpen/Close変更
MRMR作成INFOMerge Request作成
MRMRコメント追加INFOレビューコメント
MRMRマージWARNMRのマージ実行
MRMR承認INFOMRのApprove

2.4 管理操作

カテゴリ操作重要度説明
アクセス制御メンバー追加WARNプロジェクトメンバー追加
アクセス制御メンバー削除WARNプロジェクトメンバー削除
アクセス制御ロール変更CRITICAL権限レベルの変更
設定プロジェクト設定変更CRITICALプロジェクト設定の変更
設定CI/CD Variable変更CRITICALシークレット変数の追加/変更/削除
設定Protected Branch変更CRITICALブランチ保護設定の変更
設定Webhook変更CRITICALWebhook設定の追加/変更/削除

2.5 ファイルアクセス

カテゴリ操作重要度説明
ファイル機密ファイル閲覧WARNCODEOWNERS対象ファイルの閲覧
ファイル機密ファイル変更試行CRITICALCI/CDで検知・ブロックされた変更
ファイル大量ファイルダウンロードWARNアーカイブダウンロード等

3. ログフォーマット

3.1 標準ログフォーマット(JSON)

json
{
  "timestamp": "2026-03-28T09:15:30.123Z",
  "log_level": "INFO",
  "event_type": "repository.push",
  "user_id": 42,
  "username": "outsource-member-01",
  "user_type": "outsource",
  "action": "push",
  "resource_type": "repository",
  "resource_id": "78",
  "resource_name": "issueOutsource",
  "detail": {
    "branch": "feature/issue-12/add-login-validation",
    "commits_count": 3,
    "files_changed": 5
  },
  "ip_address": "203.0.113.45",
  "user_agent": "git/2.43.0",
  "session_id": "sess_abc123def456",
  "request_id": "req_789ghi012jkl",
  "result": "success",
  "correlation_id": "corr_mno345pqr678"
}

3.2 フィールド定義

フィールド必須説明
timestampISO 8601Yesイベント発生日時(UTC)
log_levelstringYesLOW / INFO / WARN / CRITICAL
event_typestringYesイベント種別(category.action 形式)
user_idintegerYesGitLabユーザーID
usernamestringYesGitLabユーザー名
user_typestringYesinternal / outsource / system
actionstringYes実行された操作
resource_typestringYes対象リソース種別
resource_idstringYes対象リソースID
resource_namestringNo対象リソース名
detailobjectNo操作の詳細情報
ip_addressstringYesクライアントIPアドレス
user_agentstringNoクライアントUser-Agent
session_idstringNoセッションID
request_idstringNoリクエストID
resultstringYessuccess / failure / blocked
correlation_idstringNo関連操作の追跡ID

3.3 GitLab標準監査ログとの対応

GitLab Premium/Ultimateの監査ログ機能を活用し、カスタムログで補完する。

ログソース取得方法内容
GitLab Audit Events APIGET /audit_eventsメンバー操作、設定変更
GitLab Events APIGET /eventsPush、MR、Issue操作
GitLab System HooksWebhook受信プロジェクト/グループレベルイベント
カスタムアプリケーションログアプリケーション出力Webhook処理、アクセス制御判定

4. ログ収集アーキテクチャ

GitLab Webhooks ──┐
                   ├──> Log Collector API ──> Message Queue ──> Log Processor
GitLab API Poll ──┘                              │
                                                  ├──> Log Storage (Primary)
                                                  ├──> Alert Engine
                                                  └──> Log Archive (Cold)

4.1 コンポーネント

コンポーネント技術選定役割
Log Collector APIFastAPI / ExpressWebhook受信、API結果の正規化
Message QueueRedis Streamsログの非同期処理バッファ
Log ProcessorPython Workerログの解析、アラート判定
Log Storage (Primary)PostgreSQL構造化ログの保存、検索
Log Archive (Cold)S3互換ストレージ長期保存用アーカイブ
Alert Engine専用Worker不正アクセス検知、通知

5. 保存期間・ローテーション

5.1 保存期間

データ種別保存先保存期間備考
CRITICAL/WARNログPrimary DB2年コンプライアンス要件
INFOログPrimary DB6ヶ月日常監視用
LOWログPrimary DB3ヶ月参照頻度低
全ログ(アーカイブ)Cold Storage5年法的要件対応
アラート履歴Primary DB3年インシデント追跡

5.2 ローテーション処理

yaml
# 日次バッチ: ログローテーション
log_rotation:
  schedule: "0 2 * * *"  # 毎日AM2:00 UTC
  tasks:
    - name: archive_expired_logs
      description: 保存期間超過ログをCold Storageへ移動
      steps:
        - query: "SELECT * FROM audit_logs WHERE timestamp < NOW() - INTERVAL '{retention_period}'"
        - export: "s3://audit-logs-archive/{year}/{month}/{day}/"
        - delete: "DELETE FROM audit_logs WHERE id IN (archived_ids)"

    - name: compress_archive
      description: アーカイブファイルの圧縮
      format: gzip

    - name: verify_archive
      description: アーカイブ整合性チェック
      method: sha256_checksum

5.3 データ量見積もり

項目見積もり
1委託メンバーあたり/日約200-500レコード
委託メンバー10名/月約10万-15万レコード
1レコードの平均サイズ約1KB
Primary DB月間増加量約100-150MB
年間アーカイブ量約1-2GB

6. 不正アクセス検知ルール

6.1 検知ルール一覧

ルールIDルール名条件重要度アクション
R001大量API呼出同一ユーザーが5分間に100回以上API呼出HIGHアラート通知 + 一時ブロック
R002業務時間外操作22:00-07:00 (JST) の操作MEDIUMアラート通知
R003未アサインIssueアクセス割当外のIssue/リポジトリへのアクセス試行HIGHアラート通知 + ブロック
R004ログイン失敗連続同一アカウントで10分間に5回以上ログイン失敗HIGHアカウント一時ロック
R005大量ファイルダウンロード1時間にリポジトリアーカイブ3回以上ダウンロードHIGHアラート通知 + ブロック
R006機密ファイル変更試行CODEOWNERS対象ファイルへの変更PushCRITICALアラート通知 + CI/CDブロック
R007異常IPアドレス登録外IPからのアクセスMEDIUMアラート通知
R008権限昇格試行Developer権限でのAdmin操作API呼出CRITICALアラート通知 + セッション無効化
R009契約期間外アクセス契約終了後のアクセス試行CRITICALアラート通知 + ブロック
R010休日・祝日操作土日祝日の操作LOWログ記録のみ

6.2 検知ルール実装例

python
# R001: 大量API呼出検知
class ExcessiveApiCallDetector:
    WINDOW_SECONDS = 300  # 5分
    THRESHOLD = 100

    async def check(self, event: AuditLog) -> Optional[Alert]:
        count = await self.redis.incr(
            f"api_calls:{event.user_id}:{event.timestamp // self.WINDOW_SECONDS}"
        )
        await self.redis.expire(
            f"api_calls:{event.user_id}:{event.timestamp // self.WINDOW_SECONDS}",
            self.WINDOW_SECONDS
        )

        if count >= self.THRESHOLD:
            return Alert(
                rule_id="R001",
                severity="HIGH",
                user_id=event.user_id,
                message=f"ユーザー {event.username}{self.WINDOW_SECONDS}秒間に{count}回のAPI呼出を実行",
                action="NOTIFY_AND_BLOCK"
            )
        return None

# R002: 業務時間外操作検知
class OffHoursDetector:
    BUSINESS_HOURS_START = 7   # 07:00 JST
    BUSINESS_HOURS_END = 22    # 22:00 JST

    async def check(self, event: AuditLog) -> Optional[Alert]:
        jst_hour = (event.timestamp.hour + 9) % 24  # UTC -> JST
        if jst_hour < self.BUSINESS_HOURS_START or jst_hour >= self.BUSINESS_HOURS_END:
            return Alert(
                rule_id="R002",
                severity="MEDIUM",
                user_id=event.user_id,
                message=f"ユーザー {event.username} が業務時間外に操作を実行 (JST {jst_hour}:00)",
                action="NOTIFY"
            )
        return None

6.3 アラート通知先

重要度通知先通知方法対応期限
CRITICALセキュリティチーム + プロジェクトOwnerSlack即座通知 + メール1時間以内
HIGHセキュリティチームSlack通知 + メール4時間以内
MEDIUMプロジェクトOwnerSlack通知翌営業日
LOW-ログ記録のみ月次レビュー

6.4 アラートフォーマット

json
{
  "alert_id": "alert_20260328_001",
  "rule_id": "R001",
  "severity": "HIGH",
  "timestamp": "2026-03-28T10:30:00Z",
  "user_id": 42,
  "username": "outsource-member-01",
  "summary": "大量API呼出を検知",
  "detail": "5分間に150回のAPI呼出を実行",
  "action_taken": "一時ブロック適用",
  "requires_ack": true,
  "notification_channels": ["slack", "email"]
}

7. ダッシュボード

7.1 監視ダッシュボード項目

パネル表示内容更新頻度
アクティブセッション現在ログイン中の委託メンバー一覧リアルタイム
操作ヒートマップ時間帯別の操作数5分
アラート一覧未対応アラートの一覧リアルタイム
API呼出数推移ユーザー別API呼出数のグラフ1分
ログイン履歴直近のログイン/ログアウトリアルタイム
リソースアクセスTop10最もアクセスされたリポジトリ/Issue1時間