Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions docs/json-schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,166 @@ Enum values:
- `type`: `BUG | VULNERABILITY | CODE_SMELL`
- `status`: `OPEN | CONFIRMED | REOPENED | RESOLVED | CLOSED`

## `krci sca list`

```json
{
"schemaVersion": "1",
"data": {
"items": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "payments-api",
"version": "main",
"classifier": "APPLICATION",
"active": true,
"isLatest": true,
"lastBomImport": 1713456000000,
"lastBomImportFormat": "CycloneDX 1.4",
"riskScore": 12.5,
"metrics": {
"critical": 1,
"high": 3,
"medium": 8,
"low": 2,
"unassigned": 0,
"vulnerabilities": 14
}
}
],
"totalCount": 42
}
}
```

`lastBomImport` is a Unix milliseconds timestamp. `metrics` is optional — the upstream
payload omits it for projects that have never had a BOM uploaded; downstream consumers
should guard on `.data.items[].metrics != null` before indexing counts.

## `krci sca get <codebase>`

Two variants: `status: "OK"` when the codebase has a Dep-Track project; `status: "NONE"`
when the Portal's lookup returned no project for the resolved `(name, branch)` pair.

```json
{
"schemaVersion": "1",
"data": {
"status": "OK",
"project": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "payments-api",
"version": "main",
"classifier": "APPLICATION",
"active": true,
"isLatest": true,
"lastBomImport": 1713456000000,
"lastBomImportFormat": "CycloneDX 1.4",
"lastVulnerabilityAnalysis": 1713459600000,
"riskScore": 12.5
},
"metrics": {
"critical": 1,
"high": 3,
"medium": 8,
"low": 2,
"unassigned": 0,
"vulnerabilities": 14,
"components": 120,
"vulnerableComponents": 12
}
}
}
```

```json
{ "schemaVersion": "1", "data": { "status": "NONE" } }
```

When `status` is `"NONE"` the `project` and `metrics` fields are absent. CLI exit is `0`
in both cases.

## `krci sca components <codebase>`

```json
{
"schemaVersion": "1",
"data": {
"status": "OK",
"items": [
{
"uuid": "5c0e...",
"name": "log4j-core",
"version": "2.11.2",
"latestVersion": "2.24.0",
"outdated": true,
"group": "org.apache.logging.log4j",
"license": "Apache-2.0",
"isInternal": false,
"riskScore": 9.8,
"metrics": {
"critical": 1,
"high": 0,
"medium": 0,
"low": 0,
"unassigned": 0,
"vulnerabilities": 1
}
}
],
"totalCount": 120
}
}
```

`status` is `"OK"` for a bound codebase and `"NONE"` for an unbound one (with
`items: [], totalCount: 0`). `outdated` is a server-side flag from Dep-Track —
no client-side semver comparison is performed. When `--severity=<min>` is passed,
the CLI additionally filters client-side to rows whose metrics contain at least
one finding of severity `>= min` (inclusive).

## `krci sca findings <codebase>`

```json
{
"schemaVersion": "1",
"data": {
"status": "OK",
"items": [
{
"component": {
"uuid": "c1",
"name": "log4j-core",
"version": "2.11.2"
},
"vulnerability": {
"vulnId": "CVE-2021-44228",
"source": "NVD",
"severity": "CRITICAL",
"cvssV3BaseScore": 10.0
},
"analysis": { "state": "NOT_SET", "isSuppressed": false },
"attribution": {
"analyzerIdentity": "OSSINDEX_ANALYZER",
"attributedOn": 1713456000000
}
}
],
"truncated": false
}
}
```

Results are sorted by `vulnerability.severity` descending (CRITICAL first), then
`component.name` ascending, then `vulnerability.vulnId` ascending. Default
excludes suppressed findings; `--include-suppressed` opts in.

The Portal caps the response at 1000 rows per request. When the upstream returned
more, the CLI sets `truncated=true` and prints a footer hint in table output;
scripts should branch on `.data.truncated` rather than counting rows.

Severity enum: `CRITICAL | HIGH | MEDIUM | LOW | INFO | UNASSIGNED`.

## Error envelope

```json
Expand Down
195 changes: 195 additions & 0 deletions docs/sca.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# `krci sca` — Software Composition Analysis from the terminal

Inspect the Dependency-Track (DT) state surfaced by the KubeRocketCI Portal —
projects, dependencies, and vulnerability findings — without leaving the
terminal. The CLI reuses the Dep-Track binding already configured on the
Portal (`DEPENDENCY_TRACK_URL` / `DEPENDENCY_TRACK_API_KEY`), so no extra
credentials are required.

## Subcommands

| Command | Purpose |
|----------------------------------|---------------------------------------------------------------------------|
| `sca list` | List SCA projects known to Dependency-Track |
| `sca get <codebase>` | Project overview: risk score, severity counts, last BOM import |
| `sca components <codebase>` | Dependencies with outdated / direct / severity filters |
| `sca findings <codebase>` | Flat vulnerability listing (CVE-level) with severity filter + truncation |

All commands accept `-o, --output` with `table` (default) or `json`.

### Codebase + branch addressing

Every per-codebase verb takes a positional `<codebase>` and an optional
`--branch`. When `--branch` is omitted, the Portal reads
`Codebase.spec.defaultBranch` from Kubernetes and uses that value as the
Dep-Track project "version". You can also supply an explicit branch name or
release tag.

### Severity filter (inclusive)

`--severity` accepts case-insensitive values `critical | high | medium | low | info`.
The filter is **inclusive**: `--severity=high` returns rows at HIGH or above;
`--severity=medium` returns CRITICAL + HIGH + MEDIUM. `INFO` implicitly
includes `UNASSIGNED`.

## `sca list`

```bash
krci sca list
```

```
NAME VERSION CLASSIFIER ACTIVE LAST_BOM RISK VULNS (C/H/M/L)
payments-api main APPLICATION yes 2h ago 12.5 1/3/8/2
loyalty-api develop APPLICATION yes 6h ago 0.0 0/0/0/0

