EXERCISE 90分

ストーリー

高橋アーキテクト
セキュリティを”人の努力”に頼るのは限界がある。自動化が鍵だ

高橋アーキテクトがCI/CDパイプラインの設計図を広げました。

高橋アーキテクト
DevSecOpsパイプラインを設計してほしい。コードのプッシュからデプロイまで、全ての段階でセキュリティチェックを自動化する設計を作ろう

課題概要

項目内容
対象TypeScript + Node.js Webアプリケーション
課題数5つ
合計時間90分
評価基準各課題の設計ドキュメントを作成すること

課題1: SAST設定を設計しよう(15分)

TypeScriptプロジェクトに対するSAST(静的解析)の設定を作成してください。

要件

  • セキュリティルールの定義
  • CIパイプラインへの統合
  • 検出時のアクション(ブロック or 警告)
解答例(自分で設計してから確認しよう)
// .semgrep.yml の設定
const semgrepConfig = {
  rules: [
    {
      id: "sql-injection",
      patterns: [
        { pattern: "db.query(`...${$VAR}...`)" },
        { pattern: "db.query('...' + $VAR + '...')" },
      ],
      message: "SQL injection risk: Use parameterized queries",
      severity: "ERROR",
      languages: ["typescript"],
    },
    {
      id: "hardcoded-secret",
      patterns: [
        { pattern: "const $KEY = \"sk-...\"" },
        { pattern: "const $KEY = \"AKIA...\"" },
      ],
      message: "Hardcoded secret detected",
      severity: "ERROR",
    },
    {
      id: "eval-usage",
      pattern: "eval($INPUT)",
      message: "eval() is dangerous and should be avoided",
      severity: "ERROR",
    },
  ],
};

// ESLint セキュリティプラグイン設定
const eslintSecurityConfig = {
  plugins: ["security"],
  rules: {
    "security/detect-object-injection": "warn",
    "security/detect-non-literal-regexp": "warn",
    "security/detect-unsafe-regex": "error",
    "security/detect-buffer-noassert": "error",
    "security/detect-eval-with-expression": "error",
    "security/detect-no-csrf-before-method-override": "error",
    "security/detect-possible-timing-attacks": "warn",
  },
};

// GitHub Actions ワークフロー
// SAST:
//   runs-on: ubuntu-latest
//   steps:
//     - uses: actions/checkout@v4
//     - name: Semgrep Scan
//       run: semgrep scan --config auto --error --json > sast-results.json
//     - name: ESLint Security
//       run: npx eslint --config .eslintrc.security.json src/

課題2: SCA(依存関係チェック)を設計しよう(15分)

依存ライブラリの脆弱性チェックとSBOM生成の自動化を設計してください。

解答例(自分で設計してから確認しよう)
# GitHub Actions: SCA ワークフロー
# name: SCA - Dependency Check
# on: [push, pull_request]
# jobs:
#   sca:
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: actions/setup-node@v4
#       - run: npm ci
#       - name: npm audit
#         run: npm audit --audit-level=high
#       - name: License Check
#         run: npx license-checker --failOn 'GPL-3.0;AGPL-3.0'
#       - name: Generate SBOM
#         run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json
#       - name: Trivy scan
#         uses: aquasecurity/trivy-action@master
#         with:
#           scan-type: 'fs'
#           scan-ref: '.'
#           severity: 'HIGH,CRITICAL'
#           exit-code: '1'
#       - name: Upload SBOM
#         uses: actions/upload-artifact@v4
#         with:
#           name: sbom
#           path: sbom.json

設計ポイント:

  • npm audit で直接依存の脆弱性チェック
  • Trivy でファイルシステム全体をスキャン
  • ライセンス互換性の確認(GPL除外)
  • SBOMを成果物として保存

課題3: DAST(動的テスト)を設計しよう(15分)

ステージング環境に対するDAST(動的テスト)のスキャン設定を設計してください。

解答例(自分で設計してから確認しよう)
// OWASP ZAP の設定
const zapScanConfig = {
  target: "https://staging.myapp.com",
  scanType: "full",

  // 認証設定
  authentication: {
    type: "json",
    loginUrl: "https://staging.myapp.com/api/auth/login",
    loginBody: {
      email: "test@example.com",
      password: "TestPassword123!",
    },
    tokenExtraction: "$.accessToken",
    tokenHeader: "Authorization: Bearer {token}",
  },

  // スキャン対象
  includePaths: [
    "https://staging.myapp.com/api/*",
  ],

  // スキャン除外
  excludePaths: [
    "https://staging.myapp.com/api/health",
    "https://staging.myapp.com/api/auth/logout",
  ],

  // アラートしきい値
  alertThresholds: {
    high: "FAIL",      // High以上はパイプライン失敗
    medium: "WARN",    // Mediumは警告
    low: "INFO",       // Lowは情報のみ
  },

  // スキャンポリシー
  policies: {
    xss: { enabled: true, strength: "high" },
    sqli: { enabled: true, strength: "high" },
    csrf: { enabled: true, strength: "medium" },
    pathTraversal: { enabled: true, strength: "high" },
    commandInjection: { enabled: true, strength: "high" },
  },
};

