Skip to content

Commit

Permalink
Sign bundles published from archives and during copy (#3202)
Browse files Browse the repository at this point in the history
* feat: Support signing bundles during copy

Make it possible to sign bundles during copy between repositories.
This is handle by creating a new signature, NOT by copying the potential
existing signature. This is done for two reasons:

1. A signature might not be present on the source bundle
1. Repositories might use different digest algorithms or calculate the digest differently

Signed-off-by: Kim Christensen <[email protected]>

---------

Signed-off-by: Kim Christensen <[email protected]>
  • Loading branch information
kichristensen authored Sep 30, 2024
1 parent 2a084ea commit 25c11c7
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 44 deletions.
1 change: 1 addition & 0 deletions cmd/porter/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ If the source bundle is a digest reference, destination must be a tagged referen
cmd.Flag("force").Annotations = map[string][]string{
"viper-key": {"force-overwrite"},
}
f.BoolVar(&opts.SignBundle, "sign-bundle", false, "Sign the bundle using the configured signing plugin")

return &cmd
}
1 change: 1 addition & 0 deletions docs/content/docs/references/cli/bundles_copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ porter bundles copy [flags]
--force Force push the bundle to overwrite the previously published bundle
-h, --help help for copy
--insecure-registry Don't require TLS for registries
--sign-bundle Sign the bundle using the configured signing plugin
--source string The fully qualified source bundle, including tag or digest.
```

Expand Down
1 change: 1 addition & 0 deletions docs/content/docs/references/cli/copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ porter copy [flags]
--force Force push the bundle to overwrite the previously published bundle
-h, --help help for copy
--insecure-registry Don't require TLS for registries
--sign-bundle Sign the bundle using the configured signing plugin
--source string The fully qualified source bundle, including tag or digest.
```

Expand Down
21 changes: 20 additions & 1 deletion pkg/porter/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type CopyOpts struct {
Destination string
InsecureRegistry bool
Force bool
SignBundle bool
}

// Validate performs validation logic on the options specified for a bundle copy
Expand Down Expand Up @@ -98,9 +99,27 @@ func (p *Porter) CopyBundle(ctx context.Context, opts *CopyOpts) error {

bunRef.Reference = destinationRef

_, err = p.Registry.PushBundle(ctx, bunRef, regOpts)
bunRef, err = p.Registry.PushBundle(ctx, bunRef, regOpts)
if err != nil {
return span.Error(fmt.Errorf("unable to copy bundle to new location: %w", err))
}

if opts.SignBundle {
for _, invImage := range bunRef.Definition.InvocationImages {
relocInvImage := bunRef.RelocationMap[invImage.Image]
span.Debugf("Signing bundle image %s...", relocInvImage)
err = p.Signer.Sign(ctx, relocInvImage)
if err != nil {
return span.Errorf("failed to sign image %s: %w", relocInvImage, err)
}
}

span.Debugf("Signing bundle %s", bunRef.Reference.String())
err = p.Signer.Sign(ctx, bunRef.Reference.String())
if err != nil {
return span.Errorf("failed to bundle %s: %w", bunRef.Reference.String(), err)
}
}

return nil
}
3 changes: 3 additions & 0 deletions pkg/porter/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ func (p *Porter) InstallBundle(ctx context.Context, opts InstallOptions) error {
}

invocationImage := bun.Definition.InvocationImages[0].Image
if relocInvImage, ok := bun.RelocationMap[invocationImage]; ok {
invocationImage = relocInvImage
}
log.Debugf("verifying bundle image signature for %s", invocationImage)
err = p.Signer.Verify(ctx, invocationImage)
if err != nil {
Expand Down
34 changes: 32 additions & 2 deletions pkg/porter/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,12 @@ func (p *Porter) publishFromFile(ctx context.Context, opts PublishOptions) error
return log.Errorf("error calculation temporary image tag: %w", err)
}
log.Debugf("Signing bundle image %s.", inImage.String())
err = p.Signer.Sign(context.Background(), inImage.String())
err = p.signImage(ctx, inImage)
if err != nil {
return log.Errorf("error signing bundle image: %w", err)
}
log.Debugf("Signing bundle artifact %s.", bundleRef.Reference.String())
err = p.Signer.Sign(context.Background(), bundleRef.Reference.String())
err = p.signImage(ctx, bundleRef.Reference)
if err != nil {
return log.Errorf("error signing bundle artifact: %w", err)
}
Expand Down Expand Up @@ -311,6 +311,19 @@ func (p *Porter) publishFromArchive(ctx context.Context, opts PublishOptions) er
}

bundleRef.RelocationMap = relocMap

if opts.SignBundle {
relocInvImage := relocMap[invImg.Image]
log.Debugf("Signing bundle image %s...", relocInvImage)
invImageRef, err := cnab.ParseOCIReference(relocInvImage)
if err != nil {
return log.Errorf("failed to parse OCI reference %s: %w", relocInvImage, err)
}
err = p.signImage(ctx, invImageRef)
if err != nil {
return log.Errorf("failed to sign image %s: %w", invImageRef.String(), err)
}
}
}
for _, img := range bundleRef.Definition.Images {
relocMap, err := p.relocateImage(bundleRef.RelocationMap, layout, img.Image, opts.Reference)
Expand All @@ -322,6 +335,14 @@ func (p *Porter) publishFromArchive(ctx context.Context, opts PublishOptions) er
}

bundleRef, err = p.Registry.PushBundle(ctx, bundleRef, regOpts)
if opts.SignBundle {
log.Debugf("Signing bundle %s...", bundleRef.String())
err = p.signImage(ctx, bundleRef.Reference)
if err != nil {
return log.Errorf("failed to sign bundle %s: %w", bundleRef.String(), err)
}
}

if err != nil {
return err
}
Expand Down Expand Up @@ -491,3 +512,12 @@ func (p *Porter) refreshCachedBundle(bundleRef cnab.BundleReference) error {
}
return nil
}

// signImage signs a image using the configured signing plugin
func (p *Porter) signImage(ctx context.Context, ref cnab.OCIReference) error {
_, log := tracing.StartSpan(ctx)
defer log.EndSpan()

log.Debugf("Signing image %s...", ref.String())
return p.Signer.Sign(context.Background(), ref.String())
}
Loading

0 comments on commit 25c11c7

Please sign in to comment.