DevSecOpsとは何か
DevSecOpsは、開発(Development)、セキュリティ(Security)、運用(Operations)を統合したアプローチです。従来のウォーターフォール型開発では、セキュリティテストはリリース直前に行われていましたが、DevSecOpsでは開発の初期段階からセキュリティを組み込む「シフトレフト」の考え方を採用します。
2025年現在、DevSecOpsは単なるバズワードから成熟した実践へと進化しました。クラウドネイティブアーキテクチャの普及、サプライチェーン攻撃の増加、規制要件の厳格化により、組織はセキュリティを開発プロセスに深く統合する必要に迫られています。
DevSecOps成熟度モデル
組織のDevSecOps成熟度を評価するためのフレームワークを紹介します。
レベル1: 初期段階(Ad-hoc)
- セキュリティテストは手動で不定期に実施
- 開発チームとセキュリティチームの連携が限定的
- 脆弱性の発見から修正まで数週間〜数ヶ月
レベル2: 基礎段階(Basic)
- 基本的なSASTツールをCI/CDに導入
- セキュリティポリシーが文書化されている
- 定期的なセキュリティレビューを実施
レベル3: 標準化段階(Standardized)
- 複数のセキュリティツールがパイプラインに統合
- セキュリティゲートによる自動ブロック機能
- セキュリティメトリクスの可視化
レベル4: 最適化段階(Optimized)
- リスクベースの脆弱性優先順位付け
- 開発者向けセキュリティトレーニングの体系化
- インシデント対応の自動化
レベル5: 革新段階(Innovative)
- AIを活用した脆弱性予測と自動修正
- セキュリティがビジネス価値として認識される
- 継続的なセキュリティ改善文化の確立
セキュリティツールチェーンの全体像
SAST(Static Application Security Testing)
SASTは、ソースコードを静的に解析して脆弱性を検出します。コードがコミットされた時点で実行され、SQLインジェクション、XSS、バッファオーバーフローなどの脆弱性を早期に発見できます。
# GitHub Actions での SAST 統合例
name: SAST Scan
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript, typescript
queries: +security-extended
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:javascript"
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/secrets
p/owasp-top-ten
generateSarif: true
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep.sarif
主要なSASTツール:
- CodeQL: GitHubが提供する強力な静的解析エンジン
- Semgrep: 軽量で高速、カスタムルールが書きやすい
- SonarQube: コード品質とセキュリティを統合的に管理
- Checkmarx: エンタープライズ向けの包括的なSASTソリューション
DAST(Dynamic Application Security Testing)
DASTは、実行中のアプリケーションに対して外部から攻撃をシミュレートします。SASTでは検出できない実行時の脆弱性を発見できます。
# DAST スキャンのCI/CD統合
name: DAST Scan
on:
deployment:
types: [completed]
jobs:
dast:
runs-on: ubuntu-latest
if: github.event.deployment.environment == 'staging'
steps:
- name: ZAP Full Scan
uses: zaproxy/action-full-scan@v0.10.0
with:
target: "https://staging.example.com"
rules_file_name: ".zap/rules.tsv"
cmd_options: "-a -j -l WARN"
issue_title: "ZAP Scan Report"
fail_action: true
allow_issue_writing: true
- name: Nuclei Scan
uses: projectdiscovery/nuclei-action@main
with:
target: "https://staging.example.com"
templates: "cves,vulnerabilities,misconfiguration"
output: "nuclei-report.txt"
sarif-export: "nuclei.sarif"
- name: Upload DAST Results
uses: actions/upload-artifact@v4
with:
name: dast-results
path: |
nuclei-report.txt
nuclei.sarif
SCA(Software Composition Analysis)
SCAは、オープンソースコンポーネントとサードパーティライブラリの脆弱性を検出します。2025年現在、サプライチェーン攻撃の増加により、SCAの重要性は飛躍的に高まっています。
# SCA 統合パイプライン
name: Dependency Security Scan
on:
push:
paths:
- "package.json"
- "package-lock.json"
- "requirements.txt"
- "go.mod"
- "Cargo.toml"
schedule:
- cron: "0 6 * * *" # 毎日午前6時に実行
jobs:
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high --sarif-file-output=snyk.sarif
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: "fs"
scan-ref: "."
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
- name: SBOM Generation
uses: anchore/sbom-action@v0
with:
format: spdx-json
output-file: sbom.spdx.json
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: high
deny-licenses: GPL-3.0, AGPL-3.0
allow-ghsas: false
IAST(Interactive Application Security Testing)
IASTは、アプリケーション内部にエージェントを配置し、実行時の動作を監視します。SASTとDASTの利点を組み合わせた手法です。
# IAST エージェント設定例(Contrast Security)
agent:
java:
enable: true
standalone_app_name: my-application
server:
name: production-server
environment: production
# ルール設定
assess:
enable: true
rules:
disabled_rules:
- reflected-xss # 特定のルールを無効化
# 保護モード
protect:
enable: true
rules:
bot-blocker:
mode: BLOCK
sql-injection:
mode: BLOCK
cmd-injection:
mode: BLOCK
# レポート設定
reporting:
period: 3000
# プロキシ設定
proxy:
enable: false
CI/CD統合の実践パターン
パターン1: ゲートキーパーモデル
各ステージにセキュリティゲートを設置し、基準を満たさない場合はパイプラインを停止します。
# GitLab CI/CD でのゲートキーパー実装
stages:
- build
- test
- security-gate-1
- integration-test
- security-gate-2
- deploy-staging
- security-gate-3
- deploy-production
variables:
SEVERITY_THRESHOLD: "HIGH"
MAX_CRITICAL_VULNS: 0
MAX_HIGH_VULNS: 5
sast-scan:
stage: security-gate-1
image: registry.gitlab.com/security-products/sast:latest
script:
- /analyzer run
artifacts:
reports:
sast: gl-sast-report.json
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
security-gate-evaluation-1:
stage: security-gate-1
needs: [sast-scan]
script:
- |
CRITICAL_COUNT=$(jq '[.vulnerabilities[] | select(.severity=="Critical")] | length' gl-sast-report.json)
HIGH_COUNT=$(jq '[.vulnerabilities[] | select(.severity=="High")] | length' gl-sast-report.json)
echo "Critical vulnerabilities: $CRITICAL_COUNT"
echo "High vulnerabilities: $HIGH_COUNT"
if [ "$CRITICAL_COUNT" -gt "$MAX_CRITICAL_VULNS" ]; then
echo "Security gate failed: Too many critical vulnerabilities"
exit 1
fi
if [ "$HIGH_COUNT" -gt "$MAX_HIGH_VULNS" ]; then
echo "Security gate failed: Too many high vulnerabilities"
exit 1
fi
echo "Security gate passed"
container-scan:
stage: security-gate-2
image: aquasec/trivy:latest
script:
- trivy image --exit-code 1 --severity CRITICAL,HIGH $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
allow_failure: false
dast-scan:
stage: security-gate-3
image: owasp/zap2docker-stable
script:
- zap-full-scan.py -t $STAGING_URL -r zap-report.html -x zap-report.xml
artifacts:
paths:
- zap-report.html
- zap-report.xml
when: always
パターン2: リスクベースアプローチ
変更の影響範囲とリスクレベルに応じて、スキャンの深度を動的に調整します。
# リスクベースのスキャン設定
name: Risk-Based Security Scan
on:
pull_request:
types: [opened, synchronize]
jobs:
risk-assessment:
runs-on: ubuntu-latest
outputs:
risk_level: ${{ steps.assess.outputs.risk_level }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Assess Risk Level
id: assess
run: |
# 変更されたファイルを取得
CHANGED_FILES=$(git diff --name-only origin/main...HEAD)
RISK_LEVEL="low"
# 認証・認可関連の変更
if echo "$CHANGED_FILES" | grep -qE "(auth|login|session|token|jwt|oauth)"; then
RISK_LEVEL="critical"
# 決済・金融関連の変更
elif echo "$CHANGED_FILES" | grep -qE "(payment|billing|transaction|stripe|paypal)"; then
RISK_LEVEL="critical"
# API・エンドポイントの変更
elif echo "$CHANGED_FILES" | grep -qE "(api/|routes/|controllers/)"; then
RISK_LEVEL="high"
# データベース・モデルの変更
elif echo "$CHANGED_FILES" | grep -qE "(models/|migrations/|schema)"; then
RISK_LEVEL="high"
# 設定ファイルの変更
elif echo "$CHANGED_FILES" | grep -qE "(config|\.env|secrets)"; then
RISK_LEVEL="medium"
fi
echo "risk_level=$RISK_LEVEL" >> $GITHUB_OUTPUT
echo "Risk Level: $RISK_LEVEL"
security-scan:
needs: risk-assessment
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Basic Scan (All PRs)
run: |
# 基本的なシークレット検出
docker run --rm -v $(pwd):/repo trufflesecurity/trufflehog:latest \
git file:///repo --only-verified
- name: Extended Scan (Medium+ Risk)
if: needs.risk-assessment.outputs.risk_level != 'low'
run: |
# SAST スキャン
semgrep --config=auto --sarif --output=semgrep.sarif .
- name: Deep Scan (High+ Risk)
if: needs.risk-assessment.outputs.risk_level == 'high' || needs.risk-assessment.outputs.risk_level == 'critical'
run: |
# 依存関係の深度スキャン
snyk test --all-projects --severity-threshold=medium
# コンテナイメージスキャン
trivy image --severity HIGH,CRITICAL ${{ env.IMAGE_NAME }}
- name: Critical Scan (Critical Risk)
if: needs.risk-assessment.outputs.risk_level == 'critical'
run: |
# 手動レビュー要求
gh pr edit ${{ github.event.pull_request.number }} \
--add-label "security-review-required"
# セキュリティチームへの通知
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H "Content-Type: application/json" \
-d '{"text": "Critical risk PR requires security review: ${{ github.event.pull_request.html_url }}"}'
セキュリティゲート設計のベストプラクティス
ゲート基準の定義
# security-gates.yaml - セキュリティゲート設定ファイル
gates:
# 開発ブランチへのマージ前ゲート
pre-merge:
name: "Pre-Merge Security Gate"
enabled: true
blocking: true
criteria:
sast:
critical: 0
high: 3
medium: 10
new_issues_only: true
secrets:
any_detected: false
sca:
critical: 0
high: 5
license_violations: false
# ステージング環境デプロイ前ゲート
pre-staging:
name: "Pre-Staging Security Gate"
enabled: true
blocking: true
criteria:
sast:
critical: 0
high: 0
medium: 5
dast:
critical: 0
high: 2
container:
critical: 0
high: 3
# 本番環境デプロイ前ゲート
pre-production:
name: "Pre-Production Security Gate"
enabled: true
blocking: true
criteria:
sast:
critical: 0
high: 0
medium: 0
dast:
critical: 0
high: 0
medium: 3
sca:
critical: 0
high: 0
eol_components: false
container:
critical: 0
high: 0
compliance:
pci_dss: true
soc2: true
gdpr: true
# 緊急デプロイ用の例外ゲート
emergency:
name: "Emergency Deploy Gate"
enabled: true
blocking: false
requires_approval:
- security-team-lead
- ciso
criteria:
sast:
critical: 0
secrets:
any_detected: false
audit:
enabled: true
retention_days: 365
例外処理とリスク受容
# 脆弱性の例外処理設定
exceptions:
# 既知の誤検出
false_positives:
- id: "CVE-2024-12345"
reason: "開発環境のみで使用、本番には影響なし"
approved_by: "security-team"
expires: "2025-06-30"
# リスク受容
risk_accepted:
- id: "SNYK-JS-LODASH-1018905"
reason: "影響を受ける関数は使用していない"
approved_by: "ciso"
expires: "2025-03-31"
compensating_controls:
- "WAFルールで入力値を検証"
- "該当エンドポイントのレート制限"
# 一時的な例外(ホットフィックス用)
temporary:
- id: "HIGH-VULN-001"
reason: "緊急のビジネス要件、修正チケット作成済み"
approved_by: "vp-engineering"
expires: "2025-01-20"
jira_ticket: "SEC-1234"
Infrastructure as Code(IaC)セキュリティ
クラウドインフラの設定ミスは、データ漏洩の主要な原因の一つです。IaCスキャンをパイプラインに統合することで、デプロイ前に設定の問題を検出できます。
# IaC セキュリティスキャン
name: IaC Security Scan
on:
push:
paths:
- "terraform/**"
- "cloudformation/**"
- "kubernetes/**"
- "helm/**"
jobs:
iac-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkov Scan
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/
framework: terraform
soft_fail: false
output_format: sarif
output_file_path: checkov.sarif
- name: tfsec Scan
uses: aquasecurity/tfsec-action@v1.0.3
with:
working_directory: terraform/
soft_fail: false
- name: Trivy Config Scan
uses: aquasecurity/trivy-action@master
with:
scan-type: "config"
scan-ref: "."
format: "sarif"
output: "trivy-config.sarif"
- name: KICS Scan
uses: Checkmarx/kics-github-action@v1.7.0
with:
path: "."
output_path: "kics-results"
output_formats: "sarif,json"
fail_on: high,medium
- name: Upload Results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: .
Terraformセキュリティポリシーの例
# Sentinel Policy(HashiCorp Sentinel)
import "tfplan/v2" as tfplan
# S3バケットは暗号化必須
s3_bucket_encryption = rule {
all tfplan.resource_changes as _, rc {
rc.type is "aws_s3_bucket" and
rc.change.after.server_side_encryption_configuration is not null
}
}
# セキュリティグループで0.0.0.0/0へのインバウンドを禁止
no_public_ingress = rule {
all tfplan.resource_changes as _, rc {
rc.type is "aws_security_group_rule" and
rc.change.after.type is "ingress" implies
rc.change.after.cidr_blocks not contains "0.0.0.0/0"
}
}
# RDSは暗号化とバックアップ必須
rds_security = rule {
all tfplan.resource_changes as _, rc {
rc.type is "aws_db_instance" implies (
rc.change.after.storage_encrypted is true and
rc.change.after.backup_retention_period > 0
)
}
}
main = rule {
s3_bucket_encryption and
no_public_ingress and
rds_security
}
シークレット管理とスキャン
# シークレット検出の包括的設定
name: Secret Detection
on:
push:
branches: ["*"]
pull_request:
branches: [main, develop]
jobs:
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Git履歴全体をスキャン
- name: TruffleHog Scan
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --only-verified
# GitLeaks でパターンマッチング
- name: Gitleaks Scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
# AWS認証情報の特化スキャン
- name: AWS Credential Scan
run: |
# AWS キーパターンの検出
if grep -rE "(AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}" --include="*.{js,ts,py,go,java,json,yaml,yml,env}" .; then
echo "AWS credentials detected!"
exit 1
fi
# Pre-commit hookの設定確認
- name: Verify Pre-commit Hooks
run: |
if [ ! -f ".pre-commit-config.yaml" ]; then
echo "Warning: pre-commit config not found"
exit 1
fi
文化と組織の変革
技術的なツールだけでは、DevSecOpsは成功しません。組織文化の変革が不可欠です。
セキュリティチャンピオンプログラム
各開発チームにセキュリティチャンピオンを配置し、セキュリティ意識を組織全体に浸透させます。
# セキュリティチャンピオン責任マトリクス
security_champions:
responsibilities:
- name: "コードレビュー"
description: "セキュリティ観点からのコードレビュー実施"
frequency: "全PR"
- name: "脆弱性トリアージ"
description: "チーム内の脆弱性優先順位付けと割り当て"
frequency: "週次"
- name: "セキュリティトレーニング"
description: "チームメンバーへのセキュリティ教育"
frequency: "月次"
- name: "インシデント対応"
description: "セキュリティインシデント発生時の初動対応"
frequency: "発生時"
training_path:
- level: "beginner"
courses:
- "OWASP Top 10 概要"
- "セキュアコーディング基礎"
certification: "Security Champion Bronze"
- level: "intermediate"
courses:
- "脅威モデリング実践"
- "ペネトレーションテスト基礎"
certification: "Security Champion Silver"
- level: "advanced"
courses:
- "アプリケーションセキュリティアーキテクチャ"
- "インシデントレスポンス"
certification: "Security Champion Gold"
メトリクスとKPI
DevSecOpsの効果を測定するための主要指標を設定します。
# DevSecOps KPI ダッシュボード設定
metrics:
# 脆弱性関連
vulnerability:
- name: "MTTR (Mean Time To Remediate)"
target:
critical: "24 hours"
high: "7 days"
medium: "30 days"
current: "$CURRENT_MTTR"
- name: "Vulnerability Escape Rate"
description: "本番環境で発見された脆弱性の割合"
target: "< 5%"
current: "$ESCAPE_RATE"
- name: "Security Debt"
description: "未修正の脆弱性の総数"
target: "< 50"
current: "$SECURITY_DEBT"
# プロセス関連
process:
- name: "Security Gate Pass Rate"
description: "初回でセキュリティゲートを通過したビルドの割合"
target: "> 85%"
current: "$PASS_RATE"
- name: "Developer Security Training Coverage"
description: "セキュリティトレーニングを完了した開発者の割合"
target: "100%"
current: "$TRAINING_COVERAGE"
# ビジネス関連
business:
- name: "Security Incident Count"
target: "0"
current: "$INCIDENT_COUNT"
- name: "Compliance Audit Findings"
target: "< 3"
current: "$AUDIT_FINDINGS"
2025年のベストプラクティス
1. AIを活用した脆弱性検出
# AI支援セキュリティスキャン
ai_security:
vulnerability_prediction:
enabled: true
model: "security-ml-v3"
features:
- code_complexity
- historical_vulnerabilities
- developer_experience
- component_age
threshold: 0.75
auto_remediation:
enabled: true
confidence_threshold: 0.95
supported_fixes:
- sql_injection_parameterization
- xss_output_encoding
- dependency_upgrade
require_approval: true
false_positive_reduction:
enabled: true
learning_from_feedback: true
minimum_training_samples: 100
2. サプライチェーンセキュリティ
# SLSA(Supply-chain Levels for Software Artifacts)準拠
slsa:
level: 3
requirements:
source:
- version_controlled: true
- verified_history: true
- two_person_reviewed: true
build:
- scripted_build: true
- build_service: true
- ephemeral_environment: true
- isolated: true
provenance:
- available: true
- authenticated: true
- service_generated: true
- non_falsifiable: true
attestation:
format: "in-toto"
sign_with: "sigstore/cosign"
verify_on_deploy: true
3. ゼロトラストセキュリティの統合
# ゼロトラスト原則のCI/CD適用
zero_trust_pipeline:
# すべてのアクセスを検証
identity_verification:
- service_accounts: "workload_identity"
- human_access: "mfa_required"
- external_services: "mtls"
# 最小権限の原則
least_privilege:
- pipeline_permissions: "minimal"
- secret_access: "just_in_time"
- artifact_access: "signed_required"
# 継続的な検証
continuous_verification:
- artifact_integrity: "every_stage"
- runtime_protection: "enabled"
- anomaly_detection: "ml_based"
まとめ
DevSecOpsは2025年において、もはやオプションではなく必須の実践となっています。成功の鍵は、適切なツールの選択、CI/CDへの緊密な統合、そして組織文化の変革にあります。
セキュリティを開発の最初から組み込む「シフトレフト」アプローチにより、脆弱性の修正コストを大幅に削減し、より安全なソフトウェアを迅速にデリバリーすることが可能になります。
継続的な学習と改善を通じて、組織全体でセキュリティ意識を高め、DevSecOpsの成熟度を段階的に向上させていくことが重要です。
← 一覧に戻る