Skip to content

Commit

Permalink
Merge branch 'main' into update-crd-version
Browse files Browse the repository at this point in the history
  • Loading branch information
binbin-li committed Mar 3, 2023
2 parents 9a24017 + 8ed9ccf commit 9224321
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 15 deletions.
55 changes: 44 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ KUBERNETES_VERSION ?= 1.25.4
GATEKEEPER_VERSION ?= 3.11.0
COSIGN_VERSION ?= 1.13.1
NOTATION_VERSION ?= 1.0.0-rc.2
ORAS_VERSION ?= 1.0.0-rc.1

HELM_VERSION ?= 3.9.2
BATS_TESTS_FILE ?= test/bats/test.bats
Expand Down Expand Up @@ -141,11 +142,11 @@ e2e-dependencies:
# Download and install jq
curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 --output ${GITHUB_WORKSPACE}/bin/jq && chmod +x ${GITHUB_WORKSPACE}/bin/jq
# Install ORAS
curl -LO https://github.com/oras-project/oras/releases/download/v0.16.0/oras_0.16.0_linux_amd64.tar.gz
curl -LO https://github.com/oras-project/oras/releases/download/v${ORAS_VERSION}/oras_${ORAS_VERSION}_linux_amd64.tar.gz
mkdir -p oras-install/
tar -zxf oras_0.16.0_*.tar.gz -C oras-install/
tar -zxf oras*.tar.gz -C oras-install/
mv oras-install/oras ${GITHUB_WORKSPACE}/bin
rm -rf oras_0.16.0_*.tar.gz oras-install/
rm -rf oras*.tar.gz oras-install/

KIND_NODE_VERSION := kindest/node:v$(KUBERNETES_VERSION)

Expand All @@ -167,7 +168,7 @@ e2e-create-local-registry:
${LOCAL_REGISTRY_IMAGE}

docker login -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} ${LOCAL_TEST_REGISTRY}
oras login \
${GITHUB_WORKSPACE}/bin/oras login \
-u ${LOCAL_TEST_REGISTRY_USERNAME} \
-p ${LOCAL_TEST_REGISTRY_PASSWORD} \
${LOCAL_TEST_REGISTRY}
Expand Down Expand Up @@ -204,6 +205,9 @@ e2e-notaryv2-setup:
echo 'FROM alpine\nCMD ["echo", "notaryv2 signed image"]' > .staging/notaryv2/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/notation:signed .staging/notaryv2
docker push ${LOCAL_TEST_REGISTRY}/notation:signed
echo 'FROM alpine\nCMD ["echo", "notaryv2 signed image OCI Image"]' > .staging/notaryv2/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/notation:signedImage .staging/notaryv2
docker push ${LOCAL_TEST_REGISTRY}/notation:signedImage

docker pull ${LOCAL_UNSIGNED_IMAGE}
docker image tag ${LOCAL_UNSIGNED_IMAGE} ${LOCAL_TEST_REGISTRY}/notation:unsigned
Expand All @@ -212,6 +216,7 @@ e2e-notaryv2-setup:
rm -rf ~/.config/notation
.staging/notaryv2/notation cert generate-test --default "ratify-bats-test"
.staging/notaryv2/notation sign -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} `docker image inspect ${LOCAL_TEST_REGISTRY}/notation:signed | jq -r .[0].RepoDigests[0]`
.staging/notaryv2/notation sign --signature-manifest image -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} `docker image inspect ${LOCAL_TEST_REGISTRY}/notation:signedImage | jq -r .[0].RepoDigests[0]`
.staging/notaryv2/notation sign -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} `docker image inspect ${LOCAL_TEST_REGISTRY}/all:v0 | jq -r .[0].RepoDigests[0]`

e2e-cosign-setup:
Expand Down Expand Up @@ -249,13 +254,23 @@ e2e-licensechecker-setup:
docker build -t ${LOCAL_TEST_REGISTRY}/licensechecker:v0 .staging/licensechecker
docker push ${LOCAL_TEST_REGISTRY}/licensechecker:v0

# Build/Push OCI Image Signature
echo 'FROM alpine@sha256:93d5a28ff72d288d69b5997b8ba47396d2cbb62a72b5d87cd3351094b5d578a0\nCMD ["echo", "licensechecker image oci image"]' > .staging/licensechecker/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/licensechecker:ociimage .staging/licensechecker
docker push ${LOCAL_TEST_REGISTRY}/licensechecker:ociimage

