zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/cli/client/client_test.go (about) 1 //go:build search 2 // +build search 3 4 package client_test 5 6 import ( 7 "bytes" 8 "crypto/tls" 9 "crypto/x509" 10 "fmt" 11 "os" 12 "path" 13 "path/filepath" 14 "testing" 15 16 . "github.com/smartystreets/goconvey/convey" 17 "gopkg.in/resty.v1" 18 19 "zotregistry.dev/zot/pkg/api" 20 "zotregistry.dev/zot/pkg/api/config" 21 "zotregistry.dev/zot/pkg/api/constants" 22 "zotregistry.dev/zot/pkg/cli/client" 23 extConf "zotregistry.dev/zot/pkg/extensions/config" 24 test "zotregistry.dev/zot/pkg/test/common" 25 ) 26 27 const ( 28 BaseSecureURL1 = "https://127.0.0.1:8088" 29 HOST1 = "127.0.0.1:8088" 30 SecurePort1 = "8088" 31 BaseSecureURL2 = "https://127.0.0.1:8089" 32 SecurePort2 = "8089" 33 BaseSecureURL3 = "https://127.0.0.1:8090" 34 SecurePort3 = "8090" 35 ServerCert = "../../../test/data/server.cert" 36 ServerKey = "../../../test/data/server.key" 37 CACert = "../../../test/data/ca.crt" 38 sourceCertsDir = "../../../test/data" 39 certsDir1 = "/.config/containers/certs.d/127.0.0.1:8088/" 40 ) 41 42 func TestTLSWithAuth(t *testing.T) { 43 Convey("Make a new controller", t, func() { 44 caCert, err := os.ReadFile(CACert) 45 So(err, ShouldBeNil) 46 caCertPool := x509.NewCertPool() 47 caCertPool.AppendCertsFromPEM(caCert) 48 49 resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) 50 defer func() { resty.SetTLSClientConfig(nil) }() 51 conf := config.New() 52 conf.HTTP.Port = SecurePort1 53 username, seedUser := test.GenerateRandomString() 54 password, seedPass := test.GenerateRandomString() 55 htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) 56 defer os.Remove(htpasswdPath) 57 58 conf.HTTP.Auth = &config.AuthConfig{ 59 HTPasswd: config.AuthHTPasswd{ 60 Path: htpasswdPath, 61 }, 62 } 63 64 conf.HTTP.TLS = &config.TLSConfig{ 65 Cert: ServerCert, 66 Key: ServerKey, 67 CACert: CACert, 68 } 69 70 enable := true 71 conf.Extensions = &extConf.ExtensionConfig{ 72 Search: &extConf.SearchConfig{BaseConfig: extConf.BaseConfig{Enable: &enable}}, 73 } 74 75 ctlr := api.NewController(conf) 76 ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") 77 ctlr.Config.Storage.RootDirectory = t.TempDir() 78 cm := test.NewControllerManager(ctlr) 79 cm.StartAndWait(conf.HTTP.Port) 80 defer cm.StopServer() 81 82 Convey("Test with htpassw auth", func() { 83 configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) 84 defer os.Remove(configPath) 85 86 home := os.Getenv("HOME") 87 destCertsDir := filepath.Join(home, certsDir1) 88 err := test.CopyTestKeysAndCerts(destCertsDir) 89 So(err, ShouldBeNil) 90 91 defer os.RemoveAll(destCertsDir) 92 93 args := []string{"name", "dummyImageName", "--url", HOST1} 94 imageCmd := client.NewImageCommand(client.NewSearchService()) 95 imageBuff := bytes.NewBufferString("") 96 imageCmd.SetOut(imageBuff) 97 imageCmd.SetErr(imageBuff) 98 imageCmd.SetArgs(args) 99 err = imageCmd.Execute() 100 So(err, ShouldNotBeNil) 101 So(imageBuff.String(), ShouldContainSubstring, "scheme not provided") 102 103 args = []string{"list", "--config", "imagetest"} 104 configPath = makeConfigFile( 105 fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, 106 BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix)) 107 defer os.Remove(configPath) 108 imageCmd = client.NewImageCommand(client.NewSearchService()) 109 imageBuff = bytes.NewBufferString("") 110 imageCmd.SetOut(imageBuff) 111 imageCmd.SetErr(imageBuff) 112 imageCmd.SetArgs(args) 113 err = imageCmd.Execute() 114 So(err, ShouldNotBeNil) 115 So(imageBuff.String(), ShouldContainSubstring, "check credentials") 116 117 user := fmt.Sprintf("%s:%s", username, password) 118 args = []string{"-u", user, "--config", "imagetest"} 119 configPath = makeConfigFile( 120 fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, 121 BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix)) 122 defer os.Remove(configPath) 123 imageCmd = client.NewImageCommand(client.NewSearchService()) 124 imageBuff = bytes.NewBufferString("") 125 imageCmd.SetOut(imageBuff) 126 imageCmd.SetErr(imageBuff) 127 imageCmd.SetArgs(args) 128 err = imageCmd.Execute() 129 So(err, ShouldBeNil) 130 }) 131 }) 132 } 133 134 func TestTLSWithoutAuth(t *testing.T) { 135 Convey("Home certs - Make a new controller", t, func() { 136 caCert, err := os.ReadFile(CACert) 137 So(err, ShouldBeNil) 138 caCertPool := x509.NewCertPool() 139 caCertPool.AppendCertsFromPEM(caCert) 140 141 resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) 142 defer func() { resty.SetTLSClientConfig(nil) }() 143 conf := config.New() 144 conf.HTTP.Port = SecurePort1 145 conf.HTTP.TLS = &config.TLSConfig{ 146 Cert: ServerCert, 147 Key: ServerKey, 148 CACert: CACert, 149 } 150 151 enable := true 152 conf.Extensions = &extConf.ExtensionConfig{ 153 Search: &extConf.SearchConfig{BaseConfig: extConf.BaseConfig{Enable: &enable}}, 154 } 155 156 ctlr := api.NewController(conf) 157 ctlr.Config.Storage.RootDirectory = t.TempDir() 158 cm := test.NewControllerManager(ctlr) 159 cm.StartAndWait(conf.HTTP.Port) 160 defer cm.StopServer() 161 162 Convey("Certs in user's home", func() { 163 configPath := makeConfigFile( 164 fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, 165 BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix)) 166 defer os.Remove(configPath) 167 168 home := os.Getenv("HOME") 169 destCertsDir := filepath.Join(home, certsDir1) 170 171 err := test.CopyFiles(sourceCertsDir, destCertsDir) 172 So(err, ShouldBeNil) 173 174 defer os.RemoveAll(destCertsDir) 175 176 args := []string{"list", "--config", "imagetest"} 177 imageCmd := client.NewImageCommand(client.NewSearchService()) 178 imageBuff := bytes.NewBufferString("") 179 imageCmd.SetOut(imageBuff) 180 imageCmd.SetErr(imageBuff) 181 imageCmd.SetArgs(args) 182 err = imageCmd.Execute() 183 So(err, ShouldBeNil) 184 }) 185 }) 186 } 187 188 func TestTLSBadCerts(t *testing.T) { 189 Convey("Make a new controller", t, func() { 190 caCert, err := os.ReadFile(CACert) 191 So(err, ShouldBeNil) 192 caCertPool := x509.NewCertPool() 193 caCertPool.AppendCertsFromPEM(caCert) 194 195 resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) 196 defer func() { resty.SetTLSClientConfig(nil) }() 197 conf := config.New() 198 conf.HTTP.Port = SecurePort3 199 conf.HTTP.TLS = &config.TLSConfig{ 200 Cert: ServerCert, 201 Key: ServerKey, 202 CACert: CACert, 203 } 204 205 ctlr := api.NewController(conf) 206 ctlr.Config.Storage.RootDirectory = t.TempDir() 207 cm := test.NewControllerManager(ctlr) 208 cm.StartAndWait(conf.HTTP.Port) 209 defer cm.StopServer() 210 211 Convey("Test with system certs", func() { 212 configPath := makeConfigFile( 213 fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, 214 BaseSecureURL3, constants.RoutePrefix, constants.ExtCatalogPrefix)) 215 defer os.Remove(configPath) 216 217 args := []string{"list", "--config", "imagetest"} 218 imageCmd := client.NewImageCommand(client.NewSearchService()) 219 imageBuff := bytes.NewBufferString("") 220 imageCmd.SetOut(imageBuff) 221 imageCmd.SetErr(imageBuff) 222 imageCmd.SetArgs(args) 223 err := imageCmd.Execute() 224 So(err, ShouldNotBeNil) 225 So(imageBuff.String(), ShouldContainSubstring, "certificate signed by unknown authority") 226 }) 227 }) 228 } 229 230 func makeConfigFile(content string) string { 231 os.Setenv("HOME", os.TempDir()) 232 233 home, err := os.UserHomeDir() 234 if err != nil { 235 panic(err) 236 } 237 238 configPath := path.Join(home, "/.zot") 239 240 if err := os.WriteFile(configPath, []byte(content), 0o600); err != nil { 241 panic(err) 242 } 243 244 return configPath 245 }