1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
package copy
import (
"context"
"fmt"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/private"
internalsig "github.com/containers/image/v5/internal/signature"
internalSigner "github.com/containers/image/v5/internal/signer"
"github.com/containers/image/v5/signature/simplesigning"
"github.com/containers/image/v5/transports"
)
// setupSigners initializes c.signers.
func (c *copier) setupSigners() error {
c.signers = append(c.signers, c.options.Signers...)
// c.signersToClose is intentionally not updated with c.options.Signers.
// We immediately append created signers to c.signers, and we rely on c.close() to clean them up; so we don’t need
// to clean up any created signers on failure.
if c.options.SignBy != "" {
opts := []simplesigning.Option{
simplesigning.WithKeyFingerprint(c.options.SignBy),
}
if c.options.SignPassphrase != "" {
opts = append(opts, simplesigning.WithPassphrase(c.options.SignPassphrase))
}
signer, err := simplesigning.NewSigner(opts...)
if err != nil {
return err
}
c.signers = append(c.signers, signer)
c.signersToClose = append(c.signersToClose, signer)
}
return nil
}
// sourceSignatures returns signatures from unparsedSource,
// and verifies that they can be used (to avoid copying a large image when we
// can tell in advance that it would ultimately fail)
func (c *copier) sourceSignatures(ctx context.Context, unparsed private.UnparsedImage,
gettingSignaturesMessage, checkingDestMessage string) ([]internalsig.Signature, error) {
var sigs []internalsig.Signature
if c.options.RemoveSignatures {
sigs = []internalsig.Signature{}
} else {
c.Printf("%s\n", gettingSignaturesMessage)
s, err := unparsed.UntrustedSignatures(ctx)
if err != nil {
return nil, fmt.Errorf("reading signatures: %w", err)
}
sigs = s
}
if len(sigs) != 0 {
c.Printf("%s\n", checkingDestMessage)
if err := c.dest.SupportsSignatures(ctx); err != nil {
return nil, fmt.Errorf("Can not copy signatures to %s: %w", transports.ImageName(c.dest.Reference()), err)
}
}
return sigs, nil
}
// createSignatures creates signatures for manifest and an optional identity.
func (c *copier) createSignatures(ctx context.Context, manifest []byte, identity reference.Named) ([]internalsig.Signature, error) {
if len(c.signers) == 0 {
// We must exit early here, otherwise copies with no Docker reference wouldn’t be possible.
return nil, nil
}
if identity != nil {
if reference.IsNameOnly(identity) {
return nil, fmt.Errorf("Sign identity must be a fully specified reference %s", identity.String())
}
} else {
identity = c.dest.Reference().DockerReference()
if identity == nil {
return nil, fmt.Errorf("Cannot determine canonical Docker reference for destination %s", transports.ImageName(c.dest.Reference()))
}
}
res := make([]internalsig.Signature, 0, len(c.signers))
for signerIndex, signer := range c.signers {
msg := internalSigner.ProgressMessage(signer)
if len(c.signers) == 1 {
c.Printf("Creating signature: %s\n", msg)
} else {
c.Printf("Creating signature %d: %s\n", signerIndex+1, msg)
}
newSig, err := internalSigner.SignImageManifest(ctx, signer, manifest, identity)
if err != nil {
if len(c.signers) == 1 {
return nil, fmt.Errorf("creating signature: %w", err)
} else {
return nil, fmt.Errorf("creating signature %d: %w", signerIndex, err)
}
}
res = append(res, newSig)
}
return res, nil
}
|