# Create/Attach SPDX
.staging/licensechecker/syft -o spdx --file .staging/licensechecker/sbom.spdx ${LOCAL_TEST_REGISTRY}/licensechecker:v0
oras attach ${LOCAL_TEST_REGISTRY}/licensechecker:v0 \
${GITHUB_WORKSPACE}/bin/oras attach ${LOCAL_TEST_REGISTRY}/licensechecker:v0 \
--artifact-type application/vnd.ratify.spdx.v0 \
--plain-http \
.staging/licensechecker/sbom.spdx:application/text
oras attach ${LOCAL_TEST_REGISTRY}/all:v0 \
${GITHUB_WORKSPACE}/bin/oras attach ${LOCAL_TEST_REGISTRY}/licensechecker:ociimage \
--artifact-type application/vnd.ratify.spdx.v0 \
--plain-http \
--image-spec v1.1-image \
.staging/licensechecker/sbom.spdx:application/text
${GITHUB_WORKSPACE}/bin/oras attach ${LOCAL_TEST_REGISTRY}/all:v0 \
--artifact-type application/vnd.ratify.spdx.v0 \
--plain-http \
.staging/licensechecker/sbom.spdx:application/text
Expand All @@ -272,30 +287,40 @@ e2e-sbom-setup:
echo 'FROM alpine\nCMD ["echo", "sbom image"]' > .staging/sbom/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/sbom:v0 .staging/sbom
docker push ${LOCAL_TEST_REGISTRY}/sbom:v0
echo 'FROM alpine\nCMD ["echo", "sbom image oci image"]' > .staging/sbom/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/sbom:ociimage .staging/sbom
docker push ${LOCAL_TEST_REGISTRY}/sbom:ociimage
echo 'FROM alpine\nCMD ["echo", "sbom image unsigned"]' > .staging/sbom/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/sbom:unsigned .staging/sbom
docker push ${LOCAL_TEST_REGISTRY}/sbom:unsigned

# Generate/Attach sbom
.staging/sbom/sbom-tool generate -b .staging/sbom -bc .staging/sbom/ratify -pn ratify -m .staging/sbom -pv 1.0 -ps acme -nsu ratify -nsb http://registry:5000 -D true
oras attach \
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type org.example.sbom.v0 \
--plain-http \
${LOCAL_TEST_REGISTRY}/sbom:v0 \
.staging/sbom/_manifest/spdx_2.2/manifest.spdx.json:application/spdx+json
oras attach \
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type org.example.sbom.v0 \
--plain-http \
--image-spec v1.1-image \
${LOCAL_TEST_REGISTRY}/sbom:ociimage \
.staging/sbom/_manifest/spdx_2.2/manifest.spdx.json:application/spdx+json
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type org.example.sbom.v0 \
--plain-http \
${LOCAL_TEST_REGISTRY}/sbom:unsigned \
.staging/sbom/_manifest/spdx_2.2/manifest.spdx.json:application/spdx+json
oras attach \
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type org.example.sbom.v0 \
--plain-http \
${LOCAL_TEST_REGISTRY}/all:v0 \
.staging/sbom/_manifest/spdx_2.2/manifest.spdx.json:application/spdx+json

# Push Signature to sbom
.staging/notaryv2/notation sign -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} ${LOCAL_TEST_REGISTRY}/sbom@`oras discover -o json --artifact-type org.example.sbom.v0 ${LOCAL_TEST_REGISTRY}/sbom:v0 | jq -r ".manifests[0].digest"`
.staging/notaryv2/notation sign --signature-manifest image -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} ${LOCAL_TEST_REGISTRY}/sbom@`oras discover -o json --artifact-type org.example.sbom.v0 ${LOCAL_TEST_REGISTRY}/sbom:ociimage | jq -r ".manifests[0].digest"`
.staging/notaryv2/notation sign -u ${LOCAL_TEST_REGISTRY_USERNAME} -p ${LOCAL_TEST_REGISTRY_PASSWORD} ${LOCAL_TEST_REGISTRY}/all@`oras discover -o json --artifact-type org.example.sbom.v0 ${LOCAL_TEST_REGISTRY}/all:v0 | jq -r ".manifests[0].digest"`

e2e-schemavalidator-setup:
Expand All @@ -310,14 +335,22 @@ e2e-schemavalidator-setup:
echo 'FROM alpine\nCMD ["echo", "schemavalidator image"]' > .staging/schemavalidator/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/schemavalidator:v0 .staging/schemavalidator
docker push ${LOCAL_TEST_REGISTRY}/schemavalidator:v0
echo 'FROM alpine\nCMD ["echo", "schemavalidator image oci image"]' > .staging/schemavalidator/Dockerfile
docker build -t ${LOCAL_TEST_REGISTRY}/schemavalidator:ociimage .staging/schemavalidator
docker push ${LOCAL_TEST_REGISTRY}/schemavalidator:ociimage

