diff --git a/go.mod b/go.mod index faf9191661..e312d92190 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/aquasecurity/trivy go 1.13 require ( - github.com/aquasecurity/fanal v0.0.0-20200505074551-9239a362deca + github.com/aquasecurity/fanal v0.0.0-20200528202907-79693bf4a058 github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b github.com/aquasecurity/trivy-db v0.0.0-20200514134639-7e57e3e02470 github.com/caarlos0/env/v6 v6.0.0 diff --git a/go.sum b/go.sum index 28f996a14c..a422f2a1d6 100644 --- a/go.sum +++ b/go.sum @@ -40,10 +40,14 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aquasecurity/fanal v0.0.0-20200505074551-9239a362deca h1:xNs3bLA5k8hySXtV6S6oOc88zDxpL2gXo4Z2qPXmx4c= -github.com/aquasecurity/fanal v0.0.0-20200505074551-9239a362deca/go.mod h1:3H3F3x2XtcdFH3o1LQJEzfu2sS/rf+XufPIngMZrKO4= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/aquasecurity/fanal v0.0.0-20200528202907-79693bf4a058 h1:vNAuJrimb3eqXSFMhZJNf0PVHfzHFnCRMDuhVi7z2Ok= +github.com/aquasecurity/fanal v0.0.0-20200528202907-79693bf4a058/go.mod h1:omM/xBVqAPNzdV/MegrjayEkKEZzI+eUpyjCXpbTMG0= github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b h1:55Ulc/gvfWm4ylhVaR7MxOwujRjA6et7KhmUbSgUFf4= github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b/go.mod h1:BpNTD9vHfrejKsED9rx04ldM1WIbeyXGYxUrqTVwxVQ= github.com/aquasecurity/testdocker v0.0.0-20200426142840-5f05bce6f12a h1:hsw7PpiymXP64evn/K7gsj3hWzMqLrdoeE6JkqDocVg= @@ -54,6 +58,8 @@ github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:x github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ= github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU= github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -92,6 +98,7 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -127,18 +134,32 @@ github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhP github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= 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= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= +github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc= +github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= +github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg= +github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= @@ -230,6 +251,9 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= @@ -242,6 +266,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= +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= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -259,12 +285,12 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= @@ -292,6 +318,7 @@ github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1N github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -306,6 +333,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a h1:0LD5FJGQpEyD78OdhX97W75RjYmMjfLPp1ePrk5URxs= @@ -355,9 +384,13 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/saracen/walker v0.0.0-20191201085201-324a081bae7e h1:NO86zOn5ScSKW8wRbMaSIcjDZUFpWdCQQnexRqZ9h9A= +github.com/saracen/walker v0.0.0-20191201085201-324a081bae7e/go.mod h1:G0Z6yVPru183i2MuRJx1DcR4dgIZtLcTdaaE/pC1BJU= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8= @@ -371,6 +404,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sosedoff/gitkit v0.2.0 h1:cVre9QZvsDzS/v42PSOsf+GCaecvb/CWGX+diP232F8= +github.com/sosedoff/gitkit v0.2.0/go.mod h1:A+o6ZazfVJwetlcHz3ah6th66XcBdsyzLo+aBt/AsK4= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -406,6 +441,8 @@ github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -429,14 +466,16 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -469,8 +508,8 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c h1:SRpq/kuj/xNci/RdvEs+RSvpfxqvLAzTKuKGlzoGdZQ= -golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -479,8 +518,9 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ 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= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -490,6 +530,7 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -505,6 +546,7 @@ golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -537,6 +579,7 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191011211836-4c025a95b26e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200210192313-1ace956b0e17 h1:a/Fd23DJvg1CaeDH0dYHahE+hCI0v9rFgxSNIThoUcM= @@ -573,8 +616,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= @@ -592,6 +636,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/app.go b/internal/app.go index a1ab92b288..b6df6625e9 100644 --- a/internal/app.go +++ b/internal/app.go @@ -12,9 +12,9 @@ import ( "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/types" + "github.com/aquasecurity/trivy/internal/artifact" "github.com/aquasecurity/trivy/internal/client" "github.com/aquasecurity/trivy/internal/server" - "github.com/aquasecurity/trivy/internal/standalone" tdb "github.com/aquasecurity/trivy/pkg/db" "github.com/aquasecurity/trivy/pkg/utils" "github.com/aquasecurity/trivy/pkg/vulnerability" @@ -240,10 +240,12 @@ func NewApp(version string) *cli.App { app.Flags = flags app.Commands = []*cli.Command{ NewImageCommand(), + NewFilesystemCommand(), + NewRepositoryCommand(), NewClientCommand(), NewServerCommand(), } - app.Action = standalone.Run + app.Action = artifact.ImageRun return app } @@ -320,11 +322,65 @@ func NewImageCommand() *cli.Command { Name: "image", Aliases: []string{"i"}, Usage: "scan an image", - Action: standalone.Run, + Action: artifact.ImageRun, Flags: imageFlags, } } +func NewFilesystemCommand() *cli.Command { + return &cli.Command{ + Name: "filesystem", + Aliases: []string{"fs"}, + Usage: "scan local filesystem", + Action: artifact.FilesystemRun, + Flags: []cli.Flag{ + &templateFlag, + &formatFlag, + &inputFlag, + &severityFlag, + &outputFlag, + &exitCodeFlag, + &clearCacheFlag, + &quietFlag, + &ignoreUnfixedFlag, + &debugFlag, + &removedPkgsFlag, + &vulnTypeFlag, + &ignoreFileFlag, + &cacheDirFlag, + &timeoutFlag, + &noProgressFlag, + }, + } +} + +func NewRepositoryCommand() *cli.Command { + return &cli.Command{ + Name: "repository", + Aliases: []string{"repo"}, + Usage: "scan remote repository", + Action: artifact.RepositoryRun, + Flags: []cli.Flag{ + &templateFlag, + &formatFlag, + &inputFlag, + &severityFlag, + &outputFlag, + &exitCodeFlag, + &clearCacheFlag, + &quietFlag, + &ignoreUnfixedFlag, + &debugFlag, + &removedPkgsFlag, + &vulnTypeFlag, + &ignoreFileFlag, + &cacheDirFlag, + &timeoutFlag, + &noProgressFlag, + }, + } +} + func NewClientCommand() *cli.Command { return &cli.Command{ Name: "client", diff --git a/internal/standalone/config/config.go b/internal/artifact/config/config.go similarity index 72% rename from internal/standalone/config/config.go rename to internal/artifact/config/config.go index 7a46311b45..c9e1f64cc9 100644 --- a/internal/standalone/config/config.go +++ b/internal/artifact/config/config.go @@ -9,12 +9,11 @@ import ( type Config struct { config.GlobalConfig + config.ArtifactConfig config.DBConfig config.ImageConfig config.ReportConfig - NoProgress bool - // deprecated onlyUpdate string // deprecated @@ -30,12 +29,11 @@ func New(c *cli.Context) (Config, error) { } return Config{ - GlobalConfig: gc, - DBConfig: config.NewDBConfig(c), - ImageConfig: config.NewImageConfig(c), - ReportConfig: config.NewReportConfig(c), - - NoProgress: c.Bool("no-progress"), + GlobalConfig: gc, + ArtifactConfig: config.NewArtifactConfig(c), + DBConfig: config.NewDBConfig(c), + ImageConfig: config.NewImageConfig(c), + ReportConfig: config.NewReportConfig(c), onlyUpdate: c.String("only-update"), refresh: c.Bool("refresh"), @@ -43,7 +41,7 @@ func New(c *cli.Context) (Config, error) { }, nil } -func (c *Config) Init() error { +func (c *Config) Init(image bool) error { if err := c.ReportConfig.Init(c.Logger); err != nil { return err } @@ -59,10 +57,16 @@ func (c *Config) Init() error { return nil } - if err := c.ImageConfig.Init(c.Context.Args(), c.Logger); err != nil { + if err := c.ArtifactConfig.Init(c.Context.Args(), c.Logger); err != nil { cli.ShowAppHelp(c.Context) return err } + if image { + if err := c.ImageConfig.Init(c.Context.Args(), c.Logger); err != nil { + return err + } + } + return nil } diff --git a/internal/standalone/config/config_test.go b/internal/artifact/config/config_test.go similarity index 91% rename from internal/standalone/config/config_test.go rename to internal/artifact/config/config_test.go index f76b95e36b..fb962a063e 100644 --- a/internal/standalone/config/config_test.go +++ b/internal/artifact/config/config_test.go @@ -38,8 +38,8 @@ func TestConfig_Init(t *testing.T) { GlobalConfig: config.GlobalConfig{ Quiet: true, }, - ImageConfig: config.ImageConfig{ - ImageName: "alpine:3.10", + ArtifactConfig: config.ArtifactConfig{ + Target: "alpine:3.10", }, ReportConfig: config.ReportConfig{ Severities: []dbTypes.Severity{dbTypes.SeverityCritical}, @@ -74,8 +74,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "centos:7", + ArtifactConfig: config.ArtifactConfig{ + Target: "centos:7", }, }, }, @@ -91,8 +91,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "debian:buster", + ArtifactConfig: config.ArtifactConfig{ + Target: "debian:buster", }, onlyUpdate: "alpine", }, @@ -110,8 +110,8 @@ func TestConfig_Init(t *testing.T) { VulnType: []string{"os", "library"}, Template: "@contrib/gitlab.tpl", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, }, }, @@ -129,8 +129,8 @@ func TestConfig_Init(t *testing.T) { Template: "@contrib/gitlab.tpl", Format: "json", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, }, }, @@ -147,8 +147,8 @@ func TestConfig_Init(t *testing.T) { VulnType: []string{"os", "library"}, Format: "template", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, }, }, @@ -165,8 +165,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "gcr.io/distroless/base", + ArtifactConfig: config.ArtifactConfig{ + Target: "gcr.io/distroless/base", }, autoRefresh: true, }, @@ -180,7 +180,7 @@ func TestConfig_Init(t *testing.T) { name: "sad: multiple image names", args: []string{"centos:7", "alpine:3.10"}, logs: []string{ - "multiple images cannot be specified", + "multiple targets cannot be specified", }, wantErr: "arguments error", }, @@ -223,7 +223,7 @@ func TestConfig_Init(t *testing.T) { require.NoError(t, err, err) c.GlobalConfig.Logger = logger.Sugar() - err = c.Init() + err = c.Init(true) // tests log messages var gotMessages []string diff --git a/internal/artifact/fs.go b/internal/artifact/fs.go new file mode 100644 index 0000000000..f5efeba187 --- /dev/null +++ b/internal/artifact/fs.go @@ -0,0 +1,36 @@ +package artifact + +import ( + "context" + "time" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/aquasecurity/fanal/cache" + "github.com/aquasecurity/trivy/internal/artifact/config" + "github.com/aquasecurity/trivy/pkg/scanner" +) + +func filesystemScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) ( + scanner.Scanner, func(), error) { + s, cleanup, err := initializeFilesystemScanner(ctx, dir, ac, lac) + if err != nil { + return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err) + } + return s, cleanup, nil +} + +func FilesystemRun(cliCtx *cli.Context) error { + c, err := config.New(cliCtx) + if err != nil { + return err + } + + // initialize config + if err = c.Init(false); err != nil { + return xerrors.Errorf("failed to initialize options: %w", err) + } + + return run(c, filesystemScanner) +} diff --git a/internal/artifact/image.go b/internal/artifact/image.go new file mode 100644 index 0000000000..ddb8d5c748 --- /dev/null +++ b/internal/artifact/image.go @@ -0,0 +1,50 @@ +package artifact + +import ( + "context" + "time" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/aquasecurity/fanal/cache" + "github.com/aquasecurity/trivy/internal/artifact/config" + "github.com/aquasecurity/trivy/pkg/scanner" +) + +func archiveScanner(ctx context.Context, input string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) ( + scanner.Scanner, func(), error) { + s, err := initializeArchiveScanner(ctx, input, ac, lac, timeout) + if err != nil { + return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize the archive scanner: %w", err) + } + return s, func() {}, nil +} + +func dockerScanner(ctx context.Context, imageName string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) ( + scanner.Scanner, func(), error) { + s, cleanup, err := initializeDockerScanner(ctx, imageName, ac, lac, timeout) + if err != nil { + return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a docker scanner: %w", err) + } + return s, cleanup, nil +} + +func ImageRun(cliCtx *cli.Context) error { + c, err := config.New(cliCtx) + if err != nil { + return err + } + + // initialize config + if err = c.Init(true); err != nil { + return xerrors.Errorf("failed to initialize options: %w", err) + } + + if c.Input != "" { + // scan tar file + return run(c, archiveScanner) + } + + return run(c, dockerScanner) +} diff --git a/internal/standalone/inject.go b/internal/artifact/inject.go similarity index 50% rename from internal/standalone/inject.go rename to internal/artifact/inject.go index 89efbbe997..84de3085dc 100644 --- a/internal/standalone/inject.go +++ b/internal/artifact/inject.go @@ -1,6 +1,6 @@ // +build wireinject -package standalone +package artifact import ( "context" @@ -12,18 +12,28 @@ import ( "github.com/google/wire" ) -func initializeDockerScanner(ctx context.Context, imageName string, layerCache cache.ImageCache, localImageCache cache.LocalImageCache, +func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, func(), error) { wire.Build(scanner.StandaloneDockerSet) return scanner.Scanner{}, nil, nil } -func initializeArchiveScanner(ctx context.Context, filePath string, layerCache cache.ImageCache, localImageCache cache.LocalImageCache, +func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, error) { wire.Build(scanner.StandaloneArchiveSet) return scanner.Scanner{}, nil } +func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { + wire.Build(scanner.StandaloneFilesystemSet) + return scanner.Scanner{}, nil, nil +} + +func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { + wire.Build(scanner.StandaloneRepositorySet) + return scanner.Scanner{}, nil, nil +} + func initializeVulnerabilityClient() vulnerability.Client { wire.Build(vulnerability.SuperSet) return vulnerability.Client{} diff --git a/internal/artifact/repository.go b/internal/artifact/repository.go new file mode 100644 index 0000000000..55a677f1e6 --- /dev/null +++ b/internal/artifact/repository.go @@ -0,0 +1,36 @@ +package artifact + +import ( + "context" + "time" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/aquasecurity/fanal/cache" + "github.com/aquasecurity/trivy/internal/artifact/config" + "github.com/aquasecurity/trivy/pkg/scanner" +) + +func repositoryScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) ( + scanner.Scanner, func(), error) { + s, cleanup, err := initializeRepositoryScanner(ctx, dir, ac, lac) + if err != nil { + return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err) + } + return s, cleanup, nil +} + +func RepositoryRun(cliCtx *cli.Context) error { + c, err := config.New(cliCtx) + if err != nil { + return err + } + + // initialize config + if err = c.Init(false); err != nil { + return xerrors.Errorf("failed to initialize options: %w", err) + } + + return run(c, repositoryScanner) +} diff --git a/internal/standalone/run.go b/internal/artifact/run.go similarity index 67% rename from internal/standalone/run.go rename to internal/artifact/run.go index 2b3d1ab572..0d9718b380 100644 --- a/internal/standalone/run.go +++ b/internal/artifact/run.go @@ -1,17 +1,17 @@ -package standalone +package artifact import ( "context" l "log" "os" + "time" - "github.com/urfave/cli/v2" "golang.org/x/xerrors" "github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/trivy-db/pkg/db" + "github.com/aquasecurity/trivy/internal/artifact/config" "github.com/aquasecurity/trivy/internal/operation" - "github.com/aquasecurity/trivy/internal/standalone/config" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/report" "github.com/aquasecurity/trivy/pkg/scanner" @@ -19,24 +19,14 @@ import ( "github.com/aquasecurity/trivy/pkg/utils" ) -func Run(cliCtx *cli.Context) error { - c, err := config.New(cliCtx) - if err != nil { - return err - } - return run(c) -} +type InitializeScanner func(context.Context, string, cache.ArtifactCache, cache.LocalArtifactCache, time.Duration) ( + scanner.Scanner, func(), error) -func run(c config.Config) (err error) { - if err = log.InitLogger(c.Debug, c.Quiet); err != nil { +func run(c config.Config, initializeScanner InitializeScanner) error { + if err := log.InitLogger(c.Debug, c.Quiet); err != nil { l.Fatal(err) } - // initialize config - if err = c.Init(); err != nil { - return xerrors.Errorf("failed to initialize options: %w", err) - } - // configure cache dir utils.SetCacheDir(c.CacheDir) cacheClient, err := cache.NewFSCache(c.CacheDir) @@ -70,32 +60,25 @@ func run(c config.Config) (err error) { } defer db.Close() - var scanner scanner.Scanner - ctx := context.Background() - - cleanup := func() {} + target := c.Target if c.Input != "" { - // scan tar file - scanner, err = initializeArchiveScanner(ctx, c.Input, cacheClient, cacheClient, c.Timeout) - if err != nil { - return xerrors.Errorf("unable to initialize the archive scanner: %w", err) - } - } else { - // scan an image in Docker Engine or Docker Registry - scanner, cleanup, err = initializeDockerScanner(ctx, c.ImageName, cacheClient, cacheClient, c.Timeout) - if err != nil { - return xerrors.Errorf("unable to initialize the docker scanner: %w", err) - } + target = c.Input + } + + ctx := context.Background() + scanner, cleanup, err := initializeScanner(ctx, target, cacheClient, cacheClient, c.Timeout) + if err != nil { + return xerrors.Errorf("unable to initialize a scanner: %w", err) } defer cleanup() scanOptions := types.ScanOptions{ VulnType: c.VulnType, - ScanRemovedPackages: c.ScanRemovedPkgs, + ScanRemovedPackages: c.ScanRemovedPkgs, // this is valid only for image subcommand } log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType) - results, err := scanner.ScanImage(scanOptions) + results, err := scanner.ScanArtifact(ctx, scanOptions) if err != nil { return xerrors.Errorf("error in image scan: %w", err) } diff --git a/internal/artifact/wire_gen.go b/internal/artifact/wire_gen.go new file mode 100644 index 0000000000..477e405fac --- /dev/null +++ b/internal/artifact/wire_gen.go @@ -0,0 +1,96 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate wire +//+build !wireinject + +package artifact + +import ( + "context" + "github.com/aquasecurity/fanal/applier" + image2 "github.com/aquasecurity/fanal/artifact/image" + local2 "github.com/aquasecurity/fanal/artifact/local" + "github.com/aquasecurity/fanal/artifact/remote" + "github.com/aquasecurity/fanal/cache" + "github.com/aquasecurity/fanal/image" + "github.com/aquasecurity/trivy-db/pkg/db" + "github.com/aquasecurity/trivy/pkg/detector/library" + "github.com/aquasecurity/trivy/pkg/detector/ospkg" + "github.com/aquasecurity/trivy/pkg/scanner" + "github.com/aquasecurity/trivy/pkg/scanner/local" + "github.com/aquasecurity/trivy/pkg/types" + "github.com/aquasecurity/trivy/pkg/vulnerability" + "time" +) + +// Injectors from inject.go: + +func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, func(), error) { + applierApplier := applier.NewApplier(localArtifactCache) + detector := ospkg.Detector{} + driverFactory := library.DriverFactory{} + libraryDetector := library.NewDetector(driverFactory) + localScanner := local.NewScanner(applierApplier, detector, libraryDetector) + dockerOption, err := types.GetDockerOption(timeout) + if err != nil { + return scanner.Scanner{}, nil, err + } + imageImage, cleanup, err := image.NewDockerImage(ctx, imageName, dockerOption) + if err != nil { + return scanner.Scanner{}, nil, err + } + artifact := image2.NewArtifact(imageImage, artifactCache) + scannerScanner := scanner.NewScanner(localScanner, artifact) + return scannerScanner, func() { + cleanup() + }, nil +} + +func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, error) { + applierApplier := applier.NewApplier(localArtifactCache) + detector := ospkg.Detector{} + driverFactory := library.DriverFactory{} + libraryDetector := library.NewDetector(driverFactory) + localScanner := local.NewScanner(applierApplier, detector, libraryDetector) + imageImage, err := image.NewArchiveImage(filePath) + if err != nil { + return scanner.Scanner{}, err + } + artifact := image2.NewArtifact(imageImage, artifactCache) + scannerScanner := scanner.NewScanner(localScanner, artifact) + return scannerScanner, nil +} + +func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { + applierApplier := applier.NewApplier(localArtifactCache) + detector := ospkg.Detector{} + driverFactory := library.DriverFactory{} + libraryDetector := library.NewDetector(driverFactory) + localScanner := local.NewScanner(applierApplier, detector, libraryDetector) + artifact := local2.NewArtifact(dir, artifactCache) + scannerScanner := scanner.NewScanner(localScanner, artifact) + return scannerScanner, func() { + }, nil +} + +func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { + applierApplier := applier.NewApplier(localArtifactCache) + detector := ospkg.Detector{} + driverFactory := library.DriverFactory{} + libraryDetector := library.NewDetector(driverFactory) + localScanner := local.NewScanner(applierApplier, detector, libraryDetector) + artifact, cleanup, err := remote.NewArtifact(url, artifactCache) + if err != nil { + return scanner.Scanner{}, nil, err + } + scannerScanner := scanner.NewScanner(localScanner, artifact) + return scannerScanner, func() { + cleanup() + }, nil +} + +func initializeVulnerabilityClient() vulnerability.Client { + config := db.Config{} + client := vulnerability.NewClient(config) + return client +} diff --git a/internal/client/config/config.go b/internal/client/config/config.go index e8b37e97d3..6a58e73ff1 100644 --- a/internal/client/config/config.go +++ b/internal/client/config/config.go @@ -12,6 +12,7 @@ import ( type Config struct { config.GlobalConfig + config.ArtifactConfig config.ImageConfig config.ReportConfig @@ -31,14 +32,14 @@ func New(c *cli.Context) (Config, error) { } return Config{ - GlobalConfig: gc, - ImageConfig: config.NewImageConfig(c), - ReportConfig: config.NewReportConfig(c), - - RemoteAddr: c.String("remote"), - token: c.String("token"), - tokenHeader: c.String("token-header"), - customHeaders: c.StringSlice("custom-headers"), + GlobalConfig: gc, + ArtifactConfig: config.NewArtifactConfig(c), + ImageConfig: config.NewImageConfig(c), + ReportConfig: config.NewReportConfig(c), + RemoteAddr: c.String("remote"), + token: c.String("token"), + tokenHeader: c.String("token-header"), + customHeaders: c.StringSlice("custom-headers"), }, nil } @@ -59,6 +60,10 @@ func (c *Config) Init() (err error) { return err } + if err := c.ArtifactConfig.Init(c.Context.Args(), c.Logger); err != nil { + return err + } + if err := c.ImageConfig.Init(c.Context.Args(), c.Logger); err != nil { cli.ShowAppHelp(c.Context) return err diff --git a/internal/client/config/config_test.go b/internal/client/config/config_test.go index 3743a5ce23..e330fd0bfc 100644 --- a/internal/client/config/config_test.go +++ b/internal/client/config/config_test.go @@ -39,8 +39,8 @@ func TestConfig_Init(t *testing.T) { GlobalConfig: config.GlobalConfig{ Quiet: true, }, - ImageConfig: config.ImageConfig{ - ImageName: "alpine:3.10", + ArtifactConfig: config.ArtifactConfig{ + Target: "alpine:3.10", }, ReportConfig: config.ReportConfig{ Severities: []dbTypes.Severity{dbTypes.SeverityCritical}, @@ -59,8 +59,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "alpine:3.11", + ArtifactConfig: config.ArtifactConfig{ + Target: "alpine:3.11", }, token: "secret", tokenHeader: "X-Trivy-Token", @@ -78,8 +78,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "alpine:3.11", + ArtifactConfig: config.ArtifactConfig{ + Target: "alpine:3.11", }, customHeaders: []string{"foo:bar"}, CustomHeaders: http.Header{ @@ -96,8 +96,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "alpine:3.11", + ArtifactConfig: config.ArtifactConfig{ + Target: "alpine:3.11", }, customHeaders: []string{"foobaz"}, CustomHeaders: http.Header{}, @@ -115,8 +115,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "centos:7", + ArtifactConfig: config.ArtifactConfig{ + Target: "centos:7", }, CustomHeaders: http.Header{}, }, @@ -134,8 +134,8 @@ func TestConfig_Init(t *testing.T) { VulnType: []string{"os", "library"}, Template: "@contrib/gitlab.tpl", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, CustomHeaders: http.Header{}, }, @@ -154,8 +154,8 @@ func TestConfig_Init(t *testing.T) { Template: "@contrib/gitlab.tpl", Format: "json", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, CustomHeaders: http.Header{}, }, @@ -173,8 +173,27 @@ func TestConfig_Init(t *testing.T) { VulnType: []string{"os", "library"}, Format: "template", }, - ImageConfig: config.ImageConfig{ - ImageName: "gitlab/gitlab-ce:12.7.2-ce.0", + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", + }, + CustomHeaders: http.Header{}, + }, + }, + { + name: "invalid option combination: --format template without --template", + args: []string{"--format", "template", "--severity", "MEDIUM", "gitlab/gitlab-ce:12.7.2-ce.0"}, + logs: []string{ + "--format template is ignored because --template not is specified. Specify --template option when you use --format template.", + }, + want: Config{ + ReportConfig: config.ReportConfig{ + Severities: []dbTypes.Severity{dbTypes.SeverityMedium}, + Output: os.Stdout, + VulnType: []string{"os", "library"}, + Format: "template", + }, + ArtifactConfig: config.ArtifactConfig{ + Target: "gitlab/gitlab-ce:12.7.2-ce.0", }, CustomHeaders: http.Header{}, }, @@ -191,8 +210,8 @@ func TestConfig_Init(t *testing.T) { Output: os.Stdout, VulnType: []string{"os", "library"}, }, - ImageConfig: config.ImageConfig{ - ImageName: "gcr.io/distroless/base", + ArtifactConfig: config.ArtifactConfig{ + Target: "gcr.io/distroless/base", }, CustomHeaders: http.Header{}, }, @@ -201,7 +220,7 @@ func TestConfig_Init(t *testing.T) { name: "sad: multiple image names", args: []string{"centos:7", "alpine:3.10"}, logs: []string{ - "multiple images cannot be specified", + "multiple targets cannot be specified", }, wantErr: "arguments error", }, @@ -234,11 +253,7 @@ func TestConfig_Init(t *testing.T) { set.String("format", "", "") set.String("token", "", "") set.String("token-header", "", "") - //set.String("custom-headers", "", "") set.Var(&cli.StringSlice{}, "custom-headers", "") - //cli.StringSliceFlag{ - // Name: "custom-headers", - //} ctx := cli.NewContext(app, set, nil) _ = set.Parse(tt.args) diff --git a/internal/client/inject.go b/internal/client/inject.go index 1b09755df4..d948be1f54 100644 --- a/internal/client/inject.go +++ b/internal/client/inject.go @@ -13,13 +13,13 @@ import ( "github.com/google/wire" ) -func initializeDockerScanner(ctx context.Context, imageName string, layerCache cache.ImageCache, customHeaders client.CustomHeaders, +func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, func(), error) { wire.Build(scanner.RemoteDockerSet) return scanner.Scanner{}, nil, nil } -func initializeArchiveScanner(ctx context.Context, filePath string, layerCache cache.ImageCache, customHeaders client.CustomHeaders, +func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, error) { wire.Build(scanner.RemoteArchiveSet) return scanner.Scanner{}, nil diff --git a/internal/client/run.go b/internal/client/run.go index 5b211ff0d1..9c54271c45 100644 --- a/internal/client/run.go +++ b/internal/client/run.go @@ -58,7 +58,7 @@ func run(c config.Config) (err error) { } } else { // scan an image in Docker Engine or Docker Registry - scanner, cleanup, err = initializeDockerScanner(ctx, c.ImageName, remoteCache, + scanner, cleanup, err = initializeDockerScanner(ctx, c.Target, remoteCache, client.CustomHeaders(c.CustomHeaders), client.RemoteURL(c.RemoteAddr), c.Timeout) if err != nil { return xerrors.Errorf("unable to initialize the docker scanner: %w", err) @@ -72,7 +72,7 @@ func run(c config.Config) (err error) { } log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType) - results, err := scanner.ScanImage(scanOptions) + results, err := scanner.ScanArtifact(ctx, scanOptions) if err != nil { return xerrors.Errorf("error in image scan: %w", err) } diff --git a/internal/client/wire_gen.go b/internal/client/wire_gen.go index 834a3dc1d4..d5471842c7 100644 --- a/internal/client/wire_gen.go +++ b/internal/client/wire_gen.go @@ -7,9 +7,9 @@ package client import ( "context" - "github.com/aquasecurity/fanal/analyzer" + image2 "github.com/aquasecurity/fanal/artifact/image" "github.com/aquasecurity/fanal/cache" - "github.com/aquasecurity/fanal/extractor/docker" + "github.com/aquasecurity/fanal/image" "github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy/pkg/rpc/client" "github.com/aquasecurity/trivy/pkg/scanner" @@ -20,33 +20,33 @@ import ( // Injectors from inject.go: -func initializeDockerScanner(ctx context.Context, imageName string, layerCache cache.ImageCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, func(), error) { +func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, func(), error) { scannerScanner := client.NewProtobufClient(url) clientScanner := client.NewScanner(customHeaders, scannerScanner) dockerOption, err := types.GetDockerOption(timeout) if err != nil { return scanner.Scanner{}, nil, err } - extractor, cleanup, err := docker.NewDockerExtractor(ctx, imageName, dockerOption) + imageImage, cleanup, err := image.NewDockerImage(ctx, imageName, dockerOption) if err != nil { return scanner.Scanner{}, nil, err } - config := analyzer.New(extractor, layerCache) - scanner2 := scanner.NewScanner(clientScanner, config) + artifact := image2.NewArtifact(imageImage, artifactCache) + scanner2 := scanner.NewScanner(clientScanner, artifact) return scanner2, func() { cleanup() }, nil } -func initializeArchiveScanner(ctx context.Context, filePath string, layerCache cache.ImageCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, error) { +func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, customHeaders client.CustomHeaders, url client.RemoteURL, timeout time.Duration) (scanner.Scanner, error) { scannerScanner := client.NewProtobufClient(url) clientScanner := client.NewScanner(customHeaders, scannerScanner) - extractor, err := docker.NewArchiveImageExtractor(filePath) + imageImage, err := image.NewArchiveImage(filePath) if err != nil { return scanner.Scanner{}, err } - config := analyzer.New(extractor, layerCache) - scanner2 := scanner.NewScanner(clientScanner, config) + artifact := image2.NewArtifact(imageImage, artifactCache) + scanner2 := scanner.NewScanner(clientScanner, artifact) return scanner2, nil } diff --git a/internal/config/artifact.go b/internal/config/artifact.go new file mode 100644 index 0000000000..27a117b358 --- /dev/null +++ b/internal/config/artifact.go @@ -0,0 +1,42 @@ +package config + +import ( + "time" + + "github.com/urfave/cli/v2" + "go.uber.org/zap" + "golang.org/x/xerrors" +) + +type ArtifactConfig struct { + Input string + Timeout time.Duration + ClearCache bool + + // this field is populated in Init() + Target string +} + +func NewArtifactConfig(c *cli.Context) ArtifactConfig { + return ArtifactConfig{ + Input: c.String("input"), + Timeout: c.Duration("timeout"), + ClearCache: c.Bool("clear-cache"), + } +} + +func (c *ArtifactConfig) Init(args cli.Args, logger *zap.SugaredLogger) (err error) { + if c.Input == "" && args.Len() == 0 { + logger.Error(`trivy requires at least 1 argument or --input option`) + return xerrors.New("arguments error") + } else if args.Len() > 1 { + logger.Error(`multiple targets cannot be specified`) + return xerrors.New("arguments error") + } + + if c.Input == "" { + c.Target = args.First() + } + + return nil +} diff --git a/internal/config/artifact_test.go b/internal/config/artifact_test.go new file mode 100644 index 0000000000..43dcccd70f --- /dev/null +++ b/internal/config/artifact_test.go @@ -0,0 +1,80 @@ +package config_test + +import ( + "flag" + "testing" + + "github.com/aquasecurity/trivy/internal/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" +) + +func TestArtifactConfig_Init(t *testing.T) { + tests := []struct { + name string + args []string + logs []string + want config.ArtifactConfig + wantErr string + }{ + { + name: "happy path", + args: []string{"alpine:3.10"}, + want: config.ArtifactConfig{ + Target: "alpine:3.10", + }, + }, + { + name: "sad: multiple image names", + args: []string{"centos:7", "alpine:3.10"}, + logs: []string{ + "multiple targets cannot be specified", + }, + wantErr: "arguments error", + }, + { + name: "sad: no image name", + logs: []string{ + "trivy requires at least 1 argument or --input option", + }, + wantErr: "arguments error", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + core, obs := observer.New(zap.InfoLevel) + logger := zap.New(core) + + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ctx := cli.NewContext(app, set, nil) + _ = set.Parse(tt.args) + + c := config.NewArtifactConfig(ctx) + + err := c.Init(ctx.Args(), logger.Sugar()) + + // tests log messages + var gotMessages []string + for _, entry := range obs.AllUntimed() { + gotMessages = append(gotMessages, entry.Message) + } + assert.Equal(t, tt.logs, gotMessages, tt.name) + + // test the error + switch { + case tt.wantErr != "": + require.NotNil(t, err) + assert.Contains(t, err.Error(), tt.wantErr, tt.name) + return + default: + assert.NoError(t, err, tt.name) + } + + assert.Equal(t, tt.want, c, tt.name) + }) + } +} diff --git a/internal/config/db.go b/internal/config/db.go index d74d5dc8d2..a0a1783de3 100644 --- a/internal/config/db.go +++ b/internal/config/db.go @@ -10,6 +10,7 @@ type DBConfig struct { DownloadDBOnly bool SkipUpdate bool Light bool + NoProgress bool } func NewDBConfig(c *cli.Context) DBConfig { @@ -18,6 +19,7 @@ func NewDBConfig(c *cli.Context) DBConfig { DownloadDBOnly: c.Bool("download-db-only"), SkipUpdate: c.Bool("skip-update"), Light: c.Bool("light"), + NoProgress: c.Bool("no-progress"), } } diff --git a/internal/config/image.go b/internal/config/image.go index ff0bb73a8c..79cbb41851 100644 --- a/internal/config/image.go +++ b/internal/config/image.go @@ -1,8 +1,6 @@ package config import ( - "time" - "github.com/google/go-containerregistry/pkg/name" "github.com/urfave/cli/v2" "go.uber.org/zap" @@ -10,40 +8,21 @@ import ( ) type ImageConfig struct { - Input string ScanRemovedPkgs bool - Timeout time.Duration - ClearCache bool - - // this field is populated in Init() - ImageName string } func NewImageConfig(c *cli.Context) ImageConfig { return ImageConfig{ - Input: c.String("input"), ScanRemovedPkgs: c.Bool("removed-pkgs"), - Timeout: c.Duration("timeout"), - ClearCache: c.Bool("clear-cache"), } } func (c *ImageConfig) Init(args cli.Args, logger *zap.SugaredLogger) (err error) { - if c.Input == "" && args.Len() == 0 { - logger.Error(`trivy requires at least 1 argument or --input option`) - return xerrors.New("arguments error") - } else if args.Len() > 1 { - logger.Error(`multiple images cannot be specified`) - return xerrors.New("arguments error") - } - - if c.Input == "" { - c.ImageName = args.First() - } + imageName := args.First() // Check whether 'latest' tag is used - if c.ImageName != "" { - ref, err := name.ParseReference(c.ImageName) + if imageName != "" { + ref, err := name.ParseReference(imageName) if err != nil { return xerrors.Errorf("invalid image: %w", err) } diff --git a/internal/config/image_test.go b/internal/config/image_test.go index 409a8147ff..3663e9218f 100644 --- a/internal/config/image_test.go +++ b/internal/config/image_test.go @@ -13,51 +13,16 @@ import ( "github.com/aquasecurity/trivy/internal/config" ) -func TestNewImageConfig(t *testing.T) { - tests := []struct { - name string - args []string - want config.ImageConfig - }{ - { - name: "happy path", - args: []string{"--clear-cache", "--input", "/tmp/alpine.tar"}, - want: config.ImageConfig{ - Input: "/tmp/alpine.tar", - ClearCache: true, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - app := &cli.App{} - set := flag.NewFlagSet("test", 0) - set.Bool("clear-cache", false, "") - set.String("input", "", "") - - c := cli.NewContext(app, set, nil) - _ = set.Parse(tt.args) - - got := config.NewImageConfig(c) - assert.Equal(t, tt.want, got, tt.name) - }) - } -} - func TestImageConfig_Init(t *testing.T) { tests := []struct { name string args []string logs []string - want config.ImageConfig wantErr string }{ { name: "happy path", args: []string{"alpine:3.10"}, - want: config.ImageConfig{ - ImageName: "alpine:3.10", - }, }, { name: "with latest tag", @@ -65,24 +30,6 @@ func TestImageConfig_Init(t *testing.T) { logs: []string{ "You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed", }, - want: config.ImageConfig{ - ImageName: "gcr.io/distroless/base", - }, - }, - { - name: "sad: multiple image names", - args: []string{"centos:7", "alpine:3.10"}, - logs: []string{ - "multiple images cannot be specified", - }, - wantErr: "arguments error", - }, - { - name: "sad: no image name", - logs: []string{ - "trivy requires at least 1 argument or --input option", - }, - wantErr: "arguments error", }, { name: "sad: invalid image name", @@ -100,7 +47,7 @@ func TestImageConfig_Init(t *testing.T) { ctx := cli.NewContext(app, set, nil) _ = set.Parse(tt.args) - c := &config.ImageConfig{} + c := config.NewImageConfig(ctx) err := c.Init(ctx.Args(), logger.Sugar()) @@ -120,8 +67,6 @@ func TestImageConfig_Init(t *testing.T) { default: assert.NoError(t, err, tt.name) } - - assert.Equal(t, &tt.want, c, tt.name) }) } } diff --git a/internal/operation/operation.go b/internal/operation/operation.go index 6adab17dbe..4ea578c9cd 100644 --- a/internal/operation/operation.go +++ b/internal/operation/operation.go @@ -17,15 +17,15 @@ import ( var SuperSet = wire.NewSet( cache.NewFSCache, - wire.Bind(new(cache.LocalImageCache), new(cache.FSCache)), + wire.Bind(new(cache.LocalArtifactCache), new(cache.FSCache)), NewCache, ) type Cache struct { - client cache.LocalImageCache + client cache.LocalArtifactCache } -func NewCache(client cache.LocalImageCache) Cache { +func NewCache(client cache.LocalArtifactCache) Cache { return Cache{client: client} } diff --git a/internal/server/config/config_test.go b/internal/server/config/config_test.go index 19567d8f90..11d5f13b3c 100644 --- a/internal/server/config/config_test.go +++ b/internal/server/config/config_test.go @@ -28,6 +28,7 @@ func TestNew(t *testing.T) { DBConfig: config.DBConfig{ Reset: true, SkipUpdate: true, + NoProgress: true, }, Listen: "localhost:8080", }, diff --git a/internal/standalone/wire_gen.go b/internal/standalone/wire_gen.go deleted file mode 100644 index a533427bf9..0000000000 --- a/internal/standalone/wire_gen.go +++ /dev/null @@ -1,65 +0,0 @@ -// Code generated by Wire. DO NOT EDIT. - -//go:generate wire -//+build !wireinject - -package standalone - -import ( - "context" - "github.com/aquasecurity/fanal/analyzer" - "github.com/aquasecurity/fanal/cache" - "github.com/aquasecurity/fanal/extractor/docker" - "github.com/aquasecurity/trivy-db/pkg/db" - "github.com/aquasecurity/trivy/pkg/detector/library" - "github.com/aquasecurity/trivy/pkg/detector/ospkg" - "github.com/aquasecurity/trivy/pkg/scanner" - "github.com/aquasecurity/trivy/pkg/scanner/local" - "github.com/aquasecurity/trivy/pkg/types" - "github.com/aquasecurity/trivy/pkg/vulnerability" - "time" -) - -// Injectors from inject.go: - -func initializeDockerScanner(ctx context.Context, imageName string, layerCache cache.ImageCache, localImageCache cache.LocalImageCache, timeout time.Duration) (scanner.Scanner, func(), error) { - applier := analyzer.NewApplier(localImageCache) - detector := ospkg.Detector{} - driverFactory := library.DriverFactory{} - libraryDetector := library.NewDetector(driverFactory) - localScanner := local.NewScanner(applier, detector, libraryDetector) - dockerOption, err := types.GetDockerOption(timeout) - if err != nil { - return scanner.Scanner{}, nil, err - } - extractor, cleanup, err := docker.NewDockerExtractor(ctx, imageName, dockerOption) - if err != nil { - return scanner.Scanner{}, nil, err - } - config := analyzer.New(extractor, layerCache) - scannerScanner := scanner.NewScanner(localScanner, config) - return scannerScanner, func() { - cleanup() - }, nil -} - -func initializeArchiveScanner(ctx context.Context, filePath string, layerCache cache.ImageCache, localImageCache cache.LocalImageCache, timeout time.Duration) (scanner.Scanner, error) { - applier := analyzer.NewApplier(localImageCache) - detector := ospkg.Detector{} - driverFactory := library.DriverFactory{} - libraryDetector := library.NewDetector(driverFactory) - localScanner := local.NewScanner(applier, detector, libraryDetector) - extractor, err := docker.NewArchiveImageExtractor(filePath) - if err != nil { - return scanner.Scanner{}, err - } - config := analyzer.New(extractor, layerCache) - scannerScanner := scanner.NewScanner(localScanner, config) - return scannerScanner, nil -} - -func initializeVulnerabilityClient() vulnerability.Client { - config := db.Config{} - client := vulnerability.NewClient(config) - return client -} diff --git a/pkg/cache/remote.go b/pkg/cache/remote.go index 36d8abd5b8..65a966ef74 100644 --- a/pkg/cache/remote.go +++ b/pkg/cache/remote.go @@ -20,32 +20,32 @@ type RemoteCache struct { type RemoteURL string -func NewRemoteCache(url RemoteURL, customHeaders http.Header) cache.ImageCache { +func NewRemoteCache(url RemoteURL, customHeaders http.Header) cache.ArtifactCache { ctx := client.WithCustomHeaders(context.Background(), customHeaders) c := rpcCache.NewCacheProtobufClient(string(url), &http.Client{}) return &RemoteCache{ctx: ctx, client: c} } -func (c RemoteCache) PutImage(imageID string, imageInfo types.ImageInfo) error { - _, err := c.client.PutImage(c.ctx, rpc.ConvertToRpcImageInfo(imageID, imageInfo)) +func (c RemoteCache) PutArtifact(imageID string, imageInfo types.ArtifactInfo) error { + _, err := c.client.PutArtifact(c.ctx, rpc.ConvertToRpcArtifactInfo(imageID, imageInfo)) if err != nil { return xerrors.Errorf("unable to store cache on the server: %w", err) } return nil } -func (c RemoteCache) PutLayer(diffID string, layerInfo types.LayerInfo) error { - _, err := c.client.PutLayer(c.ctx, rpc.ConvertToRpcLayerInfo(diffID, layerInfo)) +func (c RemoteCache) PutBlob(diffID string, layerInfo types.BlobInfo) error { + _, err := c.client.PutBlob(c.ctx, rpc.ConvertToRpcBlobInfo(diffID, layerInfo)) if err != nil { return xerrors.Errorf("unable to store cache on the server: %w", err) } return nil } -func (c RemoteCache) MissingLayers(imageID string, layerIDs []string) (bool, []string, error) { - layers, err := c.client.MissingLayers(c.ctx, rpc.ConvertToMissingLayersRequest(imageID, layerIDs)) +func (c RemoteCache) MissingBlobs(imageID string, layerIDs []string) (bool, []string, error) { + layers, err := c.client.MissingBlobs(c.ctx, rpc.ConvertToMissingBlobsRequest(imageID, layerIDs)) if err != nil { return false, nil, xerrors.Errorf("unable to fetch missing layers: %w", err) } - return layers.MissingImage, layers.MissingLayerIds, nil + return layers.MissingArtifact, layers.MissingBlobIds, nil } diff --git a/pkg/cache/remote_test.go b/pkg/cache/remote_test.go index 42946dc281..28d41f1994 100644 --- a/pkg/cache/remote_test.go +++ b/pkg/cache/remote_test.go @@ -25,29 +25,29 @@ type mockCacheServer struct { cache fcache.Cache } -func (s *mockCacheServer) PutImage(_ context.Context, in *rpcCache.PutImageRequest) (*google_protobuf.Empty, error) { - if strings.Contains(in.ImageId, "invalid") { +func (s *mockCacheServer) PutArtifact(_ context.Context, in *rpcCache.PutArtifactRequest) (*google_protobuf.Empty, error) { + if strings.Contains(in.ArtifactId, "invalid") { return &google_protobuf.Empty{}, xerrors.New("invalid image ID") } return &google_protobuf.Empty{}, nil } -func (s *mockCacheServer) PutLayer(_ context.Context, in *rpcCache.PutLayerRequest) (*google_protobuf.Empty, error) { +func (s *mockCacheServer) PutBlob(_ context.Context, in *rpcCache.PutBlobRequest) (*google_protobuf.Empty, error) { if strings.Contains(in.DiffId, "invalid") { return &google_protobuf.Empty{}, xerrors.New("invalid layer ID") } return &google_protobuf.Empty{}, nil } -func (s *mockCacheServer) MissingLayers(_ context.Context, in *rpcCache.MissingLayersRequest) (*rpcCache.MissingLayersResponse, error) { +func (s *mockCacheServer) MissingBlobs(_ context.Context, in *rpcCache.MissingBlobsRequest) (*rpcCache.MissingBlobsResponse, error) { var layerIDs []string - for _, layerID := range in.LayerIds[:len(in.LayerIds)-1] { + for _, layerID := range in.BlobIds[:len(in.BlobIds)-1] { if strings.Contains(layerID, "invalid") { return nil, xerrors.New("invalid layer ID") } layerIDs = append(layerIDs, layerID) } - return &rpcCache.MissingLayersResponse{MissingImage: true, MissingLayerIds: layerIDs}, nil + return &rpcCache.MissingBlobsResponse{MissingArtifact: true, MissingBlobIds: layerIDs}, nil } func withToken(base http.Handler, token, tokenHeader string) http.Handler { @@ -60,7 +60,7 @@ func withToken(base http.Handler, token, tokenHeader string) http.Handler { }) } -func TestRemoteCache_PutImage(t *testing.T) { +func TestRemoteCache_PutArtifact(t *testing.T) { mux := http.NewServeMux() layerHandler := rpcCache.NewCacheServer(new(mockCacheServer), nil) mux.Handle(rpcCache.CachePathPrefix, withToken(layerHandler, "valid-token", "Trivy-Token")) @@ -68,7 +68,7 @@ func TestRemoteCache_PutImage(t *testing.T) { type args struct { imageID string - imageInfo types.ImageInfo + imageInfo types.ArtifactInfo customHeaders http.Header } tests := []struct { @@ -80,7 +80,7 @@ func TestRemoteCache_PutImage(t *testing.T) { name: "happy path", args: args{ imageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - imageInfo: types.ImageInfo{ + imageInfo: types.ArtifactInfo{ SchemaVersion: 1, Architecture: "amd64", Created: time.Time{}, @@ -102,7 +102,7 @@ func TestRemoteCache_PutImage(t *testing.T) { name: "sad path", args: args{ imageID: "sha256:invalid", - imageInfo: types.ImageInfo{ + imageInfo: types.ArtifactInfo{ SchemaVersion: 1, Architecture: "amd64", Created: time.Time{}, @@ -135,7 +135,7 @@ func TestRemoteCache_PutImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders) - err := c.PutImage(tt.args.imageID, tt.args.imageInfo) + err := c.PutArtifact(tt.args.imageID, tt.args.imageInfo) if tt.wantErr != "" { require.NotNil(t, err, tt.name) assert.Contains(t, err.Error(), tt.wantErr, tt.name) @@ -147,7 +147,7 @@ func TestRemoteCache_PutImage(t *testing.T) { } } -func TestRemoteCache_PutLayer(t *testing.T) { +func TestRemoteCache_PutBlob(t *testing.T) { mux := http.NewServeMux() layerHandler := rpcCache.NewCacheServer(new(mockCacheServer), nil) mux.Handle(rpcCache.CachePathPrefix, withToken(layerHandler, "valid-token", "Trivy-Token")) @@ -155,7 +155,7 @@ func TestRemoteCache_PutLayer(t *testing.T) { type args struct { diffID string - layerInfo types.LayerInfo + layerInfo types.BlobInfo customHeaders http.Header } tests := []struct { @@ -196,7 +196,7 @@ func TestRemoteCache_PutLayer(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders) - err := c.PutLayer(tt.args.diffID, tt.args.layerInfo) + err := c.PutBlob(tt.args.diffID, tt.args.layerInfo) if tt.wantErr != "" { require.NotNil(t, err, tt.name) assert.Contains(t, err.Error(), tt.wantErr, tt.name) @@ -208,7 +208,7 @@ func TestRemoteCache_PutLayer(t *testing.T) { } } -func TestRemoteCache_MissingLayers(t *testing.T) { +func TestRemoteCache_MissingBlobs(t *testing.T) { mux := http.NewServeMux() layerHandler := rpcCache.NewCacheServer(new(mockCacheServer), nil) mux.Handle(rpcCache.CachePathPrefix, withToken(layerHandler, "valid-token", "Trivy-Token")) @@ -274,7 +274,7 @@ func TestRemoteCache_MissingLayers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := cache.NewRemoteCache(cache.RemoteURL(ts.URL), tt.args.customHeaders) - gotMissingImage, gotMissingLayerIDs, err := c.MissingLayers(tt.args.imageID, tt.args.layerIDs) + gotMissingImage, gotMissingLayerIDs, err := c.MissingBlobs(tt.args.imageID, tt.args.layerIDs) if tt.wantErr != "" { require.NotNil(t, err, tt.name) assert.Contains(t, err.Error(), tt.wantErr, tt.name) diff --git a/pkg/rpc/client/client.go b/pkg/rpc/client/client.go index c8e7fa38a5..e7a03ddb80 100644 --- a/pkg/rpc/client/client.go +++ b/pkg/rpc/client/client.go @@ -45,9 +45,9 @@ func (s Scanner) Scan(target string, imageID string, layerIDs []string, options err := r.Retry(func() error { var err error res, err = s.client.Scan(ctx, &rpc.ScanRequest{ - Target: target, - ImageId: imageID, - LayerIds: layerIDs, + Target: target, + ArtifactId: imageID, + BlobIds: layerIDs, Options: &rpc.ScanOptions{ VulnType: options.VulnType, }, diff --git a/pkg/rpc/client/client_test.go b/pkg/rpc/client/client_test.go index 55e9056966..019e1552d6 100644 --- a/pkg/rpc/client/client_test.go +++ b/pkg/rpc/client/client_test.go @@ -124,9 +124,9 @@ func TestScanner_Scan(t *testing.T) { Args: scanArgs{ CtxAnything: true, Request: &scanner.ScanRequest{ - Target: "alpine:3.11", - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Target: "alpine:3.11", + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, Options: &scanner.ScanOptions{ VulnType: []string{"os"}, }, @@ -211,9 +211,9 @@ func TestScanner_Scan(t *testing.T) { Args: scanArgs{ CtxAnything: true, Request: &scanner.ScanRequest{ - Target: "alpine:3.11", - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Target: "alpine:3.11", + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, Options: &scanner.ScanOptions{ VulnType: []string{"os"}, }, diff --git a/pkg/rpc/convert.go b/pkg/rpc/convert.go index 7779f00145..649e6aa3d9 100644 --- a/pkg/rpc/convert.go +++ b/pkg/rpc/convert.go @@ -188,28 +188,28 @@ func ConvertFromRpcApplications(rpcApps []*common.Application) []ftypes.Applicat return apps } -func ConvertFromRpcPutImageRequest(req *cache.PutImageRequest) ftypes.ImageInfo { - created, _ := ptypes.Timestamp(req.ImageInfo.Created) - return ftypes.ImageInfo{ - SchemaVersion: int(req.ImageInfo.SchemaVersion), - Architecture: req.ImageInfo.Architecture, +func ConvertFromRpcPutArtifactRequest(req *cache.PutArtifactRequest) ftypes.ArtifactInfo { + created, _ := ptypes.Timestamp(req.ArtifactInfo.Created) + return ftypes.ArtifactInfo{ + SchemaVersion: int(req.ArtifactInfo.SchemaVersion), + Architecture: req.ArtifactInfo.Architecture, Created: created, - DockerVersion: req.ImageInfo.DockerVersion, - OS: req.ImageInfo.Os, - HistoryPackages: ConvertFromRpcPkgs(req.ImageInfo.HistoryPackages), + DockerVersion: req.ArtifactInfo.DockerVersion, + OS: req.ArtifactInfo.Os, + HistoryPackages: ConvertFromRpcPkgs(req.ArtifactInfo.HistoryPackages), } } -func ConvertFromRpcPutLayerRequest(req *cache.PutLayerRequest) ftypes.LayerInfo { - return ftypes.LayerInfo{ - SchemaVersion: int(req.LayerInfo.SchemaVersion), - Digest: req.LayerInfo.Digest, - DiffID: req.LayerInfo.DiffId, - OS: ConvertFromRpcOS(req.LayerInfo.Os), - PackageInfos: ConvertFromRpcPackageInfos(req.LayerInfo.PackageInfos), - Applications: ConvertFromRpcApplications(req.LayerInfo.Applications), - OpaqueDirs: req.LayerInfo.OpaqueDirs, - WhiteoutFiles: req.LayerInfo.WhiteoutFiles, +func ConvertFromRpcPutBlobRequest(req *cache.PutBlobRequest) ftypes.BlobInfo { + return ftypes.BlobInfo{ + SchemaVersion: int(req.BlobInfo.SchemaVersion), + Digest: req.BlobInfo.Digest, + DiffID: req.BlobInfo.DiffId, + OS: ConvertFromRpcOS(req.BlobInfo.Os), + PackageInfos: ConvertFromRpcPackageInfos(req.BlobInfo.PackageInfos), + Applications: ConvertFromRpcApplications(req.BlobInfo.Applications), + OpaqueDirs: req.BlobInfo.OpaqueDirs, + WhiteoutFiles: req.BlobInfo.WhiteoutFiles, } } @@ -223,15 +223,15 @@ func ConvertToRpcOS(fos *ftypes.OS) *common.OS { } } -func ConvertToRpcImageInfo(imageID string, imageInfo ftypes.ImageInfo) *cache.PutImageRequest { +func ConvertToRpcArtifactInfo(imageID string, imageInfo ftypes.ArtifactInfo) *cache.PutArtifactRequest { t, err := ptypes.TimestampProto(imageInfo.Created) if err != nil { log.Logger.Warnf("invalid timestamp: %s", err) } - return &cache.PutImageRequest{ - ImageId: imageID, - ImageInfo: &cache.ImageInfo{ + return &cache.PutArtifactRequest{ + ArtifactId: imageID, + ArtifactInfo: &cache.ArtifactInfo{ SchemaVersion: int32(imageInfo.SchemaVersion), Architecture: imageInfo.Architecture, Created: t, @@ -242,7 +242,7 @@ func ConvertToRpcImageInfo(imageID string, imageInfo ftypes.ImageInfo) *cache.Pu } } -func ConvertToRpcLayerInfo(diffID string, layerInfo ftypes.LayerInfo) *cache.PutLayerRequest { +func ConvertToRpcBlobInfo(diffID string, layerInfo ftypes.BlobInfo) *cache.PutBlobRequest { var packageInfos []*common.PackageInfo for _, pkgInfo := range layerInfo.PackageInfos { packageInfos = append(packageInfos, &common.PackageInfo{ @@ -268,10 +268,10 @@ func ConvertToRpcLayerInfo(diffID string, layerInfo ftypes.LayerInfo) *cache.Put }) } - return &cache.PutLayerRequest{ + return &cache.PutBlobRequest{ DiffId: diffID, - LayerInfo: &cache.LayerInfo{ - SchemaVersion: ftypes.LayerJSONSchemaVersion, + BlobInfo: &cache.BlobInfo{ + SchemaVersion: ftypes.BlobJSONSchemaVersion, Digest: layerInfo.Digest, DiffId: layerInfo.DiffID, Os: ConvertToRpcOS(layerInfo.OS), @@ -283,10 +283,10 @@ func ConvertToRpcLayerInfo(diffID string, layerInfo ftypes.LayerInfo) *cache.Put } } -func ConvertToMissingLayersRequest(imageID string, layerIDs []string) *cache.MissingLayersRequest { - return &cache.MissingLayersRequest{ - ImageId: imageID, - LayerIds: layerIDs, +func ConvertToMissingBlobsRequest(imageID string, layerIDs []string) *cache.MissingBlobsRequest { + return &cache.MissingBlobsRequest{ + ArtifactId: imageID, + BlobIds: layerIDs, } } diff --git a/pkg/rpc/server/inject.go b/pkg/rpc/server/inject.go index 36036098bf..b9dc81103d 100644 --- a/pkg/rpc/server/inject.go +++ b/pkg/rpc/server/inject.go @@ -9,7 +9,7 @@ import ( "github.com/google/wire" ) -func initializeScanServer(localLayerCache cache.LocalImageCache) *ScanServer { +func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServer { wire.Build(ScanSuperSet) return &ScanServer{} } diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index d6c42a9eec..4ed0773734 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -36,7 +36,7 @@ func NewScanServer(s scanner.Driver, vulnClient vulnerability.Operation) *ScanSe func (s *ScanServer) Scan(_ context.Context, in *rpcScanner.ScanRequest) (*rpcScanner.ScanResponse, error) { options := types.ScanOptions{VulnType: in.Options.VulnType} - results, os, eosl, err := s.localScanner.Scan(in.Target, in.ImageId, in.LayerIds, options) + results, os, eosl, err := s.localScanner.Scan(in.Target, in.ArtifactId, in.BlobIds, options) if err != nil { return nil, xerrors.Errorf("failed scan, %s: %w", in.Target, err) } @@ -55,40 +55,40 @@ func NewCacheServer(c cache.Cache) *CacheServer { return &CacheServer{cache: c} } -func (s *CacheServer) PutImage(_ context.Context, in *rpcCache.PutImageRequest) (*google_protobuf.Empty, error) { - if in.ImageInfo == nil { +func (s *CacheServer) PutArtifact(_ context.Context, in *rpcCache.PutArtifactRequest) (*google_protobuf.Empty, error) { + if in.ArtifactInfo == nil { return nil, xerrors.Errorf("empty image info") } - imageInfo := rpc.ConvertFromRpcPutImageRequest(in) - if err := s.cache.PutImage(in.ImageId, imageInfo); err != nil { + imageInfo := rpc.ConvertFromRpcPutArtifactRequest(in) + if err := s.cache.PutArtifact(in.ArtifactId, imageInfo); err != nil { return nil, xerrors.Errorf("unable to store image info in cache: %w", err) } return &google_protobuf.Empty{}, nil } -func (s *CacheServer) PutLayer(_ context.Context, in *rpcCache.PutLayerRequest) (*google_protobuf.Empty, error) { - if in.LayerInfo == nil { +func (s *CacheServer) PutBlob(_ context.Context, in *rpcCache.PutBlobRequest) (*google_protobuf.Empty, error) { + if in.BlobInfo == nil { return nil, xerrors.Errorf("empty layer info") } - layerInfo := rpc.ConvertFromRpcPutLayerRequest(in) - if err := s.cache.PutLayer(in.DiffId, layerInfo); err != nil { + layerInfo := rpc.ConvertFromRpcPutBlobRequest(in) + if err := s.cache.PutBlob(in.DiffId, layerInfo); err != nil { return nil, xerrors.Errorf("unable to store layer info in cache: %w", err) } return &google_protobuf.Empty{}, nil } -func (s *CacheServer) MissingLayers(_ context.Context, in *rpcCache.MissingLayersRequest) (*rpcCache.MissingLayersResponse, error) { +func (s *CacheServer) MissingBlobs(_ context.Context, in *rpcCache.MissingBlobsRequest) (*rpcCache.MissingBlobsResponse, error) { var layerIDs []string - for _, layerID := range in.LayerIds { - l, err := s.cache.GetLayer(layerID) - if err != nil || l.SchemaVersion != ftypes.LayerJSONSchemaVersion { - layerIDs = append(layerIDs, layerID) + for _, blobID := range in.BlobIds { + l, err := s.cache.GetBlob(blobID) + if err != nil || l.SchemaVersion != ftypes.BlobJSONSchemaVersion { + layerIDs = append(layerIDs, blobID) } } var missingImage bool - img, err := s.cache.GetImage(in.ImageId) - if err != nil || img.SchemaVersion != ftypes.ImageJSONSchemaVersion { + img, err := s.cache.GetArtifact(in.ArtifactId) + if err != nil || img.SchemaVersion != ftypes.ArtifactJSONSchemaVersion { missingImage = true } - return &rpcCache.MissingLayersResponse{MissingImage: missingImage, MissingLayerIds: layerIDs}, nil + return &rpcCache.MissingBlobsResponse{MissingArtifact: missingImage, MissingBlobIds: layerIDs}, nil } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index fbf2d7f418..7a0c7e398a 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -6,19 +6,16 @@ import ( "testing" "time" - deptypes "github.com/aquasecurity/go-dep-parser/pkg/types" - - "github.com/golang/protobuf/ptypes/timestamp" - "github.com/golang/protobuf/ptypes" - google_protobuf "github.com/golang/protobuf/ptypes/empty" + "github.com/golang/protobuf/ptypes/timestamp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/xerrors" "github.com/aquasecurity/fanal/cache" ftypes "github.com/aquasecurity/fanal/types" + deptypes "github.com/aquasecurity/go-dep-parser/pkg/types" dbTypes "github.com/aquasecurity/trivy-db/pkg/types" "github.com/aquasecurity/trivy/pkg/report" "github.com/aquasecurity/trivy/pkg/scanner" @@ -30,8 +27,8 @@ import ( ) type mockCache struct { - cache.MockImageCache - cache.MockLocalImageCache + cache.MockArtifactCache + cache.MockLocalArtifactCache } func TestScanServer_Scan(t *testing.T) { @@ -41,7 +38,7 @@ func TestScanServer_Scan(t *testing.T) { tests := []struct { name string args args - scanExpectation scanner.ScanExpectation + scanExpectation scanner.DriverScanExpectation fillInfoExpectation vulnerability.FillInfoExpectation want *rpcScanner.ScanResponse wantErr string @@ -50,19 +47,19 @@ func TestScanServer_Scan(t *testing.T) { name: "happy path", args: args{ in: &rpcScanner.ScanRequest{ - Target: "alpine:3.11", - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, - Options: &rpcScanner.ScanOptions{}, + Target: "alpine:3.11", + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Options: &rpcScanner.ScanOptions{}, }, }, - scanExpectation: scanner.ScanExpectation{ - Args: scanner.ScanArgs{ + scanExpectation: scanner.DriverScanExpectation{ + Args: scanner.DriverScanArgs{ Target: "alpine:3.11", ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, - Returns: scanner.ScanReturns{ + Returns: scanner.DriverScanReturns{ Results: report.Results{ { Target: "alpine:3.11 (alpine 3.11)", @@ -128,19 +125,19 @@ func TestScanServer_Scan(t *testing.T) { name: "sad path: Scan returns an error", args: args{ in: &rpcScanner.ScanRequest{ - Target: "alpine:3.11", - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, - Options: &rpcScanner.ScanOptions{}, + Target: "alpine:3.11", + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Options: &rpcScanner.ScanOptions{}, }, }, - scanExpectation: scanner.ScanExpectation{ - Args: scanner.ScanArgs{ + scanExpectation: scanner.DriverScanExpectation{ + Args: scanner.DriverScanArgs{ Target: "alpine:3.11", ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, - Returns: scanner.ScanReturns{ + Returns: scanner.DriverScanReturns{ Err: errors.New("error"), }, }, @@ -170,23 +167,23 @@ func TestScanServer_Scan(t *testing.T) { } } -func TestCacheServer_PutImage(t *testing.T) { +func TestCacheServer_PutArtifact(t *testing.T) { type args struct { - in *rpcCache.PutImageRequest + in *rpcCache.PutArtifactRequest } tests := []struct { name string args args - putImage cache.ImageCachePutImageExpectation + putImage cache.ArtifactCachePutArtifactExpectation want *google_protobuf.Empty wantErr string }{ { name: "happy path", args: args{ - in: &rpcCache.PutImageRequest{ - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - ImageInfo: &rpcCache.ImageInfo{ + in: &rpcCache.PutArtifactRequest{ + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + ArtifactInfo: &rpcCache.ArtifactInfo{ SchemaVersion: 1, Architecture: "amd64", Created: func() *timestamp.Timestamp { @@ -199,10 +196,10 @@ func TestCacheServer_PutImage(t *testing.T) { }, }, }, - putImage: cache.ImageCachePutImageExpectation{ - Args: cache.ImageCachePutImageArgs{ - ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - ImageInfo: ftypes.ImageInfo{ + putImage: cache.ArtifactCachePutArtifactExpectation{ + Args: cache.ArtifactCachePutArtifactArgs{ + ArtifactID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + ArtifactInfo: ftypes.ArtifactInfo{ SchemaVersion: 1, Architecture: "amd64", Created: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC), @@ -216,9 +213,9 @@ func TestCacheServer_PutImage(t *testing.T) { { name: "sad path", args: args{ - in: &rpcCache.PutImageRequest{ - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - ImageInfo: &rpcCache.ImageInfo{ + in: &rpcCache.PutArtifactRequest{ + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + ArtifactInfo: &rpcCache.ArtifactInfo{ SchemaVersion: 1, Created: func() *timestamp.Timestamp { d := time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC) @@ -228,15 +225,15 @@ func TestCacheServer_PutImage(t *testing.T) { }, }, }, - putImage: cache.ImageCachePutImageExpectation{ - Args: cache.ImageCachePutImageArgs{ - ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - ImageInfo: ftypes.ImageInfo{ + putImage: cache.ArtifactCachePutArtifactExpectation{ + Args: cache.ArtifactCachePutArtifactArgs{ + ArtifactID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + ArtifactInfo: ftypes.ArtifactInfo{ SchemaVersion: 1, Created: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC), }, }, - Returns: cache.ImageCachePutImageReturns{ + Returns: cache.ArtifactCachePutArtifactReturns{ Err: xerrors.New("error"), }, }, @@ -245,7 +242,7 @@ func TestCacheServer_PutImage(t *testing.T) { { name: "sad path: empty image info", args: args{ - in: &rpcCache.PutImageRequest{}, + in: &rpcCache.PutArtifactRequest{}, }, wantErr: "empty image info", }, @@ -253,10 +250,10 @@ func TestCacheServer_PutImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockCache := new(mockCache) - mockCache.ApplyPutImageExpectation(tt.putImage) + mockCache.ApplyPutArtifactExpectation(tt.putImage) s := NewCacheServer(mockCache) - got, err := s.PutImage(context.Background(), tt.args.in) + got, err := s.PutArtifact(context.Background(), tt.args.in) if tt.wantErr != "" { require.NotNil(t, err, tt.name) @@ -271,23 +268,23 @@ func TestCacheServer_PutImage(t *testing.T) { } } -func TestCacheServer_PutLayer(t *testing.T) { +func TestCacheServer_PutBlob(t *testing.T) { type args struct { - in *rpcCache.PutLayerRequest + in *rpcCache.PutBlobRequest } tests := []struct { name string args args - putLayer cache.ImageCachePutLayerExpectation + putLayer cache.ArtifactCachePutBlobExpectation want *google_protobuf.Empty wantErr string }{ { name: "happy path", args: args{ - in: &rpcCache.PutLayerRequest{ + in: &rpcCache.PutBlobRequest{ DiffId: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079", - LayerInfo: &rpcCache.LayerInfo{ + BlobInfo: &rpcCache.BlobInfo{ SchemaVersion: 1, Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812", DiffId: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079", @@ -345,10 +342,10 @@ func TestCacheServer_PutLayer(t *testing.T) { }, }, }, - putLayer: cache.ImageCachePutLayerExpectation{ - Args: cache.ImageCachePutLayerArgs{ - DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079", - LayerInfo: ftypes.LayerInfo{ + putLayer: cache.ArtifactCachePutBlobExpectation{ + Args: cache.ArtifactCachePutBlobArgs{ + BlobID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079", + BlobInfo: ftypes.BlobInfo{ SchemaVersion: 1, Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812", DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079", @@ -415,18 +412,18 @@ func TestCacheServer_PutLayer(t *testing.T) { { name: "sad path", args: args{ - in: &rpcCache.PutLayerRequest{ - LayerInfo: &rpcCache.LayerInfo{ + in: &rpcCache.PutBlobRequest{ + BlobInfo: &rpcCache.BlobInfo{ SchemaVersion: 1, }, }, }, - putLayer: cache.ImageCachePutLayerExpectation{ - Args: cache.ImageCachePutLayerArgs{ - DiffIDAnything: true, - LayerInfoAnything: true, + putLayer: cache.ArtifactCachePutBlobExpectation{ + Args: cache.ArtifactCachePutBlobArgs{ + BlobIDAnything: true, + BlobInfoAnything: true, }, - Returns: cache.ImageCachePutLayerReturns{ + Returns: cache.ArtifactCachePutBlobReturns{ Err: xerrors.New("error"), }, }, @@ -435,14 +432,14 @@ func TestCacheServer_PutLayer(t *testing.T) { { name: "sad path: empty layer info", args: args{ - in: &rpcCache.PutLayerRequest{}, + in: &rpcCache.PutBlobRequest{}, }, - putLayer: cache.ImageCachePutLayerExpectation{ - Args: cache.ImageCachePutLayerArgs{ - DiffIDAnything: true, - LayerInfoAnything: true, + putLayer: cache.ArtifactCachePutBlobExpectation{ + Args: cache.ArtifactCachePutBlobArgs{ + BlobIDAnything: true, + BlobInfoAnything: true, }, - Returns: cache.ImageCachePutLayerReturns{ + Returns: cache.ArtifactCachePutBlobReturns{ Err: xerrors.New("error"), }, }, @@ -452,10 +449,10 @@ func TestCacheServer_PutLayer(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockCache := new(mockCache) - mockCache.ApplyPutLayerExpectation(tt.putLayer) + mockCache.ApplyPutBlobExpectation(tt.putLayer) s := NewCacheServer(mockCache) - got, err := s.PutLayer(context.Background(), tt.args.in) + got, err := s.PutBlob(context.Background(), tt.args.in) if tt.wantErr != "" { require.NotNil(t, err, tt.name) @@ -470,113 +467,113 @@ func TestCacheServer_PutLayer(t *testing.T) { } } -func TestCacheServer_MissingLayers(t *testing.T) { +func TestCacheServer_MissingBlobs(t *testing.T) { type args struct { ctx context.Context - in *rpcCache.MissingLayersRequest + in *rpcCache.MissingBlobsRequest } tests := []struct { name string args args - getLayerExpectations []cache.LocalImageCacheGetLayerExpectation - getImageExpectations []cache.LocalImageCacheGetImageExpectation - want *rpcCache.MissingLayersResponse + getLayerExpectations []cache.LocalArtifactCacheGetBlobExpectation + getImageExpectations []cache.LocalArtifactCacheGetArtifactExpectation + want *rpcCache.MissingBlobsResponse wantErr string }{ { name: "happy path", args: args{ - in: &rpcCache.MissingLayersRequest{ - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{ + in: &rpcCache.MissingBlobsRequest{ + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{ "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", }, }, }, - getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{ + getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{ { - Args: cache.LocalImageCacheGetLayerArgs{ - DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + Args: cache.LocalArtifactCacheGetBlobArgs{ + BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", }, - Returns: cache.LocalImageCacheGetLayerReturns{ - LayerInfo: ftypes.LayerInfo{}, + Returns: cache.LocalArtifactCacheGetBlobReturns{ + BlobInfo: ftypes.BlobInfo{}, }, }, { - Args: cache.LocalImageCacheGetLayerArgs{ - DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", + Args: cache.LocalArtifactCacheGetBlobArgs{ + BlobID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", }, - Returns: cache.LocalImageCacheGetLayerReturns{ - LayerInfo: ftypes.LayerInfo{ + Returns: cache.LocalArtifactCacheGetBlobReturns{ + BlobInfo: ftypes.BlobInfo{ SchemaVersion: 1, }, }, }, }, - getImageExpectations: []cache.LocalImageCacheGetImageExpectation{ + getImageExpectations: []cache.LocalArtifactCacheGetArtifactExpectation{ { - Args: cache.LocalImageCacheGetImageArgs{ - ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + Args: cache.LocalArtifactCacheGetArtifactArgs{ + ArtifactID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", }, - Returns: cache.LocalImageCacheGetImageReturns{ - ImageInfo: ftypes.ImageInfo{ + Returns: cache.LocalArtifactCacheGetArtifactReturns{ + ArtifactInfo: ftypes.ArtifactInfo{ SchemaVersion: 1, }, }, }, }, - want: &rpcCache.MissingLayersResponse{ - MissingImage: false, - MissingLayerIds: []string{"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02"}, + want: &rpcCache.MissingBlobsResponse{ + MissingArtifact: false, + MissingBlobIds: []string{"sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02"}, }, }, { name: "schema version doesn't match", args: args{ - in: &rpcCache.MissingLayersRequest{ - ImageId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIds: []string{ + in: &rpcCache.MissingBlobsRequest{ + ArtifactId: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIds: []string{ "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", }, }, }, - getLayerExpectations: []cache.LocalImageCacheGetLayerExpectation{ + getLayerExpectations: []cache.LocalArtifactCacheGetBlobExpectation{ { - Args: cache.LocalImageCacheGetLayerArgs{ - DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", + Args: cache.LocalArtifactCacheGetBlobArgs{ + BlobID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", }, - Returns: cache.LocalImageCacheGetLayerReturns{ - LayerInfo: ftypes.LayerInfo{ + Returns: cache.LocalArtifactCacheGetBlobReturns{ + BlobInfo: ftypes.BlobInfo{ SchemaVersion: 0, }, }, }, { - Args: cache.LocalImageCacheGetLayerArgs{ - DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", + Args: cache.LocalArtifactCacheGetBlobArgs{ + BlobID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", }, - Returns: cache.LocalImageCacheGetLayerReturns{ - LayerInfo: ftypes.LayerInfo{ + Returns: cache.LocalArtifactCacheGetBlobReturns{ + BlobInfo: ftypes.BlobInfo{ SchemaVersion: -1, }, }, }, }, - getImageExpectations: []cache.LocalImageCacheGetImageExpectation{ + getImageExpectations: []cache.LocalArtifactCacheGetArtifactExpectation{ { - Args: cache.LocalImageCacheGetImageArgs{ - ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + Args: cache.LocalArtifactCacheGetArtifactArgs{ + ArtifactID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", }, - Returns: cache.LocalImageCacheGetImageReturns{ - ImageInfo: ftypes.ImageInfo{}, + Returns: cache.LocalArtifactCacheGetArtifactReturns{ + ArtifactInfo: ftypes.ArtifactInfo{}, }, }, }, - want: &rpcCache.MissingLayersResponse{ - MissingImage: true, - MissingLayerIds: []string{ + want: &rpcCache.MissingBlobsResponse{ + MissingArtifact: true, + MissingBlobIds: []string{ "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02", "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5", }, @@ -586,11 +583,11 @@ func TestCacheServer_MissingLayers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockCache := new(mockCache) - mockCache.ApplyGetLayerExpectations(tt.getLayerExpectations) - mockCache.ApplyGetImageExpectations(tt.getImageExpectations) + mockCache.ApplyGetBlobExpectations(tt.getLayerExpectations) + mockCache.ApplyGetArtifactExpectations(tt.getImageExpectations) s := NewCacheServer(mockCache) - got, err := s.MissingLayers(tt.args.ctx, tt.args.in) + got, err := s.MissingBlobs(tt.args.ctx, tt.args.in) if tt.wantErr != "" { require.NotNil(t, err, tt.name) assert.Contains(t, err.Error(), tt.wantErr, tt.name) @@ -600,7 +597,7 @@ func TestCacheServer_MissingLayers(t *testing.T) { } assert.Equal(t, tt.want, got) - mockCache.MockLocalImageCache.AssertExpectations(t) + mockCache.MockLocalArtifactCache.AssertExpectations(t) }) } } diff --git a/pkg/rpc/server/wire_gen.go b/pkg/rpc/server/wire_gen.go index 4133f02f8f..e2bbb98d02 100644 --- a/pkg/rpc/server/wire_gen.go +++ b/pkg/rpc/server/wire_gen.go @@ -6,7 +6,7 @@ package server import ( - "github.com/aquasecurity/fanal/analyzer" + "github.com/aquasecurity/fanal/applier" "github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/trivy-db/pkg/db" db2 "github.com/aquasecurity/trivy/pkg/db" @@ -24,12 +24,12 @@ import ( // Injectors from inject.go: -func initializeScanServer(localLayerCache cache.LocalImageCache) *ScanServer { - applier := analyzer.NewApplier(localLayerCache) +func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServer { + applierApplier := applier.NewApplier(localArtifactCache) detector := ospkg.Detector{} driverFactory := library.DriverFactory{} libraryDetector := library.NewDetector(driverFactory) - scanner := local.NewScanner(applier, detector, libraryDetector) + scanner := local.NewScanner(applierApplier, detector, libraryDetector) config := db.Config{} client := vulnerability.NewClient(config) scanServer := NewScanServer(scanner, client) diff --git a/pkg/scanner/local/mock_applier.go b/pkg/scanner/local/mock_applier.go index e5237d31ce..5b672fcfec 100644 --- a/pkg/scanner/local/mock_applier.go +++ b/pkg/scanner/local/mock_applier.go @@ -2,8 +2,10 @@ package local -import mock "github.com/stretchr/testify/mock" -import types "github.com/aquasecurity/fanal/types" +import ( + types "github.com/aquasecurity/fanal/types" + mock "github.com/stretchr/testify/mock" +) // MockApplier is an autogenerated mock type for the Applier type type MockApplier struct { @@ -11,14 +13,14 @@ type MockApplier struct { } type ApplierApplyLayersArgs struct { - ImageID string - ImageIDAnything bool - LayerIDs []string - LayerIDsAnything bool + ArtifactID string + ArtifactIDAnything bool + BlobIDs []string + BlobIDsAnything bool } type ApplierApplyLayersReturns struct { - Detail types.ImageDetail + Detail types.ArtifactDetail Err error } @@ -29,15 +31,15 @@ type ApplierApplyLayersExpectation struct { func (_m *MockApplier) ApplyApplyLayersExpectation(e ApplierApplyLayersExpectation) { var args []interface{} - if e.Args.ImageIDAnything { + if e.Args.ArtifactIDAnything { args = append(args, mock.Anything) } else { - args = append(args, e.Args.ImageID) + args = append(args, e.Args.ArtifactID) } - if e.Args.LayerIDsAnything { + if e.Args.BlobIDsAnything { args = append(args, mock.Anything) } else { - args = append(args, e.Args.LayerIDs) + args = append(args, e.Args.BlobIDs) } _m.On("ApplyLayers", args...).Return(e.Returns.Detail, e.Returns.Err) } @@ -48,20 +50,20 @@ func (_m *MockApplier) ApplyApplyLayersExpectations(expectations []ApplierApplyL } } -// ApplyLayers provides a mock function with given fields: imageID, layerIDs -func (_m *MockApplier) ApplyLayers(imageID string, layerIDs []string) (types.ImageDetail, error) { - ret := _m.Called(imageID, layerIDs) +// ApplyLayers provides a mock function with given fields: artifactID, blobIDs +func (_m *MockApplier) ApplyLayers(artifactID string, blobIDs []string) (types.ArtifactDetail, error) { + ret := _m.Called(artifactID, blobIDs) - var r0 types.ImageDetail - if rf, ok := ret.Get(0).(func(string, []string) types.ImageDetail); ok { - r0 = rf(imageID, layerIDs) + var r0 types.ArtifactDetail + if rf, ok := ret.Get(0).(func(string, []string) types.ArtifactDetail); ok { + r0 = rf(artifactID, blobIDs) } else { - r0 = ret.Get(0).(types.ImageDetail) + r0 = ret.Get(0).(types.ArtifactDetail) } var r1 error if rf, ok := ret.Get(1).(func(string, []string) error); ok { - r1 = rf(imageID, layerIDs) + r1 = rf(artifactID, blobIDs) } else { r1 = ret.Error(1) } diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index ad4ad35937..d2b01b988d 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -19,13 +19,15 @@ import ( _ "github.com/aquasecurity/fanal/analyzer/library/yarn" _ "github.com/aquasecurity/fanal/analyzer/os/alpine" _ "github.com/aquasecurity/fanal/analyzer/os/amazonlinux" - _ "github.com/aquasecurity/fanal/analyzer/os/debianbase" + _ "github.com/aquasecurity/fanal/analyzer/os/debian" _ "github.com/aquasecurity/fanal/analyzer/os/photon" _ "github.com/aquasecurity/fanal/analyzer/os/redhatbase" _ "github.com/aquasecurity/fanal/analyzer/os/suse" + _ "github.com/aquasecurity/fanal/analyzer/os/ubuntu" _ "github.com/aquasecurity/fanal/analyzer/pkg/apk" _ "github.com/aquasecurity/fanal/analyzer/pkg/dpkg" _ "github.com/aquasecurity/fanal/analyzer/pkg/rpmcmd" + "github.com/aquasecurity/fanal/applier" ftypes "github.com/aquasecurity/fanal/types" libDetector "github.com/aquasecurity/trivy/pkg/detector/library" ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg" @@ -36,8 +38,8 @@ import ( ) var SuperSet = wire.NewSet( - analyzer.NewApplier, - wire.Bind(new(Applier), new(analyzer.Applier)), + applier.NewApplier, + wire.Bind(new(Applier), new(applier.Applier)), ospkgDetector.SuperSet, wire.Bind(new(OspkgDetector), new(ospkgDetector.Detector)), libDetector.SuperSet, @@ -46,7 +48,7 @@ var SuperSet = wire.NewSet( ) type Applier interface { - ApplyLayers(imageID string, layerIDs []string) (detail ftypes.ImageDetail, err error) + ApplyLayers(artifactID string, blobIDs []string) (detail ftypes.ArtifactDetail, err error) } type OspkgDetector interface { @@ -72,7 +74,7 @@ func (s Scanner) Scan(target string, imageID string, layerIDs []string, options if err != nil { switch err { case analyzer.ErrUnknownOS: - log.Logger.Warn("This OS is not supported and vulnerabilities in OS packages are not detected.") + log.Logger.Warn("OS is not detected and vulnerabilities in OS packages are not detected.") case analyzer.ErrNoPkgsDetected: log.Logger.Warn("No OS package is detected. Make sure you haven't deleted any files that contain information about the installed packages.") log.Logger.Warn(`e.g. files under "/lib/apk/db/", "/var/lib/dpkg/" and "/var/lib/rpm"`) diff --git a/pkg/scanner/local/scan_test.go b/pkg/scanner/local/scan_test.go index 893a46e5f2..24d39ff1a4 100644 --- a/pkg/scanner/local/scan_test.go +++ b/pkg/scanner/local/scan_test.go @@ -43,10 +43,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "alpine", Name: "3.11", @@ -182,10 +182,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{}, Applications: []ftypes.Application{ { @@ -260,10 +260,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "alpine", Name: "3.11", @@ -360,10 +360,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "fedora", Name: "27", @@ -455,10 +455,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"}, + BlobIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: nil, }, Err: analyzer.ErrUnknownOS, @@ -476,10 +476,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "alpine", Name: "3.11", @@ -616,7 +616,7 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ Err: errors.New("error"), @@ -633,10 +633,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "alpine", Name: "3.11", @@ -684,10 +684,10 @@ func TestScanner_Scan(t *testing.T) { }, applyLayersExpectation: ApplierApplyLayersExpectation{ Args: ApplierApplyLayersArgs{ - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, Returns: ApplierApplyLayersReturns{ - Detail: ftypes.ImageDetail{ + Detail: ftypes.ArtifactDetail{ OS: &ftypes.OS{ Family: "alpine", Name: "3.11", diff --git a/pkg/scanner/mock_analyzer.go b/pkg/scanner/mock_analyzer.go deleted file mode 100644 index 27bd8017c1..0000000000 --- a/pkg/scanner/mock_analyzer.go +++ /dev/null @@ -1,64 +0,0 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. - -package scanner - -import context "context" -import mock "github.com/stretchr/testify/mock" -import types "github.com/aquasecurity/fanal/types" - -// MockAnalyzer is an autogenerated mock type for the Analyzer type -type MockAnalyzer struct { - mock.Mock -} - -type AnalyzerAnalyzeArgs struct { - Ctx context.Context - CtxAnything bool -} - -type AnalyzerAnalyzeReturns struct { - Info types.ImageReference - Err error -} - -type AnalyzerAnalyzeExpectation struct { - Args AnalyzerAnalyzeArgs - Returns AnalyzerAnalyzeReturns -} - -func (_m *MockAnalyzer) ApplyAnalyzeExpectation(e AnalyzerAnalyzeExpectation) { - var args []interface{} - if e.Args.CtxAnything { - args = append(args, mock.Anything) - } else { - args = append(args, e.Args.Ctx) - } - _m.On("Analyze", args...).Return(e.Returns.Info, e.Returns.Err) -} - -func (_m *MockAnalyzer) ApplyAnalyzeExpectations(expectations []AnalyzerAnalyzeExpectation) { - for _, e := range expectations { - _m.ApplyAnalyzeExpectation(e) - } -} - -// Analyze provides a mock function with given fields: ctx -func (_m *MockAnalyzer) Analyze(ctx context.Context) (types.ImageReference, error) { - ret := _m.Called(ctx) - - var r0 types.ImageReference - if rf, ok := ret.Get(0).(func(context.Context) types.ImageReference); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(types.ImageReference) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} diff --git a/pkg/scanner/mock_driver.go b/pkg/scanner/mock_driver.go index 05631c7172..c8ecacdee4 100644 --- a/pkg/scanner/mock_driver.go +++ b/pkg/scanner/mock_driver.go @@ -2,17 +2,21 @@ package scanner -import fanaltypes "github.com/aquasecurity/fanal/types" -import mock "github.com/stretchr/testify/mock" -import report "github.com/aquasecurity/trivy/pkg/report" -import types "github.com/aquasecurity/trivy/pkg/types" +import ( + fanaltypes "github.com/aquasecurity/fanal/types" + mock "github.com/stretchr/testify/mock" + + report "github.com/aquasecurity/trivy/pkg/report" + + types "github.com/aquasecurity/trivy/pkg/types" +) // MockDriver is an autogenerated mock type for the Driver type type MockDriver struct { mock.Mock } -type ScanArgs struct { +type DriverScanArgs struct { Target string TargetAnything bool ImageID string @@ -23,19 +27,19 @@ type ScanArgs struct { OptionsAnything bool } -type ScanReturns struct { +type DriverScanReturns struct { Results report.Results OsFound *fanaltypes.OS Eols bool Err error } -type ScanExpectation struct { - Args ScanArgs - Returns ScanReturns +type DriverScanExpectation struct { + Args DriverScanArgs + Returns DriverScanReturns } -func (_m *MockDriver) ApplyScanExpectation(e ScanExpectation) { +func (_m *MockDriver) ApplyScanExpectation(e DriverScanExpectation) { var args []interface{} if e.Args.TargetAnything { args = append(args, mock.Anything) @@ -60,7 +64,7 @@ func (_m *MockDriver) ApplyScanExpectation(e ScanExpectation) { _m.On("Scan", args...).Return(e.Returns.Results, e.Returns.OsFound, e.Returns.Eols, e.Returns.Err) } -func (_m *MockDriver) ApplyScanExpectations(expectations []ScanExpectation) { +func (_m *MockDriver) ApplyScanExpectations(expectations []DriverScanExpectation) { for _, e := range expectations { _m.ApplyScanExpectation(e) } diff --git a/pkg/scanner/scan.go b/pkg/scanner/scan.go index 20c45f82cf..f029b944a4 100644 --- a/pkg/scanner/scan.go +++ b/pkg/scanner/scan.go @@ -6,9 +6,11 @@ import ( "github.com/google/wire" "golang.org/x/xerrors" - "github.com/aquasecurity/fanal/analyzer" - "github.com/aquasecurity/fanal/extractor" - "github.com/aquasecurity/fanal/extractor/docker" + "github.com/aquasecurity/fanal/artifact" + aimage "github.com/aquasecurity/fanal/artifact/image" + flocal "github.com/aquasecurity/fanal/artifact/local" + "github.com/aquasecurity/fanal/artifact/remote" + "github.com/aquasecurity/fanal/image" ftypes "github.com/aquasecurity/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/report" @@ -19,8 +21,6 @@ import ( // StandaloneSuperSet is used in the standalone mode var StandaloneSuperSet = wire.NewSet( - analyzer.New, - wire.Bind(new(Analyzer), new(analyzer.Config)), local.SuperSet, wire.Bind(new(Driver), new(local.Scanner)), NewScanner, @@ -28,21 +28,30 @@ var StandaloneSuperSet = wire.NewSet( var StandaloneDockerSet = wire.NewSet( types.GetDockerOption, - docker.NewDockerExtractor, - wire.Bind(new(extractor.Extractor), new(docker.Extractor)), + image.NewDockerImage, + aimage.NewArtifact, StandaloneSuperSet, ) var StandaloneArchiveSet = wire.NewSet( - docker.NewArchiveImageExtractor, - wire.Bind(new(extractor.Extractor), new(docker.Extractor)), + image.NewArchiveImage, + aimage.NewArtifact, + StandaloneSuperSet, +) + +var StandaloneFilesystemSet = wire.NewSet( + flocal.NewArtifact, + StandaloneSuperSet, +) + +var StandaloneRepositorySet = wire.NewSet( + remote.NewArtifact, StandaloneSuperSet, ) // RemoteSuperSet is used in the client mode var RemoteSuperSet = wire.NewSet( - analyzer.New, - wire.Bind(new(Analyzer), new(analyzer.Config)), + aimage.NewArtifact, client.SuperSet, wire.Bind(new(Driver), new(client.Scanner)), NewScanner, @@ -50,45 +59,38 @@ var RemoteSuperSet = wire.NewSet( var RemoteDockerSet = wire.NewSet( types.GetDockerOption, - docker.NewDockerExtractor, - wire.Bind(new(extractor.Extractor), new(docker.Extractor)), + image.NewDockerImage, RemoteSuperSet, ) var RemoteArchiveSet = wire.NewSet( - docker.NewArchiveImageExtractor, - wire.Bind(new(extractor.Extractor), new(docker.Extractor)), + image.NewArchiveImage, RemoteSuperSet, ) type Scanner struct { driver Driver - analyzer Analyzer + artifact artifact.Artifact } type Driver interface { Scan(target string, imageID string, layerIDs []string, options types.ScanOptions) (results report.Results, osFound *ftypes.OS, eols bool, err error) } -type Analyzer interface { - Analyze(ctx context.Context) (info ftypes.ImageReference, err error) +func NewScanner(driver Driver, ar artifact.Artifact) Scanner { + return Scanner{driver: driver, artifact: ar} } -func NewScanner(driver Driver, ac Analyzer) Scanner { - return Scanner{driver: driver, analyzer: ac} -} - -func (s Scanner) ScanImage(options types.ScanOptions) (report.Results, error) { - ctx := context.Background() - imageInfo, err := s.analyzer.Analyze(ctx) +func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (report.Results, error) { + artifactInfo, err := s.artifact.Inspect(ctx) if err != nil { return nil, xerrors.Errorf("failed analysis: %w", err) } - log.Logger.Debugf("Image ID: %s", imageInfo.ID) - log.Logger.Debugf("Layer IDs: %v", imageInfo.LayerIDs) + log.Logger.Debugf("Artifact ID: %s", artifactInfo.ID) + log.Logger.Debugf("Blob IDs: %v", artifactInfo.BlobIDs) - results, osFound, eosl, err := s.driver.Scan(imageInfo.Name, imageInfo.ID, imageInfo.LayerIDs, options) + results, osFound, eosl, err := s.driver.Scan(artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options) if err != nil { return nil, xerrors.Errorf("scan failed: %w", err) } diff --git a/pkg/scanner/scan_test.go b/pkg/scanner/scan_test.go index 42e8b4bedb..b23c376b59 100644 --- a/pkg/scanner/scan_test.go +++ b/pkg/scanner/scan_test.go @@ -1,6 +1,7 @@ package scanner import ( + "context" "errors" "os" "testing" @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/fanal/artifact" ftypes "github.com/aquasecurity/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/report" @@ -20,15 +22,15 @@ func TestMain(m *testing.M) { os.Exit(code) } -func TestScanner_ScanImage(t *testing.T) { +func TestScanner_ScanArtifact(t *testing.T) { type args struct { options types.ScanOptions } tests := []struct { name string args args - analyzeExpectation AnalyzerAnalyzeExpectation - scanExpectation ScanExpectation + inspectExpectation artifact.ArtifactInspectExpectation + scanExpectation DriverScanExpectation wantResults report.Results wantErr string }{ @@ -37,26 +39,26 @@ func TestScanner_ScanImage(t *testing.T) { args: args{ options: types.ScanOptions{VulnType: []string{"os"}}, }, - analyzeExpectation: AnalyzerAnalyzeExpectation{ - Args: AnalyzerAnalyzeArgs{ + inspectExpectation: artifact.ArtifactInspectExpectation{ + Args: artifact.ArtifactInspectArgs{ CtxAnything: true, }, - Returns: AnalyzerAnalyzeReturns{ - Info: ftypes.ImageReference{ - Name: "alpine:3.11", - ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Returns: artifact.ArtifactInspectReturns{ + Reference: ftypes.ArtifactReference{ + Name: "alpine:3.11", + ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, }, }, - scanExpectation: ScanExpectation{ - Args: ScanArgs{ + scanExpectation: DriverScanExpectation{ + Args: DriverScanArgs{ Target: "alpine:3.11", ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, Options: types.ScanOptions{VulnType: []string{"os"}}, }, - Returns: ScanReturns{ + Returns: DriverScanReturns{ Results: report.Results{ { Target: "alpine:3.11", @@ -128,11 +130,11 @@ func TestScanner_ScanImage(t *testing.T) { args: args{ options: types.ScanOptions{VulnType: []string{"os"}}, }, - analyzeExpectation: AnalyzerAnalyzeExpectation{ - Args: AnalyzerAnalyzeArgs{ + inspectExpectation: artifact.ArtifactInspectExpectation{ + Args: artifact.ArtifactInspectArgs{ CtxAnything: true, }, - Returns: AnalyzerAnalyzeReturns{ + Returns: artifact.ArtifactInspectReturns{ Err: errors.New("error"), }, }, @@ -143,26 +145,26 @@ func TestScanner_ScanImage(t *testing.T) { args: args{ options: types.ScanOptions{VulnType: []string{"os"}}, }, - analyzeExpectation: AnalyzerAnalyzeExpectation{ - Args: AnalyzerAnalyzeArgs{ + inspectExpectation: artifact.ArtifactInspectExpectation{ + Args: artifact.ArtifactInspectArgs{ CtxAnything: true, }, - Returns: AnalyzerAnalyzeReturns{ - Info: ftypes.ImageReference{ - Name: "alpine:3.11", - ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", - LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + Returns: artifact.ArtifactInspectReturns{ + Reference: ftypes.ArtifactReference{ + Name: "alpine:3.11", + ID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, }, }, }, - scanExpectation: ScanExpectation{ - Args: ScanArgs{ + scanExpectation: DriverScanExpectation{ + Args: DriverScanArgs{ Target: "alpine:3.11", ImageID: "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", LayerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, Options: types.ScanOptions{VulnType: []string{"os"}}, }, - Returns: ScanReturns{ + Returns: DriverScanReturns{ Err: errors.New("error"), }, }, @@ -174,11 +176,11 @@ func TestScanner_ScanImage(t *testing.T) { d := new(MockDriver) d.ApplyScanExpectation(tt.scanExpectation) - analyzer := new(MockAnalyzer) - analyzer.ApplyAnalyzeExpectation(tt.analyzeExpectation) + mockArtifact := new(artifact.MockArtifact) + mockArtifact.ApplyInspectExpectation(tt.inspectExpectation) - s := NewScanner(d, analyzer) - gotResults, err := s.ScanImage(tt.args.options) + s := NewScanner(d, mockArtifact) + gotResults, err := s.ScanArtifact(context.Background(), tt.args.options) if tt.wantErr != "" { require.NotNil(t, err, tt.name) require.Contains(t, err.Error(), tt.wantErr, tt.name) diff --git a/rpc/cache/service.pb.go b/rpc/cache/service.pb.go index 132e0b150f..0374a73258 100644 --- a/rpc/cache/service.pb.go +++ b/rpc/cache/service.pb.go @@ -23,7 +23,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package -type ImageInfo struct { +type ArtifactInfo struct { SchemaVersion int32 `protobuf:"varint,1,opt,name=schema_version,json=schemaVersion,proto3" json:"schema_version,omitempty"` Architecture string `protobuf:"bytes,2,opt,name=architecture,proto3" json:"architecture,omitempty"` Created *timestamp.Timestamp `protobuf:"bytes,3,opt,name=created,proto3" json:"created,omitempty"` @@ -35,121 +35,121 @@ type ImageInfo struct { XXX_sizecache int32 `json:"-"` } -func (m *ImageInfo) Reset() { *m = ImageInfo{} } -func (m *ImageInfo) String() string { return proto.CompactTextString(m) } -func (*ImageInfo) ProtoMessage() {} -func (*ImageInfo) Descriptor() ([]byte, []int) { +func (m *ArtifactInfo) Reset() { *m = ArtifactInfo{} } +func (m *ArtifactInfo) String() string { return proto.CompactTextString(m) } +func (*ArtifactInfo) ProtoMessage() {} +func (*ArtifactInfo) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{0} } -func (m *ImageInfo) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ImageInfo.Unmarshal(m, b) +func (m *ArtifactInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ArtifactInfo.Unmarshal(m, b) } -func (m *ImageInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ImageInfo.Marshal(b, m, deterministic) +func (m *ArtifactInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ArtifactInfo.Marshal(b, m, deterministic) } -func (m *ImageInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_ImageInfo.Merge(m, src) +func (m *ArtifactInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ArtifactInfo.Merge(m, src) } -func (m *ImageInfo) XXX_Size() int { - return xxx_messageInfo_ImageInfo.Size(m) +func (m *ArtifactInfo) XXX_Size() int { + return xxx_messageInfo_ArtifactInfo.Size(m) } -func (m *ImageInfo) XXX_DiscardUnknown() { - xxx_messageInfo_ImageInfo.DiscardUnknown(m) +func (m *ArtifactInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ArtifactInfo.DiscardUnknown(m) } -var xxx_messageInfo_ImageInfo proto.InternalMessageInfo +var xxx_messageInfo_ArtifactInfo proto.InternalMessageInfo -func (m *ImageInfo) GetSchemaVersion() int32 { +func (m *ArtifactInfo) GetSchemaVersion() int32 { if m != nil { return m.SchemaVersion } return 0 } -func (m *ImageInfo) GetArchitecture() string { +func (m *ArtifactInfo) GetArchitecture() string { if m != nil { return m.Architecture } return "" } -func (m *ImageInfo) GetCreated() *timestamp.Timestamp { +func (m *ArtifactInfo) GetCreated() *timestamp.Timestamp { if m != nil { return m.Created } return nil } -func (m *ImageInfo) GetDockerVersion() string { +func (m *ArtifactInfo) GetDockerVersion() string { if m != nil { return m.DockerVersion } return "" } -func (m *ImageInfo) GetOs() string { +func (m *ArtifactInfo) GetOs() string { if m != nil { return m.Os } return "" } -func (m *ImageInfo) GetHistoryPackages() []*common.Package { +func (m *ArtifactInfo) GetHistoryPackages() []*common.Package { if m != nil { return m.HistoryPackages } return nil } -type PutImageRequest struct { - ImageId string `protobuf:"bytes,1,opt,name=image_id,json=imageId,proto3" json:"image_id,omitempty"` - ImageInfo *ImageInfo `protobuf:"bytes,2,opt,name=image_info,json=imageInfo,proto3" json:"image_info,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type PutArtifactRequest struct { + ArtifactId string `protobuf:"bytes,1,opt,name=artifact_id,json=artifactId,proto3" json:"artifact_id,omitempty"` + ArtifactInfo *ArtifactInfo `protobuf:"bytes,2,opt,name=artifact_info,json=artifactInfo,proto3" json:"artifact_info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *PutImageRequest) Reset() { *m = PutImageRequest{} } -func (m *PutImageRequest) String() string { return proto.CompactTextString(m) } -func (*PutImageRequest) ProtoMessage() {} -func (*PutImageRequest) Descriptor() ([]byte, []int) { +func (m *PutArtifactRequest) Reset() { *m = PutArtifactRequest{} } +func (m *PutArtifactRequest) String() string { return proto.CompactTextString(m) } +func (*PutArtifactRequest) ProtoMessage() {} +func (*PutArtifactRequest) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{1} } -func (m *PutImageRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PutImageRequest.Unmarshal(m, b) +func (m *PutArtifactRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PutArtifactRequest.Unmarshal(m, b) } -func (m *PutImageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PutImageRequest.Marshal(b, m, deterministic) +func (m *PutArtifactRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PutArtifactRequest.Marshal(b, m, deterministic) } -func (m *PutImageRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PutImageRequest.Merge(m, src) +func (m *PutArtifactRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PutArtifactRequest.Merge(m, src) } -func (m *PutImageRequest) XXX_Size() int { - return xxx_messageInfo_PutImageRequest.Size(m) +func (m *PutArtifactRequest) XXX_Size() int { + return xxx_messageInfo_PutArtifactRequest.Size(m) } -func (m *PutImageRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PutImageRequest.DiscardUnknown(m) +func (m *PutArtifactRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PutArtifactRequest.DiscardUnknown(m) } -var xxx_messageInfo_PutImageRequest proto.InternalMessageInfo +var xxx_messageInfo_PutArtifactRequest proto.InternalMessageInfo -func (m *PutImageRequest) GetImageId() string { +func (m *PutArtifactRequest) GetArtifactId() string { if m != nil { - return m.ImageId + return m.ArtifactId } return "" } -func (m *PutImageRequest) GetImageInfo() *ImageInfo { +func (m *PutArtifactRequest) GetArtifactInfo() *ArtifactInfo { if m != nil { - return m.ImageInfo + return m.ArtifactInfo } return nil } -type LayerInfo struct { +type BlobInfo struct { SchemaVersion int32 `protobuf:"varint,1,opt,name=schema_version,json=schemaVersion,proto3" json:"schema_version,omitempty"` Os *common.OS `protobuf:"bytes,2,opt,name=os,proto3" json:"os,omitempty"` PackageInfos []*common.PackageInfo `protobuf:"bytes,3,rep,name=package_infos,json=packageInfos,proto3" json:"package_infos,omitempty"` @@ -163,130 +163,130 @@ type LayerInfo struct { XXX_sizecache int32 `json:"-"` } -func (m *LayerInfo) Reset() { *m = LayerInfo{} } -func (m *LayerInfo) String() string { return proto.CompactTextString(m) } -func (*LayerInfo) ProtoMessage() {} -func (*LayerInfo) Descriptor() ([]byte, []int) { +func (m *BlobInfo) Reset() { *m = BlobInfo{} } +func (m *BlobInfo) String() string { return proto.CompactTextString(m) } +func (*BlobInfo) ProtoMessage() {} +func (*BlobInfo) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{2} } -func (m *LayerInfo) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LayerInfo.Unmarshal(m, b) +func (m *BlobInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BlobInfo.Unmarshal(m, b) } -func (m *LayerInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LayerInfo.Marshal(b, m, deterministic) +func (m *BlobInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BlobInfo.Marshal(b, m, deterministic) } -func (m *LayerInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_LayerInfo.Merge(m, src) +func (m *BlobInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlobInfo.Merge(m, src) } -func (m *LayerInfo) XXX_Size() int { - return xxx_messageInfo_LayerInfo.Size(m) +func (m *BlobInfo) XXX_Size() int { + return xxx_messageInfo_BlobInfo.Size(m) } -func (m *LayerInfo) XXX_DiscardUnknown() { - xxx_messageInfo_LayerInfo.DiscardUnknown(m) +func (m *BlobInfo) XXX_DiscardUnknown() { + xxx_messageInfo_BlobInfo.DiscardUnknown(m) } -var xxx_messageInfo_LayerInfo proto.InternalMessageInfo +var xxx_messageInfo_BlobInfo proto.InternalMessageInfo -func (m *LayerInfo) GetSchemaVersion() int32 { +func (m *BlobInfo) GetSchemaVersion() int32 { if m != nil { return m.SchemaVersion } return 0 } -func (m *LayerInfo) GetOs() *common.OS { +func (m *BlobInfo) GetOs() *common.OS { if m != nil { return m.Os } return nil } -func (m *LayerInfo) GetPackageInfos() []*common.PackageInfo { +func (m *BlobInfo) GetPackageInfos() []*common.PackageInfo { if m != nil { return m.PackageInfos } return nil } -func (m *LayerInfo) GetApplications() []*common.Application { +func (m *BlobInfo) GetApplications() []*common.Application { if m != nil { return m.Applications } return nil } -func (m *LayerInfo) GetOpaqueDirs() []string { +func (m *BlobInfo) GetOpaqueDirs() []string { if m != nil { return m.OpaqueDirs } return nil } -func (m *LayerInfo) GetWhiteoutFiles() []string { +func (m *BlobInfo) GetWhiteoutFiles() []string { if m != nil { return m.WhiteoutFiles } return nil } -func (m *LayerInfo) GetDigest() string { +func (m *BlobInfo) GetDigest() string { if m != nil { return m.Digest } return "" } -func (m *LayerInfo) GetDiffId() string { +func (m *BlobInfo) GetDiffId() string { if m != nil { return m.DiffId } return "" } -type PutLayerRequest struct { - DiffId string `protobuf:"bytes,1,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"` - LayerInfo *LayerInfo `protobuf:"bytes,3,opt,name=layer_info,json=layerInfo,proto3" json:"layer_info,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type PutBlobRequest struct { + DiffId string `protobuf:"bytes,1,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"` + BlobInfo *BlobInfo `protobuf:"bytes,3,opt,name=blob_info,json=blobInfo,proto3" json:"blob_info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *PutLayerRequest) Reset() { *m = PutLayerRequest{} } -func (m *PutLayerRequest) String() string { return proto.CompactTextString(m) } -func (*PutLayerRequest) ProtoMessage() {} -func (*PutLayerRequest) Descriptor() ([]byte, []int) { +func (m *PutBlobRequest) Reset() { *m = PutBlobRequest{} } +func (m *PutBlobRequest) String() string { return proto.CompactTextString(m) } +func (*PutBlobRequest) ProtoMessage() {} +func (*PutBlobRequest) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{3} } -func (m *PutLayerRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PutLayerRequest.Unmarshal(m, b) +func (m *PutBlobRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PutBlobRequest.Unmarshal(m, b) } -func (m *PutLayerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PutLayerRequest.Marshal(b, m, deterministic) +func (m *PutBlobRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PutBlobRequest.Marshal(b, m, deterministic) } -func (m *PutLayerRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PutLayerRequest.Merge(m, src) +func (m *PutBlobRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PutBlobRequest.Merge(m, src) } -func (m *PutLayerRequest) XXX_Size() int { - return xxx_messageInfo_PutLayerRequest.Size(m) +func (m *PutBlobRequest) XXX_Size() int { + return xxx_messageInfo_PutBlobRequest.Size(m) } -func (m *PutLayerRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PutLayerRequest.DiscardUnknown(m) +func (m *PutBlobRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PutBlobRequest.DiscardUnknown(m) } -var xxx_messageInfo_PutLayerRequest proto.InternalMessageInfo +var xxx_messageInfo_PutBlobRequest proto.InternalMessageInfo -func (m *PutLayerRequest) GetDiffId() string { +func (m *PutBlobRequest) GetDiffId() string { if m != nil { return m.DiffId } return "" } -func (m *PutLayerRequest) GetLayerInfo() *LayerInfo { +func (m *PutBlobRequest) GetBlobInfo() *BlobInfo { if m != nil { - return m.LayerInfo + return m.BlobInfo } return nil } @@ -338,155 +338,155 @@ func (m *PutResponse) GetEosl() bool { return false } -type MissingLayersRequest struct { - ImageId string `protobuf:"bytes,1,opt,name=image_id,json=imageId,proto3" json:"image_id,omitempty"` - LayerIds []string `protobuf:"bytes,2,rep,name=layer_ids,json=layerIds,proto3" json:"layer_ids,omitempty"` +type MissingBlobsRequest struct { + ArtifactId string `protobuf:"bytes,1,opt,name=artifact_id,json=artifactId,proto3" json:"artifact_id,omitempty"` + BlobIds []string `protobuf:"bytes,2,rep,name=blob_ids,json=blobIds,proto3" json:"blob_ids,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *MissingLayersRequest) Reset() { *m = MissingLayersRequest{} } -func (m *MissingLayersRequest) String() string { return proto.CompactTextString(m) } -func (*MissingLayersRequest) ProtoMessage() {} -func (*MissingLayersRequest) Descriptor() ([]byte, []int) { +func (m *MissingBlobsRequest) Reset() { *m = MissingBlobsRequest{} } +func (m *MissingBlobsRequest) String() string { return proto.CompactTextString(m) } +func (*MissingBlobsRequest) ProtoMessage() {} +func (*MissingBlobsRequest) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{5} } -func (m *MissingLayersRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MissingLayersRequest.Unmarshal(m, b) +func (m *MissingBlobsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MissingBlobsRequest.Unmarshal(m, b) } -func (m *MissingLayersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MissingLayersRequest.Marshal(b, m, deterministic) +func (m *MissingBlobsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MissingBlobsRequest.Marshal(b, m, deterministic) } -func (m *MissingLayersRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_MissingLayersRequest.Merge(m, src) +func (m *MissingBlobsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MissingBlobsRequest.Merge(m, src) } -func (m *MissingLayersRequest) XXX_Size() int { - return xxx_messageInfo_MissingLayersRequest.Size(m) +func (m *MissingBlobsRequest) XXX_Size() int { + return xxx_messageInfo_MissingBlobsRequest.Size(m) } -func (m *MissingLayersRequest) XXX_DiscardUnknown() { - xxx_messageInfo_MissingLayersRequest.DiscardUnknown(m) +func (m *MissingBlobsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MissingBlobsRequest.DiscardUnknown(m) } -var xxx_messageInfo_MissingLayersRequest proto.InternalMessageInfo +var xxx_messageInfo_MissingBlobsRequest proto.InternalMessageInfo -func (m *MissingLayersRequest) GetImageId() string { +func (m *MissingBlobsRequest) GetArtifactId() string { if m != nil { - return m.ImageId + return m.ArtifactId } return "" } -func (m *MissingLayersRequest) GetLayerIds() []string { +func (m *MissingBlobsRequest) GetBlobIds() []string { if m != nil { - return m.LayerIds + return m.BlobIds } return nil } -type MissingLayersResponse struct { - MissingImage bool `protobuf:"varint,1,opt,name=missing_image,json=missingImage,proto3" json:"missing_image,omitempty"` - MissingLayerIds []string `protobuf:"bytes,2,rep,name=missing_layer_ids,json=missingLayerIds,proto3" json:"missing_layer_ids,omitempty"` +type MissingBlobsResponse struct { + MissingArtifact bool `protobuf:"varint,1,opt,name=missing_artifact,json=missingArtifact,proto3" json:"missing_artifact,omitempty"` + MissingBlobIds []string `protobuf:"bytes,2,rep,name=missing_blob_ids,json=missingBlobIds,proto3" json:"missing_blob_ids,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *MissingLayersResponse) Reset() { *m = MissingLayersResponse{} } -func (m *MissingLayersResponse) String() string { return proto.CompactTextString(m) } -func (*MissingLayersResponse) ProtoMessage() {} -func (*MissingLayersResponse) Descriptor() ([]byte, []int) { +func (m *MissingBlobsResponse) Reset() { *m = MissingBlobsResponse{} } +func (m *MissingBlobsResponse) String() string { return proto.CompactTextString(m) } +func (*MissingBlobsResponse) ProtoMessage() {} +func (*MissingBlobsResponse) Descriptor() ([]byte, []int) { return fileDescriptor_1f1f7d564abadf42, []int{6} } -func (m *MissingLayersResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MissingLayersResponse.Unmarshal(m, b) +func (m *MissingBlobsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MissingBlobsResponse.Unmarshal(m, b) } -func (m *MissingLayersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MissingLayersResponse.Marshal(b, m, deterministic) +func (m *MissingBlobsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MissingBlobsResponse.Marshal(b, m, deterministic) } -func (m *MissingLayersResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MissingLayersResponse.Merge(m, src) +func (m *MissingBlobsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MissingBlobsResponse.Merge(m, src) } -func (m *MissingLayersResponse) XXX_Size() int { - return xxx_messageInfo_MissingLayersResponse.Size(m) +func (m *MissingBlobsResponse) XXX_Size() int { + return xxx_messageInfo_MissingBlobsResponse.Size(m) } -func (m *MissingLayersResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MissingLayersResponse.DiscardUnknown(m) +func (m *MissingBlobsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MissingBlobsResponse.DiscardUnknown(m) } -var xxx_messageInfo_MissingLayersResponse proto.InternalMessageInfo +var xxx_messageInfo_MissingBlobsResponse proto.InternalMessageInfo -func (m *MissingLayersResponse) GetMissingImage() bool { +func (m *MissingBlobsResponse) GetMissingArtifact() bool { if m != nil { - return m.MissingImage + return m.MissingArtifact } return false } -func (m *MissingLayersResponse) GetMissingLayerIds() []string { +func (m *MissingBlobsResponse) GetMissingBlobIds() []string { if m != nil { - return m.MissingLayerIds + return m.MissingBlobIds } return nil } func init() { - proto.RegisterType((*ImageInfo)(nil), "trivy.cache.v1.ImageInfo") - proto.RegisterType((*PutImageRequest)(nil), "trivy.cache.v1.PutImageRequest") - proto.RegisterType((*LayerInfo)(nil), "trivy.cache.v1.LayerInfo") - proto.RegisterType((*PutLayerRequest)(nil), "trivy.cache.v1.PutLayerRequest") + proto.RegisterType((*ArtifactInfo)(nil), "trivy.cache.v1.ArtifactInfo") + proto.RegisterType((*PutArtifactRequest)(nil), "trivy.cache.v1.PutArtifactRequest") + proto.RegisterType((*BlobInfo)(nil), "trivy.cache.v1.BlobInfo") + proto.RegisterType((*PutBlobRequest)(nil), "trivy.cache.v1.PutBlobRequest") proto.RegisterType((*PutResponse)(nil), "trivy.cache.v1.PutResponse") - proto.RegisterType((*MissingLayersRequest)(nil), "trivy.cache.v1.MissingLayersRequest") - proto.RegisterType((*MissingLayersResponse)(nil), "trivy.cache.v1.MissingLayersResponse") + proto.RegisterType((*MissingBlobsRequest)(nil), "trivy.cache.v1.MissingBlobsRequest") + proto.RegisterType((*MissingBlobsResponse)(nil), "trivy.cache.v1.MissingBlobsResponse") } func init() { proto.RegisterFile("rpc/cache/service.proto", fileDescriptor_1f1f7d564abadf42) } var fileDescriptor_1f1f7d564abadf42 = []byte{ - // 674 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xd3, 0x30, - 0x14, 0x56, 0xdb, 0x75, 0x6d, 0x4e, 0xdb, 0x6d, 0x58, 0x6c, 0xcb, 0xba, 0x8b, 0x55, 0x81, 0x49, - 0x15, 0x17, 0x89, 0x28, 0x08, 0x71, 0x03, 0x02, 0x06, 0x48, 0x95, 0xf8, 0x99, 0x0c, 0xe2, 0x02, - 0x21, 0x55, 0x5e, 0xe2, 0xa4, 0xd6, 0x9a, 0x38, 0xb3, 0x9d, 0xa2, 0x3e, 0x00, 0x6f, 0xc7, 0xbb, - 0xf0, 0x0a, 0x28, 0x27, 0xc9, 0xd6, 0x96, 0xf2, 0x77, 0xe7, 0xf3, 0x93, 0xef, 0x7c, 0xe7, 0xfb, - 0xec, 0xc0, 0xa1, 0x4a, 0x7d, 0xcf, 0x67, 0xfe, 0x94, 0x7b, 0x9a, 0xab, 0xb9, 0xf0, 0xb9, 0x9b, - 0x2a, 0x69, 0x24, 0xd9, 0x31, 0x4a, 0xcc, 0x17, 0x2e, 0x96, 0xdc, 0xf9, 0xfd, 0xfe, 0x49, 0x24, - 0x65, 0x34, 0xe3, 0x1e, 0x56, 0x2f, 0xb2, 0xd0, 0x33, 0x22, 0xe6, 0xda, 0xb0, 0x38, 0x2d, 0x3e, - 0xe8, 0x3f, 0x8a, 0x84, 0x99, 0x66, 0x17, 0xae, 0x2f, 0x63, 0x8f, 0x5d, 0x65, 0x4c, 0x73, 0x3f, - 0x53, 0xc2, 0x2c, 0x3c, 0x04, 0xf2, 0x70, 0x8e, 0x8c, 0x63, 0x99, 0xac, 0x0e, 0xea, 0x1f, 0xaf, - 0x03, 0xf3, 0x38, 0x35, 0x8b, 0xa2, 0xe8, 0x7c, 0xab, 0x83, 0x35, 0x8e, 0x59, 0xc4, 0xc7, 0x49, - 0x28, 0xc9, 0x29, 0xec, 0x68, 0x7f, 0xca, 0x63, 0x36, 0x99, 0x73, 0xa5, 0x85, 0x4c, 0xec, 0xda, - 0xa0, 0x36, 0x6c, 0xd2, 0x5e, 0x91, 0xfd, 0x54, 0x24, 0x89, 0x03, 0x5d, 0xa6, 0xfc, 0xa9, 0x30, - 0xdc, 0x37, 0x99, 0xe2, 0x76, 0x7d, 0x50, 0x1b, 0x5a, 0x74, 0x25, 0x47, 0x1e, 0x42, 0xcb, 0x57, - 0x9c, 0x19, 0x1e, 0xd8, 0x8d, 0x41, 0x6d, 0xd8, 0x19, 0xf5, 0xdd, 0x82, 0x87, 0x5b, 0xf1, 0x70, - 0x3f, 0x56, 0x0b, 0xd2, 0xaa, 0x35, 0x27, 0x10, 0x48, 0xff, 0x92, 0xab, 0x6b, 0x02, 0x5b, 0x88, - 0xdd, 0x2b, 0xb2, 0x15, 0x81, 0x1d, 0xa8, 0x4b, 0x6d, 0x37, 0xb1, 0x54, 0x97, 0x9a, 0x3c, 0x83, - 0xbd, 0xa9, 0xd0, 0x46, 0xaa, 0xc5, 0x24, 0x65, 0xfe, 0x25, 0x8b, 0xb8, 0xb6, 0xb7, 0x07, 0x8d, - 0x61, 0x67, 0xb4, 0xef, 0x96, 0x32, 0xa3, 0x32, 0xee, 0x79, 0x51, 0xa5, 0xbb, 0x65, 0x7b, 0x19, - 0x6b, 0x27, 0x84, 0xdd, 0xf3, 0xcc, 0xa0, 0x12, 0x94, 0x5f, 0x65, 0x5c, 0x1b, 0x72, 0x04, 0x6d, - 0x91, 0xc7, 0x13, 0x11, 0xa0, 0x0c, 0x16, 0x6d, 0x61, 0x3c, 0x0e, 0xc8, 0x63, 0x80, 0xb2, 0x94, - 0x84, 0x12, 0xd7, 0xef, 0x8c, 0x8e, 0xdc, 0x55, 0x43, 0xdd, 0x6b, 0x59, 0xa9, 0x25, 0xaa, 0xa3, - 0xf3, 0xbd, 0x0e, 0xd6, 0x1b, 0xb6, 0xe0, 0xea, 0x7f, 0xf4, 0x1e, 0xe0, 0xba, 0xc5, 0x98, 0xbd, - 0xd5, 0x85, 0xde, 0x7f, 0x40, 0x01, 0x9e, 0x42, 0xaf, 0x5c, 0x1c, 0x29, 0x69, 0xbb, 0x81, 0xdb, - 0x1f, 0x6d, 0xdc, 0x1e, 0x39, 0x75, 0xd3, 0x9b, 0x40, 0x93, 0x27, 0xd0, 0x65, 0x69, 0x3a, 0x13, - 0x3e, 0x33, 0x42, 0x26, 0xda, 0xde, 0xda, 0xf4, 0xf9, 0xf3, 0x9b, 0x0e, 0xba, 0xd2, 0x4e, 0x4e, - 0xa0, 0x23, 0x53, 0x76, 0x95, 0xf1, 0x49, 0x20, 0x54, 0x6e, 0x4c, 0x63, 0x68, 0x51, 0x28, 0x52, - 0x2f, 0x85, 0xd2, 0xf9, 0xa2, 0x5f, 0xf3, 0xbb, 0x21, 0x33, 0x33, 0x09, 0xc5, 0xac, 0xb4, 0xc7, - 0xa2, 0xbd, 0x2a, 0xfb, 0x3a, 0x4f, 0x92, 0x03, 0xd8, 0x0e, 0x44, 0xc4, 0xb5, 0xb1, 0x5b, 0x28, - 0x78, 0x19, 0x91, 0x43, 0x68, 0x05, 0x22, 0x0c, 0x73, 0x27, 0xda, 0x55, 0x21, 0x0c, 0xc7, 0x81, - 0x13, 0xa0, 0x6d, 0x28, 0x68, 0x65, 0xdb, 0x52, 0x6f, 0x6d, 0xb9, 0x37, 0x37, 0x6d, 0x96, 0x37, - 0x16, 0xa6, 0x35, 0x36, 0x9b, 0x76, 0xed, 0x0d, 0xb5, 0x66, 0xd5, 0xd1, 0x39, 0x83, 0xce, 0x79, - 0x66, 0x28, 0xd7, 0xa9, 0x4c, 0x34, 0x2f, 0xed, 0xa8, 0xfd, 0xc1, 0x0e, 0x02, 0x5b, 0x5c, 0xea, - 0x19, 0x5a, 0xd6, 0xa6, 0x78, 0x76, 0xde, 0xc1, 0xed, 0xb7, 0x42, 0x6b, 0x91, 0x44, 0x38, 0x43, - 0xff, 0xc3, 0x35, 0x3b, 0x06, 0xab, 0x64, 0x1c, 0xe4, 0xf6, 0xe7, 0x82, 0xb5, 0x0b, 0x56, 0x81, - 0x76, 0xa6, 0xb0, 0xbf, 0x86, 0x57, 0xd2, 0xbb, 0x03, 0xbd, 0xb8, 0x28, 0x4c, 0x10, 0x08, 0x51, - 0xdb, 0xb4, 0x5b, 0x26, 0xf1, 0x5a, 0x92, 0x7b, 0x70, 0xab, 0x6a, 0x5a, 0x1f, 0xb1, 0x1b, 0x2f, - 0xc1, 0x8e, 0x03, 0x3d, 0xfa, 0x51, 0x83, 0xe6, 0x59, 0x2e, 0x10, 0x39, 0x83, 0x76, 0xf5, 0x4a, - 0xc8, 0xc9, 0xba, 0x74, 0x6b, 0xef, 0xa7, 0x7f, 0xf0, 0xcb, 0x83, 0x7f, 0x95, 0xff, 0x78, 0x4a, - 0x10, 0x44, 0xdf, 0x08, 0xb2, 0xec, 0xe6, 0x6f, 0x41, 0xbe, 0x40, 0x6f, 0x65, 0x7b, 0x72, 0x77, - 0x1d, 0x69, 0x93, 0xd8, 0xfd, 0xd3, 0xbf, 0x74, 0x15, 0x12, 0xbe, 0x68, 0x7d, 0x6e, 0x62, 0xc7, - 0xc5, 0x36, 0x8e, 0x7d, 0xf0, 0x33, 0x00, 0x00, 0xff, 0xff, 0x08, 0x8d, 0x6f, 0x9e, 0xc6, 0x05, - 0x00, 0x00, + // 682 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdd, 0x6e, 0xd3, 0x3e, + 0x18, 0xc6, 0xd5, 0x76, 0x5d, 0xdb, 0xb7, 0x1f, 0x9b, 0xfc, 0xff, 0xb3, 0x65, 0x05, 0xb1, 0x2a, + 0x80, 0x54, 0x4e, 0x52, 0x51, 0x3e, 0xce, 0x40, 0x74, 0x03, 0xa4, 0x1e, 0x20, 0x4a, 0x40, 0x48, + 0x70, 0x52, 0x5c, 0xc7, 0x69, 0xad, 0x35, 0x71, 0x66, 0x3b, 0x85, 0xde, 0x01, 0xf7, 0xc6, 0xcd, + 0x70, 0x09, 0xc8, 0x76, 0xb2, 0x7e, 0xac, 0x4c, 0x70, 0x16, 0x3f, 0x7e, 0xf3, 0xbc, 0xaf, 0x7f, + 0x8f, 0x13, 0x38, 0x16, 0x09, 0xe9, 0x11, 0x4c, 0x66, 0xb4, 0x27, 0xa9, 0x58, 0x30, 0x42, 0xbd, + 0x44, 0x70, 0xc5, 0x51, 0x4b, 0x09, 0xb6, 0x58, 0x7a, 0x66, 0xcb, 0x5b, 0x3c, 0x6a, 0x9f, 0x4e, + 0x39, 0x9f, 0xce, 0x69, 0xcf, 0xec, 0x4e, 0xd2, 0xb0, 0xa7, 0x58, 0x44, 0xa5, 0xc2, 0x51, 0x62, + 0x5f, 0x68, 0x3f, 0x9b, 0x32, 0x35, 0x4b, 0x27, 0x1e, 0xe1, 0x51, 0x0f, 0x5f, 0xa6, 0x58, 0x52, + 0x92, 0x0a, 0xa6, 0x96, 0x3d, 0x63, 0xd4, 0x33, 0x7d, 0x78, 0x14, 0xf1, 0x78, 0xb3, 0x51, 0xfb, + 0xf6, 0xb6, 0x31, 0x8d, 0x12, 0xb5, 0xb4, 0x9b, 0xee, 0x8f, 0x22, 0x34, 0x06, 0x42, 0xb1, 0x10, + 0x13, 0x35, 0x8c, 0x43, 0x8e, 0x1e, 0x40, 0x4b, 0x92, 0x19, 0x8d, 0xf0, 0x78, 0x41, 0x85, 0x64, + 0x3c, 0x76, 0x0a, 0x9d, 0x42, 0xb7, 0xec, 0x37, 0xad, 0xfa, 0xc9, 0x8a, 0xc8, 0x85, 0x06, 0x16, + 0x64, 0xc6, 0x14, 0x25, 0x2a, 0x15, 0xd4, 0x29, 0x76, 0x0a, 0xdd, 0x9a, 0xbf, 0xa1, 0xa1, 0x27, + 0x50, 0x21, 0x82, 0x62, 0x45, 0x03, 0xa7, 0xd4, 0x29, 0x74, 0xeb, 0xfd, 0xb6, 0x67, 0x47, 0xf1, + 0xf2, 0x51, 0xbc, 0x8f, 0xf9, 0x19, 0xfd, 0xbc, 0x54, 0x0f, 0x10, 0x70, 0x72, 0x41, 0xc5, 0xd5, + 0x00, 0x7b, 0xc6, 0xbb, 0x69, 0xd5, 0x7c, 0x80, 0x16, 0x14, 0xb9, 0x74, 0xca, 0x66, 0xab, 0xc8, + 0x25, 0x7a, 0x09, 0x87, 0x33, 0x26, 0x15, 0x17, 0xcb, 0x71, 0x82, 0xc9, 0x05, 0x9e, 0x52, 0xe9, + 0xec, 0x77, 0x4a, 0xdd, 0x7a, 0xff, 0x96, 0x97, 0x91, 0x36, 0x70, 0xbc, 0x91, 0xdd, 0xf5, 0x0f, + 0xb2, 0xf2, 0x6c, 0x2d, 0xdd, 0xef, 0x80, 0x46, 0xa9, 0xca, 0x61, 0xf8, 0xf4, 0x32, 0xa5, 0x52, + 0xa1, 0x53, 0xa8, 0xe3, 0x4c, 0x1a, 0xb3, 0xc0, 0xc0, 0xa8, 0xf9, 0x90, 0x4b, 0xc3, 0x00, 0x0d, + 0xa0, 0xb9, 0x2a, 0x88, 0x43, 0x6e, 0x50, 0xd4, 0xfb, 0x77, 0xbc, 0xcd, 0x7c, 0xbd, 0x75, 0xca, + 0x1a, 0xd4, 0x6a, 0xe5, 0xfe, 0x2c, 0x42, 0xf5, 0x6c, 0xce, 0x27, 0xff, 0x12, 0x40, 0xc7, 0x9c, + 0xdf, 0xf6, 0x3a, 0xdc, 0x3c, 0xe1, 0xbb, 0x0f, 0x86, 0xc8, 0x0b, 0x68, 0x66, 0x24, 0xcc, 0x5c, + 0xd2, 0x29, 0x19, 0x1c, 0x27, 0x3b, 0x71, 0xd8, 0xa9, 0x92, 0xd5, 0x42, 0xa2, 0xe7, 0xd0, 0xc0, + 0x49, 0x32, 0x67, 0x04, 0x2b, 0xc6, 0x63, 0xe9, 0xec, 0xed, 0x7a, 0x7d, 0xb0, 0xaa, 0xf0, 0x37, + 0xca, 0x35, 0x38, 0x9e, 0xe0, 0xcb, 0x94, 0x8e, 0x03, 0x26, 0x74, 0x52, 0x25, 0x0d, 0xce, 0x4a, + 0xaf, 0x98, 0x90, 0xfa, 0xa0, 0xdf, 0xf4, 0x65, 0xe1, 0xa9, 0x1a, 0x87, 0x6c, 0x9e, 0xe5, 0x55, + 0xf3, 0x9b, 0xb9, 0xfa, 0x46, 0x8b, 0xe8, 0x08, 0xf6, 0x03, 0x36, 0xa5, 0x52, 0x39, 0x15, 0xc3, + 0x3e, 0x5b, 0xa1, 0x63, 0xa8, 0x04, 0x2c, 0x0c, 0x75, 0x28, 0xd5, 0x7c, 0x23, 0x0c, 0x87, 0x81, + 0xfb, 0x15, 0x5a, 0xa3, 0x54, 0x69, 0x9e, 0x79, 0x86, 0x6b, 0xa5, 0x85, 0xf5, 0x52, 0xf4, 0x14, + 0x6a, 0x93, 0x39, 0x9f, 0xd8, 0xdc, 0xec, 0x1d, 0x75, 0xb6, 0x73, 0xcb, 0x83, 0xf1, 0xab, 0x93, + 0xec, 0xc9, 0x3d, 0x87, 0xfa, 0x28, 0x55, 0x3e, 0x95, 0x09, 0x8f, 0x25, 0xcd, 0xa2, 0x28, 0xdc, + 0x10, 0x05, 0x82, 0x3d, 0xca, 0xe5, 0xdc, 0xc4, 0x55, 0xf5, 0xcd, 0xb3, 0xfb, 0x1e, 0xfe, 0x7b, + 0xcb, 0xa4, 0x64, 0xf1, 0x54, 0x77, 0x90, 0x7f, 0x7d, 0xdf, 0x4e, 0xa0, 0x6a, 0x67, 0x0e, 0x74, + 0xfc, 0x1a, 0x58, 0xc5, 0x0c, 0x16, 0x48, 0xf7, 0x02, 0xfe, 0xdf, 0xb4, 0xcc, 0x06, 0x7c, 0x08, + 0x87, 0x91, 0xd5, 0xc7, 0xb9, 0x91, 0x31, 0xae, 0xfa, 0x07, 0x99, 0x9e, 0x5f, 0x4e, 0xd4, 0x5d, + 0x95, 0x6e, 0x75, 0x69, 0x45, 0x2b, 0xeb, 0x61, 0x20, 0xfb, 0xbf, 0x0a, 0x50, 0x3e, 0xd7, 0x90, + 0xd0, 0xd0, 0xe0, 0xb8, 0xb2, 0x70, 0xb7, 0x09, 0x5e, 0xff, 0xaa, 0xda, 0x47, 0xd7, 0xfe, 0x04, + 0xaf, 0xf5, 0x4f, 0x09, 0x0d, 0xa0, 0x92, 0x65, 0x87, 0xee, 0xee, 0xb0, 0x59, 0x0b, 0xf5, 0x8f, + 0x16, 0x9f, 0xa1, 0xb1, 0x0e, 0x01, 0xdd, 0xdb, 0xf6, 0xd9, 0x41, 0xbd, 0x7d, 0xff, 0xe6, 0x22, + 0xcb, 0xf1, 0xac, 0xf2, 0xa5, 0x6c, 0x0a, 0x26, 0xfb, 0xa6, 0xe7, 0xe3, 0xdf, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xf9, 0x1a, 0xc0, 0xa0, 0xdd, 0x05, 0x00, 0x00, } diff --git a/rpc/cache/service.proto b/rpc/cache/service.proto index 3872edeae8..404969accf 100644 --- a/rpc/cache/service.proto +++ b/rpc/cache/service.proto @@ -8,12 +8,12 @@ import "github.com/aquasecurity/trivy/rpc/common/service.proto"; import "google/protobuf/empty.proto"; service Cache { - rpc PutImage(PutImageRequest) returns (google.protobuf.Empty); - rpc PutLayer(PutLayerRequest) returns (google.protobuf.Empty); - rpc MissingLayers(MissingLayersRequest) returns (MissingLayersResponse); + rpc PutArtifact(PutArtifactRequest) returns (google.protobuf.Empty); + rpc PutBlob(PutBlobRequest) returns (google.protobuf.Empty); + rpc MissingBlobs(MissingBlobsRequest) returns (MissingBlobsResponse); } -message ImageInfo { +message ArtifactInfo { int32 schema_version = 1; string architecture = 2; google.protobuf.Timestamp created = 3; @@ -22,12 +22,12 @@ message ImageInfo { repeated common.Package history_packages = 6; } -message PutImageRequest { - string image_id = 1; - ImageInfo image_info = 2; +message PutArtifactRequest { + string artifact_id = 1; + ArtifactInfo artifact_info = 2; } -message LayerInfo { +message BlobInfo { int32 schema_version = 1; common.OS os = 2; repeated common.PackageInfo package_infos = 3; @@ -38,9 +38,9 @@ message LayerInfo { string diff_id = 8; } -message PutLayerRequest { - string diff_id = 1; - LayerInfo layer_info = 3; +message PutBlobRequest { + string diff_id = 1; + BlobInfo blob_info = 3; } message PutResponse { @@ -48,12 +48,12 @@ message PutResponse { bool eosl = 2; } -message MissingLayersRequest { - string image_id = 1; - repeated string layer_ids = 2; +message MissingBlobsRequest { + string artifact_id = 1; + repeated string blob_ids = 2; } -message MissingLayersResponse { - bool missing_image = 1; - repeated string missing_layer_ids = 2; +message MissingBlobsResponse { + bool missing_artifact = 1; + repeated string missing_blob_ids = 2; } diff --git a/rpc/cache/service.twirp.go b/rpc/cache/service.twirp.go index 3d205ae251..78b7f90ed3 100644 --- a/rpc/cache/service.twirp.go +++ b/rpc/cache/service.twirp.go @@ -17,6 +17,7 @@ import fmt "fmt" import ioutil "io/ioutil" import http "net/http" import strconv "strconv" +import gzip "compress/gzip" import jsonpb "github.com/golang/protobuf/jsonpb" import proto "github.com/golang/protobuf/proto" @@ -30,16 +31,19 @@ import io "io" import json "encoding/json" import url "net/url" +// A response is compressed with gzip when the response size exceeds this threshold. +const CompressThreshold = 10000 + // =============== // Cache Interface // =============== type Cache interface { - PutImage(context.Context, *PutImageRequest) (*google_protobuf1.Empty, error) + PutArtifact(context.Context, *PutArtifactRequest) (*google_protobuf1.Empty, error) - PutLayer(context.Context, *PutLayerRequest) (*google_protobuf1.Empty, error) + PutBlob(context.Context, *PutBlobRequest) (*google_protobuf1.Empty, error) - MissingLayers(context.Context, *MissingLayersRequest) (*MissingLayersResponse, error) + MissingBlobs(context.Context, *MissingBlobsRequest) (*MissingBlobsResponse, error) } // ===================== @@ -66,9 +70,9 @@ func NewCacheProtobufClient(addr string, client HTTPClient, opts ...twirp.Client prefix := urlBase(addr) + CachePathPrefix urls := [3]string{ - prefix + "PutImage", - prefix + "PutLayer", - prefix + "MissingLayers", + prefix + "PutArtifact", + prefix + "PutBlob", + prefix + "MissingBlobs", } return &cacheProtobufClient{ @@ -78,10 +82,10 @@ func NewCacheProtobufClient(addr string, client HTTPClient, opts ...twirp.Client } } -func (c *cacheProtobufClient) PutImage(ctx context.Context, in *PutImageRequest) (*google_protobuf1.Empty, error) { +func (c *cacheProtobufClient) PutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf1.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "PutImage") + ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") out := new(google_protobuf1.Empty) err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { @@ -98,10 +102,10 @@ func (c *cacheProtobufClient) PutImage(ctx context.Context, in *PutImageRequest) return out, nil } -func (c *cacheProtobufClient) PutLayer(ctx context.Context, in *PutLayerRequest) (*google_protobuf1.Empty, error) { +func (c *cacheProtobufClient) PutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf1.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "PutLayer") + ctx = ctxsetters.WithMethodName(ctx, "PutBlob") out := new(google_protobuf1.Empty) err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { @@ -118,11 +122,11 @@ func (c *cacheProtobufClient) PutLayer(ctx context.Context, in *PutLayerRequest) return out, nil } -func (c *cacheProtobufClient) MissingLayers(ctx context.Context, in *MissingLayersRequest) (*MissingLayersResponse, error) { +func (c *cacheProtobufClient) MissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "MissingLayers") - out := new(MissingLayersResponse) + ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") + out := new(MissingBlobsResponse) err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) if err != nil { twerr, ok := err.(twirp.Error) @@ -162,9 +166,9 @@ func NewCacheJSONClient(addr string, client HTTPClient, opts ...twirp.ClientOpti prefix := urlBase(addr) + CachePathPrefix urls := [3]string{ - prefix + "PutImage", - prefix + "PutLayer", - prefix + "MissingLayers", + prefix + "PutArtifact", + prefix + "PutBlob", + prefix + "MissingBlobs", } return &cacheJSONClient{ @@ -174,10 +178,10 @@ func NewCacheJSONClient(addr string, client HTTPClient, opts ...twirp.ClientOpti } } -func (c *cacheJSONClient) PutImage(ctx context.Context, in *PutImageRequest) (*google_protobuf1.Empty, error) { +func (c *cacheJSONClient) PutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf1.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "PutImage") + ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") out := new(google_protobuf1.Empty) err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { @@ -194,10 +198,10 @@ func (c *cacheJSONClient) PutImage(ctx context.Context, in *PutImageRequest) (*g return out, nil } -func (c *cacheJSONClient) PutLayer(ctx context.Context, in *PutLayerRequest) (*google_protobuf1.Empty, error) { +func (c *cacheJSONClient) PutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf1.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "PutLayer") + ctx = ctxsetters.WithMethodName(ctx, "PutBlob") out := new(google_protobuf1.Empty) err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { @@ -214,11 +218,11 @@ func (c *cacheJSONClient) PutLayer(ctx context.Context, in *PutLayerRequest) (*g return out, nil } -func (c *cacheJSONClient) MissingLayers(ctx context.Context, in *MissingLayersRequest) (*MissingLayersResponse, error) { +func (c *cacheJSONClient) MissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") ctx = ctxsetters.WithServiceName(ctx, "Cache") - ctx = ctxsetters.WithMethodName(ctx, "MissingLayers") - out := new(MissingLayersResponse) + ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") + out := new(MissingBlobsResponse) err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) if err != nil { twerr, ok := err.(twirp.Error) @@ -282,14 +286,14 @@ func (s *cacheServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { } switch req.URL.Path { - case "/twirp/trivy.cache.v1.Cache/PutImage": - s.servePutImage(ctx, resp, req) + case "/twirp/trivy.cache.v1.Cache/PutArtifact": + s.servePutArtifact(ctx, resp, req) return - case "/twirp/trivy.cache.v1.Cache/PutLayer": - s.servePutLayer(ctx, resp, req) + case "/twirp/trivy.cache.v1.Cache/PutBlob": + s.servePutBlob(ctx, resp, req) return - case "/twirp/trivy.cache.v1.Cache/MissingLayers": - s.serveMissingLayers(ctx, resp, req) + case "/twirp/trivy.cache.v1.Cache/MissingBlobs": + s.serveMissingBlobs(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) @@ -299,7 +303,7 @@ func (s *cacheServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { } } -func (s *cacheServer) servePutImage(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutArtifact(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { @@ -307,9 +311,9 @@ func (s *cacheServer) servePutImage(ctx context.Context, resp http.ResponseWrite } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": - s.servePutImageJSON(ctx, resp, req) + s.servePutArtifactJSON(ctx, resp, req) case "application/protobuf": - s.servePutImageProtobuf(ctx, resp, req) + s.servePutArtifactProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) @@ -317,16 +321,16 @@ func (s *cacheServer) servePutImage(ctx context.Context, resp http.ResponseWrite } } -func (s *cacheServer) servePutImageJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutArtifactJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "PutImage") + ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } - reqContent := new(PutImageRequest) + reqContent := new(PutArtifactRequest) unmarshaler := jsonpb.Unmarshaler{AllowUnknownFields: true} if err = unmarshaler.Unmarshal(req.Body, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the json request could not be decoded")) @@ -337,7 +341,7 @@ func (s *cacheServer) servePutImageJSON(ctx context.Context, resp http.ResponseW var respContent *google_protobuf1.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.PutImage(ctx, reqContent) + respContent, err = s.Cache.PutArtifact(ctx, reqContent) }() if err != nil { @@ -345,7 +349,7 @@ func (s *cacheServer) servePutImageJSON(ctx context.Context, resp http.ResponseW return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutImage. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutArtifact. nil responses are not supported")) return } @@ -372,9 +376,9 @@ func (s *cacheServer) servePutImageJSON(ctx context.Context, resp http.ResponseW callResponseSent(ctx, s.hooks) } -func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutArtifactProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "PutImage") + ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) @@ -386,7 +390,7 @@ func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.Respo s.writeError(ctx, resp, wrapInternal(err, "failed to read request body")) return } - reqContent := new(PutImageRequest) + reqContent := new(PutArtifactRequest) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return @@ -396,7 +400,7 @@ func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.Respo var respContent *google_protobuf1.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.PutImage(ctx, reqContent) + respContent, err = s.Cache.PutArtifact(ctx, reqContent) }() if err != nil { @@ -404,7 +408,7 @@ func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.Respo return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutImage. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutArtifact. nil responses are not supported")) return } @@ -416,6 +420,16 @@ func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.Respo return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -428,7 +442,7 @@ func (s *cacheServer) servePutImageProtobuf(ctx context.Context, resp http.Respo callResponseSent(ctx, s.hooks) } -func (s *cacheServer) servePutLayer(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutBlob(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { @@ -436,9 +450,9 @@ func (s *cacheServer) servePutLayer(ctx context.Context, resp http.ResponseWrite } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": - s.servePutLayerJSON(ctx, resp, req) + s.servePutBlobJSON(ctx, resp, req) case "application/protobuf": - s.servePutLayerProtobuf(ctx, resp, req) + s.servePutBlobProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) @@ -446,16 +460,16 @@ func (s *cacheServer) servePutLayer(ctx context.Context, resp http.ResponseWrite } } -func (s *cacheServer) servePutLayerJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutBlobJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "PutLayer") + ctx = ctxsetters.WithMethodName(ctx, "PutBlob") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } - reqContent := new(PutLayerRequest) + reqContent := new(PutBlobRequest) unmarshaler := jsonpb.Unmarshaler{AllowUnknownFields: true} if err = unmarshaler.Unmarshal(req.Body, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the json request could not be decoded")) @@ -466,7 +480,7 @@ func (s *cacheServer) servePutLayerJSON(ctx context.Context, resp http.ResponseW var respContent *google_protobuf1.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.PutLayer(ctx, reqContent) + respContent, err = s.Cache.PutBlob(ctx, reqContent) }() if err != nil { @@ -474,7 +488,7 @@ func (s *cacheServer) servePutLayerJSON(ctx context.Context, resp http.ResponseW return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutLayer. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutBlob. nil responses are not supported")) return } @@ -501,9 +515,9 @@ func (s *cacheServer) servePutLayerJSON(ctx context.Context, resp http.ResponseW callResponseSent(ctx, s.hooks) } -func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) servePutBlobProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "PutLayer") + ctx = ctxsetters.WithMethodName(ctx, "PutBlob") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) @@ -515,7 +529,7 @@ func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.Respo s.writeError(ctx, resp, wrapInternal(err, "failed to read request body")) return } - reqContent := new(PutLayerRequest) + reqContent := new(PutBlobRequest) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return @@ -525,7 +539,7 @@ func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.Respo var respContent *google_protobuf1.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.PutLayer(ctx, reqContent) + respContent, err = s.Cache.PutBlob(ctx, reqContent) }() if err != nil { @@ -533,7 +547,7 @@ func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.Respo return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutLayer. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf1.Empty and nil error while calling PutBlob. nil responses are not supported")) return } @@ -545,6 +559,16 @@ func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.Respo return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -557,7 +581,7 @@ func (s *cacheServer) servePutLayerProtobuf(ctx context.Context, resp http.Respo callResponseSent(ctx, s.hooks) } -func (s *cacheServer) serveMissingLayers(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) serveMissingBlobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { @@ -565,9 +589,9 @@ func (s *cacheServer) serveMissingLayers(ctx context.Context, resp http.Response } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": - s.serveMissingLayersJSON(ctx, resp, req) + s.serveMissingBlobsJSON(ctx, resp, req) case "application/protobuf": - s.serveMissingLayersProtobuf(ctx, resp, req) + s.serveMissingBlobsProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) @@ -575,16 +599,16 @@ func (s *cacheServer) serveMissingLayers(ctx context.Context, resp http.Response } } -func (s *cacheServer) serveMissingLayersJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) serveMissingBlobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "MissingLayers") + ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } - reqContent := new(MissingLayersRequest) + reqContent := new(MissingBlobsRequest) unmarshaler := jsonpb.Unmarshaler{AllowUnknownFields: true} if err = unmarshaler.Unmarshal(req.Body, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the json request could not be decoded")) @@ -592,10 +616,10 @@ func (s *cacheServer) serveMissingLayersJSON(ctx context.Context, resp http.Resp } // Call service method - var respContent *MissingLayersResponse + var respContent *MissingBlobsResponse func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.MissingLayers(ctx, reqContent) + respContent, err = s.Cache.MissingBlobs(ctx, reqContent) }() if err != nil { @@ -603,7 +627,7 @@ func (s *cacheServer) serveMissingLayersJSON(ctx context.Context, resp http.Resp return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingLayersResponse and nil error while calling MissingLayers. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingBlobsResponse and nil error while calling MissingBlobs. nil responses are not supported")) return } @@ -630,9 +654,9 @@ func (s *cacheServer) serveMissingLayersJSON(ctx context.Context, resp http.Resp callResponseSent(ctx, s.hooks) } -func (s *cacheServer) serveMissingLayersProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { +func (s *cacheServer) serveMissingBlobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error - ctx = ctxsetters.WithMethodName(ctx, "MissingLayers") + ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) @@ -644,17 +668,17 @@ func (s *cacheServer) serveMissingLayersProtobuf(ctx context.Context, resp http. s.writeError(ctx, resp, wrapInternal(err, "failed to read request body")) return } - reqContent := new(MissingLayersRequest) + reqContent := new(MissingBlobsRequest) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } // Call service method - var respContent *MissingLayersResponse + var respContent *MissingBlobsResponse func() { defer ensurePanicResponses(ctx, resp, s.hooks) - respContent, err = s.Cache.MissingLayers(ctx, reqContent) + respContent, err = s.Cache.MissingBlobs(ctx, reqContent) }() if err != nil { @@ -662,7 +686,7 @@ func (s *cacheServer) serveMissingLayersProtobuf(ctx context.Context, resp http. return } if respContent == nil { - s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingLayersResponse and nil error while calling MissingLayers. nil responses are not supported")) + s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingBlobsResponse and nil error while calling MissingBlobs. nil responses are not supported")) return } @@ -674,6 +698,16 @@ func (s *cacheServer) serveMissingLayersProtobuf(ctx context.Context, resp http. return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -832,6 +866,7 @@ func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) + req.Header.Set("Accept-Encoding", "gzip") req.Header.Set("Twirp-Version", "v5.10.1") return req, nil } @@ -1084,7 +1119,15 @@ func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.Clie return errorFromResponse(resp) } - respBodyBytes, err := ioutil.ReadAll(resp.Body) + r := resp.Body + if resp.Header.Get("Content-Encoding") == "gzip" { + r, err = gzip.NewReader(r) + if err != nil { + return wrapInternal(err, "invalid gzip") + } + } + + respBodyBytes, err := ioutil.ReadAll(r) if err != nil { return wrapInternal(err, "failed to read response body") } @@ -1189,6 +1232,36 @@ func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) conte return h.Error(ctx, err) } +// compressWithGzip compresses the data with gzip +func compressWithGzip(data []byte) ([]byte, error) { + var b bytes.Buffer + gz := gzip.NewWriter(&b) + defer gz.Close() + + if _, err := gz.Write(data); err != nil { + return nil, err + } + + if err := gz.Flush(); err != nil { + return nil, err + } + + if err := gz.Close(); err != nil { + return nil, err + } + + return b.Bytes(), nil +} + +func isGZipAcceptable(request *http.Request) bool { + for _, encoding := range request.Header["Accept-Encoding"] { + if encoding == "gzip" { + return true + } + } + return false +} + func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return @@ -1211,48 +1284,48 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) } var twirpFileDescriptor0 = []byte{ - // 674 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xd3, 0x30, - 0x14, 0x56, 0xdb, 0x75, 0x6d, 0x4e, 0xdb, 0x6d, 0x58, 0x6c, 0xcb, 0xba, 0x8b, 0x55, 0x81, 0x49, - 0x15, 0x17, 0x89, 0x28, 0x08, 0x71, 0x03, 0x02, 0x06, 0x48, 0x95, 0xf8, 0x99, 0x0c, 0xe2, 0x02, - 0x21, 0x55, 0x5e, 0xe2, 0xa4, 0xd6, 0x9a, 0x38, 0xb3, 0x9d, 0xa2, 0x3e, 0x00, 0x6f, 0xc7, 0xbb, - 0xf0, 0x0a, 0x28, 0x27, 0xc9, 0xd6, 0x96, 0xf2, 0x77, 0xe7, 0xf3, 0x93, 0xef, 0x7c, 0xe7, 0xfb, - 0xec, 0xc0, 0xa1, 0x4a, 0x7d, 0xcf, 0x67, 0xfe, 0x94, 0x7b, 0x9a, 0xab, 0xb9, 0xf0, 0xb9, 0x9b, - 0x2a, 0x69, 0x24, 0xd9, 0x31, 0x4a, 0xcc, 0x17, 0x2e, 0x96, 0xdc, 0xf9, 0xfd, 0xfe, 0x49, 0x24, - 0x65, 0x34, 0xe3, 0x1e, 0x56, 0x2f, 0xb2, 0xd0, 0x33, 0x22, 0xe6, 0xda, 0xb0, 0x38, 0x2d, 0x3e, - 0xe8, 0x3f, 0x8a, 0x84, 0x99, 0x66, 0x17, 0xae, 0x2f, 0x63, 0x8f, 0x5d, 0x65, 0x4c, 0x73, 0x3f, - 0x53, 0xc2, 0x2c, 0x3c, 0x04, 0xf2, 0x70, 0x8e, 0x8c, 0x63, 0x99, 0xac, 0x0e, 0xea, 0x1f, 0xaf, - 0x03, 0xf3, 0x38, 0x35, 0x8b, 0xa2, 0xe8, 0x7c, 0xab, 0x83, 0x35, 0x8e, 0x59, 0xc4, 0xc7, 0x49, - 0x28, 0xc9, 0x29, 0xec, 0x68, 0x7f, 0xca, 0x63, 0x36, 0x99, 0x73, 0xa5, 0x85, 0x4c, 0xec, 0xda, - 0xa0, 0x36, 0x6c, 0xd2, 0x5e, 0x91, 0xfd, 0x54, 0x24, 0x89, 0x03, 0x5d, 0xa6, 0xfc, 0xa9, 0x30, - 0xdc, 0x37, 0x99, 0xe2, 0x76, 0x7d, 0x50, 0x1b, 0x5a, 0x74, 0x25, 0x47, 0x1e, 0x42, 0xcb, 0x57, - 0x9c, 0x19, 0x1e, 0xd8, 0x8d, 0x41, 0x6d, 0xd8, 0x19, 0xf5, 0xdd, 0x82, 0x87, 0x5b, 0xf1, 0x70, - 0x3f, 0x56, 0x0b, 0xd2, 0xaa, 0x35, 0x27, 0x10, 0x48, 0xff, 0x92, 0xab, 0x6b, 0x02, 0x5b, 0x88, - 0xdd, 0x2b, 0xb2, 0x15, 0x81, 0x1d, 0xa8, 0x4b, 0x6d, 0x37, 0xb1, 0x54, 0x97, 0x9a, 0x3c, 0x83, - 0xbd, 0xa9, 0xd0, 0x46, 0xaa, 0xc5, 0x24, 0x65, 0xfe, 0x25, 0x8b, 0xb8, 0xb6, 0xb7, 0x07, 0x8d, - 0x61, 0x67, 0xb4, 0xef, 0x96, 0x32, 0xa3, 0x32, 0xee, 0x79, 0x51, 0xa5, 0xbb, 0x65, 0x7b, 0x19, - 0x6b, 0x27, 0x84, 0xdd, 0xf3, 0xcc, 0xa0, 0x12, 0x94, 0x5f, 0x65, 0x5c, 0x1b, 0x72, 0x04, 0x6d, - 0x91, 0xc7, 0x13, 0x11, 0xa0, 0x0c, 0x16, 0x6d, 0x61, 0x3c, 0x0e, 0xc8, 0x63, 0x80, 0xb2, 0x94, - 0x84, 0x12, 0xd7, 0xef, 0x8c, 0x8e, 0xdc, 0x55, 0x43, 0xdd, 0x6b, 0x59, 0xa9, 0x25, 0xaa, 0xa3, - 0xf3, 0xbd, 0x0e, 0xd6, 0x1b, 0xb6, 0xe0, 0xea, 0x7f, 0xf4, 0x1e, 0xe0, 0xba, 0xc5, 0x98, 0xbd, - 0xd5, 0x85, 0xde, 0x7f, 0x40, 0x01, 0x9e, 0x42, 0xaf, 0x5c, 0x1c, 0x29, 0x69, 0xbb, 0x81, 0xdb, - 0x1f, 0x6d, 0xdc, 0x1e, 0x39, 0x75, 0xd3, 0x9b, 0x40, 0x93, 0x27, 0xd0, 0x65, 0x69, 0x3a, 0x13, - 0x3e, 0x33, 0x42, 0x26, 0xda, 0xde, 0xda, 0xf4, 0xf9, 0xf3, 0x9b, 0x0e, 0xba, 0xd2, 0x4e, 0x4e, - 0xa0, 0x23, 0x53, 0x76, 0x95, 0xf1, 0x49, 0x20, 0x54, 0x6e, 0x4c, 0x63, 0x68, 0x51, 0x28, 0x52, - 0x2f, 0x85, 0xd2, 0xf9, 0xa2, 0x5f, 0xf3, 0xbb, 0x21, 0x33, 0x33, 0x09, 0xc5, 0xac, 0xb4, 0xc7, - 0xa2, 0xbd, 0x2a, 0xfb, 0x3a, 0x4f, 0x92, 0x03, 0xd8, 0x0e, 0x44, 0xc4, 0xb5, 0xb1, 0x5b, 0x28, - 0x78, 0x19, 0x91, 0x43, 0x68, 0x05, 0x22, 0x0c, 0x73, 0x27, 0xda, 0x55, 0x21, 0x0c, 0xc7, 0x81, - 0x13, 0xa0, 0x6d, 0x28, 0x68, 0x65, 0xdb, 0x52, 0x6f, 0x6d, 0xb9, 0x37, 0x37, 0x6d, 0x96, 0x37, - 0x16, 0xa6, 0x35, 0x36, 0x9b, 0x76, 0xed, 0x0d, 0xb5, 0x66, 0xd5, 0xd1, 0x39, 0x83, 0xce, 0x79, - 0x66, 0x28, 0xd7, 0xa9, 0x4c, 0x34, 0x2f, 0xed, 0xa8, 0xfd, 0xc1, 0x0e, 0x02, 0x5b, 0x5c, 0xea, - 0x19, 0x5a, 0xd6, 0xa6, 0x78, 0x76, 0xde, 0xc1, 0xed, 0xb7, 0x42, 0x6b, 0x91, 0x44, 0x38, 0x43, - 0xff, 0xc3, 0x35, 0x3b, 0x06, 0xab, 0x64, 0x1c, 0xe4, 0xf6, 0xe7, 0x82, 0xb5, 0x0b, 0x56, 0x81, - 0x76, 0xa6, 0xb0, 0xbf, 0x86, 0x57, 0xd2, 0xbb, 0x03, 0xbd, 0xb8, 0x28, 0x4c, 0x10, 0x08, 0x51, - 0xdb, 0xb4, 0x5b, 0x26, 0xf1, 0x5a, 0x92, 0x7b, 0x70, 0xab, 0x6a, 0x5a, 0x1f, 0xb1, 0x1b, 0x2f, - 0xc1, 0x8e, 0x03, 0x3d, 0xfa, 0x51, 0x83, 0xe6, 0x59, 0x2e, 0x10, 0x39, 0x83, 0x76, 0xf5, 0x4a, - 0xc8, 0xc9, 0xba, 0x74, 0x6b, 0xef, 0xa7, 0x7f, 0xf0, 0xcb, 0x83, 0x7f, 0x95, 0xff, 0x78, 0x4a, - 0x10, 0x44, 0xdf, 0x08, 0xb2, 0xec, 0xe6, 0x6f, 0x41, 0xbe, 0x40, 0x6f, 0x65, 0x7b, 0x72, 0x77, - 0x1d, 0x69, 0x93, 0xd8, 0xfd, 0xd3, 0xbf, 0x74, 0x15, 0x12, 0xbe, 0x68, 0x7d, 0x6e, 0x62, 0xc7, - 0xc5, 0x36, 0x8e, 0x7d, 0xf0, 0x33, 0x00, 0x00, 0xff, 0xff, 0x08, 0x8d, 0x6f, 0x9e, 0xc6, 0x05, - 0x00, 0x00, + // 682 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdd, 0x6e, 0xd3, 0x3e, + 0x18, 0xc6, 0xd5, 0x76, 0x5d, 0xdb, 0xb7, 0x1f, 0x9b, 0xfc, 0xff, 0xb3, 0x65, 0x05, 0xb1, 0x2a, + 0x80, 0x54, 0x4e, 0x52, 0x51, 0x3e, 0xce, 0x40, 0x74, 0x03, 0xa4, 0x1e, 0x20, 0x4a, 0x40, 0x48, + 0x70, 0x52, 0x5c, 0xc7, 0x69, 0xad, 0x35, 0x71, 0x66, 0x3b, 0x85, 0xde, 0x01, 0xf7, 0xc6, 0xcd, + 0x70, 0x09, 0xc8, 0x76, 0xb2, 0x7e, 0xac, 0x4c, 0x70, 0x16, 0x3f, 0x7e, 0xf3, 0xbc, 0xaf, 0x7f, + 0x8f, 0x13, 0x38, 0x16, 0x09, 0xe9, 0x11, 0x4c, 0x66, 0xb4, 0x27, 0xa9, 0x58, 0x30, 0x42, 0xbd, + 0x44, 0x70, 0xc5, 0x51, 0x4b, 0x09, 0xb6, 0x58, 0x7a, 0x66, 0xcb, 0x5b, 0x3c, 0x6a, 0x9f, 0x4e, + 0x39, 0x9f, 0xce, 0x69, 0xcf, 0xec, 0x4e, 0xd2, 0xb0, 0xa7, 0x58, 0x44, 0xa5, 0xc2, 0x51, 0x62, + 0x5f, 0x68, 0x3f, 0x9b, 0x32, 0x35, 0x4b, 0x27, 0x1e, 0xe1, 0x51, 0x0f, 0x5f, 0xa6, 0x58, 0x52, + 0x92, 0x0a, 0xa6, 0x96, 0x3d, 0x63, 0xd4, 0x33, 0x7d, 0x78, 0x14, 0xf1, 0x78, 0xb3, 0x51, 0xfb, + 0xf6, 0xb6, 0x31, 0x8d, 0x12, 0xb5, 0xb4, 0x9b, 0xee, 0x8f, 0x22, 0x34, 0x06, 0x42, 0xb1, 0x10, + 0x13, 0x35, 0x8c, 0x43, 0x8e, 0x1e, 0x40, 0x4b, 0x92, 0x19, 0x8d, 0xf0, 0x78, 0x41, 0x85, 0x64, + 0x3c, 0x76, 0x0a, 0x9d, 0x42, 0xb7, 0xec, 0x37, 0xad, 0xfa, 0xc9, 0x8a, 0xc8, 0x85, 0x06, 0x16, + 0x64, 0xc6, 0x14, 0x25, 0x2a, 0x15, 0xd4, 0x29, 0x76, 0x0a, 0xdd, 0x9a, 0xbf, 0xa1, 0xa1, 0x27, + 0x50, 0x21, 0x82, 0x62, 0x45, 0x03, 0xa7, 0xd4, 0x29, 0x74, 0xeb, 0xfd, 0xb6, 0x67, 0x47, 0xf1, + 0xf2, 0x51, 0xbc, 0x8f, 0xf9, 0x19, 0xfd, 0xbc, 0x54, 0x0f, 0x10, 0x70, 0x72, 0x41, 0xc5, 0xd5, + 0x00, 0x7b, 0xc6, 0xbb, 0x69, 0xd5, 0x7c, 0x80, 0x16, 0x14, 0xb9, 0x74, 0xca, 0x66, 0xab, 0xc8, + 0x25, 0x7a, 0x09, 0x87, 0x33, 0x26, 0x15, 0x17, 0xcb, 0x71, 0x82, 0xc9, 0x05, 0x9e, 0x52, 0xe9, + 0xec, 0x77, 0x4a, 0xdd, 0x7a, 0xff, 0x96, 0x97, 0x91, 0x36, 0x70, 0xbc, 0x91, 0xdd, 0xf5, 0x0f, + 0xb2, 0xf2, 0x6c, 0x2d, 0xdd, 0xef, 0x80, 0x46, 0xa9, 0xca, 0x61, 0xf8, 0xf4, 0x32, 0xa5, 0x52, + 0xa1, 0x53, 0xa8, 0xe3, 0x4c, 0x1a, 0xb3, 0xc0, 0xc0, 0xa8, 0xf9, 0x90, 0x4b, 0xc3, 0x00, 0x0d, + 0xa0, 0xb9, 0x2a, 0x88, 0x43, 0x6e, 0x50, 0xd4, 0xfb, 0x77, 0xbc, 0xcd, 0x7c, 0xbd, 0x75, 0xca, + 0x1a, 0xd4, 0x6a, 0xe5, 0xfe, 0x2c, 0x42, 0xf5, 0x6c, 0xce, 0x27, 0xff, 0x12, 0x40, 0xc7, 0x9c, + 0xdf, 0xf6, 0x3a, 0xdc, 0x3c, 0xe1, 0xbb, 0x0f, 0x86, 0xc8, 0x0b, 0x68, 0x66, 0x24, 0xcc, 0x5c, + 0xd2, 0x29, 0x19, 0x1c, 0x27, 0x3b, 0x71, 0xd8, 0xa9, 0x92, 0xd5, 0x42, 0xa2, 0xe7, 0xd0, 0xc0, + 0x49, 0x32, 0x67, 0x04, 0x2b, 0xc6, 0x63, 0xe9, 0xec, 0xed, 0x7a, 0x7d, 0xb0, 0xaa, 0xf0, 0x37, + 0xca, 0x35, 0x38, 0x9e, 0xe0, 0xcb, 0x94, 0x8e, 0x03, 0x26, 0x74, 0x52, 0x25, 0x0d, 0xce, 0x4a, + 0xaf, 0x98, 0x90, 0xfa, 0xa0, 0xdf, 0xf4, 0x65, 0xe1, 0xa9, 0x1a, 0x87, 0x6c, 0x9e, 0xe5, 0x55, + 0xf3, 0x9b, 0xb9, 0xfa, 0x46, 0x8b, 0xe8, 0x08, 0xf6, 0x03, 0x36, 0xa5, 0x52, 0x39, 0x15, 0xc3, + 0x3e, 0x5b, 0xa1, 0x63, 0xa8, 0x04, 0x2c, 0x0c, 0x75, 0x28, 0xd5, 0x7c, 0x23, 0x0c, 0x87, 0x81, + 0xfb, 0x15, 0x5a, 0xa3, 0x54, 0x69, 0x9e, 0x79, 0x86, 0x6b, 0xa5, 0x85, 0xf5, 0x52, 0xf4, 0x14, + 0x6a, 0x93, 0x39, 0x9f, 0xd8, 0xdc, 0xec, 0x1d, 0x75, 0xb6, 0x73, 0xcb, 0x83, 0xf1, 0xab, 0x93, + 0xec, 0xc9, 0x3d, 0x87, 0xfa, 0x28, 0x55, 0x3e, 0x95, 0x09, 0x8f, 0x25, 0xcd, 0xa2, 0x28, 0xdc, + 0x10, 0x05, 0x82, 0x3d, 0xca, 0xe5, 0xdc, 0xc4, 0x55, 0xf5, 0xcd, 0xb3, 0xfb, 0x1e, 0xfe, 0x7b, + 0xcb, 0xa4, 0x64, 0xf1, 0x54, 0x77, 0x90, 0x7f, 0x7d, 0xdf, 0x4e, 0xa0, 0x6a, 0x67, 0x0e, 0x74, + 0xfc, 0x1a, 0x58, 0xc5, 0x0c, 0x16, 0x48, 0xf7, 0x02, 0xfe, 0xdf, 0xb4, 0xcc, 0x06, 0x7c, 0x08, + 0x87, 0x91, 0xd5, 0xc7, 0xb9, 0x91, 0x31, 0xae, 0xfa, 0x07, 0x99, 0x9e, 0x5f, 0x4e, 0xd4, 0x5d, + 0x95, 0x6e, 0x75, 0x69, 0x45, 0x2b, 0xeb, 0x61, 0x20, 0xfb, 0xbf, 0x0a, 0x50, 0x3e, 0xd7, 0x90, + 0xd0, 0xd0, 0xe0, 0xb8, 0xb2, 0x70, 0xb7, 0x09, 0x5e, 0xff, 0xaa, 0xda, 0x47, 0xd7, 0xfe, 0x04, + 0xaf, 0xf5, 0x4f, 0x09, 0x0d, 0xa0, 0x92, 0x65, 0x87, 0xee, 0xee, 0xb0, 0x59, 0x0b, 0xf5, 0x8f, + 0x16, 0x9f, 0xa1, 0xb1, 0x0e, 0x01, 0xdd, 0xdb, 0xf6, 0xd9, 0x41, 0xbd, 0x7d, 0xff, 0xe6, 0x22, + 0xcb, 0xf1, 0xac, 0xf2, 0xa5, 0x6c, 0x0a, 0x26, 0xfb, 0xa6, 0xe7, 0xe3, 0xdf, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xf9, 0x1a, 0xc0, 0xa0, 0xdd, 0x05, 0x00, 0x00, } diff --git a/rpc/detector/service.twirp.go b/rpc/detector/service.twirp.go index 5accf05a6a..1e8e7e9e30 100644 --- a/rpc/detector/service.twirp.go +++ b/rpc/detector/service.twirp.go @@ -17,6 +17,7 @@ import fmt "fmt" import ioutil "io/ioutil" import http "net/http" import strconv "strconv" +import gzip "compress/gzip" import jsonpb "github.com/golang/protobuf/jsonpb" import proto "github.com/golang/protobuf/proto" @@ -28,6 +29,9 @@ import io "io" import json "encoding/json" import url "net/url" +// A response is compressed with gzip when the response size exceeds this threshold. +const CompressThreshold = 10000 + // ==================== // OSDetector Interface // ==================== @@ -320,6 +324,16 @@ func (s *oSDetectorServer) serveDetectProtobuf(ctx context.Context, resp http.Re return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -636,6 +650,16 @@ func (s *libDetectorServer) serveDetectProtobuf(ctx context.Context, resp http.R return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -794,6 +818,7 @@ func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) + req.Header.Set("Accept-Encoding", "gzip") req.Header.Set("Twirp-Version", "v5.10.1") return req, nil } @@ -1046,7 +1071,15 @@ func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.Clie return errorFromResponse(resp) } - respBodyBytes, err := ioutil.ReadAll(resp.Body) + r := resp.Body + if resp.Header.Get("Content-Encoding") == "gzip" { + r, err = gzip.NewReader(r) + if err != nil { + return wrapInternal(err, "invalid gzip") + } + } + + respBodyBytes, err := ioutil.ReadAll(r) if err != nil { return wrapInternal(err, "failed to read response body") } @@ -1151,6 +1184,36 @@ func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) conte return h.Error(ctx, err) } +// compressWithGzip compresses the data with gzip +func compressWithGzip(data []byte) ([]byte, error) { + var b bytes.Buffer + gz := gzip.NewWriter(&b) + defer gz.Close() + + if _, err := gz.Write(data); err != nil { + return nil, err + } + + if err := gz.Flush(); err != nil { + return nil, err + } + + if err := gz.Close(); err != nil { + return nil, err + } + + return b.Bytes(), nil +} + +func isGZipAcceptable(request *http.Request) bool { + for _, encoding := range request.Header["Accept-Encoding"] { + if encoding == "gzip" { + return true + } + } + return false +} + func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return diff --git a/rpc/scanner/service.pb.go b/rpc/scanner/service.pb.go index 2e699d13d1..31a9b7a4f0 100644 --- a/rpc/scanner/service.pb.go +++ b/rpc/scanner/service.pb.go @@ -23,8 +23,8 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type ScanRequest struct { Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` - ImageId string `protobuf:"bytes,2,opt,name=image_id,json=imageId,proto3" json:"image_id,omitempty"` - LayerIds []string `protobuf:"bytes,3,rep,name=layer_ids,json=layerIds,proto3" json:"layer_ids,omitempty"` + ArtifactId string `protobuf:"bytes,2,opt,name=artifact_id,json=artifactId,proto3" json:"artifact_id,omitempty"` + BlobIds []string `protobuf:"bytes,3,rep,name=blob_ids,json=blobIds,proto3" json:"blob_ids,omitempty"` Options *ScanOptions `protobuf:"bytes,4,opt,name=options,proto3" json:"options,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -63,16 +63,16 @@ func (m *ScanRequest) GetTarget() string { return "" } -func (m *ScanRequest) GetImageId() string { +func (m *ScanRequest) GetArtifactId() string { if m != nil { - return m.ImageId + return m.ArtifactId } return "" } -func (m *ScanRequest) GetLayerIds() []string { +func (m *ScanRequest) GetBlobIds() []string { if m != nil { - return m.LayerIds + return m.BlobIds } return nil } @@ -244,28 +244,29 @@ func init() { func init() { proto.RegisterFile("rpc/scanner/service.proto", fileDescriptor_60d0e837512b18d4) } var fileDescriptor_60d0e837512b18d4 = []byte{ - // 367 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x4d, 0x6b, 0x83, 0x30, - 0x18, 0x46, 0x5b, 0x6a, 0x8d, 0x83, 0x95, 0x1c, 0x86, 0x6d, 0xd9, 0x10, 0x4f, 0x65, 0x07, 0x65, - 0x0e, 0xb6, 0xfb, 0xa0, 0x87, 0x9e, 0x3a, 0xd2, 0xb1, 0xc3, 0x2e, 0x25, 0xd5, 0x97, 0x2e, 0xa0, - 0xc6, 0x26, 0x51, 0x26, 0xfb, 0x1f, 0xfb, 0xbd, 0xc3, 0xc4, 0xc2, 0xda, 0xd1, 0xdb, 0xfb, 0xf1, - 0xf8, 0x7c, 0xbc, 0x06, 0x4d, 0x45, 0x95, 0xc6, 0x32, 0xa5, 0x65, 0x09, 0x22, 0x96, 0x20, 0x1a, - 0x96, 0x42, 0x54, 0x09, 0xae, 0x38, 0x9e, 0x28, 0xc1, 0x9a, 0x36, 0xea, 0x97, 0x51, 0xf3, 0x30, - 0x7b, 0xda, 0x33, 0xf5, 0x59, 0xef, 0xa2, 0x94, 0x17, 0x31, 0x3d, 0xd4, 0x54, 0x42, 0x5a, 0x0b, - 0xa6, 0xda, 0x58, 0x23, 0xe3, 0x8e, 0x2a, 0xe5, 0x45, 0xc1, 0xcb, 0x53, 0xa6, 0xf0, 0xc7, 0x42, - 0xde, 0x26, 0xa5, 0x25, 0x81, 0x43, 0x0d, 0x52, 0xe1, 0x1b, 0x34, 0x52, 0x54, 0xec, 0x41, 0xf9, - 0x56, 0x60, 0x2d, 0x5c, 0xd2, 0x77, 0x78, 0x8a, 0xc6, 0xac, 0xa0, 0x7b, 0xd8, 0xb2, 0xcc, 0xb7, - 0xf5, 0xc6, 0xd1, 0xfd, 0x2a, 0xc3, 0x73, 0xe4, 0xe6, 0xb4, 0x05, 0xb1, 0x65, 0x99, 0xf4, 0x07, - 0xc1, 0x60, 0xe1, 0x92, 0xb1, 0x1e, 0xac, 0x32, 0x89, 0x9f, 0x91, 0xc3, 0x2b, 0xc5, 0x78, 0x29, - 0xfd, 0x61, 0x60, 0x2d, 0xbc, 0xe4, 0x36, 0x3a, 0xf7, 0x1e, 0x75, 0xfa, 0x6b, 0x03, 0x22, 0x47, - 0x74, 0x78, 0x6f, 0x7c, 0xf5, 0xf3, 0x4e, 0xa4, 0xa9, 0xf3, 0x72, 0xab, 0xda, 0x0a, 0x7c, 0xcb, - 0x88, 0x74, 0x83, 0xb7, 0xb6, 0x82, 0xf0, 0x0b, 0x5d, 0x99, 0x0c, 0xb2, 0xe2, 0xa5, 0x04, 0x1c, - 0x20, 0x9b, 0x4b, 0x1d, 0xc0, 0x4b, 0x26, 0xbd, 0x9e, 0x49, 0x1f, 0xad, 0x37, 0xc4, 0xe6, 0x12, - 0x63, 0x34, 0x04, 0x2e, 0x73, 0x1d, 0x65, 0x4c, 0x74, 0x8d, 0x13, 0xe4, 0x08, 0x90, 0x75, 0xae, - 0x4c, 0x0a, 0x2f, 0xf1, 0xff, 0x5b, 0x25, 0x1a, 0x40, 0x8e, 0xc0, 0xf0, 0x1b, 0x8d, 0xcc, 0xe8, - 0xe2, 0xe1, 0x96, 0xe8, 0xba, 0xf3, 0x09, 0x82, 0xee, 0x58, 0xce, 0x14, 0x03, 0xe9, 0xdb, 0x9a, - 0x7d, 0x7e, 0x6a, 0xec, 0xfd, 0x0f, 0xa8, 0x25, 0xe7, 0xdf, 0x74, 0x86, 0x75, 0xf4, 0x81, 0x26, - 0xd7, 0x75, 0xf2, 0x8a, 0x9c, 0x8d, 0xb1, 0x86, 0x97, 0x68, 0xd8, 0x95, 0xf8, 0xc2, 0x75, 0xfb, - 0xbf, 0x3b, 0xbb, 0xbb, 0xb4, 0x36, 0x87, 0x7b, 0x71, 0x3f, 0x9c, 0x7e, 0xb5, 0x1b, 0xe9, 0xf7, - 0xf1, 0xf8, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xfb, 0xa8, 0xd9, 0x86, 0x02, 0x00, 0x00, + // 377 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6b, 0xdb, 0x30, + 0x14, 0xc6, 0xb1, 0x13, 0xe2, 0xf8, 0x79, 0xb0, 0xa0, 0xc3, 0x70, 0x12, 0xb6, 0x19, 0x9f, 0xc2, + 0x0e, 0x36, 0xf3, 0x60, 0xbb, 0x0f, 0x72, 0xc8, 0x29, 0x45, 0x29, 0x3d, 0xf4, 0x12, 0x64, 0x59, + 0x4d, 0x05, 0x8e, 0xe5, 0x48, 0xb2, 0xa9, 0xe9, 0x7f, 0xd2, 0xbf, 0xb6, 0x58, 0x72, 0xa0, 0x49, + 0xc9, 0xed, 0xe9, 0xbd, 0xcf, 0x4f, 0xbf, 0xef, 0xb3, 0x60, 0x2e, 0x6b, 0x9a, 0x2a, 0x4a, 0xaa, + 0x8a, 0xc9, 0x54, 0x31, 0xd9, 0x72, 0xca, 0x92, 0x5a, 0x0a, 0x2d, 0xd0, 0x4c, 0x4b, 0xde, 0x76, + 0xc9, 0x30, 0x4c, 0xda, 0xdf, 0x8b, 0xbf, 0x07, 0xae, 0x9f, 0x9b, 0x3c, 0xa1, 0xe2, 0x98, 0x92, + 0x53, 0x43, 0x14, 0xa3, 0x8d, 0xe4, 0xba, 0x4b, 0x8d, 0x32, 0xed, 0x57, 0x51, 0x71, 0x3c, 0x8a, + 0xea, 0x72, 0x53, 0xfc, 0xe6, 0x40, 0xb0, 0xa3, 0xa4, 0xc2, 0xec, 0xd4, 0x30, 0xa5, 0xd1, 0x37, + 0x98, 0x68, 0x22, 0x0f, 0x4c, 0x87, 0x4e, 0xe4, 0xac, 0x7c, 0x3c, 0x9c, 0xd0, 0x4f, 0x08, 0x88, + 0xd4, 0xfc, 0x89, 0x50, 0xbd, 0xe7, 0x45, 0xe8, 0x9a, 0x21, 0x9c, 0x5b, 0x9b, 0x02, 0xcd, 0x61, + 0x9a, 0x97, 0x22, 0xdf, 0xf3, 0x42, 0x85, 0xa3, 0x68, 0xb4, 0xf2, 0xb1, 0xd7, 0x9f, 0x37, 0x85, + 0x42, 0xff, 0xc0, 0x13, 0xb5, 0xe6, 0xa2, 0x52, 0xe1, 0x38, 0x72, 0x56, 0x41, 0xf6, 0x3d, 0xb9, + 0xe6, 0x4f, 0x7a, 0x86, 0xad, 0x15, 0xe1, 0xb3, 0x3a, 0xfe, 0x65, 0xd9, 0x86, 0x3e, 0x5a, 0x82, + 0xdf, 0x36, 0x65, 0xb5, 0xd7, 0x5d, 0xcd, 0x42, 0xc7, 0xdc, 0x31, 0xed, 0x1b, 0xf7, 0x5d, 0xcd, + 0xe2, 0x17, 0xf8, 0x62, 0x7d, 0xa8, 0x5a, 0x54, 0x8a, 0xa1, 0x08, 0x5c, 0xa1, 0x8c, 0x89, 0x20, + 0x9b, 0x0d, 0xf7, 0xd9, 0x04, 0x92, 0xed, 0x0e, 0xbb, 0x42, 0x21, 0x04, 0x63, 0x26, 0x54, 0x69, + 0xbc, 0x4c, 0xb1, 0xa9, 0x51, 0x06, 0x9e, 0x64, 0xaa, 0x29, 0xb5, 0x35, 0x11, 0x64, 0xe1, 0x67, + 0x54, 0x6c, 0x04, 0xf8, 0x2c, 0x8c, 0x5f, 0x61, 0x62, 0x5b, 0x37, 0xc3, 0x5b, 0xc3, 0xd7, 0x9e, + 0x93, 0x49, 0x92, 0xf3, 0x92, 0x6b, 0xce, 0x54, 0xe8, 0x9a, 0xed, 0xcb, 0x4b, 0xb0, 0x87, 0x0f, + 0xa2, 0x0e, 0x5f, 0x7f, 0xd3, 0x03, 0x1b, 0xeb, 0x23, 0xb3, 0xdc, 0xd4, 0xd9, 0x1d, 0x78, 0x3b, + 0x8b, 0x86, 0xd6, 0x30, 0xee, 0x4b, 0x74, 0x23, 0xdd, 0xe1, 0x0f, 0x2f, 0x7e, 0xdc, 0x1a, 0xdb, + 0xe0, 0xfe, 0xfb, 0x8f, 0xde, 0x30, 0xca, 0x27, 0xe6, 0x8d, 0xfc, 0x79, 0x0f, 0x00, 0x00, 0xff, + 0xff, 0xdf, 0x43, 0x89, 0x65, 0x8a, 0x02, 0x00, 0x00, } diff --git a/rpc/scanner/service.proto b/rpc/scanner/service.proto index 24e695822f..40d7181b6a 100644 --- a/rpc/scanner/service.proto +++ b/rpc/scanner/service.proto @@ -10,10 +10,10 @@ service Scanner { } message ScanRequest { - string target = 1; // image name or tar file path - string image_id = 2; - repeated string layer_ids = 3; - ScanOptions options = 4; + string target = 1; // image name or tar file path + string artifact_id = 2; + repeated string blob_ids = 3; + ScanOptions options = 4; } message ScanOptions { diff --git a/rpc/scanner/service.twirp.go b/rpc/scanner/service.twirp.go index 1d527d2249..2e0618268a 100644 --- a/rpc/scanner/service.twirp.go +++ b/rpc/scanner/service.twirp.go @@ -17,6 +17,7 @@ import fmt "fmt" import ioutil "io/ioutil" import http "net/http" import strconv "strconv" +import gzip "compress/gzip" import jsonpb "github.com/golang/protobuf/jsonpb" import proto "github.com/golang/protobuf/proto" @@ -28,6 +29,9 @@ import io "io" import json "encoding/json" import url "net/url" +// A response is compressed with gzip when the response size exceeds this threshold. +const CompressThreshold = 10000 + // ================= // Scanner Interface // ================= @@ -320,6 +324,16 @@ func (s *scannerServer) serveScanProtobuf(ctx context.Context, resp http.Respons return } + // Compress the response if the size exceeds the threshold + if len(respBytes) > CompressThreshold && isGZipAcceptable(req) { + respBytes, err = compressWithGzip(respBytes) + if err != nil { + s.writeError(ctx, resp, wrapInternal(err, "failed to compress response")) + return + } + resp.Header().Set("Content-Encoding", "gzip") + } + ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) @@ -478,6 +492,7 @@ func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) + req.Header.Set("Accept-Encoding", "gzip") req.Header.Set("Twirp-Version", "v5.10.1") return req, nil } @@ -730,7 +745,15 @@ func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.Clie return errorFromResponse(resp) } - respBodyBytes, err := ioutil.ReadAll(resp.Body) + r := resp.Body + if resp.Header.Get("Content-Encoding") == "gzip" { + r, err = gzip.NewReader(r) + if err != nil { + return wrapInternal(err, "invalid gzip") + } + } + + respBodyBytes, err := ioutil.ReadAll(r) if err != nil { return wrapInternal(err, "failed to read response body") } @@ -835,6 +858,36 @@ func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) conte return h.Error(ctx, err) } +// compressWithGzip compresses the data with gzip +func compressWithGzip(data []byte) ([]byte, error) { + var b bytes.Buffer + gz := gzip.NewWriter(&b) + defer gz.Close() + + if _, err := gz.Write(data); err != nil { + return nil, err + } + + if err := gz.Flush(); err != nil { + return nil, err + } + + if err := gz.Close(); err != nil { + return nil, err + } + + return b.Bytes(), nil +} + +func isGZipAcceptable(request *http.Request) bool { + for _, encoding := range request.Header["Accept-Encoding"] { + if encoding == "gzip" { + return true + } + } + return false +} + func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return @@ -857,28 +910,29 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) } var twirpFileDescriptor0 = []byte{ - // 367 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x4d, 0x6b, 0x83, 0x30, - 0x18, 0x46, 0x5b, 0x6a, 0x8d, 0x83, 0x95, 0x1c, 0x86, 0x6d, 0xd9, 0x10, 0x4f, 0x65, 0x07, 0x65, - 0x0e, 0xb6, 0xfb, 0xa0, 0x87, 0x9e, 0x3a, 0xd2, 0xb1, 0xc3, 0x2e, 0x25, 0xd5, 0x97, 0x2e, 0xa0, - 0xc6, 0x26, 0x51, 0x26, 0xfb, 0x1f, 0xfb, 0xbd, 0xc3, 0xc4, 0xc2, 0xda, 0xd1, 0xdb, 0xfb, 0xf1, - 0xf8, 0x7c, 0xbc, 0x06, 0x4d, 0x45, 0x95, 0xc6, 0x32, 0xa5, 0x65, 0x09, 0x22, 0x96, 0x20, 0x1a, - 0x96, 0x42, 0x54, 0x09, 0xae, 0x38, 0x9e, 0x28, 0xc1, 0x9a, 0x36, 0xea, 0x97, 0x51, 0xf3, 0x30, - 0x7b, 0xda, 0x33, 0xf5, 0x59, 0xef, 0xa2, 0x94, 0x17, 0x31, 0x3d, 0xd4, 0x54, 0x42, 0x5a, 0x0b, - 0xa6, 0xda, 0x58, 0x23, 0xe3, 0x8e, 0x2a, 0xe5, 0x45, 0xc1, 0xcb, 0x53, 0xa6, 0xf0, 0xc7, 0x42, - 0xde, 0x26, 0xa5, 0x25, 0x81, 0x43, 0x0d, 0x52, 0xe1, 0x1b, 0x34, 0x52, 0x54, 0xec, 0x41, 0xf9, - 0x56, 0x60, 0x2d, 0x5c, 0xd2, 0x77, 0x78, 0x8a, 0xc6, 0xac, 0xa0, 0x7b, 0xd8, 0xb2, 0xcc, 0xb7, - 0xf5, 0xc6, 0xd1, 0xfd, 0x2a, 0xc3, 0x73, 0xe4, 0xe6, 0xb4, 0x05, 0xb1, 0x65, 0x99, 0xf4, 0x07, - 0xc1, 0x60, 0xe1, 0x92, 0xb1, 0x1e, 0xac, 0x32, 0x89, 0x9f, 0x91, 0xc3, 0x2b, 0xc5, 0x78, 0x29, - 0xfd, 0x61, 0x60, 0x2d, 0xbc, 0xe4, 0x36, 0x3a, 0xf7, 0x1e, 0x75, 0xfa, 0x6b, 0x03, 0x22, 0x47, - 0x74, 0x78, 0x6f, 0x7c, 0xf5, 0xf3, 0x4e, 0xa4, 0xa9, 0xf3, 0x72, 0xab, 0xda, 0x0a, 0x7c, 0xcb, - 0x88, 0x74, 0x83, 0xb7, 0xb6, 0x82, 0xf0, 0x0b, 0x5d, 0x99, 0x0c, 0xb2, 0xe2, 0xa5, 0x04, 0x1c, - 0x20, 0x9b, 0x4b, 0x1d, 0xc0, 0x4b, 0x26, 0xbd, 0x9e, 0x49, 0x1f, 0xad, 0x37, 0xc4, 0xe6, 0x12, - 0x63, 0x34, 0x04, 0x2e, 0x73, 0x1d, 0x65, 0x4c, 0x74, 0x8d, 0x13, 0xe4, 0x08, 0x90, 0x75, 0xae, - 0x4c, 0x0a, 0x2f, 0xf1, 0xff, 0x5b, 0x25, 0x1a, 0x40, 0x8e, 0xc0, 0xf0, 0x1b, 0x8d, 0xcc, 0xe8, - 0xe2, 0xe1, 0x96, 0xe8, 0xba, 0xf3, 0x09, 0x82, 0xee, 0x58, 0xce, 0x14, 0x03, 0xe9, 0xdb, 0x9a, - 0x7d, 0x7e, 0x6a, 0xec, 0xfd, 0x0f, 0xa8, 0x25, 0xe7, 0xdf, 0x74, 0x86, 0x75, 0xf4, 0x81, 0x26, - 0xd7, 0x75, 0xf2, 0x8a, 0x9c, 0x8d, 0xb1, 0x86, 0x97, 0x68, 0xd8, 0x95, 0xf8, 0xc2, 0x75, 0xfb, - 0xbf, 0x3b, 0xbb, 0xbb, 0xb4, 0x36, 0x87, 0x7b, 0x71, 0x3f, 0x9c, 0x7e, 0xb5, 0x1b, 0xe9, 0xf7, - 0xf1, 0xf8, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xfb, 0xa8, 0xd9, 0x86, 0x02, 0x00, 0x00, + // 377 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6b, 0xdb, 0x30, + 0x14, 0xc6, 0xb1, 0x13, 0xe2, 0xf8, 0x79, 0xb0, 0xa0, 0xc3, 0x70, 0x12, 0xb6, 0x19, 0x9f, 0xc2, + 0x0e, 0x36, 0xf3, 0x60, 0xbb, 0x0f, 0x72, 0xc8, 0x29, 0x45, 0x29, 0x3d, 0xf4, 0x12, 0x64, 0x59, + 0x4d, 0x05, 0x8e, 0xe5, 0x48, 0xb2, 0xa9, 0xe9, 0x7f, 0xd2, 0xbf, 0xb6, 0x58, 0x72, 0xa0, 0x49, + 0xc9, 0xed, 0xe9, 0xbd, 0xcf, 0x4f, 0xbf, 0xef, 0xb3, 0x60, 0x2e, 0x6b, 0x9a, 0x2a, 0x4a, 0xaa, + 0x8a, 0xc9, 0x54, 0x31, 0xd9, 0x72, 0xca, 0x92, 0x5a, 0x0a, 0x2d, 0xd0, 0x4c, 0x4b, 0xde, 0x76, + 0xc9, 0x30, 0x4c, 0xda, 0xdf, 0x8b, 0xbf, 0x07, 0xae, 0x9f, 0x9b, 0x3c, 0xa1, 0xe2, 0x98, 0x92, + 0x53, 0x43, 0x14, 0xa3, 0x8d, 0xe4, 0xba, 0x4b, 0x8d, 0x32, 0xed, 0x57, 0x51, 0x71, 0x3c, 0x8a, + 0xea, 0x72, 0x53, 0xfc, 0xe6, 0x40, 0xb0, 0xa3, 0xa4, 0xc2, 0xec, 0xd4, 0x30, 0xa5, 0xd1, 0x37, + 0x98, 0x68, 0x22, 0x0f, 0x4c, 0x87, 0x4e, 0xe4, 0xac, 0x7c, 0x3c, 0x9c, 0xd0, 0x4f, 0x08, 0x88, + 0xd4, 0xfc, 0x89, 0x50, 0xbd, 0xe7, 0x45, 0xe8, 0x9a, 0x21, 0x9c, 0x5b, 0x9b, 0x02, 0xcd, 0x61, + 0x9a, 0x97, 0x22, 0xdf, 0xf3, 0x42, 0x85, 0xa3, 0x68, 0xb4, 0xf2, 0xb1, 0xd7, 0x9f, 0x37, 0x85, + 0x42, 0xff, 0xc0, 0x13, 0xb5, 0xe6, 0xa2, 0x52, 0xe1, 0x38, 0x72, 0x56, 0x41, 0xf6, 0x3d, 0xb9, + 0xe6, 0x4f, 0x7a, 0x86, 0xad, 0x15, 0xe1, 0xb3, 0x3a, 0xfe, 0x65, 0xd9, 0x86, 0x3e, 0x5a, 0x82, + 0xdf, 0x36, 0x65, 0xb5, 0xd7, 0x5d, 0xcd, 0x42, 0xc7, 0xdc, 0x31, 0xed, 0x1b, 0xf7, 0x5d, 0xcd, + 0xe2, 0x17, 0xf8, 0x62, 0x7d, 0xa8, 0x5a, 0x54, 0x8a, 0xa1, 0x08, 0x5c, 0xa1, 0x8c, 0x89, 0x20, + 0x9b, 0x0d, 0xf7, 0xd9, 0x04, 0x92, 0xed, 0x0e, 0xbb, 0x42, 0x21, 0x04, 0x63, 0x26, 0x54, 0x69, + 0xbc, 0x4c, 0xb1, 0xa9, 0x51, 0x06, 0x9e, 0x64, 0xaa, 0x29, 0xb5, 0x35, 0x11, 0x64, 0xe1, 0x67, + 0x54, 0x6c, 0x04, 0xf8, 0x2c, 0x8c, 0x5f, 0x61, 0x62, 0x5b, 0x37, 0xc3, 0x5b, 0xc3, 0xd7, 0x9e, + 0x93, 0x49, 0x92, 0xf3, 0x92, 0x6b, 0xce, 0x54, 0xe8, 0x9a, 0xed, 0xcb, 0x4b, 0xb0, 0x87, 0x0f, + 0xa2, 0x0e, 0x5f, 0x7f, 0xd3, 0x03, 0x1b, 0xeb, 0x23, 0xb3, 0xdc, 0xd4, 0xd9, 0x1d, 0x78, 0x3b, + 0x8b, 0x86, 0xd6, 0x30, 0xee, 0x4b, 0x74, 0x23, 0xdd, 0xe1, 0x0f, 0x2f, 0x7e, 0xdc, 0x1a, 0xdb, + 0xe0, 0xfe, 0xfb, 0x8f, 0xde, 0x30, 0xca, 0x27, 0xe6, 0x8d, 0xfc, 0x79, 0x0f, 0x00, 0x00, 0xff, + 0xff, 0xdf, 0x43, 0x89, 0x65, 0x8a, 0x02, 0x00, 0x00, }