247 lines
11 KiB
Markdown
247 lines
11 KiB
Markdown
# Export Center Trivy Adapters
|
|
|
|
The Trivy adapters translate StellaOps normalized advisories into the format consumed by Aqua Security's Trivy scanner. They enable downstream tooling to reuse StellaOps' curated data without bespoke converters, while preserving Aggregation-Only Contract (AOC) boundaries. This guide documents bundle layouts, field mappings, compatibility guarantees, validation workflows, and configuration toggles introduced in Sprint 36 (`EXPORT-SVC-36-001`, `EXPORT-SVC-36-002`).
|
|
|
|
> The current Export Center build is wiring the API and workers. Treat this document as the canonical interface for adapter implementation and update any behavioural changes during task sign-off.
|
|
|
|
## 1. Adapter overview
|
|
|
|
| Variant | Bundle | Default profile | Notes |
|
|
|---------|--------|-----------------|-------|
|
|
| `trivy:db` | `db.bundle` | `trivy:db` | Core vulnerability database compatible with Trivy CLI >= 0.50.0 (schema v2). |
|
|
| `trivy:java-db` | `java-db.bundle` | Optional extension | Java ecosystem supplement (Maven, Gradle). Enabled when `ExportCenter:Profiles:Trivy:EnableJavaDb=true`. |
|
|
|
|
Both variants ship inside the export run under `/export/trivy/`. Each bundle is a gzip-compressed tarball containing:
|
|
|
|
```
|
|
metadata.json
|
|
trivy.db # BoltDB file with vulnerability/provider tables
|
|
packages/*.json # Only when schema requires JSON overlays (language ecosystems)
|
|
```
|
|
|
|
The adapters never mutate input evidence. They only reshape normalized advisories and copy the exact upstream references so consumers can trace provenance.
|
|
|
|
## 2. Bundle layout
|
|
|
|
```
|
|
trivy/
|
|
db.bundle
|
|
+-- metadata.json
|
|
+-- trivy.db
|
|
java-db.bundle # present when Java DB enabled
|
|
+-- metadata.json
|
|
+-- trivy-java.db
|
|
+-- ecosystem/...
|
|
signatures/
|
|
trivy-db.sig
|
|
trivy-java-db.sig
|
|
```
|
|
|
|
`metadata.json` aligns with Trivy's expectations (`schemaVersion`, `buildInfo`, `updatedAt`, etc.). Export Center adds an `stella` block to capture profile id, run id, and policy snapshot hints.
|
|
|
|
Example `metadata.json` (trimmed):
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": 2,
|
|
"buildInfo": {
|
|
"trivyVersion": "0.50.1",
|
|
"vulnerabilityDBVersion": "2025-10-28T00:00:00Z"
|
|
},
|
|
"updatedAt": "2025-10-29T11:42:03Z",
|
|
"stella": {
|
|
"runId": "run-20251029-01",
|
|
"profileId": "prof-trivy-db",
|
|
"tenant": "acme",
|
|
"policySnapshotId": "policy-snap-42",
|
|
"schemaVersion": 2
|
|
}
|
|
}
|
|
```
|
|
|
|
## 3. Field mappings
|
|
|
|
### 3.1 Namespace resolution
|
|
|
|
| Stella field | Trivy field | Notes |
|
|
|--------------|-------------|-------|
|
|
| `advisory.source.vendor` | `namespace` | Canonicalized to lowercase; e.g. `Ubuntu` -> `ubuntu`. |
|
|
| `advisory.source.product` | `distribution` / `ecosystem` | Mapped via allowlist (`Ubuntu 22.04` -> `ubuntu:22.04`). |
|
|
| `package.ecosystem` | `package.ecosystem` | OSS ecosystems (`npm`, `pip`, `nuget`, etc.). |
|
|
| `package.nevra` / `package.evr` | `package.version` (OS) | RPM/DEB version semantics preserved. |
|
|
|
|
If a record lacks a supported namespace, the adapter drops it and logs `adapter.trivy.unsupported_namespace`.
|
|
|
|
### 3.2 Vulnerability metadata
|
|
|
|
| Stella field | Trivy field | Transformation |
|
|
|--------------|-------------|----------------|
|
|
| `advisory.identifiers.cve[]` | `vulnerability.CVEIDs` | Array of strings. |
|
|
| `advisory.identifiers.aliases[]` | `vulnerability.CWEIDs` / `References` | CVE -> `CVEIDs`, others appended to `References`. |
|
|
| `advisory.summary` | `vulnerability.Title` | Stripped to 256 chars; rest moved to `Description`. |
|
|
| `advisory.description` | `vulnerability.Description` | Markdown allowed, normalized to LF line endings. |
|
|
| `advisory.severity.normalized` | `vulnerability.Severity` | Uses table below. |
|
|
| `advisory.cvss[]` | `vulnerability.CVSS` | Stored as `{"vector": "...", "score": 7.8, "source": "NVD"}`. |
|
|
| `advisory.published` | `vulnerability.PublishedDate` | ISO 8601 UTC. |
|
|
| `advisory.modified` | `vulnerability.LastModifiedDate` | ISO 8601 UTC. |
|
|
| `advisory.vendorStatement` | `vulnerability.VendorSeverity` / `VendorVectors` | Preserved in vendor block. |
|
|
|
|
Severity mapping:
|
|
|
|
| Stella severity | Trivy severity |
|
|
|-----------------|----------------|
|
|
| `critical` | `CRITICAL` |
|
|
| `high` | `HIGH` |
|
|
| `medium` | `MEDIUM` |
|
|
| `low` | `LOW` |
|
|
| `none` / `info` | `UNKNOWN` |
|
|
|
|
### 3.3 Affected packages
|
|
|
|
| Stella field | Trivy field | Notes |
|
|
|--------------|-------------|-------|
|
|
| `package.name` | `package.name` | For OS distros uses source package when available. |
|
|
| `package.purl` | `package.PURL` | Copied verbatim. |
|
|
| `affects.vulnerableRange` | `package.vulnerableVersionRange` | SemVer or distro version range. |
|
|
| `remediations.fixedVersion` | `package.fixedVersion` | Latest known fix. |
|
|
| `remediations.urls[]` | `package.links` | Array; duplicates removed. |
|
|
| `states.cpes[]` | `package.cpes` | For CPE-backed advisories. |
|
|
|
|
The adapter deduplicates entries by `(namespace, package.name, vulnerableRange)` to avoid duplicate records when multiple upstream segments agree.
|
|
|
|
Example mapping (Ubuntu advisory):
|
|
|
|
```jsonc
|
|
// Stella normalized input
|
|
{
|
|
"source": {"vendor": "Ubuntu", "product": "22.04"},
|
|
"identifiers": {"cve": ["CVE-2024-12345"]},
|
|
"severity": {"normalized": "high"},
|
|
"affects": [{
|
|
"package": {"name": "openssl", "ecosystem": "ubuntu", "nevra": "1.1.1f-1ubuntu2.12"},
|
|
"vulnerableRange": "< 1.1.1f-1ubuntu2.13",
|
|
"remediations": [{"fixedVersion": "1.1.1f-1ubuntu2.13"}]
|
|
}]
|
|
}
|
|
|
|
// Trivy vulnerability entry
|
|
{
|
|
"namespace": "ubuntu",
|
|
"package": {
|
|
"name": "openssl",
|
|
"version": "< 1.1.1f-1ubuntu2.13",
|
|
"fixedVersion": "1.1.1f-1ubuntu2.13"
|
|
},
|
|
"vulnerability": {
|
|
"ID": "CVE-2024-12345",
|
|
"Severity": "HIGH"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.4 Java DB specifics
|
|
|
|
The Java supplement only includes ecosystems `maven`, `gradle`, `sbt`. Additional fields:
|
|
|
|
| Stella field | Trivy Java field | Notes |
|
|
|--------------|------------------|-------|
|
|
| `package.group` | `GroupID` | Derived from Maven coordinates. |
|
|
| `package.artifact` | `ArtifactID` | Derived from Maven coordinates. |
|
|
| `package.version` | `Version` | Compared with semver-lite rules. |
|
|
| `affects.symbolicRanges[]` | `VulnerableVersions` | Strings like `[1.0.0,1.2.3)`. |
|
|
|
|
## 4. Compatibility matrix
|
|
|
|
| Trivy version | Schema version | Supported by adapter | Notes |
|
|
|---------------|----------------|----------------------|-------|
|
|
| 0.46.x | 2 | Yes | Baseline compatibility target. |
|
|
| 0.50.x | 2 | Yes | Default validation target in CI. |
|
|
| 0.51.x+ | 3 | Pending | Adapter throws `ERR_EXPORT_UNSUPPORTED_SCHEMA` until implemented. |
|
|
|
|
Schema mismatches emit `adapter.trivy.unsupported_schema_version` and abort the run. Operators can pin the schema via `ExportCenter:Adapters:Trivy:SchemaVersion`.
|
|
|
|
## 5. Validation workflow
|
|
|
|
1. **Unit tests** (`StellaOps.ExportCenter.Tests`):
|
|
- Mapping tests for OS and ecosystem packages.
|
|
- Severity conversion and range handling property tests.
|
|
2. **Integration tests** (`EXPORT-SVC-36-001`):
|
|
- Generate bundle from fixture dataset.
|
|
- Run `trivy module db import <bundle>` (Trivy CLI) to ensure the bundle is accepted.
|
|
- For Java DB, run `trivy java-repo --db <bundle>` against sample repository.
|
|
3. **CI smoke (`DEVOPS-EXPORT-36-001`)**:
|
|
- Validate metadata fields using `jq`.
|
|
- Ensure signatures verify with `cosign`.
|
|
- Check runtime by invoking `trivy fs --cache-dir <temp> --skip-update --custom-db <bundle> fixtures/image`.
|
|
|
|
Failures set the run status to `failed` with `errorCode="adapter-trivy"` so Console/CLI expose the reason.
|
|
|
|
## 6. Configuration knobs
|
|
|
|
```yaml
|
|
ExportCenter:
|
|
Adapters:
|
|
Trivy:
|
|
SchemaVersion: 2 # enforce schema version
|
|
IncludeJavaDb: true # enable java-db.bundle
|
|
AllowEmpty: false # fail when no records match
|
|
MaxCvssVectorsPerEntry: 5 # truncate to avoid oversized payloads
|
|
Distribution:
|
|
Oras:
|
|
TrivyRepository: "registry.example.com/stella/trivy-db"
|
|
PublishDelta: false
|
|
Download:
|
|
FilenameFormat: "trivy-db-{runId}.tar.gz"
|
|
IncludeMetadata: true
|
|
```
|
|
|
|
- `AllowEmpty=false` converts empty datasets into `ERR_EXPORT_EMPTY`.
|
|
- `MaxCvssVectorsPerEntry` prevents extremely large multi-vector advisories from bloating the DB.
|
|
- `PublishDelta` works in tandem with the planner's delta logic; when true, only changed blobs are pushed.
|
|
- `FilenameFormat` lets operators align downloads with existing mirror tooling.
|
|
- `IncludeMetadata` toggles whether `metadata.json` is stored alongside the bundle in the staging directory for quick inspection.
|
|
|
|
## 7. Distribution guidelines
|
|
|
|
- **Download profile**: `db.bundle` placed under `/export/trivy/` and signed. Recommended filename `trivy-db-<runId>.tar.gz`.
|
|
- **OCI push**: ORAS artifact with annotations:
|
|
- `org.opencontainers.artifact.description=StellaOps Trivy DB`
|
|
- `io.stella.export.profile=trivy:db`
|
|
- `io.stella.export.run=<runId>`
|
|
- `io.stella.export.schemaVersion=2`
|
|
- **Offline Kit**: When `offlineBundle.includeTrivyDb=true`, the exporter copies the latest full bundle plus the last `N` deltas (configurable) with manifests for quick import.
|
|
|
|
Consumers should always verify signatures using `trivy-db.sig` / `trivy-java-db.sig` before trusting the bundle.
|
|
|
|
Example verification flow:
|
|
|
|
```bash
|
|
cosign verify-blob \
|
|
--key tenants/acme/export-center.pub \
|
|
--signature signatures/trivy-db.sig \
|
|
trivy/db.bundle
|
|
|
|
trivy module db import trivy/db.bundle --cache-dir /tmp/trivy-cache
|
|
```
|
|
|
|
## 8. Troubleshooting
|
|
|
|
| Symptom | Likely cause | Remedy |
|
|
|---------|--------------|--------|
|
|
| `ERR_EXPORT_UNSUPPORTED_SCHEMA` | Trivy CLI updated schema version. | Bump `SchemaVersion`, extend mapping tables, regenerate fixtures. |
|
|
| `adapter.trivy.unsupported_namespace` | Advisory namespace not in allowlist. | Extend namespace mapping or exclude in selector. |
|
|
| `trivy import` fails with "invalid bolt page" | Corrupted bundle or truncated upload. | Re-run export; verify storage backend and signatures. |
|
|
| Missing Java advisories | `IncludeJavaDb=false` or no Java data in Findings Ledger. | Enable flag and confirm upstream connectors populate Java ecosystems. |
|
|
| Severity downgraded to UNKNOWN | Source severity missing or unrecognized. | Ensure upstream connectors populate severity or supply CVSS scores. |
|
|
| `ERR_EXPORT_EMPTY` returned unexpectedly | Selectors yielded zero records while `AllowEmpty=false`. | Review selectors; set `AllowEmpty=true` if empty exports are acceptable. |
|
|
|
|
## 9. References
|
|
|
|
- [Export Center API reference](api.md)
|
|
- [Export Center CLI Guide](cli.md)
|
|
- [Export Center Architecture](architecture.md)
|
|
- [Export Center Overview](overview.md)
|
|
- [Aqua Security Trivy documentation](https://aquasecurity.github.io/trivy/dev/database/structure/) *(external reference for schema expectations)*
|
|
|
|
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
|