Skip to content
Published on

DevSecOps完全ガイド2025:Shift-Leftセキュリティ、SAST/DAST/SCA、コンテナセキュリティまで

Authors

TL;DR

  • Shift-Leftセキュリティ: 開発初期にセキュリティを適用すれば欠陥修正コストが30倍削減
  • SAST: SonarQube、Semgrep、CodeQLでコードレベルの脆弱性(ぜいじゃくせい)を検出
  • DAST: OWASP ZAP、Burp Suiteでランタイム脆弱性を発見
  • SCA: Snyk、Dependabotで依存関係(いぞんかんけい)の脆弱性を自動パッチ
  • コンテナセキュリティ: Trivy、Grypeでイメージスキャン、最小ベースイメージ使用
  • サプライチェーン: SBOM生成、SLSAレベル達成、Sigstore署名(しょめい)
  • シークレット検出: GitLeaks、TruffleHogでコミットされた秘密情報を検出
  • GitHub Actions: 統合セキュリティパイプラインで全段階を自動化

目次

  1. DevSecOpsとは何か
  2. Shift-Leftセキュリティ戦略
  3. SAST - 静的解析
  4. DAST - 動的解析
  5. SCA - ソフトウェア構成分析
  6. コンテナセキュリティ
  7. シークレット検出
  8. サプライチェーンセキュリティ - SBOMとSLSA
  9. Policy-as-Code
  10. GitHub Actions統合セキュリティパイプライン
  11. 実践クイズ
  12. 参考資料

1. DevSecOpsとは何か

1.1 従来のセキュリティの限界

従来(じゅうらい)のソフトウェア開発では、セキュリティは最後の段階で追加されていました。開発が終わりデプロイ直前にセキュリティチームがレビューする方式でした。このアプローチの問題点は明確です。

問題影響
遅い発見修正コスト30倍増加
ボトルネックセキュリティチームが全プロジェクトをレビュー
開発者の無関心「セキュリティはセキュリティチームの仕事」マインド
リリース遅延脆弱性発見時にスケジュール全体が遅延
コンテキスト不足セキュリティチームがコードの意図を理解していない

1.2 DevSecOpsの核心原則

DevSecOpsはDevelopment + Security + Operationsの造語(ぞうご)で、セキュリティをソフトウェア開発ライフサイクル(SDLC)全体に統合する文化であり実践方法です。

5つの核心原則:

  1. 全員がセキュリティに責任: セキュリティはセキュリティチームだけの仕事ではない
  2. 自動化優先: 手動レビューの代わりに自動化ツールを活用
  3. 迅速なフィードバック: 開発者がコードを書く時点でセキュリティフィードバック
  4. 継続的改善: セキュリティメトリクスの測定と継続的な改善
  5. 共有責任: 開発、運用、セキュリティチーム間の知識共有

1.3 DevSecOpsツールエコシステム概要

┌─────────────────────────────────────────────────────────────┐
DevSecOps パイプライン                      │
├──────────┬──────────┬──────────┬──────────┬────────────────┤
PlanCodeBuildTestDeploy/Run├──────────┼──────────┼──────────┼──────────┼────────────────┤
ThreatSASTSCADASTRuntimeModelingSemgrepSnykZAPProtection│          │ CodeQLTrivyBurpFalcoSecuritySonarQube│ OSVNucleiContainerRequire  │          │          │          │ Security│ ments    │ SecretSBOMFuzzingNetwork│          │ DetectSigning  │          │ Policy├──────────┼──────────┼──────────┼──────────┼────────────────┤
Policy-as-Code (OPA / Kyverno / Conftest)└─────────────────────────────────────────────────────────────┘

2. Shift-Leftセキュリティ戦略

2.1 Shift-Leftとは?

Shift-Leftはセキュリティ活動を開発プロセスの左側(初期段階)に移動(いどう)させる戦略です。

従来の方式:
Plan -> Code -> Build -> Test -> Deploy -> [セキュリティレビュー] -> Release
                                            ^ ここで発見 = コスト高

Shift-Left方式:
Plan -> [セキュリティ] -> Code -> [セキュリティ] -> Build -> [セキュリティ] -> Test -> Deploy
  ^ ここから開始 = コスト低

2.2 Shift-Left ROI分析

IBM Systems Sciences Instituteの研究によると、欠陥修正コストは発見時点によって指数関数的(しすうかんすうてき)に増加します。

