mirror of
https://github.com/anchore/syft.git
synced 2026-10-15 07:37:20 +02:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f57d22f63 | ||
|
|
351c683cb4 | ||
|
|
534a5f54b0 | ||
|
|
8a414b5366 | ||
|
|
e34adea749 | ||
|
|
8314c0d2cb | ||
|
|
b7fa75d7f8 | ||
|
|
7d0d3e1977 | ||
|
|
58f8c852df | ||
|
|
b8f52d570e | ||
|
|
ba00f3328d | ||
|
|
962ff1ec49 | ||
|
|
40899adb87 | ||
|
|
650f71cbe0 | ||
|
|
30885ed92e | ||
|
|
51243aa65f | ||
|
|
23e3de75e3 | ||
|
|
594ba5f295 | ||
|
|
5d48882a78 | ||
|
|
ec4d595920 | ||
|
|
094b41b301 | ||
|
|
2eb2d55551 | ||
|
|
a46d12270f | ||
|
|
3e16c6813f | ||
|
|
5035d9ca1a | ||
|
|
c21b16d924 | ||
|
|
4a2fc226dd | ||
|
|
7de5643227 | ||
|
|
9de4129638 | ||
|
|
3a45653cfa | ||
|
|
b82c0ffc34 | ||
|
|
b2be411f77 | ||
|
|
ec22f4b773 | ||
|
|
e3c525b4b8 |
@@ -1 +1,2 @@
|
||||
enforce-v0: true # don't make breaking-change label bump major version before 1.0.
|
||||
title: ""
|
||||
@@ -1,14 +1,11 @@
|
||||
name: "Bootstrap"
|
||||
|
||||
description: "Bootstrap all tools and dependencies"
|
||||
inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
required: true
|
||||
default: "1.21.x"
|
||||
use-go-cache:
|
||||
description: "Restore go cache"
|
||||
required: true
|
||||
default: "true"
|
||||
cache-key-prefix:
|
||||
description: "Prefix all cache keys with this value"
|
||||
required: true
|
||||
@@ -24,49 +21,25 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
# note: go mod and build is automatically cached on default with v4+
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
- name: Restore tool cache
|
||||
id: tool-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tmp
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
|
||||
|
||||
# note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
|
||||
# some installations of project tools.
|
||||
- name: Restore go module cache
|
||||
id: go-mod-cache
|
||||
if: inputs.use-go-cache == 'true'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
|
||||
|
||||
- name: (cache-miss) Bootstrap project tools
|
||||
shell: bash
|
||||
if: steps.tool-cache.outputs.cache-hit != 'true'
|
||||
run: make bootstrap-tools
|
||||
|
||||
- name: Restore go build cache
|
||||
id: go-cache
|
||||
if: inputs.use-go-cache == 'true'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
|
||||
|
||||
- name: (cache-miss) Bootstrap go dependencies
|
||||
- name: Bootstrap go dependencies
|
||||
shell: bash
|
||||
if: steps.go-mod-cache.outputs.cache-hit != 'true' && inputs.use-go-cache == 'true'
|
||||
run: make bootstrap-go
|
||||
|
||||
- name: Install apt packages
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
@@ -4,6 +4,9 @@ on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
Benchmark-Test:
|
||||
@@ -13,13 +16,14 @@ jobs:
|
||||
# we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
|
||||
# the job by event.
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore base benchmark result
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: test/results/benchmark-main.txt
|
||||
# use base sha for PR or new commit hash for main push in benchmark result key
|
||||
@@ -35,13 +39,13 @@ jobs:
|
||||
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
|
||||
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: benchmark-test-results
|
||||
path: test/results/**/*
|
||||
|
||||
- name: Update PR benchmark results comment
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
header: benchmark
|
||||
|
||||
@@ -14,11 +14,17 @@ on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 3'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -30,16 +36,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 #v2.21.8
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -50,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 #v2.21.8
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -64,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 #v2.21.8
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
name: Add to OSS board
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
@@ -9,7 +12,6 @@ on:
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
|
||||
run:
|
||||
uses: "anchore/workflows/.github/workflows/oss-project-board-add.yaml@main"
|
||||
secrets:
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
name: "Release"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -6,15 +10,12 @@ on:
|
||||
description: tag the latest commit on main with the given version (prefixed with v)
|
||||
required: true
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.x"
|
||||
|
||||
jobs:
|
||||
quality-gate:
|
||||
environment: release
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Check if tag already exists
|
||||
# note: this will fail if the tag already exists
|
||||
@@ -23,7 +24,7 @@ jobs:
|
||||
git tag ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Check static analysis results
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: static-analysis
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check unit test results
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: unit
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -41,7 +42,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check integration test results
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: integration
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -50,7 +51,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check acceptance test results (linux)
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: acceptance-linux
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -59,7 +60,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check acceptance test results (mac)
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: acceptance-mac
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -68,7 +69,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check cli test results (linux)
|
||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
||||
uses: fountainhead/action-wait-for-check@297be350cf8393728ea4d4b39435c7d7ae167c93 # v1.1.0
|
||||
id: cli-linux
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -94,7 +95,7 @@ jobs:
|
||||
contents: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -105,13 +106,13 @@ jobs:
|
||||
build-cache-key-prefix: "snapshot"
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d #v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.TOOLBOX_DOCKER_USER }}
|
||||
password: ${{ secrets.TOOLBOX_DOCKER_PASS }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d #v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -119,7 +120,9 @@ jobs:
|
||||
|
||||
- name: Tag release
|
||||
run: |
|
||||
git tag ${{ github.event.inputs.version }}
|
||||
git config --global user.name "anchoreci"
|
||||
git config --global user.email "anchoreci@users.noreply.github.com"
|
||||
git tag -a ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }}"
|
||||
git push origin --tags
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -141,12 +144,12 @@ jobs:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- uses: anchore/sbom-action@v0
|
||||
- uses: anchore/sbom-action@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 #v0.14.3
|
||||
continue-on-error: true
|
||||
with:
|
||||
artifact-name: sbom.spdx.json
|
||||
|
||||
- uses: 8398a7/action-slack@v3
|
||||
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
|
||||
continue-on-error: true
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
@@ -155,9 +158,3 @@ jobs:
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
if: ${{ success() }}
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifacts
|
||||
path: dist/**/*
|
||||
|
||||
|
||||
@@ -9,14 +9,17 @@ env:
|
||||
GO_VERSION: "1.21.x"
|
||||
GO_STABLE_VERSION: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
update-bootstrap-tools:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
stable: ${{ env.GO_STABLE_VERSION }}
|
||||
@@ -55,13 +58,13 @@ jobs:
|
||||
echo "GLOW=GLOW_LATEST_VERSION" >> $GITHUB_OUTPUT
|
||||
id: latest-versions
|
||||
|
||||
- uses: tibdex/github-app-token@v1
|
||||
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@v5
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -5,6 +5,9 @@ on:
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.x"
|
||||
GO_STABLE_VERSION: true
|
||||
@@ -14,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@3df4ab11eba7bda6032a0b82a6bb43b11571feac #v4.0.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
stable: ${{ env.GO_STABLE_VERSION }}
|
||||
@@ -24,13 +27,13 @@ jobs:
|
||||
- run: |
|
||||
make generate-cpe-dictionary-index
|
||||
|
||||
- uses: tibdex/github-app-token@v1
|
||||
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@v5
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -9,14 +9,17 @@ env:
|
||||
GO_VERSION: "1.21.x"
|
||||
GO_STABLE_VERSION: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
upgrade-stereoscope:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
stable: ${{ env.GO_STABLE_VERSION }}
|
||||
@@ -32,13 +35,13 @@ jobs:
|
||||
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_OUTPUT
|
||||
id: latest-version
|
||||
|
||||
- uses: tibdex/github-app-token@v1
|
||||
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@v5
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -7,14 +7,16 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
Static-Analysis:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -28,37 +30,37 @@ jobs:
|
||||
name: "Unit tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore Java test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore RPM test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/rpm/test-fixtures/rpms
|
||||
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/rpm/test-fixtures/rpms.fingerprint' ) }}
|
||||
|
||||
- name: Restore go binary test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
|
||||
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
|
||||
|
||||
- name: Restore binary cataloger test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic
|
||||
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore Kernel test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/kernel/test-fixtures/cache
|
||||
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
|
||||
@@ -72,7 +74,7 @@ jobs:
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -81,7 +83,7 @@ jobs:
|
||||
run: make validate-cyclonedx-schema
|
||||
|
||||
- name: Restore integration test cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/integration/test-fixtures/cache
|
||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('test/integration/test-fixtures/cache.fingerprint') }}
|
||||
@@ -94,7 +96,7 @@ jobs:
|
||||
name: "Build snapshot artifacts"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -113,7 +115,7 @@ jobs:
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@v3
|
||||
uses: actions/cache/save@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
@@ -125,10 +127,10 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
@@ -138,7 +140,7 @@ jobs:
|
||||
|
||||
- name: Restore install.sh test image cache
|
||||
id: install-test-image-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/install/cache
|
||||
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
|
||||
@@ -161,17 +163,17 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
- name: Restore docker image cache for compare testing
|
||||
id: mac-compare-testing-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: image.tar
|
||||
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
|
||||
@@ -189,19 +191,19 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 #v4.1.0
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore CLI test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
|
||||
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
@@ -30,6 +30,7 @@ VERSION
|
||||
/test/results
|
||||
coverage.txt
|
||||
*.log
|
||||
test/integration/test-fixtures/**/go.sum
|
||||
|
||||
# probable archives
|
||||
.images
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM gcr.io/distroless/static-debian11:debug AS build
|
||||
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951 AS build
|
||||
|
||||
FROM scratch
|
||||
# needed for version check HTTPS request
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM gcr.io/distroless/static-debian11:debug
|
||||
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951
|
||||
|
||||
# create the /tmp dir, which is needed for image content cache
|
||||
WORKDIR /tmp
|
||||
|
||||
@@ -13,8 +13,8 @@ GLOW_CMD = $(TEMP_DIR)/glow
|
||||
GOLANGCILINT_VERSION := v1.54.2
|
||||
GOSIMPORTS_VERSION := v0.3.8
|
||||
BOUNCER_VERSION := v0.4.0
|
||||
CHRONICLE_VERSION := v0.7.0
|
||||
GORELEASER_VERSION := v1.20.0
|
||||
CHRONICLE_VERSION := v0.8.0
|
||||
GORELEASER_VERSION := v1.21.1
|
||||
YAJSV_VERSION := v1.4.1
|
||||
COSIGN_VERSION := v2.2.0
|
||||
QUILL_VERSION := v0.4.1
|
||||
@@ -147,13 +147,14 @@ check-json-schema-drift:
|
||||
.PHONY: unit
|
||||
unit: $(TEMP_DIR) fixtures ## Run unit tests (with coverage)
|
||||
$(call title,Running unit tests)
|
||||
go test -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/syft/test)
|
||||
go test -race -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/syft/test)
|
||||
@.github/scripts/coverage.py $(COVERAGE_THRESHOLD) $(TEMP_DIR)/unit-coverage-details.txt
|
||||
|
||||
.PHONY: integration
|
||||
integration: ## Run integration tests
|
||||
$(call title,Running integration tests)
|
||||
go test -v ./test/integration
|
||||
go run -race cmd/syft/main.go alpine:latest
|
||||
|
||||
.PHONY: validate-cyclonedx-schema
|
||||
validate-cyclonedx-schema:
|
||||
|
||||
@@ -139,6 +139,7 @@ Sources can be explicitly provided with a scheme:
|
||||
```
|
||||
docker:yourrepo/yourimage:tag use images from the Docker daemon
|
||||
podman:yourrepo/yourimage:tag use images from the Podman daemon
|
||||
containerd:yourrepo/yourimage:tag use images from the Containerd daemon
|
||||
docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save"
|
||||
oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Skopeo or otherwise)
|
||||
oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
|
||||
@@ -671,7 +672,7 @@ source:
|
||||
# the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
|
||||
digests: ["sha256"]
|
||||
|
||||
# options when pulling directly from a registry via the "registry:" scheme
|
||||
# options when pulling directly from a registry via the "registry:" or "containerd:" scheme
|
||||
registry:
|
||||
# skip TLS verification when communicating with the registry
|
||||
# SYFT_REGISTRY_INSECURE_SKIP_TLS_VERIFY env var
|
||||
|
||||
+5
-3
@@ -46,10 +46,10 @@ func create(id clio.Identification) (clio.Application, *cobra.Command) {
|
||||
return []clio.UI{noUI}, nil
|
||||
}
|
||||
|
||||
h := handler.New(handler.DefaultHandlerConfig())
|
||||
|
||||
return []clio.UI{
|
||||
ui.New(h, false, cfg.Log.Quiet),
|
||||
ui.New(cfg.Log.Quiet,
|
||||
handler.New(handler.DefaultHandlerConfig()),
|
||||
),
|
||||
noUI,
|
||||
}, nil
|
||||
},
|
||||
@@ -60,7 +60,9 @@ func create(id clio.Identification) (clio.Application, *cobra.Command) {
|
||||
// we can hoist them into the internal packages for global use.
|
||||
stereoscope.SetBus(state.Bus)
|
||||
bus.Set(state.Bus)
|
||||
|
||||
redact.Set(state.RedactStore)
|
||||
|
||||
log.Set(state.Logger)
|
||||
stereoscope.SetLogger(state.Logger)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
const powerUserExample = ` {{.appName}} {{.command}} <image>
|
||||
DEPRECATED - THIS COMMAND WILL BE REMOVED in v1.0.0
|
||||
Only image sources are supported (e.g. docker: , podman: , docker-archive: , oci: , etc.), the directory source (dir:) is not supported, template outputs are not supported.
|
||||
Template outputs are not supported.
|
||||
All behavior is controlled via application configuration and environment variables (see https://github.com/anchore/syft#configuration)
|
||||
`
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
"set the name of the target being analyzed")
|
||||
|
||||
flags.StringVarP(&cfg.Source.Version, "source-version", "",
|
||||
"set the name of the target being analyzed")
|
||||
"set the version of the target being analyzed")
|
||||
|
||||
flags.StringVarP(&cfg.BasePath, "base-path", "",
|
||||
"base directory for scanning, no links will be followed above this directory, and all paths will be reported relative to this directory")
|
||||
|
||||
@@ -2,8 +2,7 @@ package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"slices"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/formats"
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/wagoodman/go-partybus"
|
||||
"github.com/wagoodman/go-progress"
|
||||
|
||||
"github.com/anchore/bubbly/bubbles/taskprogress"
|
||||
stereoscopeParsers "github.com/anchore/stereoscope/pkg/event/parsers"
|
||||
"github.com/anchore/stereoscope/pkg/image/containerd"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
)
|
||||
|
||||
var _ interface {
|
||||
progress.Stager
|
||||
progress.Progressable
|
||||
} = (*containerdPullProgressAdapter)(nil)
|
||||
|
||||
type containerdPullStatus interface {
|
||||
Complete() bool
|
||||
Layers() []containerd.LayerID
|
||||
Current(containerd.LayerID) progress.Progressable
|
||||
}
|
||||
|
||||
type containerdPullProgressAdapter struct {
|
||||
status containerdPullStatus
|
||||
formatter containerdPullStatusFormatter
|
||||
}
|
||||
|
||||
type containerdPullStatusFormatter struct {
|
||||
auxInfoStyle lipgloss.Style
|
||||
pullCompletedStyle lipgloss.Style
|
||||
pullDownloadStyle lipgloss.Style
|
||||
pullStageChars []string
|
||||
layerCaps []string
|
||||
}
|
||||
|
||||
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
|
||||
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
if pullStatus == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tsk := m.newTaskProgress(
|
||||
taskprogress.Title{
|
||||
Default: "Pull image",
|
||||
Running: "Pulling image",
|
||||
Success: "Pulled image",
|
||||
},
|
||||
taskprogress.WithStagedProgressable(
|
||||
newContainerdPullProgressAdapter(pullStatus),
|
||||
),
|
||||
)
|
||||
|
||||
tsk.HintStyle = lipgloss.NewStyle()
|
||||
tsk.HintEndCaps = nil
|
||||
|
||||
return []tea.Model{tsk}
|
||||
}
|
||||
|
||||
func newContainerdPullProgressAdapter(status *containerd.PullStatus) *containerdPullProgressAdapter {
|
||||
return &containerdPullProgressAdapter{
|
||||
status: status,
|
||||
formatter: newContainerdPullStatusFormatter(),
|
||||
}
|
||||
}
|
||||
|
||||
func newContainerdPullStatusFormatter() containerdPullStatusFormatter {
|
||||
return containerdPullStatusFormatter{
|
||||
auxInfoStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#777777")),
|
||||
pullCompletedStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#fcba03")),
|
||||
pullDownloadStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#777777")),
|
||||
pullStageChars: strings.Split("▁▃▄▅▆▇█", ""),
|
||||
layerCaps: strings.Split("▕▏", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func (d containerdPullProgressAdapter) Size() int64 {
|
||||
return -1
|
||||
}
|
||||
|
||||
func (d containerdPullProgressAdapter) Current() int64 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (d containerdPullProgressAdapter) Error() error {
|
||||
if d.status.Complete() {
|
||||
return progress.ErrCompleted
|
||||
}
|
||||
// TODO: return intermediate error indications
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d containerdPullProgressAdapter) Stage() string {
|
||||
return d.formatter.Render(d.status)
|
||||
}
|
||||
|
||||
// Render crafts the given docker image pull status summarized into a single line.
|
||||
func (f containerdPullStatusFormatter) Render(pullStatus containerdPullStatus) string {
|
||||
var size, current uint64
|
||||
|
||||
layers := pullStatus.Layers()
|
||||
status := make(map[containerd.LayerID]progress.Progressable)
|
||||
completed := make([]string, len(layers))
|
||||
|
||||
// fetch the current state
|
||||
for idx, layer := range layers {
|
||||
completed[idx] = " "
|
||||
status[layer] = pullStatus.Current(layer)
|
||||
}
|
||||
|
||||
numCompleted := 0
|
||||
for idx, layer := range layers {
|
||||
prog := status[layer]
|
||||
curN := prog.Current()
|
||||
curSize := prog.Size()
|
||||
|
||||
if progress.IsCompleted(prog) {
|
||||
input := f.pullStageChars[len(f.pullStageChars)-1]
|
||||
completed[idx] = f.formatPullPhase(prog.Error() != nil, input)
|
||||
} else if curN != 0 {
|
||||
var ratio float64
|
||||
switch {
|
||||
case curN == 0 || curSize < 0:
|
||||
ratio = 0
|
||||
case curN >= curSize:
|
||||
ratio = 1
|
||||
default:
|
||||
ratio = float64(curN) / float64(curSize)
|
||||
}
|
||||
|
||||
i := int(ratio * float64(len(f.pullStageChars)-1))
|
||||
input := f.pullStageChars[i]
|
||||
completed[idx] = f.formatPullPhase(status[layer].Error() != nil, input)
|
||||
}
|
||||
|
||||
if progress.IsErrCompleted(status[layer].Error()) {
|
||||
numCompleted++
|
||||
}
|
||||
}
|
||||
|
||||
for _, layer := range layers {
|
||||
prog := status[layer]
|
||||
size += uint64(prog.Size())
|
||||
current += uint64(prog.Current())
|
||||
}
|
||||
|
||||
var progStr, auxInfo string
|
||||
if len(layers) > 0 {
|
||||
render := strings.Join(completed, "")
|
||||
prefix := f.pullCompletedStyle.Render(fmt.Sprintf("%d Layers", len(layers)))
|
||||
auxInfo = f.auxInfoStyle.Render(fmt.Sprintf("[%s / %s]", humanize.Bytes(current), humanize.Bytes(size)))
|
||||
if len(layers) == numCompleted {
|
||||
auxInfo = f.auxInfoStyle.Render(fmt.Sprintf("[%s] Extracting...", humanize.Bytes(size)))
|
||||
}
|
||||
|
||||
progStr = fmt.Sprintf("%s%s%s%s", prefix, f.layerCap(false), render, f.layerCap(true))
|
||||
}
|
||||
|
||||
return progStr + auxInfo
|
||||
}
|
||||
|
||||
// formatPullPhase returns a single character that represents the status of a layer pull.
|
||||
func (f containerdPullStatusFormatter) formatPullPhase(completed bool, inputStr string) string {
|
||||
if completed {
|
||||
return f.pullCompletedStyle.Render(f.pullStageChars[len(f.pullStageChars)-1])
|
||||
}
|
||||
return f.pullDownloadStyle.Render(inputStr)
|
||||
}
|
||||
|
||||
func (f containerdPullStatusFormatter) layerCap(end bool) string {
|
||||
l := len(f.layerCaps)
|
||||
if l == 0 {
|
||||
return ""
|
||||
}
|
||||
if end {
|
||||
return f.layerCaps[l-1]
|
||||
}
|
||||
return f.layerCaps[0]
|
||||
}
|
||||
@@ -49,6 +49,7 @@ func New(cfg HandlerConfig) *Handler {
|
||||
// register all supported event types with the respective handler functions
|
||||
d.AddHandlers(map[partybus.EventType]bubbly.EventHandlerFn{
|
||||
stereoscopeEvent.PullDockerImage: h.handlePullDockerImage,
|
||||
stereoscopeEvent.PullContainerdImage: h.handlePullContainerdImage,
|
||||
stereoscopeEvent.ReadImage: h.handleReadImage,
|
||||
stereoscopeEvent.FetchImage: h.handleFetchImage,
|
||||
syftEvent.PackageCatalogerStarted: h.handlePackageCatalogerStarted,
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
//go:build linux || darwin || netbsd
|
||||
// +build linux darwin netbsd
|
||||
|
||||
package ui
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/term"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
)
|
||||
|
||||
// Select is responsible for determining the specific UI function given select user option, the current platform
|
||||
// config values, and environment status (such as a TTY being present). The first UI in the returned slice of UIs
|
||||
// is intended to be used and the UIs that follow are meant to be attempted only in a fallback posture when there
|
||||
// are environmental problems (e.g. cannot write to the terminal). A writer is provided to capture the output of
|
||||
// the final SBOM report.
|
||||
func Select(verbose, quiet bool) (uis []clio.UI) {
|
||||
isStdoutATty := term.IsTerminal(int(os.Stdout.Fd()))
|
||||
isStderrATty := term.IsTerminal(int(os.Stderr.Fd()))
|
||||
notATerminal := !isStderrATty && !isStdoutATty
|
||||
|
||||
switch {
|
||||
case runtime.GOOS == "windows" || verbose || quiet || notATerminal || !isStderrATty:
|
||||
uis = append(uis, None(quiet))
|
||||
default:
|
||||
// TODO: it may make sense in the future to pass handler options into select
|
||||
h := handler.New(handler.DefaultHandlerConfig())
|
||||
uis = append(uis, New(h, verbose, quiet))
|
||||
}
|
||||
|
||||
return uis
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package ui
|
||||
|
||||
import "github.com/anchore/clio"
|
||||
|
||||
// Select is responsible for determining the specific UI function given select user option, the current platform
|
||||
// config values, and environment status (such as a TTY being present). The first UI in the returned slice of UIs
|
||||
// is intended to be used and the UIs that follow are meant to be attempted only in a fallback posture when there
|
||||
// are environmental problems (e.g. cannot write to the terminal). A writer is provided to capture the output of
|
||||
// the final SBOM report.
|
||||
func Select(verbose, quiet bool) (uis []clio.UI) {
|
||||
return append(uis, None(quiet))
|
||||
}
|
||||
@@ -1,16 +1,18 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/wagoodman/go-partybus"
|
||||
|
||||
"github.com/anchore/bubbly"
|
||||
"github.com/anchore/bubbly/bubbles/frame"
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/go-logger"
|
||||
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/event"
|
||||
@@ -29,13 +31,13 @@ type UI struct {
|
||||
subscription partybus.Unsubscribable
|
||||
finalizeEvents []partybus.Event
|
||||
|
||||
handler *handler.Handler
|
||||
handler *bubbly.HandlerCollection
|
||||
frame tea.Model
|
||||
}
|
||||
|
||||
func New(h *handler.Handler, _, quiet bool) *UI {
|
||||
func New(quiet bool, handlers ...bubbly.EventHandler) *UI {
|
||||
return &UI{
|
||||
handler: h,
|
||||
handler: bubbly.NewHandlerCollection(handlers...),
|
||||
frame: frame.New(),
|
||||
running: &sync.WaitGroup{},
|
||||
quiet: quiet,
|
||||
@@ -72,7 +74,7 @@ func (m *UI) Handle(e partybus.Event) error {
|
||||
|
||||
func (m *UI) Teardown(force bool) error {
|
||||
if !force {
|
||||
m.handler.Running.Wait()
|
||||
m.handler.Wait()
|
||||
m.program.Quit()
|
||||
// typically in all cases we would want to wait for the UI to finish. However there are still error cases
|
||||
// that are not accounted for, resulting in hangs. For now, we'll just wait for the UI to finish in the
|
||||
@@ -80,9 +82,19 @@ func (m *UI) Teardown(force bool) error {
|
||||
// string from the worker (outside of the UI after teardown).
|
||||
m.running.Wait()
|
||||
} else {
|
||||
_ = runWithTimeout(250*time.Millisecond, func() error {
|
||||
m.handler.Wait()
|
||||
return nil
|
||||
})
|
||||
|
||||
// it may be tempting to use Kill() however it has been found that this can cause the terminal to be left in
|
||||
// a bad state (where Ctrl+C and other control characters no longer works for future processes in that terminal).
|
||||
m.program.Quit()
|
||||
|
||||
_ = runWithTimeout(250*time.Millisecond, func() error {
|
||||
m.running.Wait()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: allow for writing out the full log output to the screen (only a partial log is shown currently)
|
||||
@@ -119,7 +131,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
// today we treat esc and ctrl+c the same, but in the future when the syft worker has a graceful way to
|
||||
// today we treat esc and ctrl+c the same, but in the future when the worker has a graceful way to
|
||||
// cancel in-flight work via a context, we can wire up esc to this path with bus.Exit()
|
||||
case "esc", "ctrl+c":
|
||||
bus.ExitWithInterrupt()
|
||||
@@ -135,7 +147,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.finalizeEvents = append(m.finalizeEvents, msg)
|
||||
|
||||
// why not return tea.Quit here for exit events? because there may be UI components that still need the update-render loop.
|
||||
// for this reason we'll let the syft event loop call Teardown() which will explicitly wait for these components
|
||||
// for this reason we'll let the event loop call Teardown() which will explicitly wait for these components
|
||||
return m, nil
|
||||
}
|
||||
|
||||
@@ -159,3 +171,17 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
func (m UI) View() string {
|
||||
return m.frame.View()
|
||||
}
|
||||
|
||||
func runWithTimeout(timeout time.Duration, fn func() error) (err error) {
|
||||
c := make(chan struct{}, 1)
|
||||
go func() {
|
||||
err = fn()
|
||||
c <- struct{}{}
|
||||
}()
|
||||
select {
|
||||
case <-c:
|
||||
case <-time.After(timeout):
|
||||
return fmt.Errorf("timed out after %v", timeout)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@ module github.com/anchore/syft
|
||||
go 1.21.0
|
||||
|
||||
require (
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.2
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acobaugh/osrelease v0.1.0
|
||||
github.com/adrg/xdg v0.4.0 // indirect
|
||||
github.com/anchore/bubbly v0.0.0-20230801194016-acdb4981b461
|
||||
github.com/anchore/clio v0.0.0-20230823172630-c42d666061af
|
||||
github.com/anchore/fangs v0.0.0-20230818131516-2186b10924fe
|
||||
@@ -17,10 +16,9 @@ require (
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501
|
||||
github.com/anchore/stereoscope v0.0.0-20230829142608-334c2222e137
|
||||
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44
|
||||
// we are hinting brotli to latest due to warning when installing archiver v3:
|
||||
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.0
|
||||
github.com/charmbracelet/bubbletea v0.24.2
|
||||
@@ -31,10 +29,10 @@ require (
|
||||
github.com/docker/docker v24.0.6+incompatible
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/facebookincubator/nvdtools v0.1.5
|
||||
github.com/github/go-spdx/v2 v2.1.2
|
||||
github.com/github/go-spdx/v2 v2.2.0
|
||||
github.com/gkampitakis/go-snaps v0.4.10
|
||||
github.com/go-git/go-billy/v5 v5.4.1
|
||||
github.com/go-git/go-git/v5 v5.8.1
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.9.0
|
||||
github.com/go-test/deep v1.1.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-containerregistry v0.16.1
|
||||
@@ -47,7 +45,6 @@ require (
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
@@ -56,58 +53,66 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/saferwall/pe v1.4.5
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/sassoftware/go-rpmutils v0.2.0
|
||||
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.3.1
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spdx/tools-golang v0.5.3
|
||||
github.com/spf13/afero v1.9.5
|
||||
github.com/spf13/afero v1.10.0
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.16.0 // indirect
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/vbatts/go-mtree v0.5.3
|
||||
github.com/vifraa/gopom v1.0.0
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651
|
||||
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
|
||||
golang.org/x/mod v0.12.0
|
||||
golang.org/x/net v0.15.0
|
||||
golang.org/x/term v0.12.0
|
||||
golang.org/x/term v0.12.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.25.0
|
||||
)
|
||||
|
||||
require github.com/sanity-io/litter v1.5.5
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/DataDog/zstd v1.4.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.7 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||
github.com/adrg/xdg v0.4.0 // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/charmbracelet/bubbles v0.16.1 // indirect
|
||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/containerd v1.7.0 // indirect
|
||||
github.com/containerd/continuity v0.3.0 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.1 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/cli v24.0.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
@@ -118,6 +123,8 @@ require (
|
||||
github.com/gkampitakis/ciinfo v0.2.5 // indirect
|
||||
github.com/gkampitakis/go-diff v1.3.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
@@ -144,27 +151,39 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
||||
github.com/opencontainers/runc v1.1.5 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.16.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/sylabs/sif/v2 v2.11.5 // indirect
|
||||
github.com/sylabs/squashfs v0.6.1 // indirect
|
||||
@@ -181,10 +200,14 @@ require (
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/grpc v1.55.0 // indirect
|
||||
|
||||
@@ -51,14 +51,18 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg=
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1 h1:5w1SxjGm9MTMNTuRbEPyw21ObdbaagTWF/KfF0qHTRE=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.1/go.mod h1:N/nrdWQI2SIjaACyyDs/u7+ddCkyl/zkNs8xFsHF2Ps=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.2 h1:kKQ0t1dPOlugSIYVOMiMtFqeXI2wp/f5DBIdfux8gnQ=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
@@ -73,9 +77,11 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QPUqhJldz8=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.7/go.mod h1:ILuwjA+kNW+MrN/w5un7n3mTqkwsFu4Bp05/okFUZlE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
|
||||
@@ -106,8 +112,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
|
||||
github.com/anchore/stereoscope v0.0.0-20230829142608-334c2222e137 h1:ZuiAV3lYKbGPkZR42UpoKecp/9aFU38CZSjaxjXCMYc=
|
||||
github.com/anchore/stereoscope v0.0.0-20230829142608-334c2222e137/go.mod h1:jkylrnuv++srUa2rsqCnG0n1ShD+0k2Xa6YtoNoRjAY=
|
||||
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44 h1:dKMvcpgqsRrX1ZWyqG53faVW+BahlaAO1RUEc7/rOjA=
|
||||
github.com/anchore/stereoscope v0.0.0-20230925132944-bf05af58eb44/go.mod h1:RtbeDCho0pxkPqrB1QNf/Jlxfc9juLmtYZAf2UbpJfk=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
@@ -152,9 +158,11 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG
|
||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||
github.com/charmbracelet/lipgloss v0.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU=
|
||||
github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
@@ -170,20 +178,35 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg=
|
||||
github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc=
|
||||
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
|
||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||
github.com/containerd/ttrpc v1.2.1 h1:VWv/Rzx023TBLv4WQ+9WPXlBG/s3rsRjY3i9AJ2BJdE=
|
||||
github.com/containerd/ttrpc v1.2.1/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
||||
github.com/containerd/typeurl/v2 v2.1.0 h1:yNAhJvbNEANt7ck48IlEGOxP7YAp6LLpGn5jZACDNIE=
|
||||
github.com/containerd/typeurl/v2 v2.1.0/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE=
|
||||
github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -200,6 +223,9 @@ github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryef
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
@@ -209,8 +235,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
|
||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -234,6 +260,7 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
|
||||
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
@@ -242,8 +269,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS
|
||||
github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro=
|
||||
github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/github/go-spdx/v2 v2.1.2 h1:p+Tv0yMgcuO0/vnMe9Qh4tmUgYhI6AsLVlakZ/Sx+DM=
|
||||
github.com/github/go-spdx/v2 v2.1.2/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w=
|
||||
github.com/github/go-spdx/v2 v2.2.0 h1:yBBLMasHA70Ujd35OpL/OjJOWWVNXcJGbars0GinGRI=
|
||||
github.com/github/go-spdx/v2 v2.2.0/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w=
|
||||
github.com/gkampitakis/ciinfo v0.2.5 h1:K0mac90lGguc1conc46l0YEsB7/nioWCqSnJp/6z8Eo=
|
||||
github.com/gkampitakis/ciinfo v0.2.5/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
|
||||
@@ -256,12 +283,12 @@ github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
|
||||
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
|
||||
github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
|
||||
github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -269,6 +296,11 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc=
|
||||
github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
@@ -276,6 +308,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
@@ -529,6 +562,15 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -538,6 +580,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
@@ -547,15 +590,24 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
|
||||
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/indent v1.2.1 h1:lFiviAbISHv3Rf0jcuh489bi06hj98JsVMtIDZQb9yM=
|
||||
@@ -579,6 +631,7 @@ github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
@@ -595,6 +648,9 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@@ -614,6 +670,8 @@ github.com/saferwall/pe v1.4.5/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7G
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
||||
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sassoftware/go-rpmutils v0.2.0 h1:pKW0HDYMFWQ5b4JQPiI3WI12hGsVoW0V8+GMoZiI/JE=
|
||||
github.com/sassoftware/go-rpmutils v0.2.0/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ=
|
||||
@@ -621,6 +679,7 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
|
||||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
@@ -631,6 +690,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
@@ -642,8 +702,8 @@ github.com/spdx/tools-golang v0.5.3 h1:ialnHeEYUC4+hkm5vJm4qz2x+oEJbS0mAMFrNXdQr
|
||||
github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/uFZm2NTMhI=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
|
||||
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
@@ -663,6 +723,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
@@ -683,6 +744,9 @@ github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM=
|
||||
github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y=
|
||||
github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ=
|
||||
github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@@ -700,6 +764,7 @@ github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vbatts/go-mtree v0.5.3 h1:S/jYlfG8rZ+a0bhZd+RANXejy7M4Js8fq9U+XoWTd5w=
|
||||
@@ -708,10 +773,12 @@ github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RV
|
||||
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
|
||||
github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0=
|
||||
github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA=
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20=
|
||||
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5 h1:lwgTsTy18nYqASnH58qyfRW/ldj7Gt2zzBvgYPzdA4s=
|
||||
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8=
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -745,10 +812,17 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -781,8 +855,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -796,7 +868,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
@@ -909,6 +980,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -916,6 +988,7 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -959,10 +1032,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1064,8 +1139,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -3,5 +3,5 @@ package internal
|
||||
const (
|
||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||
JSONSchemaVersion = "10.0.1"
|
||||
JSONSchemaVersion = "11.0.0"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CycloneDX Schemas
|
||||
|
||||
`syft` generates a CycloneDX BOm output. We want to be able to validate the CycloneDX schemas
|
||||
`syft` generates a CycloneDX Bom output. We want to be able to validate the CycloneDX schemas
|
||||
(and dependent schemas) against generated syft output. The best way to do this is with `xmllint`,
|
||||
however, this tool does not know how to deal with references from HTTP, only the local filesystem.
|
||||
For this reason we've included a copy of all schemas needed to validate `syft` output, modified
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,8 @@ func GetValidator(format cyclonedx.BOMFileFormat) sbom.Validator {
|
||||
}
|
||||
|
||||
xmlWithoutNS := format == cyclonedx.BOMFileFormatXML && !strings.Contains(bom.XMLNS, cycloneDXXmlSchema)
|
||||
if (cyclonedx.BOM{} == *bom || bom.Components == nil || xmlWithoutNS) {
|
||||
xmlWithoutComponents := format == cyclonedx.BOMFileFormatXML && bom.Components == nil
|
||||
if (cyclonedx.BOM{} == *bom || xmlWithoutComponents || xmlWithoutNS) {
|
||||
return fmt.Errorf("not a valid CycloneDX document")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package cyclonedxhelpers
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/CycloneDX/cyclonedx-go"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
|
||||
@@ -56,6 +56,8 @@ func SourceInfo(p pkg.Package) string {
|
||||
answer = "acquired package info from R-package DESCRIPTION file"
|
||||
case pkg.SwiftPkg:
|
||||
answer = "acquired package info from resolved Swift package manifest"
|
||||
case pkg.GithubActionPkg, pkg.GithubActionWorkflowPkg:
|
||||
answer = "acquired package info from GitHub Actions workflow file or composite action file"
|
||||
default:
|
||||
answer = "acquired package info from the following paths"
|
||||
}
|
||||
|
||||
@@ -239,6 +239,22 @@ func Test_SourceInfo(t *testing.T) {
|
||||
"from resolved Swift package manifest",
|
||||
},
|
||||
},
|
||||
{
|
||||
input: pkg.Package{
|
||||
Type: pkg.GithubActionPkg,
|
||||
},
|
||||
expected: []string{
|
||||
"from GitHub Actions workflow file or composite action file",
|
||||
},
|
||||
},
|
||||
{
|
||||
input: pkg.Package{
|
||||
Type: pkg.GithubActionWorkflowPkg,
|
||||
},
|
||||
expected: []string{
|
||||
"from GitHub Actions workflow file or composite action file",
|
||||
},
|
||||
},
|
||||
}
|
||||
var pkgTypes []pkg.Type
|
||||
for _, test := range tests {
|
||||
|
||||
@@ -5,14 +5,13 @@ import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"path"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/spdx/tools-golang/spdx"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/internal"
|
||||
@@ -722,7 +721,11 @@ func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
|
||||
|
||||
var result []*spdx.OtherLicense
|
||||
|
||||
ids := maps.Keys(licenses)
|
||||
var ids []string
|
||||
for licenseID := range licenses {
|
||||
ids = append(ids, licenseID)
|
||||
}
|
||||
|
||||
slices.Sort(ids)
|
||||
for _, id := range ids {
|
||||
license := licenses[id]
|
||||
|
||||
@@ -9,11 +9,40 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
func encoder(output io.Writer, s sbom.SBOM) error {
|
||||
func encoderV1_0(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_0)
|
||||
}
|
||||
|
||||
func encoderV1_1(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_1)
|
||||
}
|
||||
|
||||
func encoderV1_2(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_2)
|
||||
}
|
||||
|
||||
func encoderV1_3(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_3)
|
||||
}
|
||||
|
||||
func encoderV1_4(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_4)
|
||||
}
|
||||
|
||||
func encoderV1_5(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_5)
|
||||
}
|
||||
|
||||
func buildEncoder(output io.Writer, s sbom.SBOM) (cyclonedx.BOMEncoder, *cyclonedx.BOM) {
|
||||
bom := cyclonedxhelpers.ToFormatModel(s)
|
||||
enc := cyclonedx.NewBOMEncoder(output, cyclonedx.BOMFileFormatJSON)
|
||||
enc.SetPretty(true)
|
||||
enc.SetEscapeHTML(false)
|
||||
err := enc.Encode(bom)
|
||||
return err
|
||||
return enc, bom
|
||||
}
|
||||
|
||||
@@ -9,10 +9,62 @@ import (
|
||||
|
||||
const ID sbom.FormatID = "cyclonedx-json"
|
||||
|
||||
func Format() sbom.Format {
|
||||
var Format = Format1_4
|
||||
|
||||
func Format1_0() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
sbom.AnyVersion,
|
||||
encoder,
|
||||
cyclonedx.SpecVersion1_0.String(),
|
||||
encoderV1_0,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_1() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_1.String(),
|
||||
encoderV1_1,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_2() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_2.String(),
|
||||
encoderV1_2,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_3() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_3.String(),
|
||||
encoderV1_3,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_4() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_4.String(),
|
||||
encoderV1_4,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_5() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_5.String(),
|
||||
encoderV1_5,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatJSON),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatJSON),
|
||||
ID,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package cyclonedxjson
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/CycloneDX/cyclonedx-go"
|
||||
)
|
||||
|
||||
func TestFormatVersions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedVersion string
|
||||
}{
|
||||
{
|
||||
|
||||
"cyclonedx-json should default to v1.4",
|
||||
cyclonedx.SpecVersion1_4.String(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range tests {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
sbomFormat := Format()
|
||||
if sbomFormat.ID() != ID {
|
||||
t.Errorf("expected ID %q, got %q", ID, sbomFormat.ID())
|
||||
}
|
||||
|
||||
if sbomFormat.Version() != c.expectedVersion {
|
||||
t.Errorf("expected version %q, got %q", c.expectedVersion, sbomFormat.Version())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,40 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
func encoder(output io.Writer, s sbom.SBOM) error {
|
||||
func encoderV1_0(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_0)
|
||||
}
|
||||
|
||||
func encoderV1_1(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_1)
|
||||
}
|
||||
|
||||
func encoderV1_2(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_2)
|
||||
}
|
||||
|
||||
func encoderV1_3(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_3)
|
||||
}
|
||||
|
||||
func encoderV1_4(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_4)
|
||||
}
|
||||
|
||||
func encoderV1_5(output io.Writer, s sbom.SBOM) error {
|
||||
enc, bom := buildEncoder(output, s)
|
||||
return enc.EncodeVersion(bom, cyclonedx.SpecVersion1_5)
|
||||
}
|
||||
|
||||
func buildEncoder(output io.Writer, s sbom.SBOM) (cyclonedx.BOMEncoder, *cyclonedx.BOM) {
|
||||
bom := cyclonedxhelpers.ToFormatModel(s)
|
||||
enc := cyclonedx.NewBOMEncoder(output, cyclonedx.BOMFileFormatXML)
|
||||
enc.SetPretty(true)
|
||||
|
||||
err := enc.Encode(bom)
|
||||
return err
|
||||
enc.SetEscapeHTML(false)
|
||||
return enc, bom
|
||||
}
|
||||
|
||||
@@ -9,10 +9,62 @@ import (
|
||||
|
||||
const ID sbom.FormatID = "cyclonedx-xml"
|
||||
|
||||
func Format() sbom.Format {
|
||||
var Format = Format1_4
|
||||
|
||||
func Format1_0() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
sbom.AnyVersion,
|
||||
encoder,
|
||||
cyclonedx.SpecVersion1_0.String(),
|
||||
encoderV1_0,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_1() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_1.String(),
|
||||
encoderV1_1,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_2() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_2.String(),
|
||||
encoderV1_2,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_3() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_3.String(),
|
||||
encoderV1_3,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_4() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_4.String(),
|
||||
encoderV1_4,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
)
|
||||
}
|
||||
|
||||
func Format1_5() sbom.Format {
|
||||
return sbom.NewFormat(
|
||||
cyclonedx.SpecVersion1_5.String(),
|
||||
encoderV1_5,
|
||||
cyclonedxhelpers.GetDecoder(cyclonedx.BOMFileFormatXML),
|
||||
cyclonedxhelpers.GetValidator(cyclonedx.BOMFileFormatXML),
|
||||
ID, "cyclonedx", "cyclone",
|
||||
|
||||
+27
-8
@@ -6,10 +6,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/formats/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/formats/cyclonedxxml"
|
||||
@@ -26,17 +25,27 @@ import (
|
||||
func Formats() []sbom.Format {
|
||||
return []sbom.Format{
|
||||
syftjson.Format(),
|
||||
cyclonedxxml.Format(),
|
||||
cyclonedxjson.Format(),
|
||||
github.Format(),
|
||||
table.Format(),
|
||||
text.Format(),
|
||||
template.Format(),
|
||||
cyclonedxxml.Format1_0(),
|
||||
cyclonedxxml.Format1_1(),
|
||||
cyclonedxxml.Format1_2(),
|
||||
cyclonedxxml.Format1_3(),
|
||||
cyclonedxxml.Format1_4(),
|
||||
cyclonedxxml.Format1_5(),
|
||||
cyclonedxjson.Format1_0(),
|
||||
cyclonedxjson.Format1_1(),
|
||||
cyclonedxjson.Format1_2(),
|
||||
cyclonedxjson.Format1_3(),
|
||||
cyclonedxjson.Format1_4(),
|
||||
cyclonedxjson.Format1_5(),
|
||||
spdxtagvalue.Format2_1(),
|
||||
spdxtagvalue.Format2_2(),
|
||||
spdxtagvalue.Format2_3(),
|
||||
spdxjson.Format2_2(),
|
||||
spdxjson.Format2_3(),
|
||||
table.Format(),
|
||||
text.Format(),
|
||||
template.Format(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +64,7 @@ func Identify(by []byte) sbom.Format {
|
||||
|
||||
// ByName accepts a name@version string, such as:
|
||||
//
|
||||
// spdx-json@2.1 or cyclonedx@2
|
||||
// spdx-json@2.1 or cyclonedx@1.5
|
||||
func ByName(name string) sbom.Format {
|
||||
parts := strings.SplitN(name, "@", 2)
|
||||
version := sbom.AnyVersion
|
||||
@@ -71,6 +80,16 @@ func ByNameAndVersion(name string, version string) sbom.Format {
|
||||
for _, f := range Formats() {
|
||||
for _, n := range f.IDs() {
|
||||
if cleanFormatName(string(n)) == name && versionMatches(f.Version(), version) {
|
||||
// if the version is not specified and the format is cyclonedx, then we want to return the most recent version up to 1.4
|
||||
// If more aliases like cdx are added this will not catch those - we want to eventually provide a way for
|
||||
// formats to inform this function what their default version is
|
||||
// TODO: remove this check when 1.5 is stable or default formats are designed. PR below should be merged.
|
||||
// https://github.com/CycloneDX/cyclonedx-go/pull/90
|
||||
if version == sbom.AnyVersion && strings.Contains(string(n), "cyclone") {
|
||||
if f.Version() == "1.5" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if mostRecentFormat == nil || f.Version() > mostRecentFormat.Version() {
|
||||
mostRecentFormat = f
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ func TestFormats_EmptyInput(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestByName(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want sbom.FormatID
|
||||
|
||||
@@ -9,8 +9,17 @@ import (
|
||||
|
||||
"github.com/go-test/deep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/formats/internal/testutils"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeCycle(t *testing.T) {
|
||||
@@ -86,3 +95,145 @@ func TestOutOfDateParser(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_encodeDecodeFileMetadata(t *testing.T) {
|
||||
p := pkg.Package{
|
||||
Name: "pkg",
|
||||
Version: "version",
|
||||
FoundBy: "something",
|
||||
Locations: file.NewLocationSet(file.Location{
|
||||
LocationData: file.LocationData{
|
||||
Coordinates: file.Coordinates{
|
||||
RealPath: "/somewhere",
|
||||
FileSystemID: "id",
|
||||
},
|
||||
},
|
||||
LocationMetadata: file.LocationMetadata{
|
||||
Annotations: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
}),
|
||||
Licenses: pkg.NewLicenseSet(pkg.License{
|
||||
Value: "MIT",
|
||||
SPDXExpression: "MIT",
|
||||
Type: "MIT",
|
||||
URLs: internal.NewStringSet("https://example.org/license"),
|
||||
Locations: file.LocationSet{},
|
||||
}),
|
||||
Language: "language",
|
||||
Type: "type",
|
||||
CPEs: []cpe.CPE{
|
||||
{
|
||||
Part: "a",
|
||||
Vendor: "vendor",
|
||||
Product: "product",
|
||||
Version: "version",
|
||||
Update: "update",
|
||||
},
|
||||
},
|
||||
PURL: "pkg:generic/pkg@version",
|
||||
MetadataType: "",
|
||||
Metadata: nil,
|
||||
}
|
||||
p.SetID()
|
||||
|
||||
c := file.Coordinates{
|
||||
RealPath: "some-file",
|
||||
FileSystemID: "some-fs-id",
|
||||
}
|
||||
|
||||
s := sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
Packages: pkg.NewCollection(p),
|
||||
FileMetadata: map[file.Coordinates]file.Metadata{
|
||||
c: {
|
||||
FileInfo: stereoscopeFile.ManualInfo{
|
||||
NameValue: c.RealPath,
|
||||
ModeValue: 0644,
|
||||
SizeValue: 7,
|
||||
},
|
||||
Path: c.RealPath,
|
||||
Type: stereoscopeFile.TypeRegular,
|
||||
UserID: 1,
|
||||
GroupID: 2,
|
||||
MIMEType: "text/plain",
|
||||
},
|
||||
},
|
||||
FileDigests: map[file.Coordinates][]file.Digest{
|
||||
c: {
|
||||
{
|
||||
Algorithm: "sha1",
|
||||
Value: "d34db33f",
|
||||
},
|
||||
},
|
||||
},
|
||||
FileContents: map[file.Coordinates]string{
|
||||
c: "some contents",
|
||||
},
|
||||
FileLicenses: map[file.Coordinates][]file.License{
|
||||
c: {
|
||||
{
|
||||
Value: "MIT",
|
||||
SPDXExpression: "MIT",
|
||||
Type: "MIT",
|
||||
LicenseEvidence: &file.LicenseEvidence{
|
||||
Confidence: 1,
|
||||
Offset: 2,
|
||||
Extent: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
LinuxDistribution: &linux.Release{
|
||||
PrettyName: "some os",
|
||||
Name: "os",
|
||||
ID: "os-id",
|
||||
IDLike: []string{"os"},
|
||||
Version: "version",
|
||||
VersionID: "version",
|
||||
VersionCodename: "codename",
|
||||
BuildID: "build-id",
|
||||
ImageID: "image-id",
|
||||
ImageVersion: "image-version",
|
||||
Variant: "variant",
|
||||
VariantID: "variant-id",
|
||||
HomeURL: "https://example.org/os",
|
||||
SupportURL: "https://example.org/os/support",
|
||||
BugReportURL: "https://example.org/os/bugs",
|
||||
PrivacyPolicyURL: "https://example.org/os/privacy",
|
||||
CPEName: "os-cpe",
|
||||
SupportEnd: "now",
|
||||
},
|
||||
},
|
||||
Relationships: nil,
|
||||
Source: source.Description{
|
||||
ID: "some-id",
|
||||
Name: "some-name",
|
||||
Version: "some-version",
|
||||
Metadata: source.FileSourceMetadata{
|
||||
Path: "/some-file-source-path",
|
||||
Digests: []file.Digest{
|
||||
{
|
||||
Algorithm: "sha1",
|
||||
Value: "d34db33f",
|
||||
},
|
||||
},
|
||||
MIMEType: "file/zip",
|
||||
},
|
||||
},
|
||||
Descriptor: sbom.Descriptor{
|
||||
Name: "syft",
|
||||
Version: "this-version",
|
||||
},
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
err := encoder(buf, s)
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := decoder(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, s, *got)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package syftjson
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
)
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
version string
|
||||
}{
|
||||
{
|
||||
name: "default version should use latest internal version",
|
||||
version: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range tests {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
sbomFormat := Format()
|
||||
if sbomFormat.ID() != ID {
|
||||
t.Errorf("expected ID %q, got %q", ID, sbomFormat.ID())
|
||||
}
|
||||
|
||||
if sbomFormat.Version() != internal.JSONSchemaVersion {
|
||||
t.Errorf("expected version %q, got %q", c.version, sbomFormat.Version())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/license"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
@@ -10,6 +11,7 @@ type File struct {
|
||||
Metadata *FileMetadataEntry `json:"metadata,omitempty"`
|
||||
Contents string `json:"contents,omitempty"`
|
||||
Digests []file.Digest `json:"digests,omitempty"`
|
||||
Licenses []FileLicense `json:"licenses,omitempty"`
|
||||
}
|
||||
|
||||
type FileMetadataEntry struct {
|
||||
@@ -21,3 +23,16 @@ type FileMetadataEntry struct {
|
||||
MIMEType string `json:"mimeType"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type FileLicense struct {
|
||||
Value string `json:"value"`
|
||||
SPDXExpression string `json:"spdxExpression"`
|
||||
Type license.Type `json:"type"`
|
||||
Evidence *FileLicenseEvidence `json:"evidence,omitempty"`
|
||||
}
|
||||
|
||||
type FileLicenseEvidence struct {
|
||||
Confidence int `json:"confidence"`
|
||||
Offset int `json:"offset"`
|
||||
Extent int `json:"extent"`
|
||||
}
|
||||
|
||||
@@ -106,12 +106,31 @@ func toFile(s sbom.SBOM) []model.File {
|
||||
contents = contentsForLocation
|
||||
}
|
||||
|
||||
var licenses []model.FileLicense
|
||||
for _, l := range artifacts.FileLicenses[coordinates] {
|
||||
var evidence *model.FileLicenseEvidence
|
||||
if e := l.LicenseEvidence; e != nil {
|
||||
evidence = &model.FileLicenseEvidence{
|
||||
Confidence: e.Confidence,
|
||||
Offset: e.Offset,
|
||||
Extent: e.Extent,
|
||||
}
|
||||
}
|
||||
licenses = append(licenses, model.FileLicense{
|
||||
Value: l.Value,
|
||||
SPDXExpression: l.SPDXExpression,
|
||||
Type: l.Type,
|
||||
Evidence: evidence,
|
||||
})
|
||||
}
|
||||
|
||||
results = append(results, model.File{
|
||||
ID: string(coordinates.ID()),
|
||||
Location: coordinates,
|
||||
Metadata: toFileMetadataEntry(coordinates, metadata),
|
||||
Digests: digests,
|
||||
Contents: contents,
|
||||
Licenses: licenses,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
|
||||
Packages: catalog,
|
||||
FileMetadata: fileArtifacts.FileMetadata,
|
||||
FileDigests: fileArtifacts.FileDigests,
|
||||
FileContents: fileArtifacts.FileContents,
|
||||
FileLicenses: fileArtifacts.FileLicenses,
|
||||
LinuxDistribution: toSyftLinuxRelease(doc.Distro),
|
||||
},
|
||||
Source: *toSyftSourceData(doc.Source),
|
||||
@@ -66,6 +68,8 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
|
||||
ret := sbom.Artifacts{
|
||||
FileMetadata: make(map[file.Coordinates]file.Metadata),
|
||||
FileDigests: make(map[file.Coordinates][]file.Digest),
|
||||
FileContents: make(map[file.Coordinates]string),
|
||||
FileLicenses: make(map[file.Coordinates][]file.License),
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
@@ -100,6 +104,27 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
|
||||
Value: d.Value,
|
||||
})
|
||||
}
|
||||
|
||||
if f.Contents != "" {
|
||||
ret.FileContents[coord] = f.Contents
|
||||
}
|
||||
|
||||
for _, l := range f.Licenses {
|
||||
var evidence *file.LicenseEvidence
|
||||
if e := l.Evidence; e != nil {
|
||||
evidence = &file.LicenseEvidence{
|
||||
Confidence: e.Confidence,
|
||||
Offset: e.Offset,
|
||||
Extent: e.Extent,
|
||||
}
|
||||
}
|
||||
ret.FileLicenses[coord] = append(ret.FileLicenses[coord], file.License{
|
||||
Value: l.Value,
|
||||
SPDXExpression: l.SPDXExpression,
|
||||
Type: l.Type,
|
||||
LicenseEvidence: evidence,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@@ -312,6 +312,8 @@ func Test_toSyftFiles(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.want.FileContents = make(map[file.Coordinates]string)
|
||||
tt.want.FileLicenses = make(map[file.Coordinates][]file.License)
|
||||
assert.Equal(t, tt.want, toSyftFiles(tt.files))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package fileresolver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
@@ -523,11 +521,6 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) {
|
||||
func TestAllLayersResolver_AllLocations(t *testing.T) {
|
||||
img := imagetest.GetFixtureImage(t, "docker-archive", "image-files-deleted")
|
||||
|
||||
arch := "x86_64"
|
||||
if runtime.GOARCH == "arm64" {
|
||||
arch = "aarch64"
|
||||
}
|
||||
|
||||
resolver, err := NewFromContainerImageAllLayers(img)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -638,9 +631,9 @@ func TestAllLayersResolver_AllLocations(t *testing.T) {
|
||||
"/lib/apk/db/triggers",
|
||||
"/lib/apk/exec",
|
||||
"/lib/firmware",
|
||||
fmt.Sprintf("/lib/ld-musl-%s.so.1", arch),
|
||||
"/lib/ld-musl-x86_64.so.1",
|
||||
"/lib/libapk.so.3.12.0",
|
||||
fmt.Sprintf("/lib/libc.musl-%s.so.1", arch),
|
||||
"/lib/libc.musl-x86_64.so.1",
|
||||
"/lib/libcrypto.so.3",
|
||||
"/lib/libssl.so.3",
|
||||
"/lib/libz.so.1",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.17.1 as tools
|
||||
FROM alpine:3.17.1@sha256:93d5a28ff72d288d69b5997b8ba47396d2cbb62a72b5d87cd3351094b5d578a0 as tools
|
||||
FROM scratch
|
||||
COPY --from=tools /bin /bin
|
||||
COPY --from=tools /lib /lib
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -13,7 +14,6 @@ import (
|
||||
"github.com/bmatcuk/doublestar/v4"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/afero"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM busybox:1.35
|
||||
FROM busybox:1.35@sha256:7ae8447f3a7f5bccaa765926f25fc038e425cf1b2be6748727bbea9a13102094
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/elixir"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/erlang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/githubactions"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/haskell"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
@@ -74,6 +75,8 @@ func DirectoryCatalogers(cfg Config) []pkg.Cataloger {
|
||||
dotnet.NewDotnetPortableExecutableCataloger(),
|
||||
elixir.NewMixLockCataloger(),
|
||||
erlang.NewRebarLockCataloger(),
|
||||
githubactions.NewActionUsageCataloger(),
|
||||
githubactions.NewWorkflowUsageCataloger(),
|
||||
golang.NewGoModFileCataloger(cfg.Golang),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Golang),
|
||||
haskell.NewHackageCataloger(),
|
||||
@@ -110,6 +113,8 @@ func AllCatalogers(cfg Config) []pkg.Cataloger {
|
||||
dotnet.NewDotnetPortableExecutableCataloger(),
|
||||
elixir.NewMixLockCataloger(),
|
||||
erlang.NewRebarLockCataloger(),
|
||||
githubactions.NewActionUsageCataloger(),
|
||||
githubactions.NewWorkflowUsageCataloger(),
|
||||
golang.NewGoModFileCataloger(cfg.Golang),
|
||||
golang.NewGoModuleBinaryCataloger(cfg.Golang),
|
||||
haskell.NewHackageCataloger(),
|
||||
|
||||
@@ -475,6 +475,7 @@
|
||||
"fast-csv": "cpe:2.3:a:c2fo:fast-csv:*:*:*:*:*:node.js:*:*",
|
||||
"fast-http": "cpe:2.3:a:fast-http_project:fast-http:*:*:*:*:*:node.js:*:*",
|
||||
"fast-http-cli": "cpe:2.3:a:fast-http-cli_project:fast-http-cli:*:*:*:*:*:node.js:*:*",
|
||||
"fastest-json-copy": "cpe:2.3:a:fastest-json-copy_project:fastest-json-copy:*:*:*:*:*:node.js:*:*",
|
||||
"ffmepg": "cpe:2.3:a:ffmepg_project:ffmepg:*:*:*:*:*:node.js:*:*",
|
||||
"ffmpegdotjs": "cpe:2.3:a:ffmpegdotjs_project:ffmpegdotjs:*:*:*:*:*:node.js:*:*",
|
||||
"fibjs": "cpe:2.3:a:fibjs_project:fibjs:*:*:*:*:*:node.js:*:*",
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe/dictionary"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cpe
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
@@ -287,6 +288,7 @@ func GetManifestFieldGroupIDs(manifest *pkg.JavaManifest, fields []string) (grou
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(groupIDs)
|
||||
|
||||
return groupIDs
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ var DefaultArtifactIDToGroupID = map[string]string{
|
||||
"ant-weblogic": "org.apache.ant",
|
||||
"ant-xz": "org.apache.ant",
|
||||
"commons-codec": "commons-codec",
|
||||
"commons-logging": "commons-logging", // see e.g. https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1.1
|
||||
"okhttp": "com.squareup.okhttp3",
|
||||
"okio": "com.squareup.okio",
|
||||
"spring": "org.springframework",
|
||||
|
||||
@@ -36,12 +36,24 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
|
||||
if err := json.NewDecoder(reader).Decode(&cl); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, node := range cl.GraphLock.Nodes {
|
||||
|
||||
// requires is a list of package indices. We first need to fill it, and then we can resolve the package
|
||||
// in a second iteration
|
||||
var indexToPkgMap = map[string]pkg.Package{}
|
||||
|
||||
// we do not want to store the index list requires in the conan metadata, because it is not useful to have it in
|
||||
// the SBOM. Instead, we will store it in a map and then use it to build the relationships
|
||||
// maps pkg.ID to a list of indices
|
||||
var parsedPkgRequires = map[artifact.ID][]string{}
|
||||
|
||||
for idx, node := range cl.GraphLock.Nodes {
|
||||
metadata := pkg.ConanLockMetadata{
|
||||
Ref: node.Ref,
|
||||
Options: parseOptions(node.Options),
|
||||
Path: node.Path,
|
||||
Context: node.Context,
|
||||
Ref: node.Ref,
|
||||
Options: parseOptions(node.Options),
|
||||
Path: node.Path,
|
||||
Context: node.Context,
|
||||
PackageID: node.PackageID,
|
||||
Prev: node.Prev,
|
||||
}
|
||||
|
||||
p := newConanlockPackage(
|
||||
@@ -50,11 +62,28 @@ func parseConanlock(_ file.Resolver, _ *generic.Environment, reader file.Locatio
|
||||
)
|
||||
|
||||
if p != nil {
|
||||
pkgs = append(pkgs, *p)
|
||||
pk := *p
|
||||
pkgs = append(pkgs, pk)
|
||||
parsedPkgRequires[pk.ID()] = node.Requires
|
||||
indexToPkgMap[idx] = pk
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil, nil
|
||||
var relationships []artifact.Relationship
|
||||
|
||||
for _, p := range pkgs {
|
||||
requires := parsedPkgRequires[p.ID()]
|
||||
for _, r := range requires {
|
||||
// this is a pkg that package "p" depends on... make a relationship
|
||||
relationships = append(relationships, artifact.Relationship{
|
||||
From: indexToPkgMap[r],
|
||||
To: p,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, relationships, nil
|
||||
}
|
||||
|
||||
func parseOptions(options string) map[string]string {
|
||||
|
||||
@@ -13,56 +13,301 @@ func TestParseConanlock(t *testing.T) {
|
||||
fixture := "test-fixtures/conan.lock"
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "spdlog",
|
||||
Version: "1.11.0",
|
||||
PURL: "pkg:conan/spdlog@1.11.0",
|
||||
Name: "mfast",
|
||||
Version: "1.2.2",
|
||||
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "spdlog/1.11.0",
|
||||
Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"header_only": "False",
|
||||
"no_exceptions": "False",
|
||||
"shared": "False",
|
||||
"wchar_filenames": "False",
|
||||
"wchar_support": "False",
|
||||
"fmt:fPIC": "True",
|
||||
"fmt:header_only": "False",
|
||||
"fmt:shared": "False",
|
||||
"fmt:with_fmt_alias": "False",
|
||||
"fmt:with_os_api": "True",
|
||||
"fPIC": "True",
|
||||
"shared": "False",
|
||||
"with_sqlite3": "False",
|
||||
"boost:addr2line_location": "/usr/bin/addr2line",
|
||||
"boost:asio_no_deprecated": "False",
|
||||
"boost:buildid": "None",
|
||||
"boost:bzip2": "True",
|
||||
"boost:debug_level": "0",
|
||||
"boost:diagnostic_definitions": "False",
|
||||
"boost:error_code_header_only": "False",
|
||||
"boost:extra_b2_flags": "None",
|
||||
"boost:fPIC": "True",
|
||||
"boost:filesystem_no_deprecated": "False",
|
||||
"boost:header_only": "False",
|
||||
"boost:i18n_backend": "deprecated",
|
||||
"boost:i18n_backend_iconv": "libc",
|
||||
"boost:i18n_backend_icu": "False",
|
||||
"boost:layout": "system",
|
||||
"boost:lzma": "False",
|
||||
"boost:magic_autolink": "False",
|
||||
"boost:multithreading": "True",
|
||||
"boost:namespace": "boost",
|
||||
"boost:namespace_alias": "False",
|
||||
"boost:numa": "True",
|
||||
"boost:pch": "True",
|
||||
"boost:python_executable": "None",
|
||||
"boost:python_version": "None",
|
||||
"boost:segmented_stacks": "False",
|
||||
"boost:shared": "False",
|
||||
"boost:system_no_deprecated": "False",
|
||||
"boost:system_use_utf8": "False",
|
||||
"boost:visibility": "hidden",
|
||||
"boost:with_stacktrace_backtrace": "True",
|
||||
"boost:without_atomic": "False",
|
||||
"boost:without_chrono": "False",
|
||||
"boost:without_container": "False",
|
||||
"boost:without_context": "False",
|
||||
"boost:without_contract": "False",
|
||||
"boost:without_coroutine": "False",
|
||||
"boost:without_date_time": "False",
|
||||
"boost:without_exception": "False",
|
||||
"boost:without_fiber": "False",
|
||||
"boost:without_filesystem": "False",
|
||||
"boost:without_graph": "False",
|
||||
"boost:without_graph_parallel": "True",
|
||||
"boost:without_iostreams": "False",
|
||||
"boost:without_json": "False",
|
||||
"boost:without_locale": "False",
|
||||
"boost:without_log": "False",
|
||||
"boost:without_math": "False",
|
||||
"boost:without_mpi": "True",
|
||||
"boost:without_nowide": "False",
|
||||
"boost:without_program_options": "False",
|
||||
"boost:without_python": "True",
|
||||
"boost:without_random": "False",
|
||||
"boost:without_regex": "False",
|
||||
"boost:without_serialization": "False",
|
||||
"boost:without_stacktrace": "False",
|
||||
"boost:without_system": "False",
|
||||
"boost:without_test": "False",
|
||||
"boost:without_thread": "False",
|
||||
"boost:without_timer": "False",
|
||||
"boost:without_type_erasure": "False",
|
||||
"boost:without_wave": "False",
|
||||
"boost:zlib": "True",
|
||||
"boost:zstd": "False",
|
||||
"bzip2:build_executable": "True",
|
||||
"bzip2:fPIC": "True",
|
||||
"bzip2:shared": "False",
|
||||
"libbacktrace:fPIC": "True",
|
||||
"libbacktrace:shared": "False",
|
||||
"tinyxml2:fPIC": "True",
|
||||
"tinyxml2:shared": "False",
|
||||
"zlib:fPIC": "True",
|
||||
"zlib:shared": "False",
|
||||
},
|
||||
Path: "conanfile.py",
|
||||
Context: "host",
|
||||
Context: "host",
|
||||
PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac",
|
||||
Prev: "0ca9799450422cc55a92ccc6ffd57fba",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fmt",
|
||||
Version: "9.1.0",
|
||||
PURL: "pkg:conan/my_user/fmt@9.1.0?channel=my_channel",
|
||||
Name: "boost",
|
||||
Version: "1.75.0",
|
||||
PURL: "pkg:conan/boost@1.75.0",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
|
||||
Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"header_only": "False",
|
||||
"shared": "False",
|
||||
"with_fmt_alias": "False",
|
||||
"with_os_api": "True",
|
||||
"addr2line_location": "/usr/bin/addr2line",
|
||||
"asio_no_deprecated": "False",
|
||||
"buildid": "None",
|
||||
"bzip2": "True",
|
||||
"debug_level": "0",
|
||||
"diagnostic_definitions": "False",
|
||||
"error_code_header_only": "False",
|
||||
"extra_b2_flags": "None",
|
||||
"fPIC": "True",
|
||||
"filesystem_no_deprecated": "False",
|
||||
"header_only": "False",
|
||||
"i18n_backend": "deprecated",
|
||||
"i18n_backend_iconv": "libc",
|
||||
"i18n_backend_icu": "False",
|
||||
"layout": "system",
|
||||
"lzma": "False",
|
||||
"magic_autolink": "False",
|
||||
"multithreading": "True",
|
||||
"namespace": "boost",
|
||||
"namespace_alias": "False",
|
||||
"numa": "True",
|
||||
"pch": "True",
|
||||
"python_executable": "None",
|
||||
"python_version": "None",
|
||||
"segmented_stacks": "False",
|
||||
"shared": "False",
|
||||
"system_no_deprecated": "False",
|
||||
"system_use_utf8": "False",
|
||||
"visibility": "hidden",
|
||||
"with_stacktrace_backtrace": "True",
|
||||
"without_atomic": "False",
|
||||
"without_chrono": "False",
|
||||
"without_container": "False",
|
||||
"without_context": "False",
|
||||
"without_contract": "False",
|
||||
"without_coroutine": "False",
|
||||
"without_date_time": "False",
|
||||
"without_exception": "False",
|
||||
"without_fiber": "False",
|
||||
"without_filesystem": "False",
|
||||
"without_graph": "False",
|
||||
"without_graph_parallel": "True",
|
||||
"without_iostreams": "False",
|
||||
"without_json": "False",
|
||||
"without_locale": "False",
|
||||
"without_log": "False",
|
||||
"without_math": "False",
|
||||
"without_mpi": "True",
|
||||
"without_nowide": "False",
|
||||
"without_program_options": "False",
|
||||
"without_python": "True",
|
||||
"without_random": "False",
|
||||
"without_regex": "False",
|
||||
"without_serialization": "False",
|
||||
"without_stacktrace": "False",
|
||||
"without_system": "False",
|
||||
"without_test": "False",
|
||||
"without_thread": "False",
|
||||
"without_timer": "False",
|
||||
"without_type_erasure": "False",
|
||||
"without_wave": "False",
|
||||
"zlib": "True",
|
||||
"zstd": "False",
|
||||
"bzip2:build_executable": "True",
|
||||
"bzip2:fPIC": "True",
|
||||
"bzip2:shared": "False",
|
||||
"libbacktrace:fPIC": "True",
|
||||
"libbacktrace:shared": "False",
|
||||
"zlib:fPIC": "True",
|
||||
"zlib:shared": "False",
|
||||
},
|
||||
Context: "host",
|
||||
PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
|
||||
Prev: "b9d7912e6131dfa453c725593b36c808",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "zlib",
|
||||
Version: "1.2.12",
|
||||
PURL: "pkg:conan/zlib@1.2.12",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"shared": "False",
|
||||
},
|
||||
Context: "host",
|
||||
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
|
||||
Prev: "7cd359d44f89ab08e33b5db75605002c",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bzip2",
|
||||
Version: "1.0.8",
|
||||
PURL: "pkg:conan/bzip2@1.0.8",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
|
||||
Options: map[string]string{
|
||||
"build_executable": "True",
|
||||
"fPIC": "True",
|
||||
"shared": "False",
|
||||
},
|
||||
Context: "host",
|
||||
PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e",
|
||||
Prev: "b746948bc999d6f17f52a1f76e729e80",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "libbacktrace",
|
||||
Version: "cci.20210118",
|
||||
PURL: "pkg:conan/libbacktrace@cci.20210118",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"shared": "False",
|
||||
},
|
||||
Context: "host",
|
||||
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
|
||||
Prev: "98a976f017e894c27e9a158b807ec0c7",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "tinyxml2",
|
||||
Version: "9.0.0",
|
||||
PURL: "pkg:conan/tinyxml2@9.0.0",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"shared": "False",
|
||||
},
|
||||
Context: "host",
|
||||
// intentionally remove to test missing PackageID and Prev
|
||||
// PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e",
|
||||
// Prev: "548bb273d2980991baa519453d68e5cd",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: relationships are not under test
|
||||
var expectedRelationships []artifact.Relationship
|
||||
// relationships require IDs to be set to be sorted similarly
|
||||
for i := range expected {
|
||||
expected[i].SetID()
|
||||
}
|
||||
|
||||
var expectedRelationships = []artifact.Relationship{
|
||||
{
|
||||
From: expected[1], // boost
|
||||
To: expected[0], // mfast
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
Data: nil,
|
||||
},
|
||||
{
|
||||
From: expected[5], // tinyxml2
|
||||
To: expected[0], // mfast
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
Data: nil,
|
||||
},
|
||||
{
|
||||
From: expected[2], // zlib
|
||||
To: expected[1], // boost
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
Data: nil,
|
||||
},
|
||||
{
|
||||
From: expected[3], // bzip2
|
||||
To: expected[1], // boost
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
Data: nil,
|
||||
},
|
||||
{
|
||||
From: expected[4], // libbacktrace
|
||||
To: expected[1], // boost
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
Data: nil,
|
||||
},
|
||||
}
|
||||
|
||||
pkgtest.TestFileParser(t, fixture, parseConanlock, expected, expectedRelationships)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Conan test data
|
||||
|
||||
This folder contains the test data for the Conan package manager.
|
||||
|
||||
## conan.lock
|
||||
|
||||
The conan lock file is created in the following way.
|
||||
|
||||
We explicitly use a package which has dependencies, which in turn also have dependendencies.
|
||||
This is necessary to verify that the dependency tree is properly parsed.
|
||||
|
||||
1. Use `conan lock create --reference "mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39"`
|
||||
2. Manually modify the user and channel of mfast package, to be able to test that it is properly set in SBOM:
|
||||
`sed -i 's|mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39|mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39|g' conan.lock`
|
||||
3. Manually delete the package id and prev from tinyxml2 entry to test conan lock parsing if they are missing:
|
||||
`sed -i 's|\"package_id\": \"6557f18ca99c0b6a233f43db00e30efaa525e27e\",||g' conan.lock`
|
||||
`sed -i 's|\"prev\": \"548bb273d2980991baa519453d68e5cd\",||g' conan.lock`
|
||||
@@ -1,20 +1,55 @@
|
||||
{
|
||||
"graph_lock": {
|
||||
"nodes": {
|
||||
"0": {
|
||||
"ref": "spdlog/1.11.0",
|
||||
"options": "fPIC=True\nheader_only=False\nno_exceptions=False\nshared=False\nwchar_filenames=False\nwchar_support=False\nfmt:fPIC=True\nfmt:header_only=False\nfmt:shared=False\nfmt:with_fmt_alias=False\nfmt:with_os_api=True",
|
||||
"1": {
|
||||
"ref": "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
|
||||
"options": "fPIC=True\nshared=False\nwith_sqlite3=False\nboost:addr2line_location=/usr/bin/addr2line\nboost:asio_no_deprecated=False\nboost:buildid=None\nboost:bzip2=True\nboost:debug_level=0\nboost:diagnostic_definitions=False\nboost:error_code_header_only=False\nboost:extra_b2_flags=None\nboost:fPIC=True\nboost:filesystem_no_deprecated=False\nboost:header_only=False\nboost:i18n_backend=deprecated\nboost:i18n_backend_iconv=libc\nboost:i18n_backend_icu=False\nboost:layout=system\nboost:lzma=False\nboost:magic_autolink=False\nboost:multithreading=True\nboost:namespace=boost\nboost:namespace_alias=False\nboost:numa=True\nboost:pch=True\nboost:python_executable=None\nboost:python_version=None\nboost:segmented_stacks=False\nboost:shared=False\nboost:system_no_deprecated=False\nboost:system_use_utf8=False\nboost:visibility=hidden\nboost:with_stacktrace_backtrace=True\nboost:without_atomic=False\nboost:without_chrono=False\nboost:without_container=False\nboost:without_context=False\nboost:without_contract=False\nboost:without_coroutine=False\nboost:without_date_time=False\nboost:without_exception=False\nboost:without_fiber=False\nboost:without_filesystem=False\nboost:without_graph=False\nboost:without_graph_parallel=True\nboost:without_iostreams=False\nboost:without_json=False\nboost:without_locale=False\nboost:without_log=False\nboost:without_math=False\nboost:without_mpi=True\nboost:without_nowide=False\nboost:without_program_options=False\nboost:without_python=True\nboost:without_random=False\nboost:without_regex=False\nboost:without_serialization=False\nboost:without_stacktrace=False\nboost:without_system=False\nboost:without_test=False\nboost:without_thread=False\nboost:without_timer=False\nboost:without_type_erasure=False\nboost:without_wave=False\nboost:zlib=True\nboost:zstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\ntinyxml2:fPIC=True\ntinyxml2:shared=False\nzlib:fPIC=True\nzlib:shared=False",
|
||||
"package_id": "9d1f076b471417647c2022a78d5e2c1f834289ac",
|
||||
"prev": "0ca9799450422cc55a92ccc6ffd57fba",
|
||||
"requires": [
|
||||
"1"
|
||||
"2",
|
||||
"6"
|
||||
],
|
||||
"path": "conanfile.py",
|
||||
"context": "host"
|
||||
},
|
||||
"1": {
|
||||
"ref": "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
|
||||
"options": "fPIC=True\nheader_only=False\nshared=False\nwith_fmt_alias=False\nwith_os_api=True",
|
||||
"package_id": "2c09c8f84c016041549fcee94e4caae5d89424b6",
|
||||
"prev": "9f5ab13fc7c73e4a9f87e4e213f2cfa4",
|
||||
"2": {
|
||||
"ref": "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
|
||||
"options": "addr2line_location=/usr/bin/addr2line\nasio_no_deprecated=False\nbuildid=None\nbzip2=True\ndebug_level=0\ndiagnostic_definitions=False\nerror_code_header_only=False\nextra_b2_flags=None\nfPIC=True\nfilesystem_no_deprecated=False\nheader_only=False\ni18n_backend=deprecated\ni18n_backend_iconv=libc\ni18n_backend_icu=False\nlayout=system\nlzma=False\nmagic_autolink=False\nmultithreading=True\nnamespace=boost\nnamespace_alias=False\nnuma=True\npch=True\npython_executable=None\npython_version=None\nsegmented_stacks=False\nshared=False\nsystem_no_deprecated=False\nsystem_use_utf8=False\nvisibility=hidden\nwith_stacktrace_backtrace=True\nwithout_atomic=False\nwithout_chrono=False\nwithout_container=False\nwithout_context=False\nwithout_contract=False\nwithout_coroutine=False\nwithout_date_time=False\nwithout_exception=False\nwithout_fiber=False\nwithout_filesystem=False\nwithout_graph=False\nwithout_graph_parallel=True\nwithout_iostreams=False\nwithout_json=False\nwithout_locale=False\nwithout_log=False\nwithout_math=False\nwithout_mpi=True\nwithout_nowide=False\nwithout_program_options=False\nwithout_python=True\nwithout_random=False\nwithout_regex=False\nwithout_serialization=False\nwithout_stacktrace=False\nwithout_system=False\nwithout_test=False\nwithout_thread=False\nwithout_timer=False\nwithout_type_erasure=False\nwithout_wave=False\nzlib=True\nzstd=False\nbzip2:build_executable=True\nbzip2:fPIC=True\nbzip2:shared=False\nlibbacktrace:fPIC=True\nlibbacktrace:shared=False\nzlib:fPIC=True\nzlib:shared=False",
|
||||
"package_id": "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
|
||||
"prev": "b9d7912e6131dfa453c725593b36c808",
|
||||
"requires": [
|
||||
"3",
|
||||
"4",
|
||||
"5"
|
||||
],
|
||||
"context": "host"
|
||||
},
|
||||
"3": {
|
||||
"ref": "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
|
||||
"options": "fPIC=True\nshared=False",
|
||||
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
|
||||
"prev": "7cd359d44f89ab08e33b5db75605002c",
|
||||
"context": "host"
|
||||
},
|
||||
"4": {
|
||||
"ref": "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
|
||||
"options": "build_executable=True\nfPIC=True\nshared=False",
|
||||
"package_id": "c32092bf4d4bb47cf962af898e02823f499b017e",
|
||||
"prev": "b746948bc999d6f17f52a1f76e729e80",
|
||||
"context": "host"
|
||||
},
|
||||
"5": {
|
||||
"ref": "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
|
||||
"options": "fPIC=True\nshared=False",
|
||||
"package_id": "dfbe50feef7f3c6223a476cd5aeadb687084a646",
|
||||
"prev": "98a976f017e894c27e9a158b807ec0c7",
|
||||
"context": "host"
|
||||
},
|
||||
"6": {
|
||||
"ref": "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
|
||||
"options": "fPIC=True\nshared=False",
|
||||
|
||||
|
||||
"context": "host"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package githubactions
|
||||
|
||||
import "github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
|
||||
// NewActionUsageCataloger returns GitHub Actions used within workflows and composite actions.
|
||||
func NewActionUsageCataloger() *generic.Cataloger {
|
||||
return generic.NewCataloger("github-actions-usage-cataloger").
|
||||
WithParserByGlobs(parseWorkflowForActionUsage, "**/.github/workflows/*.yaml", "**/.github/workflows/*.yml").
|
||||
WithParserByGlobs(parseCompositeActionForActionUsage, "**/.github/actions/*/action.yml", "**/.github/actions/*/action.yaml")
|
||||
}
|
||||
|
||||
// NewWorkflowUsageCataloger returns shared workflows used within workflows.
|
||||
func NewWorkflowUsageCataloger() *generic.Cataloger {
|
||||
return generic.NewCataloger("github-action-workflow-usage-cataloger").
|
||||
WithParserByGlobs(parseWorkflowForWorkflowUsage, "**/.github/workflows/*.yaml", "**/.github/workflows/*.yml")
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||
)
|
||||
|
||||
func TestCataloger_Globs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fixture string
|
||||
cataloger *generic.Cataloger
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "obtain all workflow and composite action files",
|
||||
fixture: "test-fixtures/glob",
|
||||
cataloger: NewActionUsageCataloger(),
|
||||
expected: []string{
|
||||
// composite actions
|
||||
".github/actions/bootstrap/action.yaml",
|
||||
".github/actions/unbootstrap/action.yml",
|
||||
// workflows
|
||||
".github/workflows/release.yml",
|
||||
".github/workflows/validations.yaml",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "obtain all workflow files",
|
||||
fixture: "test-fixtures/glob",
|
||||
cataloger: NewWorkflowUsageCataloger(),
|
||||
expected: []string{
|
||||
// workflows
|
||||
".github/workflows/release.yml",
|
||||
".github/workflows/validations.yaml",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
pkgtest.NewCatalogTester().
|
||||
FromDirectory(t, test.fixture).
|
||||
ExpectsResolverContentQueries(test.expected).
|
||||
TestCataloger(t, test.cataloger)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func newPackageFromUsageStatement(use string, location file.Location) *pkg.Package {
|
||||
name, version := parseStepUsageStatement(use)
|
||||
|
||||
if name == "" {
|
||||
log.WithFields("file", location.RealPath, "statement", use).Trace("unable to parse github action usage statement")
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.Contains(name, ".github/workflows/") {
|
||||
return newGithubActionWorkflowPackageUsage(name, version, location)
|
||||
}
|
||||
|
||||
return newGithubActionPackageUsage(name, version, location)
|
||||
}
|
||||
|
||||
func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package {
|
||||
p := &pkg.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
|
||||
PURL: packageURL(name, version),
|
||||
Type: pkg.GithubActionWorkflowPkg,
|
||||
}
|
||||
|
||||
p.SetID()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func newGithubActionPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package {
|
||||
p := &pkg.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
|
||||
PURL: packageURL(name, version),
|
||||
Type: pkg.GithubActionPkg,
|
||||
}
|
||||
|
||||
p.SetID()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseStepUsageStatement(use string) (string, string) {
|
||||
// from octo-org/another-repo/.github/workflows/workflow.yml@v1 get octo-org/another-repo/.github/workflows/workflow.yml and v1
|
||||
// from ./.github/workflows/workflow-2.yml interpret as only the name
|
||||
|
||||
// from actions/cache@v3 get actions/cache and v3
|
||||
|
||||
fields := strings.Split(use, "@")
|
||||
switch len(fields) {
|
||||
case 1:
|
||||
return use, ""
|
||||
case 2:
|
||||
return fields[0], fields[1]
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func packageURL(name, version string) string {
|
||||
var qualifiers packageurl.Qualifiers
|
||||
var subPath string
|
||||
var namespace string
|
||||
|
||||
fields := strings.SplitN(name, "/", 3)
|
||||
switch len(fields) {
|
||||
case 1:
|
||||
return ""
|
||||
case 2:
|
||||
namespace = fields[0]
|
||||
name = fields[1]
|
||||
case 3:
|
||||
namespace = fields[0]
|
||||
name = fields[1]
|
||||
subPath = fields[2]
|
||||
}
|
||||
if namespace == "." {
|
||||
// this is a local composite action, which is unclear how to represent in a PURL without more information
|
||||
return ""
|
||||
}
|
||||
|
||||
// there isn't a github actions PURL but there is a github PURL type for referencing github repos, which is the
|
||||
// next best thing until there is a supported type.
|
||||
return packageurl.NewPackageURL(
|
||||
packageurl.TypeGithub,
|
||||
namespace,
|
||||
name,
|
||||
version,
|
||||
qualifiers,
|
||||
subPath,
|
||||
).ToString()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
var _ generic.Parser = parseCompositeActionForActionUsage
|
||||
|
||||
type compositeActionDef struct {
|
||||
Runs compositeActionRunsDef `yaml:"runs"`
|
||||
}
|
||||
|
||||
type compositeActionRunsDef struct {
|
||||
Steps []stepDef `yaml:"steps"`
|
||||
}
|
||||
|
||||
func parseCompositeActionForActionUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", err)
|
||||
}
|
||||
|
||||
var ca compositeActionDef
|
||||
if err = yaml.Unmarshal(contents, &ca); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", err)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
pkgs := pkg.NewCollection()
|
||||
|
||||
for _, step := range ca.Runs.Steps {
|
||||
if step.Uses == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
p := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||
)
|
||||
|
||||
func Test_parseCompositeActionForActionUsage(t *testing.T) {
|
||||
fixture := "test-fixtures/composite-action.yaml"
|
||||
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "actions/setup-go",
|
||||
Version: "v4",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/setup-go@v4",
|
||||
},
|
||||
{
|
||||
Name: "actions/cache",
|
||||
Version: "v3",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/cache@v3",
|
||||
},
|
||||
}
|
||||
|
||||
var expectedRelationships []artifact.Relationship
|
||||
pkgtest.TestFileParser(t, fixture, parseCompositeActionForActionUsage, expected, expectedRelationships)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
var (
|
||||
_ generic.Parser = parseWorkflowForActionUsage
|
||||
_ generic.Parser = parseWorkflowForWorkflowUsage
|
||||
)
|
||||
|
||||
type workflowDef struct {
|
||||
Jobs map[string]workflowJobDef `yaml:"jobs"`
|
||||
}
|
||||
|
||||
type workflowJobDef struct {
|
||||
Uses string `yaml:"uses"`
|
||||
Steps []stepDef `yaml:"steps"`
|
||||
}
|
||||
|
||||
type stepDef struct {
|
||||
Name string `yaml:"name"`
|
||||
Uses string `yaml:"uses"`
|
||||
With struct {
|
||||
Path string `yaml:"path"`
|
||||
Key string `yaml:"key"`
|
||||
} `yaml:"with"`
|
||||
}
|
||||
|
||||
func parseWorkflowForWorkflowUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||
}
|
||||
|
||||
var wf workflowDef
|
||||
if err = yaml.Unmarshal(contents, &wf); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
pkgs := pkg.NewCollection()
|
||||
|
||||
for _, job := range wf.Jobs {
|
||||
if job.Uses != "" {
|
||||
p := newPackageFromUsageStatement(job.Uses, reader.Location)
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
}
|
||||
|
||||
func parseWorkflowForActionUsage(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", err)
|
||||
}
|
||||
|
||||
var wf workflowDef
|
||||
if err = yaml.Unmarshal(contents, &wf); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", err)
|
||||
}
|
||||
|
||||
// we use a collection to help with deduplication before raising to higher level processing
|
||||
pkgs := pkg.NewCollection()
|
||||
|
||||
for _, job := range wf.Jobs {
|
||||
for _, step := range job.Steps {
|
||||
if step.Uses == "" {
|
||||
continue
|
||||
}
|
||||
p := newPackageFromUsageStatement(step.Uses, reader.Location)
|
||||
if p != nil {
|
||||
pkgs.Add(*p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs.Sorted(), nil, nil
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package githubactions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||
)
|
||||
|
||||
func Test_parseWorkflowForActionUsage(t *testing.T) {
|
||||
fixture := "test-fixtures/workflow-multi-job.yaml"
|
||||
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "./.github/actions/bootstrap",
|
||||
Version: "",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
|
||||
},
|
||||
{
|
||||
Name: "actions/cache",
|
||||
Version: "v3",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/cache@v3",
|
||||
},
|
||||
{
|
||||
Name: "actions/cache/restore",
|
||||
Version: "v3",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/cache@v3#restore",
|
||||
},
|
||||
{
|
||||
Name: "actions/cache/save",
|
||||
Version: "v3",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/cache@v3#save",
|
||||
},
|
||||
{
|
||||
Name: "actions/checkout",
|
||||
Version: "v4",
|
||||
Type: pkg.GithubActionPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/actions/checkout@v4",
|
||||
},
|
||||
}
|
||||
|
||||
var expectedRelationships []artifact.Relationship
|
||||
pkgtest.TestFileParser(t, fixture, parseWorkflowForActionUsage, expected, expectedRelationships)
|
||||
}
|
||||
|
||||
func Test_parseWorkflowForWorkflowUsage(t *testing.T) {
|
||||
fixture := "test-fixtures/call-shared-workflow.yaml"
|
||||
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "octo-org/this-repo/.github/workflows/workflow-1.yml",
|
||||
Version: "172239021f7ba04fe7327647b213799853a9eb89",
|
||||
Type: pkg.GithubActionWorkflowPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml",
|
||||
},
|
||||
{
|
||||
Name: "./.github/workflows/workflow-2.yml",
|
||||
Version: "",
|
||||
Type: pkg.GithubActionWorkflowPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
|
||||
},
|
||||
{
|
||||
Name: "octo-org/another-repo/.github/workflows/workflow.yml",
|
||||
Version: "v1",
|
||||
Type: pkg.GithubActionWorkflowPkg,
|
||||
Locations: fixtureLocationSet,
|
||||
PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml",
|
||||
},
|
||||
}
|
||||
|
||||
var expectedRelationships []artifact.Relationship
|
||||
pkgtest.TestFileParser(t, fixture, parseWorkflowForWorkflowUsage, expected, expectedRelationships)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
jobs:
|
||||
|
||||
call-workflow-1-in-local-repo:
|
||||
uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89
|
||||
|
||||
call-workflow-2-in-local-repo:
|
||||
uses: ./.github/workflows/workflow-2.yml
|
||||
|
||||
call-workflow-in-another-repo:
|
||||
uses: octo-org/another-repo/.github/workflows/workflow.yml@v1
|
||||
|
||||
|
||||
unit-test:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
run: make unit
|
||||
@@ -0,0 +1,81 @@
|
||||
name: "Bootstrap"
|
||||
description: "Bootstrap all tools and dependencies"
|
||||
inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
required: true
|
||||
default: "1.21.x"
|
||||
use-go-cache:
|
||||
description: "Restore go cache"
|
||||
required: true
|
||||
default: "true"
|
||||
cache-key-prefix:
|
||||
description: "Prefix all cache keys with this value"
|
||||
required: true
|
||||
default: "831180ac25"
|
||||
build-cache-key-prefix:
|
||||
description: "Prefix build cache key with this value"
|
||||
required: true
|
||||
default: "f8b6d31dea"
|
||||
bootstrap-apt-packages:
|
||||
description: "Space delimited list of tools to install via apt"
|
||||
default: "libxml2-utils"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
- name: Restore tool cache
|
||||
id: tool-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tmp
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
|
||||
|
||||
# note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
|
||||
# some installations of project tools.
|
||||
- name: Restore go module cache
|
||||
id: go-mod-cache
|
||||
if: inputs.use-go-cache == 'true'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
|
||||
|
||||
- name: (cache-miss) Bootstrap project tools
|
||||
shell: bash
|
||||
if: steps.tool-cache.outputs.cache-hit != 'true'
|
||||
run: make bootstrap-tools
|
||||
|
||||
- name: Restore go build cache
|
||||
id: go-cache
|
||||
if: inputs.use-go-cache == 'true'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
|
||||
|
||||
- name: (cache-miss) Bootstrap go dependencies
|
||||
shell: bash
|
||||
if: steps.go-mod-cache.outputs.cache-hit != 'true' && inputs.use-go-cache == 'true'
|
||||
run: make bootstrap-go
|
||||
|
||||
- name: Install apt packages
|
||||
if: inputs.bootstrap-apt-packages != ''
|
||||
shell: bash
|
||||
run: |
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
|
||||
|
||||
- name: Create all cache fingerprints
|
||||
shell: bash
|
||||
run: make fingerprints
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
# fake
|
||||
+1
@@ -0,0 +1 @@
|
||||
# fake
|
||||
+1
@@ -0,0 +1 @@
|
||||
# fake
|
||||
+1
@@ -0,0 +1 @@
|
||||
# fake
|
||||
@@ -0,0 +1,210 @@
|
||||
name: "Validations"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
|
||||
Static-Analysis:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Run static analysis
|
||||
run: make static-analysis
|
||||
|
||||
|
||||
Unit-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Unit tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore Java test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore RPM test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/rpm/test-fixtures/rpms
|
||||
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/rpm/test-fixtures/rpms.fingerprint' ) }}
|
||||
|
||||
- name: Restore go binary test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
|
||||
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
|
||||
|
||||
- name: Restore binary cataloger test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic
|
||||
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore Kernel test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: syft/pkg/cataloger/kernel/test-fixtures/cache
|
||||
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
|
||||
|
||||
- name: Run unit tests
|
||||
run: make unit
|
||||
|
||||
|
||||
Integration-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Validate syft output against the CycloneDX schema
|
||||
run: make validate-cyclonedx-schema
|
||||
|
||||
- name: Restore integration test cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/integration/test-fixtures/cache
|
||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('test/integration/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Run integration tests
|
||||
run: make integration
|
||||
|
||||
|
||||
Build-Snapshot-Artifacts:
|
||||
name: "Build snapshot artifacts"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
# why have another build cache key? We don't want unit/integration/etc test build caches to replace
|
||||
# the snapshot build cache, which includes builds for all OSs and architectures. As long as this key is
|
||||
# unique from the build-cache-key-prefix in other CI jobs, we should be fine.
|
||||
#
|
||||
# note: ideally this value should match what is used in release (just to help with build times).
|
||||
build-cache-key-prefix: "snapshot"
|
||||
bootstrap-apt-packages: ""
|
||||
|
||||
- name: Build snapshot artifacts
|
||||
run: make snapshot
|
||||
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
|
||||
Acceptance-Linux:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Acceptance tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
- name: Run comparison tests (Linux)
|
||||
run: make compare-linux
|
||||
|
||||
- name: Restore install.sh test image cache
|
||||
id: install-test-image-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/install/cache
|
||||
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
|
||||
|
||||
- name: Load test image cache
|
||||
if: steps.install-test-image-cache.outputs.cache-hit == 'true'
|
||||
run: make install-test-cache-load
|
||||
|
||||
- name: Run install.sh tests (Linux)
|
||||
run: make install-test
|
||||
|
||||
- name: (cache-miss) Create test image cache
|
||||
if: steps.install-test-image-cache.outputs.cache-hit != 'true'
|
||||
run: make install-test-cache-save
|
||||
|
||||
|
||||
Acceptance-Mac:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Acceptance tests (Mac)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
- name: Restore docker image cache for compare testing
|
||||
id: mac-compare-testing-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: image.tar
|
||||
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
|
||||
|
||||
- name: Run comparison tests (Mac)
|
||||
run: make compare-mac
|
||||
|
||||
- name: Run install.sh tests (Mac)
|
||||
run: make install-test-ci-mac
|
||||
|
||||
|
||||
Cli-Linux:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "CLI tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore CLI test-fixture cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
|
||||
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Download snapshot build
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
- name: Run CLI Tests (Linux)
|
||||
run: make cli
|
||||
@@ -1,7 +1,18 @@
|
||||
github.com/CycloneDX/cyclonedx-go v0.6.0/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.0 h1:jNxp8hL7UpcvPDFXjY+Y1ibFtsW+e5zyF9QoSmhK/zg=
|
||||
github.com/CycloneDX/cyclonedx-go v0.7.0/go.mod h1:W5Z9w8pTTL+t+yG3PCiFRGlr8PUlE0pGWzKSJbsyXkg=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.7.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/sanity-io/litter"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -252,6 +253,23 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) {
|
||||
}
|
||||
}
|
||||
|
||||
var relationshipStringer = litter.Options{
|
||||
Compact: true,
|
||||
StripPackageNames: false,
|
||||
HidePrivateFields: true, // we want to ignore package IDs
|
||||
HideZeroValues: true,
|
||||
StrictGo: true,
|
||||
//FieldExclusions: ... // these can be added for future values that need to be ignored
|
||||
//FieldFilter: ...
|
||||
}
|
||||
|
||||
func relationshipLess(x, y artifact.Relationship) bool {
|
||||
// we just need a stable sort, the ordering does not need to be sensible
|
||||
xStr := relationshipStringer.Sdump(x)
|
||||
yStr := relationshipStringer.Sdump(y)
|
||||
return xStr < yStr
|
||||
}
|
||||
|
||||
// nolint:funlen
|
||||
func (p *CatalogTester) assertPkgs(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) {
|
||||
t.Helper()
|
||||
@@ -259,6 +277,7 @@ func (p *CatalogTester) assertPkgs(t *testing.T, pkgs []pkg.Package, relationshi
|
||||
p.compareOptions = append(p.compareOptions,
|
||||
cmpopts.IgnoreFields(pkg.Package{}, "id"), // note: ID is not deterministic for test purposes
|
||||
cmpopts.SortSlices(pkg.Less),
|
||||
cmpopts.SortSlices(relationshipLess),
|
||||
cmp.Comparer(
|
||||
func(x, y file.LocationSet) bool {
|
||||
xs := x.ToSlice()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cataloger
|
||||
|
||||
import (
|
||||
"golang.org/x/exp/slices"
|
||||
"slices"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
|
||||
@@ -11,9 +11,9 @@ type ConanLockMetadata struct {
|
||||
Ref string `json:"ref"`
|
||||
PackageID string `json:"package_id,omitempty"`
|
||||
Prev string `json:"prev,omitempty"`
|
||||
Requires string `json:"requires,omitempty"`
|
||||
BuildRequires string `json:"build_requires,omitempty"`
|
||||
PythonRequires string `json:"py_requires,omitempty"`
|
||||
Requires []string `json:"requires,omitempty"`
|
||||
BuildRequires []string `json:"build_requires,omitempty"`
|
||||
PythonRequires []string `json:"py_requires,omitempty"`
|
||||
Options map[string]string `json:"options,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Context string `json:"context,omitempty"`
|
||||
|
||||
+37
-28
@@ -9,34 +9,36 @@ type Type string
|
||||
|
||||
const (
|
||||
// the full set of supported packages
|
||||
UnknownPkg Type = "UnknownPackage"
|
||||
AlpmPkg Type = "alpm"
|
||||
ApkPkg Type = "apk"
|
||||
BinaryPkg Type = "binary"
|
||||
CocoapodsPkg Type = "pod"
|
||||
ConanPkg Type = "conan"
|
||||
DartPubPkg Type = "dart-pub"
|
||||
DebPkg Type = "deb"
|
||||
DotnetPkg Type = "dotnet"
|
||||
GemPkg Type = "gem"
|
||||
GoModulePkg Type = "go-module"
|
||||
GraalVMNativeImagePkg Type = "graalvm-native-image"
|
||||
HackagePkg Type = "hackage"
|
||||
HexPkg Type = "hex"
|
||||
JavaPkg Type = "java-archive"
|
||||
JenkinsPluginPkg Type = "jenkins-plugin"
|
||||
KbPkg Type = "msrc-kb"
|
||||
LinuxKernelPkg Type = "linux-kernel"
|
||||
LinuxKernelModulePkg Type = "linux-kernel-module"
|
||||
NixPkg Type = "nix"
|
||||
NpmPkg Type = "npm"
|
||||
PhpComposerPkg Type = "php-composer"
|
||||
PortagePkg Type = "portage"
|
||||
PythonPkg Type = "python"
|
||||
Rpkg Type = "R-package"
|
||||
RpmPkg Type = "rpm"
|
||||
RustPkg Type = "rust-crate"
|
||||
SwiftPkg Type = "swift"
|
||||
UnknownPkg Type = "UnknownPackage"
|
||||
AlpmPkg Type = "alpm"
|
||||
ApkPkg Type = "apk"
|
||||
BinaryPkg Type = "binary"
|
||||
CocoapodsPkg Type = "pod"
|
||||
ConanPkg Type = "conan"
|
||||
DartPubPkg Type = "dart-pub"
|
||||
DebPkg Type = "deb"
|
||||
DotnetPkg Type = "dotnet"
|
||||
GemPkg Type = "gem"
|
||||
GithubActionPkg Type = "github-action"
|
||||
GithubActionWorkflowPkg Type = "github-action-workflow"
|
||||
GoModulePkg Type = "go-module"
|
||||
GraalVMNativeImagePkg Type = "graalvm-native-image"
|
||||
HackagePkg Type = "hackage"
|
||||
HexPkg Type = "hex"
|
||||
JavaPkg Type = "java-archive"
|
||||
JenkinsPluginPkg Type = "jenkins-plugin"
|
||||
KbPkg Type = "msrc-kb"
|
||||
LinuxKernelPkg Type = "linux-kernel"
|
||||
LinuxKernelModulePkg Type = "linux-kernel-module"
|
||||
NixPkg Type = "nix"
|
||||
NpmPkg Type = "npm"
|
||||
PhpComposerPkg Type = "php-composer"
|
||||
PortagePkg Type = "portage"
|
||||
PythonPkg Type = "python"
|
||||
Rpkg Type = "R-package"
|
||||
RpmPkg Type = "rpm"
|
||||
RustPkg Type = "rust-crate"
|
||||
SwiftPkg Type = "swift"
|
||||
)
|
||||
|
||||
// AllPkgs represents all supported package types
|
||||
@@ -50,6 +52,8 @@ var AllPkgs = []Type{
|
||||
DebPkg,
|
||||
DotnetPkg,
|
||||
GemPkg,
|
||||
GithubActionPkg,
|
||||
GithubActionWorkflowPkg,
|
||||
GoModulePkg,
|
||||
HackagePkg,
|
||||
HexPkg,
|
||||
@@ -70,6 +74,8 @@ var AllPkgs = []Type{
|
||||
}
|
||||
|
||||
// PackageURLType returns the PURL package type for the current package.
|
||||
//
|
||||
//nolint:funlen
|
||||
func (t Type) PackageURLType() string {
|
||||
switch t {
|
||||
case AlpmPkg:
|
||||
@@ -90,6 +96,9 @@ func (t Type) PackageURLType() string {
|
||||
return packageurl.TypeGem
|
||||
case HexPkg:
|
||||
return packageurl.TypeHex
|
||||
case GithubActionPkg, GithubActionWorkflowPkg:
|
||||
// note: this is not a real purl type, but it is the closest thing we have for now
|
||||
return packageurl.TypeGithub
|
||||
case GoModulePkg:
|
||||
return packageurl.TypeGolang
|
||||
case HackagePkg:
|
||||
|
||||
@@ -114,6 +114,7 @@ func TestTypeFromPURL(t *testing.T) {
|
||||
expectedTypes.Remove(string(PortagePkg))
|
||||
expectedTypes.Remove(string(BinaryPkg))
|
||||
expectedTypes.Remove(string(LinuxKernelModulePkg))
|
||||
expectedTypes.Remove(string(GithubActionPkg), string(GithubActionWorkflowPkg))
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(string(test.expected), func(t *testing.T) {
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
package sbom
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
|
||||
@@ -199,6 +199,8 @@ func parseDefaultImageSource(defaultImageSource string) image.Source {
|
||||
return image.DockerDaemonSource
|
||||
case "podman":
|
||||
return image.PodmanDaemonSource
|
||||
case "containerd":
|
||||
return image.ContainerdDaemonSource
|
||||
default:
|
||||
return image.UnknownSource
|
||||
}
|
||||
|
||||
@@ -247,6 +247,26 @@ func Test_Detect(t *testing.T) {
|
||||
expectedScheme: unknownType,
|
||||
expectedLocation: "",
|
||||
},
|
||||
{
|
||||
name: "podman-image",
|
||||
userInput: "containerd:anchore/syft",
|
||||
detection: detectorResult{
|
||||
src: image.PodmanDaemonSource,
|
||||
ref: "anchore/syft",
|
||||
},
|
||||
expectedScheme: containerImageType,
|
||||
expectedLocation: "anchore/syft",
|
||||
},
|
||||
{
|
||||
name: "containerd-image",
|
||||
userInput: "containerd:anchore/syft",
|
||||
detection: detectorResult{
|
||||
src: image.ContainerdDaemonSource,
|
||||
ref: "anchore/syft",
|
||||
},
|
||||
expectedScheme: containerImageType,
|
||||
expectedLocation: "anchore/syft",
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
@@ -6,6 +6,12 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
// this is the number of packages that should be found in the image-pkg-coverage fixture image
|
||||
// when analyzed with the squashed scope.
|
||||
coverageImageSquashedPackageCount = 24
|
||||
)
|
||||
|
||||
func TestPackagesCmdFlags(t *testing.T) {
|
||||
hiddenPackagesImage := "docker-archive:" + getFixtureImage(t, "image-hidden-packages")
|
||||
coverageImage := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")
|
||||
@@ -114,7 +120,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
name: "squashed-scope-flag",
|
||||
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
|
||||
assertions: []traitAssertion{
|
||||
assertPackageCount(24),
|
||||
assertPackageCount(coverageImageSquashedPackageCount),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -231,7 +237,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
// the application config in the log matches that of what we expect to have been configured.
|
||||
assertInOutput("parallelism: 2"),
|
||||
assertInOutput("parallelism=2"),
|
||||
assertPackageCount(24),
|
||||
assertPackageCount(coverageImageSquashedPackageCount),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -242,7 +248,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
// the application config in the log matches that of what we expect to have been configured.
|
||||
assertInOutput("parallelism: 1"),
|
||||
assertInOutput("parallelism=1"),
|
||||
assertPackageCount(24),
|
||||
assertPackageCount(coverageImageSquashedPackageCount),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
@@ -256,7 +262,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
||||
assertions: []traitAssertion{
|
||||
assertNotInOutput("secret_password"),
|
||||
assertNotInOutput("secret_key_path"),
|
||||
assertPackageCount(24),
|
||||
assertPackageCount(coverageImageSquashedPackageCount),
|
||||
assertSuccessfulReturnCode,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM debian:sid
|
||||
FROM debian:sid@sha256:bee393b48f83fdeb978ce68abb9dc955d6398b984fca88b52a09dceb45ac74b5
|
||||
ADD sources.list /etc/apt/sources.list.d/sources.list
|
||||
RUN apt update -y && apt install -y dpkg-dev
|
||||
# this as a "macho-invalid" directory which is useful for testing
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM centos:7.9.2009
|
||||
FROM centos:7.9.2009@sha256:dead07b4d8ed7e29e98de0f4504d87e8880d4347859d839686a31da35a3b532f
|
||||
# all-layers scope should pickup on vsftpd
|
||||
RUN yum install -y vsftpd
|
||||
RUN yum remove -y vsftpd
|
||||
RUN yum remove -y vsftpd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM openjdk:11
|
||||
FROM openjdk:11@sha256:e81b7f317654b0f26d3993e014b04bcb29250339b11b9de41e130feecd4cd43c
|
||||
|
||||
RUN wget --no-verbose https://github.com/spdx/tools-java/releases/download/v1.1.3/tools-java-1.1.3.zip && \
|
||||
unzip tools-java-1.1.3.zip && \
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM node:19-alpine3.15
|
||||
FROM node:19-alpine3.15@sha256:07050181369f52460e788738272bcb22b71c7cfc6fafee0b5cd27d2022513a86
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM alpine:latest
|
||||
FROM alpine@sha256:c5c5fda71656f28e49ac9c5416b3643eaa6a108a8093151d6d1afc9463be8e33
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
FROM alpine:3.6
|
||||
RUN apk update && apk add python3 wget unzip make ca-certificates
|
||||
FROM alpine:3.6@sha256:66790a2b79e1ea3e1dabac43990c54aca5d1ddf268d9a5a0285e4167c8b24475
|
||||
RUN apk update && apk add python3 wget unzip make ca-certificates
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
FROM ubuntu:20.04
|
||||
RUN apt update -y && apt install make python3 curl unzip -y
|
||||
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
|
||||
RUN apt update -y && apt install make python3 curl unzip -y
|
||||
|
||||
@@ -368,6 +368,20 @@ var dirOnlyTestCases = []testCase{
|
||||
"swift-numerics": "1.0.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find github action packages (from usage in workflow files and composite actions)",
|
||||
pkgType: pkg.GithubActionPkg,
|
||||
pkgInfo: map[string]string{
|
||||
"actions/checkout": "v4",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find github shared workflow calls (from usage in workflow files)",
|
||||
pkgType: pkg.GithubActionWorkflowPkg,
|
||||
pkgInfo: map[string]string{
|
||||
"octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var commonTestCases = []testCase{
|
||||
|
||||
@@ -96,6 +96,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
definedPkgs.Remove(string(pkg.SwiftPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
||||
|
||||
var cases []testCase
|
||||
cases = append(cases, commonTestCases...)
|
||||
|
||||
@@ -76,9 +76,9 @@ var expectedPURLs = map[string]string{
|
||||
"commons-jexl@1.1-hudson-20090508": "pkg:maven/org.jvnet.hudson/commons-jexl@1.1-hudson-20090508",
|
||||
"commons-lang@2.4": "pkg:maven/commons-lang/commons-lang@2.4",
|
||||
"commons-lang@2.5": "pkg:maven/commons-lang/commons-lang@2.5",
|
||||
"commons-logging@1.0.4": "pkg:maven/org.apache.commons.logging/commons-logging@1.0.4",
|
||||
"commons-logging@1.1": "pkg:maven/org.apache.commons.logging/commons-logging@1.1",
|
||||
"commons-logging@1.1.1": "pkg:maven/commons-logging/commons-logging@1.1.1",
|
||||
"commons-logging@1.0.4": "pkg:maven/commons-logging/commons-logging@1.0.4", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.0.4
|
||||
"commons-logging@1.1": "pkg:maven/commons-logging/commons-logging@1.1", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1
|
||||
"commons-logging@1.1.1": "pkg:maven/commons-logging/commons-logging@1.1.1", // see https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1.1
|
||||
"commons-pool@1.3": "pkg:maven/commons-pool/commons-pool@1.3",
|
||||
"crypto-util@1.0": "pkg:maven/org.jvnet.hudson/crypto-util@1.0",
|
||||
"cvs@1.2": "pkg:maven/org.jvnet.hudson.plugins/cvs@1.2",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
FROM busybox:1.31.1
|
||||
FROM busybox:1.31.1@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:latest as builder
|
||||
FROM golang:1.21.1@sha256:cffaba795c36f07e372c7191b35ceaae114d74c31c3763d442982e3a4df3b39e as builder
|
||||
WORKDIR /app
|
||||
COPY go.sum go.mod app.go ./
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM jenkins/jenkins:2.346.3-slim-jdk17
|
||||
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:latest
|
||||
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
|
||||
|
||||
RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user