github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/oci/artifact_test.go (about)

     1  package oci_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	v1 "github.com/google/go-containerregistry/pkg/v1"
    11  	fakei "github.com/google/go-containerregistry/pkg/v1/fake"
    12  	"github.com/google/go-containerregistry/pkg/v1/tarball"
    13  	"github.com/google/go-containerregistry/pkg/v1/types"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    18  	"github.com/devseccon/trivy/pkg/oci"
    19  	"github.com/devseccon/trivy/pkg/utils/fsutils"
    20  )
    21  
    22  type fakeLayer struct {
    23  	v1.Layer
    24  }
    25  
    26  func (f fakeLayer) MediaType() (types.MediaType, error) {
    27  	return "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", nil
    28  }
    29  
    30  func TestArtifact_Download(t *testing.T) {
    31  	layer, err := tarball.LayerFromFile("testdata/test.tar.gz")
    32  	require.NoError(t, err)
    33  
    34  	txtLayer, err := tarball.LayerFromFile("testdata/test.txt")
    35  	require.NoError(t, err)
    36  
    37  	flayer := fakeLayer{layer}
    38  
    39  	type layersReturns struct {
    40  		layers []v1.Layer
    41  		err    error
    42  	}
    43  	tests := []struct {
    44  		name          string
    45  		input         string
    46  		mediaType     string
    47  		layersReturns layersReturns
    48  		want          string
    49  		wantErr       string
    50  	}{
    51  		{
    52  			name:      "happy path",
    53  			input:     "testdata/test.tar.gz",
    54  			mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip",
    55  			layersReturns: layersReturns{
    56  				layers: []v1.Layer{flayer},
    57  			},
    58  			want: "Hello, world",
    59  		},
    60  		{
    61  			name:      "sad: two layers",
    62  			mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip",
    63  			layersReturns: layersReturns{
    64  				layers: []v1.Layer{
    65  					layer,
    66  					layer,
    67  				},
    68  			},
    69  			wantErr: "OCI artifact must be a single layer",
    70  		},
    71  		{
    72  			name:      "sad: Layers returns an error",
    73  			mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip",
    74  			layersReturns: layersReturns{
    75  				err: fmt.Errorf("error"),
    76  			},
    77  			wantErr: "OCI layer error",
    78  		},
    79  		{
    80  			name:  "invalid gzip",
    81  			input: "testdata/test.txt",
    82  			layersReturns: layersReturns{
    83  				layers: []v1.Layer{txtLayer},
    84  			},
    85  			wantErr: "unexpected EOF",
    86  		},
    87  		{
    88  			name:      "sad: media type doesn't match",
    89  			mediaType: "unknown",
    90  			layersReturns: layersReturns{
    91  				layers: []v1.Layer{layer},
    92  			},
    93  			wantErr: "unacceptable media type",
    94  		},
    95  	}
    96  
    97  	for _, tt := range tests {
    98  		t.Run(tt.name, func(t *testing.T) {
    99  			tempDir := t.TempDir()
   100  			fsutils.SetCacheDir(tempDir)
   101  
   102  			// Mock image
   103  			img := new(fakei.FakeImage)
   104  			img.LayersReturns(tt.layersReturns.layers, tt.layersReturns.err)
   105  			img.ManifestReturns(&v1.Manifest{
   106  				Layers: []v1.Descriptor{
   107  					{
   108  						MediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip",
   109  						Size:      100,
   110  						Digest: v1.Hash{
   111  							Algorithm: "sha256",
   112  							Hex:       "cba33656188782852f58993f45b68bfb8577f64cdcf02a604e3fc2afbeb5f2d8",
   113  						},
   114  						Annotations: map[string]string{
   115  							"org.opencontainers.image.title": "bundle.tar.gz",
   116  						},
   117  					},
   118  				},
   119  			}, nil)
   120  
   121  			artifact, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img))
   122  			require.NoError(t, err)
   123  
   124  			err = artifact.Download(context.Background(), tempDir, oci.DownloadOption{
   125  				MediaType: tt.mediaType,
   126  			})
   127  			if tt.wantErr != "" {
   128  				assert.ErrorContains(t, err, tt.wantErr)
   129  				return
   130  			}
   131  			require.NoError(t, err)
   132  
   133  			// Assert
   134  			got, err := os.ReadFile(filepath.Join(tempDir, "test.txt"))
   135  			require.NoError(t, err)
   136  
   137  			assert.Equal(t, tt.want, string(got))
   138  		})
   139  	}
   140  }