2 projects, page 1 of 1 (page-size 25)
```

Flags: `--search`, `--page`, `--page-size` (max 500), `--include-inactive`,
`--include-children`. Defaults exclude inactive projects and child versions
to match the Portal UI.

Pick dirty projects from a script:

```bash
krci sca list -o json | jq -r '.data.items[] | select(.metrics.critical>0) | .name'
```

## `sca get`

```bash
krci sca get payments-api
```

```
payments-api @ main

Codebase payments-api
Branch main
Classifier APPLICATION
Active yes
Is latest yes
Risk score 12.5
Last BOM 2026-04-18 09:12 UTC (CycloneDX 1.4), 2h ago
Last vuln scan 1h ago

Vulnerabilities:
Critical 1
High 3
Medium 8
Low 2
Info/Unassigned 0
Total 14

Components:
Total 120
Vulnerable 12
```

Target an explicit branch or pull a single metric:

```bash
krci sca get payments-api --branch=release/1.0
krci sca get payments-api -o json | jq -r '.data.project.riskScore'
```

When the codebase has no Dep-Track binding:

```bash
$ krci sca get infra-gitops
status: NONE — no SCA scanner bound for infra-gitops @ main
```

`status=NONE` always exits `0` — scripting consumers can branch on
`.data.status`.

## `sca components`

```bash
krci sca components payments-api --only-outdated
```

```
COMPONENT CURRENT LATEST OUTDATED LICENSE RISK VULNS (C/H/M/L)
log4j-core 2.11.2 2.24.0 yes Apache-2.0 9.8 1/0/0/0
commons-text 1.9 1.13.1 yes Apache-2.0 5.5 0/1/0/0

2 components, page 1 of 1 (page-size 50)
```

Combined filters are **AND** — server-side `--only-outdated` / `--only-direct`
are forwarded to Dep-Track, and `--severity` narrows client-side afterwards:

```bash
# Outdated direct dependencies with at least one HIGH or CRITICAL finding
krci sca components payments-api --only-direct --only-outdated --severity=high

# Explicit branch
krci sca components payments-api --branch=release/1.0
```

## `sca findings`

```bash
krci sca findings payments-api --severity=high
```

```
COMPONENT VERSION VULN_ID SRC SEVERITY CVSS ANALYSIS SUPPRESSED
log4j-core 2.11.2 CVE-2021-44228 NVD CRITICAL 10.0 (v3) NOT_SET no
commons-text 1.9 CVE-2022-42889 NVD CRITICAL 9.8 (v3) NOT_SET no
```

Sort: severity desc → component.name asc → vulnerability.vulnId asc.
Default excludes suppressed findings (`--include-suppressed` to opt in).

Filter by upstream vulnerability source (e.g. `NVD`, `GITHUB`, `OSV`):

```bash
krci sca findings payments-api --source=NVD
```

Very large projects are capped server-side at 1000 rows with a footer hint:

```
(findings truncated to 1000 rows — narrow the query via --severity or --source)
```

Script-friendly CVE extraction:

```bash
krci sca findings payments-api -o json | jq -r '.data.items[].vulnerability.vulnId'
```

## Exit codes

| Exit | Meaning |
|------|---------------------------------------------------------------------------|
| `0` | Command succeeded (including `status=NONE` payloads) |
| `1` | Any failure — validation, auth, not-found, upstream unavailable, bad flag |

## JSON output

Every command emits a stable `{ "schemaVersion": "1", "data": { … } }`
envelope under `-o json`. See `docs/json-schemas.md` for the exact payload
for each verb.

## Typical workflows

```bash
# Find the dirtiest projects
krci sca list -o json \
| jq -r '.data.items | sort_by(-(.riskScore // 0)) | .[0:5][] | "\(.name)@\(.version) risk=\(.riskScore // 0)"'

# Zoom into one
krci sca get payments-api
krci sca components payments-api --only-outdated
krci sca findings payments-api --severity=high

# CI gate — fail when CRITICALs exist on main
if [ "$(krci sca findings payments-api --severity=critical -o json \
| jq '.data.items | length')" -gt 0 ]; then
echo "new criticals"; exit 1
fi
```
Loading
Loading