mirror of
https://github.com/containers/podman.git
synced 2025-08-06 11:32:07 +08:00
Merge pull request #7718 from QiWang19/sign-multi-arch
Sign multi-arch images
This commit is contained in:
@ -47,6 +47,7 @@ func init() {
|
||||
certDirFlagName := "cert-dir"
|
||||
flags.StringVar(&signOptions.CertDir, certDirFlagName, "", "`Pathname` of a directory containing TLS certificates and keys")
|
||||
_ = signCommand.RegisterFlagCompletionFunc(certDirFlagName, completion.AutocompleteDefault)
|
||||
flags.BoolVarP(&signOptions.All, "all", "a", false, "Sign all the manifests of the multi-architecture image")
|
||||
}
|
||||
|
||||
func sign(cmd *cobra.Command, args []string) error {
|
||||
|
@ -19,6 +19,10 @@ By default, the signature will be written into `/var/lib/containers/sigstore` fo
|
||||
|
||||
Print usage statement.
|
||||
|
||||
#### **--all**, **-a**
|
||||
|
||||
Sign all the manifests of the multi-architecture image (default false).
|
||||
|
||||
#### **--cert-dir**=*path*
|
||||
|
||||
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
|
||||
|
@ -344,6 +344,7 @@ type SignOptions struct {
|
||||
Directory string
|
||||
SignBy string
|
||||
CertDir string
|
||||
All bool
|
||||
}
|
||||
|
||||
// SignReport describes the result of signing
|
||||
|
@ -28,6 +28,8 @@ import (
|
||||
"github.com/containers/podman/v2/pkg/rootless"
|
||||
"github.com/containers/podman/v2/pkg/util"
|
||||
"github.com/containers/storage"
|
||||
dockerRef "github.com/docker/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -718,9 +720,9 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
|
||||
logrus.Errorf("unable to close %s image source %q", srcRef.DockerReference().Name(), err)
|
||||
}
|
||||
}()
|
||||
getManifest, _, err := rawSource.GetManifest(ctx, nil)
|
||||
topManifestBlob, manifestType, err := rawSource.GetManifest(ctx, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting getManifest")
|
||||
return errors.Wrapf(err, "error getting manifest blob")
|
||||
}
|
||||
dockerReference := rawSource.Reference().DockerReference()
|
||||
if dockerReference == nil {
|
||||
@ -743,34 +745,34 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
|
||||
return err
|
||||
}
|
||||
}
|
||||
manifestDigest, err := manifest.Digest(getManifest)
|
||||
manifestDigest, err := manifest.Digest(topManifestBlob)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create signature
|
||||
newSig, err := signature.SignDockerManifest(getManifest, dockerReference.String(), mech, options.SignBy)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating new signature")
|
||||
}
|
||||
// create the signstore file
|
||||
signatureDir := fmt.Sprintf("%s@%s=%s", sigStoreDir, manifestDigest.Algorithm(), manifestDigest.Hex())
|
||||
if err := os.MkdirAll(signatureDir, 0751); err != nil {
|
||||
// The directory is allowed to exist
|
||||
if !os.IsExist(err) {
|
||||
logrus.Error(err)
|
||||
return nil
|
||||
if options.All {
|
||||
if !manifest.MIMETypeIsMultiImage(manifestType) {
|
||||
return errors.Errorf("%s is not a multi-architecture image (manifest type %s)", signimage, manifestType)
|
||||
}
|
||||
list, err := manifest.ListFromBlob(topManifestBlob, manifestType)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Error parsing manifest list %q", string(topManifestBlob))
|
||||
}
|
||||
instanceDigests := list.Instances()
|
||||
for _, instanceDigest := range instanceDigests {
|
||||
digest := instanceDigest
|
||||
man, _, err := rawSource.GetManifest(ctx, &digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = putSignature(man, mech, sigStoreDir, instanceDigest, dockerReference, options); err != nil {
|
||||
return errors.Wrapf(err, "error storing signature for %s, %v", dockerReference.String(), instanceDigest)
|
||||
}
|
||||
}
|
||||
}
|
||||
sigFilename, err := getSigFilename(signatureDir)
|
||||
if err != nil {
|
||||
logrus.Errorf("error creating sigstore file: %v", err)
|
||||
return nil
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(signatureDir, sigFilename), newSig, 0644)
|
||||
if err != nil {
|
||||
logrus.Errorf("error storing signature for %s", rawSource.Reference().DockerReference().String())
|
||||
return nil
|
||||
if err = putSignature(topManifestBlob, mech, sigStoreDir, manifestDigest, dockerReference, options); err != nil {
|
||||
return errors.Wrapf(err, "error storing signature for %s, %v", dockerReference.String(), manifestDigest)
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
@ -806,3 +808,26 @@ func localPathFromURI(url *url.URL) (string, error) {
|
||||
}
|
||||
return url.Path, nil
|
||||
}
|
||||
|
||||
// putSignature creates signature and saves it to the signstore file
|
||||
func putSignature(manifestBlob []byte, mech signature.SigningMechanism, sigStoreDir string, instanceDigest digest.Digest, dockerReference dockerRef.Reference, options entities.SignOptions) error {
|
||||
newSig, err := signature.SignDockerManifest(manifestBlob, dockerReference.String(), mech, options.SignBy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signatureDir := fmt.Sprintf("%s@%s=%s", sigStoreDir, instanceDigest.Algorithm(), instanceDigest.Hex())
|
||||
if err := os.MkdirAll(signatureDir, 0751); err != nil {
|
||||
// The directory is allowed to exist
|
||||
if !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
sigFilename, err := getSigFilename(signatureDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(filepath.Join(signatureDir, sigFilename), newSig, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -58,4 +59,19 @@ var _ = Describe("Podman image sign", func() {
|
||||
_, err = os.Stat(filepath.Join(sigDir, "library"))
|
||||
Expect(err).To(BeNil())
|
||||
})
|
||||
|
||||
It("podman sign --all multi-arch 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-multi")
|
||||
err = os.MkdirAll(sigDir, os.ModePerm)
|
||||
Expect(err).To(BeNil())
|
||||
session := podmanTest.Podman([]string{"image", "sign", "--all", "--directory", sigDir, "--sign-by", "foo@bar.com", "docker://library/alpine"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
fInfos, err := ioutil.ReadDir(filepath.Join(sigDir, "library"))
|
||||
Expect(err).To(BeNil())
|
||||
Expect(len(fInfos) > 1).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user