Skip to content

Commit

Permalink
feat: add validation of required fields in the bundle (#189)
Browse files Browse the repository at this point in the history
* feat: add validation of required fields in the bundle

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* feat: add function for validating bundle

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: go mod

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: go mod tidy

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: bundle validation tests

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

---------

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
  • Loading branch information
vishal-chdhry authored Jul 29, 2024
1 parent 6c61245 commit b06e631
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
36 changes: 36 additions & 0 deletions pkg/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ func (b *ProtobufBundle) validate() error {
return fmt.Errorf("%w: bundle version %s is not yet supported", ErrUnsupportedMediaType, bundleVersion)
}

err = validateBundle(b.Bundle)
if err != nil {
return fmt.Errorf("invalid bundle: %w", err)
}
return nil
}

Expand Down Expand Up @@ -158,6 +162,38 @@ func getBundleVersion(mediaType string) (string, error) {
return "", fmt.Errorf("%w: %s", ErrUnsupportedMediaType, mediaType)
}

func validateBundle(b *protobundle.Bundle) error {
if b == nil {
return fmt.Errorf("empty protobuf bundle")
}

if b.Content == nil {
return fmt.Errorf("missing bundle content")
}

switch b.Content.(type) {
case *protobundle.Bundle_DsseEnvelope, *protobundle.Bundle_MessageSignature:
default:
return fmt.Errorf("invalid bundle content: bundle content must be either a message signature or dsse envelope")
}

if b.VerificationMaterial == nil {
return fmt.Errorf("missing verification material")
}

if b.VerificationMaterial.Content == nil {
return fmt.Errorf("missing verification material content")
}

switch b.VerificationMaterial.Content.(type) {
case *protobundle.VerificationMaterial_PublicKey, *protobundle.VerificationMaterial_Certificate, *protobundle.VerificationMaterial_X509CertificateChain:
default:
return fmt.Errorf("invalid verififcation material content: verification material must be one of public key, x509 certificate and x509 certificate chain")
}

return nil
}

func LoadJSONFromPath(path string) (*ProtobufBundle, error) {
var bundle ProtobufBundle
bundle.Bundle = new(protobundle.Bundle)
Expand Down
89 changes: 89 additions & 0 deletions pkg/bundle/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

protobundle "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1"
protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
rekorv1 "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
_ "github.com/sigstore/rekor/pkg/types/hashedrekord"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -228,6 +229,7 @@ func Test_validate(t *testing.T) {
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.1",
},
},
wantErr: true,
},
{
name: "v0.1 with no inclusion promise",
Expand Down Expand Up @@ -277,7 +279,11 @@ func Test_validate(t *testing.T) {
},
},
},
Content: &protobundle.VerificationMaterial_PublicKey{
PublicKey: &v1.PublicKeyIdentifier{},
},
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
},
Expand All @@ -301,7 +307,11 @@ func Test_validate(t *testing.T) {
CanonicalizedBody: canonicalTlogBody,
},
},
Content: &protobundle.VerificationMaterial_PublicKey{
PublicKey: &v1.PublicKeyIdentifier{},
},
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
wantErr: true,
Expand Down Expand Up @@ -331,7 +341,11 @@ func Test_validate(t *testing.T) {
},
},
},
Content: &protobundle.VerificationMaterial_PublicKey{
PublicKey: &v1.PublicKeyIdentifier{},
},
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
},
Expand Down Expand Up @@ -364,6 +378,7 @@ func Test_validate(t *testing.T) {
X509CertificateChain: &protocommon.X509CertificateChain{},
},
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
wantErr: true,
Expand Down Expand Up @@ -397,6 +412,7 @@ func Test_validate(t *testing.T) {
Certificate: &protocommon.X509Certificate{},
},
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
},
Expand Down Expand Up @@ -749,3 +765,76 @@ func TestTimestamps(t *testing.T) {
})
}
}

func Test_BundleValidation(t *testing.T) {
tests := []struct {
name string
bundle *ProtobufBundle
errMsg string
wantErr bool
}{
{
name: "Empty verification material",
bundle: &ProtobufBundle{
Bundle: &protobundle.Bundle{
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3",
VerificationMaterial: &protobundle.VerificationMaterial{
Content: nil,
},
Content: &protobundle.Bundle_MessageSignature{},
},
},
errMsg: "invalid bundle: missing verification material content",
wantErr: true,
},
{
name: "No bundle content",
bundle: &ProtobufBundle{
Bundle: &protobundle.Bundle{
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3",
Content: nil,
},
},
errMsg: "invalid bundle: missing bundle content",
wantErr: true,
},
{
name: "Nil verification material",
bundle: &ProtobufBundle{
Bundle: &protobundle.Bundle{
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3",
Content: &protobundle.Bundle_MessageSignature{},
VerificationMaterial: nil,
},
},
errMsg: "invalid bundle: missing verification material",
wantErr: true,
},
{
name: "Valid protobuf bundle",
bundle: &ProtobufBundle{
Bundle: &protobundle.Bundle{
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3",
Content: &protobundle.Bundle_DsseEnvelope{},
VerificationMaterial: &protobundle.VerificationMaterial{
Content: &protobundle.VerificationMaterial_PublicKey{
PublicKey: &v1.PublicKeyIdentifier{},
},
TimestampVerificationData: &protobundle.TimestampVerificationData{},
},
},
},
errMsg: "",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("name:%s", tt.name), func(t *testing.T) {
err := tt.bundle.validate()
if (err != nil) != tt.wantErr || (err != nil && tt.errMsg != err.Error()) {
t.Errorf("Protobuf.Bundle() error = %v, wantErr %v", err, tt.errMsg)
return
}
})
}
}

0 comments on commit b06e631

Please sign in to comment.