From c0b547bdb239f00ef43b7f69a61813b710d0b221 Mon Sep 17 00:00:00 2001 From: Jonas Xavier Date: Tue, 22 Mar 2022 10:19:18 -0700 Subject: [PATCH 01/31] Less verbose logging in Golang Cataloger (#904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Less verbose logging in Golang Cataloger Signed-off-by: Jonas Galvão Xavier * debug for known gray errors Signed-off-by: Jonas Galvão Xavier * only show warnings when a binary is not a go executable Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- syft/pkg/cataloger/golang/scan_bin.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/golang/scan_bin.go b/syft/pkg/cataloger/golang/scan_bin.go index 847191efcba..5663492d638 100644 --- a/syft/pkg/cataloger/golang/scan_bin.go +++ b/syft/pkg/cataloger/golang/scan_bin.go @@ -24,17 +24,27 @@ func scanFile(reader unionReader, filename string) ([]*debug.BuildInfo, []string // with more than one binary readers, err := getReaders(reader) if err != nil { - log.Warnf("golang cataloger: opening binary: %v", err) + log.Warnf("golang cataloger: failed to open a binary: %v", err) return nil, nil } var builds []*debug.BuildInfo for _, r := range readers { bi, err := buildinfo.Read(r) + + // note: the stdlib does not export the error we need to check for if err != nil { - log.Warnf("golang cataloger: scanning file %s: %v", filename, err) + if err.Error() == "not a Go executable" { + // since the cataloger can only select executables and not distinguish if they are a go-compiled + // binary, we should not show warnings/logs in this case. + return nil, nil + } + // in this case we could not read the or parse the file, but not explicitly because it is not a + // go-compiled binary (though it still might be). + log.Warnf("golang cataloger: failed to read buildinfo (file=%q): %v", filename, err) return nil, nil } + builds = append(builds, bi) } From 5253da4b3631e61855c4a0e77b43c563788cf2cd Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 23 Mar 2022 14:33:41 -0400 Subject: [PATCH 02/31] Rollback referencing docker config items (#912) --- go.mod | 13 +----------- go.sum | 63 ++-------------------------------------------------------- 2 files changed, 3 insertions(+), 73 deletions(-) diff --git a/go.mod b/go.mod index 54b2a48171f..4a06287f2c8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ 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.20220314153042-1bcd40e5206b - github.com/anchore/stereoscope v0.0.0-20220322123031-7a744f443e99 + github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde github.com/antihax/optional v1.0.0 github.com/bmatcuk/doublestar/v4 v4.0.2 github.com/dustin/go-humanize v1.0.0 @@ -69,7 +69,6 @@ require ( cloud.google.com/go/kms v1.3.0 // indirect cloud.google.com/go/storage v1.21.0 // indirect github.com/Azure/azure-sdk-for-go v61.5.0+incompatible // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.24 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect @@ -80,7 +79,6 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/Microsoft/hcsshim v0.8.23 // indirect github.com/PaesslerAG/gval v1.0.0 // indirect github.com/PaesslerAG/jsonpath v0.1.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect @@ -122,14 +120,11 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b // indirect github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect - github.com/docker/go-metrics v0.0.1 // indirect github.com/envoyproxy/go-control-plane v0.10.1 // indirect github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect github.com/fatih/color v1.13.0 // indirect github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect github.com/fullstorydev/grpcurl v1.8.2 // indirect - github.com/fvbommel/sortorder v1.0.2 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect github.com/go-logr/logr v1.2.2 // indirect @@ -160,7 +155,6 @@ require ( github.com/google/trillian v1.4.0 // indirect github.com/googleapis/gax-go/v2 v2.1.1 // indirect github.com/googleapis/gnostic v0.5.5 // indirect - github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect @@ -195,12 +189,8 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/sys/mount v0.3.1 // indirect - github.com/moby/sys/mountinfo v0.6.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -225,7 +215,6 @@ require ( github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613 // indirect github.com/thales-e-security/pool v0.0.2 // indirect github.com/theupdateframework/go-tuf v0.0.0-20220211205608-f0c3294f63b9 // indirect - github.com/theupdateframework/notary v0.7.0 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/urfave/cli v1.22.5 // indirect github.com/xanzy/go-gitlab v0.56.0 // indirect diff --git a/go.sum b/go.sum index 67ea972b98e..e704c6b7566 100644 --- a/go.sum +++ b/go.sum @@ -218,7 +218,6 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2 github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= @@ -239,8 +238,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/ReneKroon/ttlcache/v2 v2.10.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= github.com/ReneKroon/ttlcache/v2 v2.11.0 h1:OvlcYFYi941SBN3v9dsDcC2N8vRxyHcCmJb3Vl4QMoM= github.com/ReneKroon/ttlcache/v2 v2.11.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= -github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= @@ -283,8 +280,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.20220314153042-1bcd40e5206b h1:YJWYt/6KQXR9JR46lLHrTTYi8rcye42tKcyjREA/hvA= github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.0-20220322123031-7a744f443e99 h1:npngzwfM+fmA56VslKxrcKNhGa2W8MMnASQ1CpuZ1ZA= -github.com/anchore/stereoscope v0.0.0-20220322123031-7a744f443e99/go.mod h1:By2EeOMx9BCf44Wu92W/gsarFKB2Yj921IANAw2Pj1k= +github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde h1:yOi6g1D2q3WwzID0QQyF+x9VkzUyGSJy3cEYbp7ZOyk= +github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde/go.mod h1:OVVJ4y/L26pspeeHNvNa7GeQfoLPWxJe13iODl9x5l4= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= @@ -409,7 +406,6 @@ github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62 github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -417,7 +413,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= @@ -442,11 +437,7 @@ github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt7 github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= @@ -491,8 +482,6 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= -github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -561,7 +550,6 @@ github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= @@ -638,7 +626,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKY github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberphone/json-canonicalization v0.0.0-20210303052042-6bc126869bf4/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b h1:lMzA7yYThpwx7iYNpTeiQnRH6h5JSfSYMJdz+pxZOW8= @@ -658,7 +645,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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= github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= -github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= @@ -688,21 +674,16 @@ github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05 github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= 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-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= @@ -712,7 +693,6 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/dvyukov/go-fuzz v0.0.0-20210914135545-4980593459a1/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -739,7 +719,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= @@ -786,8 +765,6 @@ github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZU github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw= github.com/fullstorydev/grpcurl v1.8.2 h1:2II5e++aFnctnPJir3GL6cPSwF69Ord1u/9O+fv1vrI= github.com/fullstorydev/grpcurl v1.8.2/go.mod h1:YvWNT3xRp2KIRuvCphFodG0fKkMXwaxA9CJgKCcyzUQ= -github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= -github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= @@ -957,7 +934,6 @@ github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSr github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= github.com/go-rod/rod v0.101.8/go.mod h1:N/zlT53CfSpq74nb6rOR0K8UF0SPUPBmzBnArrms+mY= github.com/go-rod/rod v0.102.1/go.mod h1:RXSLAlPodTFOmZnwaAQJIcOJ1i835r0uuTGPLO09t/M= -github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -1022,7 +998,6 @@ github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -1105,7 +1080,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= @@ -1215,7 +1189,6 @@ github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b0 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -1256,8 +1229,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -1402,11 +1373,6 @@ github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8 github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w= github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= -github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= -github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= -github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= -github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -1437,7 +1403,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -1498,7 +1463,6 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= -github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -1514,7 +1478,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2 github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -1567,7 +1530,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -1614,7 +1576,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -1631,12 +1592,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mount v0.3.1 h1:RX1K0x95oR8j5P1YefKDt7tE1C2kCCixV0H8Aza3GaI= -github.com/moby/sys/mount v0.3.1/go.mod h1:6IZknFQiqjLpwuYJD5Zk0qYEuJiws36M88MIXnZHya0= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo= -github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= @@ -1705,7 +1662,6 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -1718,7 +1674,6 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= @@ -1815,7 +1770,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -1994,12 +1948,10 @@ github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= @@ -2009,18 +1961,15 @@ github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSW github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= @@ -2080,8 +2029,6 @@ github.com/theupdateframework/go-tuf v0.0.0-20211203210025-7ded50136bf9/go.mod h github.com/theupdateframework/go-tuf v0.0.0-20220127213825-87caa18db2a6/go.mod h1:I0Gs4Tev4hYQ5wiNqN8VJ7qS0gw7KOZNQuckC624RmE= github.com/theupdateframework/go-tuf v0.0.0-20220211205608-f0c3294f63b9 h1:U8bHY5mmNuZHc3+e7l2/LAmfTk7oiMiB3Qn8fsp4z5g= github.com/theupdateframework/go-tuf v0.0.0-20220211205608-f0c3294f63b9/go.mod h1:ENa0O55YQfI0U/nn4AAuqPydrbkqQCiq9GDw6YLCyXU= -github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= -github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -2363,7 +2310,6 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -3017,7 +2963,6 @@ google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2 google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c h1:TU4rFa5APdKTq0s6B7WTsH6Xmx0Knj86s6Biz56mErE= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -3077,8 +3022,6 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= -gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -3106,8 +3049,6 @@ gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= From cc2c0e57a0d02a1719b4e34d0793f09e9699c8b0 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 23 Mar 2022 14:34:54 -0400 Subject: [PATCH 03/31] bump strset version to fix 386 builds (#911) --- go.mod | 3 ++- go.sum | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 4a06287f2c8..ece8a351087 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,8 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/pelletier/go-toml v1.9.4 github.com/pkg/profile v1.5.0 - github.com/scylladb/go-set v1.0.2 + // 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.2.0 github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7 github.com/sirupsen/logrus v1.8.1 diff --git a/go.sum b/go.sum index e704c6b7566..2bf99aa4a67 100644 --- a/go.sum +++ b/go.sum @@ -1877,8 +1877,9 @@ github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 h1:sUNzanSKA9z/h github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74/go.mod h1:YlB8wFIZmFLZ1JllNBfSURzz52fBxbliNgYALk1UDmk= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= -github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE= github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= +github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= +github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/secure-systems-lab/go-securesystemslib v0.2.0/go.mod h1:eIjBmIP8LD2MLBL/DkQWayLiz006Q4p+hCu79rvWleY= From a7db43f5ec159cad98d0298a2375ee1f4c397894 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Thu, 24 Mar 2022 10:11:51 -0400 Subject: [PATCH 04/31] Fix panic on empty sbom (#917) * Implement fmt.Stringer with format.ID Signed-off-by: Dan Luhring * Add failing test for formats processing empty SBOMs Signed-off-by: Dan Luhring * Account for nil SPDX document during Syft model conversion Signed-off-by: Dan Luhring --- .../common/spdxhelpers/to_syft_model.go | 5 ++++ syft/formats_test.go | 26 +++++++++++++++++++ syft/sbom/format.go | 5 ++++ 3 files changed, 36 insertions(+) diff --git a/internal/formats/common/spdxhelpers/to_syft_model.go b/internal/formats/common/spdxhelpers/to_syft_model.go index 63ed039a83d..ade236089e9 100644 --- a/internal/formats/common/spdxhelpers/to_syft_model.go +++ b/internal/formats/common/spdxhelpers/to_syft_model.go @@ -1,6 +1,7 @@ package spdxhelpers import ( + "errors" "strconv" "strings" @@ -17,6 +18,10 @@ import ( ) func ToSyftModel(doc *spdx.Document2_2) (*sbom.SBOM, error) { + if doc == nil { + return nil, errors.New("cannot convert SPDX document to Syft model because document is nil") + } + spdxIDMap := make(map[string]interface{}) s := &sbom.SBOM{ diff --git a/syft/formats_test.go b/syft/formats_test.go index f55dcce103e..555fb08bd39 100644 --- a/syft/formats_test.go +++ b/syft/formats_test.go @@ -1,6 +1,7 @@ package syft import ( + "bytes" "io" "os" "testing" @@ -41,6 +42,31 @@ func TestIdentify(t *testing.T) { } } +func TestFormats_EmptyInput(t *testing.T) { + for _, format := range formats { + t.Run(format.ID().String(), func(t *testing.T) { + t.Run("format.Decode", func(t *testing.T) { + input := bytes.NewReader(nil) + + assert.NotPanics(t, func() { + decodedSBOM, err := format.Decode(input) + assert.Error(t, err) + assert.Nil(t, decodedSBOM) + }) + }) + + t.Run("format.Validate", func(t *testing.T) { + input := bytes.NewReader(nil) + + assert.NotPanics(t, func() { + err := format.Validate(input) + assert.Error(t, err) + }) + }) + }) + } +} + func TestFormatByName(t *testing.T) { tests := []struct { diff --git a/syft/sbom/format.go b/syft/sbom/format.go index abdf7b97157..13cfa784899 100644 --- a/syft/sbom/format.go +++ b/syft/sbom/format.go @@ -13,6 +13,11 @@ var ( type FormatID string +// String returns a string representation of the FormatID. +func (f FormatID) String() string { + return string(f) +} + type Format interface { ID() FormatID Encode(io.Writer, SBOM) error From 47ea91086879c3e57cf399a19a8aa2a3d0d71340 Mon Sep 17 00:00:00 2001 From: briankoe741 <101280300+briankoe741@users.noreply.github.com> Date: Thu, 24 Mar 2022 19:17:14 -0500 Subject: [PATCH 05/31] Remove announcement for OSS Meetup (#915) Proposing changes to remove our 3/23 meetup Signed-off-by: Dan Luhring --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 4bf080f0ac0..a2f00e2547a 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,6 @@ A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner tool like [Grype](https://github.com/anchore/grype). -### Join our Virtual OSS Meetup! - -You are invited to join us on March 23rd, 11AM-Noon PT for our virtual open source meetup. - -Hosts Priyanka “Pinky” Ravi of Weaveworks and Dan Luhring from Anchore OSS will explore how open source project Flux is utilizing Syft-generated SBOMs to secure the software supply chain. - -[Register here!](https://get.anchore.com/anchore-oss-meetup-mar-23-2022/) - ### Join our community meetings! - Calendar: https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t From 5549939cc65069a4cbad5e45813377c2882d40e7 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Fri, 25 Mar 2022 11:36:43 -0400 Subject: [PATCH 06/31] Fixups and clarifications in README (#920) Signed-off-by: Dan Luhring --- README.md | 119 ++++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index a2f00e2547a..905efec8d10 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/anchore/syft/blob/main/LICENSE) [![Slack Invite](https://img.shields.io/badge/Slack-Join-blue?logo=slack)](https://anchore.com/slack) -A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner tool like [Grype](https://github.com/anchore/grype). +A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner like [Grype](https://github.com/anchore/grype). ### Join our community meetings! @@ -20,15 +20,25 @@ A CLI tool and Go library for generating a Software Bill of Materials (SBOM) fro ![syft-demo](https://user-images.githubusercontent.com/590471/90277200-2a253000-de33-11ea-893f-32c219eea11a.gif) ## Features -- Catalog container images and filesystems to discover packages and libraries. -- Generate in-toto attestations where an SBOM is included as the payload. -- Supports packages and libraries from various ecosystems (APK, DEB, RPM, Ruby Bundles, Python Wheel/Egg/requirements.txt, JavaScript NPM/Yarn, Java JAR/EAR/WAR/PAR/SAR, Jenkins plugins JPI/HPI, Go modules, PHP Composer) -- Linux distribution identification (supports Alpine, BusyBox, CentOS/RedHat, Debian/Ubuntu flavored distributions) -- Supports Docker and OCI image formats -- Direct support for [Grype](https://github.com/anchore/grype), a fast and powerful vulnerability matcher. - - -If you encounter an issue, please [let us know using the issue tracker](https://github.com/anchore/syft/issues). +- Generates SBOMs for container images, filesystems, archives, and more to discover packages and libraries +- Supports OCI and Docker image formats +- Linux distribution identification +- Works seamlessly with [Grype](https://github.com/anchore/grype) (a fast, modern vulnerability scanner) +- Able to create signed SBOM attestations using the [in-toto specification](https://github.com/in-toto/attestation/blob/main/spec/README.md) + +### Supported Ecosystems + +- Alpine (apk) +- Debian (dpkg) +- Go (go.mod, Go binaries) +- Java (jar, ear, war, par, sar) +- JavaScript (npm, yarn) +- Jenkins Plugins (jpi, hpi) +- PHP (composer) +- Python (wheel, egg, poetry, requirements.txt) +- Red Hat (rpm) +- Ruby (gem) +- Rust (cargo.lock) ## Installation @@ -53,15 +63,13 @@ brew install syft ### Nix -**Note**: nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/admin/syft/default.nix) - -Also syft is currently only in the [unstable channel](https://nixos.wiki/wiki/Nix_channels#The_official_channels) awaiting the `22.05` release +**Note**: Nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/admin/syft/default.nix). Syft is currently only in the [unstable channel](https://nixos.wiki/wiki/Nix_channels#The_official_channels) awaiting the `22.05` release ```bash nix-env -i syft ``` -... or, just try it out in an ephemeral nix shell +... or, just try it out in an ephemeral nix shell: ```bash nix-shell -p syft @@ -70,33 +78,28 @@ nix-shell -p syft ## Getting started #### SBOM -To generate an SBOM for an OCI image: -``` -syft -``` -**Note**: This is equivalent to specifying the `packages` subcommand: +To generate an SBOM for a container image: + ``` -syft packages +syft ``` -The above output includes only software that is visible in the container (i.e., the squashed representation of the image). -To include software from all image layers in the SBOM, regardless of its presence in the final image, provide `--scope all-layers`: +The above output includes only software that is visible in the container (i.e., the squashed representation of the image). To include software from all image layers in the SBOM, regardless of its presence in the final image, provide `--scope all-layers`: ``` -syft packages --scope all-layers +syft --scope all-layers ``` -#### SBOM Attestation -To generate an attested SBOM for an OCI image as the predicate of an in-toto attestation +#### SBOM attestation + +To generate an SBOM attestation for a container image: ``` syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags] ``` The above output is in the form of the [DSSE envelope](https://github.com/secure-systems-lab/dsse/blob/master/envelope.md#dsse-envelope). -The payload is a base64 encoded `in-toto` statement with the SBOM as the predicate, the payload type is `application/vnd.in-toto+json`, and the signatures array is populated -with the contents needed for public key verification. For details on workflows using this command see [here](#adding-an-sbom-to-an-image-as-an-attestation-using-syft). - +The payload is a base64 encoded `in-toto` statement with the generated SBOM as the predicate. For details on workflows using this command see [here](#adding-an-sbom-to-an-image-as-an-attestation-using-syft). ### Supported sources @@ -104,10 +107,10 @@ Syft can generate a SBOM from a variety of sources: ``` # catalog a container image archive (from the result of `docker image save ...`, `podman save ...`, or `skopeo copy` commands) -syft packages path/to/image.tar +syft path/to/image.tar # catalog a directory -syft packages path/to/dir +syft path/to/dir ``` Sources can be explicitly provided with a scheme: @@ -146,7 +149,7 @@ The output format for Syft is configurable as well using the `-o` (or `--output`) option: ``` -syft packages -o +syft -o ``` Where the `formats` available are: @@ -164,20 +167,16 @@ Syft can also output _multiple_ files in differing formats by appending `=` to the option, for example to output Syft JSON and SPDX JSON: ```shell -syft packages -o json=sbom.syft.json -o spdx-json=sbom.spdx.json +syft -o json=sbom.syft.json -o spdx-json=sbom.spdx.json ``` ## Private Registry Authentication ### Local Docker Credentials -When a container runtime is not present, Syft can still utilize credentials configured in common credential sources (such as `~/.docker/config.json`). -It will pull images from private registries using these credentials. The config file is where your credentials are stored when authenticating with private registries via some command like `docker login`. -For more information see the `go-containerregistry` [documentation](https://github.com/google/go-containerregistry/tree/main/pkg/authn). - +When a container runtime is not present, Syft can still utilize credentials configured in common credential sources (such as `~/.docker/config.json`). It will pull images from private registries using these credentials. The config file is where your credentials are stored when authenticating with private registries via some command like `docker login`. For more information see the `go-containerregistry` [documentation](https://github.com/google/go-containerregistry/tree/main/pkg/authn). An example `config.json` looks something like this: -``` -// config.json +```json { "auths": { "registry.example.com": { @@ -190,15 +189,17 @@ An example `config.json` looks something like this: You can run the following command as an example. It details the mount/environment configuration a container needs to access a private registry: -`docker run -v ./config.json:/config/config.json -e "DOCKER_CONFIG=/config" anchore/syft:latest ` - +``` +docker run -v ./config.json:/config/config.json -e "DOCKER_CONFIG=/config" anchore/syft:latest +``` ### Docker Credentials in Kubernetes -The below section shows a simple workflow on how to mount this config file as a secret into a container on kubernetes. -1. Create a secret. The value of `config.json` is important. It refers to the specification detailed [here](https://github.com/google/go-containerregistry/tree/main/pkg/authn#the-config-file). -Below this section is the `secret.yaml` file that the pod configuration will consume as a volume. -The key `config.json` is important. It will end up being the name of the file when mounted into the pod. - ``` + +Here's a simple workflow to mount this config file as a secret into a container on Kubernetes. + +1. Create a secret. The value of `config.json` is important. It refers to the specification detailed [here](https://github.com/google/go-containerregistry/tree/main/pkg/authn#the-config-file). Below this section is the `secret.yaml` file that the pod configuration will consume as a volume. The key `config.json` is important. It will end up being the name of the file when mounted into the pod. + + ```yaml # secret.yaml apiVersion: v1 @@ -213,11 +214,9 @@ The key `config.json` is important. It will end up being the name of the file wh `kubectl apply -f secret.yaml` -2. Create your pod running syft. The env `DOCKER_CONFIG` is important because it advertises where to look for the credential file. -In the below example, setting `DOCKER_CONFIG=/config` informs syft that credentials can be found at `/config/config.json`. -This is why we used `config.json` as the key for our secret. When mounted into containers the secrets' key is used as the filename. -The `volumeMounts` section mounts our secret to `/config`. The `volumes` section names our volume and leverages the secret we created in step one. - ``` +2. Create your pod running syft. The env `DOCKER_CONFIG` is important because it advertises where to look for the credential file. In the below example, setting `DOCKER_CONFIG=/config` informs syft that credentials can be found at `/config/config.json`. This is why we used `config.json` as the key for our secret. When mounted into containers the secrets' key is used as the filename. The `volumeMounts` section mounts our secret to `/config`. The `volumes` section names our volume and leverages the secret we created in step one. + + ```yaml # pod.yaml apiVersion: v1 @@ -246,10 +245,9 @@ The `volumeMounts` section mounts our secret to `/config`. The `volumes` section `kubectl apply -f pod.yaml` -3. The user can now run `kubectl logs syft-private-registry-demo`. The logs should show the syft analysis for the `` provided in the pod configuration. +3. The user can now run `kubectl logs syft-private-registry-demo`. The logs should show the Syft analysis for the `` provided in the pod configuration. -Using the above information, users should be able to configure private registry access without having to do so in the `grype` or `syft` configuration files. -They will also not be dependent on a docker daemon, (or some other runtime software) for registry configuration and access. +Using the above information, users should be able to configure private registry access without having to do so in the `grype` or `syft` configuration files. They will also not be dependent on a Docker daemon, (or some other runtime software) for registry configuration and access. ## Configuration @@ -464,26 +462,25 @@ anchore: `syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags]` -SBOMs themselves can serve as input to different analysis tools. The Anchore organization offers the vulnerability scanner -[grype](https://github.com/anchore/grype) as one such tool. -One of the foundational approaches to "trust" between tools is for producers to use the artifacts generated by syft as attestations to their images. -The DSSE output of `syft attest` can be used with the [cosign](https://github.com/sigstore/cosign) tool to attach an attestation to an image. +SBOMs themselves can serve as input to different analysis tools. [Grype](https://github.com/anchore/grype), a vulnerability scanner CLI tool from Anchore, is one such tool. Publishers of container images can use attestations to enable their consumers to trust Syft-generated SBOM descriptions of those container images. To create and provide these attestations, image publishers can run `syft attest` in conjunction with the [cosign](https://github.com/sigstore/cosign) tool to attach SBOM attestations to their images. -#### Example attest +#### Example attestation Note for the following example replace `docker.io/image:latest` with an image you own. You should also have push access to -its remote reference. Replace $MY_PRIVATE_KEY with a private key you own or have generated with cosign. +its remote reference. Replace `$MY_PRIVATE_KEY` with a private key you own or have generated with cosign. ```bash syft attest --key $MY_PRIVATE_KEY docker.io/image:latest > image_latest_sbom_attestation.json cosign attach attestation --attestation image_latest_sbom_attestation.json docker.io/image:latest ``` -Verify the new attestation exists on your image +Verify the new attestation exists on your image. + ```bash cosign verify-attestation -key $MY_PUBLIC_KEY docker.io/image:latest | jq '.payload | @base64d | .payload | fromjson | .predicate' ``` -You should see this output along with the attached SBOM. +You should see this output along with the attached SBOM: + ``` Verification for docker.io/image:latest -- The following checks were performed on each of these signatures: From 028cd9e27eadbf56efba13ac1ab6ef7714485426 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Mon, 28 Mar 2022 13:15:09 -0400 Subject: [PATCH 07/31] Fix nil pointer dereference in directory resolver's `indexPath` method (#924) * Add failing test for dir resolver panic Signed-off-by: Dan Luhring * Fix panic Signed-off-by: Dan Luhring --- syft/source/directory_resolver.go | 12 ++++++------ syft/source/directory_resolver_test.go | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/syft/source/directory_resolver.go b/syft/source/directory_resolver.go index b735f744edd..d3ffabc2217 100644 --- a/syft/source/directory_resolver.go +++ b/syft/source/directory_resolver.go @@ -132,10 +132,15 @@ func (r *directoryResolver) indexTree(root string, stager *progress.Stage) ([]st } func (r *directoryResolver) indexPath(path string, info os.FileInfo, err error) (string, error) { + // link cycles could cause a revisit --we should not allow this + if r.hasBeenIndexed(path) { + return "", nil + } + // ignore any path which a filter function returns true for _, filterFn := range r.pathFilterFns { if filterFn != nil && filterFn(path, info) { - if info.IsDir() { + if info != nil && info.IsDir() { return "", fs.SkipDir } return "", nil @@ -146,11 +151,6 @@ func (r *directoryResolver) indexPath(path string, info os.FileInfo, err error) return "", nil } - // link cycles could cause a revisit --we should not allow this - if r.hasBeenIndexed(path) { - return "", nil - } - if info == nil { // walk may not be able to provide a FileInfo object, don't allow for this to stop indexing; keep track of the paths and continue. r.errPaths[path] = fmt.Errorf("no file info observable at path=%q", path) diff --git a/syft/source/directory_resolver_test.go b/syft/source/directory_resolver_test.go index 795ef0b795d..f178414c55b 100644 --- a/syft/source/directory_resolver_test.go +++ b/syft/source/directory_resolver_test.go @@ -865,3 +865,24 @@ func Test_IncludeRootPathInIndex(t *testing.T) { _, exists = resolver.metadata[ref.ID()] require.True(t, exists) } + +func TestDirectoryResolver_indexPath(t *testing.T) { + // TODO: Ideally we can use an OS abstraction, which would obviate the need for real FS setup. + tempFile, err := os.CreateTemp("", "") + require.NoError(t, err) + + resolver, err := newDirectoryResolver(tempFile.Name()) + require.NoError(t, err) + + t.Run("filtering path with nil os.FileInfo", func(t *testing.T) { + // We use one of these prefixes in order to trigger a pathFilterFn + filteredPath := unixSystemRuntimePrefixes[0] + + var fileInfo os.FileInfo = nil + + assert.NotPanics(t, func() { + _, err := resolver.indexPath(filteredPath, fileInfo, nil) + assert.NoError(t, err) + }) + }) +} From f157d7a862a3e193e3fa5f34a3a594b83ea660e6 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 30 Mar 2022 13:32:49 -0400 Subject: [PATCH 08/31] Pull from DockerHub fails for public images when using SSO (#928) --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index ece8a351087..5c5d07c5fdf 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ 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.20220314153042-1bcd40e5206b - github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde + github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0 github.com/antihax/optional v1.0.0 github.com/bmatcuk/doublestar/v4 v4.0.2 github.com/dustin/go-humanize v1.0.0 diff --git a/go.sum b/go.sum index 2bf99aa4a67..8f8c09a9b0e 100644 --- a/go.sum +++ b/go.sum @@ -280,8 +280,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.20220314153042-1bcd40e5206b h1:YJWYt/6KQXR9JR46lLHrTTYi8rcye42tKcyjREA/hvA= github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde h1:yOi6g1D2q3WwzID0QQyF+x9VkzUyGSJy3cEYbp7ZOyk= -github.com/anchore/stereoscope v0.0.0-20220323180633-4bdc70599cde/go.mod h1:OVVJ4y/L26pspeeHNvNa7GeQfoLPWxJe13iODl9x5l4= +github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0 h1:mObz7bepZ6DtbIrsB2mxuOE9XEYmVtA/P/EDlKwfbjs= +github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0/go.mod h1:yoCLUZY0k/pYLNIy0L80p2Ko0PKVNXm8rHtgxp4OiSc= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= @@ -1877,7 +1877,6 @@ github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 h1:sUNzanSKA9z/h github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74/go.mod h1:YlB8wFIZmFLZ1JllNBfSURzz52fBxbliNgYALk1UDmk= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= -github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= From cb3e73e3089f171518b3f4928f76313109633ce8 Mon Sep 17 00:00:00 2001 From: Eric Larssen Date: Thu, 31 Mar 2022 14:44:55 -0500 Subject: [PATCH 09/31] Add dart support (#919) Co-authored-by: Alex Goodman --- README.md | 1 + internal/constants.go | 2 +- .../formats/common/spdxhelpers/source_info.go | 2 + .../common/spdxhelpers/source_info_test.go | 8 + internal/formats/syftjson/model/package.go | 6 + .../snapshot/TestDirectoryEncoder.golden | 4 +- .../TestEncodeFullJSONDocument.golden | 4 +- .../snapshot/TestImageEncoder.golden | 4 +- schema/json/generate.go | 1 + schema/json/schema-3.2.2.json | 1261 +++++++++++++++++ syft/pkg/cataloger/cataloger.go | 3 + syft/pkg/cataloger/dart/cataloger.go | 14 + syft/pkg/cataloger/dart/parse_pubspec_lock.go | 96 ++ .../cataloger/dart/parse_pubspec_lock_test.go | 99 ++ .../cataloger/dart/test-fixtures/pubspec.lock | 49 + syft/pkg/dart_pub_metadata.go | 38 + syft/pkg/language.go | 4 + syft/pkg/language_test.go | 7 +- syft/pkg/metadata.go | 3 + syft/pkg/type.go | 6 + syft/pkg/type_test.go | 7 +- syft/pkg/url_test.go | 14 + .../catalog_packages_cases_test.go | 13 + test/integration/catalog_packages_test.go | 5 +- .../image-pkg-coverage/pkgs/dart/pubspec.lock | 49 + 25 files changed, 1690 insertions(+), 10 deletions(-) create mode 100644 schema/json/schema-3.2.2.json create mode 100644 syft/pkg/cataloger/dart/cataloger.go create mode 100644 syft/pkg/cataloger/dart/parse_pubspec_lock.go create mode 100644 syft/pkg/cataloger/dart/parse_pubspec_lock_test.go create mode 100644 syft/pkg/cataloger/dart/test-fixtures/pubspec.lock create mode 100644 syft/pkg/dart_pub_metadata.go create mode 100644 test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock diff --git a/README.md b/README.md index 905efec8d10..ab39de4b10c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ A CLI tool and Go library for generating a Software Bill of Materials (SBOM) fro ### Supported Ecosystems - Alpine (apk) +- Dart (pubs) - Debian (dpkg) - Go (go.mod, Go binaries) - Java (jar, ear, war, par, sar) diff --git a/internal/constants.go b/internal/constants.go index 3d2266a006a..da098e08910 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -6,5 +6,5 @@ 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 = "3.2.1" + JSONSchemaVersion = "3.2.2" ) diff --git a/internal/formats/common/spdxhelpers/source_info.go b/internal/formats/common/spdxhelpers/source_info.go index d0ae4ed8036..ed5e2600b41 100644 --- a/internal/formats/common/spdxhelpers/source_info.go +++ b/internal/formats/common/spdxhelpers/source_info.go @@ -13,6 +13,8 @@ func SourceInfo(p pkg.Package) string { answer = "acquired package info from RPM DB" case pkg.ApkPkg: answer = "acquired package info from APK DB" + case pkg.DartPubPkg: + answer = "acquired package info from pubspec manifest" case pkg.DebPkg: answer = "acquired package info from DPKG DB" case pkg.NpmPkg: diff --git a/internal/formats/common/spdxhelpers/source_info_test.go b/internal/formats/common/spdxhelpers/source_info_test.go index 05e99d1bfbe..56f6c5bbdbb 100644 --- a/internal/formats/common/spdxhelpers/source_info_test.go +++ b/internal/formats/common/spdxhelpers/source_info_test.go @@ -126,6 +126,14 @@ func Test_SourceInfo(t *testing.T) { "from PHP composer manifest", }, }, + { + input: pkg.Package{ + Type: pkg.DartPubPkg, + }, + expected: []string{ + "from pubspec manifest", + }, + }, } var pkgTypes []pkg.Type for _, test := range tests { diff --git a/internal/formats/syftjson/model/package.go b/internal/formats/syftjson/model/package.go index 618e703cb4d..9ae55ee51cd 100644 --- a/internal/formats/syftjson/model/package.go +++ b/internal/formats/syftjson/model/package.go @@ -130,6 +130,12 @@ func (p *Package) UnmarshalJSON(b []byte) error { return err } p.Metadata = payload + case pkg.DartPubMetadataType: + var payload pkg.DartPubMetadata + if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + return err + } + p.Metadata = payload default: log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID) } diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden index 05c55483e2d..92b55b015fa 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden @@ -88,7 +88,7 @@ } }, "schema": { - "version": "3.2.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.1.json" + "version": "3.2.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.2.json" } } diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden index e600234aebe..728667abdb7 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden @@ -184,7 +184,7 @@ } }, "schema": { - "version": "3.2.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.1.json" + "version": "3.2.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.2.json" } } diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden index 50a3f6cedde..baa8ed26a87 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden @@ -111,7 +111,7 @@ } }, "schema": { - "version": "3.2.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.1.json" + "version": "3.2.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.2.2.json" } } diff --git a/schema/json/generate.go b/schema/json/generate.go index 140ccd3e7bd..a2ff68e57d2 100644 --- a/schema/json/generate.go +++ b/schema/json/generate.go @@ -37,6 +37,7 @@ type artifactMetadataContainer struct { Cargo pkg.CargoPackageMetadata Go pkg.GolangBinMetadata Php pkg.PhpComposerJSONMetadata + Dart pkg.DartPubMetadata } func main() { diff --git a/schema/json/schema-3.2.2.json b/schema/json/schema-3.2.2.json new file mode 100644 index 00000000000..d6649f6cfe5 --- /dev/null +++ b/schema/json/schema-3.2.2.json @@ -0,0 +1,1261 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Document", + "definitions": { + "ApkFileRecord": { + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Digest" + } + }, + "additionalProperties": true, + "type": "object" + }, + "ApkMetadata": { + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "license", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ], + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "type": "string" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ApkFileRecord" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "CargoPackageMetadata": { + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Classification": { + "required": [ + "class", + "metadata" + ], + "properties": { + "class": { + "type": "string" + }, + "metadata": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Coordinates": { + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "DartPubMetadata": { + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Descriptor": { + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": { + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "Digest": { + "required": [ + "algorithm", + "value" + ], + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Document": { + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ], + "properties": { + "artifacts": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/File" + }, + "type": "array" + }, + "secrets": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Secrets" + }, + "type": "array" + }, + "source": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Source" + }, + "distro": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/LinuxRelease" + }, + "descriptor": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Descriptor" + }, + "schema": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Schema" + } + }, + "additionalProperties": true, + "type": "object" + }, + "DpkgFileRecord": { + "required": [ + "path", + "isConfigFile" + ], + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/definitions/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "DpkgMetadata": { + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ], + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/DpkgFileRecord" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "File": { + "required": [ + "id", + "location" + ], + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/definitions/Coordinates" + }, + "metadata": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Digest" + }, + "type": "array" + }, + "classifications": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Classification" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "FileMetadataEntry": { + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType" + ], + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "GemMetadata": { + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "GolangBinMetadata": { + "required": [ + "goCompiledVersion", + "architecture" + ], + "properties": { + "goBuildSettings": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "JavaManifest": { + "properties": { + "main": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "namedSections": { + "patternProperties": { + ".*": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "JavaMetadata": { + "required": [ + "virtualPath" + ], + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/JavaManifest" + }, + "pomProperties": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PomProperties" + }, + "pomProject": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PomProject" + } + }, + "additionalProperties": true, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "items": { + "type": "string" + }, + "type": "array" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "NpmPackageJSONMetadata": { + "required": [ + "name", + "version", + "author", + "licenses", + "homepage", + "description", + "url" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "author": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Package": { + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ], + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Coordinates" + }, + "type": "array" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "language": { + "type": "string" + }, + "cpes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/definitions/ApkMetadata" + }, + { + "$ref": "#/definitions/CargoPackageMetadata" + }, + { + "$ref": "#/definitions/DartPubMetadata" + }, + { + "$ref": "#/definitions/DpkgMetadata" + }, + { + "$ref": "#/definitions/GemMetadata" + }, + { + "$ref": "#/definitions/GolangBinMetadata" + }, + { + "$ref": "#/definitions/JavaMetadata" + }, + { + "$ref": "#/definitions/NpmPackageJSONMetadata" + }, + { + "$ref": "#/definitions/PhpComposerJSONMetadata" + }, + { + "$ref": "#/definitions/PythonPackageMetadata" + }, + { + "$ref": "#/definitions/RpmdbMetadata" + } + ] + } + }, + "additionalProperties": true, + "type": "object" + }, + "PhpComposerAuthors": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PhpComposerExternalReference": { + "required": [ + "type", + "url", + "reference" + ], + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PhpComposerJSONMetadata": { + "required": [ + "name", + "version", + "source", + "dist" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/definitions/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PomParent": { + "required": [ + "groupId", + "artifactId", + "version" + ], + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PomProject": { + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ], + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PomProperties": { + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version", + "extraFields" + ], + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PythonDirectURLOriginInfo": { + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PythonFileDigest": { + "required": [ + "algorithm", + "value" + ], + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PythonFileRecord": { + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "PythonPackageMetadata": { + "required": [ + "name", + "version", + "license", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PythonDirectURLOriginInfo" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Relationship": { + "required": [ + "parent", + "child", + "type" + ], + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": { + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "RpmdbFileRecord": { + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ], + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/definitions/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "RpmdbMetadata": { + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "license", + "vendor", + "files" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "license": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "files": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/RpmdbFileRecord" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Schema": { + "required": [ + "version", + "url" + ], + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "SearchResult": { + "required": [ + "classification", + "lineNumber", + "lineOffset", + "seekPosition", + "length" + ], + "properties": { + "classification": { + "type": "string" + }, + "lineNumber": { + "type": "integer" + }, + "lineOffset": { + "type": "integer" + }, + "seekPosition": { + "type": "integer" + }, + "length": { + "type": "integer" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Secrets": { + "required": [ + "location", + "secrets" + ], + "properties": { + "location": { + "$ref": "#/definitions/Coordinates" + }, + "secrets": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/SearchResult" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "Source": { + "required": [ + "type", + "target" + ], + "properties": { + "type": { + "type": "string" + }, + "target": { + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + } + } +} diff --git a/syft/pkg/cataloger/cataloger.go b/syft/pkg/cataloger/cataloger.go index f44efeb4b52..8e10bf5d626 100644 --- a/syft/pkg/cataloger/cataloger.go +++ b/syft/pkg/cataloger/cataloger.go @@ -9,6 +9,7 @@ import ( "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/apkdb" + "github.com/anchore/syft/syft/pkg/cataloger/dart" "github.com/anchore/syft/syft/pkg/cataloger/deb" "github.com/anchore/syft/syft/pkg/cataloger/golang" "github.com/anchore/syft/syft/pkg/cataloger/java" @@ -61,6 +62,7 @@ func DirectoryCatalogers(cfg Config) []Cataloger { golang.NewGoModuleBinaryCataloger(), golang.NewGoModFileCataloger(), rust.NewCargoLockCataloger(), + dart.NewPubspecLockCataloger(), } } @@ -80,5 +82,6 @@ func AllCatalogers(cfg Config) []Cataloger { golang.NewGoModuleBinaryCataloger(), golang.NewGoModFileCataloger(), rust.NewCargoLockCataloger(), + dart.NewPubspecLockCataloger(), } } diff --git a/syft/pkg/cataloger/dart/cataloger.go b/syft/pkg/cataloger/dart/cataloger.go new file mode 100644 index 00000000000..30fd9203ff7 --- /dev/null +++ b/syft/pkg/cataloger/dart/cataloger.go @@ -0,0 +1,14 @@ +package dart + +import ( + "github.com/anchore/syft/syft/pkg/cataloger/common" +) + +// NewPubspecLockCataloger returns a new Dartlang cataloger object base on pubspec lock files. +func NewPubspecLockCataloger() *common.GenericCataloger { + globParsers := map[string]common.ParserFn{ + "**/pubspec.lock": parsePubspecLock, + } + + return common.NewGenericCataloger(nil, globParsers, "dartlang-lock-cataloger") +} diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock.go b/syft/pkg/cataloger/dart/parse_pubspec_lock.go new file mode 100644 index 00000000000..2ecd8177c68 --- /dev/null +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock.go @@ -0,0 +1,96 @@ +package dart + +import ( + "fmt" + "io" + "net/url" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/common" + "gopkg.in/yaml.v2" +) + +// integrity check +var _ common.ParserFn = parsePubspecLock + +const defaultPubRegistry string = "https://pub.dartlang.org" + +type pubspecLock struct { + Packages map[string]pubspecLockPackage `yaml:"packages"` + Sdks map[string]string `yaml:"sdks"` +} + +type pubspecLockPackage struct { + Dependency string `yaml:"dependency" mapstructure:"dependency"` + Description pubspecLockDescription `yaml:"description" mapstructure:"description"` + Source string `yaml:"source" mapstructure:"source"` + Version string `yaml:"version" mapstructure:"version"` +} + +type pubspecLockDescription struct { + Name string `yaml:"name" mapstructure:"name"` + URL string `yaml:"url" mapstructure:"url"` + Path string `yaml:"path" mapstructure:"path"` + Ref string `yaml:"ref" mapstructure:"ref"` + ResolvedRef string `yaml:"resolved-ref" mapstructure:"resolved-ref"` +} + +func parsePubspecLock(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + var packages []*pkg.Package + + dec := yaml.NewDecoder(reader) + + var p pubspecLock + if err := dec.Decode(&p); err != nil { + return nil, nil, fmt.Errorf("failed to parse pubspec.lock file: %w", err) + } + + for name, pubPkg := range p.Packages { + packages = append(packages, newPubspecLockPackage(name, pubPkg)) + } + + return packages, nil, nil +} + +func newPubspecLockPackage(name string, p pubspecLockPackage) *pkg.Package { + return &pkg.Package{ + Name: name, + Version: p.Version, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: &pkg.DartPubMetadata{ + Name: name, + Version: p.Version, + HostedURL: p.getHostedURL(), + VcsURL: p.getVcsURL(), + }, + } +} + +func (p *pubspecLockPackage) getVcsURL() string { + if p.Source == "git" { + if p.Description.Path == "." { + return fmt.Sprintf("%s@%s", p.Description.URL, p.Description.ResolvedRef) + } + + return fmt.Sprintf("%s@%s#%s", p.Description.URL, p.Description.ResolvedRef, p.Description.Path) + } + + return "" +} + +func (p *pubspecLockPackage) getHostedURL() string { + if p.Source == "hosted" && p.Description.URL != defaultPubRegistry { + u, err := url.Parse(p.Description.URL) + if err != nil { + log.Debugf("Unable to parse registry url %w", err) + return p.Description.URL + } + return u.Host + } + + return "" +} diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go new file mode 100644 index 00000000000..f881524c82d --- /dev/null +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go @@ -0,0 +1,99 @@ +package dart + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/anchore/syft/syft/pkg" +) + +func assertPackagesEqual(t *testing.T, actual []*pkg.Package, expected map[string]*pkg.Package) { + assert.Len(t, actual, len(expected)) +} + +func TestParsePubspecLock(t *testing.T) { + expected := map[string]*pkg.Package{ + "ale": { + Name: "ale", + Version: "3.3.0", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "ale", + Version: "3.3.0", + HostedURL: "pub.hosted.org", + }, + }, + "analyzer": { + Name: "analyzer", + Version: "0.40.7", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "analyzer", + Version: "0.40.7", + }, + }, + "ansicolor": { + Name: "ansicolor", + Version: "1.1.1", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "ansicolor", + Version: "1.1.1", + }, + }, + "archive": { + Name: "archive", + Version: "2.0.13", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "archive", + Version: "2.0.13", + }, + }, + "args": { + Name: "args", + Version: "1.6.0", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "args", + Version: "1.6.0", + }, + }, + "key_binder": { + Name: "key_binder", + Version: "1.11.20", + Language: pkg.Dart, + Type: pkg.DartPubPkg, + MetadataType: pkg.DartPubMetadataType, + Metadata: pkg.DartPubMetadata{ + Name: "key_binder", + Version: "1.11.20", + VcsURL: "git@github.com:Workiva/key_binder.git#3f7b3a6350e73c7dcac45301c0e18fbd42af02f7", + }, + }, + } + + fixture, err := os.Open("test-fixtures/pubspec.lock") + if err != nil { + t.Fatalf("failed to open fixture: %+v", err) + } + + actual, _, err := parsePubspecLock(fixture.Name(), fixture) + if err != nil { + t.Fatalf("failed to parse pubspec.lock: %+v", err) + } + + assertPackagesEqual(t, actual, expected) +} diff --git a/syft/pkg/cataloger/dart/test-fixtures/pubspec.lock b/syft/pkg/cataloger/dart/test-fixtures/pubspec.lock new file mode 100644 index 00000000000..c7b912f1aef --- /dev/null +++ b/syft/pkg/cataloger/dart/test-fixtures/pubspec.lock @@ -0,0 +1,49 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + ale: + dependency: transitive + description: + name: ale + url: "https://pub.hosted.org" + source: hosted + version: "3.3.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.40.7" + ansicolor: + dependency: transitive + description: + name: ansicolor + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" + key_binder: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "3f7b3a6350e73c7dcac45301c0e18fbd42af02f7" + url: "git@github.com:Workiva/key_binder.git" + source: git + version: "1.11.20" +sdks: + dart: ">=2.12.0 <3.0.0" diff --git a/syft/pkg/dart_pub_metadata.go b/syft/pkg/dart_pub_metadata.go new file mode 100644 index 00000000000..3c800877be2 --- /dev/null +++ b/syft/pkg/dart_pub_metadata.go @@ -0,0 +1,38 @@ +package pkg + +import ( + "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/linux" +) + +type DartPubMetadata struct { + Name string `mapstructure:"name" json:"name"` + Version string `mapstructure:"version" json:"version"` + HostedURL string `mapstructure:"hosted_url" json:"hosted_url,omitempty"` + VcsURL string `mapstructure:"vcs_url" json:"vcs_url,omitempty"` +} + +func (m DartPubMetadata) PackageURL(_ *linux.Release) string { + var qualifiers packageurl.Qualifiers + + if m.HostedURL != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "hosted_url", + Value: m.HostedURL, + }) + } else if m.VcsURL != "" { // Default to using Hosted if somehow both are provided + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "vcs_url", + Value: m.VcsURL, + }) + } + + return packageurl.NewPackageURL( + packageurl.TypePub, + "", + m.Name, + m.Version, + qualifiers, + "", + ).ToString() +} diff --git a/syft/pkg/language.go b/syft/pkg/language.go index 42e96b7ab43..b4b3734a363 100644 --- a/syft/pkg/language.go +++ b/syft/pkg/language.go @@ -19,6 +19,7 @@ const ( Ruby Language = "ruby" Go Language = "go" Rust Language = "rust" + Dart Language = "dart" ) // AllLanguages is a set of all programming languages detected by syft. @@ -30,6 +31,7 @@ var AllLanguages = []Language{ Ruby, Go, Rust, + Dart, } // String returns the string representation of the language. @@ -62,6 +64,8 @@ func LanguageByName(name string) Language { return Ruby case purlCargoPkgType: return Rust + case packageurl.TypePub, string(Dart): + return Dart default: return UnknownLanguage } diff --git a/syft/pkg/language_test.go b/syft/pkg/language_test.go index f2989c37a8b..2e1d5bc9abe 100644 --- a/syft/pkg/language_test.go +++ b/syft/pkg/language_test.go @@ -1,9 +1,10 @@ package pkg import ( + "testing" + "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" - "testing" ) func TestLanguageFromPURL(t *testing.T) { @@ -29,6 +30,10 @@ func TestLanguageFromPURL(t *testing.T) { purl: "pkg:golang/github.com/gorilla/context@234fd47e07d1004f0aed9c", want: Go, }, + { + purl: "pkg:pub/util@1.2.34", + want: Dart, + }, { purl: "pkg:cargo/clap@2.33.0", want: Rust, diff --git a/syft/pkg/metadata.go b/syft/pkg/metadata.go index 10c86bdfe90..efd11e3b026 100644 --- a/syft/pkg/metadata.go +++ b/syft/pkg/metadata.go @@ -17,6 +17,7 @@ const ( JavaMetadataType MetadataType = "JavaMetadata" NpmPackageJSONMetadataType MetadataType = "NpmPackageJsonMetadata" RpmdbMetadataType MetadataType = "RpmdbMetadata" + DartPubMetadataType MetadataType = "DartPubMetadata" PythonPackageMetadataType MetadataType = "PythonPackageMetadata" RustCargoPackageMetadataType MetadataType = "RustCargoPackageMetadata" KbPackageMetadataType MetadataType = "KbPackageMetadata" @@ -31,6 +32,7 @@ var AllMetadataTypes = []MetadataType{ JavaMetadataType, NpmPackageJSONMetadataType, RpmdbMetadataType, + DartPubMetadataType, PythonPackageMetadataType, RustCargoPackageMetadataType, KbPackageMetadataType, @@ -45,6 +47,7 @@ var MetadataTypeByName = map[MetadataType]reflect.Type{ JavaMetadataType: reflect.TypeOf(JavaMetadata{}), NpmPackageJSONMetadataType: reflect.TypeOf(NpmPackageJSONMetadata{}), RpmdbMetadataType: reflect.TypeOf(RpmdbMetadata{}), + DartPubMetadataType: reflect.TypeOf(DartPubMetadata{}), PythonPackageMetadataType: reflect.TypeOf(PythonPackageMetadata{}), RustCargoPackageMetadataType: reflect.TypeOf(CargoMetadata{}), KbPackageMetadataType: reflect.TypeOf(KbPackageMetadata{}), diff --git a/syft/pkg/type.go b/syft/pkg/type.go index 396faf522da..ffa965bb958 100644 --- a/syft/pkg/type.go +++ b/syft/pkg/type.go @@ -20,6 +20,7 @@ const ( GoModulePkg Type = "go-module" RustPkg Type = "rust-crate" KbPkg Type = "msrc-kb" + DartPubPkg Type = "dart-pub" ) // AllPkgs represents all supported package types @@ -36,6 +37,7 @@ var AllPkgs = []Type{ GoModulePkg, RustPkg, KbPkg, + DartPubPkg, } // PackageURLType returns the PURL package type for the current package. @@ -61,6 +63,8 @@ func (t Type) PackageURLType() string { return packageurl.TypeGolang case RustPkg: return "cargo" + case DartPubPkg: + return packageurl.TypePub default: // TODO: should this be a "generic" purl type instead? return "" @@ -98,6 +102,8 @@ func TypeByName(name string) Type { return GemPkg case "cargo", "crate": return RustPkg + case packageurl.TypePub: + return DartPubPkg default: return UnknownPkg } diff --git a/syft/pkg/type_test.go b/syft/pkg/type_test.go index d5f5bc3e40b..ade1f0913c1 100644 --- a/syft/pkg/type_test.go +++ b/syft/pkg/type_test.go @@ -1,9 +1,10 @@ package pkg import ( - "github.com/scylladb/go-set/strset" "testing" + "github.com/scylladb/go-set/strset" + "github.com/stretchr/testify/assert" ) @@ -46,6 +47,10 @@ func TestTypeFromPURL(t *testing.T) { purl: "pkg:cargo/clap@2.33.0", expected: RustPkg, }, + { + purl: "pkg:pub/util@1.2.34?hosted_url=pub.hosted.org", + expected: DartPubPkg, + }, { purl: "pkg:composer/laravel/laravel@5.5.0", expected: PhpComposerPkg, diff --git a/syft/pkg/url_test.go b/syft/pkg/url_test.go index dad951b6ba9..7d1ca3381e4 100644 --- a/syft/pkg/url_test.go +++ b/syft/pkg/url_test.go @@ -25,6 +25,20 @@ func TestPackageURL(t *testing.T) { }, expected: "pkg:golang/github.com/anchore/syft@v0.1.0", }, + { + name: "pub", + pkg: Package{ + Name: "bad-name", + Version: "0.1.0", + Type: DartPubPkg, + Metadata: DartPubMetadata{ + Name: "name", + Version: "0.2.0", + HostedURL: "pub.hosted.org", + }, + }, + expected: "pkg:pub/name@0.2.0?hosted_url=pub.hosted.org", + }, { name: "python", pkg: Package{ diff --git a/test/integration/catalog_packages_cases_test.go b/test/integration/catalog_packages_cases_test.go index 82aa81a26ff..8d566afcb86 100644 --- a/test/integration/catalog_packages_cases_test.go +++ b/test/integration/catalog_packages_cases_test.go @@ -186,6 +186,19 @@ var dirOnlyTestCases = []testCase{ "alcaeus/mongo-php-adapter": "1.1.11", }, }, + { + name: "find pubspec lock packages", + pkgType: pkg.DartPubPkg, + pkgLanguage: pkg.Dart, + pkgInfo: map[string]string{ + "ansicolor": "1.1.1", + "archive": "2.0.13", + "args": "1.6.0", + "key_binder": "1.11.20", + "ale": "3.3.0", + "analyzer": "0.40.7", + }, + }, } var commonTestCases = []testCase{ diff --git a/test/integration/catalog_packages_test.go b/test/integration/catalog_packages_test.go index b069a5cab09..ade886512e2 100644 --- a/test/integration/catalog_packages_test.go +++ b/test/integration/catalog_packages_test.go @@ -1,9 +1,10 @@ package integration import ( - "github.com/stretchr/testify/require" "testing" + "github.com/stretchr/testify/require" + "github.com/anchore/syft/syft/linux" "github.com/anchore/syft/syft/pkg/cataloger" "github.com/google/go-cmp/cmp" @@ -64,6 +65,7 @@ func TestPkgCoverageImage(t *testing.T) { // for image scans we should not expect to see any of the following package types definedLanguages.Remove(pkg.Go.String()) definedLanguages.Remove(pkg.Rust.String()) + definedLanguages.Remove(pkg.Dart.String()) observedPkgs := internal.NewStringSet() definedPkgs := internal.NewStringSet() @@ -75,6 +77,7 @@ func TestPkgCoverageImage(t *testing.T) { definedPkgs.Remove(string(pkg.KbPkg)) definedPkgs.Remove(string(pkg.GoModulePkg)) definedPkgs.Remove(string(pkg.RustPkg)) + definedPkgs.Remove(string(pkg.DartPubPkg)) var cases []testCase cases = append(cases, commonTestCases...) diff --git a/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock b/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock new file mode 100644 index 00000000000..c7b912f1aef --- /dev/null +++ b/test/integration/test-fixtures/image-pkg-coverage/pkgs/dart/pubspec.lock @@ -0,0 +1,49 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + ale: + dependency: transitive + description: + name: ale + url: "https://pub.hosted.org" + source: hosted + version: "3.3.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.40.7" + ansicolor: + dependency: transitive + description: + name: ansicolor + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.0" + key_binder: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "3f7b3a6350e73c7dcac45301c0e18fbd42af02f7" + url: "git@github.com:Workiva/key_binder.git" + source: git + version: "1.11.20" +sdks: + dart: ">=2.12.0 <3.0.0" From f24bbc1838351e4e408368f3312c76db6552e71e Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 31 Mar 2022 15:45:51 -0400 Subject: [PATCH 10/31] Deduplicate packages across multiple container image layers (#930) --- internal/anchore/import_package_sbom_test.go | 6 +- .../common/cyclonedxhelpers/component.go | 14 +- .../common/cyclonedxhelpers/component_test.go | 6 +- .../formats/common/spdxhelpers/source_info.go | 2 +- .../common/spdxhelpers/source_info_test.go | 4 +- internal/formats/common/testutils/utils.go | 16 +- internal/formats/github/encoder.go | 10 +- internal/formats/github/encoder_test.go | 36 ++- .../TestSPDXJSONDirectoryEncoder.golden | 10 +- .../snapshot/TestSPDXJSONImageEncoder.golden | 10 +- .../stereoscope-fixture-image-simple.golden | Bin 15360 -> 15360 bytes .../TestSPDXTagValueDirectoryEncoder.golden | 8 +- .../TestSPDXTagValueImageEncoder.golden | 8 +- internal/formats/syftjson/encoder_test.go | 12 +- .../snapshot/TestDirectoryEncoder.golden | 4 +- .../TestEncodeFullJSONDocument.golden | 4 +- .../snapshot/TestImageEncoder.golden | 4 +- internal/formats/syftjson/to_format_model.go | 5 +- internal/formats/syftjson/to_syft_model.go | 5 +- syft/pkg/catalog.go | 89 +++++- syft/pkg/catalog_test.go | 160 ++++++++-- syft/pkg/cataloger/common/cpe/filter_test.go | 26 +- syft/pkg/cataloger/common/cpe/generate.go | 2 +- .../pkg/cataloger/common/generic_cataloger.go | 3 +- .../common/generic_cataloger_test.go | 2 +- syft/pkg/cataloger/deb/cataloger.go | 6 +- syft/pkg/cataloger/deb/cataloger_test.go | 11 +- syft/pkg/cataloger/golang/parse_go_bin.go | 14 +- .../pkg/cataloger/golang/parse_go_bin_test.go | 38 +-- .../pkg/cataloger/python/package_cataloger.go | 2 +- .../python/package_cataloger_test.go | 2 +- .../python/parse_pipfile_lock_test.go | 10 +- .../python/parse_requirements_test.go | 10 +- syft/pkg/cataloger/python/parse_setup_test.go | 10 +- syft/pkg/cataloger/rpmdb/parse_rpmdb.go | 2 +- syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go | 4 +- ...y_specificity.go => cpe_by_specificity.go} | 12 +- ...ity_test.go => cpe_by_specificity_test.go} | 36 +-- syft/pkg/java_metadata.go | 2 +- syft/pkg/merge_cpes.go | 25 ++ syft/pkg/package.go | 42 ++- syft/pkg/package_test.go | 298 ++++++++++++++++-- .../relationships_by_file_ownership_test.go | 24 +- syft/source/coordinate_set.go | 86 +++++ syft/source/coordinate_set_test.go | 117 +++++++ syft/source/coordinates.go | 47 --- syft/source/coordinates_test.go | 51 --- syft/source/location.go | 6 + syft/source/location_set.go | 78 +++++ syft/source/location_set_test.go | 178 +++++++++++ syft/source/locations.go | 21 ++ test/cli/packages_cmd_test.go | 22 +- .../image-hidden-packages/Dockerfile | 4 + test/integration/catalog_packages_test.go | 2 +- test/integration/distro_test.go | 3 +- test/integration/encode_decode_cycle_test.go | 22 +- test/integration/node_packages_test.go | 4 +- .../integration/package_deduplication_test.go | 84 +++++ .../package_ownership_relationship_test.go | 3 +- ...regression_apk_scanner_buffer_size_test.go | 3 +- .../regression_go_bin_scanner_arch_test.go | 5 +- .../regression_java_no_main_package_test.go | 3 +- .../image-vertical-package-dups/Dockerfile | 6 + test/integration/utils_test.go | 4 +- 64 files changed, 1365 insertions(+), 378 deletions(-) rename syft/pkg/{cataloger/common/cpe/sort_by_specificity.go => cpe_by_specificity.go} (84%) rename syft/pkg/{cataloger/common/cpe/sort_by_specificity_test.go => cpe_by_specificity_test.go} (87%) create mode 100644 syft/pkg/merge_cpes.go create mode 100644 syft/source/coordinate_set.go create mode 100644 syft/source/coordinate_set_test.go delete mode 100644 syft/source/coordinates_test.go create mode 100644 syft/source/location_set.go create mode 100644 syft/source/location_set_test.go create mode 100644 syft/source/locations.go create mode 100644 test/cli/test-fixtures/image-hidden-packages/Dockerfile create mode 100644 test/integration/package_deduplication_test.go create mode 100644 test/integration/test-fixtures/image-vertical-package-dups/Dockerfile diff --git a/internal/anchore/import_package_sbom_test.go b/internal/anchore/import_package_sbom_test.go index c6939c91f87..3628a07c482 100644 --- a/internal/anchore/import_package_sbom_test.go +++ b/internal/anchore/import_package_sbom_test.go @@ -56,14 +56,14 @@ func sbomFixture() sbom.SBOM { Name: "name", Version: "version", FoundBy: "foundBy", - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "path", FileSystemID: "layerID", }, }, - }, + ), Licenses: []string{"license"}, Language: pkg.Python, Type: pkg.PythonPkg, diff --git a/internal/formats/common/cyclonedxhelpers/component.go b/internal/formats/common/cyclonedxhelpers/component.go index 0815fff1633..949d6d004d0 100644 --- a/internal/formats/common/cyclonedxhelpers/component.go +++ b/internal/formats/common/cyclonedxhelpers/component.go @@ -13,8 +13,9 @@ import ( func encodeComponent(p pkg.Package) cyclonedx.Component { props := encodeProperties(p, "syft:package") props = append(props, encodeCPEs(p)...) - if len(p.Locations) > 0 { - props = append(props, encodeProperties(p.Locations, "syft:location")...) + locations := p.Locations.ToSlice() + if len(locations) > 0 { + props = append(props, encodeProperties(locations, "syft:location")...) } if hasMetadata(p) { props = append(props, encodeProperties(p.Metadata, "syft:metadata")...) @@ -73,10 +74,13 @@ func decodeComponent(c *cyclonedx.Component) *pkg.Package { return p } -func decodeLocations(vals map[string]string) []source.Location { +func decodeLocations(vals map[string]string) source.LocationSet { v := common.Decode(reflect.TypeOf([]source.Location{}), vals, "syft:location", CycloneDXFields) - out, _ := v.([]source.Location) - return out + out, ok := v.([]source.Location) + if !ok { + out = nil + } + return source.NewLocationSet(out...) } func decodePackageMetadata(vals map[string]string, c *cyclonedx.Component, typ pkg.MetadataType) interface{} { diff --git a/internal/formats/common/cyclonedxhelpers/component_test.go b/internal/formats/common/cyclonedxhelpers/component_test.go index b267abe6d6c..4a6dc50518a 100644 --- a/internal/formats/common/cyclonedxhelpers/component_test.go +++ b/internal/formats/common/cyclonedxhelpers/component_test.go @@ -26,9 +26,9 @@ func Test_encodeComponentProperties(t *testing.T) { name: "from apk", input: pkg.Package{ FoundBy: "cataloger", - Locations: []source.Location{ - {Coordinates: source.Coordinates{RealPath: "test"}}, - }, + Locations: source.NewLocationSet( + source.Location{Coordinates: source.Coordinates{RealPath: "test"}}, + ), Metadata: pkg.ApkMetadata{ Package: "libc-utils", OriginPackage: "libc-dev", diff --git a/internal/formats/common/spdxhelpers/source_info.go b/internal/formats/common/spdxhelpers/source_info.go index ed5e2600b41..1806f72dfb1 100644 --- a/internal/formats/common/spdxhelpers/source_info.go +++ b/internal/formats/common/spdxhelpers/source_info.go @@ -35,7 +35,7 @@ func SourceInfo(p pkg.Package) string { answer = "acquired package info from the following paths" } var paths []string - for _, l := range p.Locations { + for _, l := range p.Locations.ToSlice() { paths = append(paths, l.RealPath) } diff --git a/internal/formats/common/spdxhelpers/source_info_test.go b/internal/formats/common/spdxhelpers/source_info_test.go index 56f6c5bbdbb..4016ad2be51 100644 --- a/internal/formats/common/spdxhelpers/source_info_test.go +++ b/internal/formats/common/spdxhelpers/source_info_test.go @@ -18,10 +18,10 @@ func Test_SourceInfo(t *testing.T) { name: "locations are captured", input: pkg.Package{ // note: no type given - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/a-place", "/b-place"), source.NewVirtualLocation("/c-place", "/d-place"), - }, + ), }, expected: []string{ "from the following paths", diff --git a/internal/formats/common/testutils/utils.go b/internal/formats/common/testutils/utils.go index 6b5b5f6701a..809889456cb 100644 --- a/internal/formats/common/testutils/utils.go +++ b/internal/formats/common/testutils/utils.go @@ -157,9 +157,9 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) { catalog.Add(pkg.Package{ Name: "package-1", Version: "1.0.1", - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewLocationFromImage(string(ref1.RealPath), *ref1, img), - }, + ), Type: pkg.PythonPkg, FoundBy: "the-cataloger-1", Language: pkg.Python, @@ -177,9 +177,9 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) { catalog.Add(pkg.Package{ Name: "package-2", Version: "2.0.1", - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewLocationFromImage(string(ref2.RealPath), *ref2, img), - }, + ), Type: pkg.DebPkg, FoundBy: "the-cataloger-2", MetadataType: pkg.DpkgMetadataType, @@ -234,9 +234,9 @@ func newDirectoryCatalog() *pkg.Catalog { Version: "1.0.1", Type: pkg.PythonPkg, FoundBy: "the-cataloger-1", - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewLocation("/some/path/pkg1"), - }, + ), Language: pkg.Python, MetadataType: pkg.PythonPackageMetadataType, Licenses: []string{"MIT"}, @@ -259,9 +259,9 @@ func newDirectoryCatalog() *pkg.Catalog { Version: "2.0.1", Type: pkg.DebPkg, FoundBy: "the-cataloger-2", - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewLocation("/some/path/pkg1"), - }, + ), MetadataType: pkg.DpkgMetadataType, Metadata: pkg.DpkgMetadata{ Package: "package-2", diff --git a/internal/formats/github/encoder.go b/internal/formats/github/encoder.go index 967c87e643f..2e39f7c102a 100644 --- a/internal/formats/github/encoder.go +++ b/internal/formats/github/encoder.go @@ -58,8 +58,9 @@ func toSnapshotMetadata(s *sbom.SBOM) Metadata { } func filesystem(p pkg.Package) string { - if len(p.Locations) > 0 { - return p.Locations[0].FileSystemID + locations := p.Locations.ToSlice() + if len(locations) > 0 { + return locations[0].FileSystemID } return "" } @@ -76,8 +77,9 @@ func toPath(s source.Metadata, p pkg.Package) string { if inputPath == "." { inputPath = "" } - if len(p.Locations) > 0 { - location := p.Locations[0] + locations := p.Locations.ToSlice() + if len(locations) > 0 { + location := locations[0] packagePath := location.RealPath if location.VirtualPath != "" { packagePath = location.VirtualPath diff --git a/internal/formats/github/encoder_test.go b/internal/formats/github/encoder_test.go index a08f72ce4dc..91ac837692c 100644 --- a/internal/formats/github/encoder_test.go +++ b/internal/formats/github/encoder_test.go @@ -35,32 +35,38 @@ func Test_toGithubModel(t *testing.T) { { Name: "pkg-1", Version: "1.0.1", - Locations: []source.Location{{ - Coordinates: source.Coordinates{ - RealPath: "/usr/lib", - FileSystemID: "fsid-1", + Locations: source.NewLocationSet( + source.Location{ + Coordinates: source.Coordinates{ + RealPath: "/usr/lib", + FileSystemID: "fsid-1", + }, }, - }}, + ), }, { Name: "pkg-2", Version: "2.0.2", - Locations: []source.Location{{ - Coordinates: source.Coordinates{ - RealPath: "/usr/lib", - FileSystemID: "fsid-1", + Locations: source.NewLocationSet( + source.Location{ + Coordinates: source.Coordinates{ + RealPath: "/usr/lib", + FileSystemID: "fsid-1", + }, }, - }}, + ), }, { Name: "pkg-3", Version: "3.0.3", - Locations: []source.Location{{ - Coordinates: source.Coordinates{ - RealPath: "/etc", - FileSystemID: "fsid-1", + Locations: source.NewLocationSet( + source.Location{ + Coordinates: source.Coordinates{ + RealPath: "/etc", + FileSystemID: "fsid-1", + }, }, - }}, + ), }, } { p.PURL = packageurl.NewPackageURL( diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden index c0eb44cd3d8..22f7729c7e3 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden @@ -3,18 +3,18 @@ "name": "/some/path", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-12-20T19:12:47.869816Z", + "created": "2022-03-30T21:48:28.297464Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" ], - "licenseListVersion": "3.15" + "licenseListVersion": "3.16" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/dir/some/path-4b896ded-7852-4e31-b764-136b53bdf346", + "documentNamespace": "https://anchore.com/syft/dir/some/path-e188d59b-76f6-4c7f-a9f2-1ae7d0577781", "packages": [ { - "SPDXID": "SPDXRef-1d97af55efe9512f", + "SPDXID": "SPDXRef-b85dbb4e6ece5082", "name": "package-1", "licenseConcluded": "MIT", "downloadLocation": "NOASSERTION", @@ -36,7 +36,7 @@ "versionInfo": "1.0.1" }, { - "SPDXID": "SPDXRef-ad3d1c4abd84bf75", + "SPDXID": "SPDXRef-ceda99598967ae8d", "name": "package-2", "licenseConcluded": "NONE", "downloadLocation": "NOASSERTION", diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden index e44ef6cf131..7e97a75fe97 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden @@ -3,18 +3,18 @@ "name": "user-image-input", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2021-12-20T19:13:07.647486Z", + "created": "2022-03-30T21:48:28.303986Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" ], - "licenseListVersion": "3.15" + "licenseListVersion": "3.16" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input-174da656-1824-4bd3-8604-28919f8a65bc", + "documentNamespace": "https://anchore.com/syft/image/user-image-input-9e4f4190-c5ae-4e31-a852-d1ab71357516", "packages": [ { - "SPDXID": "SPDXRef-d16127444133b5c1", + "SPDXID": "SPDXRef-2a46171f91c8d4bc", "name": "package-1", "licenseConcluded": "MIT", "downloadLocation": "NOASSERTION", @@ -36,7 +36,7 @@ "versionInfo": "1.0.1" }, { - "SPDXID": "SPDXRef-24907357f3705420", + "SPDXID": "SPDXRef-ae77680e9b1d087e", "name": "package-2", "licenseConcluded": "NONE", "downloadLocation": "NOASSERTION", diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/formats/spdx22json/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index c483fa49b75941b2cfb6a6819ff94a681f25ee41..c1b1d2b797ecd34a5276a1aa2fb18c5b0a58c732 100644 GIT binary patch literal 15360 zcmeHO+iu%N5Y=ZaKc z4r#BxuDkuJ7{OBcm#%FzyUOYr8lw^9HIDjR+4F_Fg0dOV`$VGKgH38I>Hgnpur)R2 zl)HY_XM^MD!m4A0dKhDcAS?&*f(4T;Kn>ke#l4gzVN` ze(?Rjwf#RFzkC1s- z9>CiEk8VKl|Mzk`OrxxEw%gtY==qIJx$uy+*ED8?qX(EcDL{I387Ngsb4dh?x$wg9 z*h*rg6@ZQ(w@kA*(GHyphO!?TNJz`YJ>fe4rt;(!W2awfa(sRRC68dzXajVE@y-n>o(^op5E2ZJDVs7 z4hRGU0s;YnXN7=m8LaJu|D{?6{&zpONo)J>g#RTf@W1=9f8c-jgY$EprS<=wcn6J zY-{-4@PCvC{%=1g#vT7ROM=?XoSXT-=K0?$|A*;W&6n z=@JS7fq+0jARzERL||m{EQP9mOdkK&{`^hnzm$9>7qof)M_D-kzZUPOjKl2tmy1l1 zh;8Ft5R3%h!MHdz7xT>W8cHZCSB&8>&90l53=Xp<>E*D>M<2Vo8*8l9D*K-ZL#y zZQ=xy1TbwlA*sSvk$`4t>Jlk6(avMSc$^Yo%t_n4Rq$q>(~gPk+Y4v#cWf^=0@K;g zetL>o_SUyVTU8mpNs&Rdt4TMle|Dc6KFbBi^{-S||GP5Biri^bZCIhryCba^=@v2! WZ*QOH3R;0P6aoSPfq=kwgTOxo35itz literal 15360 zcmeHOZExE)5ccQ&3Xl7m*nFpCU>~xkKnoO0(Pka6pa>|wBwB6BkmRC4kpI4u>^N?+ zMoXlq8A`!`M3Fq5?szos;UhwsawN7!<0N9G_Y)S?;cIte-{TyY9lK0QOTOY|x)t4uE(r~oYv^93}xDgRNrVqJ4kRoa}tuWXv3 znb-5u?V;_xd{y1O=?dt&X?a{-Y_E@&F8f+eQ##5FD6wh(GW(2X*=j!DLoXKaM(fMh z3w^dx^g}*hEnInB^JiXsO0%=WbffLdtST;+d76P<>%K?XZ>w~^74=3ZZocV$wTE)J zMDsLTeL+_(vD9~USI1B1`oa~HdJXl>qb2_N-Sr<)M1}bOra^nGDD#E$>D=v;N%f`b zQSgqa7XM>R<#ztZoQyCbip${t9TPs;Wp$pG<9Yy$&viMjr)ZZ|<&!-w2o4qq76=vy z7I-EWkXR;>QJOjuMLGc>kW#?ll#rO}NXN`L>ZPLE8N%UAW9PMHF&D;L?a342f1pFa z|ArVMo&Enb_#X}V{}A3EjYz=%hB5RreM;x}?~eb~8$a9pZ@vFR2n+cCAR}gj|8*S( z0NyQi0jXo(SR#eZ$9+O;ERoO|VKdGq91|839x%oGFvb4`#(IL@9vr{=b-F5x={z@j zJ}r|po9&dh#hZ%e*18Cn=;LER+9?d!hoZE)Fz0FIOtmU%7+5c?qS?n;^+;|qdNe}ryWq0_0 zkoJZ3-w>nc5`81Bxyc_JHcU^M+E+}OItlxV7z0$88x~PZ<`4VURbBwE=j5`b6XQ%W zP8+yj%~3i{pdUIoJZyHp*VKpcbh{L8s1V~{#z{@t`IJ_mrpXtJHM((qb7FJz$rbhb zY4RDPtGzZgc2SFeRijyf@2IgZKTr+GhIbOuJyhg*<$+#wiK>fbowhc7of2Njrrw{X z7V1t=d9JCDGa{Yjf)fuEZ!cmUW58LAQ%MqO4+X-!vP>~g2^KbrJhO~Sl_=`4OLPKK zH?k!Nsqw!zH3zYITz_;%c#rJBV1ZzP JV1eE(@DIZvjQs!r diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden index 84a7de316a7..7959c2f0d34 100644 --- a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden @@ -2,16 +2,16 @@ SPDXVersion: SPDX-2.2 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: /some/path -DocumentNamespace: https://anchore.com/syft/dir/some/path-4b90f56d-d596-4ad8-b6a5-17f7d801350d +DocumentNamespace: https://anchore.com/syft/dir/some/path-71aa3553-1a73-405f-9f1f-6347d6d4593b LicenseListVersion: 3.16 Creator: Organization: Anchore, Inc Creator: Tool: syft-[not provided] -Created: 2022-02-10T21:09:27Z +Created: 2022-03-30T21:48:22Z ##### Package: package-2 PackageName: package-2 -SPDXID: SPDXRef-Package-deb-package-2-ad3d1c4abd84bf75 +SPDXID: SPDXRef-Package-deb-package-2-ceda99598967ae8d PackageVersion: 2.0.1 PackageDownloadLocation: NOASSERTION FilesAnalyzed: false @@ -24,7 +24,7 @@ ExternalRef: PACKAGE_MANAGER purl a-purl-2 ##### Package: package-1 PackageName: package-1 -SPDXID: SPDXRef-Package-python-package-1-1d97af55efe9512f +SPDXID: SPDXRef-Package-python-package-1-b85dbb4e6ece5082 PackageVersion: 1.0.1 PackageDownloadLocation: NOASSERTION FilesAnalyzed: false diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden index f54713441c9..4d9011b1cdd 100644 --- a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden @@ -2,16 +2,16 @@ SPDXVersion: SPDX-2.2 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: user-image-input -DocumentNamespace: https://anchore.com/syft/image/user-image-input-26a2def6-53d0-4504-b99a-a046832508ac +DocumentNamespace: https://anchore.com/syft/image/user-image-input-e46e20f4-43a4-40e7-9f82-fd55b8a89e5f LicenseListVersion: 3.16 Creator: Organization: Anchore, Inc Creator: Tool: syft-[not provided] -Created: 2022-02-10T21:09:27Z +Created: 2022-03-30T21:48:22Z ##### Package: package-2 PackageName: package-2 -SPDXID: SPDXRef-Package-deb-package-2-73f796c846875b9e +SPDXID: SPDXRef-Package-deb-package-2-ae77680e9b1d087e PackageVersion: 2.0.1 PackageDownloadLocation: NOASSERTION FilesAnalyzed: false @@ -24,7 +24,7 @@ ExternalRef: PACKAGE_MANAGER purl a-purl-2 ##### Package: package-1 PackageName: package-1 -SPDXID: SPDXRef-Package-python-package-1-d9527e708c11f8b9 +SPDXID: SPDXRef-Package-python-package-1-2a46171f91c8d4bc PackageVersion: 1.0.1 PackageDownloadLocation: NOASSERTION FilesAnalyzed: false diff --git a/internal/formats/syftjson/encoder_test.go b/internal/formats/syftjson/encoder_test.go index 10d2576caab..9d8087d5e84 100644 --- a/internal/formats/syftjson/encoder_test.go +++ b/internal/formats/syftjson/encoder_test.go @@ -42,13 +42,13 @@ func TestEncodeFullJSONDocument(t *testing.T) { p1 := pkg.Package{ Name: "package-1", Version: "1.0.1", - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a/place/a", }, }, - }, + ), Type: pkg.PythonPkg, FoundBy: "the-cataloger-1", Language: pkg.Python, @@ -68,13 +68,13 @@ func TestEncodeFullJSONDocument(t *testing.T) { p2 := pkg.Package{ Name: "package-2", Version: "2.0.1", - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/b/place/b", }, }, - }, + ), Type: pkg.DebPkg, FoundBy: "the-cataloger-2", MetadataType: pkg.DpkgMetadataType, diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden index 92b55b015fa..71d089e1947 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden @@ -1,7 +1,7 @@ { "artifacts": [ { - "id": "1d97af55efe9512f", + "id": "b85dbb4e6ece5082", "name": "package-1", "version": "1.0.1", "type": "python", @@ -36,7 +36,7 @@ } }, { - "id": "ad3d1c4abd84bf75", + "id": "ceda99598967ae8d", "name": "package-2", "version": "2.0.1", "type": "deb", diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden index 728667abdb7..2fe4ba0dcb7 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden @@ -1,7 +1,7 @@ { "artifacts": [ { - "id": "d9a7c58726ab4bef", + "id": "b3fa3ee64756b0c6", "name": "package-1", "version": "1.0.1", "type": "python", @@ -31,7 +31,7 @@ } }, { - "id": "ac462e450060da2c", + "id": "b324f4d9ee5413fe", "name": "package-2", "version": "2.0.1", "type": "deb", diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden index baa8ed26a87..a2f5673d096 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden @@ -1,7 +1,7 @@ { "artifacts": [ { - "id": "d9527e708c11f8b9", + "id": "2a46171f91c8d4bc", "name": "package-1", "version": "1.0.1", "type": "python", @@ -32,7 +32,7 @@ } }, { - "id": "73f796c846875b9e", + "id": "ae77680e9b1d087e", "name": "package-2", "version": "2.0.1", "type": "deb", diff --git a/internal/formats/syftjson/to_format_model.go b/internal/formats/syftjson/to_format_model.go index 7d4feee4af3..ccf881a0d9b 100644 --- a/internal/formats/syftjson/to_format_model.go +++ b/internal/formats/syftjson/to_format_model.go @@ -175,8 +175,9 @@ func toPackageModel(p pkg.Package) model.Package { licenses = p.Licenses } - var coordinates = make([]source.Coordinates, len(p.Locations)) - for i, l := range p.Locations { + locations := p.Locations.ToSlice() + var coordinates = make([]source.Coordinates, len(locations)) + for i, l := range locations { coordinates[i] = l.Coordinates } diff --git a/internal/formats/syftjson/to_syft_model.go b/internal/formats/syftjson/to_syft_model.go index c8a40eb93ef..bac4df94b24 100644 --- a/internal/formats/syftjson/to_syft_model.go +++ b/internal/formats/syftjson/to_syft_model.go @@ -53,7 +53,8 @@ func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationship for _, p := range catalog.Sorted() { idMap[string(p.ID())] = p - for _, l := range p.Locations { + locations := p.Locations.ToSlice() + for _, l := range locations { idMap[string(l.Coordinates.ID())] = l.Coordinates } } @@ -166,7 +167,7 @@ func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package { Name: p.Name, Version: p.Version, FoundBy: p.FoundBy, - Locations: locations, + Locations: source.NewLocationSet(locations...), Licenses: p.Licenses, Language: p.Language, Type: p.Type, diff --git a/syft/pkg/catalog.go b/syft/pkg/catalog.go index 1c8e8db56e0..0e4d1098e2c 100644 --- a/syft/pkg/catalog.go +++ b/syft/pkg/catalog.go @@ -10,11 +10,28 @@ import ( "github.com/jinzhu/copier" ) +type orderedIDSet struct { + slice []artifact.ID +} + +func (s *orderedIDSet) add(ids ...artifact.ID) { +loopNewIDs: + for _, newID := range ids { + for _, existingID := range s.slice { + if existingID == newID { + continue loopNewIDs + } + } + s.slice = append(s.slice, newID) + } +} + // Catalog represents a collection of Packages. type Catalog struct { byID map[artifact.ID]Package - idsByType map[Type][]artifact.ID - idsByPath map[string][]artifact.ID // note: this is real path or virtual path + idsByName map[string]orderedIDSet + idsByType map[Type]orderedIDSet + idsByPath map[string]orderedIDSet // note: this is real path or virtual path lock sync.RWMutex } @@ -22,8 +39,9 @@ type Catalog struct { func NewCatalog(pkgs ...Package) *Catalog { catalog := Catalog{ byID: make(map[artifact.ID]Package), - idsByType: make(map[Type][]artifact.ID), - idsByPath: make(map[string][]artifact.ID), + idsByName: make(map[string]orderedIDSet), + idsByType: make(map[Type]orderedIDSet), + idsByPath: make(map[string]orderedIDSet), } for _, p := range pkgs { @@ -55,7 +73,12 @@ func (c *Catalog) Package(id artifact.ID) *Package { // PackagesByPath returns all packages that were discovered from the given path. func (c *Catalog) PackagesByPath(path string) []Package { - return c.Packages(c.idsByPath[path]) + return c.Packages(c.idsByPath[path].slice) +} + +// PackagesByName returns all packages that were discovered with a matching name. +func (c *Catalog) PackagesByName(name string) []Package { + return c.Packages(c.idsByName[name].slice) } // Packages returns all packages for the given ID. @@ -81,26 +104,58 @@ func (c *Catalog) Add(p Package) { id = p.ID() } - // store by package ID - c.byID[id] = p + if existing, exists := c.byID[id]; exists { + // there is already a package with this fingerprint merge the existing record with the new one + if err := existing.merge(p); err != nil { + log.Warnf("failed to merge packages: %+v", err) + } else { + c.addPathsToIndex(p) + } + return + } + + c.addToIndex(p) +} + +func (c *Catalog) addToIndex(p Package) { + c.byID[p.id] = p + c.addNameToIndex(p) + c.addTypeToIndex(p) + c.addPathsToIndex(p) +} + +func (c *Catalog) addNameToIndex(p Package) { + nameIndex := c.idsByName[p.Name] + nameIndex.add(p.id) + c.idsByName[p.Name] = nameIndex +} - // store by package type - c.idsByType[p.Type] = append(c.idsByType[p.Type], id) +func (c *Catalog) addTypeToIndex(p Package) { + typeIndex := c.idsByType[p.Type] + typeIndex.add(p.id) + c.idsByType[p.Type] = typeIndex +} - // store by file location paths +func (c *Catalog) addPathsToIndex(p Package) { observedPaths := internal.NewStringSet() - for _, l := range p.Locations { + for _, l := range p.Locations.ToSlice() { if l.RealPath != "" && !observedPaths.Contains(l.RealPath) { - c.idsByPath[l.RealPath] = append(c.idsByPath[l.RealPath], id) + c.addPathToIndex(p.id, l.RealPath) observedPaths.Add(l.RealPath) } if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Contains(l.VirtualPath) { - c.idsByPath[l.VirtualPath] = append(c.idsByPath[l.VirtualPath], id) + c.addPathToIndex(p.id, l.VirtualPath) observedPaths.Add(l.VirtualPath) } } } +func (c *Catalog) addPathToIndex(id artifact.ID, path string) { + pathIndex := c.idsByPath[path] + pathIndex.add(id) + c.idsByPath[path] = pathIndex +} + // Enumerate all packages for the given type(s), enumerating all packages if no type is specified. func (c *Catalog) Enumerate(types ...Type) <-chan Package { channel := make(chan Package) @@ -124,7 +179,7 @@ func (c *Catalog) Enumerate(types ...Type) <-chan Package { continue } } - for _, id := range ids { + for _, id := range ids.slice { p := c.Package(id) if p != nil { channel <- *p @@ -145,8 +200,10 @@ func (c *Catalog) Sorted(types ...Type) (pkgs []Package) { sort.SliceStable(pkgs, func(i, j int) bool { if pkgs[i].Name == pkgs[j].Name { if pkgs[i].Version == pkgs[j].Version { - if pkgs[i].Type == pkgs[j].Type && len(pkgs[i].Locations) > 0 && len(pkgs[j].Locations) > 0 { - return pkgs[i].Locations[0].String() < pkgs[j].Locations[0].String() + iLocations := pkgs[i].Locations.ToSlice() + jLocations := pkgs[j].Locations.ToSlice() + if pkgs[i].Type == pkgs[j].Type && len(iLocations) > 0 && len(jLocations) > 0 { + return iLocations[0].String() < jLocations[0].String() } return pkgs[i].Type < pkgs[j].Type } diff --git a/syft/pkg/catalog_test.go b/syft/pkg/catalog_test.go index 005714c0c45..43f52b87bd1 100644 --- a/syft/pkg/catalog_test.go +++ b/syft/pkg/catalog_test.go @@ -3,11 +3,11 @@ package pkg import ( "testing" - "github.com/stretchr/testify/assert" - - "github.com/scylladb/go-set/strset" - + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/source" + "github.com/scylladb/go-set/strset" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type expectedIndexes struct { @@ -19,17 +19,17 @@ func TestCatalogAddPopulatesIndex(t *testing.T) { var pkgs = []Package{ { - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/a/path", "/another/path"), source.NewVirtualLocation("/b/path", "/bee/path"), - }, + ), Type: RpmPkg, }, { - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/c/path", "/another/path"), source.NewVirtualLocation("/d/path", "/another/path"), - }, + ), Type: NpmPkg, }, } @@ -106,47 +106,169 @@ func assertIndexes(t *testing.T, c *Catalog, expectedIndexes expectedIndexes) { func TestCatalog_PathIndexDeduplicatesRealVsVirtualPaths(t *testing.T) { p1 := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/b/path", "/another/path"), source.NewVirtualLocation("/b/path", "/b/path"), - }, + ), Type: RpmPkg, Name: "Package-1", } p2 := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/b/path", "/b/path"), - }, + ), Type: RpmPkg, Name: "Package-2", } + p2Dup := Package{ + Locations: source.NewLocationSet( + source.NewVirtualLocation("/b/path", "/another/path"), + source.NewVirtualLocation("/b/path", "/c/path/b/dup"), + ), + Type: RpmPkg, + Name: "Package-2", + } + tests := []struct { - name string - pkg Package + name string + pkgs []Package + paths []string }{ { name: "multiple locations with shared path", - pkg: p1, + pkgs: []Package{p1}, + paths: []string{ + "/b/path", + "/another/path", + }, }, { name: "one location with shared path", - pkg: p2, + pkgs: []Package{p2}, + paths: []string{ + "/b/path", + }, + }, + { + name: "two instances with similar locations", + pkgs: []Package{p2, p2Dup}, + paths: []string{ + "/b/path", + "/another/path", + "/c/path/b/dup", // this updated the path index on merge + }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - actual := NewCatalog(test.pkg).PackagesByPath("/b/path") - if len(actual) != 1 { - t.Errorf("expected exactly one package path, got %d", len(actual)) + for _, path := range test.paths { + actualPackages := NewCatalog(test.pkgs...).PackagesByPath(path) + require.Len(t, actualPackages, 1) } }) } } +func TestCatalog_MergeRecords(t *testing.T) { + var tests = []struct { + name string + pkgs []Package + expectedLocations []source.Location + }{ + { + name: "multiple Locations with shared path", + pkgs: []Package{ + { + Locations: source.NewLocationSet( + source.Location{ + Coordinates: source.Coordinates{ + RealPath: "/b/path", + FileSystemID: "a", + }, + VirtualPath: "/another/path", + }, + ), + Type: RpmPkg, + }, + { + Locations: source.NewLocationSet( + source.Location{ + Coordinates: source.Coordinates{ + RealPath: "/b/path", + FileSystemID: "b", + }, + VirtualPath: "/another/path", + }, + ), + Type: RpmPkg, + }, + }, + expectedLocations: []source.Location{ + { + Coordinates: source.Coordinates{ + RealPath: "/b/path", + FileSystemID: "a", + }, + VirtualPath: "/another/path", + }, + { + Coordinates: source.Coordinates{ + RealPath: "/b/path", + FileSystemID: "b", + }, + VirtualPath: "/another/path", + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := NewCatalog(tt.pkgs...).PackagesByPath("/b/path") + require.Len(t, actual, 1) + assert.Equal(t, tt.expectedLocations, actual[0].Locations.ToSlice()) + }) + } +} + func TestCatalog_EnumerateNilCatalog(t *testing.T) { var c *Catalog assert.Empty(t, c.Enumerate()) } + +func Test_idOrderedSet_add(t *testing.T) { + tests := []struct { + name string + input []artifact.ID + expected []artifact.ID + }{ + { + name: "elements deduplicated when added", + input: []artifact.ID{ + "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", + }, + expected: []artifact.ID{ + "1", "2", "3", "4", + }, + }, + { + name: "elements retain ordering when added", + input: []artifact.ID{ + "4", "3", "2", "1", + }, + expected: []artifact.ID{ + "4", "3", "2", "1", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var s orderedIDSet + s.add(tt.input...) + assert.Equal(t, tt.expected, s.slice) + }) + } +} diff --git a/syft/pkg/cataloger/common/cpe/filter_test.go b/syft/pkg/cataloger/common/cpe/filter_test.go index 6200093e04f..d57bc8b7215 100644 --- a/syft/pkg/cataloger/common/cpe/filter_test.go +++ b/syft/pkg/cataloger/common/cpe/filter_test.go @@ -16,7 +16,7 @@ func Test_disallowJenkinsServerCPEForPluginPackage(t *testing.T) { }{ { name: "go case (filter out)", - cpe: mustCPE("cpe:2.3:a:name:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:name:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Type: pkg.JenkinsPluginPkg, }, @@ -24,7 +24,7 @@ func Test_disallowJenkinsServerCPEForPluginPackage(t *testing.T) { }, { name: "ignore jenkins plugins with unique name", - cpe: mustCPE("cpe:2.3:a:name:ci-jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:name:ci-jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Type: pkg.JenkinsPluginPkg, }, @@ -32,7 +32,7 @@ func Test_disallowJenkinsServerCPEForPluginPackage(t *testing.T) { }, { name: "ignore java packages", - cpe: mustCPE("cpe:2.3:a:name:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:name:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Type: pkg.JavaPkg, }, @@ -55,7 +55,7 @@ func Test_disallowJenkinsCPEsNotAssociatedWithJenkins(t *testing.T) { }{ { name: "filter out mismatched name (cloudbees vendor)", - cpe: mustCPE("cpe:2.3:a:cloudbees:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:cloudbees:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "not-j*nkins", Type: pkg.JavaPkg, @@ -64,7 +64,7 @@ func Test_disallowJenkinsCPEsNotAssociatedWithJenkins(t *testing.T) { }, { name: "filter out mismatched name (jenkins vendor)", - cpe: mustCPE("cpe:2.3:a:jenkins:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:jenkins:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "not-j*nkins", Type: pkg.JavaPkg, @@ -73,7 +73,7 @@ func Test_disallowJenkinsCPEsNotAssociatedWithJenkins(t *testing.T) { }, { name: "filter out mismatched name (any vendor)", - cpe: mustCPE("cpe:2.3:a:*:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "not-j*nkins", Type: pkg.JavaPkg, @@ -82,7 +82,7 @@ func Test_disallowJenkinsCPEsNotAssociatedWithJenkins(t *testing.T) { }, { name: "ignore packages with the name jenkins", - cpe: mustCPE("cpe:2.3:a:*:jenkins:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jenkins:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "jenkins-thing", Type: pkg.JavaPkg, @@ -91,7 +91,7 @@ func Test_disallowJenkinsCPEsNotAssociatedWithJenkins(t *testing.T) { }, { name: "ignore product names that are not exactly 'jenkins'", - cpe: mustCPE("cpe:2.3:a:*:jenkins-something-else:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jenkins-something-else:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "not-j*nkins", Type: pkg.JavaPkg, @@ -115,7 +115,7 @@ func Test_disallowJiraClientServerMismatch(t *testing.T) { }{ { name: "filter out mismatched name (atlassian vendor)", - cpe: mustCPE("cpe:2.3:a:atlassian:jira:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:atlassian:jira:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "something-client", Type: pkg.JavaPkg, @@ -124,7 +124,7 @@ func Test_disallowJiraClientServerMismatch(t *testing.T) { }, { name: "filter out mismatched name (jira vendor)", - cpe: mustCPE("cpe:2.3:a:jira:jira:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:jira:jira:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "something-client", Type: pkg.JavaPkg, @@ -133,7 +133,7 @@ func Test_disallowJiraClientServerMismatch(t *testing.T) { }, { name: "filter out mismatched name (any vendor)", - cpe: mustCPE("cpe:2.3:a:*:jira:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jira:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "something-client", Type: pkg.JavaPkg, @@ -142,7 +142,7 @@ func Test_disallowJiraClientServerMismatch(t *testing.T) { }, { name: "ignore package names that do not have 'client'", - cpe: mustCPE("cpe:2.3:a:*:jira:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jira:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "jira-thing", Type: pkg.JavaPkg, @@ -151,7 +151,7 @@ func Test_disallowJiraClientServerMismatch(t *testing.T) { }, { name: "ignore product names that are not exactly 'jira'", - cpe: mustCPE("cpe:2.3:a:*:jira-something-else:3.2:*:*:*:*:*:*:*"), + cpe: pkg.MustCPE("cpe:2.3:a:*:jira-something-else:3.2:*:*:*:*:*:*:*"), pkg: pkg.Package{ Name: "not-j*ra", Type: pkg.JavaPkg, diff --git a/syft/pkg/cataloger/common/cpe/generate.go b/syft/pkg/cataloger/common/cpe/generate.go index f8360555df8..4ed77ff2b65 100644 --- a/syft/pkg/cataloger/common/cpe/generate.go +++ b/syft/pkg/cataloger/common/cpe/generate.go @@ -55,7 +55,7 @@ func Generate(p pkg.Package) []pkg.CPE { // filter out any known combinations that don't accurately represent this package cpes = filter(cpes, p, cpeFilters...) - sort.Sort(BySpecificity(cpes)) + sort.Sort(pkg.CPEBySpecificity(cpes)) return cpes } diff --git a/syft/pkg/cataloger/common/generic_cataloger.go b/syft/pkg/cataloger/common/generic_cataloger.go index 7d2e3d47740..859b77ef38f 100644 --- a/syft/pkg/cataloger/common/generic_cataloger.go +++ b/syft/pkg/cataloger/common/generic_cataloger.go @@ -58,9 +58,8 @@ func (c *GenericCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, for _, p := range discoveredPackages { p.FoundBy = c.upstreamCataloger - p.Locations = append(p.Locations, location) + p.Locations.Add(location) p.SetID() - packages = append(packages, *p) } diff --git a/syft/pkg/cataloger/common/generic_cataloger_test.go b/syft/pkg/cataloger/common/generic_cataloger_test.go index 68dfe6fd118..2e3a7234ac4 100644 --- a/syft/pkg/cataloger/common/generic_cataloger_test.go +++ b/syft/pkg/cataloger/common/generic_cataloger_test.go @@ -53,7 +53,7 @@ func TestGenericCataloger(t *testing.T) { assert.Len(t, actualPkgs, len(expectedPkgs)) for _, p := range actualPkgs { - ref := p.Locations[0] + ref := p.Locations.ToSlice()[0] exP, ok := expectedPkgs[ref.RealPath] if !ok { t.Errorf("missing expected pkg: ref=%+v", ref) diff --git a/syft/pkg/cataloger/deb/cataloger.go b/syft/pkg/cataloger/deb/cataloger.go index f0c3b3ea85b..4b9146fd73b 100644 --- a/syft/pkg/cataloger/deb/cataloger.go +++ b/syft/pkg/cataloger/deb/cataloger.go @@ -60,7 +60,7 @@ func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []arti for i := range pkgs { p := &pkgs[i] p.FoundBy = c.Name() - p.Locations = []source.Location{dbLocation} + p.Locations.Add(dbLocation) // the current entry only has what may have been listed in the status file, however, there are additional // files that are listed in multiple other locations. We should retrieve them all and merge the file lists @@ -88,7 +88,7 @@ func addLicenses(resolver source.FileResolver, dbLocation source.Location, p *pk p.Licenses = parseLicensesFromCopyright(copyrightReader) // keep a record of the file where this was discovered - p.Locations = append(p.Locations, *copyrightLocation) + p.Locations.Add(*copyrightLocation) } } @@ -117,7 +117,7 @@ loopNewFiles: p.Metadata = metadata // persist location information from each new source of information - p.Locations = append(p.Locations, infoLocations...) + p.Locations.Add(infoLocations...) } func getAdditionalFileListing(resolver source.FileResolver, dbLocation source.Location, p *pkg.Package) ([]pkg.DpkgFileRecord, []source.Location) { diff --git a/syft/pkg/cataloger/deb/cataloger_test.go b/syft/pkg/cataloger/deb/cataloger_test.go index 72a837f0640..37e6eef5023 100644 --- a/syft/pkg/cataloger/deb/cataloger_test.go +++ b/syft/pkg/cataloger/deb/cataloger_test.go @@ -1,6 +1,7 @@ package deb import ( + "github.com/stretchr/testify/assert" "testing" "github.com/anchore/syft/syft/file" @@ -115,15 +116,13 @@ func TestDpkgCataloger(t *testing.T) { for idx := range actual { a := &actual[idx] // we will test the sources separately - var sourcesList = make([]string, len(a.Locations)) - for i, s := range a.Locations { + var sourcesList = make([]string, len(a.Locations.ToSlice())) + for i, s := range a.Locations.ToSlice() { sourcesList[i] = s.RealPath } - a.Locations = nil + a.Locations = source.NewLocationSet() - for _, d := range deep.Equal(sourcesList, test.sources[a.Name]) { - t.Errorf("diff: %+v", d) - } + assert.ElementsMatch(t, sourcesList, test.sources[a.Name]) } // test remaining fields... diff --git a/syft/pkg/cataloger/golang/parse_go_bin.go b/syft/pkg/cataloger/golang/parse_go_bin.go index 1a4f0f10f6f..1fc980d62d7 100644 --- a/syft/pkg/cataloger/golang/parse_go_bin.go +++ b/syft/pkg/cataloger/golang/parse_go_bin.go @@ -44,14 +44,12 @@ func newGoBinaryPackage(dep *debug.Module, goVersion, architecture string, locat } p := pkg.Package{ - FoundBy: catalogerName, - Name: dep.Path, - Version: dep.Version, - Language: pkg.Go, - Type: pkg.GoModulePkg, - Locations: []source.Location{ - location, - }, + FoundBy: catalogerName, + Name: dep.Path, + Version: dep.Version, + Language: pkg.Go, + Type: pkg.GoModulePkg, + Locations: source.NewLocationSet(location), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goVersion, diff --git a/syft/pkg/cataloger/golang/parse_go_bin_test.go b/syft/pkg/cataloger/golang/parse_go_bin_test.go index 2cd1cfcbdde..8ac560d8c39 100644 --- a/syft/pkg/cataloger/golang/parse_go_bin_test.go +++ b/syft/pkg/cataloger/golang/parse_go_bin_test.go @@ -133,14 +133,14 @@ func TestBuildGoPkgInfo(t *testing.T) { FoundBy: catalogerName, Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, }, - }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, @@ -190,14 +190,14 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.2.1", Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, }, - }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, @@ -252,14 +252,14 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.2.1", Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, }, - }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, @@ -273,14 +273,14 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.0.0-20210222170800-9c70f9b80bcf", Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, }, - }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, @@ -327,12 +327,14 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.0.0-20211006194710-c8a6f5223071", Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", - }}}, + }, + }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, @@ -344,14 +346,14 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.0.0-20210916214954-140adaaadfaf", Language: pkg.Go, Type: pkg.GoModulePkg, - Locations: []source.Location{ - { + Locations: source.NewLocationSet( + source.Location{ Coordinates: source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, }, - }, + ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ GoCompiledVersion: goCompiledVersion, diff --git a/syft/pkg/cataloger/python/package_cataloger.go b/syft/pkg/cataloger/python/package_cataloger.go index ac0a214bc11..a966e865ade 100644 --- a/syft/pkg/cataloger/python/package_cataloger.go +++ b/syft/pkg/cataloger/python/package_cataloger.go @@ -80,7 +80,7 @@ func (c *PackageCataloger) catalogEggOrWheel(resolver source.FileResolver, metad Name: metadata.Name, Version: metadata.Version, FoundBy: c.Name(), - Locations: sources, + Locations: source.NewLocationSet(sources...), Licenses: licenses, Language: pkg.Python, Type: pkg.PythonPkg, diff --git a/syft/pkg/cataloger/python/package_cataloger_test.go b/syft/pkg/cataloger/python/package_cataloger_test.go index ccca539a9e6..7479f9ef371 100644 --- a/syft/pkg/cataloger/python/package_cataloger_test.go +++ b/syft/pkg/cataloger/python/package_cataloger_test.go @@ -144,7 +144,7 @@ func TestPythonPackageWheelCataloger(t *testing.T) { t.Fatal(err) } - test.expectedPackage.Locations = locations + test.expectedPackage.Locations = source.NewLocationSet(locations...) actual, _, err := NewPythonPackageCataloger().Catalog(resolver) if err != nil { diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go index d4f3607ebb8..d9fd1a02d34 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go @@ -1,6 +1,7 @@ package python import ( + "github.com/anchore/syft/syft/source" "os" "testing" @@ -48,7 +49,14 @@ func TestParsePipFileLock(t *testing.T) { t.Fatalf("failed to parse requirements: %+v", err) } - if diff := cmp.Diff(expected, actual, cmp.AllowUnexported(pkg.Package{})); diff != "" { + if diff := cmp.Diff(expected, actual, + cmp.AllowUnexported(pkg.Package{}), + cmp.Comparer( + func(x, y source.LocationSet) bool { + return cmp.Equal(x.ToSlice(), y.ToSlice()) + }, + ), + ); diff != "" { t.Errorf("unexpected result from parsing (-expected +actual)\n%s", diff) } } diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index d57d2e36a0a..3a187105996 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -1,6 +1,7 @@ package python import ( + "github.com/anchore/syft/syft/source" "os" "testing" @@ -42,7 +43,14 @@ func TestParseRequirementsTxt(t *testing.T) { t.Fatalf("failed to parse requirements: %+v", err) } - if diff := cmp.Diff(expected, actual, cmp.AllowUnexported(pkg.Package{})); diff != "" { + if diff := cmp.Diff(expected, actual, + cmp.AllowUnexported(pkg.Package{}), + cmp.Comparer( + func(x, y source.LocationSet) bool { + return cmp.Equal(x.ToSlice(), y.ToSlice()) + }, + ), + ); diff != "" { t.Errorf("unexpected result from parsing (-expected +actual)\n%s", diff) } } diff --git a/syft/pkg/cataloger/python/parse_setup_test.go b/syft/pkg/cataloger/python/parse_setup_test.go index 41fc191564a..b5614fa3d19 100644 --- a/syft/pkg/cataloger/python/parse_setup_test.go +++ b/syft/pkg/cataloger/python/parse_setup_test.go @@ -1,6 +1,7 @@ package python import ( + "github.com/anchore/syft/syft/source" "os" "testing" @@ -54,7 +55,14 @@ func TestParseSetup(t *testing.T) { t.Fatalf("failed to parse requirements: %+v", err) } - if diff := cmp.Diff(expected, actual, cmp.AllowUnexported(pkg.Package{})); diff != "" { + if diff := cmp.Diff(expected, actual, + cmp.AllowUnexported(pkg.Package{}), + cmp.Comparer( + func(x, y source.LocationSet) bool { + return cmp.Equal(x.ToSlice(), y.ToSlice()) + }, + ), + ); diff != "" { t.Errorf("unexpected result from parsing (-expected +actual)\n%s", diff) } } diff --git a/syft/pkg/cataloger/rpmdb/parse_rpmdb.go b/syft/pkg/cataloger/rpmdb/parse_rpmdb.go index 74f694c0986..c1b79416294 100644 --- a/syft/pkg/cataloger/rpmdb/parse_rpmdb.go +++ b/syft/pkg/cataloger/rpmdb/parse_rpmdb.go @@ -63,7 +63,7 @@ func parseRpmDB(resolver source.FilePathResolver, dbLocation source.Location, re p := pkg.Package{ Name: entry.Name, Version: toELVersion(metadata), - Locations: []source.Location{dbLocation}, + Locations: source.NewLocationSet(dbLocation), FoundBy: catalogerName, Type: pkg.RpmPkg, MetadataType: pkg.RpmdbMetadataType, diff --git a/syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go b/syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go index 0bad62396ac..d378e36e90d 100644 --- a/syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go +++ b/syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go @@ -71,7 +71,7 @@ func TestParseRpmDB(t *testing.T) { "dive": { Name: "dive", Version: "0.9.2-1", - Locations: []source.Location{dbLocation}, + Locations: source.NewLocationSet(dbLocation), FoundBy: catalogerName, Type: pkg.RpmPkg, MetadataType: pkg.RpmdbMetadataType, @@ -98,7 +98,7 @@ func TestParseRpmDB(t *testing.T) { "dive": { Name: "dive", Version: "0.9.2-1", - Locations: []source.Location{dbLocation}, + Locations: source.NewLocationSet(dbLocation), FoundBy: catalogerName, Type: pkg.RpmPkg, MetadataType: pkg.RpmdbMetadataType, diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go b/syft/pkg/cpe_by_specificity.go similarity index 84% rename from syft/pkg/cataloger/common/cpe/sort_by_specificity.go rename to syft/pkg/cpe_by_specificity.go index f680509826c..73cce8d04c1 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go +++ b/syft/pkg/cpe_by_specificity.go @@ -1,4 +1,4 @@ -package cpe +package pkg import ( "sort" @@ -6,15 +6,15 @@ import ( "github.com/facebookincubator/nvdtools/wfn" ) -var _ sort.Interface = (*BySpecificity)(nil) +var _ sort.Interface = (*CPEBySpecificity)(nil) -type BySpecificity []wfn.Attributes +type CPEBySpecificity []wfn.Attributes -func (c BySpecificity) Len() int { return len(c) } +func (c CPEBySpecificity) Len() int { return len(c) } -func (c BySpecificity) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c CPEBySpecificity) Swap(i, j int) { c[i], c[j] = c[j], c[i] } -func (c BySpecificity) Less(i, j int) bool { +func (c CPEBySpecificity) Less(i, j int) bool { iScore := weightedCountForSpecifiedFields(c[i]) jScore := weightedCountForSpecifiedFields(c[j]) diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go b/syft/pkg/cpe_by_specificity_test.go similarity index 87% rename from syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go rename to syft/pkg/cpe_by_specificity_test.go index f979bd8fbda..54f8e9f1308 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go +++ b/syft/pkg/cpe_by_specificity_test.go @@ -1,40 +1,32 @@ -package cpe +package pkg import ( "sort" "testing" - "github.com/anchore/syft/syft/pkg" "github.com/stretchr/testify/assert" ) -func mustCPE(c string) pkg.CPE { - return must(pkg.NewCPE(c)) -} - -func must(c pkg.CPE, e error) pkg.CPE { - if e != nil { - panic(e) - } - return c +func mustCPE(c string) CPE { + return must(NewCPE(c)) } func TestCPESpecificity(t *testing.T) { tests := []struct { name string - input []pkg.CPE - expected []pkg.CPE + input []CPE + expected []CPE }{ { name: "sort strictly by wfn *", - input: []pkg.CPE{ + input: []CPE{ mustCPE("cpe:2.3:a:*:package:1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:*:package:1:*:*:*:*:some:*:*"), mustCPE("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"), mustCPE("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"), }, - expected: []pkg.CPE{ + expected: []CPE{ mustCPE("cpe:2.3:a:some:package:1:*:*:*:*:some:*:*"), mustCPE("cpe:2.3:a:some:package:1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:some:package:*:*:*:*:*:*:*:*"), @@ -44,7 +36,7 @@ func TestCPESpecificity(t *testing.T) { }, { name: "sort strictly by field length", - input: []pkg.CPE{ + input: []CPE{ mustCPE("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:1:1:333:*:*:*:*:1:*:*"), @@ -52,7 +44,7 @@ func TestCPESpecificity(t *testing.T) { mustCPE("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"), }, - expected: []pkg.CPE{ + expected: []CPE{ mustCPE("cpe:2.3:a:1:666666:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:1:1:1:*:*:*:*:4444:*:*"), @@ -63,7 +55,7 @@ func TestCPESpecificity(t *testing.T) { }, { name: "sort by mix of field length and specificity", - input: []pkg.CPE{ + input: []CPE{ mustCPE("cpe:2.3:a:1:666666:*:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:*:1:1:*:*:*:*:4444:*:*"), mustCPE("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"), @@ -71,7 +63,7 @@ func TestCPESpecificity(t *testing.T) { mustCPE("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"), }, - expected: []pkg.CPE{ + expected: []CPE{ mustCPE("cpe:2.3:a:55555:1:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:1:22:1:*:*:*:*:1:*:*"), mustCPE("cpe:2.3:a:1:1:1:*:*:*:*:1:*:*"), @@ -82,7 +74,7 @@ func TestCPESpecificity(t *testing.T) { }, { name: "sort by mix of field length, specificity, dash", - input: []pkg.CPE{ + input: []CPE{ mustCPE("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), @@ -90,7 +82,7 @@ func TestCPESpecificity(t *testing.T) { mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), }, - expected: []pkg.CPE{ + expected: []CPE{ mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), @@ -103,7 +95,7 @@ func TestCPESpecificity(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - sort.Sort(BySpecificity(test.input)) + sort.Sort(CPEBySpecificity(test.input)) assert.Equal(t, test.expected, test.input) }) } diff --git a/syft/pkg/java_metadata.go b/syft/pkg/java_metadata.go index 8581c218eac..baa169a359e 100644 --- a/syft/pkg/java_metadata.go +++ b/syft/pkg/java_metadata.go @@ -20,7 +20,7 @@ var jenkinsPluginPomPropertiesGroupIDs = []string{ // JavaMetadata encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship. type JavaMetadata struct { - VirtualPath string `json:"virtualPath"` + VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` // we need to include the virtual path in cyclonedx documents to prevent deduplication of jars within jars Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` PomProperties *PomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` PomProject *PomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` diff --git a/syft/pkg/merge_cpes.go b/syft/pkg/merge_cpes.go new file mode 100644 index 00000000000..cb766a72fed --- /dev/null +++ b/syft/pkg/merge_cpes.go @@ -0,0 +1,25 @@ +package pkg + +import ( + "sort" +) + +func mergeCPEs(a, b []CPE) (result []CPE) { + aCPEs := make(map[string]CPE) + + // keep all CPEs from a and create a quick string-based lookup + for _, aCPE := range a { + aCPEs[aCPE.BindToFmtString()] = aCPE + result = append(result, aCPE) + } + + // keep all unique CPEs from b + for _, bCPE := range b { + if _, exists := aCPEs[bCPE.BindToFmtString()]; !exists { + result = append(result, bCPE) + } + } + + sort.Sort(CPEBySpecificity(result)) + return result +} diff --git a/syft/pkg/package.go b/syft/pkg/package.go index 6215bf594a0..13b19ca37a2 100644 --- a/syft/pkg/package.go +++ b/syft/pkg/package.go @@ -14,18 +14,18 @@ import ( // Package represents an application or library that has been bundled into a distributable format. // TODO: if we ignore FoundBy for ID generation should we merge the field to show it was found in two places? type Package struct { - id artifact.ID `hash:"ignore"` - Name string // the package name - Version string // the version of the package - FoundBy string `cyclonedx:"foundBy"` // the specific cataloger that discovered this package - Locations []source.Location // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) - Licenses []string // licenses discovered with the package metadata - Language Language `cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) - Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) - CPEs []CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) - PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) (note: this is NOT included in the definition of the ID since all fields on a pURL are derived from other fields) - MetadataType MetadataType `cyclonedx:"metadataType"` // the shape of the additional data in the "metadata" field - Metadata interface{} // additional data found while parsing the package source + id artifact.ID `hash:"ignore"` + Name string // the package name + Version string // the version of the package + FoundBy string `cyclonedx:"foundBy"` // the specific cataloger that discovered this package + Locations source.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) + Licenses []string // licenses discovered with the package metadata + Language Language `cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) + Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) + CPEs []CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) + PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) + MetadataType MetadataType `cyclonedx:"metadataType"` // the shape of the additional data in the "metadata" field + Metadata interface{} // additional data found while parsing the package source } func (p *Package) SetID() { @@ -46,3 +46,21 @@ func (p Package) ID() artifact.ID { func (p Package) String() string { return fmt.Sprintf("Pkg(name=%q version=%q type=%q id=%q)", p.Name, p.Version, p.Type, p.id) } + +func (p *Package) merge(other Package) error { + if p.id != other.id { + return fmt.Errorf("cannot merge packages with different IDs: %q vs %q", p.id, other.id) + } + if p.PURL != other.PURL { + log.Warnf("merging packages have with different pURLs: %q=%q vs %q=%q", p.id, p.PURL, other.id, other.PURL) + } + + p.Locations.Add(other.Locations.ToSlice()...) + + p.CPEs = mergeCPEs(p.CPEs, other.CPEs) + + if p.PURL == "" { + p.PURL = other.PURL + } + return nil +} diff --git a/syft/pkg/package_test.go b/syft/pkg/package_test.go index 228726a370f..bdbcee8f112 100644 --- a/syft/pkg/package_test.go +++ b/syft/pkg/package_test.go @@ -3,24 +3,28 @@ package pkg import ( "testing" + "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/syft/syft/source" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestFingerprint(t *testing.T) { +func TestIDUniqueness(t *testing.T) { + originalLocation := source.Location{ + Coordinates: source.Coordinates{ + RealPath: "39.0742° N, 21.8243° E", + FileSystemID: "Earth", + }, + VirtualPath: "/Ancient-Greece", + } originalPkg := Package{ Name: "pi", Version: "3.14", FoundBy: "Archimedes", - Locations: []source.Location{ - { - Coordinates: source.Coordinates{ - RealPath: "39.0742° N, 21.8243° E", - FileSystemID: "Earth", - }, - VirtualPath: "/Ancient-Greece", - }, - }, + Locations: source.NewLocationSet( + originalLocation, + ), Licenses: []string{ "cc0-1.0", "MIT", @@ -45,9 +49,9 @@ func TestFingerprint(t *testing.T) { // this is a set of differential tests, ensuring that select mutations are reflected in the fingerprint (or not) tests := []struct { - name string - transform func(pkg Package) Package - expectIdentical bool + name string + transform func(pkg Package) Package + expectedIDComparison assert.ComparisonAssertionFunc }{ { name: "go case (no transform)", @@ -55,7 +59,7 @@ func TestFingerprint(t *testing.T) { // do nothing! return pkg }, - expectIdentical: true, + expectedIDComparison: assert.Equal, }, { name: "same metadata is ignored", @@ -72,7 +76,7 @@ func TestFingerprint(t *testing.T) { } return pkg }, - expectIdentical: true, + expectedIDComparison: assert.Equal, }, { name: "licenses order is ignored", @@ -84,7 +88,7 @@ func TestFingerprint(t *testing.T) { } return pkg }, - expectIdentical: true, + expectedIDComparison: assert.Equal, }, { name: "name is reflected", @@ -92,7 +96,42 @@ func TestFingerprint(t *testing.T) { pkg.Name = "new!" return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, + }, + { + name: "location is reflected", + transform: func(pkg Package) Package { + locations := source.NewLocationSet(pkg.Locations.ToSlice()...) + locations.Add(source.NewLocation("/somewhere/new")) + pkg.Locations = locations + return pkg + }, + expectedIDComparison: assert.NotEqual, + }, + { + name: "same path for different filesystem is NOT reflected", + transform: func(pkg Package) Package { + newLocation := originalLocation + newLocation.FileSystemID = "Mars" + + pkg.Locations = source.NewLocationSet(newLocation) + return pkg + }, + expectedIDComparison: assert.Equal, + }, + { + name: "multiple equivalent paths for different filesystem is NOT reflected", + transform: func(pkg Package) Package { + newLocation := originalLocation + newLocation.FileSystemID = "Mars" + + locations := source.NewLocationSet(pkg.Locations.ToSlice()...) + locations.Add(newLocation, originalLocation) + + pkg.Locations = locations + return pkg + }, + expectedIDComparison: assert.Equal, }, { name: "version is reflected", @@ -100,7 +139,7 @@ func TestFingerprint(t *testing.T) { pkg.Version = "new!" return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "licenses is reflected", @@ -108,7 +147,7 @@ func TestFingerprint(t *testing.T) { pkg.Licenses = []string{"new!"} return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "type is reflected", @@ -116,7 +155,7 @@ func TestFingerprint(t *testing.T) { pkg.Type = RustPkg return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "metadata type is reflected", @@ -124,7 +163,7 @@ func TestFingerprint(t *testing.T) { pkg.MetadataType = RustCargoPackageMetadataType return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "CPEs is ignored", @@ -132,7 +171,7 @@ func TestFingerprint(t *testing.T) { pkg.CPEs = []CPE{} return pkg }, - expectIdentical: true, + expectedIDComparison: assert.Equal, }, { name: "pURL is ignored", @@ -140,7 +179,7 @@ func TestFingerprint(t *testing.T) { pkg.PURL = "new!" return pkg }, - expectIdentical: true, + expectedIDComparison: assert.Equal, }, { name: "language is reflected", @@ -148,7 +187,7 @@ func TestFingerprint(t *testing.T) { pkg.Language = Rust return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "foundBy is reflected", @@ -156,7 +195,7 @@ func TestFingerprint(t *testing.T) { pkg.FoundBy = "new!" return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "metadata mutation is reflected", @@ -166,7 +205,7 @@ func TestFingerprint(t *testing.T) { pkg.Metadata = metadata return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "new metadata is reflected", @@ -176,7 +215,7 @@ func TestFingerprint(t *testing.T) { } return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, { name: "nil metadata is reflected", @@ -184,7 +223,7 @@ func TestFingerprint(t *testing.T) { pkg.Metadata = nil return pkg }, - expectIdentical: false, + expectedIDComparison: assert.NotEqual, }, } @@ -199,12 +238,207 @@ func TestFingerprint(t *testing.T) { transformedFingerprint := transformedPkg.ID() assert.NotEmpty(t, transformedFingerprint) - if test.expectIdentical { - assert.Equal(t, originalFingerprint, transformedFingerprint) - } else { - assert.NotEqual(t, originalFingerprint, transformedFingerprint) + test.expectedIDComparison(t, originalFingerprint, transformedFingerprint) + }) + } +} + +func TestPackage_Merge(t *testing.T) { + originalLocation := source.Location{ + Coordinates: source.Coordinates{ + RealPath: "39.0742° N, 21.8243° E", + FileSystemID: "Earth", + }, + VirtualPath: "/Ancient-Greece", + } + + similarLocation := originalLocation + similarLocation.FileSystemID = "Mars" + + tests := []struct { + name string + subject Package + other Package + expected *Package + }{ + { + name: "merge two packages (different cpes + locations)", + subject: Package{ + Name: "pi", + Version: "3.14", + FoundBy: "Archimedes", + Locations: source.NewLocationSet( + originalLocation, + ), + Licenses: []string{ + "cc0-1.0", + "MIT", + }, + Language: "math", + Type: PythonPkg, + CPEs: []CPE{ + must(NewCPE(`cpe:2.3:a:Archimedes:pi:3.14:*:*:*:*:math:*:*`)), + }, + PURL: "pkg:pypi/pi@3.14", + MetadataType: PythonPackageMetadataType, + Metadata: PythonPackageMetadata{ + Name: "pi", + Version: "3.14", + License: "cc0-1.0", + Author: "Archimedes", + AuthorEmail: "Archimedes@circles.io", + Platform: "universe", + SitePackagesRootPath: "Pi", + }, + }, + other: Package{ + Name: "pi", + Version: "3.14", + FoundBy: "Archimedes", + Locations: source.NewLocationSet( + similarLocation, // NOTE: difference; we have a different layer but the same path + ), + Licenses: []string{ + "cc0-1.0", + "MIT", + }, + Language: "math", + Type: PythonPkg, + CPEs: []CPE{ + must(NewCPE(`cpe:2.3:a:DIFFERENT:pi:3.14:*:*:*:*:math:*:*`)), // NOTE: difference + }, + PURL: "pkg:pypi/pi@3.14", + MetadataType: PythonPackageMetadataType, + Metadata: PythonPackageMetadata{ + Name: "pi", + Version: "3.14", + License: "cc0-1.0", + Author: "Archimedes", + AuthorEmail: "Archimedes@circles.io", + Platform: "universe", + SitePackagesRootPath: "Pi", + }, + }, + expected: &Package{ + Name: "pi", + Version: "3.14", + FoundBy: "Archimedes", + Locations: source.NewLocationSet( + originalLocation, + similarLocation, // NOTE: merge! + ), + Licenses: []string{ + "cc0-1.0", + "MIT", + }, + Language: "math", + Type: PythonPkg, + CPEs: []CPE{ + must(NewCPE(`cpe:2.3:a:Archimedes:pi:3.14:*:*:*:*:math:*:*`)), + must(NewCPE(`cpe:2.3:a:DIFFERENT:pi:3.14:*:*:*:*:math:*:*`)), // NOTE: merge! + }, + PURL: "pkg:pypi/pi@3.14", + MetadataType: PythonPackageMetadataType, + Metadata: PythonPackageMetadata{ + Name: "pi", + Version: "3.14", + License: "cc0-1.0", + Author: "Archimedes", + AuthorEmail: "Archimedes@circles.io", + Platform: "universe", + SitePackagesRootPath: "Pi", + }, + }, + }, + { + name: "error when there are different IDs", + subject: Package{ + Name: "pi", + Version: "3.14", + FoundBy: "Archimedes", + Locations: source.NewLocationSet( + originalLocation, + ), + Licenses: []string{ + "cc0-1.0", + "MIT", + }, + Language: "math", + Type: PythonPkg, + CPEs: []CPE{ + must(NewCPE(`cpe:2.3:a:Archimedes:pi:3.14:*:*:*:*:math:*:*`)), + }, + PURL: "pkg:pypi/pi@3.14", + MetadataType: PythonPackageMetadataType, + Metadata: PythonPackageMetadata{ + Name: "pi", + Version: "3.14", + License: "cc0-1.0", + Author: "Archimedes", + AuthorEmail: "Archimedes@circles.io", + Platform: "universe", + SitePackagesRootPath: "Pi", + }, + }, + other: Package{ + Name: "pi-DIFFERENT", // difference + Version: "3.14", + FoundBy: "Archimedes", + Locations: source.NewLocationSet( + originalLocation, + ), + Licenses: []string{ + "cc0-1.0", + "MIT", + }, + Language: "math", + Type: PythonPkg, + CPEs: []CPE{ + must(NewCPE(`cpe:2.3:a:Archimedes:pi:3.14:*:*:*:*:math:*:*`)), + }, + PURL: "pkg:pypi/pi@3.14", + MetadataType: PythonPackageMetadataType, + Metadata: PythonPackageMetadata{ + Name: "pi", + Version: "3.14", + License: "cc0-1.0", + Author: "Archimedes", + AuthorEmail: "Archimedes@circles.io", + Platform: "universe", + SitePackagesRootPath: "Pi", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.subject.SetID() + tt.other.SetID() + + err := tt.subject.merge(tt.other) + if tt.expected == nil { + require.Error(t, err) + return } + require.NoError(t, err) + + tt.expected.SetID() + require.Equal(t, tt.expected.id, tt.subject.id) + if diff := cmp.Diff(*tt.expected, tt.subject, + cmp.AllowUnexported(Package{}), + cmp.Comparer( + func(x, y source.LocationSet) bool { + return cmp.Equal( + x.ToSlice(), y.ToSlice(), + cmp.AllowUnexported(source.Location{}), + cmp.AllowUnexported(file.Reference{}), + ) + }, + ), + ); diff != "" { + t.Errorf("unexpected result from parsing (-expected +actual)\n%s", diff) + } }) } } diff --git a/syft/pkg/relationships_by_file_ownership_test.go b/syft/pkg/relationships_by_file_ownership_test.go index 69867f2702f..42844b98e66 100644 --- a/syft/pkg/relationships_by_file_ownership_test.go +++ b/syft/pkg/relationships_by_file_ownership_test.go @@ -18,10 +18,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { name: "owns-by-real-path", setup: func(t testing.TB) ([]Package, []artifact.Relationship) { parent := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/a/path", "/another/path"), source.NewVirtualLocation("/b/path", "/bee/path"), - }, + ), Type: RpmPkg, MetadataType: RpmdbMetadataType, Metadata: RpmdbMetadata{ @@ -35,10 +35,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { parent.SetID() child := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/c/path", "/another/path"), source.NewVirtualLocation("/d/path", "/another/path"), - }, + ), Type: NpmPkg, } child.SetID() @@ -61,10 +61,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { name: "owns-by-virtual-path", setup: func(t testing.TB) ([]Package, []artifact.Relationship) { parent := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/a/path", "/some/other/path"), source.NewVirtualLocation("/b/path", "/bee/path"), - }, + ), Type: RpmPkg, MetadataType: RpmdbMetadataType, Metadata: RpmdbMetadata{ @@ -78,10 +78,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { parent.SetID() child := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/c/path", "/another/path"), source.NewLocation("/d/path"), - }, + ), Type: NpmPkg, } child.SetID() @@ -103,10 +103,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { name: "ignore-empty-path", setup: func(t testing.TB) ([]Package, []artifact.Relationship) { parent := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/a/path", "/some/other/path"), source.NewVirtualLocation("/b/path", "/bee/path"), - }, + ), Type: RpmPkg, MetadataType: RpmdbMetadataType, Metadata: RpmdbMetadata{ @@ -121,10 +121,10 @@ func TestOwnershipByFilesRelationship(t *testing.T) { parent.SetID() child := Package{ - Locations: []source.Location{ + Locations: source.NewLocationSet( source.NewVirtualLocation("/c/path", "/another/path"), source.NewLocation("/d/path"), - }, + ), Type: NpmPkg, } diff --git a/syft/source/coordinate_set.go b/syft/source/coordinate_set.go new file mode 100644 index 00000000000..0ae080c270f --- /dev/null +++ b/syft/source/coordinate_set.go @@ -0,0 +1,86 @@ +package source + +import ( + "sort" + + "github.com/mitchellh/hashstructure/v2" + "github.com/scylladb/go-set/strset" +) + +type CoordinateSet struct { + set map[Coordinates]struct{} +} + +func NewCoordinateSet(coordinates ...Coordinates) (s CoordinateSet) { + for _, l := range coordinates { + s.Add(l) + } + + return s +} + +func (s *CoordinateSet) Add(coordinates ...Coordinates) { + if s.set == nil { + s.set = make(map[Coordinates]struct{}) + } + for _, l := range coordinates { + s.set[l] = struct{}{} + } +} + +func (s CoordinateSet) Remove(coordinates ...Coordinates) { + if s.set == nil { + return + } + for _, l := range coordinates { + delete(s.set, l) + } +} + +func (s CoordinateSet) Contains(l Coordinates) bool { + if s.set == nil { + return false + } + _, ok := s.set[l] + return ok +} + +func (s CoordinateSet) Paths() []string { + if s.set == nil { + return nil + } + + paths := strset.New() + for _, c := range s.ToSlice() { + paths.Add(c.RealPath) + } + pathSlice := paths.List() + sort.Strings(pathSlice) + return pathSlice +} + +func (s CoordinateSet) ToSlice() []Coordinates { + if s.set == nil { + return nil + } + coordinates := make([]Coordinates, len(s.set)) + idx := 0 + for v := range s.set { + coordinates[idx] = v + idx++ + } + sort.SliceStable(coordinates, func(i, j int) bool { + if coordinates[i].RealPath == coordinates[j].RealPath { + return coordinates[i].FileSystemID < coordinates[j].FileSystemID + } + return coordinates[i].RealPath < coordinates[j].RealPath + }) + return coordinates +} + +func (s CoordinateSet) Hash() (uint64, error) { + return hashstructure.Hash(s.ToSlice(), hashstructure.FormatV2, &hashstructure.HashOptions{ + ZeroNil: true, + SlicesAsSets: true, + }) +} diff --git a/syft/source/coordinate_set_test.go b/syft/source/coordinate_set_test.go new file mode 100644 index 00000000000..5601cdc9152 --- /dev/null +++ b/syft/source/coordinate_set_test.go @@ -0,0 +1,117 @@ +package source + +import ( + "github.com/anchore/syft/syft/artifact" + "github.com/stretchr/testify/require" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCoordinatesSet(t *testing.T) { + + binA := Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + } + + binB := Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + } + + tests := []struct { + name string + input []Coordinates + expected []Coordinates + }{ + { + name: "de-dup same location", + input: []Coordinates{ + binA, binA, binA, + }, + expected: []Coordinates{ + binA, + }, + }, + { + name: "dont de-dup different filesystem", + input: []Coordinates{ + binB, binA, + }, + expected: []Coordinates{ + binA, binB, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + set := NewCoordinateSet(test.input...) + assert.Equal(t, test.expected, set.ToSlice()) + }) + } +} + +func TestCoordinateSet_Hash(t *testing.T) { + etcA := Coordinates{ + RealPath: "/etc", + FileSystemID: "a", + } + + etcB := Coordinates{ + RealPath: "/etc", + FileSystemID: "b", + } + + binA := Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + } + + binB := Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + } + + tests := []struct { + name string + setA CoordinateSet + setB CoordinateSet + want assert.ComparisonAssertionFunc + }{ + { + name: "empty sets have the same hash", + setA: NewCoordinateSet(), + setB: NewCoordinateSet(), + want: assert.Equal, + }, + { + name: "sets with same elements have the same hash", + setA: NewCoordinateSet(binA, etcA), + setB: NewCoordinateSet(etcA, binA), + want: assert.Equal, + }, + { + name: "sets with different elements have different hashes", + setA: NewCoordinateSet(binA, etcA), + setB: NewCoordinateSet(binA), + want: assert.NotEqual, + }, + { + name: "sets with same paths but different FS IDs have different hashes", + setA: NewCoordinateSet(etcA, binA), + setB: NewCoordinateSet(etcB, binB), + want: assert.NotEqual, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotA, err := artifact.IDByHash(tt.setA) + require.NoError(t, err) + gotB, err := artifact.IDByHash(tt.setB) + require.NoError(t, err) + tt.want(t, gotA, gotB) + }) + } +} diff --git a/syft/source/coordinates.go b/syft/source/coordinates.go index 653670792ad..c35d3dcc297 100644 --- a/syft/source/coordinates.go +++ b/syft/source/coordinates.go @@ -2,7 +2,6 @@ package source import ( "fmt" - "sort" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" @@ -14,18 +13,6 @@ type Coordinates struct { FileSystemID string `json:"layerID,omitempty" cyclonedx:"layerID"` // An ID representing the filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank. } -// CoordinateSet represents a set of string types. -type CoordinateSet map[Coordinates]struct{} - -// NewCoordinateSet creates a CoordinateSet populated with values from the given slice. -func NewCoordinateSet(start ...Coordinates) CoordinateSet { - ret := make(CoordinateSet) - for _, s := range start { - ret.Add(s) - } - return ret -} - func (c Coordinates) ID() artifact.ID { f, err := artifact.IDByHash(c) if err != nil { @@ -45,37 +32,3 @@ func (c Coordinates) String() string { } return fmt.Sprintf("Location<%s>", str) } - -// Add a string to the set. -func (s CoordinateSet) Add(i Coordinates) { - s[i] = struct{}{} -} - -// Remove a string from the set. -func (s CoordinateSet) Remove(i Coordinates) { - delete(s, i) -} - -// Contains indicates if the given string is contained within the set. -func (s CoordinateSet) Contains(i Coordinates) bool { - _, ok := s[i] - return ok -} - -// ToSlice returns a sorted slice of Locations that are contained within the set. -func (s CoordinateSet) ToSlice() []Coordinates { - ret := make([]Coordinates, len(s)) - idx := 0 - for v := range s { - ret[idx] = v - idx++ - } - - sort.SliceStable(ret, func(i, j int) bool { - if ret[i].RealPath == ret[j].RealPath { - return ret[i].FileSystemID < ret[j].FileSystemID - } - return ret[i].RealPath < ret[j].RealPath - }) - return ret -} diff --git a/syft/source/coordinates_test.go b/syft/source/coordinates_test.go deleted file mode 100644 index e9f8a4a308c..00000000000 --- a/syft/source/coordinates_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package source - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCoordinateSet(t *testing.T) { - - binA := Coordinates{ - RealPath: "/bin", - FileSystemID: "a", - } - - binB := Coordinates{ - RealPath: "/bin", - FileSystemID: "b", - } - - tests := []struct { - name string - input []Coordinates - expected []Coordinates - }{ - { - name: "de-dup same location", - input: []Coordinates{ - binA, binA, binA, - }, - expected: []Coordinates{ - binA, - }, - }, - { - name: "dont de-dup different filesystem", - input: []Coordinates{ - binB, binA, - }, - expected: []Coordinates{ - binA, binB, - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, NewCoordinateSet(test.input...).ToSlice()) - }) - } -} diff --git a/syft/source/location.go b/syft/source/location.go index 3f14ed41355..04acee9f526 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -109,3 +109,9 @@ func (l Location) String() string { } return fmt.Sprintf("Location<%s>", str) } + +func (l Location) Equals(other Location) bool { + return l.RealPath == other.RealPath && + l.VirtualPath == other.VirtualPath && + l.FileSystemID == other.FileSystemID +} diff --git a/syft/source/location_set.go b/syft/source/location_set.go new file mode 100644 index 00000000000..c2e915921b7 --- /dev/null +++ b/syft/source/location_set.go @@ -0,0 +1,78 @@ +package source + +import ( + "sort" + + "github.com/mitchellh/hashstructure/v2" +) + +type LocationSet struct { + set map[Location]struct{} +} + +func NewLocationSet(locations ...Location) (s LocationSet) { + for _, l := range locations { + s.Add(l) + } + + return s +} + +func (s *LocationSet) Add(locations ...Location) { + if s.set == nil { + s.set = make(map[Location]struct{}) + } + for _, l := range locations { + s.set[l] = struct{}{} + } +} + +func (s LocationSet) Remove(locations ...Location) { + if s.set == nil { + return + } + for _, l := range locations { + delete(s.set, l) + } +} + +func (s LocationSet) Contains(l Location) bool { + if s.set == nil { + return false + } + _, ok := s.set[l] + return ok +} + +func (s LocationSet) ToSlice() []Location { + if s.set == nil { + return nil + } + locations := make([]Location, len(s.set)) + idx := 0 + for v := range s.set { + locations[idx] = v + idx++ + } + sort.Sort(Locations(locations)) + return locations +} + +func (s *LocationSet) CoordinateSet() CoordinateSet { + if s.set == nil { + return NewCoordinateSet() + } + set := NewCoordinateSet() + for l := range s.set { + set.Add(l.Coordinates) + } + return set +} + +func (s LocationSet) Hash() (uint64, error) { + // access paths and filesystem IDs are not considered when hashing a location set, only the real paths + return hashstructure.Hash(s.CoordinateSet().Paths(), hashstructure.FormatV2, &hashstructure.HashOptions{ + ZeroNil: true, + SlicesAsSets: true, + }) +} diff --git a/syft/source/location_set_test.go b/syft/source/location_set_test.go new file mode 100644 index 00000000000..dc80a4962ca --- /dev/null +++ b/syft/source/location_set_test.go @@ -0,0 +1,178 @@ +package source + +import ( + "github.com/anchore/syft/syft/artifact" + "github.com/stretchr/testify/require" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLocationSet(t *testing.T) { + + etcHostsLinkVar := Location{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/var/etc/hosts", + } + + etcHostsLinkHome := Location{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/home/wagoodman/hosts", + } + + binA := Location{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + }, + VirtualPath: "/usr/bin", + } + + binB := Location{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + }, + VirtualPath: "/usr/bin", + } + + tests := []struct { + name string + input []Location + expected []Location + }{ + { + name: "de-dup same location", + input: []Location{ + binA, binA, binA, + }, + expected: []Location{ + binA, + }, + }, + { + name: "dont de-dup different filesystem", + input: []Location{ + binB, binA, + }, + expected: []Location{ + binA, binB, + }, + }, + { + name: "dont de-dup different virtual paths", + input: []Location{ + etcHostsLinkVar, etcHostsLinkHome, + }, + expected: []Location{ + etcHostsLinkHome, etcHostsLinkVar, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + set := NewLocationSet(test.input...) + assert.Equal(t, test.expected, set.ToSlice()) + }) + } +} + +func TestLocationSet_Hash(t *testing.T) { + etcAlink := Location{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/var/etc/hosts", + } + + etcA := Location{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + } + + etcB := Location{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "b", + }, + } + + binA := Location{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + }, + VirtualPath: "/usr/bin", + } + + binB := Location{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + }, + VirtualPath: "/usr/bin", + } + + tests := []struct { + name string + setA LocationSet + setB LocationSet + want assert.ComparisonAssertionFunc + }{ + { + name: "empty sets have the same hash", + setA: NewLocationSet(), + setB: NewLocationSet(), + want: assert.Equal, + }, + { + name: "sets with same elements accessed through different paths have the same hash", + setA: NewLocationSet(binA, etcA), + setB: NewLocationSet(etcAlink, binA), + want: assert.Equal, + }, + { + name: "sets with same elements have the same hash", + setA: NewLocationSet(binA, etcA), + setB: NewLocationSet(etcA, binA), + want: assert.Equal, + }, + { + name: "sets with different element counts have different hashes", + setA: NewLocationSet(binA, etcA), + setB: NewLocationSet(binA), + want: assert.NotEqual, + }, + { + name: "sets with same path but different FS IDs have the same hash", + setA: NewLocationSet(binA), + setB: NewLocationSet(binB), + want: assert.Equal, + }, + { + name: "sets with same paths but different FS IDs have the same hash", + setA: NewLocationSet(etcA, binA), + setB: NewLocationSet(binB, etcB), + want: assert.Equal, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotA, err := artifact.IDByHash(tt.setA) + require.NoError(t, err) + gotB, err := artifact.IDByHash(tt.setB) + require.NoError(t, err) + tt.want(t, gotA, gotB) + }) + } +} diff --git a/syft/source/locations.go b/syft/source/locations.go new file mode 100644 index 00000000000..045d1ed9d3c --- /dev/null +++ b/syft/source/locations.go @@ -0,0 +1,21 @@ +package source + +type Locations []Location + +func (l Locations) Len() int { + return len(l) +} + +func (l Locations) Less(i, j int) bool { + if l[i].RealPath == l[j].RealPath { + if l[i].VirtualPath == l[j].VirtualPath { + return l[i].FileSystemID < l[j].FileSystemID + } + return l[i].VirtualPath < l[j].VirtualPath + } + return l[i].RealPath < l[j].RealPath +} + +func (l Locations) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} diff --git a/test/cli/packages_cmd_test.go b/test/cli/packages_cmd_test.go index f35788e0dda..898727af0fc 100644 --- a/test/cli/packages_cmd_test.go +++ b/test/cli/packages_cmd_test.go @@ -8,6 +8,7 @@ import ( ) func TestPackagesCmdFlags(t *testing.T) { + hiddenPackagesImage := "docker-archive:" + getFixtureImage(t, "image-hidden-packages") coverageImage := "docker-archive:" + getFixtureImage(t, "image-pkg-coverage") //badBinariesImage := "docker-archive:" + getFixtureImage(t, "image-bad-binaries") tmp := t.TempDir() + "/" @@ -99,22 +100,35 @@ func TestPackagesCmdFlags(t *testing.T) { assertSuccessfulReturnCode, }, }, + { + name: "squashed-scope-flag-hidden-packages", + args: []string{"packages", "-o", "json", "-s", "squashed", hiddenPackagesImage}, + assertions: []traitAssertion{ + assertPackageCount(162), + assertNotInOutput("vsftpd"), // hidden package + assertSuccessfulReturnCode, + }, + }, { name: "all-layers-scope-flag", - args: []string{"packages", "-o", "json", "-s", "all-layers", coverageImage}, + args: []string{"packages", "-o", "json", "-s", "all-layers", hiddenPackagesImage}, assertions: []traitAssertion{ - assertPackageCount(22), + assertPackageCount(163), // packages are now deduplicated for this case + assertInOutput("all-layers"), + assertInOutput("vsftpd"), // hidden package assertSuccessfulReturnCode, }, }, { name: "all-layers-scope-flag-by-env", - args: []string{"packages", "-o", "json", coverageImage}, + args: []string{"packages", "-o", "json", hiddenPackagesImage}, env: map[string]string{ "SYFT_PACKAGE_CATALOGER_SCOPE": "all-layers", }, assertions: []traitAssertion{ - assertPackageCount(22), + assertPackageCount(163), // packages are now deduplicated for this case + assertInOutput("all-layers"), + assertInOutput("vsftpd"), // hidden package assertSuccessfulReturnCode, }, }, diff --git a/test/cli/test-fixtures/image-hidden-packages/Dockerfile b/test/cli/test-fixtures/image-hidden-packages/Dockerfile new file mode 100644 index 00000000000..cf8ea3bfa0e --- /dev/null +++ b/test/cli/test-fixtures/image-hidden-packages/Dockerfile @@ -0,0 +1,4 @@ +FROM centos:7.9.2009 +# all-layers scope should pickup on vsftpd +RUN yum install -y vsftpd +RUN yum remove -y vsftpd \ No newline at end of file diff --git a/test/integration/catalog_packages_test.go b/test/integration/catalog_packages_test.go index ade886512e2..6c701a72ef5 100644 --- a/test/integration/catalog_packages_test.go +++ b/test/integration/catalog_packages_test.go @@ -54,7 +54,7 @@ func BenchmarkImagePackageCatalogers(b *testing.B) { } func TestPkgCoverageImage(t *testing.T) { - sbom, _ := catalogFixtureImage(t, "image-pkg-coverage") + sbom, _ := catalogFixtureImage(t, "image-pkg-coverage", source.SquashedScope) observedLanguages := internal.NewStringSet() definedLanguages := internal.NewStringSet() diff --git a/test/integration/distro_test.go b/test/integration/distro_test.go index 8d1dbfacc7e..5c9f044f052 100644 --- a/test/integration/distro_test.go +++ b/test/integration/distro_test.go @@ -1,6 +1,7 @@ package integration import ( + "github.com/anchore/syft/syft/source" "testing" "github.com/stretchr/testify/assert" @@ -9,7 +10,7 @@ import ( ) func TestDistroImage(t *testing.T) { - sbom, _ := catalogFixtureImage(t, "image-distro-id") + sbom, _ := catalogFixtureImage(t, "image-distro-id", source.SquashedScope) expected := &linux.Release{ PrettyName: "BusyBox v1.31.1", diff --git a/test/integration/encode_decode_cycle_test.go b/test/integration/encode_decode_cycle_test.go index 920dc2d7d81..348a309d229 100644 --- a/test/integration/encode_decode_cycle_test.go +++ b/test/integration/encode_decode_cycle_test.go @@ -2,12 +2,14 @@ package integration import ( "bytes" - "regexp" - "testing" - + "fmt" "github.com/anchore/syft/internal/formats/cyclonedxjson" "github.com/anchore/syft/internal/formats/cyclonedxxml" "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/syft/source" + "regexp" + "testing" + "github.com/anchore/syft/syft/sbom" "github.com/stretchr/testify/require" @@ -51,12 +53,12 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { }, }, } - for _, test := range tests { - t.Run(string(test.formatOption), func(t *testing.T) { - // use second image for relationships - for _, image := range []string{"image-pkg-coverage", "image-owning-package"} { - originalSBOM, _ := catalogFixtureImage(t, image) + for _, test := range tests { + // use second image for relationships + for _, image := range []string{"image-pkg-coverage", "image-owning-package"} { + t.Run(fmt.Sprintf("%s/%s", test.formatOption, image), func(t *testing.T) { + originalSBOM, _ := catalogFixtureImage(t, image, source.SquashedScope) format := syft.FormatByID(test.formatOption) require.NotNil(t, format) @@ -87,7 +89,7 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { t.Errorf("diff: %s", dmp.DiffPrettyText(diffs)) } } - } - }) + }) + } } } diff --git a/test/integration/node_packages_test.go b/test/integration/node_packages_test.go index 8505e5c784a..2ececa6582d 100644 --- a/test/integration/node_packages_test.go +++ b/test/integration/node_packages_test.go @@ -14,7 +14,7 @@ func TestNpmPackageLockDirectory(t *testing.T) { foundPackages := internal.NewStringSet() for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.NpmPkg) { - for _, actualLocation := range actualPkg.Locations { + for _, actualLocation := range actualPkg.Locations.ToSlice() { if strings.Contains(actualLocation.RealPath, "node_modules") { t.Errorf("found packages from package-lock.json in node_modules: %s", actualLocation) } @@ -35,7 +35,7 @@ func TestYarnPackageLockDirectory(t *testing.T) { foundPackages := internal.NewStringSet() for actualPkg := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.NpmPkg) { - for _, actualLocation := range actualPkg.Locations { + for _, actualLocation := range actualPkg.Locations.ToSlice() { if strings.Contains(actualLocation.RealPath, "node_modules") { t.Errorf("found packages from yarn.lock in node_modules: %s", actualLocation) } diff --git a/test/integration/package_deduplication_test.go b/test/integration/package_deduplication_test.go new file mode 100644 index 00000000000..8798f9d9045 --- /dev/null +++ b/test/integration/package_deduplication_test.go @@ -0,0 +1,84 @@ +package integration + +import ( + "fmt" + "github.com/anchore/syft/syft/source" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func TestPackageDeduplication(t *testing.T) { + tests := []struct { + scope source.Scope + packageCount int + instanceCount map[string]int + locationCount map[string]int + }{ + { + scope: source.AllLayersScope, + packageCount: 172, // without deduplication this would be 618 + instanceCount: map[string]int{ + "basesystem": 1, + "wget": 1, + "curl": 2, // upgraded in the image + "vsftpd": 1, + "httpd": 1, + }, + locationCount: map[string]int{ + "basesystem-10.0-7.el7.centos": 4, + "curl-7.29.0-59.el7": 1, // from base image + "curl-7.29.0-59.el7_9.1": 3, // upgrade + "wget-1.14-18.el7_6.1": 3, + "vsftpd-3.0.2-29.el7_9": 2, + "httpd-2.4.6-97.el7.centos.5": 1, + }, + }, + { + scope: source.SquashedScope, + packageCount: 170, + instanceCount: map[string]int{ + "basesystem": 1, + "wget": 1, + "curl": 1, // upgraded, but the most recent + "vsftpd": 1, + "httpd": 1, + }, + locationCount: map[string]int{ + "basesystem-10.0-7.el7.centos": 1, + "curl-7.29.0-59.el7_9.1": 1, // upgrade + "wget-1.14-18.el7_6.1": 1, + "vsftpd-3.0.2-29.el7_9": 1, + "httpd-2.4.6-97.el7.centos.5": 1, + }, + }, + } + + for _, tt := range tests { + t.Run(string(tt.scope), func(t *testing.T) { + sbom, _ := catalogFixtureImage(t, "image-vertical-package-dups", tt.scope) + + assert.Equal(t, tt.packageCount, sbom.Artifacts.PackageCatalog.PackageCount()) + for name, expectedInstanceCount := range tt.instanceCount { + pkgs := sbom.Artifacts.PackageCatalog.PackagesByName(name) + + // with multiple packages with the same name, something is wrong (or this is the wrong fixture) + require.Len(t, pkgs, expectedInstanceCount) + for _, p := range pkgs { + nameVersion := fmt.Sprintf("%s-%s", name, p.Version) + expectedLocationCount, ok := tt.locationCount[nameVersion] + if !ok { + t.Fatalf("missing name-version: %s", nameVersion) + } + + // we should see merged locations (assumption, there was 1 location for each package) + assert.Len(t, p.Locations.ToSlice(), expectedLocationCount) + + // all paths should match + assert.Len(t, p.Locations.CoordinateSet().Paths(), 1) + } + } + + }) + } +} diff --git a/test/integration/package_ownership_relationship_test.go b/test/integration/package_ownership_relationship_test.go index 587b15459c5..8335898b9b0 100644 --- a/test/integration/package_ownership_relationship_test.go +++ b/test/integration/package_ownership_relationship_test.go @@ -3,6 +3,7 @@ package integration import ( "bytes" "encoding/json" + "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/internal/formats/syftjson" @@ -22,7 +23,7 @@ func TestPackageOwnershipRelationships(t *testing.T) { for _, test := range tests { t.Run(test.fixture, func(t *testing.T) { - sbom, _ := catalogFixtureImage(t, test.fixture) + sbom, _ := catalogFixtureImage(t, test.fixture, source.SquashedScope) output := bytes.NewBufferString("") err := syftjson.Format().Encode(output, sbom) diff --git a/test/integration/regression_apk_scanner_buffer_size_test.go b/test/integration/regression_apk_scanner_buffer_size_test.go index 19bf9f92f19..d0e4d953e6d 100644 --- a/test/integration/regression_apk_scanner_buffer_size_test.go +++ b/test/integration/regression_apk_scanner_buffer_size_test.go @@ -1,6 +1,7 @@ package integration import ( + "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/syft/pkg" @@ -9,7 +10,7 @@ import ( func TestRegression212ApkBufferSize(t *testing.T) { // This is a regression test for issue #212 (https://github.com/anchore/syft/issues/212) in which the apk db could // not be processed due to a scanner buffer that was too small - sbom, _ := catalogFixtureImage(t, "image-large-apk-data") + sbom, _ := catalogFixtureImage(t, "image-large-apk-data", source.SquashedScope) expectedPkgs := 58 actualPkgs := 0 diff --git a/test/integration/regression_go_bin_scanner_arch_test.go b/test/integration/regression_go_bin_scanner_arch_test.go index 5b364d8f9e3..295dd4f10c6 100644 --- a/test/integration/regression_go_bin_scanner_arch_test.go +++ b/test/integration/regression_go_bin_scanner_arch_test.go @@ -1,6 +1,7 @@ package integration import ( + "github.com/anchore/syft/syft/source" "strings" "testing" @@ -15,12 +16,12 @@ func TestRegressionGoArchDiscovery(t *testing.T) { ) // This is a regression test to make sure the way we detect go binary packages // stays consistent and reproducible as the tool chain evolves - sbom, _ := catalogFixtureImage(t, "image-go-bin-arch-coverage") + sbom, _ := catalogFixtureImage(t, "image-go-bin-arch-coverage", source.SquashedScope) var actualELF, actualWIN, actualMACOS int for p := range sbom.Artifacts.PackageCatalog.Enumerate(pkg.GoModulePkg) { - for _, l := range p.Locations { + for _, l := range p.Locations.ToSlice() { switch { case strings.Contains(l.RealPath, "elf"): actualELF++ diff --git a/test/integration/regression_java_no_main_package_test.go b/test/integration/regression_java_no_main_package_test.go index a5f41ddaf84..417002dc923 100644 --- a/test/integration/regression_java_no_main_package_test.go +++ b/test/integration/regression_java_no_main_package_test.go @@ -1,9 +1,10 @@ package integration import ( + "github.com/anchore/syft/syft/source" "testing" ) func TestRegressionJavaNoMainPackage(t *testing.T) { // Regression: https://github.com/anchore/syft/issues/252 - catalogFixtureImage(t, "image-java-no-main-package") + catalogFixtureImage(t, "image-java-no-main-package", source.SquashedScope) } diff --git a/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile b/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile new file mode 100644 index 00000000000..ebe48155d3f --- /dev/null +++ b/test/integration/test-fixtures/image-vertical-package-dups/Dockerfile @@ -0,0 +1,6 @@ +FROM centos:7.9.2009 +# modifying the RPM DB multiple times will result in duplicate packages when using all-layers (if there was no de-dup logic) +# curl is tricky, it already exists in the image and is being upgraded +RUN yum install -y wget curl +RUN yum install -y vsftpd +RUN yum install -y httpd \ No newline at end of file diff --git a/test/integration/utils_test.go b/test/integration/utils_test.go index fd33eba8276..f05bb100a32 100644 --- a/test/integration/utils_test.go +++ b/test/integration/utils_test.go @@ -13,7 +13,7 @@ import ( "github.com/anchore/syft/syft/source" ) -func catalogFixtureImage(t *testing.T, fixtureImageName string) (sbom.SBOM, *source.Source) { +func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Scope) (sbom.SBOM, *source.Source) { imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName) tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName) userInput := "docker-archive:" + tarPath @@ -25,7 +25,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string) (sbom.SBOM, *sou // TODO: this would be better with functional options (after/during API refactor) c := cataloger.DefaultConfig() - c.Search.Scope = source.SquashedScope + c.Search.Scope = scope pkgCatalog, relationships, actualDistro, err := syft.CatalogPackages(theSource, c) if err != nil { t.Fatalf("failed to catalog image: %+v", err) From 1aeda6bb506dafce7432bd462c829c35df1dfafd Mon Sep 17 00:00:00 2001 From: Oscar Hallgren Date: Fri, 1 Apr 2022 16:42:22 +0200 Subject: [PATCH 11/31] use filepath.Base() instead of path.Base() for temp files (#882) --- syft/pkg/cataloger/java/save_archive_to_tmp.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/java/save_archive_to_tmp.go b/syft/pkg/cataloger/java/save_archive_to_tmp.go index ff7c83a5752..e8a4abe4749 100644 --- a/syft/pkg/cataloger/java/save_archive_to_tmp.go +++ b/syft/pkg/cataloger/java/save_archive_to_tmp.go @@ -5,14 +5,13 @@ import ( "io" "io/ioutil" "os" - "path" "path/filepath" "github.com/anchore/syft/internal/log" ) func saveArchiveToTmp(archiveVirtualPath string, reader io.Reader) (string, string, func(), error) { - name := path.Base(archiveVirtualPath) + name := filepath.Base(archiveVirtualPath) tempDir, err := ioutil.TempDir("", "syft-archive-contents-") if err != nil { return "", "", func() {}, fmt.Errorf("unable to create tempdir for archive processing: %w", err) From 68b7ad9770d0d97a5fb034a858cc975fcb6236bd Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 1 Apr 2022 11:30:21 -0400 Subject: [PATCH 12/31] Additionally publish docker images to GHCR (#934) --- .goreleaser.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 86b742b9dd1..9e5e2c4b16b 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -99,6 +99,11 @@ dockers: - "anchore/syft:{{ .Tag }}-amd64" - "anchore/syft:v{{ .Major }}-amd64" - "anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64" + - "ghcr.io/anchore/syft:latest" + - "ghcr.io/anchore/syft:{{ .Tag }}-amd64" + - "ghcr.io/anchore/syft:v{{ .Major }}-amd64" + - "ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64" + goarch: amd64 dockerfile: Dockerfile use: buildx build_flag_templates: @@ -112,6 +117,9 @@ dockers: - "anchore/syft:{{ .Tag }}-arm64v8" - "anchore/syft:v{{ .Major }}-arm64v8" - "anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8" + - "ghcr.io/anchore/syft:{{ .Tag }}-arm64v8" + - "ghcr.io/anchore/syft:v{{ .Major }}-arm64v8" + - "ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8" goarch: arm64 dockerfile: Dockerfile use: buildx @@ -131,3 +139,11 @@ docker_manifests: image_templates: - anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64 - anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8 + - name_template: ghcr.io/anchore/syft:{{ .Tag }} + image_templates: + - ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64 + - ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8 + - name_template: ghcr.io/anchore/syft:latest + image_templates: + - ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64 + - ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8 From 8bc5d84481f0bf4c3f8a3be4d7fc9e6ad89c30b8 Mon Sep 17 00:00:00 2001 From: Sambhav Kothari Date: Fri, 1 Apr 2022 17:19:30 +0100 Subject: [PATCH 13/31] Ensure that all cyclonedx components have bom-refs (#914) Co-authored-by: Alex Goodman --- .../common/cyclonedxhelpers/component.go | 15 +++++ .../common/cyclonedxhelpers/component_test.go | 52 ++++++++++++++++++ internal/formats/common/testutils/utils.go | 8 +-- .../TestCycloneDxDirectoryEncoder.golden | 8 ++- .../snapshot/TestCycloneDxImageEncoder.golden | 14 +++-- .../stereoscope-fixture-image-simple.golden | Bin 15360 -> 15360 bytes .../TestCycloneDxDirectoryEncoder.golden | 10 ++-- .../snapshot/TestCycloneDxImageEncoder.golden | 16 +++--- .../stereoscope-fixture-image-simple.golden | Bin 15360 -> 15360 bytes .../TestSPDXJSONDirectoryEncoder.golden | 6 +- .../snapshot/TestSPDXJSONImageEncoder.golden | 6 +- .../TestSPDXTagValueDirectoryEncoder.golden | 6 +- .../TestSPDXTagValueImageEncoder.golden | 6 +- .../snapshot/TestDirectoryEncoder.golden | 2 +- .../snapshot/TestImageEncoder.golden | 2 +- 15 files changed, 111 insertions(+), 40 deletions(-) diff --git a/internal/formats/common/cyclonedxhelpers/component.go b/internal/formats/common/cyclonedxhelpers/component.go index 949d6d004d0..d4f6606aeaf 100644 --- a/internal/formats/common/cyclonedxhelpers/component.go +++ b/internal/formats/common/cyclonedxhelpers/component.go @@ -5,6 +5,7 @@ import ( "github.com/CycloneDX/cyclonedx-go" + "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal/formats/common" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" @@ -39,9 +40,23 @@ func encodeComponent(p pkg.Package) cyclonedx.Component { Description: encodeDescription(p), ExternalReferences: encodeExternalReferences(p), Properties: properties, + BOMRef: deriveBomRef(p), } } +func deriveBomRef(p pkg.Package) string { + // try and parse the PURL if possible and append syft id to it, to make + // the purl unique in the BOM. + // TODO: In the future we may want to dedupe by PURL and combine components with + // the same PURL while preserving their unique metadata. + if parsedPURL, err := packageurl.FromString(p.PURL); err == nil { + parsedPURL.Qualifiers = append(parsedPURL.Qualifiers, packageurl.Qualifier{Key: "syft-id", Value: string(p.ID())}) + return parsedPURL.ToString() + } + // fallback is to use strictly the ID if there is no valid pURL + return string(p.ID()) +} + func hasMetadata(p pkg.Package) bool { return p.Metadata != nil } diff --git a/internal/formats/common/cyclonedxhelpers/component_test.go b/internal/formats/common/cyclonedxhelpers/component_test.go index 4a6dc50518a..ab7f3b812bb 100644 --- a/internal/formats/common/cyclonedxhelpers/component_test.go +++ b/internal/formats/common/cyclonedxhelpers/component_test.go @@ -1,6 +1,7 @@ package cyclonedxhelpers import ( + "fmt" "testing" "github.com/CycloneDX/cyclonedx-go" @@ -139,3 +140,54 @@ func Test_encodeComponentProperties(t *testing.T) { }) } } + +func Test_deriveBomRef(t *testing.T) { + pkgWithPurl := pkg.Package{ + Name: "django", + Version: "1.11.1", + PURL: "pkg:pypi/django@1.11.1", + } + pkgWithPurl.SetID() + + pkgWithOutPurl := pkg.Package{ + Name: "django", + Version: "1.11.1", + PURL: "", + } + pkgWithOutPurl.SetID() + + pkgWithBadPurl := pkg.Package{ + Name: "django", + Version: "1.11.1", + PURL: "pkg:pyjango@1.11.1", + } + pkgWithBadPurl.SetID() + + tests := []struct { + name string + pkg pkg.Package + want string + }{ + { + name: "use pURL-id hybrid", + pkg: pkgWithPurl, + want: fmt.Sprintf("pkg:pypi/django@1.11.1?syft-id=%s", pkgWithPurl.ID()), + }, + { + name: "fallback to ID when pURL is invalid", + pkg: pkgWithBadPurl, + want: string(pkgWithBadPurl.ID()), + }, + { + name: "fallback to ID when pURL is missing", + pkg: pkgWithOutPurl, + want: string(pkgWithOutPurl.ID()), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.pkg.ID() + assert.Equal(t, tt.want, deriveBomRef(tt.pkg)) + }) + } +} diff --git a/internal/formats/common/testutils/utils.go b/internal/formats/common/testutils/utils.go index 809889456cb..b1004d506fb 100644 --- a/internal/formats/common/testutils/utils.go +++ b/internal/formats/common/testutils/utils.go @@ -169,7 +169,7 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) { Name: "package-1", Version: "1.0.1", }, - PURL: "a-purl-1", + PURL: "a-purl-1", // intentionally a bad pURL for test fixtures CPEs: []pkg.CPE{ pkg.MustCPE("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"), }, @@ -187,7 +187,7 @@ func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) { Package: "package-2", Version: "2.0.1", }, - PURL: "a-purl-2", + PURL: "pkg:deb/debian/package-2@2.0.1", CPEs: []pkg.CPE{ pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, @@ -249,7 +249,7 @@ func newDirectoryCatalog() *pkg.Catalog { }, }, }, - PURL: "a-purl-2", + PURL: "a-purl-2", // intentionally a bad pURL for test fixtures CPEs: []pkg.CPE{ pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, @@ -267,7 +267,7 @@ func newDirectoryCatalog() *pkg.Catalog { Package: "package-2", Version: "2.0.1", }, - PURL: "a-purl-2", + PURL: "pkg:deb/debian/package-2@2.0.1", CPEs: []pkg.CPE{ pkg.MustCPE("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"), }, diff --git a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index 3063fdd1c8c..69b562d973e 100644 --- a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -1,10 +1,10 @@ { "bomFormat": "CycloneDX", "specVersion": "1.4", - "serialNumber": "urn:uuid:498e659b-0758-4a7f-816e-91bee18df634", + "serialNumber": "urn:uuid:dec3f6b4-8458-48bb-b60d-dfd312f6ec4e", "version": 1, "metadata": { - "timestamp": "2022-03-08T12:30:39Z", + "timestamp": "2022-04-01T11:48:04-04:00", "tools": [ { "vendor": "anchore", @@ -20,6 +20,7 @@ }, "components": [ { + "bom-ref": "b85dbb4e6ece5082", "type": "library", "name": "package-1", "version": "1.0.1", @@ -56,11 +57,12 @@ ] }, { + "bom-ref": "pkg:deb/debian/package-2@2.0.1?syft-id=ceda99598967ae8d", "type": "library", "name": "package-2", "version": "2.0.1", "cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "purl": "a-purl-2", + "purl": "pkg:deb/debian/package-2@2.0.1", "properties": [ { "name": "syft:package:foundBy", diff --git a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index 62f5871eb4d..14478f6c8dd 100644 --- a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -1,10 +1,10 @@ { "bomFormat": "CycloneDX", "specVersion": "1.4", - "serialNumber": "urn:uuid:342c3d2c-d26e-47b6-94d6-92fbf41da945", + "serialNumber": "urn:uuid:054d973e-fe99-4762-92e4-eaf01997ae41", "version": 1, "metadata": { - "timestamp": "2022-03-08T12:30:39Z", + "timestamp": "2022-04-01T11:48:04-04:00", "tools": [ { "vendor": "anchore", @@ -13,7 +13,7 @@ } ], "component": { - "bom-ref": "711095b1cdf90cce", + "bom-ref": "e777314b02b362e4", "type": "container", "name": "user-image-input", "version": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368" @@ -21,6 +21,7 @@ }, "components": [ { + "bom-ref": "2a46171f91c8d4bc", "type": "library", "name": "package-1", "version": "1.0.1", @@ -52,7 +53,7 @@ }, { "name": "syft:location:0:layerID", - "value": "sha256:16e64541f2ddf59a90391ce7bb8af90313f7d373f2105d88f3d3267b72e0ebab" + "value": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59" }, { "name": "syft:location:0:path", @@ -61,11 +62,12 @@ ] }, { + "bom-ref": "pkg:deb/debian/package-2@2.0.1?syft-id=ae77680e9b1d087e", "type": "library", "name": "package-2", "version": "2.0.1", "cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", - "purl": "a-purl-2", + "purl": "pkg:deb/debian/package-2@2.0.1", "properties": [ { "name": "syft:package:foundBy", @@ -81,7 +83,7 @@ }, { "name": "syft:location:0:layerID", - "value": "sha256:de6c235f76ea24c8503ec08891445b5d6a8bdf8249117ed8d8b0b6fb3ebe4f67" + "value": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec" }, { "name": "syft:location:0:path", diff --git a/internal/formats/cyclonedxjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/formats/cyclonedxjson/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index c483fa49b75941b2cfb6a6819ff94a681f25ee41..5b5b8030509a612ac6c0d1e630d5a86b6f232f65 100644 GIT binary patch literal 15360 zcmeHOS#R4$5Y}^lh04C#(%!oi(1$cOkN`nlByI{cFpRxuvzADKqyig;|9gj$EK5pa z#wH~=?GggC=WzBL4tI_v#?Cq6Of0-qNy3oA%1In^$C;+u8t*VgQrp-moJh@}kT~j; zk_i=*4SUTOLJUdHduVZO|JSWO%m|W-x+QcVFg&@vJX2t^PzT*a0% z&z*4^V<9Bvh!I7Z1KUCwjx;ySlbBOOBvG-n#5e-9Y~gj~YsLs7#e z8YOyM`h#fImd{`*+l{_}smsRG>Sk3wnfh##&b)S#Szuy0{y6&_jk4Kzd=R~!z{(cI zw-bG_Wb|V`o=tpt-}6^qT&3B?QM%;zIID`AX`a>)FXob`T}OAFsN`OWv{n4!Sl{?!P}|Voyc*vB>`VKf5F*0+|C@kz*iq&a zpQK}dNCwq))gj?EQVsG);P1iykBGpSa4dTWV@bpQzlPxMiVNBI>wOe<@ABu}-6>EG z2m}NI0s(=SgaE{N6GJW0%n_nkOf5Hvv&373A@&;+OO0mQ3WkZ25b*VhB~)VY>jc6+ z9(3UU6Z%E`4?!3>#Q*m2pxj2^aBCj?>AC0Hk*Bud)z(hfh7()6t>5eUU#4Z17vO_` zx^0?-2t$<4!vzcK=LY6Qua1uTbMpt+rf+|^GKClQU;3tYudmVy*tGd%vW#vl8wW18 zSH7qT3_hdi?x2y4wW!5c*_d14Yium)Ph@im3Ii+1Pp%ek%yd;^3Z{W2fLp_7)U~avBY^Bo!$L_ z&h#Giwd-574c6@>|A!%4$U^?FYgvDdUTgX9B>#s5CSm{on!LJh!y*6IHKacjz1I5Q z-u_2|;H~^0VsKm_*#CQYl9u_uwvRz=BCjlW97_ZVyEUT@Rs-OVkV^FQ_ZkIno~c>nK47TZ)Sh@;G-ApJ{SuF^o;qe49( z5D*9m1O)zT2uyUACcdn`Cy(>owKwhmoYS?l;AnpSBgB86i}uszLH6YJ^5kUHNiGmP z!S{ZepX!T6W})(h&r6$6{b7<`*JtMr)B4ckVVO>*V?R3-JOktbjI0FPZP|Z zMi(HfGKEZ9>dRf-vPu8R!?!{8S2VT$3lZYKyAsC+-P@>a(9k+}*jh~xkKnoO0(Pka6pa>|wBwB6BkmRC4kpI4u>^N?+ zMoXlq8A`!`M3Fq5?szos;UhwsawN7!<0N9G_Y)S?;cIte-{TyY9lK0QOTOY|x)t4uE(r~oYv^93}xDgRNrVqJ4kRoa}tuWXv3 znb-5u?V;_xd{y1O=?dt&X?a{-Y_E@&F8f+eQ##5FD6wh(GW(2X*=j!DLoXKaM(fMh z3w^dx^g}*hEnInB^JiXsO0%=WbffLdtST;+d76P<>%K?XZ>w~^74=3ZZocV$wTE)J zMDsLTeL+_(vD9~USI1B1`oa~HdJXl>qb2_N-Sr<)M1}bOra^nGDD#E$>D=v;N%f`b zQSgqa7XM>R<#ztZoQyCbip${t9TPs;Wp$pG<9Yy$&viMjr)ZZ|<&!-w2o4qq76=vy z7I-EWkXR;>QJOjuMLGc>kW#?ll#rO}NXN`L>ZPLE8N%UAW9PMHF&D;L?a342f1pFa z|ArVMo&Enb_#X}V{}A3EjYz=%hB5RreM;x}?~eb~8$a9pZ@vFR2n+cCAR}gj|8*S( z0NyQi0jXo(SR#eZ$9+O;ERoO|VKdGq91|839x%oGFvb4`#(IL@9vr{=b-F5x={z@j zJ}r|po9&dh#hZ%e*18Cn=;LER+9?d!hoZE)Fz0FIOtmU%7+5c?qS?n;^+;|qdNe}ryWq0_0 zkoJZ3-w>nc5`81Bxyc_JHcU^M+E+}OItlxV7z0$88x~PZ<`4VURbBwE=j5`b6XQ%W zP8+yj%~3i{pdUIoJZyHp*VKpcbh{L8s1V~{#z{@t`IJ_mrpXtJHM((qb7FJz$rbhb zY4RDPtGzZgc2SFeRijyf@2IgZKTr+GhIbOuJyhg*<$+#wiK>fbowhc7of2Njrrw{X z7V1t=d9JCDGa{Yjf)fuEZ!cmUW58LAQ%MqO4+X-!vP>~g2^KbrJhO~Sl_=`4OLPKK zH?k!Nsqw!zH3zYITz_;%c#rJBV1ZzP JV1eE(@DIZvjQs!r diff --git a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index 3e416a26e26..b75e0c629dd 100644 --- a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -1,7 +1,7 @@ - + - 2022-03-08T12:30:33Z + 2022-04-01T11:57:46-04:00 anchore @@ -14,7 +14,7 @@ - + package-1 1.0.1 @@ -32,11 +32,11 @@ /some/path/pkg1 - + package-2 2.0.1 cpe:2.3:*:some:package:2:*:*:*:*:*:*:* - a-purl-2 + pkg:deb/debian/package-2@2.0.1 the-cataloger-2 DpkgMetadata diff --git a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index 5d1b9dae417..a82e85c7f45 100644 --- a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -1,7 +1,7 @@ - + - 2022-03-08T12:30:33Z + 2022-04-01T11:57:46-04:00 anchore @@ -9,13 +9,13 @@ [not provided] - + user-image-input sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368 - + package-1 1.0.1 @@ -30,20 +30,20 @@ python PythonPackageMetadata python - sha256:16e64541f2ddf59a90391ce7bb8af90313f7d373f2105d88f3d3267b72e0ebab + sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59 /somefile-1.txt - + package-2 2.0.1 cpe:2.3:*:some:package:2:*:*:*:*:*:*:* - a-purl-2 + pkg:deb/debian/package-2@2.0.1 the-cataloger-2 DpkgMetadata deb - sha256:de6c235f76ea24c8503ec08891445b5d6a8bdf8249117ed8d8b0b6fb3ebe4f67 + sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec /somefile-2.txt 0 diff --git a/internal/formats/cyclonedxxml/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/formats/cyclonedxxml/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index c483fa49b75941b2cfb6a6819ff94a681f25ee41..5b5b8030509a612ac6c0d1e630d5a86b6f232f65 100644 GIT binary patch literal 15360 zcmeHOS#R4$5Y}^lh04C#(%!oi(1$cOkN`nlByI{cFpRxuvzADKqyig;|9gj$EK5pa z#wH~=?GggC=WzBL4tI_v#?Cq6Of0-qNy3oA%1In^$C;+u8t*VgQrp-moJh@}kT~j; zk_i=*4SUTOLJUdHduVZO|JSWO%m|W-x+QcVFg&@vJX2t^PzT*a0% z&z*4^V<9Bvh!I7Z1KUCwjx;ySlbBOOBvG-n#5e-9Y~gj~YsLs7#e z8YOyM`h#fImd{`*+l{_}smsRG>Sk3wnfh##&b)S#Szuy0{y6&_jk4Kzd=R~!z{(cI zw-bG_Wb|V`o=tpt-}6^qT&3B?QM%;zIID`AX`a>)FXob`T}OAFsN`OWv{n4!Sl{?!P}|Voyc*vB>`VKf5F*0+|C@kz*iq&a zpQK}dNCwq))gj?EQVsG);P1iykBGpSa4dTWV@bpQzlPxMiVNBI>wOe<@ABu}-6>EG z2m}NI0s(=SgaE{N6GJW0%n_nkOf5Hvv&373A@&;+OO0mQ3WkZ25b*VhB~)VY>jc6+ z9(3UU6Z%E`4?!3>#Q*m2pxj2^aBCj?>AC0Hk*Bud)z(hfh7()6t>5eUU#4Z17vO_` zx^0?-2t$<4!vzcK=LY6Qua1uTbMpt+rf+|^GKClQU;3tYudmVy*tGd%vW#vl8wW18 zSH7qT3_hdi?x2y4wW!5c*_d14Yium)Ph@im3Ii+1Pp%ek%yd;^3Z{W2fLp_7)U~avBY^Bo!$L_ z&h#Giwd-574c6@>|A!%4$U^?FYgvDdUTgX9B>#s5CSm{on!LJh!y*6IHKacjz1I5Q z-u_2|;H~^0VsKm_*#CQYl9u_uwvRz=BCjlW97_ZVyEUT@Rs-OVkV^FQ_ZkIno~c>nK47TZ)Sh@;G-ApJ{SuF^o;qe49( z5D*9m1O)zT2uyUACcdn`Cy(>owKwhmoYS?l;AnpSBgB86i}uszLH6YJ^5kUHNiGmP z!S{ZepX!T6W})(h&r6$6{b7<`*JtMr)B4ckVVO>*V?R3-JOktbjI0FPZP|Z zMi(HfGKEZ9>dRf-vPu8R!?!{8S2VT$3lZYKyAsC+-P@>a(9k+}*jh~xkKnoO0(Pka6pa>|wBwB6BkmRC4kpI4u>^N?+ zMoXlq8A`!`M3Fq5?szos;UhwsawN7!<0N9G_Y)S?;cIte-{TyY9lK0QOTOY|x)t4uE(r~oYv^93}xDgRNrVqJ4kRoa}tuWXv3 znb-5u?V;_xd{y1O=?dt&X?a{-Y_E@&F8f+eQ##5FD6wh(GW(2X*=j!DLoXKaM(fMh z3w^dx^g}*hEnInB^JiXsO0%=WbffLdtST;+d76P<>%K?XZ>w~^74=3ZZocV$wTE)J zMDsLTeL+_(vD9~USI1B1`oa~HdJXl>qb2_N-Sr<)M1}bOra^nGDD#E$>D=v;N%f`b zQSgqa7XM>R<#ztZoQyCbip${t9TPs;Wp$pG<9Yy$&viMjr)ZZ|<&!-w2o4qq76=vy z7I-EWkXR;>QJOjuMLGc>kW#?ll#rO}NXN`L>ZPLE8N%UAW9PMHF&D;L?a342f1pFa z|ArVMo&Enb_#X}V{}A3EjYz=%hB5RreM;x}?~eb~8$a9pZ@vFR2n+cCAR}gj|8*S( z0NyQi0jXo(SR#eZ$9+O;ERoO|VKdGq91|839x%oGFvb4`#(IL@9vr{=b-F5x={z@j zJ}r|po9&dh#hZ%e*18Cn=;LER+9?d!hoZE)Fz0FIOtmU%7+5c?qS?n;^+;|qdNe}ryWq0_0 zkoJZ3-w>nc5`81Bxyc_JHcU^M+E+}OItlxV7z0$88x~PZ<`4VURbBwE=j5`b6XQ%W zP8+yj%~3i{pdUIoJZyHp*VKpcbh{L8s1V~{#z{@t`IJ_mrpXtJHM((qb7FJz$rbhb zY4RDPtGzZgc2SFeRijyf@2IgZKTr+GhIbOuJyhg*<$+#wiK>fbowhc7of2Njrrw{X z7V1t=d9JCDGa{Yjf)fuEZ!cmUW58LAQ%MqO4+X-!vP>~g2^KbrJhO~Sl_=`4OLPKK zH?k!Nsqw!zH3zYITz_;%c#rJBV1ZzP JV1eE(@DIZvjQs!r diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden index 22f7729c7e3..3299321a589 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden @@ -3,7 +3,7 @@ "name": "/some/path", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2022-03-30T21:48:28.297464Z", + "created": "2022-04-01T15:48:39.459232Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" @@ -11,7 +11,7 @@ "licenseListVersion": "3.16" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/dir/some/path-e188d59b-76f6-4c7f-a9f2-1ae7d0577781", + "documentNamespace": "https://anchore.com/syft/dir/some/path-8d335d81-29c9-4236-84f1-2292ea92aaf5", "packages": [ { "SPDXID": "SPDXRef-b85dbb4e6ece5082", @@ -48,7 +48,7 @@ }, { "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", + "referenceLocator": "pkg:deb/debian/package-2@2.0.1", "referenceType": "purl" } ], diff --git a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden index 7e97a75fe97..42260c91d43 100644 --- a/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden +++ b/internal/formats/spdx22json/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden @@ -3,7 +3,7 @@ "name": "user-image-input", "spdxVersion": "SPDX-2.2", "creationInfo": { - "created": "2022-03-30T21:48:28.303986Z", + "created": "2022-04-01T15:48:39.465643Z", "creators": [ "Organization: Anchore, Inc", "Tool: syft-[not provided]" @@ -11,7 +11,7 @@ "licenseListVersion": "3.16" }, "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/image/user-image-input-9e4f4190-c5ae-4e31-a852-d1ab71357516", + "documentNamespace": "https://anchore.com/syft/image/user-image-input-e64e0be8-5031-4eec-842d-e59fb6deb518", "packages": [ { "SPDXID": "SPDXRef-2a46171f91c8d4bc", @@ -48,7 +48,7 @@ }, { "referenceCategory": "PACKAGE_MANAGER", - "referenceLocator": "a-purl-2", + "referenceLocator": "pkg:deb/debian/package-2@2.0.1", "referenceType": "purl" } ], diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden index 7959c2f0d34..ba0ba4c69a6 100644 --- a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.2 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: /some/path -DocumentNamespace: https://anchore.com/syft/dir/some/path-71aa3553-1a73-405f-9f1f-6347d6d4593b +DocumentNamespace: https://anchore.com/syft/dir/some/path-d227b0f2-4ee8-4e10-ac43-019db86d16ff LicenseListVersion: 3.16 Creator: Organization: Anchore, Inc Creator: Tool: syft-[not provided] -Created: 2022-03-30T21:48:22Z +Created: 2022-04-01T15:48:44Z ##### Package: package-2 @@ -19,7 +19,7 @@ PackageLicenseConcluded: NONE PackageLicenseDeclared: NONE PackageCopyrightText: NOASSERTION ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:2:*:*:*:*:*:*:* -ExternalRef: PACKAGE_MANAGER purl a-purl-2 +ExternalRef: PACKAGE_MANAGER purl pkg:deb/debian/package-2@2.0.1 ##### Package: package-1 diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden index 4d9011b1cdd..f2e7d394f0e 100644 --- a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.2 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: user-image-input -DocumentNamespace: https://anchore.com/syft/image/user-image-input-e46e20f4-43a4-40e7-9f82-fd55b8a89e5f +DocumentNamespace: https://anchore.com/syft/image/user-image-input-49f98c61-3418-4427-9e00-8b1c735e9799 LicenseListVersion: 3.16 Creator: Organization: Anchore, Inc Creator: Tool: syft-[not provided] -Created: 2022-03-30T21:48:22Z +Created: 2022-04-01T15:48:44Z ##### Package: package-2 @@ -19,7 +19,7 @@ PackageLicenseConcluded: NONE PackageLicenseDeclared: NONE PackageCopyrightText: NOASSERTION ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:2:*:*:*:*:*:*:* -ExternalRef: PACKAGE_MANAGER purl a-purl-2 +ExternalRef: PACKAGE_MANAGER purl pkg:deb/debian/package-2@2.0.1 ##### Package: package-1 diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden index 71d089e1947..ae51ed71720 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden @@ -51,7 +51,7 @@ "cpes": [ "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*" ], - "purl": "a-purl-2", + "purl": "pkg:deb/debian/package-2@2.0.1", "metadataType": "DpkgMetadata", "metadata": { "package": "package-2", diff --git a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden index a2f5673d096..10a5ced626f 100644 --- a/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden +++ b/internal/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden @@ -48,7 +48,7 @@ "cpes": [ "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*" ], - "purl": "a-purl-2", + "purl": "pkg:deb/debian/package-2@2.0.1", "metadataType": "DpkgMetadata", "metadata": { "package": "package-2", From 748cfbf00647df3366ec3c4ad89d87762625da5a Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 6 Apr 2022 12:27:13 -0400 Subject: [PATCH 14/31] Retry auth URL lookup without docker credentialhelper workaround (#939) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5c5d07c5fdf..f8ab5716a8e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ 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.20220314153042-1bcd40e5206b - github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0 + github.com/anchore/stereoscope v0.0.0-20220406160859-c03a18a6b270 github.com/antihax/optional v1.0.0 github.com/bmatcuk/doublestar/v4 v4.0.2 github.com/dustin/go-humanize v1.0.0 diff --git a/go.sum b/go.sum index 8f8c09a9b0e..3e744bce2ff 100644 --- a/go.sum +++ b/go.sum @@ -280,8 +280,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.20220314153042-1bcd40e5206b h1:YJWYt/6KQXR9JR46lLHrTTYi8rcye42tKcyjREA/hvA= github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0 h1:mObz7bepZ6DtbIrsB2mxuOE9XEYmVtA/P/EDlKwfbjs= -github.com/anchore/stereoscope v0.0.0-20220330165332-7fc73ee7b0f0/go.mod h1:yoCLUZY0k/pYLNIy0L80p2Ko0PKVNXm8rHtgxp4OiSc= +github.com/anchore/stereoscope v0.0.0-20220406160859-c03a18a6b270 h1:NmxPDR6vo3xjwCL6o+tpF1vUad/BVo+WaVSwueB9W9w= +github.com/anchore/stereoscope v0.0.0-20220406160859-c03a18a6b270/go.mod h1:yoCLUZY0k/pYLNIy0L80p2Ko0PKVNXm8rHtgxp4OiSc= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= From e415bb21e7a609c12dc37a2d6395796fb675e3fe Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 6 Apr 2022 17:15:55 -0400 Subject: [PATCH 15/31] Update write permissions and log into ghcr.io for release (#942) --- .github/scripts/apple-signing/setup-prod.sh | 9 +++++++++ .github/workflows/release.yaml | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/.github/scripts/apple-signing/setup-prod.sh b/.github/scripts/apple-signing/setup-prod.sh index 283a8673d4c..277831f73fb 100755 --- a/.github/scripts/apple-signing/setup-prod.sh +++ b/.github/scripts/apple-signing/setup-prod.sh @@ -21,6 +21,14 @@ fi if [ -z "$DOCKER_PASSWORD" ]; then exit_with_error "DOCKER_PASSWORD not set" fi + +if [ -z "$GHCR_USERNAME" ]; then + exit_with_error "GHCR_USERNAME not set" +fi + +if [ -z "$GHCR_PASSWORD" ]; then + exit_with_error "GHCR_PASSWORD not set" +fi set -u # setup_signing @@ -41,4 +49,5 @@ setup_signing() { commentary "log into docker -- required for publishing (since the default keychain has now been replaced)" echo "${DOCKER_PASSWORD}" | docker login docker.io -u "${DOCKER_USERNAME}" --password-stdin + echo "${GHCR_PASSWORD}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin } diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c3f25376c2a..35f3ff80a6e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -94,6 +94,8 @@ jobs: needs: [quality-gate] # due to our code signing process, it's vital that we run our release steps on macOS runs-on: macos-latest + permissions: + packages: write steps: - uses: docker-practice/actions-setup-docker@v1 @@ -128,6 +130,8 @@ jobs: - name: Build & publish release artifacts run: make release env: + GHCR_USERNAME: ${{ github.actor }} + GHCR_PASSWORD: ${{ secrets.GITHUB_TOKEN }} DOCKER_USERNAME: ${{ secrets.TOOLBOX_DOCKER_USER }} DOCKER_PASSWORD: ${{ secrets.TOOLBOX_DOCKER_PASS }} # we use a different token than GITHUB_SECRETS to additionally allow updating the homebrew repos From 782b2e334808f9021dab10f9aa8f21207ec0e12d Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Fri, 8 Apr 2022 15:12:32 -0400 Subject: [PATCH 16/31] Add digest property to parent and nested java package metadata (#941) --- .../cyclonedxhelpers/external_references.go | 32 +++++++++++++++- .../common/spdxhelpers/external_refs.go | 1 + .../common/spdxhelpers/to_syft_model.go | 8 ++++ .../formats/spdx22json/to_format_model.go | 22 ++++++++++- .../formats/spdx22tagvalue/to_format_model.go | 21 +++++++++- syft/file/digest_cataloger.go | 23 +++++++---- syft/pkg/cataloger/java/archive_parser.go | 38 ++++++++++++++++--- .../pkg/cataloger/java/archive_parser_test.go | 6 ++- syft/pkg/java_metadata.go | 14 ++++--- 9 files changed, 141 insertions(+), 24 deletions(-) diff --git a/internal/formats/common/cyclonedxhelpers/external_references.go b/internal/formats/common/cyclonedxhelpers/external_references.go index 5cc75302166..e94a60111c6 100644 --- a/internal/formats/common/cyclonedxhelpers/external_references.go +++ b/internal/formats/common/cyclonedxhelpers/external_references.go @@ -4,12 +4,15 @@ import ( "fmt" "strings" + syftFile "github.com/anchore/syft/syft/file" + "github.com/CycloneDX/cyclonedx-go" "github.com/anchore/syft/syft/pkg" ) +//nolint:funlen, gocognit func encodeExternalReferences(p pkg.Package) *[]cyclonedx.ExternalReference { - refs := []cyclonedx.ExternalReference{} + var refs []cyclonedx.ExternalReference if hasMetadata(p) { switch metadata := p.Metadata.(type) { case pkg.ApkMetadata: @@ -46,6 +49,19 @@ func encodeExternalReferences(p pkg.Package) *[]cyclonedx.ExternalReference { Type: cyclonedx.ERTypeWebsite, }) } + case pkg.JavaMetadata: + if len(metadata.ArchiveDigests) > 0 { + for _, digest := range metadata.ArchiveDigests { + refs = append(refs, cyclonedx.ExternalReference{ + URL: "", + Type: cyclonedx.ERTypeBuildMeta, + Hashes: &[]cyclonedx.Hash{{ + Algorithm: cyclonedx.HashAlgorithm(digest.Algorithm), + Value: digest.Value, + }}, + }) + } + } case pkg.PythonPackageMetadata: if metadata.DirectURLOrigin != nil && metadata.DirectURLOrigin.URL != "" { ref := cyclonedx.ExternalReference{ @@ -79,6 +95,20 @@ func decodeExternalReferences(c *cyclonedx.Component, metadata interface{}) { meta.Homepage = refURL(c, cyclonedx.ERTypeWebsite) case *pkg.GemMetadata: meta.Homepage = refURL(c, cyclonedx.ERTypeWebsite) + case *pkg.JavaMetadata: + var digests []syftFile.Digest + if ref := findExternalRef(c, cyclonedx.ERTypeBuildMeta); ref != nil { + if ref.Hashes != nil { + for _, hash := range *ref.Hashes { + digests = append(digests, syftFile.Digest{ + Algorithm: string(hash.Algorithm), + Value: hash.Value, + }) + } + } + } + + meta.ArchiveDigests = digests case *pkg.PythonPackageMetadata: if meta.DirectURLOrigin == nil { meta.DirectURLOrigin = &pkg.PythonDirectURLOriginInfo{} diff --git a/internal/formats/common/spdxhelpers/external_refs.go b/internal/formats/common/spdxhelpers/external_refs.go index 384282cb038..d114c2ab279 100644 --- a/internal/formats/common/spdxhelpers/external_refs.go +++ b/internal/formats/common/spdxhelpers/external_refs.go @@ -22,5 +22,6 @@ func ExternalRefs(p pkg.Package) (externalRefs []ExternalRef) { ReferenceType: PurlExternalRefType, }) } + return externalRefs } diff --git a/internal/formats/common/spdxhelpers/to_syft_model.go b/internal/formats/common/spdxhelpers/to_syft_model.go index ade236089e9..a36eac3de24 100644 --- a/internal/formats/common/spdxhelpers/to_syft_model.go +++ b/internal/formats/common/spdxhelpers/to_syft_model.go @@ -309,6 +309,14 @@ func extractMetadata(p *spdx.Package2_2, info pkgInfo) (pkg.MetadataType, interf Architecture: arch, Maintainer: p.PackageOriginatorPerson, } + case pkg.JavaPkg: + var digests []file.Digest + for algorithm, value := range p.PackageChecksums { + digests = append(digests, file.Digest{Algorithm: string(algorithm), Value: value.Value}) + } + return pkg.JavaMetadataType, pkg.JavaMetadata{ + ArchiveDigests: digests, + } } return pkg.UnknownMetadataType, nil } diff --git a/internal/formats/spdx22json/to_format_model.go b/internal/formats/spdx22json/to_format_model.go index 761993b3ece..2e1a0c65cff 100644 --- a/internal/formats/spdx22json/to_format_model.go +++ b/internal/formats/spdx22json/to_format_model.go @@ -55,14 +55,32 @@ func toPackages(catalog *pkg.Catalog, relationships []artifact.Relationship) []m for _, p := range catalog.Sorted() { license := spdxhelpers.License(p) packageSpdxID := model.ElementID(p.ID()).String() - + filesAnalyzed := false + + // we generate digest for some Java packages + // see page 33 of the spdx specification for 2.2 + // spdx.github.io/spdx-spec/package-information/#710-package-checksum-field + var checksums []model.Checksum + if p.MetadataType == pkg.JavaMetadataType { + javaMetadata := p.Metadata.(pkg.JavaMetadata) + if len(javaMetadata.ArchiveDigests) > 0 { + filesAnalyzed = true + for _, digest := range javaMetadata.ArchiveDigests { + checksums = append(checksums, model.Checksum{ + Algorithm: digest.Algorithm, + ChecksumValue: digest.Value, + }) + } + } + } // note: the license concluded and declared should be the same since we are collecting license information // from the project data itself (the installed package files). packages = append(packages, model.Package{ + Checksums: checksums, Description: spdxhelpers.Description(p), DownloadLocation: spdxhelpers.DownloadLocation(p), ExternalRefs: spdxhelpers.ExternalRefs(p), - FilesAnalyzed: false, + FilesAnalyzed: filesAnalyzed, HasFiles: fileIDsForPackage(packageSpdxID, relationships), Homepage: spdxhelpers.Homepage(p), // The Declared License is what the authors of a project believe govern the package diff --git a/internal/formats/spdx22tagvalue/to_format_model.go b/internal/formats/spdx22tagvalue/to_format_model.go index a52aba13b1b..2f0d84ba726 100644 --- a/internal/formats/spdx22tagvalue/to_format_model.go +++ b/internal/formats/spdx22tagvalue/to_format_model.go @@ -103,6 +103,24 @@ func toFormatPackages(catalog *pkg.Catalog) map[spdx.ElementID]*spdx.Package2_2 // the Comments on License field (section 3.16) is preferred. license := spdxhelpers.License(p) + filesAnalyzed := false + checksums := make(map[spdx.ChecksumAlgorithm]spdx.Checksum) + + // If the pkg type is Java we have attempted to generated a digest + // FilesAnalyzed should be true in this case + if p.MetadataType == pkg.JavaMetadataType { + javaMetadata := p.Metadata.(pkg.JavaMetadata) + if len(javaMetadata.ArchiveDigests) > 0 { + filesAnalyzed = true + for _, digest := range javaMetadata.ArchiveDigests { + checksums[spdx.ChecksumAlgorithm(digest.Algorithm)] = spdx.Checksum{ + Algorithm: spdx.ChecksumAlgorithm(digest.Algorithm), + Value: digest.Value, + } + } + } + } + results[spdx.ElementID(id)] = &spdx.Package2_2{ // NOT PART OF SPEC @@ -159,7 +177,7 @@ func toFormatPackages(catalog *pkg.Catalog) map[spdx.ElementID]*spdx.Package2_2 // Intent: A package can refer to a project, product, artifact, distribution or a component that is // external to the SPDX document. - FilesAnalyzed: false, + FilesAnalyzed: filesAnalyzed, // NOT PART OF SPEC: did FilesAnalyzed tag appear? IsFilesAnalyzedTagPresent: true, @@ -180,6 +198,7 @@ func toFormatPackages(catalog *pkg.Catalog) map[spdx.ElementID]*spdx.Package2_2 // to determine if any file in the original package has been changed. If the SPDX file is to be included // in a package, this value should not be calculated. The SHA-1 algorithm will be used to provide the // checksum by default. + PackageChecksums: checksums, // note: based on the purpose above no discovered checksums should be provided, but instead, only // tool-derived checksums. diff --git a/syft/file/digest_cataloger.go b/syft/file/digest_cataloger.go index cb80f1a85a4..edc096c16b1 100644 --- a/syft/file/digest_cataloger.go +++ b/syft/file/digest_cataloger.go @@ -77,30 +77,39 @@ func (i *DigestsCataloger) catalogLocation(resolver source.FileResolver, locatio } defer internal.CloseAndLogError(contentReader, location.VirtualPath) + digests, err := DigestsFromFile(contentReader, i.hashes) + if err != nil { + return nil, internal.ErrPath{Context: "digests-cataloger", Path: location.RealPath, Err: err} + } + + return digests, nil +} + +func DigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]Digest, error) { // create a set of hasher objects tied together with a single writer to feed content into - hashers := make([]hash.Hash, len(i.hashes)) - writers := make([]io.Writer, len(i.hashes)) - for idx, hashObj := range i.hashes { + hashers := make([]hash.Hash, len(hashes)) + writers := make([]io.Writer, len(hashes)) + for idx, hashObj := range hashes { hashers[idx] = hashObj.New() writers[idx] = hashers[idx] } - size, err := io.Copy(io.MultiWriter(writers...), contentReader) + size, err := io.Copy(io.MultiWriter(writers...), closer) if err != nil { - return nil, internal.ErrPath{Context: "digests-cataloger", Path: location.RealPath, Err: err} + return nil, err } if size == 0 { return make([]Digest, 0), nil } - result := make([]Digest, len(i.hashes)) + result := make([]Digest, len(hashes)) // only capture digests when there is content. It is important to do this based on SIZE and not // FILE TYPE. The reasoning is that it is possible for a tar to be crafted with a header-only // file type but a body is still allowed. for idx, hasher := range hashers { result[idx] = Digest{ - Algorithm: DigestAlgorithmName(i.hashes[idx]), + Algorithm: DigestAlgorithmName(hashes[idx]), Value: fmt.Sprintf("%+x", hasher.Sum(nil)), } } diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index b96f8f1827d..c49b591ee7d 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -1,14 +1,17 @@ package java import ( + "crypto" "fmt" "io" + "os" "path" "strings" "github.com/anchore/syft/internal/file" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" + syftFile "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/common" ) @@ -34,6 +37,11 @@ var archiveFormatGlobs = []string{ // project that we can build in CI feel free to include it } +// javaArchiveHashes are all the current hash algorithms used to calculate archive digests +var javaArchiveHashes = []crypto.Hash{ + crypto.SHA1, +} + type archiveParser struct { fileManifest file.ZipFileManifest virtualPath string @@ -101,6 +109,7 @@ func (j *archiveParser) parse() ([]*pkg.Package, []artifact.Relationship, error) } // find aux packages from pom.properties/pom.xml and potentially modify the existing parentPkg + // NOTE: we cannot generate sha1 digests from packages discovered via pom.properties/pom.xml auxPkgs, err := j.discoverPkgsFromAllMavenFiles(parentPkg) if err != nil { return nil, nil, err @@ -135,6 +144,7 @@ func (j *archiveParser) parse() ([]*pkg.Package, []artifact.Relationship, error) // discoverMainPackage parses the root Java manifest used as the parent package to all discovered nested packages. func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) { // search and parse java manifest files + // TODO: do we want to prefer or check for pom files over manifest here? manifestMatches := j.fileManifest.GlobMatch(manifestGlob) if len(manifestMatches) > 1 { return nil, fmt.Errorf("found multiple manifests in the jar: %+v", manifestMatches) @@ -157,6 +167,18 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) { return nil, nil } + archiveCloser, err := os.Open(j.archivePath) + if err != nil { + return nil, fmt.Errorf("unable to open archive path (%s): %w", j.archivePath, err) + } + defer archiveCloser.Close() + + // grab and assign digest for the entire archive + digests, err := syftFile.DigestsFromFile(archiveCloser, javaArchiveHashes) + if err != nil { + log.Warnf("failed to create digest for file=%q: %+v", j.archivePath, err) + } + return &pkg.Package{ Name: selectName(manifest, j.fileInfo), Version: selectVersion(manifest, j.fileInfo), @@ -164,8 +186,9 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) { Type: j.fileInfo.pkgType(), MetadataType: pkg.JavaMetadataType, Metadata: pkg.JavaMetadata{ - VirtualPath: j.virtualPath, - Manifest: manifest, + VirtualPath: j.virtualPath, + Manifest: manifest, + ArchiveDigests: digests, }, }, nil } @@ -181,12 +204,14 @@ func (j *archiveParser) discoverPkgsFromAllMavenFiles(parentPkg *pkg.Package) ([ var pkgs []*pkg.Package - properties, err := pomPropertiesByParentPath(j.archivePath, j.fileManifest.GlobMatch(pomPropertiesGlob), j.virtualPath) + // pom.properties + properties, err := pomPropertiesByParentPath(j.archivePath, j.virtualPath, j.fileManifest.GlobMatch(pomPropertiesGlob)) if err != nil { return nil, err } - projects, err := pomProjectByParentPath(j.archivePath, j.fileManifest.GlobMatch(pomXMLGlob), j.virtualPath) + // pom.xml + projects, err := pomProjectByParentPath(j.archivePath, j.virtualPath, j.fileManifest.GlobMatch(pomXMLGlob)) if err != nil { return nil, err } @@ -273,7 +298,7 @@ func discoverPkgsFromOpener(virtualPath, pathWithinArchive string, archiveOpener return nestedPkgs, nestedRelationships, nil } -func pomPropertiesByParentPath(archivePath string, extractPaths []string, virtualPath string) (map[string]pkg.PomProperties, error) { +func pomPropertiesByParentPath(archivePath, virtualPath string, extractPaths []string) (map[string]pkg.PomProperties, error) { contentsOfMavenPropertiesFiles, err := file.ContentsFromZip(archivePath, extractPaths...) if err != nil { return nil, fmt.Errorf("unable to extract maven files: %w", err) @@ -298,10 +323,11 @@ func pomPropertiesByParentPath(archivePath string, extractPaths []string, virtua propertiesByParentPath[path.Dir(filePath)] = *pomProperties } + return propertiesByParentPath, nil } -func pomProjectByParentPath(archivePath string, extractPaths []string, virtualPath string) (map[string]pkg.PomProject, error) { +func pomProjectByParentPath(archivePath, virtualPath string, extractPaths []string) (map[string]pkg.PomProject, error) { contentsOfMavenProjectFiles, err := file.ContentsFromZip(archivePath, extractPaths...) if err != nil { return nil, fmt.Errorf("unable to extract maven files: %w", err) diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 748bc10cce1..7af900c99c3 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -283,6 +283,11 @@ func TestParseJar(t *testing.T) { metadata := a.Metadata.(pkg.JavaMetadata) metadata.Parent = nil + // redact Digest which is computed differently between CI and local + if len(metadata.ArchiveDigests) > 0 { + metadata.ArchiveDigests = nil + } + // ignore select fields (only works for the main section) for _, field := range test.ignoreExtras { if metadata.Manifest != nil && metadata.Manifest.Main != nil { @@ -567,7 +572,6 @@ func TestParseNestedJar(t *testing.T) { } } } - } }) } diff --git a/syft/pkg/java_metadata.go b/syft/pkg/java_metadata.go index baa169a359e..4e606a03d3f 100644 --- a/syft/pkg/java_metadata.go +++ b/syft/pkg/java_metadata.go @@ -3,6 +3,7 @@ package pkg import ( "strings" + "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/linux" "github.com/anchore/syft/internal" @@ -20,12 +21,13 @@ var jenkinsPluginPomPropertiesGroupIDs = []string{ // JavaMetadata encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship. type JavaMetadata struct { - VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` // we need to include the virtual path in cyclonedx documents to prevent deduplication of jars within jars - Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` - PomProperties *PomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` - PomProject *PomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` - PURL string `hash:"ignore" json:"-"` // pURLs and CPEs are ignored for package IDs - Parent *Package `hash:"ignore" json:"-"` // note: the parent cannot be included in the minimal definition of uniqueness since this field is not reproducible in an encode-decode cycle (is lossy). + VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` // we need to include the virtual path in cyclonedx documents to prevent deduplication of jars within jars + Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` + PomProperties *PomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` + PomProject *PomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` + ArchiveDigests []file.Digest `hash:"ignore" json:"digest,omitempty"` + PURL string `hash:"ignore" json:"-"` // pURLs and CPEs are ignored for package IDs + Parent *Package `hash:"ignore" json:"-"` // note: the parent cannot be included in the minimal definition of uniqueness since this field is not reproducible in an encode-decode cycle (is lossy). } // PomProperties represents the fields of interest extracted from a Java archive's pom.properties file. From 15e45a8ce11849db464bf96f6fa6ac2790175495 Mon Sep 17 00:00:00 2001 From: Weston Steimel Date: Mon, 11 Apr 2022 13:38:52 +0000 Subject: [PATCH 17/31] add additional vendors for springframework (#945) The Official CPE dictionary currently contains entries for springframework with three different vendors: springsource, vmware, and pivotal_software. This appears to be because ownership has changed over time. Signed-off-by: Weston Steimel --- syft/pkg/cataloger/common/cpe/candidate_by_package_type.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go b/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go index 06fdc29161b..d177827d6be 100644 --- a/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go +++ b/syft/pkg/cataloger/common/cpe/candidate_by_package_type.go @@ -19,12 +19,12 @@ var defaultCandidateAdditions = buildCandidateLookup( { pkg.JavaPkg, candidateKey{PkgName: "springframework"}, - candidateAddition{AdditionalProducts: []string{"spring_framework", "springsource_spring_framework"}}, + candidateAddition{AdditionalProducts: []string{"spring_framework", "springsource_spring_framework"}, AdditionalVendors: []string{"pivotal_software", "springsource", "vmware"}}, }, { pkg.JavaPkg, candidateKey{PkgName: "spring-core"}, - candidateAddition{AdditionalProducts: []string{"spring_framework", "springsource_spring_framework"}}, + candidateAddition{AdditionalProducts: []string{"spring_framework", "springsource_spring_framework"}, AdditionalVendors: []string{"pivotal_software", "springsource", "vmware"}}, }, { // example image: docker.io/nuxeo:latest From b46d044d7e3afc2ee09fd5ff26635f783628126e Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:56:04 -0400 Subject: [PATCH 18/31] Update spdx22json to only take uppercase checksum algorithm (#946) --- internal/formats/spdx22json/to_format_model.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/formats/spdx22json/to_format_model.go b/internal/formats/spdx22json/to_format_model.go index 2e1a0c65cff..c69518f1703 100644 --- a/internal/formats/spdx22json/to_format_model.go +++ b/internal/formats/spdx22json/to_format_model.go @@ -67,7 +67,7 @@ func toPackages(catalog *pkg.Catalog, relationships []artifact.Relationship) []m filesAnalyzed = true for _, digest := range javaMetadata.ArchiveDigests { checksums = append(checksums, model.Checksum{ - Algorithm: digest.Algorithm, + Algorithm: strings.ToUpper(digest.Algorithm), ChecksumValue: digest.Value, }) } From 02a8fb6f8cf99106a676cadb6b6cf764dda2c0b6 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Tue, 12 Apr 2022 17:16:47 -0400 Subject: [PATCH 19/31] Minor readme update to correct format information (#948) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab39de4b10c..280d16b8fc3 100644 --- a/README.md +++ b/README.md @@ -156,9 +156,9 @@ syft -o Where the `formats` available are: - `json`: Use this to get as much information out of Syft as possible! - `text`: A row-oriented, human-and-machine-friendly output. -- `cyclonedx`: A XML report conforming to the [CycloneDX 1.3 specification](https://cyclonedx.org/specification/overview/). -- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.3 specification](https://cyclonedx.org/specification/overview/). -- `spdx`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/). +- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/). +- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/). +- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/). - `spdx-json`: A JSON report conforming to the [SPDX 2.2 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json). - `table`: A columnar summary (default). From 25bf679f8f345eece128548cfb68155577f89c1e Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 13 Apr 2022 13:20:40 -0400 Subject: [PATCH 20/31] Add workflow for automatic PR for new stereoscope updates (#954) --- .../workflows/update-stereoscope-release.yml | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/update-stereoscope-release.yml diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml new file mode 100644 index 00000000000..05b51c5ae49 --- /dev/null +++ b/.github/workflows/update-stereoscope-release.yml @@ -0,0 +1,50 @@ +name: PR for latest Stereoscope release +on: + schedule: + - cron: "0 8 * * *" # 3 AM EST + + workflow_dispatch: + +env: + GO_VERSION: "1.18.x" + GO_STABLE_VERSION: true + +jobs: + upgrade-stereoscope: + runs-on: ubuntu-latest + if: github.repository == 'anchore/syft' # only run for main repo + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + stable: ${{ env.GO_STABLE_VERSION }} + + - run: | + LATEST_VERSION=$(git ls-remote https://github.com/anchore/stereoscope main | head -n1 | awk '{print $1;}') + + # update go.mod + go get github.com/anchore/stereoscope@$LATEST_VERSION + + # export the version for use with create-pull-request + echo "::set-output name=LATEST_VERSION::$LATEST_VERSION" + id: latest-version + + - uses: tibdex/github-app-token@v1 + id: generate-token + with: + app_id: ${{ secrets.TOKEN_APP_ID }} + private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + + - uses: peter-evans/create-pull-request@v4 + with: + signoff: true + delete-branch: true + branch: auto/latest + labels: dependencies + commit-message: "Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}" + title: "Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}" + body: | + Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }} + token: ${{ steps.generate-token.outputs.token }} From 321eddf874c0332128b88042f162eedb6cda5d2e Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 13 Apr 2022 16:30:35 -0400 Subject: [PATCH 21/31] Auto-PR needs to run go mod tidy (#958) --- .github/workflows/update-stereoscope-release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-stereoscope-release.yml b/.github/workflows/update-stereoscope-release.yml index 05b51c5ae49..ab50c64cd25 100644 --- a/.github/workflows/update-stereoscope-release.yml +++ b/.github/workflows/update-stereoscope-release.yml @@ -26,6 +26,7 @@ jobs: # update go.mod go get github.com/anchore/stereoscope@$LATEST_VERSION + go mod tidy # export the version for use with create-pull-request echo "::set-output name=LATEST_VERSION::$LATEST_VERSION" From b7295b79de63177d59576c1ea44d7d1ff61c5877 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Thu, 14 Apr 2022 15:07:23 -0400 Subject: [PATCH 22/31] Ensure SPDXIDs are valid (#955) --- internal/formats/common/spdxhelpers/spdxid.go | 13 ++++++ .../formats/common/spdxhelpers/spdxid_test.go | 39 ++++++++++++++++++ .../formats/spdx22json/model/element_id.go | 30 ++------------ .../formats/spdx22tagvalue/encoder_test.go | 29 ++++++++++++++ .../snapshot/TestSPDXJSONSPDXIDs.golden | 40 +++++++++++++++++++ .../formats/spdx22tagvalue/to_format_model.go | 2 +- 6 files changed, 125 insertions(+), 28 deletions(-) create mode 100644 internal/formats/common/spdxhelpers/spdxid.go create mode 100644 internal/formats/common/spdxhelpers/spdxid_test.go create mode 100644 internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden diff --git a/internal/formats/common/spdxhelpers/spdxid.go b/internal/formats/common/spdxhelpers/spdxid.go new file mode 100644 index 00000000000..f7a2180c98f --- /dev/null +++ b/internal/formats/common/spdxhelpers/spdxid.go @@ -0,0 +1,13 @@ +package spdxhelpers + +import ( + "regexp" +) + +var expr = regexp.MustCompile("[^a-zA-Z0-9.-]") + +// SPDX spec says SPDXID must be: +// "SPDXRef-"[idstring] where [idstring] is a unique string containing letters, numbers, ., and/or - +func SanitizeElementID(id string) string { + return expr.ReplaceAllString(id, "-") +} diff --git a/internal/formats/common/spdxhelpers/spdxid_test.go b/internal/formats/common/spdxhelpers/spdxid_test.go new file mode 100644 index 00000000000..b66ccd45ebd --- /dev/null +++ b/internal/formats/common/spdxhelpers/spdxid_test.go @@ -0,0 +1,39 @@ +package spdxhelpers + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_SanitizeElementID(t *testing.T) { + tests := []struct { + input string + expected string + }{ + { + input: "letters", + expected: "letters", + }, + { + input: "ssl-client", + expected: "ssl-client", + }, + { + input: "ssl_client", + expected: "ssl-client", + }, + { + input: "go-module-sigs.k8s.io/structured-merge-diff/v3", + expected: "go-module-sigs.k8s.io-structured-merge-diff-v3", + }, + } + + for _, test := range tests { + t.Run(test.input, func(t *testing.T) { + actual := SanitizeElementID(test.input) + + assert.Equal(t, test.expected, actual) + }) + } +} diff --git a/internal/formats/spdx22json/model/element_id.go b/internal/formats/spdx22json/model/element_id.go index 50251fe37ce..0973ce4bd21 100644 --- a/internal/formats/spdx22json/model/element_id.go +++ b/internal/formats/spdx22json/model/element_id.go @@ -1,5 +1,7 @@ package model +import "github.com/anchore/syft/internal/formats/common/spdxhelpers" + // ElementID represents the identifier string portion of an SPDX element // identifier. DocElementID should be used for any attributes which can // contain identifiers defined in a different SPDX document. @@ -7,31 +9,5 @@ package model type ElementID string func (e ElementID) String() string { - return "SPDXRef-" + string(e) -} - -// DocElementID represents an SPDX element identifier that could be defined -// in a different SPDX document, and therefore could have a "DocumentRef-" -// portion, such as Relationship and Annotations. -// ElementID is used for attributes in which a "DocumentRef-" portion cannot -// appear, such as a Package or File definition (since it is necessarily -// being defined in the present document). -// DocumentRefID will be the empty string for elements defined in the -// present document. -// DocElementIDs should NOT contain the mandatory 'DocumentRef-' or -// 'SPDXRef-' portions. -type DocElementID struct { - DocumentRefID string - ElementRefID ElementID -} - -// RenderDocElementID takes a DocElementID and returns the string equivalent, -// with the SPDXRef- prefix (and, if applicable, the DocumentRef- prefix) -// reinserted. -func (d DocElementID) String() string { - prefix := "" - if d.DocumentRefID != "" { - prefix = "DocumentRef-" + d.DocumentRefID + ":" - } - return prefix + d.ElementRefID.String() + return "SPDXRef-" + spdxhelpers.SanitizeElementID(string(e)) } diff --git a/internal/formats/spdx22tagvalue/encoder_test.go b/internal/formats/spdx22tagvalue/encoder_test.go index af8dd500a75..9c3dba9e994 100644 --- a/internal/formats/spdx22tagvalue/encoder_test.go +++ b/internal/formats/spdx22tagvalue/encoder_test.go @@ -6,6 +6,9 @@ import ( "testing" "github.com/anchore/syft/internal/formats/common/testutils" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/sbom" + "github.com/anchore/syft/syft/source" ) var updateSpdxTagValue = flag.Bool("update-spdx-tv", false, "update the *.golden files for spdx-tv encoders") @@ -31,6 +34,32 @@ func TestSPDXTagValueImageEncoder(t *testing.T) { ) } +func TestSPDXJSONSPDXIDs(t *testing.T) { + var pkgs []pkg.Package + for _, name := range []string{"some/slashes", "@at-sign", "under_scores"} { + p := pkg.Package{ + Name: name, + } + p.SetID() + pkgs = append(pkgs, p) + } + testutils.AssertEncoderAgainstGoldenSnapshot(t, + Format(), + sbom.SBOM{ + Artifacts: sbom.Artifacts{ + PackageCatalog: pkg.NewCatalog(pkgs...), + }, + Relationships: nil, + Source: source.Metadata{ + Scheme: source.DirectoryScheme, + }, + Descriptor: sbom.Descriptor{}, + }, + true, + spdxTagValueRedactor, + ) +} + func spdxTagValueRedactor(s []byte) []byte { // each SBOM reports the time it was generated, which is not useful during snapshot testing s = regexp.MustCompile(`Created: .*`).ReplaceAll(s, []byte("redacted")) diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden new file mode 100644 index 00000000000..fb675caf785 --- /dev/null +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden @@ -0,0 +1,40 @@ +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +SPDXID: SPDXRef-DOCUMENT +DocumentName: . +DocumentNamespace: https://anchore.com/syft/dir/e69056a9-935e-4f00-b85f-9467f5d99a92 +LicenseListVersion: 3.16 +Creator: Organization: Anchore, Inc +Creator: Tool: syft-[not provided] +Created: 2022-04-13T16:38:03Z + +##### Package: @at-sign + +PackageName: @at-sign +SPDXID: SPDXRef-Package---at-sign-739e4f0d93fb8298 +PackageDownloadLocation: NOASSERTION +FilesAnalyzed: false +PackageLicenseConcluded: NONE +PackageLicenseDeclared: NONE +PackageCopyrightText: NOASSERTION + +##### Package: some/slashes + +PackageName: some/slashes +SPDXID: SPDXRef-Package--some-slashes-26db06648b24bff9 +PackageDownloadLocation: NOASSERTION +FilesAnalyzed: false +PackageLicenseConcluded: NONE +PackageLicenseDeclared: NONE +PackageCopyrightText: NOASSERTION + +##### Package: under_scores + +PackageName: under_scores +SPDXID: SPDXRef-Package--under-scores-250cbfefcdea318b +PackageDownloadLocation: NOASSERTION +FilesAnalyzed: false +PackageLicenseConcluded: NONE +PackageLicenseDeclared: NONE +PackageCopyrightText: NOASSERTION + diff --git a/internal/formats/spdx22tagvalue/to_format_model.go b/internal/formats/spdx22tagvalue/to_format_model.go index 2f0d84ba726..b189f977dba 100644 --- a/internal/formats/spdx22tagvalue/to_format_model.go +++ b/internal/formats/spdx22tagvalue/to_format_model.go @@ -96,7 +96,7 @@ func toFormatPackages(catalog *pkg.Catalog) map[spdx.ElementID]*spdx.Package2_2 for _, p := range catalog.Sorted() { // name should be guaranteed to be unique, but semantically useful and stable - id := fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.ID()) + id := spdxhelpers.SanitizeElementID(fmt.Sprintf("Package-%+v-%s-%s", p.Type, p.Name, p.ID())) // If the Concluded License is not the same as the Declared License, a written explanation should be provided // in the Comments on License field (section 3.16). With respect to NOASSERTION, a written explanation in From 248023baafdf2a74f8bdaf98beaee3f40584bb7d Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Fri, 15 Apr 2022 13:00:06 -0400 Subject: [PATCH 23/31] Update GitHub format package_url and correlator (#961) --- internal/formats/github/encoder.go | 2 +- internal/formats/github/encoder_test.go | 6 +++--- internal/formats/github/github_dependency_api.go | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/formats/github/encoder.go b/internal/formats/github/encoder.go index 2e39f7c102a..9dfc6890d44 100644 --- a/internal/formats/github/encoder.go +++ b/internal/formats/github/encoder.go @@ -130,7 +130,7 @@ func toGithubManifests(s *sbom.SBOM) Manifests { name := dependencyName(p) manifest.Resolved[name] = DependencyNode{ - Purl: p.PURL, + PackageURL: p.PURL, Metadata: toDependencyMetadata(p), Relationship: toDependencyRelationshipType(p), Scope: toDependencyScope(p), diff --git a/internal/formats/github/encoder_test.go b/internal/formats/github/encoder_test.go index 91ac837692c..3eb58c75571 100644 --- a/internal/formats/github/encoder_test.go +++ b/internal/formats/github/encoder_test.go @@ -104,12 +104,12 @@ func Test_toGithubModel(t *testing.T) { }, Resolved: DependencyGraph{ "pkg:generic/pkg-1@1.0.1": DependencyNode{ - Purl: "pkg:generic/pkg-1@1.0.1", + PackageURL: "pkg:generic/pkg-1@1.0.1", Scope: DependencyScopeRuntime, Relationship: DependencyRelationshipDirect, }, "pkg:generic/pkg-2@2.0.2": DependencyNode{ - Purl: "pkg:generic/pkg-2@2.0.2", + PackageURL: "pkg:generic/pkg-2@2.0.2", Scope: DependencyScopeRuntime, Relationship: DependencyRelationshipDirect, }, @@ -125,7 +125,7 @@ func Test_toGithubModel(t *testing.T) { }, Resolved: DependencyGraph{ "pkg:generic/pkg-3@3.0.3": DependencyNode{ - Purl: "pkg:generic/pkg-3@3.0.3", + PackageURL: "pkg:generic/pkg-3@3.0.3", Scope: DependencyScopeRuntime, Relationship: DependencyRelationshipDirect, }, diff --git a/internal/formats/github/github_dependency_api.go b/internal/formats/github/github_dependency_api.go index 86743419005..fe873d41809 100644 --- a/internal/formats/github/github_dependency_api.go +++ b/internal/formats/github/github_dependency_api.go @@ -14,9 +14,9 @@ type DependencySnapshot struct { } type Job struct { - Name string `json:"name,omitempty"` // !omitempty - ID string `json:"id,omitempty"` // !omitempty - HTMLURL string `json:"html_url,omitempty"` + Correlator string `json:"correlator,omitempty"` // !omitempty + ID string `json:"id,omitempty"` // !omitempty + HTMLURL string `json:"html_url,omitempty"` } type DetectorMetadata struct { @@ -62,7 +62,7 @@ const ( ) type DependencyNode struct { - Purl string `json:"purl,omitempty"` + PackageURL string `json:"package_url,omitempty"` Metadata Metadata `json:"metadata,omitempty"` Relationship DependencyRelationship `json:"relationship,omitempty"` Scope DependencyScope `json:"scope,omitempty"` From 172ecc0d777d60a19c78b3a631adfa81abd2f176 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 18 Apr 2022 14:10:55 -0400 Subject: [PATCH 24/31] Preserve syft IDs on SBOM decode (#963) --- internal/formats/syftjson/to_syft_model.go | 6 +++++- syft/pkg/package.go | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/formats/syftjson/to_syft_model.go b/internal/formats/syftjson/to_syft_model.go index bac4df94b24..9c28c24a610 100644 --- a/internal/formats/syftjson/to_syft_model.go +++ b/internal/formats/syftjson/to_syft_model.go @@ -177,8 +177,12 @@ func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package { Metadata: p.Metadata, } - out.SetID() + // we don't know if this package ID is truly unique, however, we need to trust the user input in case there are + // external references to it. That is, we can't derive our own ID (using pkg.SetID()) since consumers won't + // be able to historically interact with data that references the IDs from the original SBOM document being decoded now. + out.OverrideID(artifact.ID(p.ID)) + // this alias mapping is currently defunct, but could be useful in the future. id := string(out.ID()) if id != p.ID { idAliases[p.ID] = id diff --git a/syft/pkg/package.go b/syft/pkg/package.go index 13b19ca37a2..d39be9912b5 100644 --- a/syft/pkg/package.go +++ b/syft/pkg/package.go @@ -28,6 +28,10 @@ type Package struct { Metadata interface{} // additional data found while parsing the package source } +func (p *Package) OverrideID(id artifact.ID) { + p.id = id +} + func (p *Package) SetID() { id, err := artifact.IDByHash(p) if err != nil { From c270ee2a023f2ed3bacbd847bbeb6583f7db9ddc Mon Sep 17 00:00:00 2001 From: Rob Dimsdale-Zucker Date: Fri, 22 Apr 2022 12:08:44 -0400 Subject: [PATCH 25/31] Fix typo in CPE-parsing error (#966) --- syft/pkg/cpe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syft/pkg/cpe.go b/syft/pkg/cpe.go index 85290e50e33..1d640272695 100644 --- a/syft/pkg/cpe.go +++ b/syft/pkg/cpe.go @@ -30,7 +30,7 @@ func NewCPE(cpeStr string) (CPE, error) { // get a CPE object based on the given string --don't validate yet since it may be possible to escape select cases on the callers behalf c, err := newCPEWithoutValidation(cpeStr) if err != nil { - return CPE{}, fmt.Errorf("unable to prase CPE string: %w", err) + return CPE{}, fmt.Errorf("unable to parse CPE string: %w", err) } // ensure that this CPE can be validated after being fully sanitized From 7304bbf8eee578272548529dc76d517e9b55a448 Mon Sep 17 00:00:00 2001 From: Jon McEwen Date: Tue, 26 Apr 2022 16:51:24 +0100 Subject: [PATCH 26/31] =?UTF-8?q?fix:=20#953=20Derive=20language=20from=20?= =?UTF-8?q?pURL=20-=20https://github.com/anchore/syft=E2=80=A6=20(#957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christopher Phillips --- .../common/cyclonedxhelpers/component.go | 4 +++ .../common/cyclonedxhelpers/component_test.go | 28 ++++++++++++++++ syft/pkg/cataloger/catalog.go | 7 ++++ syft/pkg/language.go | 2 +- test/integration/encode_decode_cycle_test.go | 32 +++++++++++-------- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/internal/formats/common/cyclonedxhelpers/component.go b/internal/formats/common/cyclonedxhelpers/component.go index d4f6606aeaf..a0d185f5111 100644 --- a/internal/formats/common/cyclonedxhelpers/component.go +++ b/internal/formats/common/cyclonedxhelpers/component.go @@ -86,6 +86,10 @@ func decodeComponent(c *cyclonedx.Component) *pkg.Package { p.Type = pkg.TypeFromPURL(p.PURL) } + if p.Language == "" { + p.Language = pkg.LanguageFromPURL(p.PURL) + } + return p } diff --git a/internal/formats/common/cyclonedxhelpers/component_test.go b/internal/formats/common/cyclonedxhelpers/component_test.go index ab7f3b812bb..586d7c89d2a 100644 --- a/internal/formats/common/cyclonedxhelpers/component_test.go +++ b/internal/formats/common/cyclonedxhelpers/component_test.go @@ -191,3 +191,31 @@ func Test_deriveBomRef(t *testing.T) { }) } } + +func Test_decodeComponent(t *testing.T) { + javaComponentWithNoSyftProperties := cyclonedx.Component{ + Name: "ch.qos.logback/logback-classic", + Version: "1.2.3", + PackageURL: "pkg:maven/ch.qos.logback/logback-classic@1.2.3", + Type: "library", + BOMRef: "pkg:maven/ch.qos.logback/logback-classic@1.2.3", + } + + tests := []struct { + name string + component cyclonedx.Component + want pkg.Language + }{ + { + name: "derive language from pURL if missing", + component: javaComponentWithNoSyftProperties, + want: pkg.Java, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, decodeComponent(&tt.component).Language) + }) + } +} diff --git a/syft/pkg/cataloger/catalog.go b/syft/pkg/cataloger/catalog.go index dfd242a5922..fa0e4d72da0 100644 --- a/syft/pkg/cataloger/catalog.go +++ b/syft/pkg/cataloger/catalog.go @@ -70,6 +70,13 @@ func Catalog(resolver source.FileResolver, release *linux.Release, catalogers .. // generate PURL (note: this is excluded from package ID, so is safe to mutate) p.PURL = pkg.URL(p, release) + // if we were not able to identify the language we have an opportunity + // to try and get this value from the PURL. Worst case we assert that + // we could not identify the language at either stage and set UnknownLanguage + if p.Language == "" { + p.Language = pkg.LanguageFromPURL(p.PURL) + } + // create file-to-package relationships for files owned by the package owningRelationships, err := packageFileOwnershipRelationships(p, resolver) if err != nil { diff --git a/syft/pkg/language.go b/syft/pkg/language.go index b4b3734a363..d9c4905b1dd 100644 --- a/syft/pkg/language.go +++ b/syft/pkg/language.go @@ -11,7 +11,7 @@ type Language string const ( // the full set of supported programming languages - UnknownLanguage Language = "UnknownLanguage" + UnknownLanguage Language = "" Java Language = "java" JavaScript Language = "javascript" Python Language = "python" diff --git a/test/integration/encode_decode_cycle_test.go b/test/integration/encode_decode_cycle_test.go index 348a309d229..012715dc3cd 100644 --- a/test/integration/encode_decode_cycle_test.go +++ b/test/integration/encode_decode_cycle_test.go @@ -7,6 +7,7 @@ import ( "github.com/anchore/syft/internal/formats/cyclonedxxml" "github.com/anchore/syft/internal/formats/syftjson" "github.com/anchore/syft/syft/source" + "github.com/google/go-cmp/cmp" "regexp" "testing" @@ -21,12 +22,14 @@ import ( ) // TestEncodeDecodeEncodeCycleComparison is testing for differences in how SBOM documents get encoded on multiple cycles. -// By encding and decoding the sbom we can compare the differences between the set of resulting objects. However, +// By encoding and decoding the sbom we can compare the differences between the set of resulting objects. However, // this requires specific comparisons being done, and select redactions/omissions being made. Additionally, there are // already unit tests on each format encoder-decoder for properly functioning comparisons in depth, so there is no need // to do an object-to-object comparison. For this reason this test focuses on a bytes-to-bytes comparison after an // encode-decode-encode loop which will detect lossy behavior in both directions. func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { + // use second image for relationships + images := []string{"image-pkg-coverage", "image-owning-package"} tests := []struct { formatOption sbom.FormatID redactor func(in []byte) []byte @@ -34,7 +37,11 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { }{ { formatOption: syftjson.ID, - json: true, + redactor: func(in []byte) []byte { + in = regexp.MustCompile("\"(id|parent)\": \"[^\"]+\",").ReplaceAll(in, []byte{}) + return in + }, + json: true, }, { formatOption: cyclonedxjson.ID, @@ -55,9 +62,8 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { } for _, test := range tests { - // use second image for relationships - for _, image := range []string{"image-pkg-coverage", "image-owning-package"} { - t.Run(fmt.Sprintf("%s/%s", test.formatOption, image), func(t *testing.T) { + t.Run(fmt.Sprintf("%s", test.formatOption), func(t *testing.T) { + for _, image := range images { originalSBOM, _ := catalogFixtureImage(t, image, source.SquashedScope) format := syft.FormatByID(test.formatOption) @@ -81,15 +87,15 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { if test.json { s1 := string(by1) s2 := string(by2) - assert.JSONEq(t, s1, s2) - } else { - if !assert.True(t, bytes.Equal(by1, by2)) { - dmp := diffmatchpatch.New() - diffs := dmp.DiffMain(string(by1), string(by2), true) - t.Errorf("diff: %s", dmp.DiffPrettyText(diffs)) + if diff := cmp.Diff(s1, s2); diff != "" { + t.Errorf("Encode/Decode mismatch (-want +got):\n%s", diff) } + } else if !assert.True(t, bytes.Equal(by1, by2)) { + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(string(by1), string(by2), true) + t.Errorf("diff: %s", dmp.DiffPrettyText(diffs)) } - }) - } + } + }) } } From 6029dd7c2eaa1d817ee0a4fe7a07031aac23b514 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Tue, 26 Apr 2022 14:23:03 -0400 Subject: [PATCH 27/31] refactor command package to remove globals and add dependency injection --- .bouncer.yaml | 1 + .goreleaser.yaml | 3 + Makefile | 2 +- cmd/attest.go | 322 ------------ cmd/check_for_application_update.go | 31 -- cmd/cmd.go | 171 ------- cmd/completion.go | 113 ----- cmd/output_writer.go | 64 --- cmd/output_writer_test.go | 78 --- cmd/packages.go | 389 -------------- cmd/power_user.go | 160 ------ cmd/root.go | 52 -- cmd/syft/cli/attest.go | 69 +++ cmd/syft/cli/attest/attest.go | 216 ++++++++ cmd/syft/cli/attest/password.go | 56 ++ cmd/syft/cli/commands.go | 143 ++++++ cmd/syft/cli/completion.go | 54 ++ cmd/{ => syft/cli/eventloop}/event_loop.go | 4 +- .../cli/eventloop}/event_loop_test.go | 26 +- cmd/{ => syft/cli/eventloop}/signals.go | 4 +- cmd/{ => syft/cli/eventloop}/tasks.go | 59 +-- cmd/syft/cli/options/attest.go | 28 + .../cli/options/format.go} | 4 +- cmd/syft/cli/options/options.go | 11 + cmd/syft/cli/options/packages.go | 118 +++++ cmd/syft/cli/options/root.go | 36 ++ cmd/syft/cli/options/verbose.go | 18 + cmd/syft/cli/options/version.go | 17 + cmd/syft/cli/packages.go | 79 +++ cmd/syft/cli/packages/packages.go | 240 +++++++++ cmd/syft/cli/poweruser.go | 49 ++ cmd/syft/cli/poweruser/poweruser.go | 116 +++++ cmd/{ => syft/cli}/version.go | 38 +- cmd/syft/main.go | 18 + go.mod | 112 ++-- go.sum | 477 +++++++++++------- internal/config/application.go | 170 +++---- internal/config/application_test.go | 52 -- internal/config/cli_only_options.go | 7 - internal/config/config.go | 1 + .../snapshot/TestSPDXJSONSPDXIDs.golden | 4 +- main.go | 14 - schema/cyclonedx/Makefile | 4 +- test/cli/power_user_cmd_test.go | 7 - 44 files changed, 1774 insertions(+), 1863 deletions(-) delete mode 100644 cmd/attest.go delete mode 100644 cmd/check_for_application_update.go delete mode 100644 cmd/cmd.go delete mode 100644 cmd/completion.go delete mode 100644 cmd/output_writer.go delete mode 100644 cmd/output_writer_test.go delete mode 100644 cmd/packages.go delete mode 100644 cmd/power_user.go delete mode 100644 cmd/root.go create mode 100644 cmd/syft/cli/attest.go create mode 100644 cmd/syft/cli/attest/attest.go create mode 100644 cmd/syft/cli/attest/password.go create mode 100644 cmd/syft/cli/commands.go create mode 100644 cmd/syft/cli/completion.go rename cmd/{ => syft/cli/eventloop}/event_loop.go (97%) rename cmd/{ => syft/cli/eventloop}/event_loop_test.go (96%) rename cmd/{ => syft/cli/eventloop}/signals.go (83%) rename cmd/{ => syft/cli/eventloop}/tasks.go (68%) create mode 100644 cmd/syft/cli/options/attest.go rename cmd/{format_aliases.go => syft/cli/options/format.go} (90%) create mode 100644 cmd/syft/cli/options/options.go create mode 100644 cmd/syft/cli/options/packages.go create mode 100644 cmd/syft/cli/options/root.go create mode 100644 cmd/syft/cli/options/verbose.go create mode 100644 cmd/syft/cli/options/version.go create mode 100644 cmd/syft/cli/packages.go create mode 100644 cmd/syft/cli/packages/packages.go create mode 100644 cmd/syft/cli/poweruser.go create mode 100644 cmd/syft/cli/poweruser/poweruser.go rename cmd/{ => syft/cli}/version.go (65%) create mode 100644 cmd/syft/main.go delete mode 100644 internal/config/application_test.go delete mode 100644 internal/config/cli_only_options.go create mode 100644 internal/config/config.go delete mode 100644 main.go diff --git a/.bouncer.yaml b/.bouncer.yaml index c89d68f9806..cc5879e40c6 100644 --- a/.bouncer.yaml +++ b/.bouncer.yaml @@ -5,6 +5,7 @@ permit: - MPL.* - ISC ignore-packages: + - . # packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE - github.com/anchore/packageurl-go diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 9e5e2c4b16b..fd79448a7dd 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -12,6 +12,7 @@ before: builds: - id: linux-build + dir: ./cmd/syft binary: syft goos: - linux @@ -32,6 +33,7 @@ builds: -X github.com/anchore/syft/internal/version.gitDescription={{.Summary}} - id: darwin-build + dir: ./cmd/syft binary: syft goos: - darwin @@ -49,6 +51,7 @@ builds: - ./.github/scripts/apple-signing/sign.sh "{{ .Path }}" "{{ .IsSnapshot }}" "{{ .Target }}" - id: windows-build + dir: ./cmd/syft binary: syft goos: - windows diff --git a/Makefile b/Makefile index a37ea295429..77c6ee7ae94 100644 --- a/Makefile +++ b/Makefile @@ -147,7 +147,7 @@ lint-fix: ## Auto-format all source code + run golangci lint fixers .PHONY: check-licenses check-licenses: ## Ensure transitive dependencies are compliant with the current license policy - $(TEMPDIR)/bouncer check + $(TEMPDIR)/bouncer check ./cmd/syft check-go-mod-tidy: @ .github/scripts/go-mod-tidy-check.sh && echo "go.mod and go.sum are tidy!" diff --git a/cmd/attest.go b/cmd/attest.go deleted file mode 100644 index b2e0e9ff3ce..00000000000 --- a/cmd/attest.go +++ /dev/null @@ -1,322 +0,0 @@ -package cmd - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "os" - "strings" - - "github.com/anchore/syft/internal/formats/cyclonedxjson" - "github.com/anchore/syft/internal/formats/spdx22json" - "github.com/anchore/syft/internal/formats/syftjson" - - "github.com/anchore/stereoscope" - "github.com/anchore/stereoscope/pkg/image" - "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/bus" - "github.com/anchore/syft/internal/log" - "github.com/anchore/syft/internal/ui" - "github.com/anchore/syft/syft" - "github.com/anchore/syft/syft/event" - "github.com/anchore/syft/syft/sbom" - "github.com/anchore/syft/syft/source" - "github.com/in-toto/in-toto-golang/in_toto" - "github.com/pkg/errors" - "github.com/pkg/profile" - "github.com/sigstore/cosign/cmd/cosign/cli/sign" - "github.com/sigstore/cosign/pkg/cosign" - "github.com/sigstore/cosign/pkg/cosign/attestation" - "github.com/sigstore/sigstore/pkg/signature/dsse" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/spf13/viper" - "github.com/wagoodman/go-partybus" - - signatureoptions "github.com/sigstore/sigstore/pkg/signature/options" -) - -const ( - attestExample = ` {{.appName}} {{.command}} --output [FORMAT] --key [KEY] alpine:latest - - Supports the following image sources: - {{.appName}} {{.command}} --key [KEY] yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. - {{.appName}} {{.command}} --key [KEY] path/to/a/file/or/dir only for OCI tar or OCI directory - -` - attestSchemeHelp = "\n" + indent + schemeHelpHeader + "\n" + imageSchemeHelp - - attestHelp = attestExample + attestSchemeHelp - - intotoJSONDsseType = `application/vnd.in-toto+json` -) - -var attestFormats = []sbom.FormatID{ - syftjson.ID, - spdx22json.ID, - cyclonedxjson.ID, -} - -var ( - attestCmd = &cobra.Command{ - Use: "attest --output [FORMAT] --key [KEY] [SOURCE]", - Short: "Generate a package SBOM as an attestation for the given [SOURCE] container image", - Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from a container image as the predicate of an in-toto attestation", - Example: internal.Tprintf(attestHelp, map[string]interface{}{ - "appName": internal.ApplicationName, - "command": "attest", - }), - Args: validateInputArgs, - SilenceUsage: true, - SilenceErrors: true, - PreRunE: func(cmd *cobra.Command, args []string) (err error) { - if appConfig.Dev.ProfileCPU && appConfig.Dev.ProfileMem { - return fmt.Errorf("cannot profile CPU and memory simultaneously") - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - if appConfig.Dev.ProfileCPU { - defer profile.Start(profile.CPUProfile).Stop() - } else if appConfig.Dev.ProfileMem { - defer profile.Start(profile.MemProfile).Stop() - } - - return attestExec(cmd.Context(), cmd, args) - }, - } -) - -func fetchPassword(_ bool) (b []byte, err error) { - potentiallyPipedInput, err := internal.IsPipedInput() - if err != nil { - log.Warnf("unable to determine if there is piped input: %+v", err) - } - switch { - case appConfig.Attest.Password != "": - return []byte(appConfig.Attest.Password), nil - case potentiallyPipedInput: - // handle piped in passwords - pwBytes, err := io.ReadAll(os.Stdin) - if err != nil { - return nil, fmt.Errorf("unable to get password from stdin: %w", err) - } - // be resilient to input that may have newline characters (in case someone is using echo without -n) - cleanPw := strings.TrimRight(string(pwBytes), "\n") - return []byte(cleanPw), nil - case internal.IsTerminal(): - return cosign.GetPassFromTerm(false) - } - return nil, errors.New("no method available to fetch password") -} - -func selectPassFunc(keypath string) (cosign.PassFunc, error) { - keyContents, err := os.ReadFile(keypath) - if err != nil { - return nil, err - } - - var fn cosign.PassFunc = func(bool) (b []byte, err error) { return nil, nil } - - _, err = cosign.LoadPrivateKey(keyContents, nil) - if err != nil { - fn = fetchPassword - } - - return fn, nil -} - -func attestExec(ctx context.Context, _ *cobra.Command, args []string) error { - // can only be an image for attestation or OCI DIR - userInput := args[0] - si, err := source.ParseInput(userInput, appConfig.Platform, false) - if err != nil { - return fmt.Errorf("could not generate source input for attest command: %w", err) - } - - switch si.Scheme { - case source.ImageScheme, source.UnknownScheme: - // at this point we know that it cannot be dir: or file: schemes, so we will assume that the unknown scheme could represent an image - si.Scheme = source.ImageScheme - default: - return fmt.Errorf("attest command can only be used with image sources but discovered %q when given %q", si.Scheme, userInput) - } - - // if the original detection was from a local daemon we want to short circuit - // that and attempt to generate the image source from a registry source instead - switch si.ImageSource { - case image.UnknownSource, image.OciRegistrySource: - si.ImageSource = image.OciRegistrySource - default: - return fmt.Errorf("attest command can only be used with image sources fetch directly from the registry, but discovered an image source of %q when given %q", si.ImageSource, userInput) - } - - if len(appConfig.Outputs) > 1 { - return fmt.Errorf("unable to generate attestation for more than one output") - } - - format := syft.FormatByName(appConfig.Outputs[0]) - predicateType := formatPredicateType(format) - if predicateType == "" { - return fmt.Errorf("could not produce attestation predicate for given format: %q. Available formats: %+v", formatAliases(format.ID()), formatAliases(attestFormats...)) - } - - passFunc, err := selectPassFunc(appConfig.Attest.Key) - if err != nil { - return err - } - - ko := sign.KeyOpts{ - KeyRef: appConfig.Attest.Key, - PassFunc: passFunc, - } - - sv, err := sign.SignerFromKeyOpts(ctx, "", ko) - if err != nil { - return err - } - defer sv.Close() - - return eventLoop( - attestationExecWorker(*si, format, predicateType, sv), - setupSignals(), - eventSubscription, - stereoscope.Cleanup, - ui.Select(isVerbose(), appConfig.Quiet)..., - ) -} - -func attestationExecWorker(sourceInput source.Input, format sbom.Format, predicateType string, sv *sign.SignerVerifier) <-chan error { - errs := make(chan error) - go func() { - defer close(errs) - - src, cleanup, err := source.NewFromRegistry(sourceInput, appConfig.Registry.ToOptions(), appConfig.Exclusions) - if cleanup != nil { - defer cleanup() - } - if err != nil { - errs <- fmt.Errorf("failed to construct source from user input %q: %w", sourceInput.UserInput, err) - return - } - - s, err := generateSBOM(src, errs) - if err != nil { - errs <- err - return - } - - sbomBytes, err := syft.Encode(*s, format) - if err != nil { - errs <- err - return - } - - err = generateAttestation(sbomBytes, src, sv, predicateType) - if err != nil { - errs <- err - return - } - }() - return errs -} - -func formatPredicateType(format sbom.Format) string { - switch format.ID() { - case spdx22json.ID: - return in_toto.PredicateSPDX - case cyclonedxjson.ID: - // Tentative see https://github.com/in-toto/attestation/issues/82 - return "https://cyclonedx.org/bom" - case syftjson.ID: - return "https://syft.dev/bom" - default: - return "" - } -} - -func findValidDigest(digests []string) string { - // since we are only using the OCI repo provider for this source we are safe that this is only 1 value - // see https://github.com/anchore/stereoscope/blob/25ebd49a842b5ac0a20c2e2b4b81335b64ad248c/pkg/image/oci/registry_provider.go#L57-L63 - split := strings.Split(digests[0], "sha256:") - return split[1] -} - -func generateAttestation(predicate []byte, src *source.Source, sv *sign.SignerVerifier, predicateType string) error { - switch len(src.Image.Metadata.RepoDigests) { - case 0: - return fmt.Errorf("cannot generate attestation since no repo digests were found; make sure you're passing an OCI registry source for the attest command") - case 1: - default: - return fmt.Errorf("cannot generate attestation since multiple repo digests were found for the image: %+v", src.Image.Metadata.RepoDigests) - } - - wrapped := dsse.WrapSigner(sv, intotoJSONDsseType) - - sh, err := attestation.GenerateStatement(attestation.GenerateOpts{ - Predicate: bytes.NewBuffer(predicate), - Type: predicateType, - Digest: findValidDigest(src.Image.Metadata.RepoDigests), - }) - if err != nil { - return err - } - - payload, err := json.Marshal(sh) - if err != nil { - return err - } - - signedPayload, err := wrapped.SignMessage(bytes.NewReader(payload), signatureoptions.WithContext(context.Background())) - if err != nil { - return errors.Wrap(err, "unable to sign SBOM") - } - - bus.Publish(partybus.Event{ - Type: event.Exit, - Value: func() error { - _, err := os.Stdout.Write(signedPayload) - return err - }, - }) - - return nil -} - -func init() { - setAttestFlags(attestCmd.Flags()) - if err := bindAttestConfigOptions(attestCmd.Flags()); err != nil { - panic(err) - } - rootCmd.AddCommand(attestCmd) -} - -func setAttestFlags(flags *pflag.FlagSet) { - // key options - flags.StringP("key", "", "cosign.key", - "path to the private key file to use for attestation", - ) - - // in-toto attestations only support JSON predicates, so not all SBOM formats that syft can output are supported - flags.StringP( - "output", "o", formatAliases(syftjson.ID)[0], - fmt.Sprintf("the SBOM format encapsulated within the attestation, available options=%v", formatAliases(attestFormats...)), - ) - - flags.StringP( - "platform", "", "", - "an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')", - ) -} - -func bindAttestConfigOptions(flags *pflag.FlagSet) error { - // note: output is not included since this configuration option is shared between multiple subcommands - - if err := viper.BindPFlag("attest.key", flags.Lookup("key")); err != nil { - return err - } - - return nil -} diff --git a/cmd/check_for_application_update.go b/cmd/check_for_application_update.go deleted file mode 100644 index c4f1bdab392..00000000000 --- a/cmd/check_for_application_update.go +++ /dev/null @@ -1,31 +0,0 @@ -package cmd - -import ( - "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/bus" - "github.com/anchore/syft/internal/log" - "github.com/anchore/syft/internal/version" - "github.com/anchore/syft/syft/event" - "github.com/wagoodman/go-partybus" -) - -func checkForApplicationUpdate() { - if appConfig.CheckForAppUpdate { - log.Debugf("checking if new vesion of %s is available", internal.ApplicationName) - isAvailable, newVersion, err := version.IsUpdateAvailable() - if err != nil { - // this should never stop the application - log.Errorf(err.Error()) - } - if isAvailable { - log.Infof("new version of %s is available: %s (current version is %s)", internal.ApplicationName, newVersion, version.FromBuild().Version) - - bus.Publish(partybus.Event{ - Type: event.AppUpdateAvailable, - Value: newVersion, - }) - } else { - log.Debugf("no new %s update available", internal.ApplicationName) - } - } -} diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index f60b017d6e6..00000000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,171 +0,0 @@ -package cmd - -import ( - "encoding/json" - "fmt" - "os" - "sort" - - "github.com/spf13/pflag" - - "github.com/anchore/stereoscope" - "github.com/anchore/syft/internal/config" - "github.com/anchore/syft/internal/log" - "github.com/anchore/syft/internal/logger" - "github.com/anchore/syft/internal/version" - "github.com/anchore/syft/syft" - "github.com/gookit/color" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/wagoodman/go-partybus" -) - -var ( - appConfig *config.Application - eventBus *partybus.Bus - eventSubscription *partybus.Subscription -) - -func init() { - cobra.OnInitialize( - initCmdAliasBindings, - initAppConfig, - initLogging, - logAppConfig, - checkForApplicationUpdate, - logAppVersion, - initEventBus, - ) -} - -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, color.Red.Sprint(err.Error())) - os.Exit(1) - } -} - -// we must setup the config-cli bindings first before the application configuration is parsed. However, this cannot -// be done without determining what the primary command that the config options should be bound to since there are -// shared concerns (the root-packages alias). -func initCmdAliasBindings() { - activeCmd, _, err := rootCmd.Find(os.Args[1:]) - if err != nil { - panic(err) - } - - // enable all cataloger by default if power-user command is run - if activeCmd == powerUserCmd { - config.PowerUserCatalogerEnabledDefault() - } - - // set bindings based on the packages alias - switch activeCmd { - case packagesCmd, rootCmd: - // note: we need to lazily bind config options since they are shared between both the root command - // and the packages command. Otherwise there will be global viper state that is in contention. - // See for more details: https://github.com/spf13/viper/issues/233 . Additionally, the bindings must occur BEFORE - // reading the application configuration, which implies that it must be an initializer (or rewrite the command - // initialization structure against typical patterns used with cobra, which is somewhat extreme for a - // temporary alias) - if err = bindPackagesConfigOptions(activeCmd.Flags()); err != nil { - panic(err) - } - case attestCmd: - // the --output and --platform options are independently defined flags, but a shared config option - if err = bindSharedConfigOption(attestCmd.Flags()); err != nil { - panic(err) - } - // even though the root command or packages command is NOT being run, we still need default bindings - // such that application config parsing passes. - if err = bindExclusivePackagesConfigOptions(packagesCmd.Flags()); err != nil { - panic(err) - } - default: - // even though the root command or packages command is NOT being run, we still need default bindings - // such that application config parsing passes. - if err = bindPackagesConfigOptions(packagesCmd.Flags()); err != nil { - panic(err) - } - } -} - -func bindSharedConfigOption(flags *pflag.FlagSet) error { - if err := viper.BindPFlag("output", flags.Lookup("output")); err != nil { - return err - } - - if err := viper.BindPFlag("platform", flags.Lookup("platform")); err != nil { - return err - } - - return nil -} - -func initAppConfig() { - cfg, err := config.LoadApplicationConfig(viper.GetViper(), persistentOpts) - if err != nil { - fmt.Printf("failed to load application config: \n\t%+v\n", err) - os.Exit(1) - } - - appConfig = cfg -} - -func initLogging() { - cfg := logger.LogrusConfig{ - EnableConsole: (appConfig.Log.FileLocation == "" || appConfig.CliOptions.Verbosity > 0) && !appConfig.Quiet, - EnableFile: appConfig.Log.FileLocation != "", - Level: appConfig.Log.LevelOpt, - Structured: appConfig.Log.Structured, - FileLocation: appConfig.Log.FileLocation, - } - - logWrapper := logger.NewLogrusLogger(cfg) - syft.SetLogger(logWrapper) - stereoscope.SetLogger(&logger.LogrusNestedLogger{ - Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"), - }) -} - -func logAppConfig() { - log.Debugf("application config:\n%+v", color.Magenta.Sprint(appConfig.String())) -} - -func initEventBus() { - eventBus = partybus.NewBus() - eventSubscription = eventBus.Subscribe() - - stereoscope.SetBus(eventBus) - syft.SetBus(eventBus) -} - -func logAppVersion() { - versionInfo := version.FromBuild() - log.Infof("syft version: %s", versionInfo.Version) - - var fields map[string]interface{} - bytes, err := json.Marshal(versionInfo) - if err != nil { - return - } - err = json.Unmarshal(bytes, &fields) - if err != nil { - return - } - - keys := make([]string, 0, len(fields)) - for k := range fields { - keys = append(keys, k) - } - sort.Strings(keys) - - for idx, field := range keys { - value := fields[field] - branch := "├──" - if idx == len(fields)-1 { - branch = "└──" - } - log.Debugf(" %s %s: %s", branch, field, value) - } -} diff --git a/cmd/completion.go b/cmd/completion.go deleted file mode 100644 index 2e35641c9bc..00000000000 --- a/cmd/completion.go +++ /dev/null @@ -1,113 +0,0 @@ -package cmd - -import ( - "context" - "os" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - - "github.com/spf13/cobra" -) - -// completionCmd represents the completion command -var completionCmd = &cobra.Command{ - Use: "completion [bash|zsh|fish]", - Short: "Generate a shell completion for Syft (listing local docker images)", - Long: `To load completions (docker image list): - -Bash: - -$ source <(syft completion bash) - -# To load completions for each session, execute once: -Linux: - $ syft completion bash > /etc/bash_completion.d/syft -MacOS: - $ syft completion bash > /usr/local/etc/bash_completion.d/syft - -Zsh: - -# If shell completion is not already enabled in your environment you will need -# to enable it. You can execute the following once: - -$ echo "autoload -U compinit; compinit" >> ~/.zshrc - -# To load completions for each session, execute once: -$ syft completion zsh > "${fpath[1]}/_syft" - -# You will need to start a new shell for this setup to take effect. - -Fish: - -$ syft completion fish | source - -# To load completions for each session, execute once: -$ syft completion fish > ~/.config/fish/completions/syft.fish -`, - DisableFlagsInUseLine: true, - ValidArgs: []string{"bash", "zsh", "fish"}, - Args: cobra.ExactValidArgs(1), - Run: func(cmd *cobra.Command, args []string) { - var err error - switch args[0] { - case "bash": - err = cmd.Root().GenBashCompletion(os.Stdout) - case "zsh": - err = cmd.Root().GenZshCompletion(os.Stdout) - case "fish": - err = cmd.Root().GenFishCompletion(os.Stdout, true) - } - if err != nil { - panic(err) - } - }, -} - -func init() { - rootCmd.AddCommand(completionCmd) -} - -func dockerImageValidArgsFunction(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // Since we use ValidArgsFunction, Cobra will call this AFTER having parsed all flags and arguments provided - dockerImageRepoTags, err := listLocalDockerImages(toComplete) - if err != nil { - // Indicates that an error occurred and completions should be ignored - return []string{"completion failed"}, cobra.ShellCompDirectiveError - } - if len(dockerImageRepoTags) == 0 { - return []string{"no docker images found"}, cobra.ShellCompDirectiveError - } - // ShellCompDirectiveDefault indicates that the shell will perform its default behavior after completions have - // been provided (without implying other possible directives) - return dockerImageRepoTags, cobra.ShellCompDirectiveDefault -} - -func listLocalDockerImages(prefix string) ([]string, error) { - var repoTags = make([]string, 0) - ctx := context.Background() - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return repoTags, err - } - - // Only want to return tagged images - imageListArgs := filters.NewArgs() - imageListArgs.Add("dangling", "false") - images, err := cli.ImageList(ctx, types.ImageListOptions{All: false, Filters: imageListArgs}) - if err != nil { - return repoTags, err - } - - for _, image := range images { - // image may have multiple tags - for _, tag := range image.RepoTags { - if strings.HasPrefix(tag, prefix) { - repoTags = append(repoTags, tag) - } - } - } - return repoTags, nil -} diff --git a/cmd/output_writer.go b/cmd/output_writer.go deleted file mode 100644 index 6a65bda1d25..00000000000 --- a/cmd/output_writer.go +++ /dev/null @@ -1,64 +0,0 @@ -package cmd - -import ( - "fmt" - "strings" - - "github.com/anchore/syft/internal/formats/table" - - "github.com/anchore/syft/syft" - - "github.com/anchore/syft/syft/sbom" - "github.com/hashicorp/go-multierror" -) - -// makeWriter creates a sbom.Writer for output or returns an error. this will either return a valid writer -// or an error but neither both and if there is no error, sbom.Writer.Close() should be called -func makeWriter(outputs []string, defaultFile string) (sbom.Writer, error) { - outputOptions, err := parseOptions(outputs, defaultFile) - if err != nil { - return nil, err - } - - writer, err := sbom.NewWriter(outputOptions...) - if err != nil { - return nil, err - } - - return writer, nil -} - -// parseOptions utility to parse command-line option strings and retain the existing behavior of default format and file -func parseOptions(outputs []string, defaultFile string) (out []sbom.WriterOption, errs error) { - // always should have one option -- we generally get the default of "table", but just make sure - if len(outputs) == 0 { - outputs = append(outputs, string(table.ID)) - } - - for _, name := range outputs { - name = strings.TrimSpace(name) - - // split to at most two parts for = - parts := strings.SplitN(name, "=", 2) - - // the format name is the first part - name = parts[0] - - // default to the --file or empty string if not specified - file := defaultFile - - // If a file is specified as part of the output formatName, use that - if len(parts) > 1 { - file = parts[1] - } - - format := syft.FormatByName(name) - if format == nil { - errs = multierror.Append(errs, fmt.Errorf("bad output format: '%s'", name)) - continue - } - - out = append(out, sbom.NewWriterOption(format, file)) - } - return out, errs -} diff --git a/cmd/output_writer_test.go b/cmd/output_writer_test.go deleted file mode 100644 index 5798d3ceec6..00000000000 --- a/cmd/output_writer_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package cmd - -import ( - "fmt" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestOutputWriterConfig(t *testing.T) { - tmp := t.TempDir() + "/" - - tests := []struct { - outputs []string - file string - err bool - expected []string - }{ - { - outputs: []string{}, - expected: []string{""}, - }, - { - outputs: []string{"json"}, - expected: []string{""}, - }, - { - file: "test-1.json", - expected: []string{"test-1.json"}, - }, - { - outputs: []string{"json=test-2.json"}, - expected: []string{"test-2.json"}, - }, - { - outputs: []string{"json=test-3-1.json", "spdx-json=test-3-2.json"}, - expected: []string{"test-3-1.json", "test-3-2.json"}, - }, - { - outputs: []string{"text", "json=test-4.json"}, - expected: []string{"", "test-4.json"}, - }, - } - - for _, test := range tests { - t.Run(fmt.Sprintf("%s/%s", test.outputs, test.file), func(t *testing.T) { - outputs := test.outputs - for i, val := range outputs { - outputs[i] = strings.Replace(val, "=", "="+tmp, 1) - } - - file := test.file - if file != "" { - file = tmp + file - } - - _, err := makeWriter(test.outputs, file) - - if test.err { - assert.Error(t, err) - return - } else { - assert.NoError(t, err) - } - - for _, expected := range test.expected { - if expected != "" { - assert.FileExists(t, tmp+expected) - } else if file != "" { - assert.FileExists(t, file) - } else { - assert.NoFileExists(t, expected) - } - } - }) - } -} diff --git a/cmd/packages.go b/cmd/packages.go deleted file mode 100644 index bb90a94fdf8..00000000000 --- a/cmd/packages.go +++ /dev/null @@ -1,389 +0,0 @@ -package cmd - -import ( - "context" - "fmt" - "io/ioutil" - "os" - - "github.com/anchore/stereoscope" - "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/anchore" - "github.com/anchore/syft/internal/bus" - "github.com/anchore/syft/internal/formats/table" - "github.com/anchore/syft/internal/log" - "github.com/anchore/syft/internal/ui" - "github.com/anchore/syft/internal/version" - "github.com/anchore/syft/syft" - "github.com/anchore/syft/syft/artifact" - "github.com/anchore/syft/syft/event" - "github.com/anchore/syft/syft/pkg/cataloger" - "github.com/anchore/syft/syft/sbom" - "github.com/anchore/syft/syft/source" - "github.com/pkg/profile" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/spf13/viper" - "github.com/wagoodman/go-partybus" -) - -const ( - packagesExample = ` {{.appName}} {{.command}} alpine:latest a summary of discovered packages - {{.appName}} {{.command}} alpine:latest -o json show all possible cataloging details - {{.appName}} {{.command}} alpine:latest -o cyclonedx show a CycloneDX formatted SBOM - {{.appName}} {{.command}} alpine:latest -o cyclonedx-json show a CycloneDX JSON formatted SBOM - {{.appName}} {{.command}} alpine:latest -o spdx show a SPDX 2.2 Tag-Value formatted SBOM - {{.appName}} {{.command}} alpine:latest -o spdx-json show a SPDX 2.2 JSON formatted SBOM - {{.appName}} {{.command}} alpine:latest -vv show verbose debug information - - Supports the following image sources: - {{.appName}} {{.command}} yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. - {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory -` - - schemeHelpHeader = "You can also explicitly specify the scheme to use:" - imageSchemeHelp = ` {{.appName}} {{.command}} docker:yourrepo/yourimage:tag explicitly use the Docker daemon - {{.appName}} {{.command}} podman:yourrepo/yourimage:tag explicitly use the Podman daemon - {{.appName}} {{.command}} registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required) - {{.appName}} {{.command}} docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save" - {{.appName}} {{.command}} oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Skopeo or otherwise) - {{.appName}} {{.command}} oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise) -` - nonImageSchemeHelp = ` {{.appName}} {{.command}} dir:path/to/yourproject read directly from a path on disk (any directory) - {{.appName}} {{.command}} file:path/to/yourproject/file read directly from a path on disk (any single file) -` - packagesSchemeHelp = "\n" + indent + schemeHelpHeader + "\n" + imageSchemeHelp + nonImageSchemeHelp - - packagesHelp = packagesExample + packagesSchemeHelp -) - -var ( - packagesCmd = &cobra.Command{ - Use: "packages [SOURCE]", - Short: "Generate a package SBOM", - Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from container images and filesystems", - Example: internal.Tprintf(packagesHelp, map[string]interface{}{ - "appName": internal.ApplicationName, - "command": "packages", - }), - Args: validateInputArgs, - SilenceUsage: true, - SilenceErrors: true, - PreRunE: func(cmd *cobra.Command, args []string) (err error) { - if appConfig.Dev.ProfileCPU && appConfig.Dev.ProfileMem { - return fmt.Errorf("cannot profile CPU and memory simultaneously") - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - if appConfig.Dev.ProfileCPU { - defer profile.Start(profile.CPUProfile).Stop() - } else if appConfig.Dev.ProfileMem { - defer profile.Start(profile.MemProfile).Stop() - } - - return packagesExec(cmd, args) - }, - ValidArgsFunction: dockerImageValidArgsFunction, - } -) - -func init() { - setPackageFlags(packagesCmd.Flags()) - - rootCmd.AddCommand(packagesCmd) -} - -func setPackageFlags(flags *pflag.FlagSet) { - // Formatting & Input options ////////////////////////////////////////////// - flags.StringP( - "scope", "s", cataloger.DefaultSearchConfig().Scope.String(), - fmt.Sprintf("selection of layers to catalog, options=%v", source.AllScopes)) - - flags.StringArrayP( - "output", "o", formatAliases(table.ID), - fmt.Sprintf("report output format, options=%v", formatAliases(syft.FormatIDs()...)), - ) - - flags.StringP( - "file", "", "", - "file to write the default report output to (default is STDOUT)", - ) - - flags.StringP( - "platform", "", "", - "an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')", - ) - - // Upload options ////////////////////////////////////////////////////////// - flags.StringP( - "host", "H", "", - "the hostname or URL of the Anchore Enterprise instance to upload to", - ) - - flags.StringP( - "username", "u", "", - "the username to authenticate against Anchore Enterprise", - ) - - flags.StringP( - "password", "p", "", - "the password to authenticate against Anchore Enterprise", - ) - - flags.StringP( - "dockerfile", "d", "", - "include dockerfile for upload to Anchore Enterprise", - ) - - flags.StringArrayP( - "exclude", "", nil, - "exclude paths from being scanned using a glob expression", - ) - - flags.Bool( - "overwrite-existing-image", false, - "overwrite an existing image during the upload to Anchore Enterprise", - ) - - flags.Uint( - "import-timeout", 30, - "set a timeout duration (in seconds) for the upload to Anchore Enterprise", - ) -} - -func bindPackagesConfigOptions(flags *pflag.FlagSet) error { - if err := bindExclusivePackagesConfigOptions(flags); err != nil { - return err - } - if err := bindSharedConfigOption(flags); err != nil { - return err - } - return nil -} - -// NOTE(alex): Write a helper for the binding operation, which can be used to perform the binding but also double check that the intended effect was had or else return an error. Another thought is to somehow provide zero-valued defaults for all values in our config struct (maybe with reflection?). There may be a mechanism that already exists in viper that protects against this that I'm not aware of. ref: https://github.com/anchore/syft/pull/805#discussion_r801931192 -func bindExclusivePackagesConfigOptions(flags *pflag.FlagSet) error { - // Formatting & Input options ////////////////////////////////////////////// - - // note: output is not included since this configuration option is shared between multiple subcommands - - if err := viper.BindPFlag("package.cataloger.scope", flags.Lookup("scope")); err != nil { - return err - } - - if err := viper.BindPFlag("file", flags.Lookup("file")); err != nil { - return err - } - - if err := viper.BindPFlag("exclude", flags.Lookup("exclude")); err != nil { - return err - } - - // Upload options ////////////////////////////////////////////////////////// - - if err := viper.BindPFlag("anchore.host", flags.Lookup("host")); err != nil { - return err - } - - if err := viper.BindPFlag("anchore.username", flags.Lookup("username")); err != nil { - return err - } - - if err := viper.BindPFlag("anchore.password", flags.Lookup("password")); err != nil { - return err - } - - if err := viper.BindPFlag("anchore.dockerfile", flags.Lookup("dockerfile")); err != nil { - return err - } - - if err := viper.BindPFlag("anchore.overwrite-existing-image", flags.Lookup("overwrite-existing-image")); err != nil { - return err - } - - if err := viper.BindPFlag("anchore.import-timeout", flags.Lookup("import-timeout")); err != nil { - return err - } - - return nil -} - -func validateInputArgs(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - // in the case that no arguments are given we want to show the help text and return with a non-0 return code. - if err := cmd.Help(); err != nil { - return fmt.Errorf("unable to display help: %w", err) - } - return fmt.Errorf("an image/directory argument is required") - } - - return cobra.MaximumNArgs(1)(cmd, args) -} - -func packagesExec(_ *cobra.Command, args []string) error { - writer, err := makeWriter(appConfig.Outputs, appConfig.File) - if err != nil { - return err - } - - defer func() { - if err := writer.Close(); err != nil { - log.Warnf("unable to write to report destination: %w", err) - } - }() - - // could be an image or a directory, with or without a scheme - userInput := args[0] - si, err := source.ParseInput(userInput, appConfig.Platform, true) - if err != nil { - return fmt.Errorf("could not generate source input for packages command: %w", err) - } - - return eventLoop( - packagesExecWorker(*si, writer), - setupSignals(), - eventSubscription, - stereoscope.Cleanup, - ui.Select(isVerbose(), appConfig.Quiet)..., - ) -} - -func isVerbose() (result bool) { - isPipedInput, err := internal.IsPipedInput() - if err != nil { - // since we can't tell if there was piped input we assume that there could be to disable the ETUI - log.Warnf("unable to determine if there is piped input: %+v", err) - return true - } - // verbosity should consider if there is piped input (in which case we should not show the ETUI) - return appConfig.CliOptions.Verbosity > 0 || isPipedInput -} - -func generateSBOM(src *source.Source, errs chan error) (*sbom.SBOM, error) { - tasks, err := tasks() - if err != nil { - return nil, err - } - - s := sbom.SBOM{ - Source: src.Metadata, - Descriptor: sbom.Descriptor{ - Name: internal.ApplicationName, - Version: version.FromBuild().Version, - Configuration: appConfig, - }, - } - - buildRelationships(&s, src, tasks, errs) - - return &s, nil -} - -func buildRelationships(s *sbom.SBOM, src *source.Source, tasks []task, errs chan error) { - var relationships []<-chan artifact.Relationship - for _, task := range tasks { - c := make(chan artifact.Relationship) - relationships = append(relationships, c) - go runTask(task, &s.Artifacts, src, c, errs) - } - - s.Relationships = append(s.Relationships, mergeRelationships(relationships...)...) -} - -func packagesExecWorker(si source.Input, writer sbom.Writer) <-chan error { - errs := make(chan error) - go func() { - defer close(errs) - - src, cleanup, err := source.New(si, appConfig.Registry.ToOptions(), appConfig.Exclusions) - if cleanup != nil { - defer cleanup() - } - if err != nil { - errs <- fmt.Errorf("failed to construct source from user input %q: %w", si.UserInput, err) - return - } - - s, err := generateSBOM(src, errs) - if err != nil { - errs <- err - return - } - - if s == nil { - errs <- fmt.Errorf("no SBOM produced for %q", si.UserInput) - } - - if appConfig.Anchore.Host != "" { - if err := runPackageSbomUpload(src, *s); err != nil { - errs <- err - return - } - } - - bus.Publish(partybus.Event{ - Type: event.Exit, - Value: func() error { return writer.Write(*s) }, - }) - }() - return errs -} - -func mergeRelationships(cs ...<-chan artifact.Relationship) (relationships []artifact.Relationship) { - for _, c := range cs { - for n := range c { - relationships = append(relationships, n) - } - } - - return relationships -} - -func runPackageSbomUpload(src *source.Source, s sbom.SBOM) error { - log.Infof("uploading results to %s", appConfig.Anchore.Host) - - if src.Metadata.Scheme != source.ImageScheme { - return fmt.Errorf("unable to upload results: only images are supported") - } - - var dockerfileContents []byte - if appConfig.Anchore.Dockerfile != "" { - if _, err := os.Stat(appConfig.Anchore.Dockerfile); os.IsNotExist(err) { - return fmt.Errorf("unable dockerfile=%q does not exist: %w", appConfig.Anchore.Dockerfile, err) - } - - fh, err := os.Open(appConfig.Anchore.Dockerfile) - if err != nil { - return fmt.Errorf("unable to open dockerfile=%q: %w", appConfig.Anchore.Dockerfile, err) - } - - dockerfileContents, err = ioutil.ReadAll(fh) - if err != nil { - return fmt.Errorf("unable to read dockerfile=%q: %w", appConfig.Anchore.Dockerfile, err) - } - } - - c, err := anchore.NewClient(anchore.Configuration{ - BaseURL: appConfig.Anchore.Host, - Username: appConfig.Anchore.Username, - Password: appConfig.Anchore.Password, - }) - if err != nil { - return fmt.Errorf("failed to create anchore client: %w", err) - } - - importCfg := anchore.ImportConfig{ - ImageMetadata: src.Image.Metadata, - SBOM: s, - Dockerfile: dockerfileContents, - OverwriteExistingUpload: appConfig.Anchore.OverwriteExistingImage, - Timeout: appConfig.Anchore.ImportTimeout, - } - - if err := c.Import(context.Background(), importCfg); err != nil { - return fmt.Errorf("failed to upload results to host=%s: %+v", appConfig.Anchore.Host, err) - } - - return nil -} diff --git a/cmd/power_user.go b/cmd/power_user.go deleted file mode 100644 index 495328b9796..00000000000 --- a/cmd/power_user.go +++ /dev/null @@ -1,160 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/anchore/stereoscope" - "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/bus" - "github.com/anchore/syft/internal/formats/syftjson" - "github.com/anchore/syft/internal/log" - "github.com/anchore/syft/internal/ui" - "github.com/anchore/syft/internal/version" - "github.com/anchore/syft/syft/artifact" - "github.com/anchore/syft/syft/event" - "github.com/anchore/syft/syft/sbom" - "github.com/anchore/syft/syft/source" - "github.com/gookit/color" - "github.com/pkg/profile" - "github.com/spf13/cobra" - "github.com/wagoodman/go-partybus" -) - -const powerUserExample = ` {{.appName}} {{.command}} - - 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. - - All behavior is controlled via application configuration and environment variables (see https://github.com/anchore/syft#configuration) -` - -var powerUserOpts = struct { - configPath string -}{} - -var powerUserCmd = &cobra.Command{ - Use: "power-user [IMAGE]", - Short: "Run bulk operations on container images", - Example: internal.Tprintf(powerUserExample, map[string]interface{}{ - "appName": internal.ApplicationName, - "command": "power-user", - }), - Args: validateInputArgs, - Hidden: true, - SilenceUsage: true, - SilenceErrors: true, - PreRunE: func(cmd *cobra.Command, args []string) error { - if appConfig.Dev.ProfileCPU && appConfig.Dev.ProfileMem { - return fmt.Errorf("cannot profile CPU and memory simultaneously") - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - if appConfig.Dev.ProfileCPU { - defer profile.Start(profile.CPUProfile).Stop() - } else if appConfig.Dev.ProfileMem { - defer profile.Start(profile.MemProfile).Stop() - } - - return powerUserExec(cmd, args) - }, - ValidArgsFunction: dockerImageValidArgsFunction, -} - -func init() { - powerUserCmd.Flags().StringVarP(&powerUserOpts.configPath, "config", "c", "", "config file path with all power-user options") - - rootCmd.AddCommand(powerUserCmd) -} - -func powerUserExec(_ *cobra.Command, args []string) error { - // could be an image or a directory, with or without a scheme - userInput := args[0] - - writer, err := sbom.NewWriter( - sbom.NewWriterOption( - syftjson.Format(), - appConfig.File, - ), - ) - if err != nil { - return err - } - - defer func() { - if err := writer.Close(); err != nil { - log.Warnf("unable to write to report destination: %+v", err) - } - - // inform user at end of run that command will be removed - deprecated := color.Style{color.Red, color.OpBold}.Sprint("DEPRECATED: This command will be removed in v1.0.0") - fmt.Fprintln(os.Stderr, deprecated) - }() - - return eventLoop( - powerUserExecWorker(userInput, writer), - setupSignals(), - eventSubscription, - stereoscope.Cleanup, - ui.Select(isVerbose(), appConfig.Quiet)..., - ) -} -func powerUserExecWorker(userInput string, writer sbom.Writer) <-chan error { - errs := make(chan error) - go func() { - defer close(errs) - - appConfig.Secrets.Cataloger.Enabled = true - appConfig.FileMetadata.Cataloger.Enabled = true - appConfig.FileContents.Cataloger.Enabled = true - appConfig.FileClassification.Cataloger.Enabled = true - tasks, err := tasks() - if err != nil { - errs <- err - return - } - - si, err := source.ParseInput(userInput, appConfig.Platform, true) - if err != nil { - errs <- err - return - } - - src, cleanup, err := source.New(*si, appConfig.Registry.ToOptions(), appConfig.Exclusions) - if err != nil { - errs <- err - return - } - if cleanup != nil { - defer cleanup() - } - - s := sbom.SBOM{ - Source: src.Metadata, - Descriptor: sbom.Descriptor{ - Name: internal.ApplicationName, - Version: version.FromBuild().Version, - Configuration: appConfig, - }, - } - - var relationships []<-chan artifact.Relationship - for _, task := range tasks { - c := make(chan artifact.Relationship) - relationships = append(relationships, c) - - go runTask(task, &s.Artifacts, src, c, errs) - } - - s.Relationships = append(s.Relationships, mergeRelationships(relationships...)...) - - bus.Publish(partybus.Event{ - Type: event.Exit, - Value: func() error { return writer.Write(s) }, - }) - }() - - return errs -} diff --git a/cmd/root.go b/cmd/root.go deleted file mode 100644 index c0402b324e5..00000000000 --- a/cmd/root.go +++ /dev/null @@ -1,52 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/anchore/syft/internal" - "github.com/anchore/syft/internal/config" - "github.com/anchore/syft/internal/version" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var persistentOpts = config.CliOnlyOptions{} - -// rootCmd is currently an alias for the packages command -var rootCmd = &cobra.Command{ - Short: packagesCmd.Short, - Long: packagesCmd.Long, - Args: packagesCmd.Args, - Example: packagesCmd.Example, - SilenceUsage: true, - SilenceErrors: true, - PreRunE: packagesCmd.PreRunE, - RunE: packagesCmd.RunE, - ValidArgsFunction: packagesCmd.ValidArgsFunction, - Version: version.FromBuild().Version, -} - -const indent = " " - -func init() { - // set universal flags - rootCmd.PersistentFlags().StringVarP(&persistentOpts.ConfigPath, "config", "c", "", "application config file") - // setting the version template to just print out the string since we already have a templatized version string - rootCmd.SetVersionTemplate(fmt.Sprintf("%s {{.Version}}\n", internal.ApplicationName)) - flag := "quiet" - rootCmd.PersistentFlags().BoolP( - flag, "q", false, - "suppress all logging output", - ) - - if err := viper.BindPFlag(flag, rootCmd.PersistentFlags().Lookup(flag)); err != nil { - fmt.Printf("unable to bind flag '%s': %+v", flag, err) - os.Exit(1) - } - - rootCmd.PersistentFlags().CountVarP(&persistentOpts.Verbosity, "verbose", "v", "increase verbosity (-v = info, -vv = debug)") - - // set common options that are not universal (package subcommand-alias specific) - setPackageFlags(rootCmd.Flags()) -} diff --git a/cmd/syft/cli/attest.go b/cmd/syft/cli/attest.go new file mode 100644 index 00000000000..e92e24d59ee --- /dev/null +++ b/cmd/syft/cli/attest.go @@ -0,0 +1,69 @@ +package cli + +import ( + "fmt" + "log" + + "github.com/anchore/syft/cmd/syft/cli/attest" + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + attestExample = ` {{.appName}} {{.command}} --output [FORMAT] --key [KEY] alpine:latest + Supports the following image sources: + {{.appName}} {{.command}} --key [KEY] yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. + {{.appName}} {{.command}} --key [KEY] path/to/a/file/or/dir only for OCI tar or OCI directory +` + attestSchemeHelp = "\n" + indent + schemeHelpHeader + "\n" + imageSchemeHelp + + attestHelp = attestExample + attestSchemeHelp +) + +func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions) *cobra.Command { + ao := options.AttestOptions{} + cmd := &cobra.Command{ + Use: "attest --output [FORMAT] --key [KEY] [SOURCE]", + Short: "Generate a package SBOM as an attestation for the given [SOURCE] container image", + Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from a container image as the predicate of an in-toto attestation", + Example: internal.Tprintf(attestHelp, map[string]interface{}{ + "appName": internal.ApplicationName, + "command": "attest", + }), + Args: func(cmd *cobra.Command, args []string) error { + // run to unmarshal viper object onto app config + // the viper object correctly + if err := app.LoadAllValues(v, ro.Config); err != nil { + return fmt.Errorf("invalid application config: %v", err) + } + // configure logging for command + newLogWrapper(app) + logApplicationConfig(app) + return validateArgs(cmd, args) + }, + SilenceUsage: true, + SilenceErrors: true, + RunE: func(cmd *cobra.Command, args []string) error { + // this MUST be called first to make sure app config decodes + // the viper object correctly + newLogWrapper(app) + logApplicationConfig(app) + + if app.CheckForAppUpdate { + checkForApplicationUpdate() + } + + return attest.Run(cmd.Context(), app, args) + }, + } + + err := ao.AddFlags(cmd, v) + if err != nil { + log.Fatal(err) + } + + return cmd +} diff --git a/cmd/syft/cli/attest/attest.go b/cmd/syft/cli/attest/attest.go new file mode 100644 index 00000000000..62e712f4dfa --- /dev/null +++ b/cmd/syft/cli/attest/attest.go @@ -0,0 +1,216 @@ +package attest + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/anchore/stereoscope" + "github.com/anchore/stereoscope/pkg/image" + "github.com/anchore/syft/cmd/syft/cli/eventloop" + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/cli/packages" + "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/config" + "github.com/anchore/syft/internal/formats/cyclonedxjson" + "github.com/anchore/syft/internal/formats/spdx22json" + "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/internal/ui" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/event" + "github.com/anchore/syft/syft/sbom" + "github.com/anchore/syft/syft/source" + "github.com/in-toto/in-toto-golang/in_toto" + "github.com/pkg/errors" + "github.com/sigstore/cosign/cmd/cosign/cli/sign" + "github.com/sigstore/cosign/pkg/cosign/attestation" + "github.com/sigstore/sigstore/pkg/signature/dsse" + "github.com/wagoodman/go-partybus" + + signatureoptions "github.com/sigstore/sigstore/pkg/signature/options" +) + +var ( + allowedAttestFormats = []sbom.FormatID{ + syftjson.ID, + spdx22json.ID, + cyclonedxjson.ID, + } + + intotoJSONDsseType = `application/vnd.in-toto+json` +) + +func Run(ctx context.Context, app *config.Application, args []string) error { + // We cannot generate an attestation for more than one output + if len(app.Outputs) > 1 { + return fmt.Errorf("unable to generate attestation for more than one output") + } + + // can only be an image for attestation or OCI DIR + userInput := args[0] + si, err := parseImageSource(userInput, app) + if err != nil { + return err + } + + format := syft.FormatByName(app.Outputs[0]) + predicateType := formatPredicateType(format) + if predicateType == "" { + return fmt.Errorf("could not produce attestation predicate for given format: %q. Available formats: %+v", options.FormatAliases(format.ID()), options.FormatAliases(allowedAttestFormats...)) + } + + passFunc, err := selectPassFunc(app.Attest.Key, app.Attest.Password) + if err != nil { + return err + } + + ko := sign.KeyOpts{ + KeyRef: app.Attest.Key, + PassFunc: passFunc, + } + + sv, err := sign.SignerFromKeyOpts(ctx, "", "", ko) + if err != nil { + return err + } + defer sv.Close() + + eventBus := partybus.NewBus() + stereoscope.SetBus(eventBus) + syft.SetBus(eventBus) + + return eventloop.EventLoop( + execWorker(app, *si, format, predicateType, sv), + eventloop.SetupSignals(), + eventBus.Subscribe(), + stereoscope.Cleanup, + ui.Select(options.IsVerbose(app), app.Quiet)..., + ) +} + +func parseImageSource(userInput string, app *config.Application) (s *source.Input, err error) { + si, err := source.ParseInput(userInput, app.Platform, false) + if err != nil { + return nil, fmt.Errorf("could not generate source input for attest command: %w", err) + } + + switch si.Scheme { + case source.ImageScheme, source.UnknownScheme: + // at this point we know that it cannot be dir: or file: schemes; + // we will assume that the unknown scheme could represent an image; + si.Scheme = source.ImageScheme + default: + return nil, fmt.Errorf("attest command can only be used with image sources but discovered %q when given %q", si.Scheme, userInput) + } + + // if the original detection was from the local daemon we want to short circuit + // that and attempt to generate the image source from its current registry source instead + switch si.ImageSource { + case image.UnknownSource, image.OciRegistrySource: + si.ImageSource = image.OciRegistrySource + default: + return nil, fmt.Errorf("attest command can only be used with image sources fetch directly from the registry, but discovered an image source of %q when given %q", si.ImageSource, userInput) + } + + return si, nil +} + +func execWorker(app *config.Application, sourceInput source.Input, format sbom.Format, predicateType string, sv *sign.SignerVerifier) <-chan error { + errs := make(chan error) + go func() { + defer close(errs) + + src, cleanup, err := source.NewFromRegistry(sourceInput, app.Registry.ToOptions(), app.Exclusions) + if cleanup != nil { + defer cleanup() + } + if err != nil { + errs <- fmt.Errorf("failed to construct source from user input %q: %w", sourceInput.UserInput, err) + return + } + + s, err := packages.GenerateSBOM(src, errs, app) + if err != nil { + errs <- err + return + } + + sbomBytes, err := syft.Encode(*s, format) + if err != nil { + errs <- err + return + } + + err = generateAttestation(sbomBytes, src, sv, predicateType) + if err != nil { + errs <- err + return + } + }() + return errs +} + +func generateAttestation(predicate []byte, src *source.Source, sv *sign.SignerVerifier, predicateType string) error { + switch len(src.Image.Metadata.RepoDigests) { + case 0: + return fmt.Errorf("cannot generate attestation since no repo digests were found; make sure you're passing an OCI registry source for the attest command") + case 1: + default: + return fmt.Errorf("cannot generate attestation since multiple repo digests were found for the image: %+v", src.Image.Metadata.RepoDigests) + } + + wrapped := dsse.WrapSigner(sv, intotoJSONDsseType) + + sh, err := attestation.GenerateStatement(attestation.GenerateOpts{ + Predicate: bytes.NewBuffer(predicate), + Type: predicateType, + Digest: findValidDigest(src.Image.Metadata.RepoDigests), + }) + if err != nil { + return err + } + + payload, err := json.Marshal(sh) + if err != nil { + return err + } + + signedPayload, err := wrapped.SignMessage(bytes.NewReader(payload), signatureoptions.WithContext(context.Background())) + if err != nil { + return errors.Wrap(err, "unable to sign SBOM") + } + + bus.Publish(partybus.Event{ + Type: event.Exit, + Value: func() error { + _, err := os.Stdout.Write(signedPayload) + return err + }, + }) + + return nil +} + +func findValidDigest(digests []string) string { + // since we are only using the OCI repo provider for this source we are safe that this is only 1 value + // see https://github.com/anchore/stereoscope/blob/25ebd49a842b5ac0a20c2e2b4b81335b64ad248c/pkg/image/oci/registry_provider.go#L57-L63 + split := strings.Split(digests[0], "sha256:") + return split[1] +} + +func formatPredicateType(format sbom.Format) string { + switch format.ID() { + case spdx22json.ID: + return in_toto.PredicateSPDX + case cyclonedxjson.ID: + // Tentative see https://github.com/in-toto/attestation/issues/82 + return "https://cyclonedx.org/bom" + case syftjson.ID: + return "https://syft.dev/bom" + default: + return "" + } +} diff --git a/cmd/syft/cli/attest/password.go b/cmd/syft/cli/attest/password.go new file mode 100644 index 00000000000..89520a0e90b --- /dev/null +++ b/cmd/syft/cli/attest/password.go @@ -0,0 +1,56 @@ +package attest + +import ( + "errors" + "fmt" + "io" + "os" + "strings" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" + "github.com/sigstore/cosign/pkg/cosign" +) + +func selectPassFunc(keypath, password string) (cosign.PassFunc, error) { + keyContents, err := os.ReadFile(keypath) + if err != nil { + return nil, err + } + + var fn cosign.PassFunc = func(bool) (b []byte, err error) { return nil, nil } + + _, err = cosign.LoadPrivateKey(keyContents, nil) + if err != nil { + fn = func(bool) (b []byte, err error) { + return fetchPassword(password) + } + } + + return fn, nil +} + +func fetchPassword(password string) (b []byte, err error) { + potentiallyPipedInput, err := internal.IsPipedInput() + if err != nil { + log.Warnf("unable to determine if there is piped input: %+v", err) + } + + switch { + case password != "": + return []byte(password), nil + case potentiallyPipedInput: + // handle piped in passwords + pwBytes, err := io.ReadAll(os.Stdin) + if err != nil { + return nil, fmt.Errorf("unable to get password from stdin: %w", err) + } + // be resilient to input that may have newline characters (in case someone is using echo without -n) + cleanPw := strings.TrimRight(string(pwBytes), "\n") + return []byte(cleanPw), nil + case internal.IsTerminal(): + return cosign.GetPassFromTerm(false) + } + + return nil, errors.New("no method available to fetch password") +} diff --git a/cmd/syft/cli/commands.go b/cmd/syft/cli/commands.go new file mode 100644 index 00000000000..c0f8bd39ca0 --- /dev/null +++ b/cmd/syft/cli/commands.go @@ -0,0 +1,143 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/anchore/stereoscope" + "github.com/anchore/syft/internal/logger" + "github.com/anchore/syft/syft" + + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/config" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/version" + "github.com/anchore/syft/syft/event" + "github.com/gookit/color" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/wagoodman/go-partybus" +) + +const indent = " " + +// New constructs the `syft packages` command, aliases the root command to `syft packages`, +// and constructs the `syft power-user` and `syft attest` commands. It is also responsible for +// organizing flag usage and injecting the application config for each command. +// Because of how the `cobra` library behaves, the application's configuration is initialized +// at this level. Values from the config should only be used after `app.LoadAllValues` has been called. +// Cobra does not have knowledge of the user provided flags until the `RunE` block of each command. +// `RunE` is the earliest that the complete application configuration can be loaded. +func New() (*cobra.Command, error) { + app := &config.Application{} + + // allow for nested options to be specified via environment variables + // e.g. pod.context = APPNAME_POD_CONTEXT + v := viper.NewWithOptions(viper.EnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))) + + // since root is aliased as the packages cmd we need to construct this command first + // we also need the command to have information about the `root` options because of this alias + ro := &options.RootOptions{} + po := &options.PackagesOptions{} + packagesCmd := Packages(v, app, ro, po) + + // root options are also passed to the attestCmd so that a user provided config location can be discovered + attestCmd := Attest(v, app, ro) + poweruserCmd := PowerUser(v, app, ro) + + // rootCmd is currently an alias for the packages command + rootCmd := &cobra.Command{ + Short: packagesCmd.Short, + Long: packagesCmd.Long, + Args: packagesCmd.Args, + Example: packagesCmd.Example, + SilenceUsage: true, + SilenceErrors: true, + RunE: packagesCmd.RunE, + Version: version.FromBuild().Version, + } + rootCmd.SetVersionTemplate(fmt.Sprintf("%s {{.Version}}\n", internal.ApplicationName)) + + // start adding flags to all the commands + err := ro.AddFlags(rootCmd, v) + if err != nil { + return nil, err + } + // package flags need to be decorated onto the rootCmd so that rootCmd can function as a packages alias + err = po.AddFlags(rootCmd, v) + if err != nil { + return nil, err + } + // attest also uses flags from the packagesCmd since it generates an sbom + err = po.AddFlags(attestCmd, v) + if err != nil { + return nil, err + } + // poweruser also uses the packagesCmd flags since it is a specialized version of the command + err = po.AddFlags(poweruserCmd, v) + if err != nil { + return nil, err + } + + // Add sub-commands. + rootCmd.AddCommand(packagesCmd) + rootCmd.AddCommand(attestCmd) + rootCmd.AddCommand(poweruserCmd) + rootCmd.AddCommand(Completion()) + rootCmd.AddCommand(Version(v, app)) + + return rootCmd, err +} + +func validateArgs(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + // in the case that no arguments are given we want to show the help text and return with a non-0 return code. + if err := cmd.Help(); err != nil { + return fmt.Errorf("unable to display help: %w", err) + } + return fmt.Errorf("an image/directory argument is required") + } + + return cobra.MaximumNArgs(1)(cmd, args) +} + +func checkForApplicationUpdate() { + log.Debugf("checking if new vesion of %s is available", internal.ApplicationName) + isAvailable, newVersion, err := version.IsUpdateAvailable() + if err != nil { + // this should never stop the application + log.Errorf(err.Error()) + } + if isAvailable { + log.Infof("new version of %s is available: %s (current version is %s)", internal.ApplicationName, newVersion, version.FromBuild().Version) + + bus.Publish(partybus.Event{ + Type: event.AppUpdateAvailable, + Value: newVersion, + }) + } else { + log.Debugf("no new %s update available", internal.ApplicationName) + } +} + +func logApplicationConfig(app *config.Application) { + log.Debugf("application config:\n%+v", color.Magenta.Sprint(app.String())) +} + +func newLogWrapper(app *config.Application) { + cfg := logger.LogrusConfig{ + EnableConsole: (app.Log.FileLocation == "" || app.Verbosity > 0) && !app.Quiet, + EnableFile: app.Log.FileLocation != "", + Level: app.Log.LevelOpt, + Structured: app.Log.Structured, + FileLocation: app.Log.FileLocation, + } + + logWrapper := logger.NewLogrusLogger(cfg) + syft.SetLogger(logWrapper) + stereoscope.SetLogger(&logger.LogrusNestedLogger{ + Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"), + }) +} diff --git a/cmd/syft/cli/completion.go b/cmd/syft/cli/completion.go new file mode 100644 index 00000000000..9896f8d732f --- /dev/null +++ b/cmd/syft/cli/completion.go @@ -0,0 +1,54 @@ +package cli + +import ( + "os" + + "github.com/spf13/cobra" +) + +func Completion() *cobra.Command { + cmd := &cobra.Command{ + Use: "completion [bash|zsh|fish]", + Short: "Generate a shell completion for Syft (listing local docker images)", + Long: `To load completions (docker image list): + Bash: + $ source <(syft completion bash) +# To load completions for each session, execute once: + Linux: + $ syft completion bash > /etc/bash_completion.d/syft + MacOS: + $ syft completion bash > /usr/local/etc/bash_completion.d/syft + Zsh: +# If shell completion is not already enabled in your environment you will need +# to enable it. You can execute the following once: + $ echo "autoload -U compinit; compinit" >> ~/.zshrc +# To load completions for each session, execute once: + $ syft completion zsh > "${fpath[1]}/_syft" +# You will need to start a new shell for this setup to take effect. + Fish: + $ syft completion fish | source +# To load completions for each session, execute once: + $ syft completion fish > ~/.config/fish/completions/syft.fish + `, + DisableFlagsInUseLine: true, + ValidArgs: []string{"bash", "zsh", "fish"}, + Args: cobra.ExactValidArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + var err error + switch args[0] { + case "bash": + err = cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + err = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + err = cmd.Root().GenFishCompletion(os.Stdout, true) + } + if err != nil { + return err + } + return nil + }, + } + + return cmd +} diff --git a/cmd/event_loop.go b/cmd/syft/cli/eventloop/event_loop.go similarity index 97% rename from cmd/event_loop.go rename to cmd/syft/cli/eventloop/event_loop.go index 6af43d2d99d..c369dc0c9f3 100644 --- a/cmd/event_loop.go +++ b/cmd/syft/cli/eventloop/event_loop.go @@ -1,4 +1,4 @@ -package cmd +package eventloop import ( "errors" @@ -15,7 +15,7 @@ import ( // signal interrupts. Is responsible for handling each event relative to a given UI an to coordinate eventing until // an eventual graceful exit. // nolint:funlen -func eventLoop(workerErrs <-chan error, signals <-chan os.Signal, subscription *partybus.Subscription, cleanupFn func(), uxs ...ui.UI) error { +func EventLoop(workerErrs <-chan error, signals <-chan os.Signal, subscription *partybus.Subscription, cleanupFn func(), uxs ...ui.UI) error { defer cleanupFn() events := subscription.Events() var err error diff --git a/cmd/event_loop_test.go b/cmd/syft/cli/eventloop/event_loop_test.go similarity index 96% rename from cmd/event_loop_test.go rename to cmd/syft/cli/eventloop/event_loop_test.go index 782c27c1742..d2a12fd52af 100644 --- a/cmd/event_loop_test.go +++ b/cmd/syft/cli/eventloop/event_loop_test.go @@ -1,4 +1,4 @@ -package cmd +package eventloop import ( "fmt" @@ -42,7 +42,7 @@ func (u *uiMock) Teardown(_ bool) error { return u.Called().Error(0) } -func Test_eventLoop_gracefulExit(t *testing.T) { +func Test_EventLoop_gracefulExit(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -92,7 +92,7 @@ func Test_eventLoop_gracefulExit(t *testing.T) { } assert.NoError(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, @@ -109,7 +109,7 @@ func Test_eventLoop_gracefulExit(t *testing.T) { testWithTimeout(t, 5*time.Second, test) } -func Test_eventLoop_workerError(t *testing.T) { +func Test_EventLoop_workerError(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -155,7 +155,7 @@ func Test_eventLoop_workerError(t *testing.T) { // ensure we see an error returned assert.ErrorIs(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, @@ -174,7 +174,7 @@ func Test_eventLoop_workerError(t *testing.T) { testWithTimeout(t, 5*time.Second, test) } -func Test_eventLoop_unsubscribeError(t *testing.T) { +func Test_EventLoop_unsubscribeError(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -226,7 +226,7 @@ func Test_eventLoop_unsubscribeError(t *testing.T) { // unsubscribe errors should be handled and ignored, not propagated. We are additionally asserting that // this case is handled as a controlled shutdown (this test should not timeout) assert.NoError(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, @@ -243,7 +243,7 @@ func Test_eventLoop_unsubscribeError(t *testing.T) { testWithTimeout(t, 5*time.Second, test) } -func Test_eventLoop_handlerError(t *testing.T) { +func Test_EventLoop_handlerError(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -296,7 +296,7 @@ func Test_eventLoop_handlerError(t *testing.T) { // handle errors SHOULD propagate the event loop. We are additionally asserting that this case is // handled as a controlled shutdown (this test should not timeout) assert.ErrorIs(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, @@ -315,7 +315,7 @@ func Test_eventLoop_handlerError(t *testing.T) { testWithTimeout(t, 5*time.Second, test) } -func Test_eventLoop_signalsStopExecution(t *testing.T) { +func Test_EventLoop_signalsStopExecution(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -351,7 +351,7 @@ func Test_eventLoop_signalsStopExecution(t *testing.T) { } assert.NoError(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, @@ -368,7 +368,7 @@ func Test_eventLoop_signalsStopExecution(t *testing.T) { testWithTimeout(t, 5*time.Second, test) } -func Test_eventLoop_uiTeardownError(t *testing.T) { +func Test_EventLoop_uiTeardownError(t *testing.T) { test := func(t *testing.T) { testBus := partybus.NewBus() @@ -421,7 +421,7 @@ func Test_eventLoop_uiTeardownError(t *testing.T) { // ensure we see an error returned assert.ErrorIs(t, - eventLoop( + EventLoop( worker(), signaler(), subscription, diff --git a/cmd/signals.go b/cmd/syft/cli/eventloop/signals.go similarity index 83% rename from cmd/signals.go rename to cmd/syft/cli/eventloop/signals.go index f20379d1eeb..72a97711e8d 100644 --- a/cmd/signals.go +++ b/cmd/syft/cli/eventloop/signals.go @@ -1,4 +1,4 @@ -package cmd +package eventloop import ( "os" @@ -6,7 +6,7 @@ import ( "syscall" ) -func setupSignals() <-chan os.Signal { +func SetupSignals() <-chan os.Signal { c := make(chan os.Signal, 1) // Note: A buffered channel is recommended for this; see https://golang.org/pkg/os/signal/#Notify interruptions := []os.Signal{ diff --git a/cmd/tasks.go b/cmd/syft/cli/eventloop/tasks.go similarity index 68% rename from cmd/tasks.go rename to cmd/syft/cli/eventloop/tasks.go index 2d272e7dbfb..c98bcc15fe5 100644 --- a/cmd/tasks.go +++ b/cmd/syft/cli/eventloop/tasks.go @@ -1,9 +1,10 @@ -package cmd +package eventloop import ( "crypto" "fmt" + "github.com/anchore/syft/internal/config" "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" @@ -11,12 +12,12 @@ import ( "github.com/anchore/syft/syft/source" ) -type task func(*sbom.Artifacts, *source.Source) ([]artifact.Relationship, error) +type Task func(*sbom.Artifacts, *source.Source) ([]artifact.Relationship, error) -func tasks() ([]task, error) { - var tasks []task +func Tasks(app *config.Application) ([]Task, error) { + var tasks []Task - generators := []func() (task, error){ + generators := []func(app *config.Application) (Task, error){ generateCatalogPackagesTask, generateCatalogFileMetadataTask, generateCatalogFileDigestsTask, @@ -26,7 +27,7 @@ func tasks() ([]task, error) { } for _, generator := range generators { - task, err := generator() + task, err := generator(app) if err != nil { return nil, err } @@ -39,13 +40,13 @@ func tasks() ([]task, error) { return tasks, nil } -func generateCatalogPackagesTask() (task, error) { - if !appConfig.Package.Cataloger.Enabled { +func generateCatalogPackagesTask(app *config.Application) (Task, error) { + if !app.Package.Cataloger.Enabled { return nil, nil } task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, appConfig.Package.ToConfig()) + packageCatalog, relationships, theDistro, err := syft.CatalogPackages(src, app.Package.ToConfig()) if err != nil { return nil, err } @@ -59,15 +60,15 @@ func generateCatalogPackagesTask() (task, error) { return task, nil } -func generateCatalogFileMetadataTask() (task, error) { - if !appConfig.FileMetadata.Cataloger.Enabled { +func generateCatalogFileMetadataTask(app *config.Application) (Task, error) { + if !app.FileMetadata.Cataloger.Enabled { return nil, nil } metadataCataloger := file.NewMetadataCataloger() task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - resolver, err := src.FileResolver(appConfig.FileMetadata.Cataloger.ScopeOpt) + resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt) if err != nil { return nil, err } @@ -83,8 +84,8 @@ func generateCatalogFileMetadataTask() (task, error) { return task, nil } -func generateCatalogFileDigestsTask() (task, error) { - if !appConfig.FileMetadata.Cataloger.Enabled { +func generateCatalogFileDigestsTask(app *config.Application) (Task, error) { + if !app.FileMetadata.Cataloger.Enabled { return nil, nil } @@ -98,7 +99,7 @@ func generateCatalogFileDigestsTask() (task, error) { } var hashes []crypto.Hash - for _, hashStr := range appConfig.FileMetadata.Digests { + for _, hashStr := range app.FileMetadata.Digests { name := file.CleanDigestAlgorithmName(hashStr) hashObj, ok := supportedHashAlgorithms[name] if !ok { @@ -113,7 +114,7 @@ func generateCatalogFileDigestsTask() (task, error) { } task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - resolver, err := src.FileResolver(appConfig.FileMetadata.Cataloger.ScopeOpt) + resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt) if err != nil { return nil, err } @@ -129,23 +130,23 @@ func generateCatalogFileDigestsTask() (task, error) { return task, nil } -func generateCatalogSecretsTask() (task, error) { - if !appConfig.Secrets.Cataloger.Enabled { +func generateCatalogSecretsTask(app *config.Application) (Task, error) { + if !app.Secrets.Cataloger.Enabled { return nil, nil } - patterns, err := file.GenerateSearchPatterns(file.DefaultSecretsPatterns, appConfig.Secrets.AdditionalPatterns, appConfig.Secrets.ExcludePatternNames) + patterns, err := file.GenerateSearchPatterns(file.DefaultSecretsPatterns, app.Secrets.AdditionalPatterns, app.Secrets.ExcludePatternNames) if err != nil { return nil, err } - secretsCataloger, err := file.NewSecretsCataloger(patterns, appConfig.Secrets.RevealValues, appConfig.Secrets.SkipFilesAboveSize) + secretsCataloger, err := file.NewSecretsCataloger(patterns, app.Secrets.RevealValues, app.Secrets.SkipFilesAboveSize) if err != nil { return nil, err } task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - resolver, err := src.FileResolver(appConfig.Secrets.Cataloger.ScopeOpt) + resolver, err := src.FileResolver(app.Secrets.Cataloger.ScopeOpt) if err != nil { return nil, err } @@ -161,8 +162,8 @@ func generateCatalogSecretsTask() (task, error) { return task, nil } -func generateCatalogFileClassificationsTask() (task, error) { - if !appConfig.FileClassification.Cataloger.Enabled { +func generateCatalogFileClassificationsTask(app *config.Application) (Task, error) { + if !app.FileClassification.Cataloger.Enabled { return nil, nil } @@ -173,7 +174,7 @@ func generateCatalogFileClassificationsTask() (task, error) { } task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - resolver, err := src.FileResolver(appConfig.FileClassification.Cataloger.ScopeOpt) + resolver, err := src.FileResolver(app.FileClassification.Cataloger.ScopeOpt) if err != nil { return nil, err } @@ -189,18 +190,18 @@ func generateCatalogFileClassificationsTask() (task, error) { return task, nil } -func generateCatalogContentsTask() (task, error) { - if !appConfig.FileContents.Cataloger.Enabled { +func generateCatalogContentsTask(app *config.Application) (Task, error) { + if !app.FileContents.Cataloger.Enabled { return nil, nil } - contentsCataloger, err := file.NewContentsCataloger(appConfig.FileContents.Globs, appConfig.FileContents.SkipFilesAboveSize) + contentsCataloger, err := file.NewContentsCataloger(app.FileContents.Globs, app.FileContents.SkipFilesAboveSize) if err != nil { return nil, err } task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) { - resolver, err := src.FileResolver(appConfig.FileContents.Cataloger.ScopeOpt) + resolver, err := src.FileResolver(app.FileContents.Cataloger.ScopeOpt) if err != nil { return nil, err } @@ -216,7 +217,7 @@ func generateCatalogContentsTask() (task, error) { return task, nil } -func runTask(t task, a *sbom.Artifacts, src *source.Source, c chan<- artifact.Relationship, errs chan<- error) { +func RunTask(t Task, a *sbom.Artifacts, src *source.Source, c chan<- artifact.Relationship, errs chan<- error) { defer close(c) relationships, err := t(a, src) diff --git a/cmd/syft/cli/options/attest.go b/cmd/syft/cli/options/attest.go new file mode 100644 index 00000000000..b36d1cb3f46 --- /dev/null +++ b/cmd/syft/cli/options/attest.go @@ -0,0 +1,28 @@ +package options + +import ( + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +type AttestOptions struct { + Key string +} + +var _ Interface = (*AttestOptions)(nil) + +func (o *AttestOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error { + cmd.PersistentFlags().StringVarP(&o.Key, "key", "", "cosign.key", + "path to the private key file to use for attestation") + + return bindAttestationConfigOptions(cmd.PersistentFlags(), v) +} + +func bindAttestationConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error { + if err := v.BindPFlag("attest.key", flags.Lookup("key")); err != nil { + return err + } + + return nil +} diff --git a/cmd/format_aliases.go b/cmd/syft/cli/options/format.go similarity index 90% rename from cmd/format_aliases.go rename to cmd/syft/cli/options/format.go index 375b5f6574a..8ccdf44c65a 100644 --- a/cmd/format_aliases.go +++ b/cmd/syft/cli/options/format.go @@ -1,11 +1,11 @@ -package cmd +package options import ( "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/sbom" ) -func formatAliases(ids ...sbom.FormatID) (aliases []string) { +func FormatAliases(ids ...sbom.FormatID) (aliases []string) { for _, id := range ids { switch id { case syft.JSONFormatID: diff --git a/cmd/syft/cli/options/options.go b/cmd/syft/cli/options/options.go new file mode 100644 index 00000000000..f8646bbb9c8 --- /dev/null +++ b/cmd/syft/cli/options/options.go @@ -0,0 +1,11 @@ +package options + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type Interface interface { + // AddFlags adds this options' flags to the cobra command. + AddFlags(cmd *cobra.Command, v *viper.Viper) error +} diff --git a/cmd/syft/cli/options/packages.go b/cmd/syft/cli/options/packages.go new file mode 100644 index 00000000000..8615a249eb6 --- /dev/null +++ b/cmd/syft/cli/options/packages.go @@ -0,0 +1,118 @@ +package options + +import ( + "fmt" + + "github.com/anchore/syft/internal/formats/table" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/pkg/cataloger" + "github.com/anchore/syft/syft/source" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +type PackagesOptions struct { + Scope string + Output []string + File string + Platform string + Host string + Username string + Password string + Dockerfile string + Exclude []string + OverwriteExistingImage bool + ImportTimeout uint +} + +var _ Interface = (*PackagesOptions)(nil) + +func (o *PackagesOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error { + cmd.PersistentFlags().StringVarP(&o.Scope, "scope", "s", cataloger.DefaultSearchConfig().Scope.String(), + fmt.Sprintf("selection of layers to catalog, options=%v", source.AllScopes)) + + cmd.PersistentFlags().StringArrayVarP(&o.Output, "output", "o", FormatAliases(table.ID), + fmt.Sprintf("report output format, options=%v", FormatAliases(syft.FormatIDs()...))) + + cmd.PersistentFlags().StringVarP(&o.File, "file", "", "", + "file to write the default report output to (default is STDOUT)") + + cmd.PersistentFlags().StringVarP(&o.Platform, "platform", "", "", + "an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')") + + cmd.PersistentFlags().StringVarP(&o.Host, "host", "H", "", + "the hostname or URL of the Anchore Enterprise instance to upload to") + + cmd.PersistentFlags().StringVarP(&o.Username, "username", "u", "", + "the username to authenticate against Anchore Enterprise") + + cmd.PersistentFlags().StringVarP(&o.Password, "password", "p", "", + "the password to authenticate against Anchore Enterprise") + + cmd.PersistentFlags().StringVarP(&o.Dockerfile, "dockerfile", "d", "", + "include dockerfile for upload to Anchore Enterprise") + + cmd.PersistentFlags().StringArrayVarP(&o.Exclude, "exclude", "", nil, + "exclude paths from being scanned using a glob expression") + + cmd.PersistentFlags().BoolVarP(&o.OverwriteExistingImage, "overwrite-existing-image", "", false, + "overwrite an existing image during the upload to Anchore Enterprise") + + cmd.PersistentFlags().UintVarP(&o.ImportTimeout, "import-timeout", "", 30, + "set a timeout duration (in seconds) for the upload to Anchore Enterprise") + + return bindPackageConfigOptions(cmd.PersistentFlags(), v) +} + +func bindPackageConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error { + // Formatting & Input options ////////////////////////////////////////////// + + if err := v.BindPFlag("package.cataloger.scope", flags.Lookup("scope")); err != nil { + return err + } + + if err := v.BindPFlag("file", flags.Lookup("file")); err != nil { + return err + } + + if err := v.BindPFlag("exclude", flags.Lookup("exclude")); err != nil { + return err + } + + if err := v.BindPFlag("output", flags.Lookup("output")); err != nil { + return err + } + + if err := v.BindPFlag("platform", flags.Lookup("platform")); err != nil { + return err + } + + // Upload options ////////////////////////////////////////////////////////// + + if err := v.BindPFlag("anchore.host", flags.Lookup("host")); err != nil { + return err + } + + if err := v.BindPFlag("anchore.username", flags.Lookup("username")); err != nil { + return err + } + + if err := v.BindPFlag("anchore.password", flags.Lookup("password")); err != nil { + return err + } + + if err := v.BindPFlag("anchore.dockerfile", flags.Lookup("dockerfile")); err != nil { + return err + } + + if err := v.BindPFlag("anchore.overwrite-existing-image", flags.Lookup("overwrite-existing-image")); err != nil { + return err + } + + if err := v.BindPFlag("anchore.import-timeout", flags.Lookup("import-timeout")); err != nil { + return err + } + + return nil +} diff --git a/cmd/syft/cli/options/root.go b/cmd/syft/cli/options/root.go new file mode 100644 index 00000000000..176ec2aece6 --- /dev/null +++ b/cmd/syft/cli/options/root.go @@ -0,0 +1,36 @@ +package options + +import ( + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +type RootOptions struct { + Config string + Quiet bool + Verbose int +} + +var _ Interface = (*RootOptions)(nil) + +func (o *RootOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error { + cmd.PersistentFlags().StringVarP(&o.Config, "config", "c", "", "application config file") + cmd.PersistentFlags().CountVarP(&o.Verbose, "verbose", "v", "increase verbosity (-v = info, -vv = debug)") + cmd.PersistentFlags().BoolVarP(&o.Quiet, "quiet", "q", false, "suppress all logging output") + + return bindRootConfigOptions(cmd.PersistentFlags(), v) +} + +func bindRootConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error { + if err := v.BindPFlag("config", flags.Lookup("config")); err != nil { + return err + } + if err := v.BindPFlag("verbosity", flags.Lookup("verbose")); err != nil { + return err + } + if err := v.BindPFlag("quiet", flags.Lookup("quiet")); err != nil { + return err + } + return nil +} diff --git a/cmd/syft/cli/options/verbose.go b/cmd/syft/cli/options/verbose.go new file mode 100644 index 00000000000..aa53bb40ebe --- /dev/null +++ b/cmd/syft/cli/options/verbose.go @@ -0,0 +1,18 @@ +package options + +import ( + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/config" + "github.com/anchore/syft/internal/log" +) + +func IsVerbose(app *config.Application) (result bool) { + isPipedInput, err := internal.IsPipedInput() + if err != nil { + // since we can't tell if there was piped input we assume that there could be to disable the ETUI + log.Warnf("unable to determine if there is piped input: %+v", err) + return true + } + // verbosity should consider if there is piped input (in which case we should not show the ETUI) + return app.Verbosity > 0 || isPipedInput +} diff --git a/cmd/syft/cli/options/version.go b/cmd/syft/cli/options/version.go new file mode 100644 index 00000000000..ea03c7c48e6 --- /dev/null +++ b/cmd/syft/cli/options/version.go @@ -0,0 +1,17 @@ +package options + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type VersionOptions struct { + Output string +} + +var _ Interface = (*PackagesOptions)(nil) + +func (o *VersionOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error { + cmd.Flags().StringVarP(&o.Output, "output", "o", "text", "format to show version information (available=[text, json])") + return nil +} diff --git a/cmd/syft/cli/packages.go b/cmd/syft/cli/packages.go new file mode 100644 index 00000000000..1ad4e6de34e --- /dev/null +++ b/cmd/syft/cli/packages.go @@ -0,0 +1,79 @@ +package cli + +import ( + "fmt" + "log" + + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/cli/packages" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + packagesExample = ` {{.appName}} {{.command}} alpine:latest a summary of discovered packages + {{.appName}} {{.command}} alpine:latest -o json show all possible cataloging details + {{.appName}} {{.command}} alpine:latest -o cyclonedx show a CycloneDX formatted SBOM + {{.appName}} {{.command}} alpine:latest -o cyclonedx-json show a CycloneDX JSON formatted SBOM + {{.appName}} {{.command}} alpine:latest -o spdx show a SPDX 2.2 Tag-Value formatted SBOM + {{.appName}} {{.command}} alpine:latest -o spdx-json show a SPDX 2.2 JSON formatted SBOM + {{.appName}} {{.command}} alpine:latest -vv show verbose debug information + + Supports the following image sources: + {{.appName}} {{.command}} yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. + {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory +` + + schemeHelpHeader = "You can also explicitly specify the scheme to use:" + imageSchemeHelp = ` {{.appName}} {{.command}} docker:yourrepo/yourimage:tag explicitly use the Docker daemon + {{.appName}} {{.command}} podman:yourrepo/yourimage:tag explicitly use the Podman daemon + {{.appName}} {{.command}} registry:yourrepo/yourimage:tag pull image directly from a registry (no container runtime required) + {{.appName}} {{.command}} docker-archive:path/to/yourimage.tar use a tarball from disk for archives created from "docker save" + {{.appName}} {{.command}} oci-archive:path/to/yourimage.tar use a tarball from disk for OCI archives (from Skopeo or otherwise) + {{.appName}} {{.command}} oci-dir:path/to/yourimage read directly from a path on disk for OCI layout directories (from Skopeo or otherwise) +` + nonImageSchemeHelp = ` {{.appName}} {{.command}} dir:path/to/yourproject read directly from a path on disk (any directory) + {{.appName}} {{.command}} file:path/to/yourproject/file read directly from a path on disk (any single file) +` + packagesSchemeHelp = "\n" + indent + schemeHelpHeader + "\n" + imageSchemeHelp + nonImageSchemeHelp + + packagesHelp = packagesExample + packagesSchemeHelp +) + +func Packages(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "packages [SOURCE]", + Short: "Generate a package SBOM", + Long: "Generate a packaged-based Software Bill Of Materials (SBOM) from container images and filesystems", + Example: internal.Tprintf(packagesHelp, map[string]interface{}{ + "appName": internal.ApplicationName, + "command": "packages", + }), + Args: func(cmd *cobra.Command, args []string) error { + if err := app.LoadAllValues(v, ro.Config); err != nil { + return fmt.Errorf("invalid application config: %v", err) + } + // configure logging for command + newLogWrapper(app) + logApplicationConfig(app) + return validateArgs(cmd, args) + }, + SilenceUsage: true, + SilenceErrors: true, + RunE: func(cmd *cobra.Command, args []string) error { + if app.CheckForAppUpdate { + checkForApplicationUpdate() + } + return packages.Run(cmd.Context(), app, args) + }, + } + + err := po.AddFlags(cmd, v) + if err != nil { + log.Fatal(err) + } + + return cmd +} diff --git a/cmd/syft/cli/packages/packages.go b/cmd/syft/cli/packages/packages.go new file mode 100644 index 00000000000..c0615022ff1 --- /dev/null +++ b/cmd/syft/cli/packages/packages.go @@ -0,0 +1,240 @@ +package packages + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/anchore/stereoscope" + "github.com/anchore/syft/cmd/syft/cli/eventloop" + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/anchore" + "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/config" + "github.com/anchore/syft/internal/formats/table" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/ui" + "github.com/anchore/syft/internal/version" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/event" + "github.com/anchore/syft/syft/sbom" + "github.com/anchore/syft/syft/source" + "github.com/hashicorp/go-multierror" + "github.com/wagoodman/go-partybus" +) + +func Run(ctx context.Context, app *config.Application, args []string) error { + writer, err := makeWriter(app.Outputs, app.File) + if err != nil { + return err + } + + defer func() { + if err := writer.Close(); err != nil { + log.Warnf("unable to write to report destination: %w", err) + } + }() + + // could be an image or a directory, with or without a scheme + userInput := args[0] + si, err := source.ParseInput(userInput, app.Platform, true) + if err != nil { + return fmt.Errorf("could not generate source input for packages command: %w", err) + } + + eventBus := partybus.NewBus() + stereoscope.SetBus(eventBus) + syft.SetBus(eventBus) + + return eventloop.EventLoop( + execWorker(app, *si, writer), + eventloop.SetupSignals(), + eventBus.Subscribe(), + stereoscope.Cleanup, + ui.Select(options.IsVerbose(app), app.Quiet)..., + ) +} + +func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error { + errs := make(chan error) + go func() { + defer close(errs) + + src, cleanup, err := source.New(si, app.Registry.ToOptions(), app.Exclusions) + if cleanup != nil { + defer cleanup() + } + if err != nil { + errs <- fmt.Errorf("failed to construct source from user input %q: %w", si.UserInput, err) + return + } + + s, err := GenerateSBOM(src, errs, app) + if err != nil { + errs <- err + return + } + + if s == nil { + errs <- fmt.Errorf("no SBOM produced for %q", si.UserInput) + } + + if app.Anchore.Host != "" { + if err := runPackageSbomUpload(src, *s, app); err != nil { + errs <- err + return + } + } + + bus.Publish(partybus.Event{ + Type: event.Exit, + Value: func() error { return writer.Write(*s) }, + }) + }() + return errs +} + +func GenerateSBOM(src *source.Source, errs chan error, app *config.Application) (*sbom.SBOM, error) { + tasks, err := eventloop.Tasks(app) + if err != nil { + return nil, err + } + + s := sbom.SBOM{ + Source: src.Metadata, + Descriptor: sbom.Descriptor{ + Name: internal.ApplicationName, + Version: version.FromBuild().Version, + Configuration: app, + }, + } + + buildRelationships(&s, src, tasks, errs) + + return &s, nil +} + +func buildRelationships(s *sbom.SBOM, src *source.Source, tasks []eventloop.Task, errs chan error) { + var relationships []<-chan artifact.Relationship + for _, task := range tasks { + c := make(chan artifact.Relationship) + relationships = append(relationships, c) + go eventloop.RunTask(task, &s.Artifacts, src, c, errs) + } + + s.Relationships = append(s.Relationships, MergeRelationships(relationships...)...) +} + +func MergeRelationships(cs ...<-chan artifact.Relationship) (relationships []artifact.Relationship) { + for _, c := range cs { + for n := range c { + relationships = append(relationships, n) + } + } + + return relationships +} + +func runPackageSbomUpload(src *source.Source, s sbom.SBOM, app *config.Application) error { + log.Infof("uploading results to %s", app.Anchore.Host) + + if src.Metadata.Scheme != source.ImageScheme { + return fmt.Errorf("unable to upload results: only images are supported") + } + + var dockerfileContents []byte + if app.Anchore.Dockerfile != "" { + if _, err := os.Stat(app.Anchore.Dockerfile); os.IsNotExist(err) { + return fmt.Errorf("unable dockerfile=%q does not exist: %w", app.Anchore.Dockerfile, err) + } + + fh, err := os.Open(app.Anchore.Dockerfile) + if err != nil { + return fmt.Errorf("unable to open dockerfile=%q: %w", app.Anchore.Dockerfile, err) + } + + dockerfileContents, err = ioutil.ReadAll(fh) + if err != nil { + return fmt.Errorf("unable to read dockerfile=%q: %w", app.Anchore.Dockerfile, err) + } + } + + c, err := anchore.NewClient(anchore.Configuration{ + BaseURL: app.Anchore.Host, + Username: app.Anchore.Username, + Password: app.Anchore.Password, + }) + + if err != nil { + return fmt.Errorf("failed to create anchore client: %w", err) + } + + importCfg := anchore.ImportConfig{ + ImageMetadata: src.Image.Metadata, + SBOM: s, + Dockerfile: dockerfileContents, + OverwriteExistingUpload: app.Anchore.OverwriteExistingImage, + Timeout: app.Anchore.ImportTimeout, + } + + if err := c.Import(context.Background(), importCfg); err != nil { + return fmt.Errorf("failed to upload results to host=%s: %+v", app.Anchore.Host, err) + } + + return nil +} + +// makeWriter creates a sbom.Writer for output or returns an error. this will either return a valid writer +// or an error but neither both and if there is no error, sbom.Writer.Close() should be called +func makeWriter(outputs []string, defaultFile string) (sbom.Writer, error) { + outputOptions, err := parseOptions(outputs, defaultFile) + if err != nil { + return nil, err + } + + writer, err := sbom.NewWriter(outputOptions...) + if err != nil { + return nil, err + } + + return writer, nil +} + +// parseOptions utility to parse command-line option strings and retain the existing behavior of default format and file +func parseOptions(outputs []string, defaultFile string) (out []sbom.WriterOption, errs error) { + // always should have one option -- we generally get the default of "table", but just make sure + if len(outputs) == 0 { + outputs = append(outputs, string(table.ID)) + } + + for _, name := range outputs { + name = strings.TrimSpace(name) + + // split to at most two parts for = + parts := strings.SplitN(name, "=", 2) + + // the format name is the first part + name = parts[0] + + // default to the --file or empty string if not specified + file := defaultFile + + // If a file is specified as part of the output formatName, use that + if len(parts) > 1 { + file = parts[1] + } + + format := syft.FormatByName(name) + if format == nil { + errs = multierror.Append(errs, fmt.Errorf("bad output format: '%s'", name)) + continue + } + + out = append(out, sbom.NewWriterOption(format, file)) + } + return out, errs +} diff --git a/cmd/syft/cli/poweruser.go b/cmd/syft/cli/poweruser.go new file mode 100644 index 00000000000..1ca95e99a56 --- /dev/null +++ b/cmd/syft/cli/poweruser.go @@ -0,0 +1,49 @@ +package cli + +import ( + "fmt" + + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/cli/poweruser" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const powerUserExample = ` {{.appName}} {{.command}} + 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. + All behavior is controlled via application configuration and environment variables (see https://github.com/anchore/syft#configuration) +` + +func PowerUser(v *viper.Viper, app *config.Application, ro *options.RootOptions) *cobra.Command { + cmd := &cobra.Command{ + Use: "power-user [IMAGE]", + Short: "Run bulk operations on container images", + Example: internal.Tprintf(powerUserExample, map[string]interface{}{ + "appName": internal.ApplicationName, + "command": "power-user", + }), + Args: func(cmd *cobra.Command, args []string) error { + if err := app.LoadAllValues(v, ro.Config); err != nil { + return fmt.Errorf("invalid application config: %v", err) + } + // configure logging for command + newLogWrapper(app) + logApplicationConfig(app) + return validateArgs(cmd, args) + }, + Hidden: true, + SilenceUsage: true, + SilenceErrors: true, + RunE: func(cmd *cobra.Command, args []string) error { + if app.CheckForAppUpdate { + checkForApplicationUpdate() + } + return poweruser.Run(cmd.Context(), app, args) + }, + } + + return cmd +} diff --git a/cmd/syft/cli/poweruser/poweruser.go b/cmd/syft/cli/poweruser/poweruser.go new file mode 100644 index 00000000000..7faad4cce09 --- /dev/null +++ b/cmd/syft/cli/poweruser/poweruser.go @@ -0,0 +1,116 @@ +package poweruser + +import ( + "context" + "fmt" + "os" + + "github.com/anchore/stereoscope" + "github.com/anchore/syft/cmd/syft/cli/eventloop" + "github.com/anchore/syft/cmd/syft/cli/options" + "github.com/anchore/syft/cmd/syft/cli/packages" + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/bus" + "github.com/anchore/syft/internal/config" + "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/ui" + "github.com/anchore/syft/internal/version" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/event" + "github.com/anchore/syft/syft/sbom" + "github.com/anchore/syft/syft/source" + "github.com/gookit/color" + "github.com/wagoodman/go-partybus" +) + +func Run(ctx context.Context, app *config.Application, args []string) error { + writer, err := sbom.NewWriter(sbom.WriterOption{ + Format: syftjson.Format(), + Path: app.File, + }) + if err != nil { + return err + } + + defer func() { + if err := writer.Close(); err != nil { + log.Warnf("unable to write to report destination: %+v", err) + } + + // inform user at end of run that command will be removed + deprecated := color.Style{color.Red, color.OpBold}.Sprint("DEPRECATED: This command will be removed in v1.0.0") + fmt.Fprintln(os.Stderr, deprecated) + }() + + userInput := args[0] + si, err := source.ParseInput(userInput, app.Platform, true) + if err != nil { + return fmt.Errorf("could not generate source input for packages command: %w", err) + } + + eventBus := partybus.NewBus() + stereoscope.SetBus(eventBus) + syft.SetBus(eventBus) + + return eventloop.EventLoop( + execWorker(app, *si, writer), + eventloop.SetupSignals(), + eventBus.Subscribe(), + stereoscope.Cleanup, + ui.Select(options.IsVerbose(app), app.Quiet)..., + ) +} + +func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error { + errs := make(chan error) + go func() { + defer close(errs) + + app.Secrets.Cataloger.Enabled = true + app.FileMetadata.Cataloger.Enabled = true + app.FileContents.Cataloger.Enabled = true + app.FileClassification.Cataloger.Enabled = true + tasks, err := eventloop.Tasks(app) + if err != nil { + errs <- err + return + } + + src, cleanup, err := source.New(si, app.Registry.ToOptions(), app.Exclusions) + if err != nil { + errs <- err + return + } + if cleanup != nil { + defer cleanup() + } + + s := sbom.SBOM{ + Source: src.Metadata, + Descriptor: sbom.Descriptor{ + Name: internal.ApplicationName, + Version: version.FromBuild().Version, + Configuration: app, + }, + } + + var relationships []<-chan artifact.Relationship + for _, task := range tasks { + c := make(chan artifact.Relationship) + relationships = append(relationships, c) + + go eventloop.RunTask(task, &s.Artifacts, src, c, errs) + } + + s.Relationships = append(s.Relationships, packages.MergeRelationships(relationships...)...) + + bus.Publish(partybus.Event{ + Type: event.Exit, + Value: func() error { return writer.Write(s) }, + }) + }() + + return errs +} diff --git a/cmd/version.go b/cmd/syft/cli/version.go similarity index 65% rename from cmd/version.go rename to cmd/syft/cli/version.go index 406936a4f08..078fb005781 100644 --- a/cmd/version.go +++ b/cmd/syft/cli/version.go @@ -1,33 +1,41 @@ -package cmd +package cli import ( "encoding/json" "fmt" + "log" "os" + "github.com/anchore/syft/cmd/syft/cli/options" "github.com/anchore/syft/internal" - + "github.com/anchore/syft/internal/config" "github.com/anchore/syft/internal/version" "github.com/spf13/cobra" + "github.com/spf13/viper" ) -var versionCmdOutputFormat string +func Version(v *viper.Viper, app *config.Application) *cobra.Command { + o := &options.VersionOptions{} + cmd := &cobra.Command{ + Use: "version", + Short: "show the version", + RunE: func(cmd *cobra.Command, args []string) error { + return printVersion(o.Output) + }, + } -var versionCmd = &cobra.Command{ - Use: "version", - Short: "show the version", - Run: printVersion, -} + err := o.AddFlags(cmd, v) + if err != nil { + log.Fatal(err) + } -func init() { - versionCmd.Flags().StringVarP(&versionCmdOutputFormat, "output", "o", "text", "format to show version information (available=[text, json])") - rootCmd.AddCommand(versionCmd) + return cmd } -func printVersion(_ *cobra.Command, _ []string) { +func printVersion(output string) error { versionInfo := version.FromBuild() - switch versionCmdOutputFormat { + switch output { case "text": fmt.Println("Application: ", internal.ApplicationName) fmt.Println("Version: ", versionInfo.Version) @@ -55,7 +63,9 @@ func printVersion(_ *cobra.Command, _ []string) { os.Exit(1) } default: - fmt.Printf("unsupported output format: %s\n", versionCmdOutputFormat) + fmt.Printf("unsupported output format: %s\n", output) os.Exit(1) } + + return nil } diff --git a/cmd/syft/main.go b/cmd/syft/main.go new file mode 100644 index 00000000000..51d42fd6d1b --- /dev/null +++ b/cmd/syft/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "log" + + "github.com/anchore/syft/cmd/syft/cli" +) + +func main() { + cli, err := cli.New() + if err != nil { + log.Fatalf("error during command construction: %v", err) + } + + if err := cli.Execute(); err != nil { + log.Fatalf("error during command execution: %v", err) + } +} diff --git a/go.mod b/go.mod index f8ab5716a8e..960b960f919 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,6 @@ require ( github.com/google/uuid v1.3.0 github.com/gookit/color v1.4.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/in-toto/in-toto-golang v0.3.4-0.20211211042327-af1f9fb822bf github.com/jinzhu/copier v0.3.2 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mholt/archiver/v3 v3.5.1 @@ -33,45 +32,45 @@ require ( github.com/mitchellh/mapstructure v1.4.3 github.com/olekukonko/tablewriter v0.0.5 github.com/pelletier/go-toml v1.9.4 - github.com/pkg/profile v1.5.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.2.0 - github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7 github.com/sirupsen/logrus v1.8.1 github.com/spdx/tools-golang v0.2.0 github.com/spf13/afero v1.8.0 - github.com/spf13/cobra v1.3.0 + github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.1 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/vifraa/gopom v0.1.0 github.com/wagoodman/go-partybus v0.0.0-20210627031916-db1f5573bbc5 github.com/wagoodman/go-progress v0.0.0-20200731105512-1020f39e6240 github.com/wagoodman/jotframe v0.0.0-20211129225309-56b0d0a4aebb github.com/x-cray/logrus-prefixed-formatter v0.5.2 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/mod v0.5.1 - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 + golang.org/x/net v0.0.0-20220325170049-de3da57026de golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/docker/docker v20.10.12+incompatible - github.com/sigstore/cosign v1.6.0 + github.com/in-toto/in-toto-golang v0.3.4-0.20211211042327-af1f9fb822bf + github.com/sigstore/cosign v1.7.2 + github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f ) require ( bitbucket.org/creachadair/shell v0.0.6 // indirect cloud.google.com/go v0.100.2 // indirect - cloud.google.com/go/compute v1.3.0 // indirect - cloud.google.com/go/iam v0.1.1 // indirect - cloud.google.com/go/kms v1.3.0 // indirect - cloud.google.com/go/storage v1.21.0 // indirect - github.com/Azure/azure-sdk-for-go v61.5.0+incompatible // indirect + cloud.google.com/go/compute v1.5.0 // indirect + cloud.google.com/go/iam v0.3.0 // indirect + cloud.google.com/go/kms v1.4.0 // indirect + cloud.google.com/go/storage v1.22.0 // indirect + github.com/Azure/azure-sdk-for-go v63.0.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.24 // indirect + github.com/Azure/go-autorest/autorest v0.11.25 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect @@ -89,21 +88,21 @@ require ( github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.43.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/config v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.14.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.11.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.9.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 // indirect - github.com/aws/smithy-go v1.10.0 // indirect - github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220216180153-3d7835abdf40 // indirect + github.com/aws/aws-sdk-go v1.43.30 // indirect + github.com/aws/aws-sdk-go-v2 v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.9.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.10.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.15.0 // indirect + github.com/aws/smithy-go v1.11.0 // indirect + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -134,7 +133,7 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect github.com/go-openapi/loads v0.21.1 // indirect - github.com/go-openapi/runtime v0.23.1 // indirect + github.com/go-openapi/runtime v0.23.3 // indirect github.com/go-openapi/spec v0.20.4 // indirect github.com/go-openapi/strfmt v0.21.2 // indirect github.com/go-openapi/swag v0.21.1 // indirect @@ -144,7 +143,7 @@ require ( github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect @@ -154,26 +153,27 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/trillian v1.4.0 // indirect - github.com/googleapis/gax-go/v2 v2.1.1 // indirect + github.com/googleapis/gax-go/v2 v2.2.0 // indirect github.com/googleapis/gnostic v0.5.5 // indirect + github.com/googleapis/go-type-adapters v1.0.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.1.0 // indirect + github.com/hashicorp/go-hclog v1.2.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/go-retryablehttp v0.7.0 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.2 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.4.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/vault/api v1.4.1 // indirect + github.com/hashicorp/vault/api v1.5.0 // indirect github.com/hashicorp/vault/sdk v0.4.1 // indirect github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -184,6 +184,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect + github.com/letsencrypt/boulder v0.0.0-20220331220046-b23ab962616e // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect @@ -196,7 +197,7 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pierrec/lz4 v2.6.1+incompatible // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect @@ -211,14 +212,15 @@ require ( github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/soheilhy/cmux v0.1.5 // indirect - github.com/spiffe/go-spiffe/v2 v2.0.0-beta.12 // indirect + github.com/spiffe/go-spiffe/v2 v2.0.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613 // indirect github.com/thales-e-security/pool v0.0.2 // indirect github.com/theupdateframework/go-tuf v0.0.0-20220211205608-f0c3294f63b9 // indirect + github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/urfave/cli v1.22.5 // indirect - github.com/xanzy/go-gitlab v0.56.0 // indirect + github.com/xanzy/go-gitlab v0.62.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/zeebo/errs v1.2.2 // indirect @@ -249,23 +251,23 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect - golang.org/x/tools v0.1.8 // indirect - google.golang.org/api v0.70.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + golang.org/x/tools v0.1.10 // indirect + google.golang.org/api v0.74.0 // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect - k8s.io/api v0.23.3 // indirect - k8s.io/apimachinery v0.23.3 // indirect - k8s.io/client-go v0.23.3 // indirect - k8s.io/klog/v2 v2.40.1 // indirect + k8s.io/api v0.23.5 // indirect + k8s.io/apimachinery v0.23.5 // indirect + k8s.io/client-go v0.23.5 // indirect + k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89 // indirect k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf // indirect - k8s.io/utils v0.0.0-20220127004650-9b3446523e65 // indirect - knative.dev/pkg v0.0.0-20220202132633-df430fa0dd96 // indirect + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect + knative.dev/pkg v0.0.0-20220325200448-1f7514acd0c2 // indirect sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect - sigs.k8s.io/release-utils v0.4.1-0.20220207182343-6dadf2228617 // indirect + sigs.k8s.io/release-utils v0.6.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) @@ -317,15 +319,15 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect + golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect + golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c // indirect - google.golang.org/grpc v1.44.0 // indirect + google.golang.org/genproto v0.0.0-20220405205423-9d709892a2bf // indirect + google.golang.org/grpc v1.45.0 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 3e744bce2ff..bd8b60de4eb 100644 --- a/go.sum +++ b/go.sum @@ -50,22 +50,22 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA= -cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= -cloud.google.com/go/compute v1.3.0 h1:mPL/MzDDYHsh5tHRS9mhmhWlcgClCrCa6ApQCU6wnHI= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68= cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= +cloud.google.com/go/iam v0.3.0 h1:exkAomrVUuzx9kWFI1wm3KI0uoDeUFPB4kKGzx6x+Gc= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0= cloud.google.com/go/kms v1.1.0/go.mod h1:WdbppnCDMDpOvoYBMn1+gNmOeEoZYqAv+HeuKARGCXI= -cloud.google.com/go/kms v1.3.0 h1:hWHaFmfTjtWVgSfX/rzE1qmZa/1AFr/6xQXhnufjyZQ= -cloud.google.com/go/kms v1.3.0/go.mod h1:EIdZ6hpR15zmiaKC8YKYoXplDFnL+Z6f5VCGHJMDhLs= +cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/monitoring v0.1.0/go.mod h1:Hpm3XfzJv+UTiXzCG5Ffp0wijzHTC7Cv4eR7o3x/fEE= cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -87,22 +87,19 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM= -cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14= -cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA= +cloud.google.com/go/storage v1.22.0 h1:NUV0NNp9nkBuW66BFRLuMgldN60C57ET3dhbwLIYio8= +cloud.google.com/go/storage v1.22.0/go.mod h1:GbaLEoMqbVm6sx3Z0R++gSiBlgMv6yUi2q1DeGFKQgE= cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g= cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A= code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= -contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY= -contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8= -contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= @@ -124,8 +121,8 @@ github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v60.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v60.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v61.5.0+incompatible h1:OSHSFeNm7D1InGsQrFjyN9hpxD5Ec60PdsWWudCpah4= -github.com/Azure/azure-sdk-for-go v61.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v63.0.0+incompatible h1:whPsa+jCHQSo5wGMPNLw4bz8q9Co2+vnXHzXGctoTaQ= +github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= @@ -133,9 +130,7 @@ github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEew github.com/Azure/go-amqp v0.16.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= github.com/Azure/go-amqp v0.16.4/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 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/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -146,8 +141,9 @@ github.com/Azure/go-autorest/autorest v0.11.8/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNh github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.22/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs= -github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest v0.11.25 h1:yp+V8DGur2aIUE87ebP8twPLz6k68jtJTlg61mEoByA= +github.com/Azure/go-autorest/autorest v0.11.25/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= @@ -168,8 +164,9 @@ github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWV github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= @@ -185,7 +182,9 @@ github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CycloneDX/cyclonedx-go v0.5.0 h1:RWCnu2OrWUTF5C9DA3L0qVziUD2HlxSUWcL2OXlxfqE= github.com/CycloneDX/cyclonedx-go v0.5.0/go.mod h1:nQXAzrejxO39b14JFz2SvsUElegYfwBDowIzqjdUMk4= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= github.com/GoogleCloudPlatform/cloudsql-proxy v1.27.0/go.mod h1:bn9iHmAjogMoIPkqBGyJ9R1m9cXGCjBE/cuhBs3oEsQ= @@ -222,7 +221,6 @@ github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01 github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/PaesslerAG/gval v1.0.0 h1:GEKnRwkWDdf9dOmKcNrar9EA1bz1z9DqPIO1+iLzhd8= @@ -240,9 +238,7 @@ github.com/ReneKroon/ttlcache/v2 v2.11.0 h1:OvlcYFYi941SBN3v9dsDcC2N8vRxyHcCmJb3 github.com/ReneKroon/ttlcache/v2 v2.11.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= @@ -254,10 +250,8 @@ github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzd github.com/adrg/xdg v0.2.1 h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic= github.com/adrg/xdg v0.2.1/go.mod h1:ZuOshBmzV4Ta+s23hdfFZnBsdzmoR3US0d7ErpqSbTQ= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= github.com/alecthomas/jsonschema v0.0.0-20210301060011-54c507b6f074 h1:Lw9q+WyJLFOR+AULchS5/2GKfM+6gOh4szzizdfH3MU= github.com/alecthomas/jsonschema v0.0.0-20210301060011-54c507b6f074/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= @@ -283,7 +277,6 @@ github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b/go.mod h1: github.com/anchore/stereoscope v0.0.0-20220406160859-c03a18a6b270 h1:NmxPDR6vo3xjwCL6o+tpF1vUad/BVo+WaVSwueB9W9w= github.com/anchore/stereoscope v0.0.0-20220406160859-c03a18a6b270/go.mod h1:yoCLUZY0k/pYLNIy0L80p2Ko0PKVNXm8rHtgxp4OiSc= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -338,48 +331,48 @@ github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK github.com/aws/aws-sdk-go v1.42.8/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.42.22/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= -github.com/aws/aws-sdk-go v1.43.0 h1:y4UrPbxU/mIL08qksVPE/nwH9IXuC1udjOaNyhEe+pI= -github.com/aws/aws-sdk-go v1.43.0/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= +github.com/aws/aws-sdk-go v1.43.30 h1:Q3lgrX/tz/MkEiPVVQnOQThBAK2QC2SCTCKTD1mwGFA= +github.com/aws/aws-sdk-go v1.43.30/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250= github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= -github.com/aws/aws-sdk-go-v2 v1.13.0 h1:1XIXAfxsEmbhbj5ry3D3vX+6ZcUYvIqSm4CWWEuGZCA= -github.com/aws/aws-sdk-go-v2 v1.13.0/go.mod h1:L6+ZpqHaLbAaxsqV0L4cvxZY7QupWJB4fhkf8LXvC7w= +github.com/aws/aws-sdk-go-v2 v1.14.0 h1:IzSYBJHu0ZdUi27kIW6xVrs0eSxI4AzwbenzfXhhVs4= +github.com/aws/aws-sdk-go-v2 v1.14.0/go.mod h1:ZA3Y8V0LrlWj63MQAnRHgKf/5QB//LSZCPNWlWrNGLU= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= github.com/aws/aws-sdk-go-v2/config v1.5.0/go.mod h1:RWlPOAW3E3tbtNAqTwvSW54Of/yP3oiZXMI0xfUdjyA= github.com/aws/aws-sdk-go-v2/config v1.10.1/go.mod h1:auIv5pIIn3jIBHNRcVQcsczn6Pfa6Dyv80Fai0ueoJU= -github.com/aws/aws-sdk-go-v2/config v1.13.1 h1:yLv8bfNoT4r+UvUKQKqRtdnvuWGMK5a82l4ru9Jvnuo= -github.com/aws/aws-sdk-go-v2/config v1.13.1/go.mod h1:Ba5Z4yL/UGbjQUzsiaN378YobhFo0MLfueXGiOsYtEs= +github.com/aws/aws-sdk-go-v2/config v1.14.0 h1:Yr8/7R6H8nqqfqgLATrcB83ax6FE2HcDXEB54XPhE98= +github.com/aws/aws-sdk-go-v2/config v1.14.0/go.mod h1:GKDRrvsq/PTaOYc9252u8Uah1hsIdtor4oIrFvUNPNM= github.com/aws/aws-sdk-go-v2/credentials v1.3.1/go.mod h1:r0n73xwsIVagq8RsxmZbGSRQFj9As3je72C2WzUIToc= github.com/aws/aws-sdk-go-v2/credentials v1.6.1/go.mod h1:QyvQk1IYTqBWSi1T6UgT/W8DMxBVa5pVuLFSRLLhGf8= -github.com/aws/aws-sdk-go-v2/credentials v1.8.0 h1:8Ow0WcyDesGNL0No11jcgb1JAtE+WtubqXjgxau+S0o= -github.com/aws/aws-sdk-go-v2/credentials v1.8.0/go.mod h1:gnMo58Vwx3Mu7hj1wpcG8DI0s57c9o42UQ6wgTQT5to= +github.com/aws/aws-sdk-go-v2/credentials v1.9.0 h1:R3Q5s1uGLUg0aUzi+oRaUqRXhd17G/9+PiVnAwXp4sY= +github.com/aws/aws-sdk-go-v2/credentials v1.9.0/go.mod h1:PyHKqk/+tJuDY7T8R580S1j/AcSD+ODeUZ99CAUKLqQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.3.0/go.mod h1:2LAuqPx1I6jNfaGDucWfA2zqQCYCOMCDHiCOciALyNw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0/go.mod h1:5E1J3/TTYy6z909QNR0QnXGBpfESYGDqd3O0zqONghU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 h1:NITDuUZO34mqtOwFWZiXo7yAHj7kf+XPE+EiKuCBNUI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0/go.mod h1:I6/fHT/fH460v09eg2gVrd8B/IqskhNdpcLH0WNO3QI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0 h1:CkM4d3lNeMXMZ0BDX3BtCktnKA1Ftud84Hb6d+Ix4Rk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0/go.mod h1:rwdUKJV5rm+vHu1ncD1iGDqahBEL8O0tBjVqo9eO2N0= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1/go.mod h1:wN/mvkow08GauDwJ70jnzJ1e+hE+Q3Q7TwpYLXOe9oI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0/go.mod h1:NO3Q5ZTTQtO2xIg2+xTXYDiT7knSejfeDm7WGDaOo0U= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4 h1:CRiQJ4E2RhfDdqbie1ZYDo8QtIo75Mk7oTdJSfwJTMQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4/go.mod h1:XHgQ7Hz2WY2GAn//UXHofLfPXWh+s62MbMOijrg12Lw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5 h1:+phazLmKkjBYhFTsGYH9J7jgnA8+Aer2yE4QeS4zn6A= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5/go.mod h1:2hXc8ooJqF2nAznsbJQIn+7h851/bu8GVC80OVTTqf8= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0/go.mod h1:anlUzBoEWglcUxUQwZA7HQOEVEnQALVZsizAapB2hq8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0 h1:3ADoioDMOtF4uiK59vCpplpCwugEU+v4ZFD29jDL3RQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0/go.mod h1:BsCSJHx5DnDXIrOcqB8KN1/B+hXLG/bi4Y6Vjcx/x9E= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0 h1:PO+HNeJBeRK0yVD9CQZ+VUrYfd5sXqS7YdPYHHcDkR4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0/go.mod h1:miRSv9l093jX/t/j+mBCaLqFHo9xKYzJ7DGm1BsGoJM= github.com/aws/aws-sdk-go-v2/internal/ini v1.1.1/go.mod h1:Zy8smImhTdOETZqfyn01iNOe0CNggVbPjCajyaz6Gvg= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0/go.mod h1:6oXGy4GLpypD3uCh8wcqztigGgmhLToMfjavgh+VySg= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5 h1:ixotxbfTCFpqbuwFv/RcZwyzhkxPSYDYEMcj4niB5Uk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5/go.mod h1:R3sWUqPcfXSiF/LSFJhjyJmpg9uV6yP2yv3YZZjldVI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6 h1:c8s9EhIPVFMFS+R1+rtEghGrf7v83gSUWbcCYX/OPes= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6/go.mod h1:o1ippSg3yJx5EuT4AOGXJCUcmt5vrcxla1cg6K1Q8Iw= github.com/aws/aws-sdk-go-v2/service/ecr v1.4.1/go.mod h1:FglZcyeiBqcbvyinl+n14aT/EWC7S1MIH+Gan2iizt0= -github.com/aws/aws-sdk-go-v2/service/ecr v1.14.0 h1:AAZJJAENsQ4yYbnfvqPZT8Nc1YlEd5CZ4usymlC2b4U= -github.com/aws/aws-sdk-go-v2/service/ecr v1.14.0/go.mod h1:a3WUi3JjM3MFtIYenSYPJ7UZPXsw7U7vzebnynxucks= +github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0 h1:lY2Z2sBP+zSbJ6CvvmnFgPcgknoQ0OJV88AwVetRRFk= +github.com/aws/aws-sdk-go-v2/service/ecr v1.15.0/go.mod h1:4zYI85WiYDhFaU1jPFVfkD7HlBcdnITDE3QxDwy4Kus= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.1/go.mod h1:eD5Eo4drVP2FLTw0G+SMIPWNWvQRGGTtIZR2XeAagoA= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.11.0 h1:axOp0EcAVRrF7F8d9gqApgT/9RjN34aR+cuW5LTgROo= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.11.0/go.mod h1:iurUYk+aG+E2DO0MnQEZKh9zsaIxuTcrvCaAUTUhuTU= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0 h1:LsqBpyRofMG6eDs6YGud6FhdGyIyXelAasPOZ6wWLro= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.12.0/go.mod h1:IArQ3IBR00FkuraKwudKZZU32OxJfdTdwV+W5iZh3Y4= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1/go.mod h1:zceowr5Z1Nh2WVP8bf/3ikB41IZW59E4yIYbg+pC6mw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0/go.mod h1:Mq6AEc+oEjCUlBuLiK5YwW4shSOAKCQ3tXN0sQeYoBA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0 h1:4QAOB3KrvI1ApJK14sliGr3Ie2pjyvNypn/lfzDHfUw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0/go.mod h1:K/qPe6AP2TGYv4l6n7c88zh9jWBDf6nHhvg1fx/EWfU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0 h1:JNMALY8/ZnFsfAzBHtC4gq8JeZPANmIoI2VaBgYzbf8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0/go.mod h1:rBDLgXDAwHOfxZKLRDl8OGTPzFDC+a2pLqNNj8+QwfI= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0/go.mod h1:xKCZ4YFSF2s4Hnb/J0TLeOsKuGzICzcElaOKNGrVnx4= github.com/aws/aws-sdk-go-v2/service/kms v1.10.0/go.mod h1:ZkHWL8m5Nw1g9yMXqpCjnIJtSDToAmNbXXZ9gj0bO7s= github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0/go.mod h1:Gwz3aVctJe6mUY9T//bcALArPUaFmNAy2rTB9qN4No8= @@ -389,19 +382,20 @@ github.com/aws/aws-sdk-go-v2/service/sqs v1.12.0/go.mod h1:TDqDmQnsbgL2ZMIGUf3z9 github.com/aws/aws-sdk-go-v2/service/ssm v1.15.0/go.mod h1:kJa2uHklY03rKsNSbEsToeUgWJ1PambXBtRNacorRhg= github.com/aws/aws-sdk-go-v2/service/sso v1.3.1/go.mod h1:J3A3RGUvuCZjvSuZEcOpHDnzZP/sKbhDWV2T1EOzFIM= github.com/aws/aws-sdk-go-v2/service/sso v1.6.0/go.mod h1:Q/l0ON1annSU+mc0JybDy1Gy6dnJxIcWjphO6qJPzvM= -github.com/aws/aws-sdk-go-v2/service/sso v1.9.0 h1:1qLJeQGBmNQW3mBNzK2CFmrQNmoXWrscPqsrAaU1aTA= -github.com/aws/aws-sdk-go-v2/service/sso v1.9.0/go.mod h1:vCV4glupK3tR7pw7ks7Y4jYRL86VvxS+g5qk04YeWrU= +github.com/aws/aws-sdk-go-v2/service/sso v1.10.0 h1:qCuSRiQhsPU46NH79HUyPQEn5AcpMj+2gsqMYwtzdw8= +github.com/aws/aws-sdk-go-v2/service/sso v1.10.0/go.mod h1:m1CRRFX7eH3EE6w0ntdu+lo+Ph9VS7y8qRV/vdym0ZY= github.com/aws/aws-sdk-go-v2/service/sts v1.6.0/go.mod h1:q7o0j7d7HrJk/vr9uUt3BVRASvcU7gYZB9PUgPiByXg= github.com/aws/aws-sdk-go-v2/service/sts v1.10.0/go.mod h1:jLKCFqS+1T4i7HDqCP9GM4Uk75YW1cS0o82LdxpMyOE= -github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 h1:ksiDXhvNYg0D2/UFkLejsaz3LqpW5yjNQ8Nx9Sn2c0E= -github.com/aws/aws-sdk-go-v2/service/sts v1.14.0/go.mod h1:u0xMJKDvvfocRjiozsoZglVNXRG19043xzp3r2ivLIk= +github.com/aws/aws-sdk-go-v2/service/sts v1.15.0 h1:zC/vHxWTlqZ0tIPJItg0zWHsa25cH7tXsUknSGcH39o= +github.com/aws/aws-sdk-go-v2/service/sts v1.15.0/go.mod h1:E264g2Gl5U9KTGzmd8ypGEAoh75VmqyuA/Ox5O1eRE4= github.com/aws/smithy-go v1.6.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.10.0 h1:gsoZQMNHnX+PaghNw4ynPsyGP7aUCqx5sY2dlPQsZ0w= -github.com/aws/smithy-go v1.10.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220216180153-3d7835abdf40 h1:skzbn0VkQsUGOtr8M0A2xSjZsnLvq/FaFUOd81FUu9A= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220216180153-3d7835abdf40/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= +github.com/aws/smithy-go v1.11.0 h1:nOfSDwiiH232f90OuevPnAEQO5ZqH+xnn8uGVsvBCw4= +github.com/aws/smithy-go v1.11.0/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795 h1:IWeCJzU+IYaO2rVEBlGPTBfe90cmGXFTLdhUFlzDGsY= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20220228164355-396b2034c795/go.mod h1:8vJsEZ4iRqG+Vx6pKhWK6U00qcj0KC37IsfszMkY6UE= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/beeker1121/goque v1.0.3-0.20191103205551-d618510128af/go.mod h1:84CWnaDz4g1tEVnFLnuBigmGK15oPohy0RfvSN8d4eg= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -422,13 +416,10 @@ github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAw github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA= github.com/bmatcuk/doublestar/v4 v4.0.2/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bradleyjkemp/cupaloy/v2 v2.7.0 h1:AT0vOjO68RcLyenLCHOGZzSNiuto7ziqzq6Q1/3xzMQ= @@ -440,10 +431,8 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= -github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= -github.com/carolynvs/magex v0.6.0/go.mod h1:hqaEkr9TAv+kFb/5wgDiTdszF13rpe0Q+bWHmTe6N74= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cavaliercoder/badio v0.0.0-20160213150051-ce5280129e9e/go.mod h1:V284PjgVwSk4ETmz84rpu9ehpGg7swlIH8npP9k2bGw= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= @@ -494,6 +483,7 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH 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 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= @@ -613,6 +603,7 @@ github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= @@ -650,9 +641,7 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= -github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= -github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzkU0rAM92tn3hb3Anb7oz7KcnixF49+2wOMe4= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= @@ -686,7 +675,6 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= @@ -695,10 +683,10 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210914135545-4980593459a1/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/eggsampler/acme/v3 v3.2.1/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -722,12 +710,18 @@ github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg= +github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01/go.mod h1:ypD5nozFk9vcGw1ATYefw6jHe/jZP++Z15/+VTMcWhc= +github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8= +github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52/go.mod h1:yIquW87NGRw1FU5p5lEkpnt/QxoH5uPAOUlOVkAUuMg= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/facebookincubator/nvdtools v0.1.4 h1:x1Ucw9+bSkMd8DJJN4jNQ1Lk4PSFlJarGOxp9D6WUMo= github.com/facebookincubator/nvdtools v0.1.4/go.mod h1:0/FIVnSEl9YHXLq3tKBPpKaI0iUceDhdSHPlIwIX44Y= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -778,6 +772,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.1/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -789,6 +784,7 @@ github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJu 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= +github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -800,7 +796,6 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -862,8 +857,8 @@ github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2g github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= github.com/go-openapi/runtime v0.21.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs= -github.com/go-openapi/runtime v0.23.1 h1:/Drg9R96eMmgKJHVWZADz78XbE39/6QiIiB45mc+epo= -github.com/go-openapi/runtime v0.23.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/runtime v0.23.3 h1:/dxjx4KCOQI5ImBMz036F6v/DzZ2NUjSRvbLJs1rgoE= +github.com/go-openapi/runtime v0.23.3/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= @@ -930,10 +925,12 @@ github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= 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-rod/rod v0.101.8/go.mod h1:N/zlT53CfSpq74nb6rOR0K8UF0SPUPBmzBnArrms+mY= -github.com/go-rod/rod v0.102.1/go.mod h1:RXSLAlPodTFOmZnwaAQJIcOJ1i835r0uuTGPLO09t/M= +github.com/go-rod/rod v0.104.4 h1:sQR35AFo9ceR7ksh+Ld81bQzIbrXlQH/IO46iCWqxts= +github.com/go-rod/rod v0.104.4/go.mod h1:trmrxxg+qUodIIQiYeyJbW5ZMo0FSajmdEGw2tHzlM4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -960,30 +957,51 @@ github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2 github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/attrs v0.1.0/go.mod h1:fmNpaWyHM0tRm8gCZWKx8yY9fvaNLo2PyzBNSrBZ5Hw= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.8.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/envy v1.9.0/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/fizz v1.10.0/go.mod h1:J2XGPO0AfJ1zKw7+2BA+6FEGAkyEsdCOLvN93WCT2WI= github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= +github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/genny/v2 v2.0.5/go.mod h1:kRkJuAw9mdI37AiEYjV4Dl+TgkBDYf8HZVjLkqe5eBg= github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/github_flavored_markdown v1.1.0/go.mod h1:TSpTKWcRTI0+v7W3x8dkSKMLJSUpuVitlptCkpeY8ic= github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/helpers v0.6.0/go.mod h1:pncVrer7x/KRvnL5aJABLAuT/RhKRR9klL6dkUOhyv8= +github.com/gobuffalo/helpers v0.6.1/go.mod h1:wInbDi0vTJKZBviURTLRMFLE4+nF2uRuuL2fnlYo7w4= github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM= github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/nulls v0.2.0/go.mod h1:w4q8RoSCEt87Q0K0sRIZWYeIxkxog5mh3eN3C/n+dUc= github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI= github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/packr/v2 v2.8.0/go.mod h1:PDk2k3vGevNE3SwVyVRgQCCXETC9SaONCNSXT1Q8M1g= +github.com/gobuffalo/plush/v4 v4.0.0/go.mod h1:ErFS3UxKqEb8fpFJT7lYErfN/Nw6vHGiDMTjxpk5bQ0= +github.com/gobuffalo/pop/v5 v5.3.1/go.mod h1:vcEDhh6cJ3WVENqJDFt/6z7zNb7lLnlN8vj3n5G9rYA= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gobuffalo/tags/v3 v3.0.2/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= +github.com/gobuffalo/tags/v3 v3.1.0/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= +github.com/gobuffalo/validate/v3 v3.0.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= +github.com/gobuffalo/validate/v3 v3.1.0/go.mod h1:HFpjq+AIiA2RHoQnQVTFKF/ZpUPXwyw82LgyDPxQ9r0= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -995,6 +1013,7 @@ github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= @@ -1008,8 +1027,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -1067,20 +1087,12 @@ github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZ github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= -github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70= -github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= -github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y= -github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= -github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= -github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55/go.mod h1:fmo8aiSEWkJeiGXUJf+sPvuDgEFgqIoZSs843ePKrGg= -github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= -github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.0.22-0.20181127102053-c25855a82c75/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= github.com/google/certificate-transparency-go v1.1.2-0.20210512142713-bed466244fa6/go.mod h1:aF2dp7Dh81mY8Y/zpzyXps4fQW5zQbDu2CxfpJB6NkI= @@ -1105,7 +1117,6 @@ github.com/google/go-containerregistry v0.7.1-0.20211118220127-abdc633f8305/go.m github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= github.com/google/go-containerregistry v0.8.1-0.20220209165246-a44adc326839 h1:7PunQZxMao2q43If8gKj1JFRzapmhgny9NWwXY4PGa4= github.com/google/go-containerregistry v0.8.1-0.20220209165246-a44adc326839/go.mod h1:cwx3SjrH84Rh9VFJSIhPh43ovyOp3DCWgY3h8nWmdGQ= -github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec= github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg= @@ -1122,7 +1133,6 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= -github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -1170,12 +1180,15 @@ github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0 h1:s7jOdKSaksJVOxE0Y/S32otcfiP+UQ0cL8/GTKaONwE= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= @@ -1193,8 +1206,6 @@ github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -1252,8 +1263,9 @@ github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39 github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw= github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -1279,8 +1291,9 @@ github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtf github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ= github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.2 h1:Tz6v3Jb2DRnDCfifRSjYKG0m8dLdNq6bcDkB41en7nw= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.2/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3 h1:geBw3SBrxQq+buvbf4K+Qltv1gjaXJxy8asD4CjGYow= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= @@ -1292,8 +1305,9 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -1318,14 +1332,18 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vault/api v1.3.0/go.mod h1:EabNQLI0VWbWoGlA+oBLC8PXmR9D60aUVgQGvangFWQ= github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw= -github.com/hashicorp/vault/api v1.4.1 h1:mWLfPT0RhxBitjKr6swieCEP2v5pp/M//t70S3kMLRo= -github.com/hashicorp/vault/api v1.4.1/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM= +github.com/hashicorp/vault/api v1.5.0 h1:Bp6yc2bn7CWkOrVIzFT/Qurzx528bdavF3nz590eu28= +github.com/hashicorp/vault/api v1.5.0/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM= github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0= github.com/hashicorp/vault/sdk v0.4.1 h1:3SaHOJY687jY1fnB61PtL0cOkKItphrbLmux7T92HBo= github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/honeycombio/beeline-go v1.1.1 h1:sU8r4ae34uEL3/CguSl8Mr+Asz9DL1nfH9Wwk85Pc7U= +github.com/honeycombio/beeline-go v1.1.1/go.mod h1:kN0cfUGBMfA87DyCYbiiLoSzWsnw3bluZvNEWtatHxk= +github.com/honeycombio/libhoney-go v1.15.2 h1:5NGcjOxZZma13dmzNcl3OtGbF1hECA0XHJNHEb2t2ck= +github.com/honeycombio/libhoney-go v1.15.2/go.mod h1:JzhRPYgoBCd0rZvudrqmej4Ntx0w7AT3wAJpf5+t1WA= github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= @@ -1351,16 +1369,40 @@ github.com/in-toto/in-toto-golang v0.3.4-0.20211211042327-af1f9fb822bf/go.mod h1 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.6.0/go.mod h1:yeseQo4xhQbgyJs2c87RAXOH2i624N0Fh1KSPJya7qo= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik= +github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= -github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= -github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jedisct1/go-minisign v0.0.0-20210703085342-c1f07ee84431 h1:zqyV5j9xEuPQw2ma4RzzS9O74UwTq3vcMmpoHyL6xlI= github.com/jedisct1/go-minisign v0.0.0-20210703085342-c1f07ee84431/go.mod h1:3VIJLjlf5Iako82IX/5KOoCzDmogK5mO+bl+DRItnR8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -1381,7 +1423,10 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4= +github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= @@ -1411,7 +1456,9 @@ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/karrick/godirwalk v1.15.3/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= +github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -1421,7 +1468,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -1431,7 +1477,6 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1456,15 +1501,23 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/labstack/echo/v4 v4.3.0/go.mod h1:PvmtTvhVqKDzDQy4d3bWzPjZLzom4iQbAZy2sgZ/qI8= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/letsencrypt/boulder v0.0.0-20220331220046-b23ab962616e h1:1aV3EJ4ZMsc63MFU4rB+ccSEhZvvVD71T9RA4Rqd3hI= +github.com/letsencrypt/boulder v0.0.0-20220331220046-b23ab962616e/go.mod h1:Bl3mfF2LHYepsU2XfzMceIglyByfPe1IFAXtO+p37Qk= +github.com/letsencrypt/challtestsrv v1.2.1/go.mod h1:Ur4e4FvELUXLGhkMztHOsPIsvGxD/kzSJninOrkM+zc= github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -1475,9 +1528,9 @@ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQ github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/luna-duclos/instrumentedsql v1.1.3/go.mod h1:9J1njvFds+zN7y85EDhN9XNQLANWwZt2ULeIC8yMNYs= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -1493,7 +1546,9 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= @@ -1514,6 +1569,7 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= @@ -1531,12 +1587,14 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1/go.mod h1:DK1Cjkc0E49ShgRVs5jy5ASrM15svSnem3K/hiSGD8o= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mediocregopher/radix/v4 v4.0.0/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= @@ -1544,14 +1602,15 @@ github.com/mgechev/revive v1.1.2/go.mod h1:bnXsMr+ZTH09V5rssEI+jHAZ4z+ZdyhgO/zsy 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/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -1597,9 +1656,7 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1615,6 +1672,7 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= +github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -1666,7 +1724,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -1676,7 +1733,6 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= @@ -1721,7 +1777,6 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= @@ -1748,9 +1803,9 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1758,8 +1813,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug= -github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= 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= @@ -1768,6 +1821,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1780,8 +1834,9 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1801,7 +1856,6 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= @@ -1821,7 +1875,6 @@ github.com/prometheus/procfs v0.7.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.1/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= github.com/pseudomuto/protoc-gen-doc v1.4.1/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= @@ -1836,9 +1889,7 @@ github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mo github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/qur/ar v0.0.0-20130629153254-282534b91770/go.mod h1:SjlYv2m9lpV0UW6K7lDqVJwEIIvSjaHbGk7nIfY8Hxw= -github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -1847,6 +1898,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= @@ -1854,6 +1907,9 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1876,7 +1932,6 @@ github.com/sassoftware/go-rpmutils v0.1.1/go.mod h1:euhXULoBpvAxqrBHEyJS4Tsu3hHx github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 h1:sUNzanSKA9z/h8xXl+ZJoxIYZL0Qx306MmxqRrvUgr0= github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74/go.mod h1:YlB8wFIZmFLZ1JllNBfSURzz52fBxbliNgYALk1UDmk= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -1896,23 +1951,25 @@ github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAx github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sigstore/cosign v1.6.0 h1:GBG+asPgsf2iawldL9uO8JDGbFO5yXuvaBTjdejsMzo= -github.com/sigstore/cosign v1.6.0/go.mod h1:Ocd28z0Pwtd6+A8s/Vb4SbhwuWOqVdeYAW4yCGF4Ndg= +github.com/sigstore/cosign v1.7.2 h1:kFC0jmPUDfoMOhuL1hHGi+ZdJkeF0qpPYZWmMqKMV+4= +github.com/sigstore/cosign v1.7.2/go.mod h1:v7UKVCOvw9HD5WlApAotoVfjwUzddwg6InJTTshkaOg= github.com/sigstore/fulcio v0.1.2-0.20220114150912-86a2036f9bc7 h1:XE7A9lJ+wYhmUFBWYTaw3Ph943zHB4iBYd5R0SX0ZOA= github.com/sigstore/fulcio v0.1.2-0.20220114150912-86a2036f9bc7/go.mod h1:ANQivY/lfOp9hN92S813LEthkm/kit96hzeIF3SNoZA= github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3 h1:mbqXrm8YZXN/cJMGeBkgPnswtfrOxDE1f7QZdJ+POQE= github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3/go.mod h1:u9clLqaVjqV9pExVL1XkM37dGyMCOX/LMocS9nsnWDY= github.com/sigstore/sigstore v1.0.2-0.20211210190220-04746d994282/go.mod h1:SuM+QIHtnnR9eGsURRLv5JfxM6KeaU0XKA1O7FmLs4Q= github.com/sigstore/sigstore v1.1.0/go.mod h1:gDpcHw4VwpoL5C6N1Ud1YtBsc+ikRDwDelDlWRyYoE8= -github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7 h1:YIyoYwE9ggfBS+LgryGxZEhHQLS21V78jwdAM6fLkIY= -github.com/sigstore/sigstore v1.1.1-0.20220217212907-e48ca03a5ba7/go.mod h1:fPeKQqm6gcEp4Dp6nLp2LMCo3m+U0WfhzIqguCbhY9k= +github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f h1:JPD9q1718mub78ILVcTqOZ/q4ECKCQ7JQfUX/q+nEJ4= +github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f/go.mod h1:9wYagRiKz/8KgK/YFPM6FA8WrNjv3Y6rQUQWBLqJXs0= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1936,7 +1993,9 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM= github.com/spdx/tools-golang v0.2.0 h1:KBNcw7xvVycRWeCWZK/5xQJA+plymW1+rTCs8ekJDro= @@ -1955,12 +2014,14 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1979,8 +2040,8 @@ github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhU github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/spiffe/go-spiffe/v2 v2.0.0-beta.12 h1:Lh9MRyNNsAbGbMiKbVHDw+qk/DlkjS9wBTlH8v7OnaA= -github.com/spiffe/go-spiffe/v2 v2.0.0-beta.12/go.mod h1:TEfgrEcyFhuSuvqohJt6IxENUNeHfndWCCV1EX7UaVk= +github.com/spiffe/go-spiffe/v2 v2.0.0 h1:y6N7BZAxgaFZYELyrIdxSMm2e2tWpzgQewUts9h1hfM= +github.com/spiffe/go-spiffe/v2 v2.0.0/go.mod h1:TEfgrEcyFhuSuvqohJt6IxENUNeHfndWCCV1EX7UaVk= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= @@ -1989,7 +2050,6 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= @@ -2005,8 +2065,9 @@ github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= @@ -2035,6 +2096,8 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= github.com/tilinna/clock v1.1.0/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= @@ -2049,8 +2112,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1 github.com/tomarrell/wrapcheck/v2 v2.4.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2OgfoG8bLp9ZyoBfyY= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= -github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -2071,11 +2132,12 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= @@ -2090,6 +2152,10 @@ github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:tw github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d/go.mod h1:JPirS5jde/CF5qIjcK4WX+eQmKXdPc6vcZkJ/P0hfPw= github.com/wagoodman/go-partybus v0.0.0-20210627031916-db1f5573bbc5 h1:phTLPgMRDYTizrBSKsNSOa2zthoC2KsJsaY/8sg3rD8= github.com/wagoodman/go-partybus v0.0.0-20210627031916-db1f5573bbc5/go.mod h1:JPirS5jde/CF5qIjcK4WX+eQmKXdPc6vcZkJ/P0hfPw= @@ -2098,13 +2164,15 @@ github.com/wagoodman/go-progress v0.0.0-20200731105512-1020f39e6240 h1:r6BlIP7CV github.com/wagoodman/go-progress v0.0.0-20200731105512-1020f39e6240/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA= github.com/wagoodman/jotframe v0.0.0-20211129225309-56b0d0a4aebb h1:Yz6VVOcLuWLAHYlJzTw7JKnWxdV/WXpug2X0quEzRnY= github.com/wagoodman/jotframe v0.0.0-20211129225309-56b0d0a4aebb/go.mod h1:nDi3BAC5nEbVbg+WSJDHLbjHv0ZToq8nMPA97XMxF3E= +github.com/weppos/publicsuffix-go v0.15.1-0.20210807195340-dc689ff0bb59/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= +github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= -github.com/xanzy/go-gitlab v0.56.0 h1:/QHBvk3IKVNwvXB/UOWVb5J6VCN6r2bg9/WxjUbFY/0= -github.com/xanzy/go-gitlab v0.56.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM= +github.com/xanzy/go-gitlab v0.62.0 h1:D3WuIK1UJ7JPSiYI077PQaU5dcPEshpimCSP07Do1aQ= +github.com/xanzy/go-gitlab v0.62.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -2129,10 +2197,16 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/ysmood/goob v0.3.0/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs= +github.com/ysmood/goob v0.3.1 h1:qMp5364BGS1DLJVrAqUxTF6KOFt0YDot8GC70u/0jbI= github.com/ysmood/goob v0.3.1/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs= github.com/ysmood/got v0.15.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= +github.com/ysmood/got v0.19.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= github.com/ysmood/gotrace v0.2.2/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= +github.com/ysmood/gotrace v0.4.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= github.com/ysmood/gson v0.6.4/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/gson v0.7.0 h1:oQhY2FQtfy3+bgaNeqopd7NGAB6Me+UpG0n7oO4VDko= +github.com/ysmood/gson v0.7.0/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/leakless v0.7.0 h1:XCGdaPExyoreoQd+H5qgxM3ReNbSPFsEXpSKwbXbwQw= github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -2151,6 +2225,12 @@ github.com/zalando/go-keyring v0.1.0/go.mod h1:RaxNwUITJaHVdQ0VC7pELPZ3tOWn13nr0 github.com/zalando/go-keyring v0.1.1/go.mod h1:OIC+OZ28XbmwFxU/Rp9V7eKzZjamBJwRzC8UFJH9+L8= github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g= github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= +github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= +github.com/zmap/zcrypto v0.0.0-20210811211718-6f9bc4aff20f/go.mod h1:y/9hjFEub4DtQxTHp/pqticBgdYeCwL97vojV3lsvHY= +github.com/zmap/zlint/v3 v3.3.1-0.20211019173530-cb17369b4628/go.mod h1:O+4OXRfNLKqOyDl4eKZ1SBlYudKGUBGRFcv+m1KLr28= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -2225,13 +2305,17 @@ go.opentelemetry.io/contrib v1.3.0 h1:p9Gd+3dD7yB+AIph2Ltg11QDX6Y+yWMH0YQVTpTTP2 go.opentelemetry.io/contrib v1.3.0/go.mod h1:FlyPNX9s4U6MCsWEc5YAK4KzKNHFDsjrDUZijJiXvy8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/contrib/propagators v0.19.0 h1:HrixVNZYFjUl/Db+Tr3DhqzLsVW9GeVf/Gye+C5dNUY= +go.opentelemetry.io/contrib/propagators v0.19.0/go.mod h1:4QOdZClXISU5S43xZxk5tYaWcpb+lehqfKtE6PK6msE= +go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= @@ -2240,6 +2324,7 @@ go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -2253,7 +2338,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -2267,6 +2351,7 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= @@ -2277,6 +2362,7 @@ go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= gocloud.dev v0.24.1-0.20211119014450-028788aaaa4c/go.mod h1:EIJSlY7nvfeoWaV2GauF6es27gZfqtTVon47QFueoyE= +goji.io/v3 v3.0.0/go.mod h1:c02FFnNiVNCDo+DpR2IhBQpM9r5G1BG/MkHNTPUJ13U= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2288,6 +2374,7 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -2297,19 +2384,20 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -2319,7 +2407,6 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -2328,8 +2415,8 @@ golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506 h1:EuGTJDfeg/PGZJp3gq1K+14eSLFTsrj1eg8KQuiUyKg= -golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -2367,8 +2454,9 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2432,7 +2520,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= @@ -2442,11 +2529,12 @@ golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2454,8 +2542,10 @@ golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127074510-2fabfed7e28f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de h1:pZB1TWnKi+o4bENlbzAgLrEbY4RMYmUIRobMcSmfeYc= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2478,8 +2568,10 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2592,6 +2684,7 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2611,6 +2704,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2636,11 +2730,12 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 h1:eJv7u3ksNXoLbGSKuv2s/SIO4tJVxc/A+MTpzxDgz/Q= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -2660,10 +2755,12 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2686,6 +2783,7 @@ golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -2697,6 +2795,7 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2727,6 +2826,7 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= @@ -2782,16 +2882,19 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -2810,7 +2913,6 @@ google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= @@ -2839,11 +2941,11 @@ google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFd google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg= -google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80= -google.golang.org/api v0.70.0 h1:67zQnAE0T2rB0A3CwLSas0K+SbVzSxP+zTLkQLexeiw= google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0 h1:ExR2D+5TYIrMphWgs5JCgwRhEDlPDXXrLwHHMgPHTXE= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2891,7 +2993,6 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2913,6 +3014,7 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210331142528-b7513248f0ba/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= @@ -2954,14 +3056,15 @@ google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c h1:TU4rFa5APdKTq0s6B7WTsH6Xmx0Knj86s6Biz56mErE= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220405205423-9d709892a2bf h1:JTjwKJX9erVpsw17w+OIPP7iAgEkN/r8urhWSunEDTs= +google.golang.org/genproto v0.0.0-20220405205423-9d709892a2bf/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -3001,8 +3104,9 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -3018,16 +3122,18 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc= +gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= @@ -3039,6 +3145,7 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -3095,82 +3202,66 @@ honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= -k8s.io/api v0.23.3 h1:KNrME8KHGr12Ozjf8ytOewKzZh6hl/hHUZeHddT3a38= -k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ= -k8s.io/apiextensions-apiserver v0.22.5/go.mod h1:tIXeZ0BrDxUb1PoAz+tgOz43Zi1Bp4BEEqVtUccMJbE= +k8s.io/api v0.23.5 h1:zno3LUiMubxD/V1Zw3ijyKO3wxrhbUF1Ck+VjBvfaoA= +k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= -k8s.io/apimachinery v0.23.3 h1:7IW6jxNzrXTsP0c8yXz2E5Yx/WTzVPTsHIx/2Vm0cIk= -k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= +k8s.io/apimachinery v0.23.5 h1:Va7dwhp8wgkUPWsEXk6XglXWU4IKYLKNlv8VkX7SDM0= +k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/client-go v0.23.3 h1:23QYUmCQ/W6hW78xIwm3XqZrrKZM+LWDqW2zfo+szJs= -k8s.io/client-go v0.23.3/go.mod h1:47oMd+YvAOqZM7pcQ6neJtBiFH7alOyfunYN48VsmwE= -k8s.io/code-generator v0.22.5/go.mod h1:sbdWCOVob+KaQ5O7xs8PNNaCTpbWVqNgA6EPwLOmRNk= +k8s.io/client-go v0.23.5 h1:zUXHmEuqx0RY4+CsnkOn5l0GU+skkRXKGJrhmE2SLd8= +k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.40.1 h1:P4RRucWk/lFOlDdkAr3mc7iWFkgKrZY9qZMAgek06S4= -k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89 h1:bUNlsw5yb353zbKMj8srOr6V2Ajhz1VkTKonP1L8r2o= +k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89/go.mod h1:N3kgBtsFxMb4nQ0eBDgbHEt/dtxBuTkSFQ+7K5OUoz4= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf h1:M9XBsiMslw2lb2ZzglC0TOkBPK5NQi0/noUrdnoFwUg= k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220127004650-9b3446523e65 h1:ONWS0Wgdg5wRiQIAui7L/023aC9+IxrIrydY7l8llsE= -k8s.io/utils v0.0.0-20220127004650-9b3446523e65/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -knative.dev/hack v0.0.0-20220118141833-9b2ed8471e30/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= -knative.dev/pkg v0.0.0-20220202132633-df430fa0dd96 h1:JU0DFa06CaUtwSkAY0b3j47ohEJLIYlpPPgNgbPHlAo= -knative.dev/pkg v0.0.0-20220202132633-df430fa0dd96/go.mod h1:etVT7Tm8pSDf4RKhGk4r7j/hj3dNBpvT7bO6a6wpahs= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +knative.dev/pkg v0.0.0-20220325200448-1f7514acd0c2 h1:dJ1YKQ1IvCfxtYqS1dHm18VT153ntHi5uJsFVv7oxfc= +knative.dev/pkg v0.0.0-20220325200448-1f7514acd0c2/go.mod h1:5xt0nzCwxvQ2N4w71smY7pYm5nVrQ8qnRsMinSLVpio= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= -pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/release-utils v0.4.1-0.20220207182343-6dadf2228617 h1:qbKzP8fFAdlnj4WqB9KrAuW4ply+bUQkdRlVrH4Jus0= -sigs.k8s.io/release-utils v0.4.1-0.20220207182343-6dadf2228617/go.mod h1:t9pL38kZkTBVDcjL1y7ajrkNQFLiArVAjOVO0sxzFF0= +sigs.k8s.io/release-utils v0.6.0 h1:wJDuzWJqPH4a5FAxAXE2aBvbB6UMIW7iYMhsKnIMQkA= +sigs.k8s.io/release-utils v0.6.0/go.mod h1:kR1/DuYCJ4covppUasYNcA11OixC9O37B/E0ejRfb+c= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/internal/config/application.go b/internal/config/application.go index c9085fe9530..adb53fc2731 100644 --- a/internal/config/application.go +++ b/internal/config/application.go @@ -7,17 +7,20 @@ import ( "reflect" "strings" + "github.com/sirupsen/logrus" + "github.com/adrg/xdg" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" "github.com/mitchellh/go-homedir" - "github.com/sirupsen/logrus" "github.com/spf13/viper" "gopkg.in/yaml.v2" ) -var ErrApplicationConfigNotFound = fmt.Errorf("application config not found") - -var catalogerEnabledDefault = false +var ( + ErrApplicationConfigNotFound = fmt.Errorf("application config not found") + catalogerEnabledDefault = false +) type defaultValueLoader interface { loadDefaultValues(*viper.Viper) @@ -29,13 +32,15 @@ type parser interface { // Application is the main syft application configuration. type Application struct { - ConfigPath string `yaml:",omitempty" json:"configPath"` // the location where the application config was read from (either from -c or discovered while loading) + // the location where the application config was read from (either from -c or discovered while loading); default .syft.yaml + ConfigPath string `yaml:"configPath,omitempty" json:"configPath" mapstructure:"config"` + Verbosity uint `yaml:"verbosity,omitempty" json:"verbosity" mapstructure:"verbosity"` + // -q, indicates to not show any status output to stderr (ETUI or logging UI) + Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"` Outputs []string `yaml:"output" json:"output" mapstructure:"output"` // -o, the format to use for output File string `yaml:"file" json:"file" mapstructure:"file"` // --file, the file to write report output to - Quiet bool `yaml:"quiet" json:"quiet" mapstructure:"quiet"` // -q, indicates to not show any status output to stderr (ETUI or logging UI) CheckForAppUpdate bool `yaml:"check-for-app-update" json:"check-for-app-update" mapstructure:"check-for-app-update"` // whether to check for an application update on start up or not Anchore anchore `yaml:"anchore" json:"anchore" mapstructure:"anchore"` // options for interacting with Anchore Engine/Enterprise - CliOptions CliOnlyOptions `yaml:"-" json:"-"` // all options only available through the CLI (not via env vars or config) Dev development `yaml:"dev" json:"dev" mapstructure:"dev"` Log logging `yaml:"log" json:"log" mapstructure:"log"` // all logging-related options Package pkg `yaml:"package" json:"package" mapstructure:"package"` @@ -49,54 +54,34 @@ type Application struct { Platform string `yaml:"platform" json:"platform" mapstructure:"platform"` } -// PowerUserCatalogerEnabledDefault switches all catalogers to be enabled when running power-user command -func PowerUserCatalogerEnabledDefault() { - catalogerEnabledDefault = true -} +func (cfg *Application) LoadAllValues(v *viper.Viper, configPath string) error { + // priority order: viper.Set, flag, env, config, kv, defaults + // flags have already been loaded into viper by command construction -func newApplicationConfig(v *viper.Viper, cliOpts CliOnlyOptions) *Application { - config := &Application{ - CliOptions: cliOpts, + // check if user specified config; otherwise read all possible paths + if err := loadConfig(v, configPath); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Not Found; ignore this error + log.Debug("no config file found; proceeding with defaults") + } } - config.loadDefaultValues(v) - return config -} - -// LoadApplicationConfig populates the given viper object with application configuration discovered on disk -func LoadApplicationConfig(v *viper.Viper, cliOpts CliOnlyOptions) (*Application, error) { - // the user may not have a config, and this is OK, we can use the default config + default cobra cli values instead - config := newApplicationConfig(v, cliOpts) - if err := readConfig(v, cliOpts.ConfigPath); err != nil && !errors.Is(err, ErrApplicationConfigNotFound) { - return nil, err - } + // load default config values into viper + loadDefaultValues(v) - if err := v.Unmarshal(config); err != nil { - return nil, fmt.Errorf("unable to parse config: %w", err) - } - config.ConfigPath = v.ConfigFileUsed() + // load environment variables + v.SetEnvPrefix(internal.ApplicationName) + v.AllowEmptyEnv(true) + v.AutomaticEnv() - if err := config.parseConfigValues(); err != nil { - return nil, fmt.Errorf("invalid application config: %w", err) + // unmarshal fully populated viper object onto config + err := v.Unmarshal(cfg) + if err != nil { + return err } - return config, nil -} - -// init loads the default configuration values into the viper instance (before the config values are read and parsed). -func (cfg Application) loadDefaultValues(v *viper.Viper) { - // set the default values for primitive fields in this struct - v.SetDefault("check-for-app-update", true) - - // for each field in the configuration struct, see if the field implements the defaultValueLoader interface and invoke it if it does - value := reflect.ValueOf(cfg) - for i := 0; i < value.NumField(); i++ { - // note: the defaultValueLoader method receiver is NOT a pointer receiver. - if loadable, ok := value.Field(i).Interface().(defaultValueLoader); ok { - // the field implements defaultValueLoader, call it - loadable.loadDefaultValues(v) - } - } + // Convert all populated config options to their internal application values ex: scope string => scopeOpt source.Scope + return cfg.parseConfigValues() } func (cfg *Application) parseConfigValues() error { @@ -110,7 +95,6 @@ func (cfg *Application) parseConfigValues() error { return err } } - // parse nested config options // for each field in the configuration struct, see if the field implements the parser interface // note: the app config is a pointer, so we need to grab the elements explicitly (to traverse the address) @@ -127,17 +111,6 @@ func (cfg *Application) parseConfigValues() error { return nil } -func (cfg *Application) parseFile() error { - if cfg.File != "" { - expandedPath, err := homedir.Expand(cfg.File) - if err != nil { - return fmt.Errorf("unable to expand file path=%q: %w", cfg.File, err) - } - cfg.File = expandedPath - } - return nil -} - func (cfg *Application) parseUploadOptions() error { if cfg.Anchore.Host == "" && cfg.Anchore.Dockerfile != "" { return fmt.Errorf("cannot provide dockerfile option without enabling upload") @@ -152,11 +125,17 @@ func (cfg *Application) parseLogLevelOption() error { // we should be able to quiet the console logging and leave file logging alone... // ... this will be an enhancement for later cfg.Log.LevelOpt = logrus.PanicLevel - case cfg.Log.Level != "": - if cfg.CliOptions.Verbosity > 0 { - return fmt.Errorf("cannot explicitly set log level (cfg file or env var) and use -v flag together") - } + case cfg.Verbosity > 0: + switch v := cfg.Verbosity; { + case v == 1: + cfg.Log.LevelOpt = logrus.InfoLevel + case v >= 2: + cfg.Log.LevelOpt = logrus.DebugLevel + default: + cfg.Log.LevelOpt = logrus.ErrorLevel + } + case cfg.Log.Level != "": lvl, err := logrus.ParseLevel(strings.ToLower(cfg.Log.Level)) if err != nil { return fmt.Errorf("bad log level configured (%q): %w", cfg.Log.Level, err) @@ -164,18 +143,10 @@ func (cfg *Application) parseLogLevelOption() error { cfg.Log.LevelOpt = lvl if cfg.Log.LevelOpt >= logrus.InfoLevel { - cfg.CliOptions.Verbosity = 1 + cfg.Verbosity = 1 } default: - - switch v := cfg.CliOptions.Verbosity; { - case v == 1: - cfg.Log.LevelOpt = logrus.InfoLevel - case v >= 2: - cfg.Log.LevelOpt = logrus.DebugLevel - default: - cfg.Log.LevelOpt = logrus.ErrorLevel - } + cfg.Log.LevelOpt = logrus.InfoLevel } if cfg.Log.Level == "" { @@ -185,43 +156,64 @@ func (cfg *Application) parseLogLevelOption() error { return nil } +func (cfg *Application) parseFile() error { + if cfg.File != "" { + expandedPath, err := homedir.Expand(cfg.File) + if err != nil { + return fmt.Errorf("unable to expand file path=%q: %w", cfg.File, err) + } + cfg.File = expandedPath + } + return nil +} + +// init loads the default configuration values into the viper instance (before the config values are read and parsed). +func loadDefaultValues(v *viper.Viper) { + // set the default values for primitive fields in this struct + v.SetDefault("quiet", false) + v.SetDefault("check-for-app-update", true) + + // for each field in the configuration struct, see if the field implements the defaultValueLoader interface and invoke it if it does + value := reflect.ValueOf(Application{}) + for i := 0; i < value.NumField(); i++ { + // note: the defaultValueLoader method receiver is NOT a pointer receiver. + if loadable, ok := value.Field(i).Interface().(defaultValueLoader); ok { + // the field implements defaultValueLoader, call it + loadable.loadDefaultValues(v) + } + } +} + func (cfg Application) String() string { // yaml is pretty human friendly (at least when compared to json) - appCfgStr, err := yaml.Marshal(&cfg) + appaStr, err := yaml.Marshal(&cfg) if err != nil { return err.Error() } - return string(appCfgStr) + return string(appaStr) } -// readConfig attempts to read the given config path from disk or discover an alternate store location -// nolint:funlen -func readConfig(v *viper.Viper, configPath string) error { +func loadConfig(v *viper.Viper, configPath string) error { var err error - v.AutomaticEnv() - v.SetEnvPrefix(internal.ApplicationName) - // allow for nested options to be specified via environment variables - // e.g. pod.context = APPNAME_POD_CONTEXT - v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) - // use explicitly the given user config if configPath != "" { v.SetConfigFile(configPath) if err := v.ReadInConfig(); err != nil { return fmt.Errorf("unable to read application config=%q : %w", configPath, err) } + v.Set("config", v.ConfigFileUsed()) // don't fall through to other options if the config path was explicitly provided return nil } // start searching for valid configs in order... - // 1. look for ..yaml (in the current directory) v.AddConfigPath(".") v.SetConfigName("." + internal.ApplicationName) if err = v.ReadInConfig(); err == nil { + v.Set("config", v.ConfigFileUsed()) return nil } else if !errors.As(err, &viper.ConfigFileNotFoundError{}) { return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err) @@ -231,6 +223,7 @@ func readConfig(v *viper.Viper, configPath string) error { v.AddConfigPath("." + internal.ApplicationName) v.SetConfigName("config") if err = v.ReadInConfig(); err == nil { + v.Set("config", v.ConfigFileUsed()) return nil } else if !errors.As(err, &viper.ConfigFileNotFoundError{}) { return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err) @@ -242,6 +235,7 @@ func readConfig(v *viper.Viper, configPath string) error { v.AddConfigPath(home) v.SetConfigName("." + internal.ApplicationName) if err = v.ReadInConfig(); err == nil { + v.Set("config", v.ConfigFileUsed()) return nil } else if !errors.As(err, &viper.ConfigFileNotFoundError{}) { return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err) @@ -255,10 +249,10 @@ func readConfig(v *viper.Viper, configPath string) error { } v.SetConfigName("config") if err = v.ReadInConfig(); err == nil { + v.Set("config", v.ConfigFileUsed()) return nil } else if !errors.As(err, &viper.ConfigFileNotFoundError{}) { return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err) } - - return ErrApplicationConfigNotFound + return nil } diff --git a/internal/config/application_test.go b/internal/config/application_test.go deleted file mode 100644 index cad03c33695..00000000000 --- a/internal/config/application_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package config - -import ( - "github.com/docker/docker/pkg/homedir" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "path/filepath" - "testing" -) - -func TestApplication_parseFile(t *testing.T) { - tests := []struct { - name string - config Application - expected string - wantErr require.ErrorAssertionFunc - }{ - { - name: "expand home dir", - config: Application{ - File: "~/place.txt", - }, - expected: filepath.Join(homedir.Get(), "place.txt"), - }, - { - name: "passthrough other paths", - config: Application{ - File: "/other/place.txt", - }, - expected: "/other/place.txt", - }, - { - name: "no path", - config: Application{ - File: "", - }, - expected: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cfg := tt.config - - if tt.wantErr == nil { - tt.wantErr = require.NoError - } - - tt.wantErr(t, cfg.parseFile()) - assert.Equal(t, tt.expected, cfg.File) - }) - } -} diff --git a/internal/config/cli_only_options.go b/internal/config/cli_only_options.go deleted file mode 100644 index 5ece4d7eb68..00000000000 --- a/internal/config/cli_only_options.go +++ /dev/null @@ -1,7 +0,0 @@ -package config - -// CliOnlyOptions are options that are in the application config in memory, but are only exposed via CLI switches (not from unmarshaling a config file) -type CliOnlyOptions struct { - ConfigPath string // -c. where the read config is on disk - Verbosity int // -v or -vv , controlling which UI (ETUI vs logging) and what the log level should be -} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 00000000000..d912156bec0 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1 @@ +package config diff --git a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden index fb675caf785..eb2488f3169 100644 --- a/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden +++ b/internal/formats/spdx22tagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.2 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: . -DocumentNamespace: https://anchore.com/syft/dir/e69056a9-935e-4f00-b85f-9467f5d99a92 +DocumentNamespace: https://anchore.com/syft/dir/644e30b7-5a31-4d0b-a903-b96c757921c2 LicenseListVersion: 3.16 Creator: Organization: Anchore, Inc Creator: Tool: syft-[not provided] -Created: 2022-04-13T16:38:03Z +Created: 2022-04-19T15:10:19Z ##### Package: @at-sign diff --git a/main.go b/main.go deleted file mode 100644 index df0522d5bb1..00000000000 --- a/main.go +++ /dev/null @@ -1,14 +0,0 @@ -/* -Syft is a CLI tool and go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. - -Note that Syft is both a command line tool as well as a library. See the syft/ child package for library functionality. -*/ -package main - -import ( - "github.com/anchore/syft/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/schema/cyclonedx/Makefile b/schema/cyclonedx/Makefile index 3831cad2eb4..8b10c792eca 100644 --- a/schema/cyclonedx/Makefile +++ b/schema/cyclonedx/Makefile @@ -1,7 +1,7 @@ .DEFAULT_GOAL := validate-schema .PHONY: validate-schema validate-schema: - go run ../../main.go ubuntu:latest -vv -o cyclonedx > bom.xml + go run ../../cmd/syft/main.go ubuntu:latest -vv -o cyclonedx > bom.xml xmllint --noout --schema ./cyclonedx.xsd bom.xml - go run ../../main.go ubuntu:latest -vv -o cyclonedx-json > bom.json + go run ../../cmd/syft/main.go ubuntu:latest -vv -o cyclonedx-json > bom.json ../../.tmp/yajsv -s cyclonedx.json bom.json diff --git a/test/cli/power_user_cmd_test.go b/test/cli/power_user_cmd_test.go index 393e28e051d..95e698cb1f5 100644 --- a/test/cli/power_user_cmd_test.go +++ b/test/cli/power_user_cmd_test.go @@ -21,13 +21,6 @@ func TestPowerUserCmdFlags(t *testing.T) { assertFailingReturnCode, }, }, - { - name: "json-output-flag-fails", - args: []string{"power-user", "-o", "json", "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")}, - assertions: []traitAssertion{ - assertFailingReturnCode, - }, - }, { name: "default-results-w-pkg-coverage", args: []string{"power-user", "docker-archive:" + getFixtureImage(t, "image-pkg-coverage")}, From 7d8ea39ee56cd12a12ddfbd809b259cbd351de61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6berl?= Date: Thu, 28 Apr 2022 16:42:12 +0200 Subject: [PATCH 28/31] update to cyclonedx-go 0.5.2 (#971) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 960b960f919..89ae61bd194 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/anchore/syft go 1.18 require ( - github.com/CycloneDX/cyclonedx-go v0.5.0 + github.com/CycloneDX/cyclonedx-go v0.5.2 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acobaugh/osrelease v0.1.0 github.com/adrg/xdg v0.2.1 diff --git a/go.sum b/go.sum index bd8b60de4eb..462981be2c3 100644 --- a/go.sum +++ b/go.sum @@ -180,8 +180,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.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.5.0 h1:RWCnu2OrWUTF5C9DA3L0qVziUD2HlxSUWcL2OXlxfqE= -github.com/CycloneDX/cyclonedx-go v0.5.0/go.mod h1:nQXAzrejxO39b14JFz2SvsUElegYfwBDowIzqjdUMk4= +github.com/CycloneDX/cyclonedx-go v0.5.2 h1:CkdGw2R/tZWmEbSypJVZG+3+2SAsDjJirfIrG/RbIVg= +github.com/CycloneDX/cyclonedx-go v0.5.2/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= From 36973021fad57baf443ffa88181394b87ce109a0 Mon Sep 17 00:00:00 2001 From: Sambhav Kothari Date: Fri, 29 Apr 2022 16:18:45 +0100 Subject: [PATCH 29/31] Rename syft-id to package-id (#970) Co-authored-by: Christopher Phillips --- Makefile | 2 +- internal/formats/common/cyclonedxhelpers/component.go | 2 +- internal/formats/common/cyclonedxhelpers/component_test.go | 2 +- .../test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden | 2 +- .../test-fixtures/snapshot/TestCycloneDxImageEncoder.golden | 2 +- .../test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden | 2 +- .../test-fixtures/snapshot/TestCycloneDxImageEncoder.golden | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 77c6ee7ae94..5a4d2ab580f 100644 --- a/Makefile +++ b/Makefile @@ -305,7 +305,7 @@ cli: $(SNAPSHOTDIR) ## Run CLI tests chmod 755 "$(SNAPSHOT_BIN)" $(SNAPSHOT_BIN) version SYFT_BINARY_LOCATION='$(SNAPSHOT_BIN)' \ - go test -count=1 -v ./test/cli + go test -count=1 -timeout=15m -v ./test/cli .PHONY: changelog changelog: clean-changelog CHANGELOG.md diff --git a/internal/formats/common/cyclonedxhelpers/component.go b/internal/formats/common/cyclonedxhelpers/component.go index a0d185f5111..9fb598dc6d7 100644 --- a/internal/formats/common/cyclonedxhelpers/component.go +++ b/internal/formats/common/cyclonedxhelpers/component.go @@ -50,7 +50,7 @@ func deriveBomRef(p pkg.Package) string { // TODO: In the future we may want to dedupe by PURL and combine components with // the same PURL while preserving their unique metadata. if parsedPURL, err := packageurl.FromString(p.PURL); err == nil { - parsedPURL.Qualifiers = append(parsedPURL.Qualifiers, packageurl.Qualifier{Key: "syft-id", Value: string(p.ID())}) + parsedPURL.Qualifiers = append(parsedPURL.Qualifiers, packageurl.Qualifier{Key: "package-id", Value: string(p.ID())}) return parsedPURL.ToString() } // fallback is to use strictly the ID if there is no valid pURL diff --git a/internal/formats/common/cyclonedxhelpers/component_test.go b/internal/formats/common/cyclonedxhelpers/component_test.go index 586d7c89d2a..f38fe2bc8d3 100644 --- a/internal/formats/common/cyclonedxhelpers/component_test.go +++ b/internal/formats/common/cyclonedxhelpers/component_test.go @@ -171,7 +171,7 @@ func Test_deriveBomRef(t *testing.T) { { name: "use pURL-id hybrid", pkg: pkgWithPurl, - want: fmt.Sprintf("pkg:pypi/django@1.11.1?syft-id=%s", pkgWithPurl.ID()), + want: fmt.Sprintf("pkg:pypi/django@1.11.1?package-id=%s", pkgWithPurl.ID()), }, { name: "fallback to ID when pURL is invalid", diff --git a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index 69b562d973e..1e78b418b49 100644 --- a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -57,7 +57,7 @@ ] }, { - "bom-ref": "pkg:deb/debian/package-2@2.0.1?syft-id=ceda99598967ae8d", + "bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=ceda99598967ae8d", "type": "library", "name": "package-2", "version": "2.0.1", diff --git a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index 14478f6c8dd..315a418268c 100644 --- a/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/internal/formats/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -62,7 +62,7 @@ ] }, { - "bom-ref": "pkg:deb/debian/package-2@2.0.1?syft-id=ae77680e9b1d087e", + "bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=ae77680e9b1d087e", "type": "library", "name": "package-2", "version": "2.0.1", diff --git a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index b75e0c629dd..aa66e8ec0d0 100644 --- a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -32,7 +32,7 @@ /some/path/pkg1 - + package-2 2.0.1 cpe:2.3:*:some:package:2:*:*:*:*:*:*:* diff --git a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index a82e85c7f45..78caa7f7acb 100644 --- a/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/internal/formats/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -34,7 +34,7 @@ /somefile-1.txt - + package-2 2.0.1 cpe:2.3:*:some:package:2:*:*:*:*:*:*:* From 4ce2edda9eda4eda81b0459d77ef753a8b0bfa7f Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Mon, 2 May 2022 10:54:10 -0400 Subject: [PATCH 30/31] add version info and remove double config call (#977) --- cmd/syft/cli/attest.go | 3 --- cmd/syft/cli/commands.go | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/syft/cli/attest.go b/cmd/syft/cli/attest.go index e92e24d59ee..21bfe6b9362 100644 --- a/cmd/syft/cli/attest.go +++ b/cmd/syft/cli/attest.go @@ -49,9 +49,6 @@ func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions) *c RunE: func(cmd *cobra.Command, args []string) error { // this MUST be called first to make sure app config decodes // the viper object correctly - newLogWrapper(app) - logApplicationConfig(app) - if app.CheckForAppUpdate { checkForApplicationUpdate() } diff --git a/cmd/syft/cli/commands.go b/cmd/syft/cli/commands.go index c0f8bd39ca0..fff623d5826 100644 --- a/cmd/syft/cli/commands.go +++ b/cmd/syft/cli/commands.go @@ -123,6 +123,8 @@ func checkForApplicationUpdate() { } func logApplicationConfig(app *config.Application) { + versionInfo := version.FromBuild() + log.Infof("syft version: %+v", versionInfo.Version) log.Debugf("application config:\n%+v", color.Magenta.Sprint(app.String())) } From 0bd3558fb28045920b65047d1ec67519c767f5bc Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Mon, 2 May 2022 10:54:30 -0400 Subject: [PATCH 31/31] reduce noise of log output (#976) --- internal/config/application.go | 2 +- syft/source/directory_resolver.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/config/application.go b/internal/config/application.go index adb53fc2731..80573c72d69 100644 --- a/internal/config/application.go +++ b/internal/config/application.go @@ -146,7 +146,7 @@ func (cfg *Application) parseLogLevelOption() error { cfg.Verbosity = 1 } default: - cfg.Log.LevelOpt = logrus.InfoLevel + cfg.Log.LevelOpt = logrus.WarnLevel } if cfg.Log.Level == "" { diff --git a/syft/source/directory_resolver.go b/syft/source/directory_resolver.go index d3ffabc2217..be90dd82a26 100644 --- a/syft/source/directory_resolver.go +++ b/syft/source/directory_resolver.go @@ -338,7 +338,7 @@ func (r directoryResolver) FilesByPath(userPaths ...string) ([]Location, error) // we should be resolving symlinks and preserving this information as a VirtualPath to the real file evaluatedPath, err := filepath.EvalSymlinks(userStrPath) if err != nil { - log.Warnf("directory resolver unable to evaluate symlink for path=%q : %+v", userPath, err) + log.Debugf("directory resolver unable to evaluate symlink for path=%q : %+v", userPath, err) continue }