# Create/Attach Scan Results
.staging/schemavalidator/trivy image --format sarif --output .staging/schemavalidator/trivy-scan.sarif ${LOCAL_TEST_REGISTRY}/schemavalidator:v0
oras attach \
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type vnd.aquasecurity.trivy.report.sarif.v1 \
${LOCAL_TEST_REGISTRY}/schemavalidator:v0 \
.staging/schemavalidator/trivy-scan.sarif:application/sarif+json
oras attach \
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type vnd.aquasecurity.trivy.report.sarif.v1 \
${LOCAL_TEST_REGISTRY}/schemavalidator:ociimage \
--image-spec v1.1-image \
.staging/schemavalidator/trivy-scan.sarif:application/sarif+json
${GITHUB_WORKSPACE}/bin/oras attach \
--artifact-type vnd.aquasecurity.trivy.report.sarif.v1 \
${LOCAL_TEST_REGISTRY}/all:v0 \
.staging/schemavalidator/trivy-scan.sarif:application/sarif+json
Expand Down
1 change: 0 additions & 1 deletion pkg/ocispecs/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type ReferenceManifest struct {
ArtifactType string `json:"artifactType,omitempty"`
Blobs []oci.Descriptor `json:"blobs"`
Subject *oci.Descriptor `json:"subject,omitempty"`
Layers []oci.Descriptor `json:"layers"`
Annotations map[string]string `json:"annotations,omitempty"`
}

Expand Down
15 changes: 13 additions & 2 deletions pkg/referrerstore/oras/oras.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,20 @@ func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReferen
}

referenceManifest := ocispecs.ReferenceManifest{}

// marshal manifest bytes into reference manifest descriptor
if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
return ocispecs.ReferenceManifest{}, err
if referenceDesc.Descriptor.MediaType == oci.MediaTypeImageManifest {
var imageManifest oci.Manifest
if err := json.Unmarshal(manifestBytes, &imageManifest); err != nil {
return ocispecs.ReferenceManifest{}, err
}
referenceManifest = OciManifestToReferenceManifest(imageManifest)
} else if referenceDesc.Descriptor.MediaType == oci.MediaTypeArtifactManifest {
if err := json.Unmarshal(manifestBytes, &referenceManifest); err != nil {
return ocispecs.ReferenceManifest{}, err
}
} else {
return ocispecs.ReferenceManifest{}, fmt.Errorf("unsupported manifest media type: %s", referenceDesc.Descriptor.MediaType)
}

return referenceManifest, nil
Expand Down
10 changes: 10 additions & 0 deletions pkg/referrerstore/oras/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,13 @@ func OciDescriptorToReferenceDescriptor(ociDescriptor oci.Descriptor) ocispecs.R
ArtifactType: ociDescriptor.ArtifactType,
}
}

func OciManifestToReferenceManifest(ociManifest oci.Manifest) ocispecs.ReferenceManifest {
return ocispecs.ReferenceManifest{
MediaType: ociManifest.MediaType,
ArtifactType: ociManifest.Config.MediaType,
Blobs: ociManifest.Layers,
Subject: ociManifest.Subject,
Annotations: ociManifest.Annotations,
}
}
93 changes: 93 additions & 0 deletions pkg/referrerstore/oras/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright The Ratify Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package oras

import (
"reflect"
"testing"

"github.com/deislabs/ratify/pkg/ocispecs"
oci "github.com/opencontainers/image-spec/specs-go/v1"
)

