mirror of
https://github.com/project-zot/zot.git
synced 2025-02-03 23:09:41 -05:00
Which could be imported independently. See more details: 1. "zotregistry.io/zot/pkg/test/common" - currently used as tcommon "zotregistry.io/zot/pkg/test/common" - inside pkg/test test "zotregistry.io/zot/pkg/test/common" - in tests . "zotregistry.io/zot/pkg/test/common" - in tests Decouple zb from code in test/pkg in order to keep the size small. 2. "zotregistry.io/zot/pkg/test/image-utils" - curently used as . "zotregistry.io/zot/pkg/test/image-utils" 3. "zotregistry.io/zot/pkg/test/deprecated" - curently used as "zotregistry.io/zot/pkg/test/deprecated" This one will bre replaced gradually by image-utils in the future. 4. "zotregistry.io/zot/pkg/test/signature" - (cosign + notation) use as "zotregistry.io/zot/pkg/test/signature" 5. "zotregistry.io/zot/pkg/test/auth" - (bearer + oidc) curently used as authutils "zotregistry.io/zot/pkg/test/auth" 6. "zotregistry.io/zot/pkg/test/oci-utils" - curently used as ociutils "zotregistry.io/zot/pkg/test/oci-utils" Some unused functions were removed, some were replaced, and in a few cases specific funtions were moved to the files they were used in. Added an interface for the StoreController, this reduces the number of imports of the entire image store, decreasing binary size for tests. If the zb code was still coupled with pkg/test, this would have reflected in zb size. Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
464 lines
13 KiB
Go
464 lines
13 KiB
Go
//go:build sync && scrub && metrics && search
|
|
// +build sync,scrub,metrics,search
|
|
|
|
package signature_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
notconfig "github.com/notaryproject/notation-go/config"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
|
"zotregistry.io/zot/pkg/api"
|
|
"zotregistry.io/zot/pkg/api/config"
|
|
tcommon "zotregistry.io/zot/pkg/test/common"
|
|
. "zotregistry.io/zot/pkg/test/image-utils"
|
|
signature "zotregistry.io/zot/pkg/test/signature"
|
|
)
|
|
|
|
func TestLoadNotationSigningkeys(t *testing.T) {
|
|
Convey("notation directory doesn't exist", t, func() {
|
|
_, err := signature.LoadNotationSigningkeys(t.TempDir())
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("wrong content of signingkeys.json", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(dir, "signingkeys.json")
|
|
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = signature.LoadNotationSigningkeys(tempDir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("not enough permissions to access signingkeys.json", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(dir, "signingkeys.json")
|
|
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o300) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = signature.LoadNotationSigningkeys(tempDir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("signingkeys.json not exists so it is created successfully", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = signature.LoadNotationSigningkeys(tempDir)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("signingkeys.json not exists - error trying to create it", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
// create notation directory without write permissions
|
|
err := os.Mkdir(dir, 0o555)
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = signature.LoadNotationSigningkeys(tempDir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|
|
|
|
func TestLoadNotationConfig(t *testing.T) {
|
|
Convey("directory doesn't exist", t, func() {
|
|
_, err := signature.LoadNotationConfig(t.TempDir())
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("wrong content of signingkeys.json", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(dir, "signingkeys.json")
|
|
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
_, err = signature.LoadNotationConfig(tempDir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("check default value of signature format", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(dir, "signingkeys.json")
|
|
err = os.WriteFile(filePath, []byte("{\"SignatureFormat\": \"\"}"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
configInfo, err := signature.LoadNotationConfig(tempDir)
|
|
So(err, ShouldBeNil)
|
|
So(configInfo.SignatureFormat, ShouldEqual, "jws")
|
|
})
|
|
}
|
|
|
|
func TestSignWithNotation(t *testing.T) {
|
|
Convey("notation directory doesn't exist", t, func() {
|
|
err := signature.SignWithNotation("key", "reference", t.TempDir())
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("key not found", t, func() {
|
|
tempDir := t.TempDir()
|
|
dir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(dir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(dir, "signingkeys.json")
|
|
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignWithNotation("key", "reference", tempDir)
|
|
So(err, ShouldEqual, signature.ErrKeyNotFound)
|
|
})
|
|
|
|
Convey("not enough permissions to access notation/localkeys dir", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tdir)
|
|
|
|
err = signature.GenerateNotationCerts(tdir, "key")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = os.Chmod(path.Join(tdir, "notation", "localkeys"), 0o000)
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignWithNotation("key", "reference", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
|
|
err = os.Chmod(path.Join(tdir, "notation", "localkeys"), 0o755)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("error parsing reference", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tdir)
|
|
|
|
err = signature.GenerateNotationCerts(tdir, "key")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignWithNotation("key", "invalidReference", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("error signing", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tdir)
|
|
|
|
err = signature.GenerateNotationCerts(tdir, "key")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignWithNotation("key", "localhost:8080/invalidreference:1.0", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|
|
|
|
func TestVerifyWithNotation(t *testing.T) {
|
|
Convey("notation directory doesn't exist", t, func() {
|
|
err := signature.VerifyWithNotation("reference", t.TempDir())
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("error parsing reference", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tdir)
|
|
|
|
err = signature.GenerateNotationCerts(tdir, "key")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.VerifyWithNotation("invalidReference", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("error trying to get manifest", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tdir)
|
|
|
|
err = signature.GenerateNotationCerts(tdir, "key")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.VerifyWithNotation("localhost:8080/invalidreference:1.0", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("invalid content of trustpolicy.json", t, func() {
|
|
// start a new server
|
|
port := tcommon.GetFreePort()
|
|
baseURL := tcommon.GetBaseURL(port)
|
|
dir := t.TempDir()
|
|
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
conf.Storage.RootDirectory = dir
|
|
|
|
ctlr := api.NewController(conf)
|
|
cm := tcommon.NewControllerManager(ctlr)
|
|
// this blocks
|
|
cm.StartAndWait(port)
|
|
defer cm.StopServer()
|
|
|
|
repoName := "signed-repo"
|
|
tag := "1.0"
|
|
|
|
image := CreateRandomImage()
|
|
|
|
err := UploadImage(image, baseURL, repoName, tag)
|
|
So(err, ShouldBeNil)
|
|
|
|
tempDir := t.TempDir()
|
|
notationDir := path.Join(tempDir, "notation")
|
|
err = os.Mkdir(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(notationDir, "trustpolicy.json")
|
|
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.VerifyWithNotation(fmt.Sprintf("localhost:%s/%s:%s", port, repoName, tag), tempDir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|
|
|
|
func TestListNotarySignatures(t *testing.T) {
|
|
Convey("error parsing reference", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
_, err = signature.ListNotarySignatures("invalidReference", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("error trying to get manifest", t, func() {
|
|
cwd, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
defer func() { _ = os.Chdir(cwd) }()
|
|
tdir := t.TempDir()
|
|
_ = os.Chdir(tdir)
|
|
|
|
_, err = signature.ListNotarySignatures("localhost:8080/invalidreference:1.0", tdir)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|
|
|
|
func TestGenerateNotationCerts(t *testing.T) {
|
|
Convey("write key file with permission", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
notationDir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(notationDir, "localkeys")
|
|
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.GenerateNotationCerts(t.TempDir(), "cert")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("write cert file with permission", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
notationDir := path.Join(tempDir, "notation", "localkeys")
|
|
err := os.MkdirAll(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(notationDir, "cert.crt")
|
|
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
|
|
err = os.Chmod(filePath, 0o000)
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.GenerateNotationCerts(t.TempDir(), "cert")
|
|
So(err, ShouldNotBeNil)
|
|
|
|
err = os.Chmod(filePath, 0o755)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("signingkeys.json file - not enough permission", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
notationDir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
filePath := path.Join(notationDir, "signingkeys.json")
|
|
_, err = os.Create(filePath) //nolint: gosec
|
|
So(err, ShouldBeNil)
|
|
err = os.Chmod(filePath, 0o000)
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.GenerateNotationCerts(t.TempDir(), "cert")
|
|
So(err, ShouldNotBeNil)
|
|
|
|
err = os.Remove(filePath)
|
|
So(err, ShouldBeNil)
|
|
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
|
|
So(err, ShouldBeNil)
|
|
signingKeysBuf, err := json.Marshal(notconfig.SigningKeys{})
|
|
So(err, ShouldBeNil)
|
|
err = os.WriteFile(filePath, signingKeysBuf, 0o555) //nolint:gosec // test code
|
|
So(err, ShouldBeNil)
|
|
err = signature.GenerateNotationCerts(t.TempDir(), "cert")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
Convey("keysuite already exists in signingkeys.json", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
notationDir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
certName := "cert-test"
|
|
filePath := path.Join(notationDir, "signingkeys.json")
|
|
keyPath := path.Join(notationDir, "localkeys", certName+".key")
|
|
certPath := path.Join(notationDir, "localkeys", certName+".crt")
|
|
signingKeys := notconfig.SigningKeys{}
|
|
keySuite := notconfig.KeySuite{
|
|
Name: certName,
|
|
X509KeyPair: ¬config.X509KeyPair{
|
|
KeyPath: keyPath,
|
|
CertificatePath: certPath,
|
|
},
|
|
}
|
|
signingKeys.Keys = []notconfig.KeySuite{keySuite}
|
|
signingKeysBuf, err := json.Marshal(signingKeys)
|
|
So(err, ShouldBeNil)
|
|
err = os.WriteFile(filePath, signingKeysBuf, 0o600)
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.GenerateNotationCerts(t.TempDir(), certName)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
Convey("truststore files", t, func() {
|
|
tempDir := t.TempDir()
|
|
|
|
notationDir := path.Join(tempDir, "notation")
|
|
err := os.Mkdir(notationDir, 0o777)
|
|
So(err, ShouldBeNil)
|
|
|
|
certName := "cert-test"
|
|
trustStorePath := path.Join(notationDir, fmt.Sprintf("truststore/x509/ca/%s", certName))
|
|
err = os.MkdirAll(trustStorePath, 0o755)
|
|
So(err, ShouldBeNil)
|
|
err = os.Chmod(path.Join(notationDir, "truststore/x509"), 0o000)
|
|
So(err, ShouldBeNil)
|
|
|
|
signature.NotationPathLock.Lock()
|
|
defer signature.NotationPathLock.Unlock()
|
|
|
|
signature.LoadNotationPath(tempDir)
|
|
|
|
err = signature.GenerateNotationCerts(tempDir, certName)
|
|
So(err, ShouldNotBeNil)
|
|
|
|
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
|
|
So(err, ShouldBeNil)
|
|
err = os.Chmod(path.Join(notationDir, "truststore/x509"), 0o755)
|
|
So(err, ShouldBeNil)
|
|
_, err = os.Create(path.Join(trustStorePath, "cert-test.crt"))
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.GenerateNotationCerts(tempDir, certName)
|
|
So(err, ShouldNotBeNil)
|
|
|
|
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
|
|
So(err, ShouldBeNil)
|
|
err = os.Remove(path.Join(trustStorePath, "cert-test.crt"))
|
|
So(err, ShouldBeNil)
|
|
err = os.Chmod(path.Join(notationDir, "truststore/x509/ca", certName), 0o555)
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.GenerateNotationCerts(tempDir, certName)
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
}
|