Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ binary:
@echo "Making $@ ..."
@docker pull neuvector/build_fleet:${BUILD_IMAGE_TAG}
@docker run --rm -ia STDOUT --name build --net=none -v $(CURDIR):/go/src/github.com/neuvector/sigstore-interface -w /go/src/github.com/neuvector/sigstore-interface --entrypoint ./make_bin.sh neuvector/build_fleet:${BUILD_IMAGE_TAG}

test:
go build -ldflags='-s -w' -buildvcs=false . && bash ./integration-test.sh
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ toolchain go1.22.5
require (
github.com/google/go-containerregistry v0.19.1
github.com/sigstore/cosign/v2 v2.2.4
github.com/sigstore/rekor v1.3.6
github.com/sigstore/sigstore v1.8.3
github.com/theupdateframework/go-tuf v0.7.0
)
Expand Down Expand Up @@ -82,7 +83,6 @@ require (
github.com/sassoftware/relic v7.2.1+incompatible // indirect
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/sigstore/rekor v1.3.6 // indirect
github.com/sigstore/timestamp-authority v1.2.2 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
16 changes: 16 additions & 0 deletions integration-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
echo "#############################"
echo "testing rootless keypair only"
echo "#############################"
./sigstore-interface --config-file testing/cases/rootless-keypair-only.json
echo ""

echo "#############################"
echo "testing public keypair"
echo "#############################"
./sigstore-interface --config-file testing/cases/public-keypair.json
echo ""

echo "#############################"
echo "testing suse app collection"
echo "#############################"
./sigstore-interface --config-file testing/cases/suse-app-collection.json
50 changes: 38 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import (
"github.com/sigstore/cosign/v2/pkg/oci"
"github.com/sigstore/cosign/v2/pkg/oci/signature"
sig "github.com/sigstore/cosign/v2/pkg/signature"
rekor "github.com/sigstore/rekor/pkg/client"
"github.com/sigstore/sigstore/pkg/cryptoutils"
sigtuf "github.com/sigstore/sigstore/pkg/tuf"
)

const DEFAULT_REKOR_URL string = "https://rekor.sigstore.dev"

type Configuration struct {
ImageDigest string `json:"ImageDigest"`
RootsOfTrust []RootOfTrust `json:"RootsOfTrust"`
Expand Down Expand Up @@ -159,6 +162,10 @@ func generateCosignSignatureObjects(sigData SignatureData) ([]oci.Signature, err
return signatures, nil
}

func printWarningLine(message string) {
fmt.Printf("\033[33m%s\033[0m\n", message)
}

func verify(imgDigest v1.Hash, rootOfTrust RootOfTrust, sigs []oci.Signature, proxy Proxy) (satisfiedVerifiers []string, err error) {
ctx := context.Background()
cosignOptions := cosign.CheckOpts{ClaimVerifier: cosign.SimpleClaimVerifier}
Expand All @@ -169,22 +176,35 @@ func verify(imgDigest v1.Hash, rootOfTrust RootOfTrust, sigs []oci.Signature, pr
for _, verifier := range rootOfTrust.Verifiers {
cosignOptions.SigVerifier = nil
cosignOptions.Identities = nil

fmt.Printf(">> checking verifier %s\n", verifier.Name)
err = setVerifierCosignOptions(&cosignOptions, verifier, rootOfTrust, ctx)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, signature := range sigs {
fmt.Printf("verifying signature %d\n", i)
_, err := cosign.VerifyImageSignature(ctx, signature, imgDigest, &cosignOptions)
if err != nil {
// the image is not signed by this verifier
fmt.Printf("signature not verified: %s\n", err.Error())
} else {
fmt.Printf("signature %d satisfies verifier %s\n", i, verifier.Name)
satisfiedVerifiers = append(satisfiedVerifiers, fmt.Sprintf("%s/%s", rootOfTrust.Name, verifier.Name))
break
}
fmt.Println("could not create valid cosign options for verifier, skipping verifier")
continue
}

for i, signature := range sigs {
bundle, err := signature.Bundle()
if err != nil {
fmt.Printf("error when retrieving bundle for signature, skipping signature: %s\n", err.Error())
continue
}
if bundle == nil {
printWarningLine("no bundle found, any tlog verification must happen through network")
} else {
fmt.Printf("signature bundle: %s\n", bundle.Payload.LogID)
}
fmt.Printf("verifying signature %d\n", i)
_, err = cosign.VerifyImageSignature(ctx, signature, imgDigest, &cosignOptions)
if err != nil {
// the image is not signed by this verifier
fmt.Printf("signature not verified: %s\n", err.Error())
} else {
fmt.Printf("signature %d satisfies verifier %s\n", i, verifier.Name)
satisfiedVerifiers = append(satisfiedVerifiers, fmt.Sprintf("%s/%s", rootOfTrust.Name, verifier.Name))
break
}
}
}
Expand Down Expand Up @@ -319,6 +339,12 @@ func setVerifierCosignOptions(cosignOptions *cosign.CheckOpts, verifier Verifier
if rootOfTrust.SCTPublicKey == "" {
cosignOptions.IgnoreSCT = true
}
} else {
rekorClient, err := rekor.GetRekorClient(DEFAULT_REKOR_URL)
if err != nil {
return fmt.Errorf("could not get rekor client for online tlog validation: %s", err.Error())
}
cosignOptions.RekorClient = rekorClient
}
if rootOfTrust.RootlessKeypairsOnly {
cosignOptions.IgnoreSCT = true
Expand Down
28 changes: 28 additions & 0 deletions testing/cases/public-keypair.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"ImageDigest": "sha256:c2ced31c5dda37cb805f481e3fa34b742cc8980f439b20af3111b08e66cff8e1",
"RootsOfTrust": [
{
"Name": "public-root-of-trust",
"RootlessKeypairsOnly": false,
"Verifiers": [
{
"Name": "esther-keypair",
"Type": "keypair",
"KeyPairOptions": {
"PublicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbAOAuM6OwpU/buX7td4VvyKUGyI6\nwXPSUQjeQwc2wzr4wNveeQ4LbZbtH8bAohoOwfgeHUiVFwpgGIB6d+J3hw==\n-----END PUBLIC KEY-----"
},
"KeylessOptions": {
"CertIssuer": "",
"CertSubject": ""
}
}
]
}
],
"SignatureData": {
"Manifest": "{\"schemaVersion\":2,\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"size\":243,\"digest\":\"sha256:ff9575f3be16905499996bc3f8045d86ce9d9f8aabdd192c47eb3824f7df30da\"},\"layers\":[{\"mediaType\":\"application/vnd.dev.cosign.simplesigning.v1+json\",\"size\":243,\"digest\":\"sha256:19cf962d284f30ff6d6b5744e61f8f200311c35aac53e5f50019aea690582e4b\",\"annotations\":{\"dev.cosignproject.cosign/signature\":\"MEYCIQCz8Hg3Ad/d5Pe5/I+jWlgIpKsRyY8YKvwiuqYPrQK2DgIhAMe/lJN08Ylieb22rJ9D7LEP5QJHruAX6GGgQ+RZyi5N\",\"dev.sigstore.cosign/bundle\":\"{\\\"SignedEntryTimestamp\\\":\\\"MEUCIHol8ZGEFFDNSIDL36wuBwOwRmqzLMcUxHVDbFB0jkW7AiEAsI1nquIgcg6/jvDOt2Tj6dMJdvIR4/dgyrUgG3VgNd0=\\\",\\\"Payload\\\":{\\\"body\\\":\\\"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxOWNmOTYyZDI4NGYzMGZmNmQ2YjU3NDRlNjFmOGYyMDAzMTFjMzVhYWM1M2U1ZjUwMDE5YWVhNjkwNTgyZTRiIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUN6OEhnM0FkL2Q1UGU1L0kraldsZ0lwS3NSeVk4WUt2d2l1cVlQclFLMkRnSWhBTWUvbEpOMDhZbGllYjIycko5RDdMRVA1UUpIcnVBWDZHR2dRK1JaeWk1TiIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGWWtGUFFYVk5OazkzY0ZVdlluVllOM1JrTkZaMmVVdFZSM2xKTmdwM1dGQlRWVkZxWlZGM1l6SjNlbkkwZDA1MlpXVlJORXhpV21KMFNEaGlRVzlvYjA5M1ptZGxTRlZwVmtaM2NHZEhTVUkyWkN0S00yaDNQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=\\\",\\\"integratedTime\\\":1685639122,\\\"logIndex\\\":22394206,\\\"logID\\\":\\\"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\\\"}}\"}}]}",
"Payloads": {
"sha256:19cf962d284f30ff6d6b5744e61f8f200311c35aac53e5f50019aea690582e4b": "{\"critical\":{\"identity\":{\"docker-reference\":\"quay.io/nvlab/cosign-esther\"},\"image\":{\"docker-manifest-digest\":\"sha256:c2ced31c5dda37cb805f481e3fa34b742cc8980f439b20af3111b08e66cff8e1\"},\"type\":\"cosign container image signature\"},\"optional\":null}"
}
}
}
28 changes: 28 additions & 0 deletions testing/cases/rootless-keypair-only.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"ImageDigest": "sha256:c2ced31c5dda37cb805f481e3fa34b742cc8980f439b20af3111b08e66cff8e1",
"RootsOfTrust": [
{
"Name": "public-root-of-trust",
"RootlessKeypairsOnly": true,
"Verifiers": [
{
"Name": "esther-keypair",
"Type": "keypair",
"KeyPairOptions": {
"PublicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbAOAuM6OwpU/buX7td4VvyKUGyI6\nwXPSUQjeQwc2wzr4wNveeQ4LbZbtH8bAohoOwfgeHUiVFwpgGIB6d+J3hw==\n-----END PUBLIC KEY-----"
},
"KeylessOptions": {
"CertIssuer": "",
"CertSubject": ""
}
}
]
}
],
"SignatureData": {
"Manifest": "{\"schemaVersion\":2,\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"size\":243,\"digest\":\"sha256:ff9575f3be16905499996bc3f8045d86ce9d9f8aabdd192c47eb3824f7df30da\"},\"layers\":[{\"mediaType\":\"application/vnd.dev.cosign.simplesigning.v1+json\",\"size\":243,\"digest\":\"sha256:19cf962d284f30ff6d6b5744e61f8f200311c35aac53e5f50019aea690582e4b\",\"annotations\":{\"dev.cosignproject.cosign/signature\":\"MEYCIQCz8Hg3Ad/d5Pe5/I+jWlgIpKsRyY8YKvwiuqYPrQK2DgIhAMe/lJN08Ylieb22rJ9D7LEP5QJHruAX6GGgQ+RZyi5N\",\"dev.sigstore.cosign/bundle\":\"{\\\"SignedEntryTimestamp\\\":\\\"MEUCIHol8ZGEFFDNSIDL36wuBwOwRmqzLMcUxHVDbFB0jkW7AiEAsI1nquIgcg6/jvDOt2Tj6dMJdvIR4/dgyrUgG3VgNd0=\\\",\\\"Payload\\\":{\\\"body\\\":\\\"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxOWNmOTYyZDI4NGYzMGZmNmQ2YjU3NDRlNjFmOGYyMDAzMTFjMzVhYWM1M2U1ZjUwMDE5YWVhNjkwNTgyZTRiIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUN6OEhnM0FkL2Q1UGU1L0kraldsZ0lwS3NSeVk4WUt2d2l1cVlQclFLMkRnSWhBTWUvbEpOMDhZbGllYjIycko5RDdMRVA1UUpIcnVBWDZHR2dRK1JaeWk1TiIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGWWtGUFFYVk5OazkzY0ZVdlluVllOM1JrTkZaMmVVdFZSM2xKTmdwM1dGQlRWVkZxWlZGM1l6SjNlbkkwZDA1MlpXVlJORXhpV21KMFNEaGlRVzlvYjA5M1ptZGxTRlZwVmtaM2NHZEhTVUkyWkN0S00yaDNQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=\\\",\\\"integratedTime\\\":1685639122,\\\"logIndex\\\":22394206,\\\"logID\\\":\\\"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\\\"}}\"}}]}",
"Payloads": {
"sha256:19cf962d284f30ff6d6b5744e61f8f200311c35aac53e5f50019aea690582e4b": "{\"critical\":{\"identity\":{\"docker-reference\":\"quay.io/nvlab/cosign-esther\"},\"image\":{\"docker-manifest-digest\":\"sha256:c2ced31c5dda37cb805f481e3fa34b742cc8980f439b20af3111b08e66cff8e1\"},\"type\":\"cosign container image signature\"},\"optional\":null}"
}
}
}
24 changes: 24 additions & 0 deletions testing/cases/suse-app-collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"ImageDigest": "sha256:30e637c70f75c9f22ee0f2b4d0c3471ad3ed2f153f994ec5fe1031ab27d4282c",
"RootsOfTrust": [
{
"Name": "public-root",
"Verifiers": [
{
"Name": "suse-app-collection-key",
"Type": "keypair",
"KeypairOptions": {
"PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA02FtEt5gBywiyxbmkVsb\nCujcBg5lur0kpEbfDk10gCcs9shVEqEO3ZsOXHursgoaDAWqdPtsYhsgczGeJz9w\nAw+r6BuRV8YOkE37A8s/7IOQUW0tlqtnt11OKhIiZ9+e5l3ed2H1ymKQO3dgreSy\nrShqYdA3hrItswyp41ApF6zhjSPlR6lAmq3X4wMYLAPptmzfxigTnR4hxB5UNPhs\ni2qA4vLrUM/i+NohECuLr1EAymvupH26HLEdM+eZnlQn+WbhIP5Grc4ba7XrBv7K\nkywgTC7CxkiJZR0mUcUD2wTX/Je8Ewj6oPSalx09e2jtzvmU5Kr9XUyMF7Zsj5CA\nIwIDAQAB\n-----END PUBLIC KEY-----"
},
"KeylessOptions": {}
}
]
}
],
"SignatureData": {
"Manifest": "{\"schemaVersion\":2,\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"size\":233,\"digest\":\"sha256:d68903a35c7e4df921427de185d2fb6238c26fbe98e87151b3245900732ba626\"},\"layers\":[{\"mediaType\":\"application/vnd.dev.cosign.simplesigning.v1+json\",\"size\":266,\"digest\":\"sha256:f29eb2be43ee8b54274fcf03e548e3029e96c3babaad27dcdd39a7e13ff82ddb\",\"annotations\":{\"dev.cosignproject.cosign/signature\":\"gj5seEtnOF6Ct4aBkHT/axoiG5rvcJ1zcUv06pnwWCELpRpg7Tp8PFfSP5wjCfO24B1joWpljU16vFKgebYO/yumcNYGy4z7b8tls46QG9dEmMDgwg/bhYk6/r9avVqpdTvcsyEWyR6ewcT9Pk6E3c3BKUytlz14utwFK3rULvZRX+3MrNYH0DL7Kmc3x/FYAzzrz4ewjOAHF1lc77nxgn2u22lWo+h+9a68AquLhuyV+MUP4PD5uNP+ty+NZTa4zdwgVohNk5gEzD/ZugKVonRRMH0ACniQdm/x5A2oMF0Nw0kBBsiOwhIElLlQGpfW6joarqEZB2wSAhJbhe+rsQ==\",\"org.open-build-service.cosign.cookie\":\"a5e6be82775da3e0f4ea85e70fd6024a7d03ecee62536e0ecb179a40ae750b31\"}}]}",
"Payloads": {
"sha256:f29eb2be43ee8b54274fcf03e548e3029e96c3babaad27dcdd39a7e13ff82ddb": "{\"critical\":{\"identity\":{\"docker-reference\":\"dp.apps.rancher.io/containers/openjdk\"},\"image\":{\"docker-manifest-digest\":\"sha256:30e637c70f75c9f22ee0f2b4d0c3471ad3ed2f153f994ec5fe1031ab27d4282c\"},\"type\":\"cosign container image signature\"},\"optional\":{\"creator\":\"OBS\"}}"
}
}
}
104 changes: 104 additions & 0 deletions vendor/github.com/sigstore/rekor/pkg/client/options.go

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

66 changes: 66 additions & 0 deletions vendor/github.com/sigstore/rekor/pkg/client/rekor_client.go

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

1 change: 1 addition & 0 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ github.com/sigstore/cosign/v2/pkg/signature
github.com/sigstore/cosign/v2/pkg/types
# github.com/sigstore/rekor v1.3.6
## explicit; go 1.21
github.com/sigstore/rekor/pkg/client
github.com/sigstore/rekor/pkg/generated/client
github.com/sigstore/rekor/pkg/generated/client/entries
github.com/sigstore/rekor/pkg/generated/client/index
Expand Down
Loading