mirror of
https://github.com/containers/podman.git
synced 2025-06-27 05:26:50 +08:00
Merge pull request #7081 from QiWang19/sigature-store
fix bug podman sign storage path
This commit is contained in:
1
go.mod
1
go.mod
@ -62,7 +62,6 @@ require (
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
k8s.io/api v0.18.6
|
||||
k8s.io/apimachinery v0.18.6
|
||||
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -682,10 +683,6 @@ func (ir *ImageEngine) Shutdown(_ context.Context) {
|
||||
}
|
||||
|
||||
func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entities.SignOptions) (*entities.SignReport, error) {
|
||||
dockerRegistryOptions := image.DockerRegistryOptions{
|
||||
DockerCertPath: options.CertDir,
|
||||
}
|
||||
|
||||
mech, err := signature.NewGPGSigningMechanism()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error initializing GPG")
|
||||
@ -704,7 +701,6 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
|
||||
}
|
||||
|
||||
for _, signimage := range names {
|
||||
var sigStoreDir string
|
||||
srcRef, err := alltransports.ParseImageName(signimage)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing image name")
|
||||
@ -725,40 +721,38 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
|
||||
if dockerReference == nil {
|
||||
return nil, errors.Errorf("cannot determine canonical Docker reference for destination %s", transports.ImageName(rawSource.Reference()))
|
||||
}
|
||||
|
||||
// create the signstore file
|
||||
rtc, err := ir.Libpod.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newImage, err := ir.Libpod.ImageRuntime().New(ctx, signimage, rtc.Engine.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: options.SignBy}, nil, util.PullImageMissing)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error pulling image %s", signimage)
|
||||
var sigStoreDir string
|
||||
if options.Directory != "" {
|
||||
sigStoreDir = options.Directory
|
||||
}
|
||||
if sigStoreDir == "" {
|
||||
if rootless.IsRootless() {
|
||||
sigStoreDir = filepath.Join(filepath.Dir(ir.Libpod.StorageConfig().GraphRoot), "sigstore")
|
||||
} else {
|
||||
var sigStoreURI string
|
||||
registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs)
|
||||
if registryInfo != nil {
|
||||
if sigStoreDir = registryInfo.SigStoreStaging; sigStoreDir == "" {
|
||||
sigStoreDir = registryInfo.SigStore
|
||||
|
||||
if sigStoreURI = registryInfo.SigStoreStaging; sigStoreURI == "" {
|
||||
sigStoreURI = registryInfo.SigStore
|
||||
}
|
||||
}
|
||||
if sigStoreURI == "" {
|
||||
return nil, errors.Errorf("no signature storage configuration found for %s", rawSource.Reference().DockerReference().String())
|
||||
|
||||
}
|
||||
sigStoreDir, err = localPathFromURI(sigStoreURI)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid signature storage %s", sigStoreURI)
|
||||
}
|
||||
}
|
||||
}
|
||||
sigStoreDir, err = isValidSigStoreDir(sigStoreDir)
|
||||
manifestDigest, err := manifest.Digest(getManifest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid signature storage %s", sigStoreDir)
|
||||
return nil, err
|
||||
}
|
||||
repos, err := newImage.RepoDigests()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error calculating repo digests for %s", signimage)
|
||||
}
|
||||
if len(repos) == 0 {
|
||||
logrus.Errorf("no repodigests associated with the image %s", signimage)
|
||||
continue
|
||||
repo := reference.Path(dockerReference)
|
||||
if path.Clean(repo) != repo { // Coverage: This should not be reachable because /./ and /../ components are not valid in docker references
|
||||
return nil, errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", dockerReference.String())
|
||||
}
|
||||
|
||||
// create signature
|
||||
@ -766,22 +760,21 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error creating new signature")
|
||||
}
|
||||
|
||||
trimmedDigest := strings.TrimPrefix(repos[0], strings.Split(repos[0], "/")[0])
|
||||
sigStoreDir = filepath.Join(sigStoreDir, strings.Replace(trimmedDigest, ":", "=", 1))
|
||||
if err := os.MkdirAll(sigStoreDir, 0751); err != nil {
|
||||
// create the signstore file
|
||||
signatureDir := fmt.Sprintf("%s@%s=%s", filepath.Join(sigStoreDir, repo), manifestDigest.Algorithm(), manifestDigest.Hex())
|
||||
if err := os.MkdirAll(signatureDir, 0751); err != nil {
|
||||
// The directory is allowed to exist
|
||||
if !os.IsExist(err) {
|
||||
logrus.Errorf("error creating directory %s: %s", sigStoreDir, err)
|
||||
logrus.Errorf("error creating directory %s: %s", signatureDir, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
sigFilename, err := getSigFilename(sigStoreDir)
|
||||
sigFilename, err := getSigFilename(signatureDir)
|
||||
if err != nil {
|
||||
logrus.Errorf("error creating sigstore file: %v", err)
|
||||
continue
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(sigStoreDir, sigFilename), newSig, 0644)
|
||||
err = ioutil.WriteFile(filepath.Join(signatureDir, sigFilename), newSig, 0644)
|
||||
if err != nil {
|
||||
logrus.Errorf("error storing signature for %s", rawSource.Reference().DockerReference().String())
|
||||
continue
|
||||
@ -809,14 +802,12 @@ func getSigFilename(sigStoreDirPath string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func isValidSigStoreDir(sigStoreDir string) (string, error) {
|
||||
writeURIs := map[string]bool{"file": true}
|
||||
func localPathFromURI(sigStoreDir string) (string, error) {
|
||||
url, err := url.Parse(sigStoreDir)
|
||||
if err != nil {
|
||||
return sigStoreDir, errors.Wrapf(err, "invalid directory %s", sigStoreDir)
|
||||
}
|
||||
_, exists := writeURIs[url.Scheme]
|
||||
if !exists {
|
||||
if url.Scheme != "file" {
|
||||
return sigStoreDir, errors.Errorf("writing to %s is not supported. Use a supported scheme", sigStoreDir)
|
||||
}
|
||||
sigStoreDir = url.Path
|
||||
|
@ -12,9 +12,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// PolicyContent struct for policy.json file
|
||||
@ -157,7 +157,7 @@ func HaveMatchRegistry(key string, registryConfigs *RegistryConfiguration) *Regi
|
||||
searchKey = searchKey[:strings.LastIndex(searchKey, "/")]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return registryConfigs.DefaultDocker
|
||||
}
|
||||
|
||||
// CreateTmpFile creates a temp file under dir and writes the content into it
|
||||
|
62
test/e2e/image_sign_test.go
Normal file
62
test/e2e/image_sign_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
// +build !remote
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/containers/podman/v2/test/utils"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Podman image sign", func() {
|
||||
var (
|
||||
origGNUPGHOME string
|
||||
tempdir string
|
||||
err error
|
||||
podmanTest *PodmanTestIntegration
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
tempdir, err = CreateTempDirInTempDir()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
podmanTest = PodmanTestCreate(tempdir)
|
||||
podmanTest.Setup()
|
||||
podmanTest.SeedImages()
|
||||
|
||||
tempGNUPGHOME := filepath.Join(podmanTest.TempDir, "tmpGPG")
|
||||
err := os.Mkdir(tempGNUPGHOME, os.ModePerm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
origGNUPGHOME = os.Getenv("GNUPGHOME")
|
||||
err = os.Setenv("GNUPGHOME", tempGNUPGHOME)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
podmanTest.Cleanup()
|
||||
f := CurrentGinkgoTestDescription()
|
||||
processTestResult(f)
|
||||
os.Setenv("GNUPGHOME", origGNUPGHOME)
|
||||
})
|
||||
|
||||
It("podman sign image", func() {
|
||||
cmd := exec.Command("gpg", "--import", "sign/secret-key.asc")
|
||||
err := cmd.Run()
|
||||
Expect(err).To(BeNil())
|
||||
sigDir := filepath.Join(podmanTest.TempDir, "test-sign")
|
||||
err = os.MkdirAll(sigDir, os.ModePerm)
|
||||
Expect(err).To(BeNil())
|
||||
session := podmanTest.Podman([]string{"image", "sign", "--directory", sigDir, "--sign-by", "foo@bar.com", "docker://library/alpine"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
_, err = os.Stat(filepath.Join(sigDir, "library"))
|
||||
Expect(err).To(BeNil())
|
||||
})
|
||||
})
|
57
test/e2e/sign/secret-key.asc
Normal file
57
test/e2e/sign/secret-key.asc
Normal file
@ -0,0 +1,57 @@
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
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
|
||||
=6kcB
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
Reference in New Issue
Block a user