diff --git a/dir/path.go b/dir/path.go index c5442519..28c1db4a 100644 --- a/dir/path.go +++ b/dir/path.go @@ -60,11 +60,11 @@ const ( // PathTrustPolicy is the OCI trust policy file relative path. // Deprecated: PathTrustPolicy exists for historical compatibility and should not be used. // To get OCI trust policy path, use PathOCITrustPolicy. - PathTrustPolicy = PathOCITrustPolicy + PathTrustPolicy = "trustpolicy.json" // PathOCITrustPolicy is the OCI trust policy file relative path. - PathOCITrustPolicy = "trustpolicy.json" + PathOCITrustPolicy = "trustpolicy.oci.json" // PathBlobTrustPolicy is the Blob trust policy file relative path. - PathBlobTrustPolicy = "trustpolicy.json" + PathBlobTrustPolicy = "trustpolicy.blob.json" // PathPlugins is the plugins directory relative path. PathPlugins = "plugins" // LocalKeysDir is the directory name for local key relative path. diff --git a/example_SignBlob_test.go b/example_signBlob_test.go similarity index 91% rename from example_SignBlob_test.go rename to example_signBlob_test.go index 34766dc6..0374f975 100644 --- a/example_SignBlob_test.go +++ b/example_signBlob_test.go @@ -49,6 +49,7 @@ func Example_signBlob() { SigningAgent: "example signing agent", }, ContentMediaType: exampleContentMediaType, + UserMetadata: map[string]string{"buildId": "101"}, } // exampleReader reads the data that needs to be signed. This data can be in a file or in memory. @@ -79,6 +80,6 @@ func Example_signBlob() { // Output: // Successfully signed // signature Payload ContentType: application/vnd.cncf.notary.payload.v1+json - // signature Payload Content: {"targetArtifact":{"digest":"sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61","mediaType":"video/mp4","size":12}} + // signature Payload Content: {"targetArtifact":{"annotations":{"buildId":"101"},"digest":"sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61","mediaType":"video/mp4","size":12}} // signerInfo SigningAgent: example signing agent } diff --git a/example_VerifyBlob_test.go b/example_verifyBlob_test.go similarity index 63% rename from example_VerifyBlob_test.go rename to example_verifyBlob_test.go index 68f872e0..37d952d0 100644 --- a/example_VerifyBlob_test.go +++ b/example_verifyBlob_test.go @@ -45,7 +45,7 @@ var exampleBlobPolicyDocument = trustpolicy.BlobDocument{ // ExampleLocalVerify demonstrates how to use verifier.Verify to verify a // signature of the target artifact at local (without using a // registry.Repository). -func Example_BlobVerify() { +func Example_verifyBlob() { // Both COSE ("application/cose") and JWS ("application/jose+json") // signature mediaTypes are supported. exampleSignatureMediaType := jws.MediaTypeEnvelope @@ -114,30 +114,30 @@ func createTrustStoreForBlobVerify() error { // Notary certificate requirements: // https://github.com/notaryproject/notaryproject/blob/v1.0.0/specs/signature-specification.md#certificate-requirements exampleX509Certificate := `-----BEGIN CERTIFICATE----- -MIIEajCCAtKgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzEL +MIIEbDCCAtSgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzEL MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEl -MCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAeFw0yNDA0MDIw -MjU2MzJaFw0yNDA0MDMwMjU2MzJaMGQxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJX -QTEQMA4GA1UEBxMHU2VhdHRsZTEPMA0GA1UEChMGTm90YXJ5MSUwIwYDVQQDExxO -b3RhdGlvbiBFeGFtcGxlIHNlbGYtc2lnbmVkMIIBojANBgkqhkiG9w0BAQEFAAOC -AY8AMIIBigKCAYEApZbB7U2x+XnucIVUoFEjUkNnjkZ0jpNfndHF49rTpqJTstsP -slW/d3qRlrTvsT61iaerLfFoIMkAq2G8KIOY0tCijyr3witWaeyd9sIvGggj770u -wngVpmASUuRZfmltHcTkn7m2gwJATuUc1ugHvxRE2+A7jbd2m7CfjGmwN+THg0Xe -5MggOKKd/2nEvePUsNedMF2Po5hzHG3rNQVxNyzbseIiDUq4qGl7h6zUIuYoSP0k -IPhsAPq9zhPkdXTQw39Ch3iDrVN/D+xOYuTukURFX45SnSTaqiFZEBoDEKIqfAwz -GUIm+yL5eNk6OOCZlmffXVadwdCnhwGMit8TUQQQOPtE3ALSRiXfdKUeBnkDIhcV -3MGLcrPy7kyq3IK7WwHhdfhhxGmJVAaZ/FuseeVT881UVD2Opj1j+MRWSurEiyiM -G/sTLEO53fIpp4eTP78CD6dYTrMC277C6X91WtCxQSnsYThP2miZHwZZY2jYt+hT -DpmWBP3i4ijl+75/AgMBAAGjJzAlMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK -BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAYEARLg5VcXNRdWaEuM01iheXzBL -AtGmZLf+fA4nl8j4FktNfYci1GtqwJqDmfXj74xXGgltnX4uMG+dTPln3c+tHJn3 -OJBgvCeB2sZWMoV4wjLZo1XOcIszdxUY7rI3PA/2ZRm75v7Qf0Yvg5DQRUgMMlvo -7Wu07mZoNLVccABndvj6nCntKaRu48YexXFWX+Y3qn8rCidH61Q8rmScdrSnYCwT -0TM23GoszeCtgdShgA0/NqqTefpC90zoKISze3K0zyIfsn9+kw3JHbw+PnqSQ/z8 -NqG/FGiv0x4fk0FZ9yOpT+4CoVGgnCub7YEYtUGQL70GbTjPXMto+hnXK3maWzBz -tOQxZrHLSIdOXaLfnRE+vGEDQ29hxQJj/S9H6WbXz6Gx1UpHp8y5RjWiphHV555F -/Ham1A4O1H2mK8l4b7oufB1u3cah1uQZ64xzr0VHVQnzmCm1MwQUkmF+5B/Ce9mC -IqbYJlmoCQWeDVqVSpPJrZgTmcA+djqsvhTi7zbr +MCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAgFw0yNDA0MDQy +MTIwMjBaGA8yMTI0MDQwNDIxMjAyMFowZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT +AldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxJTAjBgNVBAMT +HE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwggGiMA0GCSqGSIb3DQEBAQUA +A4IBjwAwggGKAoIBgQDGIiN4yCjSVqFELZwxK/BMb8BokP587L8oPrZ1g8H7LudB +moLNDT7vF9xccbCfU3yNuOd0WaOgnENiCs81VHidyJsj1Oz3u+0Zn3ng7V+uZr6m +AIO74efA9ClMiY4i4HIt8IAZF57AL2mzDnCITgSWxikf030Il85MI42STvA+qYuz +ZEOp3XvKo8bDgQFvbtgK0HYYMfrka7VDmIWVo0rBMGm5btI8HOYQ0r9aqsrCxLAv +1AQeOQm+wbRcp4R5PIUJr+REGn7JCbOyXg/7qqHXKKmvV5yrGaraw8gZ5pqP/RHK +XUJIfvD0Vf2epJmsvC+6vXkSWtz+cA8J4GQx4J4SXL57hoYkC5qv39SOLzlWls3I +6fgeO+SZ0sceMd8NKlom/L5eOJBfB3bTQB83hq/3bRtjT7/qCMsL3VcndKkS+vGF +JPw5uTH+pmBgHrLr6tRoRRjwRFuZ0dO05AbdjCaxgVDtFI3wNbaXn/1VlRGySQIS +UNWxCrUsSzndeqwmjqsCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM +MAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBgQBdi0SaJAaeKBB0I+Fjcbmc +4zRvHE4GDSMSDnAK97nrZCZ9iwKuY4x6mv9lwQe2P3VXROoL9JmONNf0yaObOwQj +ILGnbe2rzYtUardz2gzh+6KNzJHspRvk1f06mp4496XQ3STMRSr8kno1svKQMy0Y +FRsGMKs4fWHavIAqNXg9ymrZvvXiatN2UiVtAA/jBFScZAWskeb2WHNzORi7H5Z1 +mp5+IlNYQpzdIu/dvLVxzhh2UvkRdsQqsMgt/MOU84RncwUNZM4yI5EGPoaSJdsj +AGNd+UV6ur7QmVI2Q9EZNRlaDJtaoZmKns5j1SlmDXWKbdRmw42ORDudODj/pHA9 ++u+ca9t3uLsbqO9yPm8m+6fyxffWS11QAH6O7EjydJWcEe5tYkPpL6kcaEyQKESm +5CDlsk+W3ElpaUu6tsnGKODvgdAN3m0noC+qxzCMqoCM4+M5V6OptR98MDl2FK0B +5+WF6YHBxf/uqDvFktUczjrIWuyfECywp05bpGAErGE= -----END CERTIFICATE-----` // Adding the certificate into the trust store. @@ -148,5 +148,5 @@ IqbYJlmoCQWeDVqVSpPJrZgTmcA+djqsvhTi7zbr } func getSignatureEnvelope() string { - return `{"payload":"eyJ0YXJnZXRBcnRpZmFjdCI6eyJkaWdlc3QiOiJzaGEzODQ6YjhhYjI0ZGFmYmE1Y2Y3ZTRjODljNTYyZjgxMWNmMTA0OTNkNDIwM2RhOTgyZDNiMTM0NWYzNjZjYTg2M2Q5YzJlZDMyM2RiZDBmYjdmZjgzYTgwMzAyY2VmZmE1YTYxIiwibWVkaWFUeXBlIjoidmlkZW8vbXA0Iiwic2l6ZSI6MTJ9fQ","protected":"eyJhbGciOiJQUzM4NCIsImNyaXQiOlsiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSJdLCJjdHkiOiJhcHBsaWNhdGlvbi92bmQuY25jZi5ub3RhcnkucGF5bG9hZC52MStqc29uIiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSI6Im5vdGFyeS54NTA5IiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1RpbWUiOiIyMDI0LTA0LTAxVDE5OjU2OjMzLTA3OjAwIn0","header":{"x5c":["MIIEajCCAtKgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTElMCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAeFw0yNDA0MDIwMjU2MzJaFw0yNDA0MDMwMjU2MzJaMGQxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEPMA0GA1UEChMGTm90YXJ5MSUwIwYDVQQDExxOb3RhdGlvbiBFeGFtcGxlIHNlbGYtc2lnbmVkMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEApZbB7U2x+XnucIVUoFEjUkNnjkZ0jpNfndHF49rTpqJTstsPslW/d3qRlrTvsT61iaerLfFoIMkAq2G8KIOY0tCijyr3witWaeyd9sIvGggj770uwngVpmASUuRZfmltHcTkn7m2gwJATuUc1ugHvxRE2+A7jbd2m7CfjGmwN+THg0Xe5MggOKKd/2nEvePUsNedMF2Po5hzHG3rNQVxNyzbseIiDUq4qGl7h6zUIuYoSP0kIPhsAPq9zhPkdXTQw39Ch3iDrVN/D+xOYuTukURFX45SnSTaqiFZEBoDEKIqfAwzGUIm+yL5eNk6OOCZlmffXVadwdCnhwGMit8TUQQQOPtE3ALSRiXfdKUeBnkDIhcV3MGLcrPy7kyq3IK7WwHhdfhhxGmJVAaZ/FuseeVT881UVD2Opj1j+MRWSurEiyiMG/sTLEO53fIpp4eTP78CD6dYTrMC277C6X91WtCxQSnsYThP2miZHwZZY2jYt+hTDpmWBP3i4ijl+75/AgMBAAGjJzAlMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAYEARLg5VcXNRdWaEuM01iheXzBLAtGmZLf+fA4nl8j4FktNfYci1GtqwJqDmfXj74xXGgltnX4uMG+dTPln3c+tHJn3OJBgvCeB2sZWMoV4wjLZo1XOcIszdxUY7rI3PA/2ZRm75v7Qf0Yvg5DQRUgMMlvo7Wu07mZoNLVccABndvj6nCntKaRu48YexXFWX+Y3qn8rCidH61Q8rmScdrSnYCwT0TM23GoszeCtgdShgA0/NqqTefpC90zoKISze3K0zyIfsn9+kw3JHbw+PnqSQ/z8NqG/FGiv0x4fk0FZ9yOpT+4CoVGgnCub7YEYtUGQL70GbTjPXMto+hnXK3maWzBztOQxZrHLSIdOXaLfnRE+vGEDQ29hxQJj/S9H6WbXz6Gx1UpHp8y5RjWiphHV555F/Ham1A4O1H2mK8l4b7oufB1u3cah1uQZ64xzr0VHVQnzmCm1MwQUkmF+5B/Ce9mCIqbYJlmoCQWeDVqVSpPJrZgTmcA+djqsvhTi7zbr"],"io.cncf.notary.signingAgent":"example signing agent"},"signature":"JRz9B-yzx-DLrHuwHMuR4Nqn82t2r8TxBXSnMxZfCSexcD6Q2eo8XC_OUuWwrLlwT07kE9RmoseOyp3YUVFR-VuIGr1vaL8lE8DfQTJOhMPg2AwUzqPtXrKTat8r3FYqWCDchCpUt7ZvxGCjgstqbp2xrxfFxvwfEtJgT9dhPB8C3AoFA-8ZpWRb61YH_SJNhjfsn2YmPq_YCPVH7hhgJA-7lG49whIdwNT0E4RGKa58gvxa4gA4jld1-f87Bamp_oWMiByvmZwwR_zNtnn1OoefWrld6uDW1ahr5pP56QIDLEfhYEmYk7Zf_V2HTGKZ6j6-48jgemqwdqe3moX6QeTJRhEo-MYtvhlj4Q1oCWSbfgnspX2UMelygl1MmmlUNUeeP93crE5T09hW8uFCcnOuF9gRN5yN5rgpXr68DlSMXwFZJEMvbBCEwdtYI8xQoLi9F1bIQ97RfQLwPeqXgPMkAeQOtWB238LhETP5jyHc4fuoR-w62H3n7j-quY7l"}` + return `{"payload":"eyJ0YXJnZXRBcnRpZmFjdCI6eyJkaWdlc3QiOiJzaGEzODQ6YjhhYjI0ZGFmYmE1Y2Y3ZTRjODljNTYyZjgxMWNmMTA0OTNkNDIwM2RhOTgyZDNiMTM0NWYzNjZjYTg2M2Q5YzJlZDMyM2RiZDBmYjdmZjgzYTgwMzAyY2VmZmE1YTYxIiwibWVkaWFUeXBlIjoidmlkZW8vbXA0Iiwic2l6ZSI6MTJ9fQ","protected":"eyJhbGciOiJQUzM4NCIsImNyaXQiOlsiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSJdLCJjdHkiOiJhcHBsaWNhdGlvbi92bmQuY25jZi5ub3RhcnkucGF5bG9hZC52MStqc29uIiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSI6Im5vdGFyeS54NTA5IiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1RpbWUiOiIyMDI0LTA0LTA0VDE0OjIwOjIxLTA3OjAwIn0","header":{"x5c":["MIIEbDCCAtSgAwIBAgIBUzANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTElMCMGA1UEAxMcTm90YXRpb24gRXhhbXBsZSBzZWxmLXNpZ25lZDAgFw0yNDA0MDQyMTIwMjBaGA8yMTI0MDQwNDIxMjAyMFowZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxJTAjBgNVBAMTHE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDGIiN4yCjSVqFELZwxK/BMb8BokP587L8oPrZ1g8H7LudBmoLNDT7vF9xccbCfU3yNuOd0WaOgnENiCs81VHidyJsj1Oz3u+0Zn3ng7V+uZr6mAIO74efA9ClMiY4i4HIt8IAZF57AL2mzDnCITgSWxikf030Il85MI42STvA+qYuzZEOp3XvKo8bDgQFvbtgK0HYYMfrka7VDmIWVo0rBMGm5btI8HOYQ0r9aqsrCxLAv1AQeOQm+wbRcp4R5PIUJr+REGn7JCbOyXg/7qqHXKKmvV5yrGaraw8gZ5pqP/RHKXUJIfvD0Vf2epJmsvC+6vXkSWtz+cA8J4GQx4J4SXL57hoYkC5qv39SOLzlWls3I6fgeO+SZ0sceMd8NKlom/L5eOJBfB3bTQB83hq/3bRtjT7/qCMsL3VcndKkS+vGFJPw5uTH+pmBgHrLr6tRoRRjwRFuZ0dO05AbdjCaxgVDtFI3wNbaXn/1VlRGySQISUNWxCrUsSzndeqwmjqsCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBgQBdi0SaJAaeKBB0I+Fjcbmc4zRvHE4GDSMSDnAK97nrZCZ9iwKuY4x6mv9lwQe2P3VXROoL9JmONNf0yaObOwQjILGnbe2rzYtUardz2gzh+6KNzJHspRvk1f06mp4496XQ3STMRSr8kno1svKQMy0YFRsGMKs4fWHavIAqNXg9ymrZvvXiatN2UiVtAA/jBFScZAWskeb2WHNzORi7H5Z1mp5+IlNYQpzdIu/dvLVxzhh2UvkRdsQqsMgt/MOU84RncwUNZM4yI5EGPoaSJdsjAGNd+UV6ur7QmVI2Q9EZNRlaDJtaoZmKns5j1SlmDXWKbdRmw42ORDudODj/pHA9+u+ca9t3uLsbqO9yPm8m+6fyxffWS11QAH6O7EjydJWcEe5tYkPpL6kcaEyQKESm5CDlsk+W3ElpaUu6tsnGKODvgdAN3m0noC+qxzCMqoCM4+M5V6OptR98MDl2FK0B5+WF6YHBxf/uqDvFktUczjrIWuyfECywp05bpGAErGE="],"io.cncf.notary.signingAgent":"example signing agent"},"signature":"liOjdgQ9BKuQTZGXRh3o6P8AMUIq_MKQReEcqA5h8M4RYs3DV_wXfaLCr2x_NRcwjTZsoO1_J77hmzkkk4L0IuFP8Qw0KKtmc83G0yFi4yYV5fwzrIbnhC2GRLuqLPnK-C4qYmv52ld3ebvo7XWwRHu30-VXePmTRFp6iG-eSAgkNgwhxSZ0ZmTFLG3ceNiX2bxpLHlXdPwA3aFKbd6nKrzo4CZ1ZyLNmAIaoA5-kmc0Hyt45trpxaaiWusI_pcTLw71YCqEAs32tEq3q6hRAgAZZN-Qvm9GyNp9EuaPiKjMbJFqtjome5ITxyNd-5t09dDCUgSe3t-iqv2Blm4E080AP1TYwUKLYklGniUP1dAtOau5G2juZLpl7tr4LQ99mycflnAmV7e79eEWXffvy5EAl77dW4_vM7lEemm08m2wddGuDOWXYb1j1r2_a5Xb92umHq6ZMhAp200A0pUkm9640x8z5jdudi_7KeezdqUK7ZMmSxHohiylyKD_20Cy"}` } diff --git a/verifier/verifier_test.go b/verifier/verifier_test.go index be22eecd..212c611a 100644 --- a/verifier/verifier_test.go +++ b/verifier/verifier_test.go @@ -16,6 +16,7 @@ package verifier import ( "context" "crypto/x509" + "encoding/pem" "errors" "fmt" "net/http" @@ -29,6 +30,9 @@ import ( "github.com/notaryproject/notation-core-go/revocation" "github.com/notaryproject/notation-core-go/signature" + _ "github.com/notaryproject/notation-core-go/signature/cose" + "github.com/notaryproject/notation-core-go/signature/jws" + _ "github.com/notaryproject/notation-core-go/signature/jws" "github.com/notaryproject/notation-core-go/testhelper" corex509 "github.com/notaryproject/notation-core-go/x509" "github.com/notaryproject/notation-go" @@ -40,12 +44,43 @@ import ( "github.com/notaryproject/notation-go/signer" "github.com/notaryproject/notation-go/verifier/trustpolicy" "github.com/notaryproject/notation-go/verifier/truststore" + "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - _ "github.com/notaryproject/notation-core-go/signature/cose" - _ "github.com/notaryproject/notation-core-go/signature/jws" ) +var testSig = `{"payload":"eyJ0YXJnZXRBcnRpZmFjdCI6eyJhbm5vdGF0aW9ucyI6eyJidWlsZElkIjoiMTAxIn0sImRpZ2VzdCI6InNoYTM4NDpiOGFiMjRkYWZiYTVjZjdlNGM4OWM1NjJmODExY2YxMDQ5M2Q0MjAzZGE5ODJkM2IxMzQ1ZjM2NmNhODYzZDljMmVkMzIzZGJkMGZiN2ZmODNhODAzMDJjZWZmYTVhNjEiLCJtZWRpYVR5cGUiOiJ2aWRlby9tcDQiLCJzaXplIjoxMn19","protected":"eyJhbGciOiJQUzM4NCIsImNyaXQiOlsiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSJdLCJjdHkiOiJhcHBsaWNhdGlvbi92bmQuY25jZi5ub3RhcnkucGF5bG9hZC52MStqc29uIiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1NjaGVtZSI6Im5vdGFyeS54NTA5IiwiaW8uY25jZi5ub3Rhcnkuc2lnbmluZ1RpbWUiOiIyMDI0LTA0LTA0VDE1OjAzOjA2LTA3OjAwIn0","header":{"x5c":["MIIEbTCCAtWgAwIBAgICAK0wDQYJKoZIhvcNAQELBQAwZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxJTAjBgNVBAMTHE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwIBcNMjQwNDA0MjIwMzA1WhgPMjEyNDA0MDQyMjAzMDVaMGQxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEPMA0GA1UEChMGTm90YXJ5MSUwIwYDVQQDExxOb3RhdGlvbiBFeGFtcGxlIHNlbGYtc2lnbmVkMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0dXD9UqzZcGlBlvPHO2uf+Sel/xwf/eOMS6Q30GV6JPeu9czLmyR0YMfC6P0N4zDzVYYZtQLkS5lalTMGX9A3yj9aXtXvtoYtLx2mF1CfdQJMcrT63wVVTWiPPe2JT8KHkkiACzVY6LTwc4s+DIAw9Gv21Uu6bFy4WWlGMp8UwTucR0JqaFoXzB6vxVRTkK8RRLM9Pj0hM5NwobpuZ+pc+ZS/7PhdvQHVzHeLLV9S7fHxw3n1c0ti8VUjSPSqCIEqOL3Eu/0pWMXB2A1xzn3RBfnzZMD3Tw3ksFgLMVzblhv41c6gr4cgjaS4wWwUvq9Xndd7Io8QNvxyiRDX5cHwQSEOmDfmegTIaLR0dKfvjY4ZJq8Y1DnaXU4RD6XeihtZykMlx7nTUyZZXpQ1akjh3VMzPykJ4mIknHh02zGRT9ZE8E1kYzRWhU/0MAzVrTTFHpric6jO459ouTnQXFjKwAcoD5+bNY6TuhC18iar7+l4BPPI1mFuqETnMfkkJQZAgMBAAGjJzAlMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAYEAe5wyQPo+h1Yk2PkaA5aJKuU8azF2pTLfhQwAn/1XqPcmhNQuomOP0waoBsh+6sexfIDZaNuJ+zZUxqYHke/23+768SMiJCpuJfion3ak3Ka/IVNz48G0V+V+Vog+elkZzpdUQd30njLVcoQsihp0I/Gs3pnG2SeHmsdvYVuzycdYWTt5BFu4N8VWg4x4pfRMgDG7HGxRAacz2vTdqAx6rpWjO4xc0ZO8iUKjAeKHc7RuSx2dhUaRP9P8G8NBNtG6xNnbXIEjH6kP05srFRZ2jxm1an7sjsOpbBdIDztc0J+cb5yjBx7zo1OzWcmDUqMEXDR/WoygPzwhhHvWWvTqwVSEUvYnSaI6wxyHGxPFuX3+vCEZxU8NEGIuJtfYXWeo9cev5+PqjDgVu0uCWF53ZFsXNWbpff1qpG/CgrpFh3vN6uquMK9H5zaJBKr0GZFUsNRB1S8cUBgcjIZlWv3wrJQaOIFzF4RFO9dsYcG/b7ubdqSNGe4qfbsyuWf+1xsx"],"io.cncf.notary.signingAgent":"example signing agent"},"signature":"WMtF0u9GnQxJCpgrcxKZtNKNf3fvu2vnvOjd_2vQvjB4I9YKRYDQdr1q0AC0rU9b5aAGqP6Uh3jTbPkHHmOzGhXhRtidunfzOAeC6dPinR_RlnVMnVUY4cimZZG6Tg2tlgqGazgdzphnuZQpxUnK5mSInnWztXz_1-l_UJdPII49loJVE23hvWKDp8xOvMLftFXFlCYF9wE1ecTsYEAdrgB_XurFqbhhfeNcYie02aSMXfN0-ip9MHlIPhGrrOKLVm0w_S3nNBnuHHZ5lARgTm7tHtiNC0XxGCCk8qqteRZ4Vm2VM_UFMVOpdfh5KE_iTzmPCiHfNOJfgmvg5nysL1XUwGJ_KzCkPfY1Hq_4k73lia6RS6NSl1bSQ_s3uMBm3nx74WCmjK89RAihMIQ6s0PmUKQoWsIZ_5lWZ6uFW6LreoYyBFwvVVsSGSUx54-Gh76bwrt75va2VHpolSEXdhjcTK0KgscKLjU-LYDA_JD6AUaCi3WzMnpMSnO-9u_G"}` +var trustedCert = `-----BEGIN CERTIFICATE----- +MIIEbTCCAtWgAwIBAgICAK0wDQYJKoZIhvcNAQELBQAwZDELMAkGA1UEBhMCVVMx +CzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3Rhcnkx +JTAjBgNVBAMTHE5vdGF0aW9uIEV4YW1wbGUgc2VsZi1zaWduZWQwIBcNMjQwNDA0 +MjIwMzA1WhgPMjEyNDA0MDQyMjAzMDVaMGQxCzAJBgNVBAYTAlVTMQswCQYDVQQI +EwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEPMA0GA1UEChMGTm90YXJ5MSUwIwYDVQQD +ExxOb3RhdGlvbiBFeGFtcGxlIHNlbGYtc2lnbmVkMIIBojANBgkqhkiG9w0BAQEF +AAOCAY8AMIIBigKCAYEA0dXD9UqzZcGlBlvPHO2uf+Sel/xwf/eOMS6Q30GV6JPe +u9czLmyR0YMfC6P0N4zDzVYYZtQLkS5lalTMGX9A3yj9aXtXvtoYtLx2mF1CfdQJ +McrT63wVVTWiPPe2JT8KHkkiACzVY6LTwc4s+DIAw9Gv21Uu6bFy4WWlGMp8UwTu +cR0JqaFoXzB6vxVRTkK8RRLM9Pj0hM5NwobpuZ+pc+ZS/7PhdvQHVzHeLLV9S7fH +xw3n1c0ti8VUjSPSqCIEqOL3Eu/0pWMXB2A1xzn3RBfnzZMD3Tw3ksFgLMVzblhv +41c6gr4cgjaS4wWwUvq9Xndd7Io8QNvxyiRDX5cHwQSEOmDfmegTIaLR0dKfvjY4 +ZJq8Y1DnaXU4RD6XeihtZykMlx7nTUyZZXpQ1akjh3VMzPykJ4mIknHh02zGRT9Z +E8E1kYzRWhU/0MAzVrTTFHpric6jO459ouTnQXFjKwAcoD5+bNY6TuhC18iar7+l +4BPPI1mFuqETnMfkkJQZAgMBAAGjJzAlMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUE +DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAYEAe5wyQPo+h1Yk2PkaA5aJ +KuU8azF2pTLfhQwAn/1XqPcmhNQuomOP0waoBsh+6sexfIDZaNuJ+zZUxqYHke/2 +3+768SMiJCpuJfion3ak3Ka/IVNz48G0V+V+Vog+elkZzpdUQd30njLVcoQsihp0 +I/Gs3pnG2SeHmsdvYVuzycdYWTt5BFu4N8VWg4x4pfRMgDG7HGxRAacz2vTdqAx6 +rpWjO4xc0ZO8iUKjAeKHc7RuSx2dhUaRP9P8G8NBNtG6xNnbXIEjH6kP05srFRZ2 +jxm1an7sjsOpbBdIDztc0J+cb5yjBx7zo1OzWcmDUqMEXDR/WoygPzwhhHvWWvTq +wVSEUvYnSaI6wxyHGxPFuX3+vCEZxU8NEGIuJtfYXWeo9cev5+PqjDgVu0uCWF53 +ZFsXNWbpff1qpG/CgrpFh3vN6uquMK9H5zaJBKr0GZFUsNRB1S8cUBgcjIZlWv3w +rJQaOIFzF4RFO9dsYcG/b7ubdqSNGe4qfbsyuWf+1xsx +-----END CERTIFICATE-----` + +var ociPolicy = dummyOCIPolicyDocument() +var blobPolicy = dummyBlobPolicyDocument() +var store = truststore.NewX509TrustStore(dir.ConfigFS()) +var pm = mock.PluginManager{} + func TestNewVerifier_Error(t *testing.T) { policyDocument := dummyOCIPolicyDocument() _, err := New(&policyDocument, nil, nil) @@ -56,9 +91,8 @@ func TestNewVerifier_Error(t *testing.T) { } func TestInvalidArtifactUriValidations(t *testing.T) { - policyDocument := dummyOCIPolicyDocument() verifier := Verifier{ - ociTrustPolicyDoc: &policyDocument, + ociTrustPolicyDoc: &ociPolicy, pluginManager: mock.PluginManager{}, } @@ -88,9 +122,8 @@ func TestInvalidArtifactUriValidations(t *testing.T) { } func TestErrorNoApplicableTrustPolicy_Error(t *testing.T) { - policyDocument := dummyOCIPolicyDocument() verifier := Verifier{ - ociTrustPolicyDoc: &policyDocument, + ociTrustPolicyDoc: &ociPolicy, pluginManager: mock.PluginManager{}, } opts := notation.VerifierVerifyOptions{ArtifactReference: "non-existent-domain.com/repo@sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333"} @@ -650,90 +683,157 @@ func TestVerifyRevocation(t *testing.T) { }) } +func TestNew(t *testing.T) { + if _, err := New(&ociPolicy, store, pm); err != nil { + t.Fatalf("expected New constructor to succeed, but got %v", err) + } +} + func TestNewWithOptions(t *testing.T) { + if _, err := NewWithOptions(&ociPolicy, store, pm, VerifierOptions{}); err != nil { + t.Fatalf("expected NewWithOptions constructor to succeed, but got %v", err) + } } func TestNewVerifierWithOptions(t *testing.T) { - policy := dummyOCIPolicyDocument() - store := truststore.NewX509TrustStore(dir.ConfigFS()) - pm := mock.PluginManager{} - client := &http.Client{Timeout: 2 * time.Second} - r, err := revocation.New(client) + r, err := revocation.New(&http.Client{}) if err != nil { t.Fatalf("unexpected error while creating revocation object: %v", err) } opts := VerifierOptions{RevocationClient: r} - t.Run("successful call from New (default value)", func(t *testing.T) { - v, err := New(&policy, store, pm) - if err != nil { - t.Fatalf("expected New constructor to succeed with default client, but got %v", err) - } - verifierV, ok := v.(*Verifier) - if !ok { - t.Fatal("expected constructor to return a Verifier object") - } - if !(verifierV.ociTrustPolicyDoc == &policy) { - t.Fatalf("expected ociTrustPolicyDoc %v, but got %v", &policy, verifierV.ociTrustPolicyDoc) - } - if !(verifierV.trustStore == store) { - t.Fatalf("expected trustStore %v, but got %v", store, verifierV.trustStore) - } - if !reflect.DeepEqual(verifierV.pluginManager, pm) { - t.Fatalf("expected pluginManager %v, but got %v", pm, verifierV.pluginManager) - } - if verifierV.revocationClient == nil { - t.Fatal("expected nonnil revocationClient") - } - }) - t.Run("successful with empty options", func(t *testing.T) { - v, err := NewWithOptions(&policy, store, pm, VerifierOptions{}) + v, err := NewVerifierWithOptions(&ociPolicy, &blobPolicy, store, pm, opts) + if err != nil { + t.Fatalf("expected NewVerifierWithOptions constructor to succeed, but got %v", err) + } + if !(v.ociTrustPolicyDoc == &ociPolicy) { + t.Fatalf("expected ociTrustPolicyDoc %v, but got %v", v, v.ociTrustPolicyDoc) + } + if !(v.trustStore == store) { + t.Fatalf("expected trustStore %v, but got %v", store, v.trustStore) + } + if !reflect.DeepEqual(v.pluginManager, pm) { + t.Fatalf("expected pluginManager %v, but got %v", pm, v.pluginManager) + } + if v.revocationClient == nil { + t.Fatal("expected nonnil revocationClient") + } - if err != nil { - t.Fatalf("expected NewWithOptions constructor to succeed with empty options, but got %v", err) - } - verifierV, ok := v.(*Verifier) - if !ok { - t.Fatal("expected constructor to return a Verifier object") - } - if !(verifierV.ociTrustPolicyDoc == &policy) { - t.Fatalf("expected ociTrustPolicyDoc %v, but got %v", &policy, verifierV.ociTrustPolicyDoc) - } - if !(verifierV.trustStore == store) { - t.Fatalf("expected trustStore %v, but got %v", store, verifierV.trustStore) - } - if !reflect.DeepEqual(verifierV.pluginManager, pm) { - t.Fatalf("expected pluginManager %v, but got %v", pm, verifierV.pluginManager) - } - if verifierV.revocationClient == nil { - t.Fatal("expected nonnil revocationClient") - } - }) - t.Run("successful with client", func(t *testing.T) { - v, err := NewWithOptions(&policy, store, pm, opts) + _, err = NewVerifierWithOptions(nil, &blobPolicy, store, pm, opts) + if err != nil { + t.Fatalf("expected NewVerifierWithOptions constructor to succeed, but got %v", err) + } - if err != nil { - t.Fatalf("expected NewWithOptions constructor to succeed, but got %v", err) - } + _, err = NewVerifierWithOptions(&ociPolicy, nil, store, pm, opts) + if err != nil { + t.Fatalf("expected NewVerifierWithOptions constructor to succeed, but got %v", err) + } - expectedV := &Verifier{ - ociTrustPolicyDoc: &policy, - trustStore: store, - pluginManager: pm, - revocationClient: r, - } - if !reflect.DeepEqual(expectedV, v) { - t.Fatalf("expected %v to be created, but got %v", expectedV, v) - } - }) - t.Run("fail with nil trust policy", func(t *testing.T) { - _, err := NewWithOptions(nil, store, pm, opts) + opts.RevocationClient = nil + _, err = NewVerifierWithOptions(&ociPolicy, nil, store, pm, opts) + if err != nil { + t.Fatalf("expected NewVerifierWithOptions constructor to succeed, but got %v", err) + } +} - expectedErrMsg := "both ociTrustPolicy and blobTrustPolicy cannot be nil" - if err == nil || err.Error() != expectedErrMsg { - t.Fatalf("expected NewWithOptions constructor to fail with %v, but got %v", expectedErrMsg, err) - } - }) +func TestNewVerifierWithOptionsError(t *testing.T) { + r, err := revocation.New(&http.Client{}) + if err != nil { + t.Fatalf("unexpected error while creating revocation object: %v", err) + } + opts := VerifierOptions{RevocationClient: r} + + _, err = NewVerifierWithOptions(nil, nil, store, pm, opts) + if err == nil || err.Error() != "both ociTrustPolicy and blobTrustPolicy cannot be nil" { + t.Errorf("expected err but not found.") + } + + _, err = NewVerifierWithOptions(&ociPolicy, &blobPolicy, nil, pm, opts) + if err == nil || err.Error() != "trustStore cannot be nil" { + t.Errorf("expected err but not found.") + } +} + +func TestVerifyBlob(t *testing.T) { + policy := &trustpolicy.BlobDocument{ + Version: "1.0", + BlobTrustPolicies: []trustpolicy.BlobTrustPolicy{ + { + Name: "blob-test-policy", + SignatureVerification: trustpolicy.SignatureVerification{VerificationLevel: "strict"}, + TrustStores: []string{"ca:dummy-ts"}, + TrustedIdentities: []string{"*"}, + }, + }, + } + v, err := NewVerifier(nil, policy, &testTrustStore{}, pm) + if err != nil { + t.Fatalf("unexpected error while creating Verifier: %v", err) + } + + descGenFunc := func(digest.Algorithm) (ocispec.Descriptor, error) { + return ocispec.Descriptor{ + MediaType: "video/mp4", + Digest: "sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61", + Size: 12, + }, nil + } + opts := notation.BlobVerifierVerifyOptions{ + SignatureMediaType: jws.MediaTypeEnvelope, + TrustPolicyName: "blob-test-policy", + } + + // verify with without user defined metadata + if _, err = v.VerifyBlob(context.Background(), descGenFunc, []byte(testSig), opts); err != nil { + t.Fatalf("VerifyBlob() returned unexpected error: %v", err) + } + + // verify with user defined metadata + opts.UserMetadata = map[string]string{"buildId": "101"} + if _, err = v.VerifyBlob(context.Background(), descGenFunc, []byte(testSig), opts); err != nil { + t.Fatalf("VerifyBlob() with user metadata returned unexpected error: %v", err) + } +} + +func TestVerifyBlob_Error(t *testing.T) { + policy := &trustpolicy.BlobDocument{ + Version: "1.0", + BlobTrustPolicies: []trustpolicy.BlobTrustPolicy{ + { + Name: "blob-test-policy", + SignatureVerification: trustpolicy.SignatureVerification{VerificationLevel: "strict"}, + TrustStores: []string{"ca:dummy-ts"}, + TrustedIdentities: []string{"*"}, + }, + }, + } + v, err := NewVerifier(nil, policy, &testTrustStore{}, pm) + if err != nil { + t.Fatalf("unexpected error while creating Verifier: %v", err) + } + + descGenFunc := func(digest.Algorithm) (ocispec.Descriptor, error) { + return ocispec.Descriptor{ + MediaType: "video/mp4", + Digest: "sha384:b8ab24dafba5cf7e4c89c562f811cf10493d4203da982d3b1345f366ca863d9c2ed323dbd0fb7ff83a80302ceffa5a61", + Size: 12, + }, nil + } + opts := notation.BlobVerifierVerifyOptions{ + SignatureMediaType: jws.MediaTypeEnvelope, + TrustPolicyName: "blob-test-policy", + } + + // verify with without user defined metadata + if _, err = v.VerifyBlob(context.Background(), descGenFunc, []byte(testSig), opts); err != nil { + t.Fatalf("VerifyBlob() returned unexpected error: %v", err) + } + + // verify with user defined metadata + opts.UserMetadata = map[string]string{"buildId": "101"} + if _, err = v.VerifyBlob(context.Background(), descGenFunc, []byte(testSig), opts); err != nil { + t.Fatalf("VerifyBlob() with user metadata returned unexpected error: %v", err) + } } func TestVerificationPluginInteractions(t *testing.T) { @@ -1014,7 +1114,6 @@ func assertPluginVerification(scheme signature.SigningScheme, t *testing.T) { } func TestVerifyX509TrustedIdentities(t *testing.T) { - certs, _ := corex509.ReadCertificateFile(filepath.FromSlash("testdata/verifier/signing-cert.pem")) // cert's subject is "CN=SomeCN,OU=SomeOU,O=SomeOrg,L=Seattle,ST=WA,C=US" unsupportedCerts, _ := corex509.ReadCertificateFile(filepath.FromSlash("testdata/verifier/bad-cert.pem")) // cert's subject is "CN=bad=#CN,OU=SomeOU,O=SomeOrg,L=Seattle,ST=WA,C=US" @@ -1210,3 +1309,14 @@ func verifyResult(outcome *notation.VerificationOutcome, expectedResult notation t.Fatalf("assertion failed. expected : %v got : %v", expectedErr, outcome.Error) } } + +// testTrustStore implements truststore.X509TrustStore and returns the trusted certificates for a given trust-store. +type testTrustStore struct { + certs []*x509.Certificate +} + +func (ts *testTrustStore) GetCertificates(_ context.Context, _ truststore.Type, _ string) ([]*x509.Certificate, error) { + block, _ := pem.Decode([]byte(trustedCert)) + cert, _ := x509.ParseCertificate(block.Bytes) + return []*x509.Certificate{cert}, nil +}