発見段階相対コスト
要件定義1xセキュリティ要件の漏れを発見
設計5xアーキテクチャ脆弱性を発見
実装10xコードレベル脆弱性を発見
テスト20xQA段階で発見
運用30x本番環境で発見
インシデント発生後100x+データ漏洩事故

2.3 Shift-Left実装ステップ

ステップ1: セキュリティチャンピオンプログラム

各開発チームにセキュリティチャンピオンを指定します。

# security-champions.yaml
teams:
  - name: "Backend Team"
    champion: "alice@company.com"
    responsibilities:
      - "PRセキュリティレビュー"
      - "SAST結果のトリアージ"
      - "月次セキュリティ教育実施"
    training:
      - "OWASP Top 10"
      - "Secure Coding Practices"
      - "Threat Modeling基礎"
  - name: "Frontend Team"
    champion: "bob@company.com"
    responsibilities:
      - "XSS/CSRF防止レビュー"
      - "依存関係脆弱性管理"
      - "CSPヘッダー管理"

ステップ2: 脅威モデリング

STRIDEモデルを活用した脅威(きょうい)モデリングを設計段階で実施します。

STRIDE脅威モデル:
┌─────────────────────────────────────────┐
S - Spoofing(なりすまし)T - Tampering(改ざん)R - Repudiation(否認)I - Information Disclosure(情報漏洩)D - Denial of Service(サービス拒否)E - Elevation of Privilege(権限昇格)└─────────────────────────────────────────┘

ステップ3: IDEセキュリティプラグイン

開発者のIDEで直接セキュリティフィードバックを提供します。

// .vscode/settings.json
{
  "semgrep.scan.autoScan": true,
  "semgrep.scan.configuration": [
    "p/owasp-top-ten",
    "p/typescript",
    "p/react"
  ],
  "sonarlint.connectedMode.project": {
    "connectionId": "my-sonarqube",
    "projectKey": "my-project"
  }
}

3. SAST - 静的解析

3.1 SASTとは?

SAST(Static Application Security Testing)はソースコード、バイトコード、バイナリを実行せずに解析してセキュリティ脆弱性を見つける技法です。

SASTが検出する主な脆弱性:

  • SQLインジェクション
  • クロスサイトスクリプティング(XSS)
  • パストラバーサル
  • ハードコードされたシークレット
  • 安全でない暗号化
  • バッファオーバーフロー

3.2 SonarQubeセットアップ

# docker-compose.yml - SonarQubeローカルセットアップ
version: "3.8"
services:
  sonarqube:
    image: sonarqube:community
    ports:
      - "9000:9000"
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarqube
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonar_data:/opt/sonarqube/data
      - sonar_logs:/opt/sonarqube/logs
      - sonar_extensions:/opt/sonarqube/extensions
    depends_on:
      - db
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: sonarqube
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  sonar_data:
  sonar_logs:
  sonar_extensions:
  postgres_data:
# sonar-project.properties
sonar.projectKey=my-app
sonar.projectName=My Application
sonar.projectVersion=1.0
sonar.sources=src
sonar.tests=tests
sonar.language=ts
sonar.sourceEncoding=UTF-8
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.qualitygate.wait=true

3.3 Semgrep実践活用

Semgrepは軽量(けいりょう)で高速なSASTツールで、カスタムルールの作成が容易です。

# .semgrep.yml - カスタムセキュリティルール
rules:
  - id: no-eval-usage
    patterns:
      - pattern: eval(...)
    message: "eval()の使用はコードインジェクションのリスクがあります"
    severity: ERROR
    languages: [javascript, typescript]
    metadata:
      owasp: "A03:2021 Injection"
      cwe: "CWE-95"

  - id: no-innerHTML
    patterns:
      - pattern: $EL.innerHTML = $VAL
    message: "innerHTMLの直接設定はXSSリスクがあります。textContentまたはDOMPurifyを使用してください"
    severity: WARNING
    languages: [javascript, typescript]

  - id: sql-injection-risk
    patterns:
      - pattern: |
          $DB.query(`... ${$VAR} ...`)
      - pattern: |
          $DB.query("..." + $VAR + "...")
    message: "SQLインジェクションリスク!パラメータバインディングを使用してください"
    severity: ERROR
    languages: [javascript, typescript]
    fix: |
      $DB.query("... $1 ...", [$VAR])

  - id: no-hardcoded-secrets
    patterns:
      - pattern: |
          const $KEY = "AKIA..."
      - pattern: |
          const $KEY = "sk-..."
    message: "ハードコードされたシークレットが検出されました。環境変数を使用してください"
    severity: ERROR
    languages: [javascript, typescript]
