sbom-supply-chain について
sbom-supply-chain は、ソフトウェアのビルドとリリースに携わるチーム向けのスキルです。SBOM の生成、脆弱性チェック、成果物の検証に加え、署名や証明、サプライチェーンポリシーの適用を扱います。
主な機能
- 01CycloneDX と SPDX の SBOM 生成
- 02SBOM に基づく脆弱性照合
- 03cosign による成果物の署名
- 04SBOM と来歴証明の添付
- 05検証ポリシーの適用
活用シーン
- 01イメージやアプリケーションビルドの SBOM 作成
- 02デプロイ前の依存関係チェック
- 03成果物の署名と来歴証明の必須化
- 04セキュリティレビューや SLSA 要件への準備
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill sbom-supply-chainインストール後、Claude Code で/sbom-supply-chainを入力して読み込まれたか確認します。
詳細
SBOM とサプライチェーンセキュリティ
再現可能なメタデータと検証ゲートにより、リリースへの信頼性を高めます。
このスキルを使う場面
次のような場合にこのスキルを使います。
- コンテナイメージやアプリケーションのビルド向けに SBOM を生成する
- デプロイ前に依存関係を検証する
- 署名済みアーティファクトと来歴のポリシーを適用する
- SOC2、ISO 27001、または顧客のセキュリティレビューに備える
- SLSA フレームワークの要件を実装する
- サプライチェーンの脆弱性(Log4Shell のようなインシデントなど)に対応する
前提条件
- SBOM 生成用の
syftがインストールされていること - CycloneDX SBOM 生成用の
cdxgenがインストールされていること - SBOM に対する脆弱性マッチング用の
grype - 署名とアテステーション用の
cosignv2+ - OCI アーティファクトに対応したコンテナレジストリ
- キーレス署名用の OIDC ID を備えた CI/CD パイプライン
SBOM 形式
CycloneDX と SPDX の比較
comparison:
cyclonedx:
standard: "OWASP CycloneDX"
focus: "Application security, vulnerability tracking"
formats: ["JSON", "XML", "Protocol Buffers"]
strengths:
- Vulnerability references (VEX support)
- Service and API dependency tracking
- Hardware BOM support
best_for: "Security-focused SBOM, vulnerability management"
spdx:
standard: "Linux Foundation SPDX (ISO/IEC 5962:2021)"
focus: "License compliance, legal review"
formats: ["JSON", "RDF/XML", "Tag-Value", "YAML"]
strengths:
- ISO standard
- License expression language
- Relationship modeling
best_for: "License compliance, regulatory requirements"
Syft による SBOM 生成
# Generate SBOM for a container image (CycloneDX JSON)
syft ghcr.io/acme/api:v1.2.3 -o cyclonedx-json > sbom-cyclonedx.json
# Generate SBOM in SPDX format
syft ghcr.io/acme/api:v1.2.3 -o spdx-json > sbom-spdx.json
# Generate SBOM from a local directory (source code)
syft dir:. -o cyclonedx-json > sbom-source.json
# Generate SBOM from a Dockerfile/built image
syft docker:my-local-image:latest -o cyclonedx-json > sbom-local.json
# Generate SBOM for a specific package ecosystem
syft dir:. --catalogers python -o cyclonedx-json > sbom-python.json
# Include file hashes for deeper analysis
syft ghcr.io/acme/api:v1.2.3 -o cyclonedx-json --file-metadata > sbom-with-hashes.json
# Multiple output formats simultaneously
syft ghcr.io/acme/api:v1.2.3 \
-o cyclonedx-json=sbom-cdx.json \
-o spdx-json=sbom-spdx.json \
-o table=sbom-summary.txt
cdxgen による SBOM 生成
# Install cdxgen
npm install -g @cyclonedx/cdxgen
# Generate CycloneDX SBOM for a project directory
cdxgen -o sbom.json .
# Specify project type
cdxgen -t python -o sbom-python.json .
cdxgen -t java -o sbom-java.json .
cdxgen -t node -o sbom-node.json .
cdxgen -t go -o sbom-go.json .
# Generate SBOM with evidence (call stacks, file occurrences)
cdxgen --evidence -o sbom-with-evidence.json .
# Generate for a container image
cdxgen -t docker -o sbom-container.json ghcr.io/acme/api:v1.2.3
# Generate with deep analysis (slower but more accurate)
cdxgen --deep -o sbom-deep.json .
# Output in different formats
cdxgen -o sbom.xml --format xml .
脆弱性マッチング
# Scan SBOM for vulnerabilities with Grype
grype sbom:sbom-cyclonedx.json
# Fail on critical/high vulnerabilities
grype sbom:sbom-cyclonedx.json --fail-on high
# Output as JSON for CI processing
grype sbom:sbom-cyclonedx.json -o json > vulnerability-report.json
# Scan container image directly
grype ghcr.io/acme/api:v1.2.3
# Use Trivy with SBOM input
trivy sbom sbom-cyclonedx.json
# Trivy scan with severity filter
trivy sbom sbom-cyclonedx.json --severity CRITICAL,HIGH --exit-code 1
Cosign による署名とアテステーション
イメージの署名
# Keyless signing (recommended - uses OIDC identity from CI)
cosign sign ghcr.io/acme/api@sha256:abc123...
# Sign with a key pair
cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/acme/api@sha256:abc123...
# Verify keyless signature
cosign verify \
--certificate-identity=https://github.com/acme/api/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/acme/api@sha256:abc123...
# Verify with key
cosign verify --key cosign.pub ghcr.io/acme/api@sha256:abc123...
SBOM アテステーション
# Attach SBOM as an in-toto attestation to a container image
cosign attest --predicate sbom-cyclonedx.json \
--type cyclonedx \
ghcr.io/acme/api@sha256:abc123...
# Attach SPDX SBOM
cosign attest --predicate sbom-spdx.json \
--type spdx \
ghcr.io/acme/api@sha256:abc123...
# Verify SBOM attestation
cosign verify-attestation \
--type cyclonedx \
--certificate-identity=https://github.com/acme/api/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/acme/api@sha256:abc123...
# Extract the SBOM from attestation
cosign verify-attestation --type cyclonedx \
--certificate-identity=... --certificate-oidc-issuer=... \
ghcr.io/acme/api@sha256:abc123... | jq -r '.payload' | base64 -d | jq '.predicate'
In-toto 来歴アテステーション
# Create a custom provenance attestation
cat > provenance.json << 'EOF'
{
"buildType": "https://github.com/acme/build-system@v1",
"builder": {
"id": "https://github.com/acme/api/.github/workflows/build.yml@refs/heads/main"
},
"invocation": {
"configSource": {
"uri": "git+https://github.com/acme/api@refs/heads/main",
"digest": { "sha1": "abc123def456" },
"entryPoint": ".github/workflows/build.yml"
}
},
"metadata": {
"buildStartedOn": "2025-01-15T10:00:00Z",
"buildFinishedOn": "2025-01-15T10:05:00Z",
"completeness": {
"parameters": true,
"environment": true,
"materials": true
}
},
"materials": [
{
"uri": "git+https://github.com/acme/api@refs/heads/main",
"digest": { "sha1": "abc123def456" }
},
{
"uri": "pkg:docker/[email protected]",
"digest": { "sha256": "def456..." }
}
]
}
EOF
# Attach provenance attestation
cosign attest --predicate provenance.json \
--type slsaprovenance \
ghcr.io/acme/api@sha256:abc123...
CI/CD パイプラインへの統合
# .github/workflows/sbom-supply-chain.yml
name: Build with SBOM and Signing
on:
push:
tags: ['v*']
permissions:
contents: read
packages: write
id-token: write # Required for keyless signing
jobs:
build-sign-attest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
id: build
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
- name: Install tools
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
- name: Generate SBOM
run: |
syft ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }} \
-o cyclonedx-json=sbom-cdx.json \
-o spdx-json=sbom-spdx.json
- name: Scan SBOM for vulnerabilities
run: |
grype sbom:sbom-cdx.json --fail-on critical -o json > vuln-report.json
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign image (keyless)
run: |
cosign sign ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
- name: Attach SBOM attestation
run: |
cosign attest --predicate sbom-cdx.json \
--type cyclonedx \
ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: sbom-and-reports
path: |
sbom-cdx.json
sbom-spdx.json
vuln-report.json
ポリシーの適用
Kyverno ポリシー:SBOM を含む署名済みイメージを必須にする
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images-with-sbom
spec:
validationFailureAction: Enforce
webhookTimeoutSeconds: 30
rules:
- name: verify-signature
match:
any:
- resources:
kinds: ["Pod"]
verifyImages:
- imageReferences: ["ghcr.io/acme/*"]
attestors:
- entries:
- keyless:
subject: "https://github.com/acme/*"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: "https://rekor.sigstore.dev"
attestations:
- type: cyclonedx
conditions:
- all:
- key: "{{ components[].name }}"
operator: AllNotIn
value: ["log4j-core"]
OPA ポリシー:デプロイ前に SBOM を検証する
package sbom.verify
import rego.v1
default allow := false
allow if {
sbom_present
no_critical_vulns
signed_by_ci
}
sbom_present if {
input.attestations.cyclonedx != null
count(input.attestations.cyclonedx.components) > 0
}
no_critical_vulns if {
not any_critical
}
any_critical if {
some vuln in input.vulnerability_report.matches
vuln.vulnerability.severity == "Critical"
vuln.vulnerability.fix.state == "fixed"
}
signed_by_ci if {
input.signature.issuer == "https://token.actions.githubusercontent.com"
startswith(input.signature.subject, "https://github.com/acme/")
}
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| Syft が依存関係を検出できない | パッケージマネージャーまたは形式がサポートされていない | syft のカタログ化ツール一覧を確認します。より詳細な分析には cdxgen を使います。上流にコントリビュートします |
| Cosign の署名が「no identity token」で失敗する | CI に OIDC プロバイダーがない | GitHub Actions で id-token: write 権限が設定されていることを確認します。OIDC プロバイダーの設定を確認します |
| Grype が誤検出を報告する | パッケージのバージョン検出が不正確 | SBOM の正確性を確認します。grype の GitHub に報告します。確認済みの誤検出には無視ルールを追加します |
| SBOM アテステーションが大きすぎる | 依存関係が多い大きなイメージ | SBOM を圧縮します。SPDX のコンパクト形式を使います。レイヤーごとに分割することを検討します |
| アドミッションコントローラーで検証に失敗する | ID または発行者 URL が誤っている | --certificate-identity と --certificate-oidc-issuer の値が正確であることを確認します |
| cdxgen が空の SBOM を生成する | プロジェクトの種類が検出されていない | -t で種類を明示します。マニフェストファイル(package.json など)が存在することを確認します |
ベストプラクティス
- 互換性を最大限に高めるため、CycloneDX と SPDX の両方で SBOM を生成します
- キーレス署名(Sigstore/Fulcio)ですべてのリリースアーティファクトに署名します
- in-toto アテステーションとして SBOM をコンテナイメージに添付します
- CI で SBOM の脆弱性をスキャンし、重大な検出結果があれば処理をブロックします
- 監査とインシデント対応に備え、すべてのリリースの SBOM を保管します
- アドミッションコントローラー(Kyverno、OPA)で署名検証を適用します
- 保管済みの SBOM に対する新たな CVE を継続的に監視します
- リリース時だけでなく、すべてのビルドパイプラインに SBOM 生成を含めます
- SBOM の完全性指標(記録された依存関係の割合)を追跡します
- 誤検出に対応するため、VEX(Vulnerability Exploitability eXchange)プロセスを確立します
関連スキル
- dependency-scanning - ライブラリの脆弱性のトリアージ
- container-scanning - コンテナの CVE スキャン
- policy-as-code - ポリシーの適用
- model-supply-chain-security - ML アーティファクトの信頼性
コメント
Markdown 対応