Skip to content

Commit

Permalink
Integrate container image signing in krel stage
Browse files Browse the repository at this point in the history
Pushed images and manifest lists on stage are now signed by using the
release-sdk.

Signed-off-by: Sascha Grunert <[email protected]>
  • Loading branch information
saschagrunert committed Jan 20, 2022
1 parent e01ebb9 commit c9d1fc2
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 11 deletions.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/cheggaaa/pb/v3 v3.0.8
github.com/go-git/go-git/v5 v5.4.2
github.com/golang/protobuf v1.5.2
github.com/google/go-containerregistry v0.7.1-0.20211118220127-abdc633f8305
github.com/google/go-containerregistry v0.8.0
github.com/google/go-github/v39 v39.2.0
github.com/google/uuid v1.3.0
github.com/hashicorp/go-multierror v1.1.1
Expand All @@ -35,7 +35,7 @@ require (
sigs.k8s.io/bom v0.1.1-0.20211228172218-5dc67098b61b
sigs.k8s.io/mdtoc v1.1.0
sigs.k8s.io/promo-tools/v3 v3.3.0
sigs.k8s.io/release-sdk v0.6.0
sigs.k8s.io/release-sdk v0.6.1-0.20220119112205-bf90f85874ce
sigs.k8s.io/release-utils v0.3.0
sigs.k8s.io/yaml v1.3.0
sigs.k8s.io/zeitgeist v0.3.0
Expand Down Expand Up @@ -97,10 +97,10 @@ require (
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/grpc v1.43.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
Expand Down
13 changes: 8 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.7.0/go.mod h1:2zaoelrL0d08gGbpdP3LqyUuBmhWbpD6IOe2s9nLS2k=
github.com/google/go-containerregistry v0.7.1-0.20211118220127-abdc633f8305 h1:4upgCb+N0/tewaAT+rPGk8zuKCG1hOoICHvFMxy1CMQ=
github.com/google/go-containerregistry v0.7.1-0.20211118220127-abdc633f8305/go.mod h1:6cMIl1RfryEiPzBE67OgtZdEiLWz4myqCQIiBMy3CsM=
github.com/google/go-containerregistry v0.8.0 h1:mtR24eN6rapCN+shds82qFEIWWmg64NPMuyCNT7/Ogc=
github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI=
github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM=
github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
github.com/google/go-github/v34 v34.0.0 h1:/siYFImY8KwGc5QD1gaPf+f8QX6tLwxNIco2RkYxoFA=
Expand Down Expand Up @@ -1406,8 +1407,9 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down Expand Up @@ -1640,8 +1642,9 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
Expand Down Expand Up @@ -1755,8 +1758,8 @@ sigs.k8s.io/mdtoc v1.1.0/go.mod h1:QZLVEdHH2iNIR4uHAZyvFRtjloHgVItk8lo/mzCtq3w=
sigs.k8s.io/promo-tools/v3 v3.3.0 h1:lpXFhB1+fM1/uOmXehhl72JqoK66o4aowGsOIO5irRQ=
sigs.k8s.io/promo-tools/v3 v3.3.0/go.mod h1:hGHcj+AuxenaCG6sI76p9KKUSijlyNjv4X8MULS1yeA=
sigs.k8s.io/release-sdk v0.5.0/go.mod h1:m7EwAKZb9Hua+b8pXnJLMJ/5WY/Fs1CeqxBZYXx0u0A=
sigs.k8s.io/release-sdk v0.6.0 h1:fs8stFuU/15UATcZxKzD7CUv5/sYge85e3Jds5TaaNE=
sigs.k8s.io/release-sdk v0.6.0/go.mod h1:m7EwAKZb9Hua+b8pXnJLMJ/5WY/Fs1CeqxBZYXx0u0A=
sigs.k8s.io/release-sdk v0.6.1-0.20220119112205-bf90f85874ce h1:Ywfxc8W0cAu5Whr0Jh74dlZxPQPbFiJpoaYkRG63Ex8=
sigs.k8s.io/release-sdk v0.6.1-0.20220119112205-bf90f85874ce/go.mod h1:o0cC5ugZigdTwvMUj+ohstTEATmF7R4fHa8j/iFomzw=
sigs.k8s.io/release-utils v0.2.0/go.mod h1:9O5livl2h3Q56jUkoZ7UnV22XVRB6MuD4l/51C2vAPg=
sigs.k8s.io/release-utils v0.3.0 h1:cyNeXvm+2lPn67f4MWmq9xapZDAI5hekpT7iQPRxta4=
sigs.k8s.io/release-utils v0.3.0/go.mod h1:J9xpziRNRI4mAeMZxPRryDodQMoMudMu6yC1aViFHU4=
Expand Down
41 changes: 39 additions & 2 deletions pkg/release/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,22 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"

"sigs.k8s.io/release-sdk/sign"
"sigs.k8s.io/release-utils/command"
)

// Images is a wrapper around container image related functionality
type Images struct {
client commandClient
signer *sign.Signer
}

// NewImages creates a new Images instance
func NewImages() *Images {
return &Images{&defaultCommandClient{}}
return &Images{
client: &defaultCommandClient{},
signer: sign.New(sign.Default()),
}
}

// SetClient can be used to set the internal command client
Expand All @@ -51,6 +56,8 @@ type commandClient interface {
Execute(cmd string, args ...string) error
ExecuteOutput(cmd string, args ...string) (string, error)
RepoTagFromTarball(path string) (string, error)
Sign(*sign.Signer, string) error
Verify(*sign.Signer, string) error
}

type defaultCommandClient struct{}
Expand Down Expand Up @@ -78,6 +85,16 @@ func (*defaultCommandClient) RepoTagFromTarball(path string) (string, error) {
return tagOutput.OutputTrimNL(), nil
}

func (*defaultCommandClient) Sign(signer *sign.Signer, reference string) error {
_, err := signer.Sign(reference)
return err
}

func (*defaultCommandClient) Verify(signer *sign.Signer, reference string) error {
_, err := signer.Verify(reference)
return err
}

var tagRegex = regexp.MustCompile(`^.+/(.+):.+$`)

// PublishImages releases container images to the provided target registry
Expand Down Expand Up @@ -113,6 +130,10 @@ func (i *Images) Publish(registry, version, buildPath string) error {
return errors.Wrap(err, "push container image")
}

if err := i.client.Sign(i.signer, newTagWithArch); err != nil {
return errors.Wrap(err, "sign container image")
}

if err := i.client.Execute(
"docker", "rmi", origTag, newTagWithArch,
); err != nil {
Expand Down Expand Up @@ -166,6 +187,10 @@ func (i *Images) Publish(registry, version, buildPath string) error {
); err != nil {
return errors.Wrap(err, "push manifest")
}

if err := i.client.Sign(i.signer, imageVersion); err != nil {
return errors.Wrap(err, "sign manifest list")
}
}

return nil
Expand All @@ -178,7 +203,14 @@ func (i *Images) Validate(registry, version, buildPath string) error {
version = i.normalizeVersion(version)

manifestImages, err := i.getManifestImages(
registry, version, buildPath, nil,
registry, version, buildPath,
func(_, _, image string) error {
logrus.Infof("Verifying that image is signed: %s", image)
return errors.Wrap(
i.client.Verify(i.signer, image),
"verify signed image",
)
},
)
if err != nil {
return errors.Wrap(err, "get manifest images")
Expand All @@ -195,6 +227,11 @@ func (i *Images) Validate(registry, version, buildPath string) error {
)
}

logrus.Info("Verifying that image manifest list is signed")
if err := i.client.Verify(i.signer, imageVersion); err != nil {
return errors.Wrap(err, "verify signed manifest list")
}

manifest := string(manifestBytes)
manifestFile, err := os.CreateTemp("", "manifest-")
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions pkg/release/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,32 @@ func TestPublish(t *testing.T) {
},
shouldError: true,
},
{ // failure on sign image
prepare: func(mock *releasefakes.FakeCommandClient) (string, func()) {
tempDir := newImagesPath(t)
prepareImages(t, tempDir, mock)

mock.SignReturns(errors.New(""))

return tempDir, func() {
require.Nil(t, os.RemoveAll(tempDir))
}
},
shouldError: true,
},
{ // failure on sign manifest
prepare: func(mock *releasefakes.FakeCommandClient) (string, func()) {
tempDir := newImagesPath(t)
prepareImages(t, tempDir, mock)

mock.SignReturnsOnCall(10, errors.New(""))

return tempDir, func() {
require.Nil(t, os.RemoveAll(tempDir))
}
},
shouldError: true,
},
} {
sut := release.NewImages()
clientMock := &releasefakes.FakeCommandClient{}
Expand Down
154 changes: 154 additions & 0 deletions pkg/release/releasefakes/fake_command_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c9d1fc2

Please sign in to comment.