# Semgrep実行
semgrep --config auto --config .semgrep.yml src/

# 特定のルールセットのみ実行
semgrep --config p/owasp-top-ten src/
semgrep --config p/typescript src/

# CI用JSON出力
semgrep --config auto --json --output results.json src/

3.4 CodeQL高度なクエリ

GitHub CodeQLはコードをデータベースに変換してクエリする強力なツールです。

// codeql-queries/sql-injection.ql
/**
 * @name SQL injection in query string
 * @description ユーザー入力がSQLクエリに直接含まれている
 * @kind path-problem
 * @problem.severity error
 * @security-severity 9.8
 * @precision high
 * @id js/sql-injection
 * @tags security
 *       external/cwe/cwe-089
 */

import javascript
import DataFlow::PathGraph

class SqlInjectionConfig extends TaintTracking::Configuration {
  SqlInjectionConfig() { this = "SqlInjectionConfig" }

  override predicate isSource(DataFlow::Node source) {
    exists(Express::RequestInputAccess input |
      source = input
    )
  }

  override predicate isSink(DataFlow::Node sink) {
    exists(DatabaseAccess query |
      sink = query.getAQueryArgument()
    )
  }
}

from SqlInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
  "このクエリは$@からのユーザー入力を含みます。",
  source.getNode(), "ユーザー入力"

3.5 SASTツール比較

機能SonarQubeSemgrepCodeQL
価格Community無料OSS無料OSS無料
対応言語30+30+10+
カスタムルールJava DSLYAMLQL Language
CI統合良好非常に良好GitHub最適化
速度普通非常に高速低速(DB構築)
精度高い高い非常に高い
学習曲線普通低い高い

4. DAST - 動的解析

4.1 DASTとは?

DAST(Dynamic Application Security Testing)は実行中のアプリケーションに実際の攻撃をシミュレーションして脆弱性を検出します。ソースコードが不要なため「ブラックボックステスティング」とも呼ばれます。

4.2 OWASP ZAP自動化

# zap-automation.yaml
env:
  contexts:
    - name: "My Web App"
      urls:
        - "https://staging.example.com"
      includePaths:
        - "https://staging.example.com/.*"
      excludePaths:
        - "https://staging.example.com/logout"
      authentication:
        method: "form"
        parameters:
          loginUrl: "https://staging.example.com/login"
          loginRequestData: "username=test&password=test123"

jobs:
  - type: spider
    parameters:
      context: "My Web App"
      maxDuration: 5
      maxDepth: 10

  - type: spiderAjax
    parameters:
      context: "My Web App"
      maxDuration: 5

  - type: passiveScan-wait
    parameters:
      maxDuration: 10

  - type: activeScan
    parameters:
      context: "My Web App"
      maxRuleDurationInMins: 5
      policy: "API-Scan"

  - type: report
    parameters:
      template: "modern"
      reportDir: "/zap/reports"
      reportFile: "zap-report"
      reportTitle: "ZAP Security Report"
    risks:
      - high
      - medium
      - low
# DockerでZAP自動化スキャン実行
docker run --rm -v $(pwd):/zap/wrk:rw \
  -t zaproxy/zap-stable \
  zap.sh -cmd -autorun /zap/wrk/zap-automation.yaml

# APIスキャン(OpenAPIスペック基盤)
docker run --rm -v $(pwd):/zap/wrk:rw \
  -t zaproxy/zap-stable \
  zap-api-scan.py \
    -t https://staging.example.com/openapi.json \
    -f openapi \
    -r api-report.html

4.3 DASTとSASTの比較

特性SASTDAST
分析タイミングビルド時ランタイム
ソースコード必要はいいいえ
実行環境必要いいえはい
誤検知率高い低い
カバレッジ全コード到達可能なパス
脆弱性タイプコードレベルランタイム/設定
フィードバック速度高速低速

5. SCA - ソフトウェア構成分析

5.1 なぜSCAが重要か?

現代のアプリケーションの80%以上がオープンソースコードで構成されています。Log4Shell(CVE-2021-44228)は単一のオープンソースライブラリの脆弱性(ぜいじゃくせい)が世界的な影響を与えうることを示しました。

