Files
zot/pkg/cli/client/client_test.go
T
Andrei Aaron 9dfa7c3ae6 refactor(test): new apis for creating temporary files (#3605)
Replace MakeTempFile usage with MakeTempFilePath and MakeTempFileWithContent
helpers that automatically handle file lifecycle. This prevents resource
leaks by ensuring temporary files are properly closed.

Shoudld also make the tests easier to read.

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
2025-12-05 09:54:38 +02:00

263 lines
7.5 KiB
Go

//go:build search
package client_test
import (
"bytes"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"path"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
"zotregistry.dev/zot/v2/pkg/api"
"zotregistry.dev/zot/v2/pkg/api/config"
"zotregistry.dev/zot/v2/pkg/api/constants"
"zotregistry.dev/zot/v2/pkg/cli/client"
extConf "zotregistry.dev/zot/v2/pkg/extensions/config"
test "zotregistry.dev/zot/v2/pkg/test/common"
)
const (
BaseSecureURL1 = "https://127.0.0.1:8088"
HOST1 = "127.0.0.1:8088"
SecurePort1 = "8088"
BaseSecureURL2 = "https://127.0.0.1:8089"
SecurePort2 = "8089"
BaseSecureURL3 = "https://127.0.0.1:8090"
SecurePort3 = "8090"
ServerCert = "../../../test/data/server.cert"
ServerKey = "../../../test/data/server.key"
CACert = "../../../test/data/ca.crt"
sourceCertsDir = "../../../test/data"
certsDir1 = ".config/containers/certs.d/127.0.0.1:8088"
)
func TestTLSWithAuth(t *testing.T) {
Convey("Make a new controller", t, func() {
caCert, err := os.ReadFile(CACert)
So(err, ShouldBeNil)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12})
defer func() { resty.SetTLSClientConfig(nil) }()
conf := config.New()
conf.HTTP.Port = SecurePort1
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(t, test.GetBcryptCredString(username, password))
conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{
Path: htpasswdPath,
},
}
conf.HTTP.TLS = &config.TLSConfig{
Cert: ServerCert,
Key: ServerKey,
CACert: CACert,
}
enable := true
conf.Extensions = &extConf.ExtensionConfig{
Search: &extConf.SearchConfig{BaseConfig: extConf.BaseConfig{Enable: &enable}},
}
ctlr := api.NewController(conf)
ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password")
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("Test with htpassw auth", func() {
_ = makeConfigFile(t, `{"configs":[{"_name":"imagetest","showspinner":false}]}`)
// Use the HOME that makeConfigFile set (temp directory) for certificates
home := os.Getenv("HOME")
destCertsDir := filepath.Join(home, certsDir1)
err := test.CopyTestKeysAndCerts(destCertsDir)
So(err, ShouldBeNil)
defer os.RemoveAll(destCertsDir)
args := []string{"name", "dummyImageName", "--url", HOST1}
imageCmd := client.NewImageCommand(client.NewSearchService())
imageBuff := bytes.NewBufferString("")
imageCmd.SetOut(imageBuff)
imageCmd.SetErr(imageBuff)
imageCmd.SetArgs(args)
err = imageCmd.Execute()
So(err, ShouldNotBeNil)
So(imageBuff.String(), ShouldContainSubstring, "scheme not provided")
args = []string{"list", "--config", "imagetest"}
_ = makeConfigFile(t,
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
// Ensure certificates are in the HOME directory that makeConfigFile set
home = os.Getenv("HOME")
destCertsDir = filepath.Join(home, certsDir1)
err = test.CopyTestKeysAndCerts(destCertsDir)
So(err, ShouldBeNil)
imageCmd = client.NewImageCommand(client.NewSearchService())
imageBuff = bytes.NewBufferString("")
imageCmd.SetOut(imageBuff)
imageCmd.SetErr(imageBuff)
imageCmd.SetArgs(args)
err = imageCmd.Execute()
So(err, ShouldNotBeNil)
So(imageBuff.String(), ShouldContainSubstring, "check credentials")
user := fmt.Sprintf("%s:%s", username, password)
args = []string{"-u", user, "--config", "imagetest"}
_ = makeConfigFile(t,
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
imageCmd = client.NewImageCommand(client.NewSearchService())
imageBuff = bytes.NewBufferString("")
imageCmd.SetOut(imageBuff)
imageCmd.SetErr(imageBuff)
imageCmd.SetArgs(args)
err = imageCmd.Execute()
So(err, ShouldBeNil)
})
})
}
func TestTLSWithoutAuth(t *testing.T) {
Convey("Home certs - Make a new controller", t, func() {
caCert, err := os.ReadFile(CACert)
So(err, ShouldBeNil)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12})
defer func() { resty.SetTLSClientConfig(nil) }()
conf := config.New()
conf.HTTP.Port = SecurePort1
conf.HTTP.TLS = &config.TLSConfig{
Cert: ServerCert,
Key: ServerKey,
CACert: CACert,
}
enable := true
conf.Extensions = &extConf.ExtensionConfig{
Search: &extConf.SearchConfig{BaseConfig: extConf.BaseConfig{Enable: &enable}},
}
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("Certs in user's home", func() {
_ = makeConfigFile(t,
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
home := os.Getenv("HOME")
destCertsDir := filepath.Join(home, certsDir1)
err := test.CopyFiles(sourceCertsDir, destCertsDir)
So(err, ShouldBeNil)
defer os.RemoveAll(destCertsDir)
args := []string{"list", "--config", "imagetest"}
imageCmd := client.NewImageCommand(client.NewSearchService())
imageBuff := bytes.NewBufferString("")
imageCmd.SetOut(imageBuff)
imageCmd.SetErr(imageBuff)
imageCmd.SetArgs(args)
err = imageCmd.Execute()
So(err, ShouldBeNil)
})
})
}
func TestTLSBadCerts(t *testing.T) {
Convey("Make a new controller", t, func() {
caCert, err := os.ReadFile(CACert)
So(err, ShouldBeNil)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12})
defer func() { resty.SetTLSClientConfig(nil) }()
conf := config.New()
conf.HTTP.Port = SecurePort3
conf.HTTP.TLS = &config.TLSConfig{
Cert: ServerCert,
Key: ServerKey,
CACert: CACert,
}
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("Test with system certs", func() {
_ = makeConfigFile(t,
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
BaseSecureURL3, constants.RoutePrefix, constants.ExtCatalogPrefix))
args := []string{"list", "--config", "imagetest"}
imageCmd := client.NewImageCommand(client.NewSearchService())
imageBuff := bytes.NewBufferString("")
imageCmd.SetOut(imageBuff)
imageCmd.SetErr(imageBuff)
imageCmd.SetArgs(args)
err := imageCmd.Execute()
So(err, ShouldNotBeNil)
So(imageBuff.String(), ShouldContainSubstring, "certificate signed by unknown authority")
})
})
}
func makeConfigFile(t *testing.T, content string) string {
t.Helper()
tempDir := t.TempDir()
os.Setenv("HOME", tempDir)
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
configPath := path.Join(home, "/.zot")
if err := os.WriteFile(configPath, []byte(content), 0o600); err != nil {
panic(err)
}
return configPath
}