課題4: 監査ログ設計をしよう(20分)

アプリケーションの監査ログの設計を行い、記録すべきイベント一覧と検出ルールを定義してください。

解答例(自分で設計してから確認しよう)
// 監査ログイベント一覧
const auditEvents = [
  // 認証イベント
  { event: "auth.login.success", severity: "info", alert: false },
  { event: "auth.login.failure", severity: "warning", alert: true },
  { event: "auth.logout", severity: "info", alert: false },
  { event: "auth.mfa.verify", severity: "info", alert: false },
  { event: "auth.password.change", severity: "info", alert: true },
  { event: "auth.password.reset", severity: "warning", alert: true },

  // データアクセスイベント
  { event: "data.export", severity: "warning", alert: true },
  { event: "data.bulk_read", severity: "info", alert: false },
  { event: "data.sensitive_access", severity: "warning", alert: true },

  // 管理操作
  { event: "admin.user.create", severity: "info", alert: false },
  { event: "admin.user.delete", severity: "warning", alert: true },
  { event: "admin.role.change", severity: "warning", alert: true },
  { event: "admin.config.change", severity: "warning", alert: true },

  // セキュリティイベント
  { event: "security.rate_limit", severity: "warning", alert: true },
  { event: "security.access_denied", severity: "warning", alert: true },
  { event: "security.invalid_token", severity: "warning", alert: true },
  { event: "security.suspicious_ip", severity: "error", alert: true },
];

// 検出ルール
const detectionRules = [
  {
    name: "ブルートフォース検知",
    query: "auth.login.failure COUNT > 10 IN 5min FROM same IP",
    action: "block_ip + alert",
    severity: "critical",
  },
  {
    name: "アカウント乗っ取り兆候",
    query: "auth.password.change AND auth.login.success FROM new_ip IN 1hour",
    action: "suspend_account + alert",
    severity: "critical",
  },
  {
    name: "大量データ流出兆候",
    query: "data.export COUNT > 100 IN 1hour FROM same user",
    action: "revoke_session + alert",
    severity: "high",
  },
  {
    name: "権限昇格試行",
    query: "security.access_denied COUNT > 5 IN 10min FROM same user",
    action: "alert + monitor",
    severity: "high",
  },
];

課題5: 統合パイプラインを設計しよう(25分)

課題1-4の結果を統合した、完全なDevSecOpsパイプラインを設計してください。

解答例(自分で設計してから確認しよう)
┌─────────────────────────────────────────────────────┐
│                DevSecOps パイプライン                   │
├─────────────────────────────────────────────────────┤
│                                                     │
│  [Pre-commit]                                       │
│  ├── gitleaks(シークレット検出)                      │
│  └── ESLint Security(セキュリティルール)              │
│       │                                             │
│  [Build & Test]                                     │
│  ├── npm ci(依存インストール)                        │
│  ├── Semgrep SAST(静的解析)          ── FAIL → 停止 │
│  ├── npm audit(脆弱性チェック)       ── FAIL → 停止 │
│  ├── License Check(ライセンス確認)                  │
│  ├── Unit Tests(単体テスト)                        │
│  └── SBOM生成                                      │
│       │                                             │
│  [Container]                                        │
│  ├── Docker Build                                   │
│  ├── Trivy Scan(コンテナ脆弱性)     ── FAIL → 停止 │
│  └── Image Signing(署名)                          │
│       │                                             │
│  [Staging Deploy]                                   │
│  ├── デプロイ                                       │
│  ├── DAST Scan(動的テスト)          ── FAIL → 停止 │
│  └── Integration Tests                              │
│       │                                             │
│  [Approval Gate]                                    │
│  └── セキュリティレビュー承認                          │
│       │                                             │
│  [Production Deploy]                                │
│  ├── カナリアリリース(10%)                          │
│  ├── 監視(エラーレート、レイテンシ)                  │
│  ├── 段階的ロールアウト                              │
│  └── 監査ログ監視開始                                │
│                                                     │
└─────────────────────────────────────────────────────┘

ゲート基準(パイプラインを止める条件):

ゲート基準
SASTCritical/High 検出でFAIL
SCACVSS 7.0以上の脆弱性でFAIL
ContainerCritical 脆弱性でFAIL
DASTHigh 以上のアラートでFAIL

達成度チェック

課題テーマ完了
課題1SAST設定[ ]
課題2SCA設計[ ]
課題3DAST設計[ ]
課題4監査ログ設計[ ]
課題5統合パイプライン設計[ ]

まとめ

ポイント内容
SASTソースコードの静的解析をCIに統合
SCA依存関係の脆弱性チェックとSBOM管理
DAST実行中のアプリに対する動的テスト
統合全テストをパイプラインに組み込み自動化

チェックリスト

  • SASTの設定とルール定義ができた
  • SCAとSBOM生成の自動化を設計できた
  • DASTのスキャン設定を作成できた
  • 監査ログのイベントと検出ルールを定義できた
  • 統合パイプラインを設計できた

次のステップへ

お疲れさまでした。DevSecOpsパイプラインの設計演習が完了しました。 次はStep 5のチェックポイントです。


推定所要時間: 90分