Runner
CVEScan runners make contact with a remote jobs API endpoint and authenticate themselves with a unique runner-token.
A runner is launched in the foreground with a cvescan start-runner subcommand.
It will initialize a jobs queue, a process pool with a maximum of n_workers and start a supervisor loop. Each worker in the pool will start a worker loop, consume jobs from the queue and report results back to the jobs API.
Jobs are leased to the runner for a given period of time, which might need to be renewed (see lease renewal) during job's runtime. A job with an expired lease will not be able to report results to the jobs API.
Note
A runner can be started through the CVEScan docker image.
Configuration
endpoint and runner-token are configurable respectively from their corresponding CVESCAN_RUNNER_ENDPOINT, CVESCAN_RUNNER_TOKEN and CVESCAN_RUNNER_UPDATE_PERIOD environment variables or from the runner section in CVEScan's configuration file as:
Note
Instead of setting the above environment variables, a runner can also be configured by mounting files containing the expected values in the container and setting CVESCAN_RUNNER_ENDPOINT_FILE, CVESCAN_RUNNER_TOKEN_FILE and CVESCAN_RUNNER_UPDATE_PERIOD_FILE environment variables to their corresponding paths.
Supervisor loop
The supervisor loop is responsible for putting jobs in the queue, renewing leases and enforcing the update period. It will keep running until interrupted by a signal. SIGINT is used for graceful shutdown, while SIGTERM is used for immediate shutdown. It will always start by putting a update job in the queue.
flowchart TD
A[Start]
A --> B[Init jobs queue, leases registry, worker pool]
Z[End]
subgraph Supervisor Loop
B --> C[Put update job in queue, lease in registry]
C --> selector
selector{"Runner interrupted?"}
freeworker{"Idle worker?"}
selector -->|No| freeworker
freeworker -->|Yes| D[Request jobs API]
jobreceived{"Job pending?"}
D --> jobreceived
jobreceived -->|Yes| E[Put job in queue, lease in registry]
leaseextensionrequired{"Any lease require extension?"}
freeworker -->|No| leaseextensionrequired
jobreceived -->|No| leaseextensionrequired
E --> leaseextensionrequired
leaseextensionrequired -->|Yes| F[Extend lease]
updaterequired{"Update period elapsed?"}
leaseextensionrequired -->|No| updaterequired
F --> updaterequired
updaterequired -->|Yes| G[Put update job in queue, lease in registry]
delay["Polling delay"]
updaterequired -->|No| delay
G --> delay
delay --> selector
end
selector -->|Yes| Z
Worker loop
The worker loop is responsible for consuming jobs from the queue, executing them and reporting results to the jobs API. It will keep running until the pool is terminated by the supervisor loop.
flowchart LR
subgraph Worker Loop
WA[Start]
jobinqueue{"Get job from queue?"}
WA --> jobinqueue
jobinqueue -->|No| jobinqueue
jobinqueue -->|Yes| WB[Execute job]
WB --> WC[Report to jobs API]
WC --> WD[Clear job lease from registry]
WD --> jobinqueue
end
Lease renewal & results reporting
A job lease is renewed by the supervisor loop when half of the allocated time has passed. If a job lease expires, the worker executing it will not be able to report results to the jobs API.
When a worker reports results to the jobs API, it will include the job's lease token in the request. Results reporting and lease renewal are subject to a race condition. Therefore each lease is protected by a lock which needs to be acquired for either operations.
Update job
An update job will trigger updates for the specified CVEScan datasources.
Scan job
The scan job will trigger a scan for the job encoded SBOM. By default it scans against the NVD datasource and the OSV connector. The scan job can be configured to specify which datasources are to be used for both detection and consolidation of vulnerabilities. If a linux kernel is present it will perform an advanced scan of the associated vulnerabilities.
flowchart LR
subgraph Worker Loop
SA[Start]
SA --> SB[Scan components against enabled datasources]
SB --> NVD[(NVD datastore)]
SB --> OSV[(OSV connector)]
SB --> SC[Consolidate vulnerabilities]
SC --> NVD
SC --> OSV
SC --> UCT[(UCT repository)]
SC --> EPSS[(EPSS datastore)]
SC --> KEV[(KEV repository)]
islinuxkernel{"Is linux kernel present?"}
SC --> islinuxkernel
islinuxkernel -->|No| SD
islinuxkernel -->|Yes| SE[Linux kernel vulnerabilities filtering]
SE --> LK[(Linux kernel repository)]
SE --> SD
SD[End]
end