EXERCISE 60分

ストーリー

佐藤CTO
SAST、SCA、DAST、コンテナスキャン、IaCスキャン — 個々のツールは分かった

佐藤CTOがパイプライン設計書を広げました。

佐藤CTO
これらを統合して、エンドツーエンドのセキュリティパイプラインを構築してくれ。開発速度を落とさず、セキュリティを担保する仕組みだ

対象プロジェクト:マイクロサービスECプラットフォーム

技術スタック

コンポーネント技術
バックエンドTypeScript (Node.js)
フロントエンドNext.js
インフラTerraform + AWS
コンテナDocker + EKS
CI/CDGitHub Actions
レジストリAmazon ECR

Mission 1:Pre-commit セキュリティゲートの設計(15分)

開発者がコードをコミットする前に動作するセキュリティチェックを設計してください。

要件

  1. シークレットスキャンの設定
  2. Lintingセキュリティルールの定義
  3. 開発者体験を損なわない実行速度(10秒以内)
  4. .pre-commit-config.yamlを作成
解答例
# .pre-commit-config.yaml
repos:
  # シークレットスキャン
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks
        name: Detect Secrets

  # セキュリティ Lint(軽量チェックのみ)
  - repo: https://github.com/semgrep/semgrep
    rev: v1.50.0
    hooks:
      - id: semgrep
        name: Security Lint
        args:
          - '--config'
          - 'p/typescript'
          - '--config'
          - '.semgrep/quick-checks.yml'
          - '--error'
          - '--timeout'
          - '5'  # 5秒タイムアウト

  # Dockerfile セキュリティチェック
  - repo: https://github.com/hadolint/hadolint
    rev: v2.12.0
    hooks:
      - id: hadolint
        name: Dockerfile Lint

  # 秘密鍵の検出
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: detect-private-key
      - id: detect-aws-credentials
      - id: check-added-large-files
        args: ['--maxkb=500']
# .semgrep/quick-checks.yml(軽量ルール)
rules:
  - id: no-eval
    pattern: eval($X)
    message: "eval() は禁止されています"
    languages: [typescript, javascript]
    severity: ERROR

  - id: no-innerhtml
    pattern: $EL.innerHTML = $X
    message: "innerHTML は XSSリスクがあります"
    languages: [typescript, javascript]
    severity: WARNING

  - id: no-hardcoded-password
    patterns:
      - pattern: |
          const password = "..."
    message: "パスワードのハードコードは禁止です"
    languages: [typescript, javascript]
    severity: ERROR

Mission 2:CI パイプラインのセキュリティゲート設計(15分)

GitHub ActionsでのCIパイプラインにセキュリティチェックを組み込んでください。

要件

  1. SAST(Semgrep + SonarQube)
  2. SCA(Snyk + npm audit)
  3. コンテナスキャン(Trivy)
  4. IaCスキャン(Checkov)
  5. SBOM生成
  6. セキュリティゲート(全チェック通過を必須に)
解答例
# .github/workflows/security-ci.yml
name: Security CI Pipeline

on:
  pull_request:
    branches: [main, develop]
  push:
    branches: [main]

concurrency:
  group: security-${{ github.ref }}
  cancel-in-progress: true

jobs:
  # ===== Phase 1: コードスキャン(並列実行) =====
  sast-semgrep:
    name: SAST (Semgrep)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten
            p/typescript
            .semgrep/

  sast-sonarqube:
    name: SAST (SonarQube)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: sonarsource/sonarqube-scan-action@v2
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
      - uses: sonarsource/sonarqube-quality-gate-check@v1
        timeout-minutes: 5
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

  sca:
    name: SCA (Snyk + npm audit)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 18
      - run: npm ci
      - uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high
      - name: License Check
        run: npx license-checker --failOn "GPL-3.0;AGPL-3.0"

  secret-scan:
    name: Secret Scanning
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  iac-scan:
    name: IaC Security (Checkov)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bridgecrewio/checkov-action@master
        with:
          directory: ./infrastructure
          framework: terraform
          output_format: sarif

  # ===== Phase 2: ビルドとコンテナスキャン =====
  container-security:
    name: Container Security
    needs: [sast-semgrep, sca, secret-scan]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Image
        run: docker build -t app:${{ github.sha }} .
      - name: Trivy Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: app:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif
          severity: CRITICAL,HIGH
          exit-code: 1
      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          image: app:${{ github.sha }}
          format: spdx-json
          output-file: sbom.spdx.json
      - uses: actions/upload-artifact@v4
        with:
          name: sbom
          path: sbom.spdx.json

  # ===== Security Gate =====
  security-gate:
    name: Security Gate
    needs: [sast-semgrep, sast-sonarqube, sca, secret-scan, iac-scan, container-security]
    runs-on: ubuntu-latest
    steps:
      - name: All Security Checks Passed
        run: echo "All security checks passed. Ready for merge."

