notaryproject / notation-go

A collection of libraries for supporting sign and verify OCI artifacts. Based on Notary Project specifications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

application/jose+json is not supported

phbelitz opened this issue · comments

What is not working as expected?

After integrating notation-go into a Kubernetes admission controller and trying to verify the image ghcr.io/deislabs/ratify/notary-image:signed, verification fails with unable to parse the digital signature, error : signature envelope format with media type \"application/jose+json\" is not supported.

What did you expect to happen?

notation-go should support signature formats it itself created and successfully validate the signature of ghcr.io/deislabs/ratify/notary-image:signed.

How can we reproduce it?

The image ghcr.io/deislabs/ratify/notary-image:signed was used and for verification the following certificate:

-----BEGIN CERTIFICATE-----
MIIDQzCCAiugAwIBAgIUDxHQ9JxxmnrLWTA5rAtIZCzY8mMwDQYJKoZIhvcNAQEL
BQAwKTEPMA0GA1UECgwGUmF0aWZ5MRYwFAYDVQQDDA1SYXRpZnkgU2FtcGxlMB4X
DTIzMDYyOTA1MjgzMloXDTMzMDYyNjA1MjgzMlowKTEPMA0GA1UECgwGUmF0aWZ5
MRYwFAYDVQQDDA1SYXRpZnkgU2FtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAshmsL2VM9ojhgTVUUuEsZro9jfI27VKZJ4naWSHJihmOki7IoZS8
3/3ATpkE1lGbduJ77M9UxQbEW1PnESB0bWtMQtjIbser3mFCn15yz4nBXiTIu/K4
FYv6HVdc6/cds3jgfEFNw/8RVMBUGNUiSEWa1lV1zDM2v/8GekUr6SNvMyqtY8oo
ItwxfUvlhgMNlLgd96mVnnPVLmPkCmXFN9iBMhSce6sn6P9oDIB+pr1ZpE4F5bwa
gRBg2tWN3Tz9H/z2a51Xbn7hCT5OLBRlkorHJl2HKKRoXz1hBgR8xOL+zRySH9Qo
3yx6WvluYDNfVbCREzKJf9fFiQeVe0EJOwIDAQABo2MwYTAdBgNVHQ4EFgQUKzci
EKCDwPBn4I1YZ+sDdnxEir4wHwYDVR0jBBgwFoAUKzciEKCDwPBn4I1YZ+sDdnxE
ir4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQEL
BQADggEBAGh6duwc1MvV+PUYvIkDfgj158KtYX+bv4PmcV/aemQUoArqM1ECYFjt
BlBVmTRJA0lijU5I0oZje80zW7P8M8pra0BM6x3cPnh/oZGrsuMizd4h5b5TnwuJ
hRvKFFUVeHn9kORbyQwRQ5SpL8cRGyYp+T6ncEmo0jdIOM5dgfdhwHgb+i3TejcF
90sUs65zovUjv1wa11SqOdu12cCj/MYp+H8j2lpaLL2t0cbFJlBY6DNJgxr5qync
cz8gbXrZmNbzC7W5QK5J7fcx6tlffOpt5cm427f9NiK2tira50HU7gC3HJkbiSTp
Xw10iXXMZzSbQ0/Hj2BF4B40WfAkgRg=
-----END CERTIFICATE-----

Here a shortened version of the code I used (took away lots of the error handling and surrounding logic):

type NotaryV2Validator struct {
	Name        string
	Type        string
	Trust_store truststore.X509TrustStore
}

func (nv2v *NotaryV2Validator) ValidateImage(
	ctx context.Context,
	image name.Reference,
	args policy.RuleOptions,
) (string, error) {
	img, tag := transformImage(image)

	policy, _ := nv2v.setUpTrustPolicy(img, args)
	ver, _ := verifier.New(policy, nv2v.Trust_store, nil)
	remoteRepo, _ := remote.NewRepository(img + tag)
	remoteRegistry := registry.NewRepository(remoteRepo)

	desc, _ := remoteRegistry.Resolve(nv2_ctx, img+tag)
	exampleVerifyOptions := notation.VerifyOptions{
		ArtifactReference:    fmt.Sprintf("%s@%s", img, desc.Digest.String()),
		MaxSignatureAttempts: 50,
	}

	digest, _, err := notation.Verify(nv2_ctx, ver, remoteRegistry, exampleVerifyOptions)
	if err != nil {
		return "", fmt.Errorf("failed to verify image: %s", err)
	}

	return string(digest.Digest), nil
}

func (nv2v *NotaryV2Validator) setUpTrustPolicy(
	image string,
	args policy.RuleOptions,
) (*trustpolicy.Document, error) {
	// imtr stores the certificates to be used for verification
	imtr := nv2v.Trust_store.(*InMemoryTrustStore)
	// selects all the certificates to use, by an overarching policy
	trs, _ := common.GetTrustRoots(args.TrustRoots, imtr.trust_roots, true)

	return &trustpolicy.Document{
		Version: "1.0",
		TrustPolicies: []trustpolicy.TrustPolicy{
			{
				Name:           "default",
				RegistryScopes: []string{image},
				SignatureVerification: trustpolicy.SignatureVerification{
					VerificationLevel: trustpolicy.LevelStrict.Name,
				},
				TrustStores: utils.Map[common.TrustRoot, string](
					trs,
					func(tr common.TrustRoot) string {
						return fmt.Sprintf("ca:%s", tr.Name)
					},
				),
				TrustedIdentities: []string{"*"},
			},
		},
	}, nil
}

Describe your environment

Running inside a distroless/base-debian11 container. The code was compiled to a binary using Go 1.19. The container itself is running inside a Kubernetes cluster as an admission controller.

What is the version of your notation-go Library?

github.com/notaryproject/notation-go v1.0.0

@phbelitz I'm trying to troubleshoot the issue, could you try adding a single line in your code under import:
_ "github.com/notaryproject/notation-core-go/signature/jws".
(Note the underscore _ at the front of the import, since you are not directly using jws package, it won't stand without this underscore.) Let's see if this could fix the issue. Thanks.

@Two-Hearts yes, awesome. I guess i should import the _ "github.com/notaryproject/notation-core-go/signature/cose" aswell? Wasn't aware that those are necessary. Closing this as the problem was fixed.

I guess i should import the _ "github.com/notaryproject/notation-core-go/signature/cose" aswell?

@phbelitz Yes, since we support two signature formats at the moment. You should also import COSE as well.