github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/remote/remote_test.go (about) 1 package remote 2 3 import ( 4 "context" 5 "encoding/base64" 6 "fmt" 7 "net/http/httptest" 8 "os" 9 "path/filepath" 10 "testing" 11 12 "github.com/google/go-containerregistry/pkg/name" 13 v1 "github.com/google/go-containerregistry/pkg/v1" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 "github.com/aquasecurity/testdocker/auth" 18 "github.com/aquasecurity/testdocker/registry" 19 "github.com/devseccon/trivy/pkg/fanal/types" 20 ) 21 22 func setupPrivateRegistry() *httptest.Server { 23 imagePaths := map[string]string{ 24 "v2/library/alpine:3.10": "../fanal/test/testdata/alpine-310.tar.gz", 25 } 26 tr := registry.NewDockerRegistry(registry.Option{ 27 Images: imagePaths, 28 Auth: auth.Auth{ 29 User: "test", 30 Password: "testpass", 31 Secret: "secret", 32 }, 33 }) 34 35 return tr 36 } 37 38 // setupConfigDir sets up an isolated configDir() for this test. 39 func setupConfigDir(t *testing.T) string { 40 p := t.TempDir() 41 t.Setenv("DOCKER_CONFIG", p) 42 return p 43 } 44 45 func setupDockerConfig(t *testing.T, content string) { 46 cd := setupConfigDir(t) 47 p := filepath.Join(cd, "config.json") 48 49 err := os.WriteFile(p, []byte(content), 0600) 50 require.NoError(t, err) 51 } 52 53 func encode(user, pass string) string { 54 delimited := fmt.Sprintf("%s:%s", user, pass) 55 return base64.StdEncoding.EncodeToString([]byte(delimited)) 56 } 57 58 func TestGet(t *testing.T) { 59 tr := setupPrivateRegistry() 60 defer tr.Close() 61 62 serverAddr := tr.Listener.Addr().String() 63 64 type args struct { 65 imageName string 66 config string 67 option types.RegistryOptions 68 } 69 tests := []struct { 70 name string 71 args args 72 want *Descriptor 73 wantErr string 74 }{ 75 { 76 name: "single credential", 77 args: args{ 78 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 79 option: types.RegistryOptions{ 80 Credentials: []types.Credential{ 81 { 82 Username: "test", 83 Password: "testpass", 84 }, 85 }, 86 Insecure: true, 87 }, 88 }, 89 }, 90 { 91 name: "multiple credential", 92 args: args{ 93 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 94 option: types.RegistryOptions{ 95 Credentials: []types.Credential{ 96 { 97 Username: "foo", 98 Password: "bar", 99 }, 100 { 101 Username: "test", 102 Password: "testpass", 103 }, 104 }, 105 Insecure: true, 106 }, 107 }, 108 }, 109 { 110 name: "keychain", 111 args: args{ 112 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 113 config: fmt.Sprintf(`{"auths": {"%s": {"auth": %q}}}`, serverAddr, encode("test", "testpass")), 114 option: types.RegistryOptions{ 115 Insecure: true, 116 }, 117 }, 118 }, 119 { 120 name: "platform", 121 args: args{ 122 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 123 option: types.RegistryOptions{ 124 Credentials: []types.Credential{ 125 { 126 Username: "test", 127 Password: "testpass", 128 }, 129 }, 130 Insecure: true, 131 Platform: types.Platform{ 132 Platform: &v1.Platform{ 133 OS: "", 134 Architecture: "amd64", 135 }, 136 }, 137 }, 138 }, 139 }, 140 { 141 name: "force platform", 142 args: args{ 143 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 144 option: types.RegistryOptions{ 145 Credentials: []types.Credential{ 146 { 147 Username: "test", 148 Password: "testpass", 149 }, 150 }, 151 Insecure: true, 152 Platform: types.Platform{ 153 Force: true, 154 Platform: &v1.Platform{ 155 OS: "windows", 156 Architecture: "amd64", 157 }, 158 }, 159 }, 160 }, 161 wantErr: "the specified platform not found", 162 }, 163 { 164 name: "bad credential", 165 args: args{ 166 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 167 option: types.RegistryOptions{ 168 Credentials: []types.Credential{ 169 { 170 Username: "foo", 171 Password: "bar", 172 }, 173 }, 174 Insecure: true, 175 }, 176 }, 177 wantErr: "invalid username/password", 178 }, 179 { 180 name: "bad keychain", 181 args: args{ 182 imageName: fmt.Sprintf("%s/library/alpine:3.10", serverAddr), 183 config: fmt.Sprintf(`{"auths": {"%s": {"auth": %q}}}`, serverAddr, encode("foo", "bar")), 184 option: types.RegistryOptions{ 185 Insecure: true, 186 }, 187 }, 188 wantErr: "invalid username/password", 189 }, 190 } 191 for _, tt := range tests { 192 t.Run(tt.name, func(t *testing.T) { 193 n, err := name.ParseReference(tt.args.imageName) 194 require.NoError(t, err) 195 196 if tt.args.config != "" { 197 setupDockerConfig(t, tt.args.config) 198 } 199 200 _, err = Get(context.Background(), n, tt.args.option) 201 if tt.wantErr != "" { 202 assert.ErrorContains(t, err, tt.wantErr, err) 203 return 204 } 205 assert.NoError(t, err) 206 }) 207 } 208 }