mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
feat(report): add image reference to report metadata (#9729)
This commit is contained in:
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -249,7 +250,7 @@ func TestRegistry(t *testing.T) {
|
||||
runTest(t, osArgs, tt.golden, types.FormatJSON, runOptions{
|
||||
wantErr: tt.wantErr,
|
||||
fakeUUID: "3ff14136-e09f-4df9-80ea-%012d",
|
||||
override: overrideFuncs(overrideUID, func(_ *testing.T, want, got *types.Report) {
|
||||
override: overrideFuncs(overrideUID, func(t *testing.T, want, got *types.Report) {
|
||||
// Exclude ArtifactID from comparison because registry tests use random ports
|
||||
// (e.g., localhost:54321/alpine:3.10), which causes RepoTags and the calculated
|
||||
// Artifact ID to vary on each test run.
|
||||
@@ -258,6 +259,7 @@ func TestRegistry(t *testing.T) {
|
||||
|
||||
want.ArtifactName = s
|
||||
want.Metadata.RepoTags = []string{s}
|
||||
want.Metadata.Reference = testutil.MustParseReference(t, s)
|
||||
for i := range want.Results {
|
||||
want.Results[i].Target = fmt.Sprintf("%s (%s)", s, tt.os)
|
||||
}
|
||||
|
||||
1
integration/testdata/almalinux-8.json.golden
vendored
1
integration/testdata/almalinux-8.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:almalinux-8"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:almalinux-8",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "a467f67a48d469e1975b7414f33f2cf87121d4cc59d2ee029ea58e6b81774769",
|
||||
|
||||
1
integration/testdata/alpine-310.json.golden
vendored
1
integration/testdata/alpine-310.json.golden
vendored
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-310"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-310",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "0a80155a31551fcc1a36fccbbda79fcd3f0b1c7d270653d00310e6e2217c57e6",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-39"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-39",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-39"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-39",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-39"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-39",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f",
|
||||
|
||||
1
integration/testdata/alpine-39.json.golden
vendored
1
integration/testdata/alpine-39.json.golden
vendored
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-39"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-39",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:alpine-distroless"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:alpine-distroless",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "github.com/chainguard-dev/apko",
|
||||
|
||||
1
integration/testdata/amazon-1.json.golden
vendored
1
integration/testdata/amazon-1.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:amazon-1"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:amazon-1",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "ef1b126795001e9b4bdc14a01180e4d8146282d279f53e05adfaa8195ecda20e",
|
||||
|
||||
1
integration/testdata/amazon-2.json.golden
vendored
1
integration/testdata/amazon-2.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:amazon-2"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:amazon-2",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "e020a5508b9f809b29659128692cd634e3d4fba3f2c13d2029d797317b5c3a56",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:busybox-with-lockfile"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:busybox-with-lockfile",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2022-06-07T04:24:40.230164Z",
|
||||
|
||||
1
integration/testdata/centos-6.json.golden
vendored
1
integration/testdata/centos-6.json.golden
vendored
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:centos-6"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:centos-6",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "https://github.com/CentOS/sig-cloud-instance-images",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:centos-7",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "cc6043a787f6d1c7ae3e121ebdf1c4478186336aa7274871780a0a7bcc3a061a",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:centos-7",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "cc6043a787f6d1c7ae3e121ebdf1c4478186336aa7274871780a0a7bcc3a061a",
|
||||
|
||||
1
integration/testdata/centos-7.json.golden
vendored
1
integration/testdata/centos-7.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:centos-7",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "cc6043a787f6d1c7ae3e121ebdf1c4478186336aa7274871780a0a7bcc3a061a",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:debian-buster"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:debian-buster",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "cbb6a20ddb7dedfeee41aeb21e9780f14afbb0f47a6b1ffa514a1822f45d0a51",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:debian-buster"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:debian-buster",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "cbb6a20ddb7dedfeee41aeb21e9780f14afbb0f47a6b1ffa514a1822f45d0a51",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:debian-stretch"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:debian-stretch",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "957bc0b73d29f0e1030fec9c63f81d3e81baa610cffcc9c574b14fee6d1821ae",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:distroless-base"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:distroless-base",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "Bazel",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:distroless-python27"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:distroless-python27",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "Bazel",
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2N5Y2xvbmVkeC5vcmcvYm9tIiwic3ViamVjdCI6W3sibmFtZSI6ImluZGV4LmRvY2tlci5pby9saWJyYXJ5L2NlbnRvcyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJiZTY1ZjQ4OGI3NzY0YWQzNjM4ZjIzNmI3YjUxNWIzNjc4MzY5YTUxMjRjNDdiOGQzMjkxNmQ2NDg3NDE4ZWE0In19XSwicHJlZGljYXRlIjp7ImJvbUZvcm1hdCI6IkN5Y2xvbmVEWCIsInNwZWNWZXJzaW9uIjoiMS40Iiwic2VyaWFsTnVtYmVyIjoidXJuOnV1aWQ6MTQ1NWMwMmQtNjRjYS00NTNlLWE1ZGYtZGRmYjcwYTdjODA0IiwidmVyc2lvbiI6MSwibWV0YWRhdGEiOnsidGltZXN0YW1wIjoiMjAyMi0wNi0xNFQxNTowODo0OCswMDowMCIsInRvb2xzIjpbeyJ2ZW5kb3IiOiJhcXVhc2VjdXJpdHkiLCJuYW1lIjoidHJpdnkiLCJ2ZXJzaW9uIjoiZGV2In1dLCJjb21wb25lbnQiOnsiYm9tLXJlZiI6ImQwZDQxZTMwLTk2NTAtNDg5ZC05NDhkLTQyNWZmMmVkNjNkMiIsInR5cGUiOiJjb250YWluZXIiLCJuYW1lIjoiaW50ZWdyYXRpb24vdGVzdGRhdGEvZml4dHVyZXMvaW1hZ2VzL2NlbnRvcy03LnRhci5neiIsInByb3BlcnRpZXMiOlt7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U2NoZW1hVmVyc2lvbiIsInZhbHVlIjoiMiJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpJbWFnZUlEIiwidmFsdWUiOiJzaGEyNTY6ZjFjYjdjN2Q1OGI3M2VhYzg1OWMzOTU4ODJlZWM0OWQ1MDY1MTI0NGUzNDJjZDZjNjhhNWM3ODA5Nzg1ZjQyNyJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpEaWZmSUQiLCJ2YWx1ZSI6InNoYTI1Njo4OTE2OWQ4N2RiZTJiNzJiYTQyYmZiYjM1NzljOTU3MzIyYmFjYTI4ZTAzYTFlNTU4MDc2NTQyYTFjMWIyYjRhIn0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlJlcG9UYWciLCJ2YWx1ZSI6ImdoY3IuaW8vYXF1YXNlY3VyaXR5L3RyaXZ5LXRlc3QtaW1hZ2VzOmNlbnRvcy03In1dfX0sImNvbXBvbmVudHMiOlt7ImJvbS1yZWYiOiJwa2c6cnBtL2NlbnRvcy9iYXNoQDQuMi40Ni0zMS5lbDc/YXJjaD14ODZfNjQmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCIsInR5cGUiOiJsaWJyYXJ5IiwibmFtZSI6ImJhc2giLCJ2ZXJzaW9uIjoiNC4yLjQ2LTMxLmVsNyIsImxpY2Vuc2VzIjpbeyJleHByZXNzaW9uIjoiR1BMdjMrIn1dLCJwdXJsIjoicGtnOnJwbS9jZW50b3MvYmFzaEA0LjIuNDYtMzEuZWw3P2FyY2g9eDg2XzY0JmRpc3Rybz1jZW50b3MtNy42LjE4MTAiLCJwcm9wZXJ0aWVzIjpbeyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlBrZ0lEIiwidmFsdWUiOiJiYXNoQDQuMi40Ni0zMS5lbDcueDg2XzY0In0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlNyY05hbWUiLCJ2YWx1ZSI6ImJhc2gifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U3JjVmVyc2lvbiIsInZhbHVlIjoiNC4yLjQ2In0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlNyY1JlbGVhc2UiLCJ2YWx1ZSI6IjMxLmVsNyJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpMYXllckRpZ2VzdCIsInZhbHVlIjoic2hhMjU2OmFjOTIwODIwN2FkYWFjM2E0OGU1NGE0ZGM2YjQ5YzY5ZTc4YzMwNzJkMmIzYWRkN2VmZGFiZjgxNGRiMjEzM2IifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6TGF5ZXJEaWZmSUQiLCJ2YWx1ZSI6InNoYTI1Njo4OTE2OWQ4N2RiZTJiNzJiYTQyYmZiYjM1NzljOTU3MzIyYmFjYTI4ZTAzYTFlNTU4MDc2NTQyYTFjMWIyYjRhIn1dfSx7ImJvbS1yZWYiOiJwa2c6cnBtL2NlbnRvcy9vcGVuc3NsLWxpYnNAMS4wLjJrLTE2LmVsNz9hcmNoPXg4Nl82NCZlcG9jaD0xJmRpc3Rybz1jZW50b3MtNy42LjE4MTAiLCJ0eXBlIjoibGlicmFyeSIsIm5hbWUiOiJvcGVuc3NsLWxpYnMiLCJ2ZXJzaW9uIjoiMS4wLjJrLTE2LmVsNyIsImxpY2Vuc2VzIjpbeyJleHByZXNzaW9uIjoiT3BlblNTTCJ9XSwicHVybCI6InBrZzpycG0vY2VudG9zL29wZW5zc2wtbGlic0AxLjAuMmstMTYuZWw3P2FyY2g9eDg2XzY0JmVwb2NoPTEmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCIsInByb3BlcnRpZXMiOlt7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6UGtnSUQiLCJ2YWx1ZSI6Im9wZW5zc2wtbGlic0AxLjAuMmstMTYuZWw3Lng4Nl82NCJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpTcmNOYW1lIiwidmFsdWUiOiJvcGVuc3NsIn0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlNyY1ZlcnNpb24iLCJ2YWx1ZSI6IjEuMC4yayJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpTcmNSZWxlYXNlIiwidmFsdWUiOiIxNi5lbDcifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U3JjRXBvY2giLCJ2YWx1ZSI6IjEifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6TGF5ZXJEaWdlc3QiLCJ2YWx1ZSI6InNoYTI1NjphYzkyMDgyMDdhZGFhYzNhNDhlNTRhNGRjNmI0OWM2OWU3OGMzMDcyZDJiM2FkZDdlZmRhYmY4MTRkYjIxMzNiIn0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OkxheWVyRGlmZklEIiwidmFsdWUiOiJzaGEyNTY6ODkxNjlkODdkYmUyYjcyYmE0MmJmYmIzNTc5Yzk1NzMyMmJhY2EyOGUwM2ExZTU1ODA3NjU0MmExYzFiMmI0YSJ9XX0seyJib20tcmVmIjoiMDE3NWY3MzItZGY5ZC00YmI4LTlmNTYtODcwODk4ZTNmZjg5IiwidHlwZSI6Im9wZXJhdGluZy1zeXN0ZW0iLCJuYW1lIjoiY2VudG9zIiwidmVyc2lvbiI6IjcuNi4xODEwIiwicHJvcGVydGllcyI6W3sibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpUeXBlIiwidmFsdWUiOiJjZW50b3MifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6Q2xhc3MiLCJ2YWx1ZSI6Im9zLXBrZ3MifV19XSwiZGVwZW5kZW5jaWVzIjpbeyJyZWYiOiIwMTc1ZjczMi1kZjlkLTRiYjgtOWY1Ni04NzA4OThlM2ZmODkiLCJkZXBlbmRzT24iOlsicGtnOnJwbS9jZW50b3MvYmFzaEA0LjIuNDYtMzEuZWw3P2FyY2g9eDg2XzY0JmRpc3Rybz1jZW50b3MtNy42LjE4MTAiLCJwa2c6cnBtL2NlbnRvcy9vcGVuc3NsLWxpYnNAMS4wLjJrLTE2LmVsNz9hcmNoPXg4Nl82NCZlcG9jaD0xJmRpc3Rybz1jZW50b3MtNy42LjE4MTAiXX0seyJyZWYiOiJkMGQ0MWUzMC05NjUwLTQ4OWQtOTQ4ZC00MjVmZjJlZDYzZDIiLCJkZXBlbmRzT24iOlsiMDE3NWY3MzItZGY5ZC00YmI4LTlmNTYtODcwODk4ZTNmZjg5Il19XX19Cg==","signatures":[{"keyid":"","sig":"MEUCIQCtj78dipe+yzdlIsmwjn9QeaBTAPQacwIJAWfnrtp7FwIgcViOUgPA0WFYjimrIl7vbygdSpduM+ZzY3cqrDciH1U="}]}
|
||||
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2N5Y2xvbmVkeC5vcmcvYm9tIiwic3ViamVjdCI6W3sibmFtZSI6ImluZGV4LmRvY2tlci5pby9saWJyYXJ5L2NlbnRvcyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJiZTY1ZjQ4OGI3NzY0YWQzNjM4ZjIzNmI3YjUxNWIzNjc4MzY5YTUxMjRjNDdiOGQzMjkxNmQ2NDg3NDE4ZWE0In19XSwicHJlZGljYXRlIjp7ImJvbUZvcm1hdCI6IkN5Y2xvbmVEWCIsInNwZWNWZXJzaW9uIjoiMS40Iiwic2VyaWFsTnVtYmVyIjoidXJuOnV1aWQ6MTQ1NWMwMmQtNjRjYS00NTNlLWE1ZGYtZGRmYjcwYTdjODA0IiwidmVyc2lvbiI6MSwibWV0YWRhdGEiOnsidGltZXN0YW1wIjoiMjAyMi0wNi0xNFQxNTowODo0OCswMDowMCIsInRvb2xzIjpbeyJ2ZW5kb3IiOiJhcXVhc2VjdXJpdHkiLCJuYW1lIjoidHJpdnkiLCJ2ZXJzaW9uIjoiZGV2In1dLCJjb21wb25lbnQiOnsiYm9tLXJlZiI6ImQwZDQxZTMwLTk2NTAtNDg5ZC05NDhkLTQyNWZmMmVkNjNkMiIsInR5cGUiOiJjb250YWluZXIiLCJuYW1lIjoiaW50ZWdyYXRpb24vdGVzdGRhdGEvZml4dHVyZXMvaW1hZ2VzL2NlbnRvcy03LnRhci5neiIsInByb3BlcnRpZXMiOlt7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U2NoZW1hVmVyc2lvbiIsInZhbHVlIjoiMiJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpJbWFnZUlEIiwidmFsdWUiOiJzaGEyNTY6ZjFjYjdjN2Q1OGI3M2VhYzg1OWMzOTU4ODJlZWM0OWQ1MDY1MTI0NGUzNDJjZDZjNjhhNWM3ODA5Nzg1ZjQyNyJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpEaWZmSUQiLCJ2YWx1ZSI6InNoYTI1Njo4OTE2OWQ4N2RiZTJiNzJiYTQyYmZiYjM1NzljOTU3MzIyYmFjYTI4ZTAzYTFlNTU4MDc2NTQyYTFjMWIyYjRhIn0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlJlcG9UYWciLCJ2YWx1ZSI6ImdoY3IuaW8vYXF1YXNlY3VyaXR5L3RyaXZ5LXRlc3QtaW1hZ2VzOmNlbnRvcy03In0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlJlZmVyZW5jZSIsInZhbHVlIjoiZ2hjci5pby9hcXVhc2VjdXJpdHkvdHJpdnktdGVzdC1pbWFnZXM6Y2VudG9zLTcifV19fSwiY29tcG9uZW50cyI6W3siYm9tLXJlZiI6InBrZzpycG0vY2VudG9zL2Jhc2hANC4yLjQ2LTMxLmVsNz9hcmNoPXg4Nl82NCZkaXN0cm89Y2VudG9zLTcuNi4xODEwIiwidHlwZSI6ImxpYnJhcnkiLCJuYW1lIjoiYmFzaCIsInZlcnNpb24iOiI0LjIuNDYtMzEuZWw3IiwibGljZW5zZXMiOlt7ImV4cHJlc3Npb24iOiJHUEx2MysifV0sInB1cmwiOiJwa2c6cnBtL2NlbnRvcy9iYXNoQDQuMi40Ni0zMS5lbDc/YXJjaD14ODZfNjQmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCIsInByb3BlcnRpZXMiOlt7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6UGtnSUQiLCJ2YWx1ZSI6ImJhc2hANC4yLjQ2LTMxLmVsNy54ODZfNjQifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U3JjTmFtZSIsInZhbHVlIjoiYmFzaCJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpTcmNWZXJzaW9uIiwidmFsdWUiOiI0LjIuNDYifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U3JjUmVsZWFzZSIsInZhbHVlIjoiMzEuZWw3In0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OkxheWVyRGlnZXN0IiwidmFsdWUiOiJzaGEyNTY6YWM5MjA4MjA3YWRhYWMzYTQ4ZTU0YTRkYzZiNDljNjllNzhjMzA3MmQyYjNhZGQ3ZWZkYWJmODE0ZGIyMTMzYiJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpMYXllckRpZmZJRCIsInZhbHVlIjoic2hhMjU2Ojg5MTY5ZDg3ZGJlMmI3MmJhNDJiZmJiMzU3OWM5NTczMjJiYWNhMjhlMDNhMWU1NTgwNzY1NDJhMWMxYjJiNGEifV19LHsiYm9tLXJlZiI6InBrZzpycG0vY2VudG9zL29wZW5zc2wtbGlic0AxLjAuMmstMTYuZWw3P2FyY2g9eDg2XzY0JmVwb2NoPTEmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCIsInR5cGUiOiJsaWJyYXJ5IiwibmFtZSI6Im9wZW5zc2wtbGlicyIsInZlcnNpb24iOiIxLjAuMmstMTYuZWw3IiwibGljZW5zZXMiOlt7ImV4cHJlc3Npb24iOiJPcGVuU1NMIn1dLCJwdXJsIjoicGtnOnJwbS9jZW50b3Mvb3BlbnNzbC1saWJzQDEuMC4yay0xNi5lbDc/YXJjaD14ODZfNjQmZXBvY2g9MSZkaXN0cm89Y2VudG9zLTcuNi4xODEwIiwicHJvcGVydGllcyI6W3sibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpQa2dJRCIsInZhbHVlIjoib3BlbnNzbC1saWJzQDEuMC4yay0xNi5lbDcueDg2XzY0In0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlNyY05hbWUiLCJ2YWx1ZSI6Im9wZW5zc2wifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6U3JjVmVyc2lvbiIsInZhbHVlIjoiMS4wLjJrIn0seyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlNyY1JlbGVhc2UiLCJ2YWx1ZSI6IjE2LmVsNyJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpTcmNFcG9jaCIsInZhbHVlIjoiMSJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpMYXllckRpZ2VzdCIsInZhbHVlIjoic2hhMjU2OmFjOTIwODIwN2FkYWFjM2E0OGU1NGE0ZGM2YjQ5YzY5ZTc4YzMwNzJkMmIzYWRkN2VmZGFiZjgxNGRiMjEzM2IifSx7Im5hbWUiOiJhcXVhc2VjdXJpdHk6dHJpdnk6TGF5ZXJEaWZmSUQiLCJ2YWx1ZSI6InNoYTI1Njo4OTE2OWQ4N2RiZTJiNzJiYTQyYmZiYjM1NzljOTU3MzIyYmFjYTI4ZTAzYTFlNTU4MDc2NTQyYTFjMWIyYjRhIn1dfSx7ImJvbS1yZWYiOiIwMTc1ZjczMi1kZjlkLTRiYjgtOWY1Ni04NzA4OThlM2ZmODkiLCJ0eXBlIjoib3BlcmF0aW5nLXN5c3RlbSIsIm5hbWUiOiJjZW50b3MiLCJ2ZXJzaW9uIjoiNy42LjE4MTAiLCJwcm9wZXJ0aWVzIjpbeyJuYW1lIjoiYXF1YXNlY3VyaXR5OnRyaXZ5OlR5cGUiLCJ2YWx1ZSI6ImNlbnRvcyJ9LHsibmFtZSI6ImFxdWFzZWN1cml0eTp0cml2eTpDbGFzcyIsInZhbHVlIjoib3MtcGtncyJ9XX1dLCJkZXBlbmRlbmNpZXMiOlt7InJlZiI6IjAxNzVmNzMyLWRmOWQtNGJiOC05ZjU2LTg3MDg5OGUzZmY4OSIsImRlcGVuZHNPbiI6WyJwa2c6cnBtL2NlbnRvcy9iYXNoQDQuMi40Ni0zMS5lbDc/YXJjaD14ODZfNjQmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCIsInBrZzpycG0vY2VudG9zL29wZW5zc2wtbGlic0AxLjAuMmstMTYuZWw3P2FyY2g9eDg2XzY0JmVwb2NoPTEmZGlzdHJvPWNlbnRvcy03LjYuMTgxMCJdfSx7InJlZiI6ImQwZDQxZTMwLTk2NTAtNDg5ZC05NDhkLTQyNWZmMmVkNjNkMiIsImRlcGVuZHNPbiI6WyIwMTc1ZjczMi1kZjlkLTRiYjgtOWY1Ni04NzA4OThlM2ZmODkiXX1dfX0K","signatures":[{"keyid":"","sig":"MEUCIQCtj78dipe+yzdlIsmwjn9QeaBTAPQacwIJAWfnrtp7FwIgcViOUgPA0WFYjimrIl7vbygdSpduM+ZzY3cqrDciH1U="}]}
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
{
|
||||
"name": "aquasecurity:trivy:RepoTag",
|
||||
"value": "ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
},
|
||||
{
|
||||
"name": "aquasecurity:trivy:Reference",
|
||||
"value": "ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
"SchemaVersion: 2",
|
||||
"ImageID: sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427",
|
||||
"DiffID: sha256:89169d87dbe2b72ba42bfbb3579c957322baca28e03a1e558076542a1c1b2b4a",
|
||||
"RepoTag: ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
"RepoTag: ghcr.io/aquasecurity/trivy-test-images:centos-7",
|
||||
"Reference: ghcr.io/aquasecurity/trivy-test-images:centos-7"
|
||||
],
|
||||
"filesAnalyzed": false,
|
||||
"name": "integration/testdata/fixtures/images/centos-7.tar.gz"
|
||||
|
||||
@@ -16,6 +16,7 @@ PackageAttributionText: SchemaVersion: 2
|
||||
PackageAttributionText: ImageID: sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427
|
||||
PackageAttributionText: DiffID: sha256:89169d87dbe2b72ba42bfbb3579c957322baca28e03a1e558076542a1c1b2b4a
|
||||
PackageAttributionText: RepoTag: ghcr.io/aquasecurity/trivy-test-images:centos-7
|
||||
PackageAttributionText: Reference: ghcr.io/aquasecurity/trivy-test-images:centos-7
|
||||
|
||||
##### Package: centos
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:fluentd-multiple-lockfiles"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:fluentd-multiple-lockfiles",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "232f3fc7ddffd71dc3ff52c6c0c3a5feea2f51acffd9b53850a8fc6f1a15319a",
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
"name": "aquasecurity:trivy:ImageID",
|
||||
"value": "sha256:5a992077baba51b97f27591a10d54d2f2723dc9c81a3fe419e261023f2554933"
|
||||
},
|
||||
{
|
||||
"name": "aquasecurity:trivy:Reference",
|
||||
"value": "ghcr.io/aquasecurity/trivy-test-images:fluentd-multiple-lockfiles"
|
||||
},
|
||||
{
|
||||
"name": "aquasecurity:trivy:RepoTag",
|
||||
"value": "ghcr.io/aquasecurity/trivy-test-images:fluentd-multiple-lockfiles"
|
||||
|
||||
1
integration/testdata/mariner-1.0.json.golden
vendored
1
integration/testdata/mariner-1.0.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:mariner-1.0"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:mariner-1.0",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2022-01-27T01:19:38.526301656Z",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:opensuse-leap-151"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:opensuse-leap-151",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "Fabian Vogt \u003cfvogt@suse.com\u003e",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:opensuse-tumbleweed"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:opensuse-tumbleweed",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "Fabian Vogt \u003cfvogt@suse.com\u003e",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:oraclelinux-8"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:oraclelinux-8",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "Oracle Linux Product Team \u003col-ovm-info_ww@oracle.com\u003e",
|
||||
|
||||
1
integration/testdata/photon-30.json.golden
vendored
1
integration/testdata/photon-30.json.golden
vendored
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:photon-30"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:photon-30",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "ed27e7f1fbd8ef9d3ea89947f682907e9a65a8e51bbe2e0eba60db6e69213848",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:rockylinux-8"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:rockylinux-8",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "16458df10693f731fae0492f791a5e4b725245c35cf28c7fca00982219d7bdf3",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:sle-micro-rancher-5.4_ndb"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:sle-micro-rancher-5.4_ndb",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"author": "SUSE LLC (https://www.suse.com/)",
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:spring4shell-jre11"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:spring4shell-jre11",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2022-06-07T03:41:13.228952Z",
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:spring4shell-jre8"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:spring4shell-jre8",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2022-06-06T13:51:57.120019Z",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:ubi-7"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:ubi-7",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2019-09-02T12:56:43.939095Z",
|
||||
|
||||
1
integration/testdata/ubi-7.json.golden
vendored
1
integration/testdata/ubi-7.json.golden
vendored
@@ -19,6 +19,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:ubi-7"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:ubi-7",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"created": "2019-09-02T12:56:43.939095Z",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "41b694b9b42f9c5ef7fb40c24272927a727a6d6cb8120bb3eae5849ceb9bee77",
|
||||
|
||||
1
integration/testdata/ubuntu-1804.json.golden
vendored
1
integration/testdata/ubuntu-1804.json.golden
vendored
@@ -21,6 +21,7 @@
|
||||
"RepoTags": [
|
||||
"ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804"
|
||||
],
|
||||
"Reference": "ghcr.io/aquasecurity/trivy-test-images:ubuntu-1804",
|
||||
"ImageConfig": {
|
||||
"architecture": "amd64",
|
||||
"container": "41b694b9b42f9c5ef7fb40c24272927a727a6d6cb8120bb3eae5849ceb9bee77",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -72,9 +72,9 @@ func imageName(img, subpath, tag, digest string) string {
|
||||
}
|
||||
|
||||
// MustParseReference parses a string into a Reference and fails the test if there's an error
|
||||
func MustParseReference(t *testing.T, s string) image.Reference {
|
||||
func MustParseReference(t *testing.T, s string) name.Reference {
|
||||
t.Helper()
|
||||
ref, err := image.ParseReference(s)
|
||||
ref, err := name.ParseReference(s)
|
||||
require.NoError(t, err)
|
||||
return ref
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/google/go-containerregistry/pkg/v1"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
"github.com/aquasecurity/trivy/pkg/misconf"
|
||||
@@ -104,7 +104,7 @@ type ImageMetadata struct {
|
||||
DiffIDs []string // uncompressed layer IDs
|
||||
RepoTags []string
|
||||
RepoDigests []string
|
||||
Reference image.Reference // image reference matching the artifact name
|
||||
Reference name.Reference // image reference matching the artifact name
|
||||
ConfigFile v1.ConfigFile
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -13,7 +12,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -24,6 +22,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/handler"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
@@ -173,48 +172,33 @@ func (a Artifact) Clean(_ artifact.Reference) error {
|
||||
}
|
||||
|
||||
// findMatchingReference finds a RepoTag or RepoDigest that matches the artifact name
|
||||
func (a Artifact) findMatchingReference(artifactName string, repoTags, repoDigests []string) image.Reference {
|
||||
func (a Artifact) findMatchingReference(artifactName string, repoTags, repoDigests []string) name.Reference {
|
||||
// Convert strings to typed references
|
||||
parsedTags := a.parseRepoTags(repoTags)
|
||||
parsedDigests := a.parseRepoDigests(repoDigests)
|
||||
|
||||
ref := a.findMatchingRepoReference(artifactName, parsedTags, parsedDigests)
|
||||
return image.NewReference(ref)
|
||||
references := a.parseImageReferences(slices.Concat(repoTags, repoDigests))
|
||||
return a.findMatchingRepoReference(artifactName, references)
|
||||
}
|
||||
|
||||
// parseRepoTags parses repo tags into name.Tag
|
||||
func (a Artifact) parseRepoTags(repoTags []string) []name.Tag {
|
||||
return lo.FilterMap(repoTags, func(tagStr string, _ int) (name.Tag, bool) {
|
||||
tag, err := name.NewTag(tagStr)
|
||||
// parseImageReferences parses repo tags/digests into name.Reference
|
||||
func (a Artifact) parseImageReferences(references []string) []name.Reference {
|
||||
return lo.FilterMap(references, func(ref string, _ int) (name.Reference, bool) {
|
||||
tag, err := name.ParseReference(ref)
|
||||
if err != nil {
|
||||
a.logger.Debug("Failed to parse repo tag", log.String("tag", tagStr), log.Err(err))
|
||||
return name.Tag{}, false
|
||||
a.logger.Debug("Failed to parse repo tag/digest", log.String("ref", ref), log.Err(err))
|
||||
return name.Reference{}, false
|
||||
}
|
||||
return tag, true
|
||||
})
|
||||
}
|
||||
|
||||
// parseRepoDigests parses repo digests into name.Digest
|
||||
func (a Artifact) parseRepoDigests(repoDigests []string) []name.Digest {
|
||||
return lo.FilterMap(repoDigests, func(digestStr string, _ int) (name.Digest, bool) {
|
||||
digest, err := name.NewDigest(digestStr)
|
||||
if err != nil {
|
||||
a.logger.Debug("Failed to parse repo digest", log.String("digest", digestStr), log.Err(err))
|
||||
return name.Digest{}, false
|
||||
}
|
||||
return digest, true
|
||||
})
|
||||
}
|
||||
|
||||
// findMatchingRepoReference finds a RepoTag or RepoDigest that matches the artifact name
|
||||
func (a Artifact) findMatchingRepoReference(artifactName string, repoTags []name.Tag, repoDigests []name.Digest) name.Reference {
|
||||
func (a Artifact) findMatchingRepoReference(artifactName string, references []name.Reference) name.Reference {
|
||||
// If there are no RepoTags or RepoDigests, return nil
|
||||
if len(repoTags) == 0 && len(repoDigests) == 0 {
|
||||
return nil
|
||||
if len(references) == 0 {
|
||||
return name.Reference{}
|
||||
}
|
||||
|
||||
// Select the first available reference as fallback
|
||||
fallback := cmp.Or[name.Reference](lo.FirstOrEmpty(repoTags), lo.FirstOrEmpty(repoDigests))
|
||||
// Use the first available reference as fallback (tags take precedence over digests)
|
||||
fallback := lo.FirstOrEmpty(references)
|
||||
|
||||
// TODO(knqyf263): refactor to use a more robust method instead of suffix-based detection
|
||||
// Check if artifact name looks like a file path (tar archive)
|
||||
@@ -240,22 +224,11 @@ func (a Artifact) findMatchingRepoReference(artifactName string, repoTags []name
|
||||
}
|
||||
|
||||
artifactRefName := artifactRef.Name()
|
||||
|
||||
switch artifactRef.(type) {
|
||||
case name.Digest:
|
||||
// Try to find a matching digest from RepoDigests
|
||||
if digest, ok := lo.Find(repoDigests, func(d name.Digest) bool {
|
||||
return artifactRefName == d.Name()
|
||||
}); ok {
|
||||
return digest
|
||||
}
|
||||
case name.Tag:
|
||||
// Try to find a matching tag from RepoTags
|
||||
if tag, ok := lo.Find(repoTags, func(t name.Tag) bool {
|
||||
return artifactRefName == t.Name()
|
||||
}); ok {
|
||||
return tag
|
||||
}
|
||||
// Try to find a matching digest from RepoTags/RepoDigests
|
||||
if ref, ok := lo.Find(references, func(d name.Reference) bool {
|
||||
return artifactRefName == d.Name()
|
||||
}); ok {
|
||||
return ref
|
||||
}
|
||||
|
||||
// If no matching tag/digest found, use the first RepoTag or RepoDigest as fallback
|
||||
|
||||
@@ -94,6 +94,7 @@ func (a Artifact) Inspect(ctx context.Context) (artifact.Reference, error) {
|
||||
DiffIDs: bom.Metadata.DiffIDs,
|
||||
RepoTags: bom.Metadata.RepoTags,
|
||||
RepoDigests: bom.Metadata.RepoDigests,
|
||||
Reference: bom.Metadata.Reference,
|
||||
},
|
||||
|
||||
// Keep an original report
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/cachetest"
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom"
|
||||
@@ -203,6 +204,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
RepoTags: []string{
|
||||
"maven-test-project:latest",
|
||||
},
|
||||
Reference: testutil.MustParseReference(t, "maven-test-project:latest"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
4
pkg/fanal/artifact/sbom/testdata/bom.json
vendored
4
pkg/fanal/artifact/sbom/testdata/bom.json
vendored
@@ -39,6 +39,10 @@
|
||||
{
|
||||
"name": "aquasecurity:trivy:RepoTag",
|
||||
"value": "maven-test-project:latest"
|
||||
},
|
||||
{
|
||||
"name": "aquasecurity:trivy:Reference",
|
||||
"value": "maven-test-project:latest"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package image
|
||||
package name
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -13,11 +13,6 @@ type Reference struct {
|
||||
name.Reference
|
||||
}
|
||||
|
||||
// NewReference creates a new Reference from name.Reference
|
||||
func NewReference(ref name.Reference) Reference {
|
||||
return Reference{Reference: ref}
|
||||
}
|
||||
|
||||
// ParseReference parses a string into a Reference
|
||||
func ParseReference(s string) (Reference, error) {
|
||||
if s == "" {
|
||||
@@ -56,7 +51,7 @@ func (r *Reference) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the reference is empty
|
||||
func (r Reference) IsEmpty() bool {
|
||||
// IsZero returns true if the reference is empty (for omitzero support)
|
||||
func (r Reference) IsZero() bool {
|
||||
return lo.IsNil(r.Reference)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package image_test
|
||||
package name_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
)
|
||||
|
||||
func TestReference_MarshalJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref image.Reference
|
||||
ref name.Reference
|
||||
want string
|
||||
}{
|
||||
{
|
||||
@@ -29,7 +29,7 @@ func TestReference_MarshalJSON(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "empty reference",
|
||||
ref: image.Reference{},
|
||||
ref: name.Reference{},
|
||||
want: `""`,
|
||||
},
|
||||
}
|
||||
@@ -81,14 +81,14 @@ func TestReference_UnmarshalJSON(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var r image.Reference
|
||||
var r name.Reference
|
||||
err := json.Unmarshal([]byte(tt.json), &r)
|
||||
tt.wantErr(t, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
assert.Equal(t, tt.wantIsEmpty, r.IsEmpty())
|
||||
if !r.IsEmpty() {
|
||||
assert.Equal(t, tt.wantIsEmpty, r.IsZero())
|
||||
if !r.IsZero() {
|
||||
assert.Equal(t, tt.want, r.String())
|
||||
}
|
||||
})
|
||||
@@ -98,7 +98,7 @@ func TestReference_UnmarshalJSON(t *testing.T) {
|
||||
func TestReference_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref image.Reference
|
||||
ref name.Reference
|
||||
want string
|
||||
}{
|
||||
{
|
||||
@@ -128,7 +128,7 @@ func TestReference_String(t *testing.T) {
|
||||
func TestReference_Context(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref image.Reference
|
||||
ref name.Reference
|
||||
want string
|
||||
}{
|
||||
{
|
||||
@@ -158,7 +158,7 @@ func TestReference_Context(t *testing.T) {
|
||||
func TestReference_IsEmpty(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref image.Reference
|
||||
ref name.Reference
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
@@ -168,14 +168,14 @@ func TestReference_IsEmpty(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "empty reference",
|
||||
ref: image.Reference{},
|
||||
ref: name.Reference{},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, tt.ref.IsEmpty())
|
||||
assert.Equal(t, tt.want, tt.ref.IsZero())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ func TestReference_JSONRoundTrip(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Unmarshal from JSON
|
||||
var decoded image.Reference
|
||||
var decoded name.Reference
|
||||
err = json.Unmarshal(data, &decoded)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -33,6 +33,7 @@ const (
|
||||
PropertyRepoDigest = "RepoDigest"
|
||||
PropertyDiffID = "DiffID"
|
||||
PropertyRepoTag = "RepoTag"
|
||||
PropertyReference = "Reference"
|
||||
PropertyLabelsPrefix = "Labels"
|
||||
|
||||
// Package properties
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/dependency"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
@@ -105,6 +106,10 @@ func (m *Decoder) decodeRoot(s *types.SBOM) error {
|
||||
s.Metadata.DiffIDs = append(s.Metadata.DiffIDs, prop.Value)
|
||||
case core.PropertyRepoTag:
|
||||
s.Metadata.RepoTags = append(s.Metadata.RepoTags, prop.Value)
|
||||
case core.PropertyReference:
|
||||
if s.Metadata.Reference, err = name.ParseReference(prop.Value); err != nil {
|
||||
m.logger.Warn("Failed to parse image reference", log.String("value", prop.Value), log.Err(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -167,6 +167,13 @@ func (e *Encoder) rootComponent(r types.Report) (*core.Component, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if !r.Metadata.Reference.IsZero() {
|
||||
props = append(props, core.Property{
|
||||
Name: core.PropertyReference,
|
||||
Value: r.Metadata.Reference.String(),
|
||||
})
|
||||
}
|
||||
|
||||
root.Properties = filterProperties(props)
|
||||
|
||||
return root, nil
|
||||
|
||||
@@ -92,6 +92,7 @@ func (s Service) ScanArtifact(ctx context.Context, options types.ScanOptions) (t
|
||||
DiffIDs: artifactInfo.ImageMetadata.DiffIDs,
|
||||
RepoTags: artifactInfo.ImageMetadata.RepoTags,
|
||||
RepoDigests: artifactInfo.ImageMetadata.RepoDigests,
|
||||
Reference: artifactInfo.ImageMetadata.Reference,
|
||||
ImageConfig: artifactInfo.ImageMetadata.ConfigFile,
|
||||
Size: scanResponse.Layers.TotalSize(),
|
||||
Layers: lo.Ternary(len(scanResponse.Layers) > 0, scanResponse.Layers, nil),
|
||||
@@ -125,7 +126,7 @@ func (s Service) generateArtifactID(artifactInfo artifact.Reference) string {
|
||||
|
||||
// Use the Reference field if available
|
||||
ref := artifactInfo.ImageMetadata.Reference
|
||||
if ref.IsEmpty() {
|
||||
if ref.IsZero() {
|
||||
// Reference is empty when RepoTags and RepoDigests are both empty.
|
||||
// This happens in the following cases:
|
||||
// 1. Images built without tags (e.g., "docker build ." without -t flag)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/internal/dbtest"
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/clock"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/applier"
|
||||
@@ -77,6 +78,7 @@ func TestScanner_ScanArtifact(t *testing.T) {
|
||||
DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
},
|
||||
},
|
||||
Reference: testutil.MustParseReference(t, "alpine:3.11"),
|
||||
ImageConfig: v1.ConfigFile{
|
||||
Architecture: "amd64",
|
||||
Container: "fb71ddde5f6411a82eb056a9190f0cc1c80d7f77a8509ee90a2054428edb0024",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1" // nolint: goimports
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image/name"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
)
|
||||
@@ -37,12 +38,13 @@ type Metadata struct {
|
||||
OS *ftypes.OS `json:",omitempty"`
|
||||
|
||||
// Container image
|
||||
ImageID string `json:",omitempty"`
|
||||
DiffIDs []string `json:",omitempty"`
|
||||
RepoTags []string `json:",omitempty"`
|
||||
RepoDigests []string `json:",omitempty"`
|
||||
ImageConfig v1.ConfigFile `json:",omitzero"`
|
||||
Layers ftypes.Layers `json:",omitzero"`
|
||||
ImageID string `json:",omitempty"`
|
||||
DiffIDs []string `json:",omitempty"`
|
||||
RepoTags []string `json:",omitempty"`
|
||||
RepoDigests []string `json:",omitempty"`
|
||||
Reference name.Reference `json:",omitzero"`
|
||||
ImageConfig v1.ConfigFile `json:",omitzero"`
|
||||
Layers ftypes.Layers `json:",omitzero"`
|
||||
|
||||
// Git repository
|
||||
RepoURL string `json:",omitzero"`
|
||||
|
||||
Reference in New Issue
Block a user