5.2 Snyk設定

# .snyk - Snykポリシーファイル
version: v1.5
ignore:
  SNYK-JS-LODASH-590103:
    - '*':
        reason: "該当関数を使用していない"
        expires: "2026-06-01T00:00:00.000Z"
patch: {}

language-settings:
  javascript:
    severity-threshold: high
# Snyk CLI使用法
snyk test                    # 脆弱性検査
snyk monitor                 # 継続的モニタリング登録
snyk test --severity-threshold=high  # 高い重大度のみ
snyk code test               # SASTスキャン
snyk container test myimage:latest  # コンテナスキャン
snyk iac test terraform/     # IaCスキャン

5.3 Dependabot設定

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "09:00"
      timezone: "Asia/Tokyo"
    open-pull-requests-limit: 10
    reviewers:
      - "security-team"
    labels:
      - "dependencies"
      - "security"
    commit-message:
      prefix: "deps"
      include: "scope"
    groups:
      security-patches:
        patterns:
          - "*"
        update-types:
          - "security"

  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "docker"
      - "dependencies"

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "ci"
      - "dependencies"

5.4 Renovate高度な設定

// renovate.json
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:base",
    ":semanticCommits",
    "group:allNonMajor",
    "schedule:weekends"
  ],
  "vulnerabilityAlerts": {
    "enabled": true,
    "labels": ["security"],
    "schedule": ["at any time"]
  },
  "packageRules": [
    {
      "matchUpdateTypes": ["patch"],
      "automerge": true,
      "automergeType": "pr",
      "platformAutomerge": true
    },
    {
      "matchPackagePatterns": ["eslint", "prettier"],
      "groupName": "linting tools",
      "automerge": true
    },
    {
      "matchPackagePatterns": ["^@types/"],
      "groupName": "type definitions",
      "automerge": true
    }
  ],
  "prConcurrentLimit": 5,
  "prHourlyLimit": 2
}

6. コンテナセキュリティ

6.1 コンテナセキュリティの重要性

コンテナイメージにはOSパッケージ、ランタイム、アプリケーション依存関係がすべて含まれます。1つのイメージに数百の脆弱性が存在する可能性があります。

6.2 Trivyイメージスキャン

# 基本イメージスキャン
trivy image myapp:latest

# 重大度フィルタリング
trivy image --severity CRITICAL,HIGH myapp:latest

# 修正可能な脆弱性のみ
trivy image --ignore-unfixed myapp:latest

# SBOM生成
trivy image --format cyclonedx --output sbom.json myapp:latest

# CI用JSON出力と終了コード
trivy image --format json --output results.json \
  --exit-code 1 --severity CRITICAL myapp:latest

# ファイルシステムスキャン(ビルド前)
trivy fs --security-checks vuln,secret,config .

# Kubernetesマニフェストスキャン
trivy config k8s/

6.3 安全なDockerfile作成

# BAD - セキュリティアンチパターン
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3
COPY . /app
RUN pip install -r requirements.txt
USER root
EXPOSE 8080
CMD ["python3", "app.py"]
# GOOD - セキュリティベストプラクティス
# 1. 最小ベースイメージ使用
FROM python:3.12-slim AS builder