func TestOciManifestToReferenceManifest(t *testing.T) {
type args struct {
ociManifest oci.Manifest
}
tests := []struct {
name string
args args
want ocispecs.ReferenceManifest
}{
{
name: "empty",
args: args{
ociManifest: oci.Manifest{},
},
want: ocispecs.ReferenceManifest{
MediaType: "",
ArtifactType: "",
},
},
{
name: "simple",
args: args{
ociManifest: oci.Manifest{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Config: oci.Descriptor{
MediaType: "application/vnd.oci.image.config.v1+json",
},
},
},
want: ocispecs.ReferenceManifest{
MediaType: "application/vnd.oci.image.manifest.v1+json",
ArtifactType: "application/vnd.oci.image.config.v1+json",
},
},
{
name: "layers",
args: args{
ociManifest: oci.Manifest{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Config: oci.Descriptor{
MediaType: "application/vnd.oci.image.config.v1+json",
},
Layers: []oci.Descriptor{
{
MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
},
},
},
},
want: ocispecs.ReferenceManifest{
MediaType: "application/vnd.oci.image.manifest.v1+json",
ArtifactType: "application/vnd.oci.image.config.v1+json",
Blobs: []oci.Descriptor{
{
MediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := OciManifestToReferenceManifest(tt.args.ociManifest); !reflect.DeepEqual(got, tt.want) {
t.Errorf("OciManifestToReferenceManifest() = %v, want %v", got, tt.want)
}
})
}
}
4 changes: 4 additions & 0 deletions pkg/verifier/notaryv2/notaryv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ func (v *notaryV2Verifier) Verify(ctx context.Context,
return verifier.VerifierResult{IsSuccess: false}, fmt.Errorf("failed to get reference manifest for reference: %s, err: %w", subjectReference.Original, err)
}

if len(referenceManifest.Blobs) == 0 {
return verifier.VerifierResult{IsSuccess: false}, fmt.Errorf("no signature content found for referrer: %s@%s", subjectReference.Path, referenceDescriptor.Digest.String())
}

for _, blobDesc := range referenceManifest.Blobs {
refBlob, err := store.GetBlobContent(ctx, subjectReference, blobDesc.Digest)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion plugins/verifier/cosign/cosign.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
}

signatures := []oci.Signature{}
for _, blob := range referenceManifest.Layers {
for _, blob := range referenceManifest.Blobs {
blobBytes, err := referrerStore.GetBlobContent(ctx, subjectReference, blob.Digest)
if err != nil {
return errorToVerifyResult(input.Config.Name, fmt.Errorf("failed to get blob content: %w", err)), nil
Expand Down
8 changes: 8 additions & 0 deletions plugins/verifier/licensechecker/licensechecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, desc
return nil, err
}

if len(referenceManifest.Blobs) == 0 {
return &verifier.VerifierResult{
Name: input.Name,
IsSuccess: false,
Message: fmt.Sprintf("License Check FAILED: no blobs found for referrer %s@%s", subjectReference.Path, descriptor.Digest.String()),
}, nil
}

for _, blobDesc := range referenceManifest.Blobs {
refBlob, err := store.GetBlobContent(ctx, subjectReference, blobDesc.Digest)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions plugins/verifier/schemavalidator/schema_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ func VerifyReference(args *skel.CmdArgs, subjectReference common.Reference, refe
return nil, fmt.Errorf("error fetching reference manifest for subject: %s reference descriptor: %v", subjectReference, referenceDescriptor.Descriptor)
}

if len(referenceManifest.Blobs) == 0 {
return &verifier.VerifierResult{
Name: input.Name,
IsSuccess: false,
Message: fmt.Sprintf("schema validation failed: no blobs found for referrer %s@%s", subjectReference.Path, referenceDescriptor.Digest.String()),
}, nil
}

for _, blobDesc := range referenceManifest.Blobs {
refBlob, err := referrerStore.GetBlobContent(ctx, subjectReference, blobDesc.Digest)
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions test/bats/cli-test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ load helpers
run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/notation:signed
assert_cmd_verify_success

# Test with OCI Image Manifest Signature
run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/notation:signedImage
assert_cmd_verify_success

run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/notation:unsigned
assert_cmd_verify_failure
}
Expand All @@ -25,6 +29,10 @@ load helpers
run bin/ratify verify -c $RATIFY_DIR/complete_licensechecker_config.json -s $LOCAL_TEST_REGISTRY/licensechecker:v0
assert_cmd_verify_success

# Test with OCI Image Manifest Signature
run bin/ratify verify -c $RATIFY_DIR/complete_licensechecker_config.json -s $LOCAL_TEST_REGISTRY/licensechecker:ociimage
assert_cmd_verify_success

run bin/ratify verify -c $RATIFY_DIR/partial_licensechecker_config.json -s $LOCAL_TEST_REGISTRY/licensechecker:v0
assert_cmd_verify_failure
}
Expand All @@ -34,13 +42,21 @@ load helpers
run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/sbom:v0
assert_cmd_verify_success

# Test with OCI Image Manifest Signature
run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/sbom:ociimage
assert_cmd_verify_success

run bin/ratify verify -c $RATIFY_DIR/config.json -s $LOCAL_TEST_REGISTRY/sbom:unsigned
assert_cmd_verify_failure
}

@test "schemavalidator verifier test" {
run bin/ratify verify -c $RATIFY_DIR/schemavalidator_config.json -s $LOCAL_TEST_REGISTRY/schemavalidator:v0
assert_cmd_verify_success

# Test with OCI Image Manifest Signature
run bin/ratify verify -c $RATIFY_DIR/schemavalidator_config.json -s $LOCAL_TEST_REGISTRY/schemavalidator:ociimage
assert_cmd_verify_success
}

@test "sbom/notary/cosign/licensechecker verifiers test" {
Expand Down
Loading

0 comments on commit 9224321

Please sign in to comment.