github.com/ishita82/trivy-gitaction@v0.0.0-20240206054925-e937cc05f8e3/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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/aquasecurity/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  }