Skip to content

Commit

Permalink
Add bundle signature verification
Browse files Browse the repository at this point in the history
As part of container image we also have detached gpg bundle signature
and this pr is verify that with bundle to make sure bundle is coming
from us.
  • Loading branch information
praveenkumar committed Jul 6, 2022
1 parent 14f57d6 commit 3eeb176
Show file tree
Hide file tree
Showing 64 changed files with 12,365 additions and 1 deletion.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.4
github.com/Masterminds/semver/v3 v3.1.1
github.com/Microsoft/go-winio v0.5.2
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135
github.com/RedHatQE/gowinx v0.0.3
github.com/YourFin/binappend v0.0.0-20181105185800-0add4bf0b9ad
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
Expand Down Expand Up @@ -192,6 +193,7 @@ require (

replace (
github.com/apcera/gssapi => github.com/openshift/gssapi v0.0.0-20161010215902-5fb4217df13b
golang.org/x/crypto/openpgp => github.com/ProtonMail/go-crypto/openpgp v0.0.0-20220623141421-5afb4c282135

k8s.io/kubectl => github.com/openshift/kubernetes-kubectl v0.0.0-20220124124213-df787b5b471c
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135 h1:xDc/cFH/hwyr9KyWc0sm26lpsscqtfZBvU8NpRLHwJ0=
github.com/ProtonMail/go-crypto v0.0.0-20220623141421-5afb4c282135/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
Expand Down
15 changes: 15 additions & 0 deletions pkg/crc/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ const (
RegistryURI = "quay.io/crcont"
ClusterDomain = ".crc.testing"
AppsDomain = ".apps-crc.testing"

GPGPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYrvgDRYJKwYBBAHaRw8BAQdAoW+hjSRYpTAdLEE1u6ZuYNER1g97e8ygT4ic
mvo1AKi0MmNyYyAoS2V5IHRvIHNpZ24gYnVuZGxlIHVzZWQgYnkgY3JjKSA8Y3Jj
QGNyYy5kZXY+iJkEExYKAEEWIQS4RlW/rByOBn/ZyofcfqxAChv9+wUCYrvgDQIb
AwUJEswDAAULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRDcfqxAChv9+/ep
APwISi03R7npwimqdL7NYKDGMO8ikOwmmPkqh9CKwt4CdwD8Cc6HNcZumHDpJ4gH
x7FXxIS9KLwDihpm1Gxr4t1t5Qy4OARiu+ANEgorBgEEAZdVAQUBAQdA/w7pM7hf
bxZ2qwSuoBuhcA1sAlPSb3NrIZf3CceoqzQDAQgHiH4EGBYKACYWIQS4RlW/rByO
Bn/ZyofcfqxAChv9+wUCYrvgDQIbDAUJEswDAAAKCRDcfqxAChv9+2UkAQCNCdaf
vnhbvfPHDltmwDZ3aD4l3jjSKpeySeKQocgjQAD6A7kawst/50k4wb+vUDUnEoYo
9Ix7lKfKWCXil/z0vg4=
=lmb/
-----END PGP PUBLIC KEY BLOCK-----`
)

var adminHelperExecutableForOs = map[string]string{
Expand Down
96 changes: 96 additions & 0 deletions pkg/crc/gpg/gpg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package gpg

import (
"bytes"
"errors"
"fmt"
"io"
"os"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/code-ready/crc/pkg/crc/constants"
)

func readSignature(signatureFilePath string) (*packet.Signature, error) {
sigFile, err := os.Open(signatureFilePath)
if err != nil {
return nil, err
}
sigFileBlock, err := armor.Decode(sigFile)
if err != nil {
sigFile.Close()
return nil, fmt.Errorf("error decoding signature file: %w", err)
}
if sigFileBlock.Type != openpgp.SignatureType {
sigFile.Close()
return nil, errors.New("not an armored signature")
}

sigFileBody, err := packet.Read(sigFileBlock.Body)
if err != nil {
sigFile.Close()
return nil, fmt.Errorf("error reading signature file: %w", err)
}
signature, ok := sigFileBody.(*packet.Signature)
if !ok {
sigFile.Close()
return nil, errors.New("not a valid signature file")
}
return signature, sigFile.Close()
}

func getPublicKey() (*packet.PublicKey, error) {
pubKeyBlock, err := armor.Decode(bytes.NewReader([]byte(constants.GPGPublicKey)))
if err != nil {
return nil, fmt.Errorf("error decoding public key: %s", err)
}
if pubKeyBlock.Type != openpgp.PublicKeyType {
return nil, errors.New("not an armored public key")
}

pubKeyBody, err := packet.Read(pubKeyBlock.Body)
if err != nil {
return nil, fmt.Errorf("error reading public key: %s", err)
}

// Was it really a public key file ? If yes, get the PublicKey
publicKey, ok := pubKeyBody.(*packet.PublicKey)
if !ok {
return nil, errors.New("invalid public key")
}
return publicKey, nil
}

func Verify(filePath, signatureFilePath string) error {
f, err := os.Open(filePath)
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()

signature, err := readSignature(signatureFilePath)
if err != nil {
return err
}

publicKey, err := getPublicKey()
if err != nil {
return err
}

// Get the hash method used for the signature
hash := signature.Hash.New()
_, err = io.Copy(hash, f)
if err != nil {
return err
}

// Check the signature
return publicKey.VerifySignature(hash, signature)
}
18 changes: 17 additions & 1 deletion pkg/crc/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"

"github.com/code-ready/crc/pkg/crc/constants"
"github.com/code-ready/crc/pkg/crc/gpg"
"github.com/code-ready/crc/pkg/crc/logging"
crcpreset "github.com/code-ready/crc/pkg/crc/preset"
"github.com/code-ready/crc/pkg/crc/version"
Expand Down Expand Up @@ -112,9 +113,24 @@ func PullBundle(preset crcpreset.Preset) error {
if err != nil {
return err
}
_, err = extract.Uncompress(filepath.Join(destDir, imgLayer), constants.MachineCacheDir, true)
fileList, err := extract.Uncompress(filepath.Join(destDir, imgLayer), constants.MachineCacheDir, true)
if err != nil {
return err
}
logging.Debugf("Bundle and sign path %v", fileList)

logging.Info("Verifying the bundle signature...")
if len(fileList) != 2 {
return fmt.Errorf("image layer contains more files than expected %v", fileList)
}
bundleFilePath, sigFilePath := fileList[0], fileList[1]
if !strings.HasSuffix(sigFilePath, ".crcbundle.sig") {
sigFilePath, bundleFilePath = fileList[0], fileList[1]
}

if err := gpg.Verify(bundleFilePath, sigFilePath); err != nil {
return err
}

return nil
}
3 changes: 3 additions & 0 deletions vendor/github.com/ProtonMail/go-crypto/AUTHORS

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

3 changes: 3 additions & 0 deletions vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS

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

27 changes: 27 additions & 0 deletions vendor/github.com/ProtonMail/go-crypto/LICENSE

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

22 changes: 22 additions & 0 deletions vendor/github.com/ProtonMail/go-crypto/PATENTS

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

Loading

0 comments on commit 3eeb176

Please sign in to comment.