Mission 3:DAST統合の設計(15分)

ステージング環境へのデプロイ後に自動実行されるDASTパイプラインを設計してください。

要件

  1. OWASP ZAPによるフルスキャン
  2. APIセキュリティテスト(OpenAPI仕様ベース)
  3. スキャン結果の通知とチケット自動起票
  4. スキャンの除外ルール設定
解答例
# .github/workflows/dast.yml
name: DAST Pipeline

on:
  deployment_status:
    # ステージングデプロイ完了後に実行

jobs:
  dast-scan:
    if: >-
      github.event.deployment_status.state == 'success' &&
      github.event.deployment_status.environment == 'staging'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Wait for application readiness
        run: |
          TARGET_URL="${{ github.event.deployment_status.target_url }}"
          for i in $(seq 1 30); do
            if curl -s -o /dev/null -w "%{http_code}" "$TARGET_URL/health" | grep -q "200"; then
              echo "Application is ready"
              exit 0
            fi
            echo "Waiting... ($i/30)"
            sleep 10
          done
          echo "Application not ready after 5 minutes"
          exit 1

      - name: OWASP ZAP API Scan
        uses: zaproxy/action-api-scan@v0.7.0
        with:
          target: ${{ github.event.deployment_status.target_url }}/api/openapi.json
          format: openapi
          rules_file_name: .zap/rules.tsv
          allow_issue_writing: true

      - name: OWASP ZAP Full Scan
        uses: zaproxy/action-full-scan@v0.10.0
        with:
          target: ${{ github.event.deployment_status.target_url }}
          rules_file_name: .zap/rules.tsv

      - name: Notify Results
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "DAST scan detected vulnerabilities in staging",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*DAST Scan Alert*\nVulnerabilities found in staging deployment.\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Results>"
                  }
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SECURITY_SLACK_WEBHOOK }}

Mission 4:セキュリティダッシュボードとメトリクス設計(15分)

パイプライン全体のセキュリティ状況を可視化するダッシュボードを設計してください。

要件

  1. KPI/メトリクスの定義
  2. ダッシュボードのレイアウト設計
  3. アラートルールの設定
  4. レポーティングの自動化
解答例
// セキュリティダッシュボードのデータモデル
interface SecurityDashboard {
  overview: {
    totalVulnerabilities: number;
    criticalCount: number;
    highCount: number;
    mediumCount: number;
    lowCount: number;
    mttrCritical: string;   // Mean Time to Remediate
    mttrHigh: string;
    pipelinePassRate: number; // %
    sbomCoverage: number;   // %
  };
  trends: {
    period: string;
    newVulnerabilities: number;
    resolvedVulnerabilities: number;
    openVulnerabilities: number;
  }[];
  byCategory: {
    sast: { total: number; critical: number; falsePositiveRate: number };
    sca: { total: number; critical: number; outdatedDeps: number };
    dast: { total: number; critical: number; lastScanDate: string };
    container: { total: number; critical: number; baseImageAge: number };
    iac: { total: number; critical: number; policyViolations: number };
  };
}

// アラートルール
interface AlertRule {
  name: string;
  condition: string;
  severity: 'critical' | 'warning' | 'info';
  channel: string;
  cooldown: string;
}

const alertRules: AlertRule[] = [
  {
    name: 'Critical Vulnerability Detected',
    condition: 'new_vulnerability.severity == "critical"',
    severity: 'critical',
    channel: '#security-incidents',
    cooldown: '0m',  // 即座に通知
  },
  {
    name: 'MTTR SLA Breach',
    condition: 'vulnerability.age > sla[vulnerability.severity]',
    severity: 'warning',
    channel: '#security-alerts',
    cooldown: '4h',
  },
  {
    name: 'Pipeline Pass Rate Drop',
    condition: 'pipeline.pass_rate < 80',
    severity: 'warning',
    channel: '#engineering',
    cooldown: '24h',
  },
  {
    name: 'Secret Leak Detected',
    condition: 'secret_scan.findings > 0',
    severity: 'critical',
    channel: '#security-incidents',
    cooldown: '0m',
  },
];

SLA(Service Level Agreement)

重要度検出からの修正期限エスカレーション
Critical24時間以内4時間後に自動エスカレーション
High7日以内3日後にリマインド
Medium30日以内14日後にリマインド
Low90日以内バックログで管理

評価基準

評価項目配点合格ライン
Pre-commitゲートの設計20%実行速度と網羅性のバランスが取れている
CIパイプラインの設計30%SAST/SCA/コンテナ/IaCが適切に統合されている
DAST統合の設計25%自動化されたDASTと通知フローが設計されている
ダッシュボードとメトリクス25%KPIとSLAが定義されている

推定読了時間: 60分