# 2. パッケージインストール後キャッシュクリア
RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc && \
    rm -rf /var/lib/apt/lists/*

# 3. 別のビルドステージ
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# 4. 最終イメージは最小化
FROM python:3.12-slim

# 5. 非rootユーザー
RUN groupadd -r appuser && useradd -r -g appuser appuser

# 6. ビルドアーティファクトのみコピー
COPY --from=builder /install /usr/local
COPY --chown=appuser:appuser . /app

WORKDIR /app
USER appuser

# 7. 読み取り専用ファイルシステムサポート
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/health || exit 1

CMD ["python3", "app.py"]

6.4 GrypeとDocker Scout

# Grype - イメージ脆弱性スキャン
grype myapp:latest
grype myapp:latest --only-fixed
grype myapp:latest -o json > grype-results.json

# Docker Scout - Docker Desktop統合
docker scout cves myapp:latest
docker scout recommendations myapp:latest
docker scout quickview myapp:latest

6.5 コンテナセキュリティチェックリスト

コンテナセキュリティチェックリスト:

イメージビルド:
  [x] 最小ベースイメージ(distroless, alpine, slim)
  [x] マルチステージビルド
  [x] 非rootユーザー実行
  [x] 不要なパッケージ削除
  [x] .dockerignore設定
  [x] イメージ署名(cosign)

ランタイム:
  [x] 読み取り専用ファイルシステム
  [x] リソース制限(CPU、メモリ)
  [x] capabilities最小化
  [x] seccomp/AppArmorプロファイル
  [x] ネットワークポリシー適用

レジストリ:
  [x] プライベートレジストリ使用
  [x] イメージ脆弱性スキャン
  [x] タグ不変性設定
  [x] イメージ署名検証

7. シークレット検出

7.1 漏洩するシークレットの現実

GitHubによると、毎年数百万件のシークレットが公開リポジトリにコミットされています。APIキー、パスワード、証明書が漏洩(ろうえい)すると数分で悪用される可能性があります。

7.2 GitLeaks設定

# .gitleaks.toml
title = "Custom Gitleaks Configuration"

[extend]
useDefault = true

[[rules]]
id = "custom-api-key"
description = "Custom API Key Pattern"
regex = '''(?i)api[_-]?key\s*[:=]\s*['"][a-zA-Z0-9]{32,}['"]'''
entropy = 3.5
secretGroup = 0
tags = ["api", "key"]

[[rules]]
id = "private-key-file"
description = "Private Key File Reference"
regex = '''(?i)(private[_-]?key|ssh[_-]?key)\s*[:=]\s*['"].*\.(pem|key|p12)['"]'''
tags = ["key", "private"]

[allowlist]
description = "Global Allowlist"
paths = [
  '''\.gitleaks\.toml''',
  '''test/.*''',
  '''.*_test\.go''',
  '''.*\.test\.(ts|js)'''
]
regexes = [
  '''EXAMPLE_.*''',
  '''REPLACE_ME'''
]
# GitLeaks実行
gitleaks detect --source . --verbose
gitleaks detect --source . --report-format json --report-path leaks.json

# Git履歴全体スキャン
gitleaks detect --source . --log-opts="--all"

# pre-commit hook
gitleaks protect --staged --verbose

7.3 TruffleHog活用

# リポジトリ全体スキャン
trufflehog git file://. --only-verified

# GitHub組織全体スキャン
trufflehog github --org=my-org --only-verified

# Dockerイメージスキャン
trufflehog docker --image=myapp:latest

# S3バケットスキャン
trufflehog s3 --bucket=my-bucket

7.4 pre-commit Hook設定

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: detect-private-key
      - id: check-added-large-files
        args: ['--maxkb=500']

  - repo: https://github.com/returntocorp/semgrep
    rev: v1.50.0
    hooks:
      - id: semgrep
        args: ['--config', 'p/secrets', '--error']

8. サプライチェーンセキュリティ - SBOMとSLSA

8.1 サプライチェーン攻撃事例

事件影響
SolarWinds202018,000以上の機関が被害
Codecov2021CIスクリプト改ざん
ua-parser-js2021npmパッケージハイジャック
Log4Shell2021世界中のJavaアプリに影響
xz utils2024Linuxバックドア試み

8.2 SBOM生成

SBOM(Software Bill of Materials)はソフトウェアに含まれるすべての構成要素(こうせいようそ)のリストです。

# CycloneDXフォーマットSBOM生成
# npmプロジェクト
npx @cyclonedx/cyclonedx-npm --output-file sbom.json

# Pythonプロジェクト
cyclonedx-py requirements requirements.txt -o sbom.json

# コンテナイメージ
trivy image --format cyclonedx -o sbom.json myapp:latest
syft myapp:latest -o cyclonedx-json > sbom.json

# SPDXフォーマット
syft myapp:latest -o spdx-json > sbom-spdx.json
// SBOM例(CycloneDX簡略版)
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "version": 1,
  "metadata": {
    "component": {
      "type": "application",
      "name": "my-web-app",
      "version": "2.1.0"
    }
  },
  "components": [
    {
      "type": "library",
      "name": "express",
      "version": "4.18.2",
      "purl": "pkg:npm/express@4.18.2",
      "licenses": [{ "license": { "id": "MIT" } }]
    },
    {
      "type": "library",
      "name": "lodash",
      "version": "4.17.21",
      "purl": "pkg:npm/lodash@4.17.21"
    }
  ]
}

8.3 SLSAフレームワーク

SLSA(Supply-chain Levels for Software Artifacts)はサプライチェーンセキュリティの成熟度(せいじゅくど)を測定するフレームワークです。

SLSAレベル:
┌──────────────┬─────────────────────────────────────┐
SLSA Level 0 │ セキュリティ保証なし                    │
SLSA Level 1 │ ビルドプロセス文書化(provenance)       │
SLSA Level 2 │ ホスティングビルド、署名付きprovenance    │
SLSA Level 3 │ 隔離ビルド、改ざん防止                  │
└──────────────┴─────────────────────────────────────┘

8.4 Sigstoreでアーティファクト署名

# cosignでコンテナイメージ署名
cosign sign --key cosign.key myregistry/myapp:v1.0.0

# キーレス署名(OIDC基盤)
cosign sign myregistry/myapp:v1.0.0

# 署名検証
cosign verify --key cosign.pub myregistry/myapp:v1.0.0

# SBOM添付
cosign attach sbom --sbom sbom.json myregistry/myapp:v1.0.0

# アーティファクト証明(attestation)生成
cosign attest --predicate provenance.json \
  --type slsaprovenance \
  myregistry/myapp:v1.0.0

9. Policy-as-Code

9.1 OPA(Open Policy Agent)

# policy/kubernetes.rego
package kubernetes.admission

# rootコンテナ禁止
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  container.securityContext.runAsUser == 0
  msg := sprintf("コンテナ'%s'がrootで実行されます", [container.name])
}

# latestタグ禁止
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  endswith(container.image, ":latest")
  msg := sprintf("コンテナ'%s'がlatestタグを使用しています", [container.name])
}

# リソース制限必須
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.resources.limits
  msg := sprintf("コンテナ'%s'にリソース制限がありません", [container.name])
}

# 読み取り専用ルートファイルシステム必須
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.securityContext.readOnlyRootFilesystem
  msg := sprintf("コンテナ'%s'が読み取り専用ファイルシステムを使用していません", [container.name])
}

9.2 Kyvernoポリシー

# kyverno-policies.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-team-label
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "すべてのPodには'team'ラベルが必要です"
        pattern:
          metadata:
            labels:
              team: "?*"

---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged
spec:
  validationFailureAction: Enforce
  rules:
    - name: no-privileged-containers
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Privilegedコンテナは許可されていません"
        pattern:
          spec:
            containers:
              - securityContext:
                  privileged: "false"

9.3 ConftestでIaC検証

# ConftestでTerraform検証
conftest test terraform/ --policy policy/

# Dockerfile検証
conftest test Dockerfile --policy policy/docker/

# Kubernetesマニフェスト検証
conftest test k8s/ --policy policy/kubernetes/
# policy/docker/dockerfile.rego
package main

deny[msg] {
  input[i].Cmd == "from"
  val := input[i].Value
  contains(val[0], ":latest")
  msg := "FROMでlatestタグの使用は禁止です"
}

deny[msg] {
  input[i].Cmd == "user"
  val := input[i].Value
  val[0] == "root"
  msg := "USER rootの使用は禁止です"
}

10. GitHub Actions統合セキュリティパイプライン

10.1 総合セキュリティワークフロー

# .github/workflows/security.yml
name: Security Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 6 * * 1'  # 毎週月曜日午前6時

permissions:
  contents: read
  security-events: write
  pull-requests: write

jobs:
  # Stage 1: シークレット検出
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: GitLeaks Scan
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # Stage 2: SAST
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Semgrep Scan
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/owasp-top-ten
            p/typescript
            p/react
          generateSarif: "1"

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: semgrep.sarif
        if: always()

  # Stage 3: SCA
  sca:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Snyk Security Scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

  # Stage 4: コンテナセキュリティ
  container-security:
    runs-on: ubuntu-latest
    needs: [sast]
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker Image
        run: docker build -t myapp:test .

      - name: Trivy Image Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:test'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Upload Trivy SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'
        if: always()

  # Stage 5: SBOM生成
  sbom:
    runs-on: ubuntu-latest
    needs: [container-security]
    steps:
      - uses: actions/checkout@v4

      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          image: myapp:test
          format: cyclonedx-json
          output-file: sbom.json

      - name: Upload SBOM
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path: sbom.json

  # 最終: セキュリティゲート
  security-gate:
    runs-on: ubuntu-latest
    needs: [secret-scan, sast, sca, container-security]
    steps:
      - name: Security Gate Check
        run: |
          echo "All security checks passed!"
          echo "Pipeline completed at $(date)"

10.2 セキュリティパイプラインメトリクス

成功するDevSecOpsプログラムで追跡すべき主要メトリクスです。

メトリクス説明目標
MTTR脆弱性平均修正時間Critical: 24時間以内
脆弱性密度コード1000行あたりの脆弱性数0.5以下
スキャンカバレッジセキュリティスキャン適用リポジトリ割合100%
誤検知率全発見中の誤検知割合20%以下
パイプライン通過率セキュリティゲート通過率85%以上
依存関係最新度最新バージョン依存関係の割合80%以上

11. 実践クイズ

Q1: SASTとDASTの違いは何ですか?

回答:

  • SASTはソースコードを静的に解析して脆弱性を見つけます。ビルド段階で実行され、実行環境は不要です。
  • DASTは実行中のアプリケーションに攻撃をシミュレーションします。ランタイム環境が必要で、ソースコードなしでも可能です。
  • SASTは誤検知率が高いですが全コードを分析でき、DASTは誤検知率が低いですが到達可能なパスのみ分析します。
  • 両方を使用するのが理想的で、これをIAST(Interactive AST)とも呼びます。
Q2: Shift-Leftセキュリティがコストを削減する理由は?

回答:

  • 欠陥修正コストは発見時点が遅いほど指数関数的に増加します。
  • 要件段階で発見すれば1x、設計5x、実装10x、テスト20x、運用30x、インシデント後100x+のコストがかかります。
  • Shift-Leftはセキュリティを開発初期(左側)に移動させ、欠陥を早期に発見するためコストが削減されます。
  • また、開発者がコードを書く時点でフィードバックを受けるため、コンテキストスイッチコストも削減されます。
Q3: SBOMがサプライチェーンセキュリティで重要な理由は?

回答:

  • SBOMはソフトウェアに含まれるすべての構成要素(ライブラリ、フレームワークなど)のリストです。
  • Log4Shellのような脆弱性が発見された場合、SBOMで影響を受けるシステムを即座に特定できます。
  • ライセンスコンプライアンスの確認にも不可欠です。
  • 米国大統領令(EO 14028)では政府ソフトウェアサプライヤーにSBOM提出を義務化しました。
  • CycloneDXとSPDXが代表的なSBOM標準フォーマットです。
Q4: 安全なコンテナイメージを作るためのベストプラクティス5つは?

回答:

  1. 最小ベースイメージ: distroless、alpine、slimイメージ使用で攻撃対象面を縮小
  2. マルチステージビルド: ビルドツールを最終イメージに含めない
  3. 非rootユーザー: USER命令でroot以外のユーザーで実行
  4. イメージ署名: cosignでイメージ署名と検証
  5. 定期的スキャン: Trivy/Grypeでイメージ脆弱性を定期スキャン

追加事項: 読み取り専用ファイルシステム、capabilities最小化、不要パッケージ削除

Q5: GitHub Actionsでセキュリティパイプラインを構成する際の実行順序は?

回答:

推奨順序:

  1. シークレット検出(GitLeaks)- 最速で最も重要
  2. SAST(Semgrep/CodeQL)- コードレベル脆弱性
  3. SCA(Snyk/Dependabot)- 依存関係脆弱性
  4. IaCスキャン(Trivy/Conftest)- インフラ設定検証
  5. コンテナセキュリティ(Trivy)- イメージビルド後スキャン
  6. SBOM生成 - アーティファクト一覧生成
  7. DAST(ZAP)- ステージングデプロイ後ランタイムテスト
  8. セキュリティゲート - 全結果を総合判断

シークレット検出とSASTは並列実行可能で、DASTはデプロイ後のみ実行可能です。


12. 参考資料

  1. OWASP DevSecOps Guideline
  2. NIST Secure Software Development Framework (SSDF)
  3. SLSA - Supply-chain Levels for Software Artifacts
  4. Sigstore - Software Signing
  5. Semgrep Registry
  6. GitHub Security Lab
  7. Trivy Documentation
  8. Snyk Learn - Security Education
  9. OWASP Top 10 (2021)
  10. CycloneDX SBOM Standard
  11. OPA - Open Policy Agent
  12. Kyverno Documentation
  13. CISA SBOM Resources
  14. Google SLSA GitHub Generator