0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-01-20 22:52:51 -05:00
zot/pkg/extensions/imagetrust/cosign.go

145 lines
2.9 KiB
Go
Raw Normal View History

//go:build imagetrust
// +build imagetrust
package imagetrust
import (
"bytes"
"context"
"crypto"
"encoding/base64"
refactor(extensions)!: refactor the extensions URLs and errors (#1636) BREAKING CHANGE: The functionality provided by the mgmt endpoint has beed redesigned - see details below BREAKING CHANGE: The API keys endpoint has been moved - see details below BREAKING CHANGE: The mgmt extension config has been removed - endpoint is now enabled by having both the search and the ui extensions enabled BREAKING CHANGE: The API keys configuration has been moved from extensions to http>auth>apikey mgmt and imagetrust extensions: - separate the _zot/ext/mgmt into 3 separate endpoints: _zot/ext/auth, _zot/ext/notation, _zot/ext/cosign - signature verification logic is in a separate `imagetrust` extension - better hanling or errors in case of signature uploads: logging and error codes (more 400 and less 500 errors) - add authz on signature uploads (and add a new middleware in common for this purpose) - remove the mgmt extension configuration - it is now enabled if the UI and the search extensions are enabled userprefs estension: - userprefs are enabled if both search and ui extensions are enabled (as opposed to just search) apikey extension is removed and logic moved into the api folder - Move apikeys code out of pkg/extensions and into pkg/api - Remove apikey configuration options from the extensions configuration and move it inside the http auth section - remove the build label apikeys other changes: - move most of the logic adding handlers to the extensions endpoints out of routes.go and into the extensions files. - add warnings in case the users are still using configurations with the obsolete settings for mgmt and api keys - add a new function in the extension package which could be a single point of starting backgroud tasks for all extensions - more clear methods for verifying specific extensions are enabled - fix http methods paired with the UI handlers - rebuild swagger docs Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
2023-08-02 21:58:34 +03:00
"fmt"
"io"
"os"
"path"
godigest "github.com/opencontainers/go-digest"
"github.com/sigstore/cosign/v2/pkg/cosign/pkcs11key"
sigs "github.com/sigstore/cosign/v2/pkg/signature"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"
zerr "zotregistry.io/zot/errors"
)
const cosignDirRelativePath = "_cosign"
var cosignDir = "" //nolint:gochecknoglobals
func InitCosignDir(rootDir string) error {
dir := path.Join(rootDir, cosignDirRelativePath)
_, err := os.Stat(dir)
if os.IsNotExist(err) {
err = os.MkdirAll(dir, defaultDirPerms)
if err != nil {
return err
}
}
if err == nil {
cosignDir = dir
}
return err
}
func GetCosignDirPath() (string, error) {
if cosignDir != "" {
return cosignDir, nil
}
return "", zerr.ErrSignConfigDirNotSet
}
func VerifyCosignSignature(
repo string, digest godigest.Digest, signatureKey string, layerContent []byte,
) (string, bool, error) {
cosignDir, err := GetCosignDirPath()
if err != nil {
return "", false, err
}
files, err := os.ReadDir(cosignDir)
if err != nil {
return "", false, err
}
for _, file := range files {
if !file.IsDir() {
// cosign verify the image
ctx := context.Background()
keyRef := path.Join(cosignDir, file.Name())
hashAlgorithm := crypto.SHA256
pubKey, err := sigs.PublicKeyFromKeyRefWithHashAlgo(ctx, keyRef, hashAlgorithm)
if err != nil {
continue
}
pkcs11Key, ok := pubKey.(*pkcs11key.Key)
if ok {
defer pkcs11Key.Close()
}
verifier := pubKey
b64sig := signatureKey
signature, err := base64.StdEncoding.DecodeString(b64sig)
if err != nil {
continue
}
compressed := io.NopCloser(bytes.NewReader(layerContent))
payload, err := io.ReadAll(compressed)
if err != nil {
continue
}
err = verifier.VerifySignature(bytes.NewReader(signature), bytes.NewReader(payload), options.WithContext(ctx))
if err == nil {
publicKey, err := os.ReadFile(keyRef)
if err != nil {
continue
}
return string(publicKey), true, nil
}
}
}
return "", false, nil
}
func UploadPublicKey(publicKeyContent []byte) error {
// validate public key
if ok, err := validatePublicKey(publicKeyContent); !ok {
return err
}
// add public key to "{rootDir}/_cosign/{name.pub}"
configDir, err := GetCosignDirPath()
if err != nil {
return err
}
name := godigest.FromBytes(publicKeyContent)
// store public key
publicKeyPath := path.Join(configDir, name.String())
return os.WriteFile(publicKeyPath, publicKeyContent, defaultFilePerms)
}
func validatePublicKey(publicKeyContent []byte) (bool, error) {
_, err := cryptoutils.UnmarshalPEMToPublicKey(publicKeyContent)
if err != nil {
refactor(extensions)!: refactor the extensions URLs and errors (#1636) BREAKING CHANGE: The functionality provided by the mgmt endpoint has beed redesigned - see details below BREAKING CHANGE: The API keys endpoint has been moved - see details below BREAKING CHANGE: The mgmt extension config has been removed - endpoint is now enabled by having both the search and the ui extensions enabled BREAKING CHANGE: The API keys configuration has been moved from extensions to http>auth>apikey mgmt and imagetrust extensions: - separate the _zot/ext/mgmt into 3 separate endpoints: _zot/ext/auth, _zot/ext/notation, _zot/ext/cosign - signature verification logic is in a separate `imagetrust` extension - better hanling or errors in case of signature uploads: logging and error codes (more 400 and less 500 errors) - add authz on signature uploads (and add a new middleware in common for this purpose) - remove the mgmt extension configuration - it is now enabled if the UI and the search extensions are enabled userprefs estension: - userprefs are enabled if both search and ui extensions are enabled (as opposed to just search) apikey extension is removed and logic moved into the api folder - Move apikeys code out of pkg/extensions and into pkg/api - Remove apikey configuration options from the extensions configuration and move it inside the http auth section - remove the build label apikeys other changes: - move most of the logic adding handlers to the extensions endpoints out of routes.go and into the extensions files. - add warnings in case the users are still using configurations with the obsolete settings for mgmt and api keys - add a new function in the extension package which could be a single point of starting backgroud tasks for all extensions - more clear methods for verifying specific extensions are enabled - fix http methods paired with the UI handlers - rebuild swagger docs Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
2023-08-02 21:58:34 +03:00
return false, fmt.Errorf("%w: %w", zerr.ErrInvalidPublicKeyContent, err)
}
return true, nil
}