github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/integration/docker_engine_test.go (about) 1 //go:build integration 2 // +build integration 3 4 package integration 5 6 import ( 7 "context" 8 "io" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 api "github.com/docker/docker/api/types" 15 "github.com/docker/docker/client" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestDockerEngine(t *testing.T) { 21 if *update { 22 t.Skipf("This test doesn't update golden files") 23 } 24 tests := []struct { 25 name string 26 imageTag string 27 invalidImage bool 28 ignoreUnfixed bool 29 ignoreStatus []string 30 severity []string 31 ignoreIDs []string 32 input string 33 golden string 34 wantErr string 35 }{ 36 { 37 name: "alpine:3.9", 38 imageTag: "ghcr.io/devseccon/trivy-test-images:alpine-39", 39 input: "testdata/fixtures/images/alpine-39.tar.gz", 40 golden: "testdata/alpine-39.json.golden", 41 }, 42 { 43 name: "alpine:3.9, with high and critical severity", 44 severity: []string{"HIGH", "CRITICAL"}, 45 imageTag: "ghcr.io/devseccon/trivy-test-images:alpine-39", 46 input: "testdata/fixtures/images/alpine-39.tar.gz", 47 golden: "testdata/alpine-39-high-critical.json.golden", 48 }, 49 { 50 name: "alpine:3.9, with .trivyignore", 51 imageTag: "ghcr.io/devseccon/trivy-test-images:alpine-39", 52 ignoreIDs: []string{"CVE-2019-1549", "CVE-2019-14697"}, 53 input: "testdata/fixtures/images/alpine-39.tar.gz", 54 golden: "testdata/alpine-39-ignore-cveids.json.golden", 55 }, 56 { 57 name: "alpine:3.10", 58 imageTag: "ghcr.io/devseccon/trivy-test-images:alpine-310", 59 input: "testdata/fixtures/images/alpine-310.tar.gz", 60 golden: "testdata/alpine-310.json.golden", 61 }, 62 { 63 name: "amazonlinux:1", 64 imageTag: "ghcr.io/devseccon/trivy-test-images:amazon-1", 65 input: "testdata/fixtures/images/amazon-1.tar.gz", 66 golden: "testdata/amazon-1.json.golden", 67 }, 68 { 69 name: "amazonlinux:2", 70 imageTag: "ghcr.io/devseccon/trivy-test-images:amazon-2", 71 input: "testdata/fixtures/images/amazon-2.tar.gz", 72 golden: "testdata/amazon-2.json.golden", 73 }, 74 { 75 name: "almalinux 8", 76 imageTag: "ghcr.io/devseccon/trivy-test-images:almalinux-8", 77 input: "testdata/fixtures/images/almalinux-8.tar.gz", 78 golden: "testdata/almalinux-8.json.golden", 79 }, 80 { 81 name: "rocky linux 8", 82 imageTag: "ghcr.io/devseccon/trivy-test-images:rockylinux-8", 83 input: "testdata/fixtures/images/rockylinux-8.tar.gz", 84 golden: "testdata/rockylinux-8.json.golden", 85 }, 86 { 87 name: "centos 6", 88 imageTag: "ghcr.io/devseccon/trivy-test-images:centos-6", 89 input: "testdata/fixtures/images/centos-6.tar.gz", 90 golden: "testdata/centos-6.json.golden", 91 }, 92 { 93 name: "centos 7", 94 imageTag: "ghcr.io/devseccon/trivy-test-images:centos-7", 95 input: "testdata/fixtures/images/centos-7.tar.gz", 96 golden: "testdata/centos-7.json.golden", 97 }, 98 { 99 name: "centos 7, with --ignore-unfixed option", 100 imageTag: "ghcr.io/devseccon/trivy-test-images:centos-7", 101 ignoreUnfixed: true, 102 input: "testdata/fixtures/images/centos-7.tar.gz", 103 golden: "testdata/centos-7-ignore-unfixed.json.golden", 104 }, 105 { 106 name: "centos 7, with --ignore-status option", 107 imageTag: "ghcr.io/devseccon/trivy-test-images:centos-7", 108 ignoreStatus: []string{"will_not_fix"}, 109 input: "testdata/fixtures/images/centos-7.tar.gz", 110 golden: "testdata/centos-7-ignore-unfixed.json.golden", 111 }, 112 { 113 name: "centos 7, with --ignore-unfixed option, with medium severity", 114 imageTag: "ghcr.io/devseccon/trivy-test-images:centos-7", 115 ignoreUnfixed: true, 116 severity: []string{"MEDIUM"}, 117 input: "testdata/fixtures/images/centos-7.tar.gz", 118 golden: "testdata/centos-7-medium.json.golden", 119 }, 120 { 121 name: "registry.redhat.io/ubi7", 122 imageTag: "ghcr.io/devseccon/trivy-test-images:ubi-7", 123 input: "testdata/fixtures/images/ubi-7.tar.gz", 124 golden: "testdata/ubi-7.json.golden", 125 }, 126 { 127 name: "debian buster/10", 128 imageTag: "ghcr.io/devseccon/trivy-test-images:debian-buster", 129 input: "testdata/fixtures/images/debian-buster.tar.gz", 130 golden: "testdata/debian-buster.json.golden", 131 }, 132 { 133 name: "debian buster/10, with --ignore-unfixed option", 134 ignoreUnfixed: true, 135 imageTag: "ghcr.io/devseccon/trivy-test-images:debian-buster", 136 input: "testdata/fixtures/images/debian-buster.tar.gz", 137 golden: "testdata/debian-buster-ignore-unfixed.json.golden", 138 }, 139 { 140 name: "debian buster/10, with --ignore-status option", 141 ignoreStatus: []string{"affected"}, 142 imageTag: "ghcr.io/devseccon/trivy-test-images:debian-buster", 143 input: "testdata/fixtures/images/debian-buster.tar.gz", 144 golden: "testdata/debian-buster-ignore-unfixed.json.golden", 145 }, 146 { 147 name: "debian stretch/9", 148 imageTag: "ghcr.io/devseccon/trivy-test-images:debian-stretch", 149 input: "testdata/fixtures/images/debian-stretch.tar.gz", 150 golden: "testdata/debian-stretch.json.golden", 151 }, 152 { 153 name: "distroless base", 154 imageTag: "ghcr.io/devseccon/trivy-test-images:distroless-base", 155 input: "testdata/fixtures/images/distroless-base.tar.gz", 156 golden: "testdata/distroless-base.json.golden", 157 }, 158 { 159 name: "distroless python2.7", 160 imageTag: "ghcr.io/devseccon/trivy-test-images:distroless-python27", 161 input: "testdata/fixtures/images/distroless-python27.tar.gz", 162 golden: "testdata/distroless-python27.json.golden", 163 }, 164 { 165 name: "oracle linux 8", 166 imageTag: "ghcr.io/devseccon/trivy-test-images:oraclelinux-8", 167 input: "testdata/fixtures/images/oraclelinux-8.tar.gz", 168 golden: "testdata/oraclelinux-8.json.golden", 169 }, 170 { 171 name: "ubuntu 18.04", 172 imageTag: "ghcr.io/devseccon/trivy-test-images:ubuntu-1804", 173 input: "testdata/fixtures/images/ubuntu-1804.tar.gz", 174 golden: "testdata/ubuntu-1804.json.golden", 175 }, 176 { 177 name: "ubuntu 18.04, with --ignore-unfixed option", 178 imageTag: "ghcr.io/devseccon/trivy-test-images:ubuntu-1804", 179 ignoreUnfixed: true, 180 input: "testdata/fixtures/images/ubuntu-1804.tar.gz", 181 golden: "testdata/ubuntu-1804-ignore-unfixed.json.golden", 182 }, 183 { 184 name: "opensuse leap 15.1", 185 imageTag: "ghcr.io/devseccon/trivy-test-images:opensuse-leap-151", 186 input: "testdata/fixtures/images/opensuse-leap-151.tar.gz", 187 golden: "testdata/opensuse-leap-151.json.golden", 188 }, 189 { 190 name: "photon 3.0", 191 imageTag: "ghcr.io/devseccon/trivy-test-images:photon-30", 192 input: "testdata/fixtures/images/photon-30.tar.gz", 193 golden: "testdata/photon-30.json.golden", 194 }, 195 { 196 name: "CBL-Mariner 1.0", 197 imageTag: "ghcr.io/devseccon/trivy-test-images:mariner-1.0", 198 input: "testdata/fixtures/images/mariner-1.0.tar.gz", 199 golden: "testdata/mariner-1.0.json.golden", 200 }, 201 { 202 name: "busybox with Cargo.lock", 203 imageTag: "ghcr.io/devseccon/trivy-test-images:busybox-with-lockfile", 204 input: "testdata/fixtures/images/busybox-with-lockfile.tar.gz", 205 golden: "testdata/busybox-with-lockfile.json.golden", 206 }, 207 { 208 name: "sad path, invalid image", 209 invalidImage: true, 210 input: "badimage:latest", 211 wantErr: "unable to inspect the image (badimage:latest)", 212 }, 213 } 214 215 // Set up testing DB 216 cacheDir := initDB(t) 217 218 // Set a temp dir so that modules will not be loaded 219 t.Setenv("XDG_DATA_HOME", cacheDir) 220 221 ctx := context.Background() 222 defer ctx.Done() 223 224 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) 225 require.NoError(t, err) 226 227 for _, tt := range tests { 228 t.Run(tt.name, func(t *testing.T) { 229 if !tt.invalidImage { 230 testfile, err := os.Open(tt.input) 231 require.NoError(t, err, tt.name) 232 233 // ensure image doesnt already exists 234 _, _ = cli.ImageRemove(ctx, tt.input, api.ImageRemoveOptions{ 235 Force: true, 236 PruneChildren: true, 237 }) 238 239 // load image into docker engine 240 res, err := cli.ImageLoad(ctx, testfile, true) 241 require.NoError(t, err, tt.name) 242 io.Copy(io.Discard, res.Body) 243 244 // tag our image to something unique 245 err = cli.ImageTag(ctx, tt.imageTag, tt.input) 246 require.NoError(t, err, tt.name) 247 } 248 249 tmpDir := t.TempDir() 250 output := filepath.Join(tmpDir, "result.json") 251 252 osArgs := []string{"--cache-dir", cacheDir, "image", 253 "--skip-update", "--format=json", "--output", output} 254 255 if tt.ignoreUnfixed { 256 osArgs = append(osArgs, "--ignore-unfixed") 257 } 258 259 if len(tt.ignoreStatus) != 0 { 260 osArgs = append(osArgs, 261 []string{"--ignore-status", strings.Join(tt.ignoreStatus, ",")}..., 262 ) 263 } 264 if len(tt.severity) != 0 { 265 osArgs = append(osArgs, 266 []string{"--severity", strings.Join(tt.severity, ",")}..., 267 ) 268 } 269 if len(tt.ignoreIDs) != 0 { 270 trivyIgnore := ".trivyignore" 271 err = os.WriteFile(trivyIgnore, []byte(strings.Join(tt.ignoreIDs, "\n")), 0444) 272 assert.NoError(t, err, "failed to write .trivyignore") 273 defer os.Remove(trivyIgnore) 274 } 275 osArgs = append(osArgs, tt.input) 276 277 // Run Trivy 278 err = execute(osArgs) 279 if tt.wantErr != "" { 280 require.Error(t, err) 281 assert.Contains(t, err.Error(), tt.wantErr, tt.name) 282 return 283 } 284 285 assert.NoError(t, err, tt.name) 286 287 // check for vulnerability output info 288 compareReports(t, tt.golden, output, nil) 289 290 // cleanup 291 _, err = cli.ImageRemove(ctx, tt.input, api.ImageRemoveOptions{ 292 Force: true, 293 PruneChildren: true, 294 }) 295 _, err = cli.ImageRemove(ctx, tt.imageTag, api.ImageRemoveOptions{ 296 Force: true, 297 PruneChildren: true, 298 }) 299 assert.NoError(t, err, tt.name) 300 }) 301 } 302 }