diff --git a/cmd/skopeo/copy.go b/cmd/skopeo/copy.go index 3e9b3153..953d2ecc 100644 --- a/cmd/skopeo/copy.go +++ b/cmd/skopeo/copy.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/projectatomic/skopeo/image" - "github.com/projectatomic/skopeo/signature" + "github.com/containers/image/image" + "github.com/containers/image/signature" "github.com/urfave/cli" ) diff --git a/cmd/skopeo/fixtures/corrupt.signature b/cmd/skopeo/fixtures/corrupt.signature deleted file mode 120000 index 36e7e79b..00000000 --- a/cmd/skopeo/fixtures/corrupt.signature +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/corrupt.signature \ No newline at end of file diff --git a/cmd/skopeo/fixtures/corrupt.signature b/cmd/skopeo/fixtures/corrupt.signature new file mode 100644 index 00000000..95c29087 Binary files /dev/null and b/cmd/skopeo/fixtures/corrupt.signature differ diff --git a/cmd/skopeo/fixtures/image.manifest.json b/cmd/skopeo/fixtures/image.manifest.json deleted file mode 120000 index a115eb98..00000000 --- a/cmd/skopeo/fixtures/image.manifest.json +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/image.manifest.json \ No newline at end of file diff --git a/cmd/skopeo/fixtures/image.manifest.json b/cmd/skopeo/fixtures/image.manifest.json new file mode 100644 index 00000000..198da23f --- /dev/null +++ b/cmd/skopeo/fixtures/image.manifest.json @@ -0,0 +1,26 @@ +{ + "schemaVersion": 2, + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "config": { + "mediaType": "application/vnd.docker.container.image.v1+json", + "size": 7023, + "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" + }, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 32654, + "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f" + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 16724, + "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 73109, + "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" + } + ] +} \ No newline at end of file diff --git a/cmd/skopeo/fixtures/image.signature b/cmd/skopeo/fixtures/image.signature deleted file mode 120000 index dae8bd52..00000000 --- a/cmd/skopeo/fixtures/image.signature +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/image.signature \ No newline at end of file diff --git a/cmd/skopeo/fixtures/image.signature b/cmd/skopeo/fixtures/image.signature new file mode 100644 index 00000000..f8927212 Binary files /dev/null and b/cmd/skopeo/fixtures/image.signature differ diff --git a/cmd/skopeo/fixtures/pubring.gpg b/cmd/skopeo/fixtures/pubring.gpg deleted file mode 120000 index cda2fbc8..00000000 --- a/cmd/skopeo/fixtures/pubring.gpg +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/pubring.gpg \ No newline at end of file diff --git a/cmd/skopeo/fixtures/pubring.gpg b/cmd/skopeo/fixtures/pubring.gpg new file mode 100644 index 00000000..2d922b42 Binary files /dev/null and b/cmd/skopeo/fixtures/pubring.gpg differ diff --git a/cmd/skopeo/fixtures/secring.gpg b/cmd/skopeo/fixtures/secring.gpg deleted file mode 120000 index 8d3ffa52..00000000 --- a/cmd/skopeo/fixtures/secring.gpg +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/secring.gpg \ No newline at end of file diff --git a/cmd/skopeo/fixtures/secring.gpg b/cmd/skopeo/fixtures/secring.gpg new file mode 100644 index 00000000..36cf0f7d Binary files /dev/null and b/cmd/skopeo/fixtures/secring.gpg differ diff --git a/cmd/skopeo/fixtures/trustdb.gpg b/cmd/skopeo/fixtures/trustdb.gpg deleted file mode 120000 index 55945b32..00000000 --- a/cmd/skopeo/fixtures/trustdb.gpg +++ /dev/null @@ -1 +0,0 @@ -../../../signature/fixtures/trustdb.gpg \ No newline at end of file diff --git a/cmd/skopeo/fixtures/trustdb.gpg b/cmd/skopeo/fixtures/trustdb.gpg new file mode 100644 index 00000000..5449174f Binary files /dev/null and b/cmd/skopeo/fixtures/trustdb.gpg differ diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go index 3addb3fa..bee9500c 100644 --- a/cmd/skopeo/inspect.go +++ b/cmd/skopeo/inspect.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/projectatomic/skopeo/docker" - "github.com/projectatomic/skopeo/manifest" + "github.com/containers/image/docker" + "github.com/containers/image/manifest" "github.com/urfave/cli" ) diff --git a/cmd/skopeo/main.go b/cmd/skopeo/main.go index afffd63e..5f8c2625 100644 --- a/cmd/skopeo/main.go +++ b/cmd/skopeo/main.go @@ -5,7 +5,7 @@ import ( "os" "github.com/Sirupsen/logrus" - "github.com/projectatomic/skopeo/version" + "github.com/containers/image/version" "github.com/urfave/cli" ) diff --git a/cmd/skopeo/signing.go b/cmd/skopeo/signing.go index a935e2cd..0d45912d 100644 --- a/cmd/skopeo/signing.go +++ b/cmd/skopeo/signing.go @@ -5,7 +5,7 @@ import ( "fmt" "io/ioutil" - "github.com/projectatomic/skopeo/signature" + "github.com/containers/image/signature" "github.com/urfave/cli" ) diff --git a/cmd/skopeo/signing_test.go b/cmd/skopeo/signing_test.go index 14c37a26..9662f23e 100644 --- a/cmd/skopeo/signing_test.go +++ b/cmd/skopeo/signing_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/projectatomic/skopeo/signature" + "github.com/containers/image/signature" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index cf6d2a1e..86de067c 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -5,11 +5,11 @@ import ( "fmt" "strings" - "github.com/projectatomic/skopeo/directory" - "github.com/projectatomic/skopeo/docker" - "github.com/projectatomic/skopeo/image" - "github.com/projectatomic/skopeo/openshift" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/directory" + "github.com/containers/image/docker" + "github.com/containers/image/image" + "github.com/containers/image/openshift" + "github.com/containers/image/types" "github.com/urfave/cli" ) diff --git a/doc.go b/doc.go deleted file mode 100644 index a3c3926b..00000000 --- a/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Package skopeo provides libraries and commands to interact with containers images. -// -// package main -// -// import ( -// "fmt" -// -// "github.com/projectatomic/skopeo/docker" -// ) -// -// func main() { -// img, err := docker.NewDockerImage("fedora", "", false) -// if err != nil { -// panic(err) -// } -// b, err := img.Manifest() -// if err != nil { -// panic(err) -// } -// fmt.Printf("%s", string(b)) -// } -// -// TODO(runcom) -package skopeo diff --git a/hack/vendor.sh b/hack/vendor.sh index 4322db64..08379bb0 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -6,6 +6,7 @@ rm -rf vendor/ source 'hack/.vendor-helpers.sh' clone git github.com/urfave/cli v1.17.0 +clone git github.com/containers/image master clone git github.com/Sirupsen/logrus v0.10.0 clone git github.com/go-check/check v1 clone git github.com/stretchr/testify v1.1.3 diff --git a/image/image_test.go b/image/image_test.go deleted file mode 100644 index ba1b653b..00000000 --- a/image/image_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package image - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestUniqueLayerDigests(t *testing.T) { - for _, test := range []struct{ input, expected []string }{ - // Ensure that every element of expected: is unique! - {input: []string{}, expected: []string{}}, - {input: []string{"a"}, expected: []string{"a"}}, - {input: []string{"a", "b", "c"}, expected: []string{"a", "b", "c"}}, - {input: []string{"a", "a", "c"}, expected: []string{"a", "c"}}, - {input: []string{"a", "b", "a"}, expected: []string{"a", "b"}}, - } { - in := []fsLayersSchema1{} - for _, e := range test.input { - in = append(in, fsLayersSchema1{e}) - } - - m := manifestSchema1{FSLayers: in} - res := uniqueLayerDigests(&m) - // Test that the length is the same and each expected element is present. - // This requires each element of test.expected to be unique, as noted above. - assert.Len(t, res, len(test.expected)) - for _, e := range test.expected { - assert.Contains(t, res, e) - } - } -} diff --git a/integration/copy_test.go b/integration/copy_test.go index 66d8ef93..c23d4398 100644 --- a/integration/copy_test.go +++ b/integration/copy_test.go @@ -6,8 +6,8 @@ import ( "os" "path/filepath" + "github.com/containers/image/manifest" "github.com/go-check/check" - "github.com/projectatomic/skopeo/manifest" ) func init() { diff --git a/manifest/fixtures/non-json.manifest.json b/manifest/fixtures/non-json.manifest.json deleted file mode 100644 index f8927212..00000000 Binary files a/manifest/fixtures/non-json.manifest.json and /dev/null differ diff --git a/manifest/fixtures/unknown-version.manifest.json b/manifest/fixtures/unknown-version.manifest.json deleted file mode 100644 index b0f34b63..00000000 --- a/manifest/fixtures/unknown-version.manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "schemaVersion": 99999, - "name": "mitr/noversion-nonsense", - "tag": "latest" -} diff --git a/manifest/fixtures/v2list.manifest.json b/manifest/fixtures/v2list.manifest.json deleted file mode 100644 index 1bf9896e..00000000 --- a/manifest/fixtures/v2list.manifest.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "schemaVersion": 2, - "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", - "manifests": [ - { - "mediaType": "application/vnd.docker.distribution.manifest.v1+json", - "size": 2094, - "digest": "sha256:7820f9a86d4ad15a2c4f0c0e5479298df2aa7c2f6871288e2ef8546f3e7b6783", - "platform": { - "architecture": "ppc64le", - "os": "linux" - } - }, - { - "mediaType": "application/vnd.docker.distribution.manifest.v1+json", - "size": 1922, - "digest": "sha256:ae1b0e06e8ade3a11267564a26e750585ba2259c0ecab59ab165ad1af41d1bdd", - "platform": { - "architecture": "amd64", - "os": "linux", - "features": [ - "sse" - ] - } - }, - { - "mediaType": "application/vnd.docker.distribution.manifest.v1+json", - "size": 2084, - "digest": "sha256:e4c0df75810b953d6717b8f8f28298d73870e8aa2a0d5e77b8391f16fdfbbbe2", - "platform": { - "architecture": "s390x", - "os": "linux" - } - }, - { - "mediaType": "application/vnd.docker.distribution.manifest.v1+json", - "size": 2084, - "digest": "sha256:07ebe243465ef4a667b78154ae6c3ea46fdb1582936aac3ac899ea311a701b40", - "platform": { - "architecture": "arm", - "os": "linux", - "variant": "armv7" - } - }, - { - "mediaType": "application/vnd.docker.distribution.manifest.v1+json", - "size": 2090, - "digest": "sha256:fb2fc0707b86dafa9959fe3d29e66af8787aee4d9a23581714be65db4265ad8a", - "platform": { - "architecture": "arm64", - "os": "linux", - "variant": "armv8" - } - } - ] -} diff --git a/manifest/fixtures/v2s1-invalid-signatures.manifest.json b/manifest/fixtures/v2s1-invalid-signatures.manifest.json deleted file mode 100644 index 8dfefd4e..00000000 --- a/manifest/fixtures/v2s1-invalid-signatures.manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "schemaVersion": 1, - "name": "mitr/buxybox", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - ], - "history": [ - ], - "signatures": 1 -} diff --git a/manifest/fixtures/v2s1.manifest.json b/manifest/fixtures/v2s1.manifest.json deleted file mode 100644 index d384e3e6..00000000 --- a/manifest/fixtures/v2s1.manifest.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "schemaVersion": 1, - "name": "mitr/buxybox", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" - }, - { - "blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" - }, - { - "blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"f1b5eb0a1215f663765d509b6cdf3841bc2bcff0922346abb943d1342d469a97\",\"parent\":\"594075be8d003f784074cc639d970d1fa091a8197850baaae5052c01564ac535\",\"created\":\"2016-03-03T11:29:44.222098366Z\",\"container\":\"c0924f5b281a1992127d0afc065e59548ded8880b08aea4debd56d4497acb17a\",\"container_config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) LABEL Checksum=4fef81d30f31f9213c642881357e6662846a0f884c2366c13ebad807b4031368 ./tests/test-images/Dockerfile.2\"],\"Image\":\"594075be8d003f784074cc639d970d1fa091a8197850baaae5052c01564ac535\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":{\"Checksum\":\"4fef81d30f31f9213c642881357e6662846a0f884c2366c13ebad807b4031368 ./tests/test-images/Dockerfile.2\",\"Name\":\"atomic-test-2\"}},\"docker_version\":\"1.8.2-fc22\",\"author\":\"\\\"William Temple \\u003cwtemple at redhat dot com\\u003e\\\"\",\"config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"594075be8d003f784074cc639d970d1fa091a8197850baaae5052c01564ac535\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":{\"Checksum\":\"4fef81d30f31f9213c642881357e6662846a0f884c2366c13ebad807b4031368 ./tests/test-images/Dockerfile.2\",\"Name\":\"atomic-test-2\"}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" - }, - { - "v1Compatibility": "{\"id\":\"594075be8d003f784074cc639d970d1fa091a8197850baaae5052c01564ac535\",\"parent\":\"03dfa1cd1abe452bc2b69b8eb2362fa6beebc20893e65437906318954f6276d4\",\"created\":\"2016-03-03T11:29:38.563048924Z\",\"container\":\"fd4cf54dcd239fbae9bdade9db48e41880b436d27cb5313f60952a46ab04deff\",\"container_config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) LABEL Name=atomic-test-2\"],\"Image\":\"03dfa1cd1abe452bc2b69b8eb2362fa6beebc20893e65437906318954f6276d4\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":{\"Name\":\"atomic-test-2\"}},\"docker_version\":\"1.8.2-fc22\",\"author\":\"\\\"William Temple \\u003cwtemple at redhat dot com\\u003e\\\"\",\"config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"03dfa1cd1abe452bc2b69b8eb2362fa6beebc20893e65437906318954f6276d4\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":{\"Name\":\"atomic-test-2\"}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" - }, - { - "v1Compatibility": "{\"id\":\"03dfa1cd1abe452bc2b69b8eb2362fa6beebc20893e65437906318954f6276d4\",\"created\":\"2016-03-03T11:29:32.948089874Z\",\"container\":\"56f0fe1dfc95755dd6cda10f7215c9937a8d9c6348d079c581a261fd4c2f3a5f\",\"container_config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) MAINTAINER \\\"William Temple \\u003cwtemple at redhat dot com\\u003e\\\"\"],\"Image\":\"\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.8.2-fc22\",\"author\":\"\\\"William Temple \\u003cwtemple at redhat dot com\\u003e\\\"\",\"config\":{\"Hostname\":\"56f0fe1dfc95\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":null,\"PublishService\":\"\",\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"VolumeDriver\":\"\",\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n" - } - ], - "signatures": [ - { - "header": { - "jwk": { - "crv": "P-256", - "kid": "OZ45:U3IG:TDOI:PMBD:NGP2:LDIW:II2U:PSBI:MMCZ:YZUP:TUUO:XPZT", - "kty": "EC", - "x": "ReC5c0J9tgXSdUL4_xzEt5RsD8kFt2wWSgJcpAcOQx8", - "y": "3sBGEqQ3ZMeqPKwQBAadN2toOUEASha18xa0WwsDF-M" - }, - "alg": "ES256" - }, - "signature": "dV1paJ3Ck1Ph4FcEhg_frjqxdlGdI6-ywRamk6CvMOcaOEUdCWCpCPQeBQpD2N6tGjkoG1BbstkFNflllfenCw", - "protected": "eyJmb3JtYXRMZW5ndGgiOjU0NzgsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wNC0xOFQyMDo1NDo0MloifQ" - } - ] -} \ No newline at end of file diff --git a/manifest/fixtures/v2s2.manifest.json b/manifest/fixtures/v2s2.manifest.json deleted file mode 100644 index 198da23f..00000000 --- a/manifest/fixtures/v2s2.manifest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "schemaVersion": 2, - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "config": { - "mediaType": "application/vnd.docker.container.image.v1+json", - "size": 7023, - "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" - }, - "layers": [ - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 32654, - "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 16724, - "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 73109, - "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" - } - ] -} \ No newline at end of file diff --git a/manifest/fixtures/v2s2nomime.manifest.json b/manifest/fixtures/v2s2nomime.manifest.json deleted file mode 100644 index a0b06c23..00000000 --- a/manifest/fixtures/v2s2nomime.manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "schemaVersion": 2, - "config": { - "mediaType": "application/vnd.docker.container.image.v1+json", - "size": 7023, - "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" - }, - "layers": [ - ] -} diff --git a/manifest/fixtures_info_test.go b/manifest/fixtures_info_test.go deleted file mode 100644 index f756ff9e..00000000 --- a/manifest/fixtures_info_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package manifest - -const ( - // TestV2S2ManifestDigest is the Docker manifest digest of "v2s2.manifest.json" - TestDockerV2S2ManifestDigest = "sha256:20bf21ed457b390829cdbeec8795a7bea1626991fda603e0d01b4e7f60427e55" - // TestV2S1ManifestDigest is the Docker manifest digest of "v2s1.manifest.json" - TestDockerV2S1ManifestDigest = "sha256:077594da70fc17ec2c93cfa4e6ed1fcc26992851fb2c71861338aaf4aa9e41b1" -) diff --git a/manifest/manifest_test.go b/manifest/manifest_test.go deleted file mode 100644 index 561e0c3b..00000000 --- a/manifest/manifest_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package manifest - -import ( - "crypto/sha256" - "encoding/hex" - "io/ioutil" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGuessMIMEType(t *testing.T) { - cases := []struct { - path string - mimeType string - }{ - {"v2s2.manifest.json", DockerV2Schema2MIMEType}, - {"v2list.manifest.json", DockerV2ListMIMEType}, - {"v2s1.manifest.json", DockerV2Schema1MIMEType}, - {"v2s1-invalid-signatures.manifest.json", DockerV2Schema1MIMEType}, - {"v2s2nomime.manifest.json", DockerV2Schema2MIMEType}, // It is unclear whether this one is legal, but we should guess v2s2 if anything at all. - {"unknown-version.manifest.json", ""}, - {"non-json.manifest.json", ""}, // Not a manifest (nor JSON) at all - } - - for _, c := range cases { - manifest, err := ioutil.ReadFile(filepath.Join("fixtures", c.path)) - require.NoError(t, err) - mimeType := GuessMIMEType(manifest) - assert.Equal(t, c.mimeType, mimeType) - } -} - -func TestDigest(t *testing.T) { - cases := []struct { - path string - digest string - }{ - {"v2s2.manifest.json", TestDockerV2S2ManifestDigest}, - {"v2s1.manifest.json", TestDockerV2S1ManifestDigest}, - } - for _, c := range cases { - manifest, err := ioutil.ReadFile(filepath.Join("fixtures", c.path)) - require.NoError(t, err) - digest, err := Digest(manifest) - require.NoError(t, err) - assert.Equal(t, c.digest, digest) - } - - manifest, err := ioutil.ReadFile("fixtures/v2s1-invalid-signatures.manifest.json") - require.NoError(t, err) - digest, err := Digest(manifest) - assert.Error(t, err) - - digest, err = Digest([]byte{}) - require.NoError(t, err) - assert.Equal(t, "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", digest) -} - -func TestMatchesDigest(t *testing.T) { - cases := []struct { - path string - digest string - result bool - }{ - // Success - {"v2s2.manifest.json", TestDockerV2S2ManifestDigest, true}, - {"v2s1.manifest.json", TestDockerV2S1ManifestDigest, true}, - // No match (switched s1/s2) - {"v2s2.manifest.json", TestDockerV2S1ManifestDigest, false}, - {"v2s1.manifest.json", TestDockerV2S2ManifestDigest, false}, - // Unrecognized algorithm - {"v2s2.manifest.json", "md5:2872f31c5c1f62a694fbd20c1e85257c", false}, - // Mangled format - {"v2s2.manifest.json", TestDockerV2S2ManifestDigest + "abc", false}, - {"v2s2.manifest.json", TestDockerV2S2ManifestDigest[:20], false}, - {"v2s2.manifest.json", "", false}, - } - for _, c := range cases { - manifest, err := ioutil.ReadFile(filepath.Join("fixtures", c.path)) - require.NoError(t, err) - res, err := MatchesDigest(manifest, c.digest) - require.NoError(t, err) - assert.Equal(t, c.result, res) - } - - manifest, err := ioutil.ReadFile("fixtures/v2s1-invalid-signatures.manifest.json") - require.NoError(t, err) - // Even a correct SHA256 hash is rejected if we can't strip the JSON signature. - hash := sha256.Sum256(manifest) - res, err := MatchesDigest(manifest, "sha256:"+hex.EncodeToString(hash[:])) - assert.False(t, res) - assert.Error(t, err) - - res, err = MatchesDigest([]byte{}, "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") - assert.True(t, res) - assert.NoError(t, err) -} diff --git a/signature/docker_test.go b/signature/docker_test.go deleted file mode 100644 index 766fb036..00000000 --- a/signature/docker_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package signature - -import ( - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSignDockerManifest(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - manifest, err := ioutil.ReadFile("fixtures/image.manifest.json") - require.NoError(t, err) - - // Successful signing - signature, err := SignDockerManifest(manifest, TestImageSignatureReference, mech, TestKeyFingerprint) - require.NoError(t, err) - - verified, err := VerifyDockerManifestSignature(signature, manifest, TestImageSignatureReference, mech, TestKeyFingerprint) - assert.NoError(t, err) - assert.Equal(t, TestImageSignatureReference, verified.DockerReference) - assert.Equal(t, TestImageManifestDigest, verified.DockerManifestDigest) - - // Error computing Docker manifest - invalidManifest, err := ioutil.ReadFile("fixtures/v2s1-invalid-signatures.manifest.json") - require.NoError(t, err) - _, err = SignDockerManifest(invalidManifest, TestImageSignatureReference, mech, TestKeyFingerprint) - assert.Error(t, err) - - // Error creating blob to sign - _, err = SignDockerManifest(manifest, "", mech, TestKeyFingerprint) - assert.Error(t, err) - - // Error signing - _, err = SignDockerManifest(manifest, TestImageSignatureReference, mech, "this fingerprint doesn't exist") - assert.Error(t, err) -} - -func TestVerifyDockerManifestSignature(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - manifest, err := ioutil.ReadFile("fixtures/image.manifest.json") - require.NoError(t, err) - signature, err := ioutil.ReadFile("fixtures/image.signature") - require.NoError(t, err) - - // Successful verification - sig, err := VerifyDockerManifestSignature(signature, manifest, TestImageSignatureReference, mech, TestKeyFingerprint) - require.NoError(t, err) - assert.Equal(t, TestImageSignatureReference, sig.DockerReference) - assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest) - - // For extra paranoia, test that we return nil data on error. - - // Error computing Docker manifest - invalidManifest, err := ioutil.ReadFile("fixtures/v2s1-invalid-signatures.manifest.json") - require.NoError(t, err) - sig, err = VerifyDockerManifestSignature(signature, invalidManifest, TestImageSignatureReference, mech, TestKeyFingerprint) - assert.Error(t, err) - assert.Nil(t, sig) - - // Error verifying signature - corruptSignature, err := ioutil.ReadFile("fixtures/corrupt.signature") - sig, err = VerifyDockerManifestSignature(corruptSignature, manifest, TestImageSignatureReference, mech, TestKeyFingerprint) - assert.Error(t, err) - assert.Nil(t, sig) - - // Key fingerprint mismatch - sig, err = VerifyDockerManifestSignature(signature, manifest, TestImageSignatureReference, mech, "unexpected fingerprint") - assert.Error(t, err) - assert.Nil(t, sig) - - // Docker reference mismatch - sig, err = VerifyDockerManifestSignature(signature, manifest, "example.com/doesnt/match", mech, TestKeyFingerprint) - assert.Error(t, err) - assert.Nil(t, sig) - - // Docker manifest digest mismatch - sig, err = VerifyDockerManifestSignature(signature, []byte("unexpected manifest"), TestImageSignatureReference, mech, TestKeyFingerprint) - assert.Error(t, err) - assert.Nil(t, sig) -} diff --git a/signature/fixtures/.gitignore b/signature/fixtures/.gitignore deleted file mode 100644 index 3730cb25..00000000 --- a/signature/fixtures/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/*.gpg~ -/.gpg-v21-migrated -/private-keys-v1.d -/random_seed diff --git a/signature/fixtures/corrupt.signature b/signature/fixtures/corrupt.signature deleted file mode 100644 index 95c29087..00000000 Binary files a/signature/fixtures/corrupt.signature and /dev/null differ diff --git a/signature/fixtures/dir-img-manifest-digest-error/manifest.json b/signature/fixtures/dir-img-manifest-digest-error/manifest.json deleted file mode 120000 index 3dee14b4..00000000 --- a/signature/fixtures/dir-img-manifest-digest-error/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../v2s1-invalid-signatures.manifest.json \ No newline at end of file diff --git a/signature/fixtures/dir-img-manifest-digest-error/signature-1 b/signature/fixtures/dir-img-manifest-digest-error/signature-1 deleted file mode 120000 index f010fd4c..00000000 --- a/signature/fixtures/dir-img-manifest-digest-error/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/signature/fixtures/dir-img-mixed/manifest.json b/signature/fixtures/dir-img-mixed/manifest.json deleted file mode 120000 index ff7d2ffa..00000000 --- a/signature/fixtures/dir-img-mixed/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/signature/fixtures/dir-img-mixed/signature-1 b/signature/fixtures/dir-img-mixed/signature-1 deleted file mode 120000 index b27cdc45..00000000 --- a/signature/fixtures/dir-img-mixed/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../invalid-blob.signature \ No newline at end of file diff --git a/signature/fixtures/dir-img-mixed/signature-2 b/signature/fixtures/dir-img-mixed/signature-2 deleted file mode 120000 index f010fd4c..00000000 --- a/signature/fixtures/dir-img-mixed/signature-2 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/signature/fixtures/dir-img-modified-manifest/manifest.json b/signature/fixtures/dir-img-modified-manifest/manifest.json deleted file mode 100644 index 82fde381..00000000 --- a/signature/fixtures/dir-img-modified-manifest/manifest.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "schemaVersion": 2, - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "config": { - "mediaType": "application/vnd.docker.container.image.v1+json", - "size": 7023, - "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" - }, - "layers": [ - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 32654, - "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 16724, - "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 73109, - "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" - } - ], - "extra": "this manifest has been modified" -} diff --git a/signature/fixtures/dir-img-modified-manifest/signature-1 b/signature/fixtures/dir-img-modified-manifest/signature-1 deleted file mode 120000 index f010fd4c..00000000 --- a/signature/fixtures/dir-img-modified-manifest/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/signature/fixtures/dir-img-no-manifest/signature-1 b/signature/fixtures/dir-img-no-manifest/signature-1 deleted file mode 120000 index f010fd4c..00000000 --- a/signature/fixtures/dir-img-no-manifest/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/signature/fixtures/dir-img-unsigned/manifest.json b/signature/fixtures/dir-img-unsigned/manifest.json deleted file mode 120000 index ff7d2ffa..00000000 --- a/signature/fixtures/dir-img-unsigned/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/signature/fixtures/dir-img-valid-2/manifest.json b/signature/fixtures/dir-img-valid-2/manifest.json deleted file mode 120000 index ff7d2ffa..00000000 --- a/signature/fixtures/dir-img-valid-2/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/manifest.json \ No newline at end of file diff --git a/signature/fixtures/dir-img-valid-2/signature-1 b/signature/fixtures/dir-img-valid-2/signature-1 deleted file mode 120000 index f010fd4c..00000000 --- a/signature/fixtures/dir-img-valid-2/signature-1 +++ /dev/null @@ -1 +0,0 @@ -../dir-img-valid/signature-1 \ No newline at end of file diff --git a/signature/fixtures/dir-img-valid-2/signature-2 b/signature/fixtures/dir-img-valid-2/signature-2 deleted file mode 100644 index dbba8f42..00000000 Binary files a/signature/fixtures/dir-img-valid-2/signature-2 and /dev/null differ diff --git a/signature/fixtures/dir-img-valid/manifest.json b/signature/fixtures/dir-img-valid/manifest.json deleted file mode 120000 index c5bd2543..00000000 --- a/signature/fixtures/dir-img-valid/manifest.json +++ /dev/null @@ -1 +0,0 @@ -../image.manifest.json \ No newline at end of file diff --git a/signature/fixtures/dir-img-valid/signature-1 b/signature/fixtures/dir-img-valid/signature-1 deleted file mode 100644 index d0e18720..00000000 Binary files a/signature/fixtures/dir-img-valid/signature-1 and /dev/null differ diff --git a/signature/fixtures/double.signature b/signature/fixtures/double.signature deleted file mode 100644 index 76b17e2a..00000000 Binary files a/signature/fixtures/double.signature and /dev/null differ diff --git a/signature/fixtures/expired.signature b/signature/fixtures/expired.signature deleted file mode 100644 index c609c379..00000000 Binary files a/signature/fixtures/expired.signature and /dev/null differ diff --git a/signature/fixtures/image.manifest.json b/signature/fixtures/image.manifest.json deleted file mode 100644 index 198da23f..00000000 --- a/signature/fixtures/image.manifest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "schemaVersion": 2, - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "config": { - "mediaType": "application/vnd.docker.container.image.v1+json", - "size": 7023, - "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" - }, - "layers": [ - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 32654, - "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 16724, - "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 73109, - "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" - } - ] -} \ No newline at end of file diff --git a/signature/fixtures/image.signature b/signature/fixtures/image.signature deleted file mode 100644 index f8927212..00000000 Binary files a/signature/fixtures/image.signature and /dev/null differ diff --git a/signature/fixtures/invalid-blob.signature b/signature/fixtures/invalid-blob.signature deleted file mode 100644 index c8db18ca..00000000 Binary files a/signature/fixtures/invalid-blob.signature and /dev/null differ diff --git a/signature/fixtures/policy.json b/signature/fixtures/policy.json deleted file mode 100644 index 5e3d5bbb..00000000 --- a/signature/fixtures/policy.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "default": [ - { - "type": "reject" - } - ], - "specific": { - "example.com/playground": [ - { - "type": "insecureAcceptAnything" - } - ], - "example.com/production": [ - { - "type": "signedBy", - "keyType": "GPGKeys", - "keyPath": "/keys/employee-gpg-keyring" - } - ], - "example.com/hardened": [ - { - "type": "signedBy", - "keyType": "GPGKeys", - "keyPath": "/keys/employee-gpg-keyring", - "signedIdentity": { - "type": "matchRepository" - } - }, - { - "type": "signedBy", - "keyType": "signedByGPGKeys", - "keyPath": "/keys/public-key-signing-gpg-keyring", - "signedIdentity": { - "type": "matchExact" - } - }, - { - "type": "signedBaseLayer", - "baseLayerIdentity": { - "type": "exactRepository", - "dockerRepository": "registry.access.redhat.com/rhel7/rhel" - } - } - ], - "example.com/hardened-x509": [ - { - "type": "signedBy", - "keyType": "X509Certificates", - "keyPath": "/keys/employee-cert-file", - "signedIdentity": { - "type": "matchRepository" - } - }, - { - "type": "signedBy", - "keyType": "signedByX509CAs", - "keyPath": "/keys/public-key-signing-ca-file" - } - ], - "registry.access.redhat.com": [ - { - "type": "signedBy", - "keyType": "signedByGPGKeys", - "keyPath": "/keys/RH-key-signing-key-gpg-keyring" - } - ], - "bogus/key-data-example": [ - { - "type": "signedBy", - "keyType": "signedByGPGKeys", - "keyData": "bm9uc2Vuc2U=" - } - ], - "bogus/signed-identity-example": [ - { - "type": "signedBaseLayer", - "baseLayerIdentity": { - "type": "exactReference", - "dockerReference": "registry.access.redhat.com/rhel7/rhel:latest" - } - } - ] - } -} \ No newline at end of file diff --git a/signature/fixtures/public-key.gpg b/signature/fixtures/public-key.gpg deleted file mode 100644 index 46901d58..00000000 --- a/signature/fixtures/public-key.gpg +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mI0EVurzqQEEAL3qkFq4K2URtSWVDYnQUNA9HdM9sqS2eAWfqUFMrkD5f+oN+LBL -tPyaE5GNLA0vXY7nHAM2TeM8ijZ/eMP17Raj64JL8GhCymL3wn2jNvb9XaF0R0s6 -H0IaRPPu45A3SnxLwm4Orc/9Z7/UxtYjKSg9xOaTiVPzJgaf5Vm4J4ApABEBAAG0 -EnNrb3BlbyB0ZXN0aW5nIGtleYi4BBMBAgAiBQJW6vOpAhsDBgsJCAcDAgYVCAIJ -CgsEFgIDAQIeAQIXgAAKCRDbcvIYi7RsyBbOBACgJFiKDlQ1UyvsNmGqJ7D0OpbS -1OppJlradKgZXyfahFswhFI+7ZREvELLHbinq3dBy5cLXRWzQKdJZNHknSN5Tjf2 -0ipVBQuqpcBo+dnKiG4zH6fhTri7yeTZksIDfsqlI6FXDOdKLUSnahagEBn4yU+x -jHPvZk5SuuZv56A45biNBFbq86kBBADIC/9CsAlOmRALuYUmkhcqEjuFwn3wKz2d -IBjzgvro7zcVNNCgxQfMEjcUsvEh5cx13G3QQHcwOKy3M6Bv6VMhfZjd+1P1el4P -0fJS8GFmhWRBknMN8jFsgyohQeouQ798RFFv94KszfStNnr/ae8oao5URmoUXSCa -/MdUxn0YKwARAQABiJ8EGAECAAkFAlbq86kCGwwACgkQ23LyGIu0bMjUywQAq0dn -lUpDNSoLTcpNWuVvHQ7c/qmnE4TyiSLiRiAywdEWA6gMiyhUUucuGsEhMFP1WX1k -UNwArZ6UG7BDOUsvngP7jKGNqyUOQrq1s/r8D+0MrJGOWErGLlfttO2WeoijECkI -5qm8cXzAra3Xf/Z3VjxYTKSnNu37LtZkakdTdYE= -=tJAt ------END PGP PUBLIC KEY BLOCK----- diff --git a/signature/fixtures/pubring.gpg b/signature/fixtures/pubring.gpg deleted file mode 100644 index 2d922b42..00000000 Binary files a/signature/fixtures/pubring.gpg and /dev/null differ diff --git a/signature/fixtures/secring.gpg b/signature/fixtures/secring.gpg deleted file mode 100644 index 36cf0f7d..00000000 Binary files a/signature/fixtures/secring.gpg and /dev/null differ diff --git a/signature/fixtures/trustdb.gpg b/signature/fixtures/trustdb.gpg deleted file mode 100644 index 5449174f..00000000 Binary files a/signature/fixtures/trustdb.gpg and /dev/null differ diff --git a/signature/fixtures/unknown-key.signature b/signature/fixtures/unknown-key.signature deleted file mode 100644 index 2277b130..00000000 Binary files a/signature/fixtures/unknown-key.signature and /dev/null differ diff --git a/signature/fixtures/unsigned-encrypted.signature b/signature/fixtures/unsigned-encrypted.signature deleted file mode 100644 index 7da65dec..00000000 Binary files a/signature/fixtures/unsigned-encrypted.signature and /dev/null differ diff --git a/signature/fixtures/unsigned-literal.signature b/signature/fixtures/unsigned-literal.signature deleted file mode 100644 index 9b660cb2..00000000 Binary files a/signature/fixtures/unsigned-literal.signature and /dev/null differ diff --git a/signature/fixtures/v2s1-invalid-signatures.manifest.json b/signature/fixtures/v2s1-invalid-signatures.manifest.json deleted file mode 100644 index 8dfefd4e..00000000 --- a/signature/fixtures/v2s1-invalid-signatures.manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "schemaVersion": 1, - "name": "mitr/buxybox", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - ], - "history": [ - ], - "signatures": 1 -} diff --git a/signature/fixtures_info_test.go b/signature/fixtures_info_test.go deleted file mode 100644 index 2ffbbe21..00000000 --- a/signature/fixtures_info_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package signature - -const ( - // TestImageManifestDigest is the Docker manifest digest of "image.manifest.json" - TestImageManifestDigest = "sha256:20bf21ed457b390829cdbeec8795a7bea1626991fda603e0d01b4e7f60427e55" - // TestImageSignatureReference is the Docker image reference signed in "image.signature" - TestImageSignatureReference = "testing/manifest" - // TestKeyFingerprint is the fingerprint of the private key in this directory. - TestKeyFingerprint = "1D8230F6CDB6A06716E414C1DB72F2188BB46CC8" -) diff --git a/signature/json_test.go b/signature/json_test.go deleted file mode 100644 index 01781e98..00000000 --- a/signature/json_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package signature - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type mSI map[string]interface{} // To minimize typing the long name - -// A short-hand way to get a JSON object field value or panic. No error handling done, we know -// what we are working with, a panic in a test is good enough, and fitting test cases on a single line -// is a priority. -func x(m mSI, fields ...string) mSI { - for _, field := range fields { - // Not .(mSI) because type assertion of an unnamed type to a named type always fails (the types - // are not "identical"), but the assignment is fine because they are "assignable". - m = m[field].(map[string]interface{}) - } - return m -} - -func TestValidateExactMapKeys(t *testing.T) { - // Empty map and keys - err := validateExactMapKeys(mSI{}) - assert.NoError(t, err) - - // Success - err = validateExactMapKeys(mSI{"a": nil, "b": 1}, "b", "a") - assert.NoError(t, err) - - // Extra map keys - err = validateExactMapKeys(mSI{"a": nil, "b": 1}, "a") - assert.Error(t, err) - - // Extra expected keys - err = validateExactMapKeys(mSI{"a": 1}, "b", "a") - assert.Error(t, err) - - // Unexpected key values - err = validateExactMapKeys(mSI{"a": 1}, "b") - assert.Error(t, err) -} - -func TestMapField(t *testing.T) { - // Field not found - _, err := mapField(mSI{"a": mSI{}}, "b") - assert.Error(t, err) - - // Field has a wrong type - _, err = mapField(mSI{"a": 1}, "a") - assert.Error(t, err) - - // Success - // FIXME? We can't use mSI as the type of child, that type apparently can't be converted to the raw map type. - child := map[string]interface{}{"b": mSI{}} - m, err := mapField(mSI{"a": child, "b": nil}, "a") - require.NoError(t, err) - assert.Equal(t, child, m) -} - -func TestStringField(t *testing.T) { - // Field not found - _, err := stringField(mSI{"a": "x"}, "b") - assert.Error(t, err) - - // Field has a wrong type - _, err = stringField(mSI{"a": 1}, "a") - assert.Error(t, err) - - // Success - s, err := stringField(mSI{"a": "x", "b": nil}, "a") - require.NoError(t, err) - assert.Equal(t, "x", s) -} - -// implementsUnmarshalJSON is a minimalistic type used to detect that -// paranoidUnmarshalJSONObject uses the json.Unmarshaler interface of resolved -// pointers. -type implementsUnmarshalJSON bool - -// Compile-time check that Policy implements json.Unmarshaler. -var _ json.Unmarshaler = (*implementsUnmarshalJSON)(nil) - -func (dest *implementsUnmarshalJSON) UnmarshalJSON(data []byte) error { - _ = data // We don't care, not really. - *dest = true // Mark handler as called - return nil -} - -func TestParanoidUnmarshalJSONObject(t *testing.T) { - type testStruct struct { - A string - B int - } - ts := testStruct{} - var unmarshalJSONCalled implementsUnmarshalJSON - tsResolver := func(key string) interface{} { - switch key { - case "a": - return &ts.A - case "b": - return &ts.B - case "implementsUnmarshalJSON": - return &unmarshalJSONCalled - default: - return nil - } - } - - // Empty object - ts = testStruct{} - err := paranoidUnmarshalJSONObject([]byte(`{}`), tsResolver) - require.NoError(t, err) - assert.Equal(t, testStruct{}, ts) - - // Success - ts = testStruct{} - err = paranoidUnmarshalJSONObject([]byte(`{"a":"x", "b":2}`), tsResolver) - require.NoError(t, err) - assert.Equal(t, testStruct{A: "x", B: 2}, ts) - - // json.Unamarshaler is used for decoding values - ts = testStruct{} - unmarshalJSONCalled = implementsUnmarshalJSON(false) - err = paranoidUnmarshalJSONObject([]byte(`{"implementsUnmarshalJSON":true}`), tsResolver) - require.NoError(t, err) - assert.Equal(t, unmarshalJSONCalled, implementsUnmarshalJSON(true)) - - // Various kinds of invalid input - for _, input := range []string{ - ``, // Empty input - `&`, // Entirely invalid JSON - `1`, // Not an object - `{&}`, // Invalid key JSON - `{1:1}`, // Key not a string - `{"b":1, "b":1}`, // Duplicate key - `{"thisdoesnotexist":1}`, // Key rejected by resolver - `{"a":&}`, // Invalid value JSON - `{"a":1}`, // Type mismatch - `{"a":"value"}{}`, // Extra data after object - } { - ts = testStruct{} - err := paranoidUnmarshalJSONObject([]byte(input), tsResolver) - assert.Error(t, err, input) - } -} diff --git a/signature/mechanism_test.go b/signature/mechanism_test.go deleted file mode 100644 index e6cbc0a7..00000000 --- a/signature/mechanism_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package signature - -import ( - "bytes" - "io/ioutil" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - testGPGHomeDirectory = "./fixtures" -) - -func TestNewGPGSigningMechanism(t *testing.T) { - // A dumb test just for code coverage. We test more with newGPGSigningMechanismInDirectory(). - _, err := NewGPGSigningMechanism() - assert.NoError(t, err) -} - -func TestNewGPGSigningMechanismInDirectory(t *testing.T) { - // A dumb test just for code coverage. - _, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - assert.NoError(t, err) - // The various GPG failure cases are not obviously easy to reach. -} - -func TestGPGSigningMechanismImportKeysFromBytes(t *testing.T) { - testDir, err := ioutil.TempDir("", "gpg-import-keys") - require.NoError(t, err) - defer os.RemoveAll(testDir) - - mech, err := newGPGSigningMechanismInDirectory(testDir) - require.NoError(t, err) - - // Try validating a signature when the key is unknown. - signature, err := ioutil.ReadFile("./fixtures/invalid-blob.signature") - require.NoError(t, err) - content, signingFingerprint, err := mech.Verify(signature) - require.Error(t, err) - - // Successful import - keyBlob, err := ioutil.ReadFile("./fixtures/public-key.gpg") - require.NoError(t, err) - keyIdentities, err := mech.ImportKeysFromBytes(keyBlob) - require.NoError(t, err) - assert.Equal(t, []string{TestKeyFingerprint}, keyIdentities) - - // After import, the signature should validate. - content, signingFingerprint, err = mech.Verify(signature) - require.NoError(t, err) - assert.Equal(t, []byte("This is not JSON\n"), content) - assert.Equal(t, TestKeyFingerprint, signingFingerprint) - - // Two keys: just concatenate the valid input twice. - keyIdentities, err = mech.ImportKeysFromBytes(bytes.Join([][]byte{keyBlob, keyBlob}, nil)) - require.NoError(t, err) - assert.Equal(t, []string{TestKeyFingerprint, TestKeyFingerprint}, keyIdentities) - - // Invalid input: This is accepted anyway by GPG, just returns no keys. - keyIdentities, err = mech.ImportKeysFromBytes([]byte("This is invalid")) - require.NoError(t, err) - assert.Equal(t, []string{}, keyIdentities) - // The various GPG/GPGME failures cases are not obviously easy to reach. -} - -func TestGPGSigningMechanismSign(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - - // Successful signing - content := []byte("content") - signature, err := mech.Sign(content, TestKeyFingerprint) - require.NoError(t, err) - - signedContent, signingFingerprint, err := mech.Verify(signature) - require.NoError(t, err) - assert.EqualValues(t, content, signedContent) - assert.Equal(t, TestKeyFingerprint, signingFingerprint) - - // Error signing - _, err = mech.Sign(content, "this fingerprint doesn't exist") - assert.Error(t, err) - // The various GPG/GPGME failures cases are not obviously easy to reach. -} - -func assertSigningError(t *testing.T, content []byte, fingerprint string, err error) { - assert.Error(t, err) - assert.Nil(t, content) - assert.Empty(t, fingerprint) -} - -func TestGPGSigningMechanismVerify(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - - // Successful verification - signature, err := ioutil.ReadFile("./fixtures/invalid-blob.signature") - require.NoError(t, err) - content, signingFingerprint, err := mech.Verify(signature) - require.NoError(t, err) - assert.Equal(t, []byte("This is not JSON\n"), content) - assert.Equal(t, TestKeyFingerprint, signingFingerprint) - - // For extra paranoia, test that we return nil data on error. - - // Completely invalid signature. - content, signingFingerprint, err = mech.Verify([]byte{}) - assertSigningError(t, content, signingFingerprint, err) - - content, signingFingerprint, err = mech.Verify([]byte("invalid signature")) - assertSigningError(t, content, signingFingerprint, err) - - // Literal packet, not a signature - signature, err = ioutil.ReadFile("./fixtures/unsigned-literal.signature") - require.NoError(t, err) - content, signingFingerprint, err = mech.Verify(signature) - assertSigningError(t, content, signingFingerprint, err) - - // Encrypted data, not a signature. - signature, err = ioutil.ReadFile("./fixtures/unsigned-encrypted.signature") - require.NoError(t, err) - content, signingFingerprint, err = mech.Verify(signature) - assertSigningError(t, content, signingFingerprint, err) - - // FIXME? Is there a way to create a multi-signature so that gpgme_op_verify returns multiple signatures? - - // Expired signature - signature, err = ioutil.ReadFile("./fixtures/expired.signature") - require.NoError(t, err) - content, signingFingerprint, err = mech.Verify(signature) - assertSigningError(t, content, signingFingerprint, err) - - // Corrupt signature - signature, err = ioutil.ReadFile("./fixtures/corrupt.signature") - require.NoError(t, err) - content, signingFingerprint, err = mech.Verify(signature) - assertSigningError(t, content, signingFingerprint, err) - - // Valid signature with an unknown key - signature, err = ioutil.ReadFile("./fixtures/unknown-key.signature") - require.NoError(t, err) - content, signingFingerprint, err = mech.Verify(signature) - assertSigningError(t, content, signingFingerprint, err) - - // The various GPG/GPGME failures cases are not obviously easy to reach. -} diff --git a/signature/policy_config_test.go b/signature/policy_config_test.go deleted file mode 100644 index 23c2f1a6..00000000 --- a/signature/policy_config_test.go +++ /dev/null @@ -1,1174 +0,0 @@ -package signature - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// policyFixtureContents is a data structure equal to the contents of "fixtures/policy.json" -var policyFixtureContents = &Policy{ - Default: PolicyRequirements{NewPRReject()}, - Specific: map[string]PolicyRequirements{ - "example.com/playground": { - NewPRInsecureAcceptAnything(), - }, - "example.com/production": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, - "/keys/employee-gpg-keyring", - NewPRMMatchExact()), - }, - "example.com/hardened": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, - "/keys/employee-gpg-keyring", - NewPRMMatchRepository()), - xNewPRSignedByKeyPath(SBKeyTypeSignedByGPGKeys, - "/keys/public-key-signing-gpg-keyring", - NewPRMMatchExact()), - xNewPRSignedBaseLayer(xNewPRMExactRepository("registry.access.redhat.com/rhel7/rhel")), - }, - "example.com/hardened-x509": { - xNewPRSignedByKeyPath(SBKeyTypeX509Certificates, - "/keys/employee-cert-file", - NewPRMMatchRepository()), - xNewPRSignedByKeyPath(SBKeyTypeSignedByX509CAs, - "/keys/public-key-signing-ca-file", - NewPRMMatchExact()), - }, - "registry.access.redhat.com": { - xNewPRSignedByKeyPath(SBKeyTypeSignedByGPGKeys, - "/keys/RH-key-signing-key-gpg-keyring", - NewPRMMatchExact()), - }, - "bogus/key-data-example": { - xNewPRSignedByKeyData(SBKeyTypeSignedByGPGKeys, - []byte("nonsense"), - NewPRMMatchExact()), - }, - "bogus/signed-identity-example": { - xNewPRSignedBaseLayer(xNewPRMExactReference("registry.access.redhat.com/rhel7/rhel:latest")), - }, - }, -} - -func TestNewPolicyFromFile(t *testing.T) { - // Success - policy, err := NewPolicyFromFile("./fixtures/policy.json") - require.NoError(t, err) - assert.Equal(t, policyFixtureContents, policy) - - // Error reading file - _, err = NewPolicyFromFile("/this/doesnt/exist") - assert.Error(t, err) - - // A failure case; most are tested in the individual method unit tests. - _, err = NewPolicyFromFile("/dev/null") - require.Error(t, err) - assert.IsType(t, InvalidPolicyFormatError(""), err) -} - -func TestNewPolicyFromBytes(t *testing.T) { - // Success - bytes, err := ioutil.ReadFile("./fixtures/policy.json") - require.NoError(t, err) - policy, err := NewPolicyFromBytes(bytes) - require.NoError(t, err) - assert.Equal(t, policyFixtureContents, policy) - - // A failure case; most are tested in the individual method unit tests. - _, err = NewPolicyFromBytes([]byte("")) - require.Error(t, err) - assert.IsType(t, InvalidPolicyFormatError(""), err) -} - -// FIXME? There is quite a bit of duplication below. Factor some of it out? - -// addExtraJSONMember adds adds an additional member "$name": $extra, -// possibly with a duplicate name, to encoded. -// Errors, if any, are reported through t. -func addExtraJSONMember(t *testing.T, encoded []byte, name string, extra interface{}) []byte { - extraJSON, err := json.Marshal(extra) - require.NoError(t, err) - - require.True(t, bytes.HasSuffix(encoded, []byte("}"))) - preservedLen := len(encoded) - 1 - - return bytes.Join([][]byte{encoded[:preservedLen], []byte(`,"`), []byte(name), []byte(`":`), extraJSON, []byte("}")}, nil) -} - -func TestInvalidPolicyFormatError(t *testing.T) { - // A stupid test just to keep code coverage - s := "test" - err := InvalidPolicyFormatError(s) - assert.Equal(t, s, err.Error()) -} - -// Return the result of modifying validJSON with fn and unmarshaling it into *p -func tryUnmarshalModifiedPolicy(t *testing.T, p *Policy, validJSON []byte, modifyFn func(mSI)) error { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - modifyFn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - *p = Policy{} - return json.Unmarshal(testJSON, p) -} - -// xNewPRSignedByKeyPath is like NewPRSignedByKeyPath, except it must not fail. -func xNewPRSignedByKeyPath(keyType sbKeyType, keyPath string, signedIdentity PolicyReferenceMatch) PolicyRequirement { - pr, err := NewPRSignedByKeyPath(keyType, keyPath, signedIdentity) - if err != nil { - panic("xNewPRSignedByKeyPath failed") - } - return pr -} - -// xNewPRSignedByKeyData is like NewPRSignedByKeyData, except it must not fail. -func xNewPRSignedByKeyData(keyType sbKeyType, keyData []byte, signedIdentity PolicyReferenceMatch) PolicyRequirement { - pr, err := NewPRSignedByKeyData(keyType, keyData, signedIdentity) - if err != nil { - panic("xNewPRSignedByKeyData failed") - } - return pr -} - -func TestPolicyUnmarshalJSON(t *testing.T) { - var p Policy - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &p) - assert.Error(t, err) - err = p.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &p) - assert.Error(t, err) - - // Start with a valid JSON. - validPolicy := Policy{ - Default: []PolicyRequirement{ - xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("abc"), NewPRMMatchExact()), - }, - Specific: map[string]PolicyRequirements{ - "docker.io/library/busybox": []PolicyRequirement{ - xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("def"), NewPRMMatchExact()), - }, - "registry.access.redhat.com": []PolicyRequirement{ - xNewPRSignedByKeyData(SBKeyTypeSignedByGPGKeys, []byte("RH"), NewPRMMatchRepository()), - }, - }, - } - validJSON, err := json.Marshal(validPolicy) - require.NoError(t, err) - - // Success - p = Policy{} - err = json.Unmarshal(validJSON, &p) - require.NoError(t, err) - assert.Equal(t, validPolicy, p) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // The "default" field is missing - func(v mSI) { delete(v, "default") }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // "default" not an array - func(v mSI) { v["default"] = 1 }, - func(v mSI) { v["default"] = mSI{} }, - // "specific" not an object - func(v mSI) { v["specific"] = 1 }, - func(v mSI) { v["specific"] = []string{} }, - // "default" is an invalid PolicyRequirements - func(v mSI) { v["default"] = PolicyRequirements{} }, - // A field in "specific" is an invalid PolicyRequirements - func(v mSI) { x(v, "specific")["docker.io/library/busybox"] = PolicyRequirements{} }, - } - for _, fn := range breakFns { - err = tryUnmarshalModifiedPolicy(t, &p, validJSON, fn) - assert.Error(t, err) - } - - // Duplicated fields - for _, field := range []string{"default", "specific"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - p = Policy{} - err = json.Unmarshal(testJSON, &p) - assert.Error(t, err) - } - - // Various allowed modifications to the policy - allowedModificationFns := []func(mSI){ - // Delete the map of specific policies - func(v mSI) { delete(v, "specific") }, - // Use an empty map of specific policies - func(v mSI) { v["specific"] = map[string]PolicyRequirements{} }, - } - for _, fn := range allowedModificationFns { - err = tryUnmarshalModifiedPolicy(t, &p, validJSON, fn) - require.NoError(t, err) - } -} - -func TestPolicyRequirementsUnmarshalJSON(t *testing.T) { - var reqs PolicyRequirements - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &reqs) - assert.Error(t, err) - err = reqs.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an array - err = json.Unmarshal([]byte("1"), &reqs) - assert.Error(t, err) - - // Start with a valid JSON. - validReqs := PolicyRequirements{ - xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("def"), NewPRMMatchExact()), - xNewPRSignedByKeyData(SBKeyTypeSignedByGPGKeys, []byte("RH"), NewPRMMatchRepository()), - } - validJSON, err := json.Marshal(validReqs) - require.NoError(t, err) - - // Success - reqs = PolicyRequirements{} - err = json.Unmarshal(validJSON, &reqs) - require.NoError(t, err) - assert.Equal(t, validReqs, reqs) - - for _, invalid := range [][]interface{}{ - // No requirements - {}, - // A member is not an object - {1}, - // A member has an invalid type - {prSignedBy{prCommon: prCommon{Type: "this is invalid"}}}, - // A member has a valid type but invalid contents - {prSignedBy{ - prCommon: prCommon{Type: prTypeSignedBy}, - KeyType: "this is invalid", - }}, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - reqs = PolicyRequirements{} - err = json.Unmarshal(testJSON, &reqs) - assert.Error(t, err, string(testJSON)) - } -} - -func TestNewPolicyRequirementFromJSON(t *testing.T) { - // Sample success. Others tested in the individual PolicyRequirement.UnmarshalJSON implementations. - validReq := NewPRInsecureAcceptAnything() - validJSON, err := json.Marshal(validReq) - require.NoError(t, err) - req, err := newPolicyRequirementFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validReq, req) - - // Invalid - for _, invalid := range []interface{}{ - // Not an object - 1, - // Missing type - prCommon{}, - // Invalid type - prCommon{Type: "this is invalid"}, - // Valid type but invalid contents - prSignedBy{ - prCommon: prCommon{Type: prTypeSignedBy}, - KeyType: "this is invalid", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - _, err = newPolicyRequirementFromJSON(testJSON) - assert.Error(t, err, string(testJSON)) - } -} - -func TestNewPRInsecureAcceptAnything(t *testing.T) { - _pr := NewPRInsecureAcceptAnything() - pr, ok := _pr.(*prInsecureAcceptAnything) - require.True(t, ok) - assert.Equal(t, &prInsecureAcceptAnything{prCommon{prTypeInsecureAcceptAnything}}, pr) -} - -func TestPRInsecureAcceptAnythingUnmarshalJSON(t *testing.T) { - var pr prInsecureAcceptAnything - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &pr) - assert.Error(t, err) - err = pr.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &pr) - assert.Error(t, err) - - // Start with a valid JSON. - validPR := NewPRInsecureAcceptAnything() - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success - pr = prInsecureAcceptAnything{} - err = json.Unmarshal(validJSON, &pr) - require.NoError(t, err) - assert.Equal(t, validPR, &pr) - - // newPolicyRequirementFromJSON recognizes this type - _pr, err := newPolicyRequirementFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - for _, invalid := range []mSI{ - // Missing "type" field - {}, - // Wrong "type" field - {"type": 1}, - {"type": "this is invalid"}, - // Extra fields - { - "type": string(prTypeInsecureAcceptAnything), - "unknown": "foo", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - pr = prInsecureAcceptAnything{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err, string(testJSON)) - } - - // Duplicated fields - for _, field := range []string{"type"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - pr = prInsecureAcceptAnything{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - } -} - -func TestNewPRReject(t *testing.T) { - _pr := NewPRReject() - pr, ok := _pr.(*prReject) - require.True(t, ok) - assert.Equal(t, &prReject{prCommon{prTypeReject}}, pr) -} - -func TestPRRejectUnmarshalJSON(t *testing.T) { - var pr prReject - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &pr) - assert.Error(t, err) - err = pr.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &pr) - assert.Error(t, err) - - // Start with a valid JSON. - validPR := NewPRReject() - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success - pr = prReject{} - err = json.Unmarshal(validJSON, &pr) - require.NoError(t, err) - assert.Equal(t, validPR, &pr) - - // newPolicyRequirementFromJSON recognizes this type - _pr, err := newPolicyRequirementFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - for _, invalid := range []mSI{ - // Missing "type" field - {}, - // Wrong "type" field - {"type": 1}, - {"type": "this is invalid"}, - // Extra fields - { - "type": string(prTypeReject), - "unknown": "foo", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - pr = prReject{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err, string(testJSON)) - } - - // Duplicated fields - for _, field := range []string{"type"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - pr = prReject{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - } -} - -func TestNewPRSignedBy(t *testing.T) { - const testPath = "/foo/bar" - testData := []byte("abc") - testIdentity := NewPRMMatchExact() - - // Success - pr, err := newPRSignedBy(SBKeyTypeGPGKeys, testPath, nil, testIdentity) - require.NoError(t, err) - assert.Equal(t, &prSignedBy{ - prCommon: prCommon{prTypeSignedBy}, - KeyType: SBKeyTypeGPGKeys, - KeyPath: testPath, - KeyData: nil, - SignedIdentity: testIdentity, - }, pr) - pr, err = newPRSignedBy(SBKeyTypeGPGKeys, "", testData, testIdentity) - require.NoError(t, err) - assert.Equal(t, &prSignedBy{ - prCommon: prCommon{prTypeSignedBy}, - KeyType: SBKeyTypeGPGKeys, - KeyPath: "", - KeyData: testData, - SignedIdentity: testIdentity, - }, pr) - - // Invalid keyType - pr, err = newPRSignedBy(sbKeyType(""), testPath, nil, testIdentity) - assert.Error(t, err) - pr, err = newPRSignedBy(sbKeyType("this is invalid"), testPath, nil, testIdentity) - assert.Error(t, err) - - // Both keyPath and keyData specified - pr, err = newPRSignedBy(SBKeyTypeGPGKeys, testPath, testData, testIdentity) - assert.Error(t, err) - - // Invalid signedIdentity - pr, err = newPRSignedBy(SBKeyTypeGPGKeys, testPath, nil, nil) - assert.Error(t, err) -} - -func TestNewPRSignedByKeyPath(t *testing.T) { - const testPath = "/foo/bar" - _pr, err := NewPRSignedByKeyPath(SBKeyTypeGPGKeys, testPath, NewPRMMatchExact()) - require.NoError(t, err) - pr, ok := _pr.(*prSignedBy) - require.True(t, ok) - assert.Equal(t, testPath, pr.KeyPath) - // Failure cases tested in TestNewPRSignedBy. -} - -func TestNewPRSignedByKeyData(t *testing.T) { - testData := []byte("abc") - _pr, err := NewPRSignedByKeyData(SBKeyTypeGPGKeys, testData, NewPRMMatchExact()) - require.NoError(t, err) - pr, ok := _pr.(*prSignedBy) - require.True(t, ok) - assert.Equal(t, testData, pr.KeyData) - // Failure cases tested in TestNewPRSignedBy. -} - -// Return the result of modifying vaoidJSON with fn and unmarshalingit into *pr -func tryUnmarshalModifiedSignedBy(t *testing.T, pr *prSignedBy, validJSON []byte, modifyFn func(mSI)) error { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - modifyFn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - *pr = prSignedBy{} - return json.Unmarshal(testJSON, &pr) -} - -func TestPRSignedByUnmarshalJSON(t *testing.T) { - var pr prSignedBy - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &pr) - assert.Error(t, err) - err = pr.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &pr) - assert.Error(t, err) - - // Start with a valid JSON. - validPR, err := NewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("abc"), NewPRMMatchExact()) - require.NoError(t, err) - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success with KeyData - pr = prSignedBy{} - err = json.Unmarshal(validJSON, &pr) - require.NoError(t, err) - assert.Equal(t, validPR, &pr) - - // Success with KeyPath - kpPR, err := NewPRSignedByKeyPath(SBKeyTypeGPGKeys, "/foo/bar", NewPRMMatchExact()) - require.NoError(t, err) - testJSON, err := json.Marshal(kpPR) - require.NoError(t, err) - pr = prSignedBy{} - err = json.Unmarshal(testJSON, &pr) - require.NoError(t, err) - assert.Equal(t, kpPR, &pr) - - // newPolicyRequirementFromJSON recognizes this type - _pr, err := newPolicyRequirementFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // The "type" field is missing - func(v mSI) { delete(v, "type") }, - // Wrong "type" field - func(v mSI) { v["type"] = 1 }, - func(v mSI) { v["type"] = "this is invalid" }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // The "keyType" field is missing - func(v mSI) { delete(v, "keyType") }, - // Invalid "keyType" field - func(v mSI) { v["keyType"] = "this is invalid" }, - // Both "keyPath" and "keyData" is missing - func(v mSI) { delete(v, "keyData") }, - // Both "keyPath" and "keyData" is present - func(v mSI) { v["keyPath"] = "/foo/bar" }, - // Invalid "keyPath" field - func(v mSI) { delete(v, "keyData"); v["keyPath"] = 1 }, - func(v mSI) { v["type"] = "this is invalid" }, - // Invalid "keyData" field - func(v mSI) { v["keyData"] = 1 }, - func(v mSI) { v["keyData"] = "this is invalid base64" }, - // Invalid "signedIdentity" field - func(v mSI) { v["signedIdentity"] = "this is invalid" }, - // "signedIdentity" an explicit nil - func(v mSI) { v["signedIdentity"] = nil }, - } - for _, fn := range breakFns { - err = tryUnmarshalModifiedSignedBy(t, &pr, validJSON, fn) - assert.Error(t, err, string(testJSON)) - } - - // Duplicated fields - for _, field := range []string{"type", "keyType", "keyData", "signedIdentity"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - pr = prSignedBy{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - } - // Handle "keyPath", which is not in validJSON, specially - pathPR, err := NewPRSignedByKeyPath(SBKeyTypeGPGKeys, "/foo/bar", NewPRMMatchExact()) - require.NoError(t, err) - testJSON, err = json.Marshal(pathPR) - require.NoError(t, err) - testJSON = addExtraJSONMember(t, testJSON, "keyPath", pr.KeyPath) - pr = prSignedBy{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - - // Various allowed modifications to the requirement - allowedModificationFns := []func(mSI){ - // Delete the signedIdentity field - func(v mSI) { delete(v, "signedIdentity") }, - } - for _, fn := range allowedModificationFns { - err = tryUnmarshalModifiedSignedBy(t, &pr, validJSON, fn) - require.NoError(t, err) - } - -} - -func TestSBKeyTypeIsValid(t *testing.T) { - // Valid values - for _, s := range []sbKeyType{ - SBKeyTypeGPGKeys, - SBKeyTypeSignedByGPGKeys, - SBKeyTypeX509Certificates, - SBKeyTypeSignedByX509CAs, - } { - assert.True(t, s.IsValid()) - } - - // Invalid values - for _, s := range []string{"", "this is invalid"} { - assert.False(t, sbKeyType(s).IsValid()) - } -} - -func TestSBKeyTypeUnmarshalJSON(t *testing.T) { - var kt sbKeyType - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &kt) - assert.Error(t, err) - err = kt.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not a string - err = json.Unmarshal([]byte("1"), &kt) - assert.Error(t, err) - - // Valid values. - for _, v := range []sbKeyType{ - SBKeyTypeGPGKeys, - SBKeyTypeSignedByGPGKeys, - SBKeyTypeX509Certificates, - SBKeyTypeSignedByX509CAs, - } { - kt = sbKeyType("") - err = json.Unmarshal([]byte(`"`+string(v)+`"`), &kt) - assert.NoError(t, err) - } - - // Invalid values - kt = sbKeyType("") - err = json.Unmarshal([]byte(`""`), &kt) - assert.Error(t, err) - - kt = sbKeyType("") - err = json.Unmarshal([]byte(`"this is invalid"`), &kt) - assert.Error(t, err) -} - -// NewPRSignedBaseLayer is like NewPRSignedBaseLayer, except it must not fail. -func xNewPRSignedBaseLayer(baseLayerIdentity PolicyReferenceMatch) PolicyRequirement { - pr, err := NewPRSignedBaseLayer(baseLayerIdentity) - if err != nil { - panic("xNewPRSignedBaseLayer failed") - } - return pr -} - -func TestNewPRSignedBaseLayer(t *testing.T) { - testBLI := NewPRMMatchExact() - - // Success - _pr, err := NewPRSignedBaseLayer(testBLI) - require.NoError(t, err) - pr, ok := _pr.(*prSignedBaseLayer) - require.True(t, ok) - assert.Equal(t, &prSignedBaseLayer{ - prCommon: prCommon{prTypeSignedBaseLayer}, - BaseLayerIdentity: testBLI, - }, pr) - - // Invalid baseLayerIdentity - _, err = NewPRSignedBaseLayer(nil) - assert.Error(t, err) -} - -func TestPRSignedBaseLayerUnmarshalJSON(t *testing.T) { - var pr prSignedBaseLayer - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &pr) - assert.Error(t, err) - err = pr.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &pr) - assert.Error(t, err) - - // Start with a valid JSON. - baseIdentity, err := NewPRMExactReference("registry.access.redhat.com/rhel7/rhel:7.2.3") - require.NoError(t, err) - validPR, err := NewPRSignedBaseLayer(baseIdentity) - require.NoError(t, err) - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success - pr = prSignedBaseLayer{} - err = json.Unmarshal(validJSON, &pr) - require.NoError(t, err) - assert.Equal(t, validPR, &pr) - - // newPolicyRequirementFromJSON recognizes this type - _pr, err := newPolicyRequirementFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // The "type" field is missing - func(v mSI) { delete(v, "type") }, - // Wrong "type" field - func(v mSI) { v["type"] = 1 }, - func(v mSI) { v["type"] = "this is invalid" }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // The "baseLayerIdentity" field is missing - func(v mSI) { delete(v, "baseLayerIdentity") }, - // Invalid "baseLayerIdentity" field - func(v mSI) { v["baseLayerIdentity"] = "this is invalid" }, - // Invalid "baseLayerIdentity" an explicit nil - func(v mSI) { v["baseLayerIdentity"] = nil }, - } - for _, fn := range breakFns { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - fn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - pr = prSignedBaseLayer{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - } - - // Duplicated fields - for _, field := range []string{"type", "baseLayerIdentity"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - pr = prSignedBaseLayer{} - err = json.Unmarshal(testJSON, &pr) - assert.Error(t, err) - } -} - -func TestNewPolicyReferenceMatchFromJSON(t *testing.T) { - // Sample success. Others tested in the individual PolicyReferenceMatch.UnmarshalJSON implementations. - validPRM := NewPRMMatchExact() - validJSON, err := json.Marshal(validPRM) - require.NoError(t, err) - prm, err := newPolicyReferenceMatchFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPRM, prm) - - // Invalid - for _, invalid := range []interface{}{ - // Not an object - 1, - // Missing type - prmCommon{}, - // Invalid type - prmCommon{Type: "this is invalid"}, - // Valid type but invalid contents - prmExactReference{ - prmCommon: prmCommon{Type: prmTypeExactReference}, - DockerReference: "", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - _, err = newPolicyReferenceMatchFromJSON(testJSON) - assert.Error(t, err, string(testJSON)) - } -} - -func TestNewPRMMatchExact(t *testing.T) { - _prm := NewPRMMatchExact() - prm, ok := _prm.(*prmMatchExact) - require.True(t, ok) - assert.Equal(t, &prmMatchExact{prmCommon{prmTypeMatchExact}}, prm) -} - -func TestPRMMatchExactUnmarshalJSON(t *testing.T) { - var prm prmMatchExact - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &prm) - assert.Error(t, err) - err = prm.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &prm) - assert.Error(t, err) - - // Start with a valid JSON. - validPR := NewPRMMatchExact() - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success - prm = prmMatchExact{} - err = json.Unmarshal(validJSON, &prm) - require.NoError(t, err) - assert.Equal(t, validPR, &prm) - - // newPolicyReferenceMatchFromJSON recognizes this type - _pr, err := newPolicyReferenceMatchFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - for _, invalid := range []mSI{ - // Missing "type" field - {}, - // Wrong "type" field - {"type": 1}, - {"type": "this is invalid"}, - // Extra fields - { - "type": string(prmTypeMatchExact), - "unknown": "foo", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - prm = prmMatchExact{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err, string(testJSON)) - } - - // Duplicated fields - for _, field := range []string{"type"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - prm = prmMatchExact{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } -} - -func TestNewPRMMatchRepository(t *testing.T) { - _prm := NewPRMMatchRepository() - prm, ok := _prm.(*prmMatchRepository) - require.True(t, ok) - assert.Equal(t, &prmMatchRepository{prmCommon{prmTypeMatchRepository}}, prm) -} - -func TestPRMMatchRepositoryUnmarshalJSON(t *testing.T) { - var prm prmMatchRepository - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &prm) - assert.Error(t, err) - err = prm.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &prm) - assert.Error(t, err) - - // Start with a valid JSON. - validPR := NewPRMMatchRepository() - validJSON, err := json.Marshal(validPR) - require.NoError(t, err) - - // Success - prm = prmMatchRepository{} - err = json.Unmarshal(validJSON, &prm) - require.NoError(t, err) - assert.Equal(t, validPR, &prm) - - // newPolicyReferenceMatchFromJSON recognizes this type - _pr, err := newPolicyReferenceMatchFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPR, _pr) - - for _, invalid := range []mSI{ - // Missing "type" field - {}, - // Wrong "type" field - {"type": 1}, - {"type": "this is invalid"}, - // Extra fields - { - "type": string(prmTypeMatchRepository), - "unknown": "foo", - }, - } { - testJSON, err := json.Marshal(invalid) - require.NoError(t, err) - - prm = prmMatchRepository{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err, string(testJSON)) - } - - // Duplicated fields - for _, field := range []string{"type"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - prm = prmMatchRepository{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } -} - -// xNewPRMExactReference is like NewPRMExactReference, except it must not fail. -func xNewPRMExactReference(dockerReference string) PolicyReferenceMatch { - pr, err := NewPRMExactReference(dockerReference) - if err != nil { - panic("xNewPRMExactReference failed") - } - return pr -} - -func TestNewPRMExactReference(t *testing.T) { - const testDR = "library/busybox:latest" - - // Success - _prm, err := NewPRMExactReference(testDR) - require.NoError(t, err) - prm, ok := _prm.(*prmExactReference) - require.True(t, ok) - assert.Equal(t, &prmExactReference{ - prmCommon: prmCommon{prmTypeExactReference}, - DockerReference: testDR, - }, prm) - - // Invalid dockerReference - _, err = NewPRMExactReference("") - assert.Error(t, err) - // Uppercase is invalid in Docker reference components. - _, err = NewPRMExactReference("INVALIDUPPERCASE:latest") - assert.Error(t, err) - // Missing tag - _, err = NewPRMExactReference("library/busybox") - assert.Error(t, err) -} - -func TestPRMExactReferenceUnmarshalJSON(t *testing.T) { - var prm prmExactReference - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &prm) - assert.Error(t, err) - err = prm.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &prm) - assert.Error(t, err) - - // Start with a valid JSON. - validPRM, err := NewPRMExactReference("library/buxybox:latest") - require.NoError(t, err) - validJSON, err := json.Marshal(validPRM) - require.NoError(t, err) - - // Success - prm = prmExactReference{} - err = json.Unmarshal(validJSON, &prm) - require.NoError(t, err) - assert.Equal(t, validPRM, &prm) - - // newPolicyReferenceMatchFromJSON recognizes this type - _prm, err := newPolicyReferenceMatchFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPRM, _prm) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // The "type" field is missing - func(v mSI) { delete(v, "type") }, - // Wrong "type" field - func(v mSI) { v["type"] = 1 }, - func(v mSI) { v["type"] = "this is invalid" }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // The "dockerReference" field is missing - func(v mSI) { delete(v, "dockerReference") }, - // Invalid "dockerReference" field - func(v mSI) { v["dockerReference"] = 1 }, - } - for _, fn := range breakFns { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - fn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - prm = prmExactReference{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } - - // Duplicated fields - for _, field := range []string{"type", "baseLayerIdentity"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - prm = prmExactReference{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } -} - -// xNewPRMExactRepository is like NewPRMExactRepository, except it must not fail. -func xNewPRMExactRepository(dockerRepository string) PolicyReferenceMatch { - pr, err := NewPRMExactRepository(dockerRepository) - if err != nil { - panic("xNewPRMExactRepository failed") - } - return pr -} - -func TestNewPRMExactRepository(t *testing.T) { - const testDR = "library/busybox:latest" - - // Success - _prm, err := NewPRMExactRepository(testDR) - require.NoError(t, err) - prm, ok := _prm.(*prmExactRepository) - require.True(t, ok) - assert.Equal(t, &prmExactRepository{ - prmCommon: prmCommon{prmTypeExactRepository}, - DockerRepository: testDR, - }, prm) - - // Invalid dockerRepository - _, err = NewPRMExactRepository("") - assert.Error(t, err) - // Uppercase is invalid in Docker reference components. - _, err = NewPRMExactRepository("INVALIDUPPERCASE") - assert.Error(t, err) -} - -func TestPRMExactRepositoryUnmarshalJSON(t *testing.T) { - var prm prmExactRepository - - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &prm) - assert.Error(t, err) - err = prm.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &prm) - assert.Error(t, err) - - // Start with a valid JSON. - validPRM, err := NewPRMExactRepository("library/buxybox:latest") - require.NoError(t, err) - validJSON, err := json.Marshal(validPRM) - require.NoError(t, err) - - // Success - prm = prmExactRepository{} - err = json.Unmarshal(validJSON, &prm) - require.NoError(t, err) - assert.Equal(t, validPRM, &prm) - - // newPolicyReferenceMatchFromJSON recognizes this type - _prm, err := newPolicyReferenceMatchFromJSON(validJSON) - require.NoError(t, err) - assert.Equal(t, validPRM, _prm) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // The "type" field is missing - func(v mSI) { delete(v, "type") }, - // Wrong "type" field - func(v mSI) { v["type"] = 1 }, - func(v mSI) { v["type"] = "this is invalid" }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // The "dockerRepository" field is missing - func(v mSI) { delete(v, "dockerRepository") }, - // Invalid "dockerRepository" field - func(v mSI) { v["dockerRepository"] = 1 }, - } - for _, fn := range breakFns { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - fn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - prm = prmExactRepository{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } - - // Duplicated fields - for _, field := range []string{"type", "baseLayerIdentity"} { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - testJSON := addExtraJSONMember(t, validJSON, field, tmp[field]) - - prm = prmExactRepository{} - err = json.Unmarshal(testJSON, &prm) - assert.Error(t, err) - } -} diff --git a/signature/policy_eval_baselayer_test.go b/signature/policy_eval_baselayer_test.go deleted file mode 100644 index 937cb928..00000000 --- a/signature/policy_eval_baselayer_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package signature - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestPRSignedBaseLayerIsSignatureAuthorAccepted(t *testing.T) { - pr, err := NewPRSignedBaseLayer(NewPRMMatchRepository()) - require.NoError(t, err) - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err := pr.isSignatureAuthorAccepted(nil, nil) - assertSARUnknown(t, sar, parsedSig, err) -} - -func TestPRSignedBaseLayerIsRunningImageAllowed(t *testing.T) { - // This will obviously need to change after signedBaseLayer is implemented. - pr, err := NewPRSignedBaseLayer(NewPRMMatchRepository()) - require.NoError(t, err) - // Pass a nil pointer to, kind of, test that the return value does not depend on the image. - res, err := pr.isRunningImageAllowed(nil) - assertRunningRejectedPolicyRequirement(t, res, err) -} diff --git a/signature/policy_eval_signedby_test.go b/signature/policy_eval_signedby_test.go deleted file mode 100644 index a40e7977..00000000 --- a/signature/policy_eval_signedby_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package signature - -import ( - "io/ioutil" - "os" - "path" - "testing" - - "github.com/projectatomic/skopeo/directory" - "github.com/projectatomic/skopeo/image" - "github.com/projectatomic/skopeo/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// dirImageMock returns a types.Image for a directory, claiming a specified intendedDockerReference. -func dirImageMock(dir, intendedDockerReference string) types.Image { - return image.FromSource(&dirImageSourceMock{ - ImageSource: directory.NewDirImageSource(dir), - intendedDockerReference: intendedDockerReference, - }) -} - -// dirImageSourceMock inherits dirImageSource, but overrides its IntendedDockerReference method. -type dirImageSourceMock struct { - types.ImageSource - intendedDockerReference string -} - -func (d *dirImageSourceMock) IntendedDockerReference() string { - return d.intendedDockerReference -} - -func TestPRSignedByIsSignatureAuthorAccepted(t *testing.T) { - ktGPG := SBKeyTypeGPGKeys - prm := NewPRMMatchExact() - testImage := dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - testImageSig, err := ioutil.ReadFile("fixtures/dir-img-valid/signature-1") - require.NoError(t, err) - - // Successful validation, with KeyData and KeyPath - pr, err := NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sar, parsedSig, err := pr.isSignatureAuthorAccepted(testImage, testImageSig) - assertSARAccepted(t, sar, parsedSig, err, Signature{ - DockerManifestDigest: TestImageManifestDigest, - DockerReference: "testing/manifest:latest", - }) - - keyData, err := ioutil.ReadFile("fixtures/public-key.gpg") - require.NoError(t, err) - pr, err = NewPRSignedByKeyData(ktGPG, keyData, prm) - require.NoError(t, err) - sar, parsedSig, err = pr.isSignatureAuthorAccepted(testImage, testImageSig) - assertSARAccepted(t, sar, parsedSig, err, Signature{ - DockerManifestDigest: TestImageManifestDigest, - DockerReference: "testing/manifest:latest", - }) - - // Unimplemented and invalid KeyType values - for _, keyType := range []sbKeyType{SBKeyTypeSignedByGPGKeys, - SBKeyTypeX509Certificates, - SBKeyTypeSignedByX509CAs, - sbKeyType("This is invalid"), - } { - // Do not use NewPRSignedByKeyData, because it would reject invalid values. - pr := &prSignedBy{ - KeyType: keyType, - KeyData: []byte("abc"), - SignedIdentity: prm, - } - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err := pr.isSignatureAuthorAccepted(nil, nil) - assertSARRejected(t, sar, parsedSig, err) - } - - // Both KeyPath and KeyData set. Do not use NewPRSignedBy*, because it would reject this. - prSB := &prSignedBy{ - KeyType: ktGPG, - KeyPath: "/foo/bar", - KeyData: []byte("abc"), - SignedIdentity: prm, - } - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err = prSB.isSignatureAuthorAccepted(nil, nil) - assertSARRejected(t, sar, parsedSig, err) - - // Invalid KeyPath - pr, err = NewPRSignedByKeyPath(ktGPG, "/this/does/not/exist", prm) - require.NoError(t, err) - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err = pr.isSignatureAuthorAccepted(nil, nil) - assertSARRejected(t, sar, parsedSig, err) - - // Errors initializing the temporary GPG directory and mechanism are not obviously easy to reach. - - // KeyData has no public keys. - pr, err = NewPRSignedByKeyData(ktGPG, []byte{}, prm) - require.NoError(t, err) - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err = pr.isSignatureAuthorAccepted(nil, nil) - assertSARRejectedPolicyRequirement(t, sar, parsedSig, err) - - // A signature which does not GPG verify - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - // Pass a nil pointer to, kind of, test that the return value does not depend on the image parmater.. - sar, parsedSig, err = pr.isSignatureAuthorAccepted(nil, []byte("invalid signature")) - assertSARRejected(t, sar, parsedSig, err) - - // A valid signature using an unknown key. - // (This is (currently?) rejected through the "mech.Verify fails" path, not the "!identityFound" path, - // because we use a temporary directory and only import the trusted keys.) - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sig, err := ioutil.ReadFile("fixtures/unknown-key.signature") - require.NoError(t, err) - // Pass a nil pointer to, kind of, test that the return value does not depend on the image parmater.. - sar, parsedSig, err = pr.isSignatureAuthorAccepted(nil, sig) - assertSARRejected(t, sar, parsedSig, err) - - // A valid signature of an invalid JSON. - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sig, err = ioutil.ReadFile("fixtures/invalid-blob.signature") - require.NoError(t, err) - // Pass a nil pointer to, kind of, test that the return value does not depend on the image parmater.. - sar, parsedSig, err = pr.isSignatureAuthorAccepted(nil, sig) - assertSARRejected(t, sar, parsedSig, err) - assert.IsType(t, InvalidSignatureError{}, err) - - // A valid signature with a rejected identity. - nonmatchingPRM, err := NewPRMExactReference("this/doesnt:match") - require.NoError(t, err) - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", nonmatchingPRM) - require.NoError(t, err) - sar, parsedSig, err = pr.isSignatureAuthorAccepted(testImage, testImageSig) - assertSARRejectedPolicyRequirement(t, sar, parsedSig, err) - - // Error reading image manifest - image := dirImageMock("fixtures/dir-img-no-manifest", "testing/manifest:latest") - sig, err = ioutil.ReadFile("fixtures/dir-img-no-manifest/signature-1") - require.NoError(t, err) - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sar, parsedSig, err = pr.isSignatureAuthorAccepted(image, sig) - assertSARRejected(t, sar, parsedSig, err) - - // Error computing manifest digest - image = dirImageMock("fixtures/dir-img-manifest-digest-error", "testing/manifest:latest") - sig, err = ioutil.ReadFile("fixtures/dir-img-manifest-digest-error/signature-1") - require.NoError(t, err) - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sar, parsedSig, err = pr.isSignatureAuthorAccepted(image, sig) - assertSARRejected(t, sar, parsedSig, err) - - // A valid signature with a non-matching manifest - image = dirImageMock("fixtures/dir-img-modified-manifest", "testing/manifest:latest") - sig, err = ioutil.ReadFile("fixtures/dir-img-modified-manifest/signature-1") - require.NoError(t, err) - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - sar, parsedSig, err = pr.isSignatureAuthorAccepted(image, sig) - assertSARRejectedPolicyRequirement(t, sar, parsedSig, err) -} - -// createInvalidSigDir creates a directory suitable for dirImageMock, in which image.Signatures() -// fails. -// The caller should eventually call os.RemoveAll on the returned path. -func createInvalidSigDir(t *testing.T) string { - dir, err := ioutil.TempDir("", "skopeo-test-unreadable-signature") - require.NoError(t, err) - err = ioutil.WriteFile(path.Join(dir, "manifest.json"), []byte("{}"), 0644) - require.NoError(t, err) - // Creating a 000-permissions file would work for unprivileged accounts, but root (in particular, - // in the Docker container we use for testing) would still have access. So, create a symlink - // pointing to itself, to cause an ELOOP. (Note that a symlink pointing to a nonexistent file would be treated - // just like a nonexistent signature file, and not an error.) - err = os.Symlink("signature-1", path.Join(dir, "signature-1")) - require.NoError(t, err) - return dir -} - -func TestPRSignedByIsRunningImageAllowed(t *testing.T) { - ktGPG := SBKeyTypeGPGKeys - prm := NewPRMMatchExact() - - // A simple success case: single valid signature. - image := dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - pr, err := NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err := pr.isRunningImageAllowed(image) - assertRunningAllowed(t, allowed, err) - - // Error reading signatures - invalidSigDir := createInvalidSigDir(t) - defer os.RemoveAll(invalidSigDir) - image = dirImageMock(invalidSigDir, "testing/manifest:latest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningRejected(t, allowed, err) - - // No signatures - image = dirImageMock("fixtures/dir-img-unsigned", "testing/manifest:latest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, allowed, err) - - // 1 invalid signature: use dir-img-valid, but a non-matching Docker reference - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:notlatest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, allowed, err) - - // 2 valid signatures - image = dirImageMock("fixtures/dir-img-valid-2", "testing/manifest:latest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningAllowed(t, allowed, err) - - // One invalid, one valid signature (in this order) - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:latest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningAllowed(t, allowed, err) - - // 2 invalid signatures: use dir-img-valid-2, but a non-matching Docker reference - image = dirImageMock("fixtures/dir-img-valid-2", "testing/manifest:notlatest") - pr, err = NewPRSignedByKeyPath(ktGPG, "fixtures/public-key.gpg", prm) - require.NoError(t, err) - allowed, err = pr.isRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, allowed, err) -} diff --git a/signature/policy_eval_simple_test.go b/signature/policy_eval_simple_test.go deleted file mode 100644 index c4434b10..00000000 --- a/signature/policy_eval_simple_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package signature - -import "testing" - -func TestPRInsecureAcceptAnythingIsSignatureAuthorAccepted(t *testing.T) { - pr := NewPRInsecureAcceptAnything() - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err := pr.isSignatureAuthorAccepted(nil, nil) - assertSARUnknown(t, sar, parsedSig, err) -} - -func TestPRInsecureAcceptAnythingIsRunningImageAllowed(t *testing.T) { - pr := NewPRInsecureAcceptAnything() - // Pass a nil pointer to, kind of, test that the return value does not depend on the image. - res, err := pr.isRunningImageAllowed(nil) - assertRunningAllowed(t, res, err) -} - -func TestPRRejectIsSignatureAuthorAccepted(t *testing.T) { - pr := NewPRReject() - // Pass nil pointers to, kind of, test that the return value does not depend on the parameters. - sar, parsedSig, err := pr.isSignatureAuthorAccepted(nil, nil) - assertSARRejectedPolicyRequirement(t, sar, parsedSig, err) -} - -func TestPRRejectIsRunningImageAllowed(t *testing.T) { - // This will obviously need to change after this is implemented. - pr := NewPRReject() - // Pass a nil pointer to, kind of, test that the return value does not depend on the image. - res, err := pr.isRunningImageAllowed(nil) - assertRunningRejectedPolicyRequirement(t, res, err) -} diff --git a/signature/policy_eval_test.go b/signature/policy_eval_test.go deleted file mode 100644 index 254b285d..00000000 --- a/signature/policy_eval_test.go +++ /dev/null @@ -1,504 +0,0 @@ -package signature - -import ( - "fmt" - "os" - "testing" - - "github.com/projectatomic/skopeo/reference" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestPolicyRequirementError(t *testing.T) { - // A stupid test just to keep code coverage - s := "test" - err := PolicyRequirementError(s) - assert.Equal(t, s, err.Error()) -} - -func TestPolicyContextChangeState(t *testing.T) { - pc, err := NewPolicyContext(&Policy{Default: PolicyRequirements{NewPRReject()}}) - require.NoError(t, err) - defer pc.Destroy() - - require.Equal(t, pcReady, pc.state) - err = pc.changeState(pcReady, pcInUse) - require.NoError(t, err) - - err = pc.changeState(pcReady, pcInUse) - require.Error(t, err) - - // Return state to pcReady to allow pc.Destroy to clean up. - err = pc.changeState(pcInUse, pcReady) - require.NoError(t, err) -} - -func TestPolicyContextNewDestroy(t *testing.T) { - pc, err := NewPolicyContext(&Policy{Default: PolicyRequirements{NewPRReject()}}) - require.NoError(t, err) - assert.Equal(t, pcReady, pc.state) - - err = pc.Destroy() - require.NoError(t, err) - assert.Equal(t, pcDestroyed, pc.state) - - // Trying to destroy when not pcReady - pc, err = NewPolicyContext(&Policy{Default: PolicyRequirements{NewPRReject()}}) - require.NoError(t, err) - err = pc.changeState(pcReady, pcInUse) - require.NoError(t, err) - err = pc.Destroy() - require.Error(t, err) - assert.Equal(t, pcInUse, pc.state) // The state, and hopefully nothing else, has changed. - - err = pc.changeState(pcInUse, pcReady) - require.NoError(t, err) - err = pc.Destroy() - assert.NoError(t, err) -} - -func TestFullyExpandedDockerReference(t *testing.T) { - sha256Digest := "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - // Test both that fullyExpandedDockerReference returns the expected value (fullName+suffix), - // and that .FullName returns the expected value (fullName), i.e. that the two functions are - // consistent. - for inputName, fullName := range map[string]string{ - "example.com/ns/repo": "example.com/ns/repo", - "example.com/repo": "example.com/repo", - "localhost/ns/repo": "localhost/ns/repo", - // Note that "localhost" is special here: notlocalhost/repo is be parsed as docker.io/notlocalhost.repo: - "localhost/repo": "localhost/repo", - "notlocalhost/repo": "docker.io/notlocalhost/repo", - "docker.io/ns/repo": "docker.io/ns/repo", - "docker.io/library/repo": "docker.io/library/repo", - "docker.io/repo": "docker.io/library/repo", - "ns/repo": "docker.io/ns/repo", - "library/repo": "docker.io/library/repo", - "repo": "docker.io/library/repo", - } { - for inputSuffix, mappedSuffix := range map[string]string{ - ":tag": ":tag", - sha256Digest: sha256Digest, - "": "", - // A github.com/distribution/reference value can have a tag and a digest at the same time! - // github.com/skopeo/reference handles that by dropping the tag. That is not obviously the - // right thing to do, but it is at least reasonable, so test that we keep behaving reasonably. - // This test case should not be construed to make this an API promise. - ":tag" + sha256Digest: sha256Digest, - } { - fullInput := inputName + inputSuffix - ref, err := reference.ParseNamed(fullInput) - require.NoError(t, err) - assert.Equal(t, fullName, ref.FullName(), fullInput) - expanded, err := fullyExpandedDockerReference(ref) - require.NoError(t, err) - assert.Equal(t, fullName+mappedSuffix, expanded, fullInput) - } - } -} - -func TestPolicyContextRequirementsForImage(t *testing.T) { - ktGPG := SBKeyTypeGPGKeys - prm := NewPRMMatchExact() - - policy := &Policy{ - Default: PolicyRequirements{NewPRReject()}, - Specific: map[string]PolicyRequirements{}, - } - // Just put _something_ into the Specific map for the keys we care about, and make it pairwise - // distinct so that we can compare the values and show them when debugging the tests. - for _, scope := range []string{ - "unmatched", - "hostname.com", - "hostname.com/namespace", - "hostname.com/namespace/repo", - "hostname.com/namespace/repo:latest", - "hostname.com/namespace/repo:tag2", - "localhost", - "localhost/namespace", - "localhost/namespace/repo", - "localhost/namespace/repo:latest", - "localhost/namespace/repo:tag2", - "deep.com", - "deep.com/n1", - "deep.com/n1/n2", - "deep.com/n1/n2/n3", - "deep.com/n1/n2/n3/repo", - "deep.com/n1/n2/n3/repo:tag2", - "docker.io", - "docker.io/library", - "docker.io/library/busybox", - "docker.io/namespaceindocker", - "docker.io/namespaceindocker/repo", - "docker.io/namespaceindocker/repo:tag2", - // Note: these non-fully-expanded repository names are not matched against canonical (shortened) - // Docker names; they are instead parsed as starting with hostnames. - "busybox", - "library/busybox", - "namespaceindocker", - "namespaceindocker/repo", - "namespaceindocker/repo:tag2", - } { - policy.Specific[scope] = PolicyRequirements{xNewPRSignedByKeyData(ktGPG, []byte(scope), prm)} - } - - pc, err := NewPolicyContext(policy) - require.NoError(t, err) - - for input, matched := range map[string]string{ - // Full match - "hostname.com/namespace/repo:latest": "hostname.com/namespace/repo:latest", - "hostname.com/namespace/repo:tag2": "hostname.com/namespace/repo:tag2", - "hostname.com/namespace/repo": "hostname.com/namespace/repo:latest", - "localhost/namespace/repo:latest": "localhost/namespace/repo:latest", - "localhost/namespace/repo:tag2": "localhost/namespace/repo:tag2", - "localhost/namespace/repo": "localhost/namespace/repo:latest", - "deep.com/n1/n2/n3/repo:tag2": "deep.com/n1/n2/n3/repo:tag2", - // Repository match - "hostname.com/namespace/repo:notlatest": "hostname.com/namespace/repo", - "localhost/namespace/repo:notlatest": "localhost/namespace/repo", - "deep.com/n1/n2/n3/repo:nottag2": "deep.com/n1/n2/n3/repo", - // Namespace match - "hostname.com/namespace/notrepo:latest": "hostname.com/namespace", - "localhost/namespace/notrepo:latest": "localhost/namespace", - "deep.com/n1/n2/n3/notrepo:tag2": "deep.com/n1/n2/n3", - "deep.com/n1/n2/notn3/repo:tag2": "deep.com/n1/n2", - "deep.com/n1/notn2/n3/repo:tag2": "deep.com/n1", - // Host name match - "hostname.com/notnamespace/repo:latest": "hostname.com", - "localhost/notnamespace/repo:latest": "localhost", - "deep.com/notn1/n2/n3/repo:tag2": "deep.com", - // Default - "this.doesnt/match:anything": "", - "this.doesnt/match-anything/defaulttag": "", - - // docker.io canonizalication effects - "docker.io/library/busybox": "docker.io/library/busybox", - "library/busybox": "docker.io/library/busybox", - "busybox": "docker.io/library/busybox", - "docker.io/library/somethinginlibrary": "docker.io/library", - "library/somethinginlibrary": "docker.io/library", - "somethinginlibrary": "docker.io/library", - "docker.io/namespaceindocker/repo:tag2": "docker.io/namespaceindocker/repo:tag2", - "namespaceindocker/repo:tag2": "docker.io/namespaceindocker/repo:tag2", - "docker.io/namespaceindocker/repo:nottag2": "docker.io/namespaceindocker/repo", - "namespaceindocker/repo:nottag2": "docker.io/namespaceindocker/repo", - "docker.io/namespaceindocker/notrepo:tag2": "docker.io/namespaceindocker", - "namespaceindocker/notrepo:tag2": "docker.io/namespaceindocker", - "docker.io/notnamespaceindocker/repo:tag2": "docker.io", - "notnamespaceindocker/repo:tag2": "docker.io", - } { - var expected PolicyRequirements - if matched != "" { - e, ok := policy.Specific[matched] - require.True(t, ok, fmt.Sprintf("case %s: expected reqs not found", input)) - expected = e - } else { - expected = policy.Default - } - - reqs, err := pc.requirementsForImage(refImageMock(input)) - require.NoError(t, err) - comment := fmt.Sprintf("case %s: %#v", input, reqs[0]) - // Do not sue assert.Equal, which would do a deep contents comparison; we want to compare - // the pointers. Also, == does not work on slices; so test that the slices start at the - // same element and have the same length. - assert.True(t, &(reqs[0]) == &(expected[0]), comment) - assert.True(t, len(reqs) == len(expected), comment) - } - - // Invalid reference format - _, err = pc.requirementsForImage(refImageMock("UPPERCASEISINVALID")) - assert.Error(t, err) -} - -func TestPolicyContextGetSignaturesWithAcceptedAuthor(t *testing.T) { - expectedSig := &Signature{ - DockerManifestDigest: TestImageManifestDigest, - DockerReference: "testing/manifest:latest", - } - - pc, err := NewPolicyContext(&Policy{ - Default: PolicyRequirements{NewPRReject()}, - Specific: map[string]PolicyRequirements{ - "docker.io/testing/manifest:latest": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchExact()), - }, - "docker.io/testing/manifest:twoAccepts": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - }, - "docker.io/testing/manifest:acceptReject": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - NewPRReject(), - }, - "docker.io/testing/manifest:acceptUnknown": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - xNewPRSignedBaseLayer(NewPRMMatchRepository()), - }, - "docker.io/testing/manifest:rejectUnknown": { - NewPRReject(), - xNewPRSignedBaseLayer(NewPRMMatchRepository()), - }, - "docker.io/testing/manifest:unknown": { - xNewPRSignedBaseLayer(NewPRMMatchRepository()), - }, - "docker.io/testing/manifest:unknown2": { - NewPRInsecureAcceptAnything(), - }, - "docker.io/testing/manifest:invalidEmptyRequirements": {}, - }, - }) - require.NoError(t, err) - defer pc.Destroy() - - // Success - image := dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - sigs, err := pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Equal(t, []*Signature{expectedSig}, sigs) - - // Two signatures - // FIXME? Use really different signatures for this? - image = dirImageMock("fixtures/dir-img-valid-2", "testing/manifest:latest") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Equal(t, []*Signature{expectedSig, expectedSig}, sigs) - - // No signatures - image = dirImageMock("fixtures/dir-img-unsigned", "testing/manifest:latest") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // Only invalid signatures - image = dirImageMock("fixtures/dir-img-modified-manifest", "testing/manifest:latest") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // 1 invalid, 1 valid signature (in this order) - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:latest") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Equal(t, []*Signature{expectedSig}, sigs) - - // Two sarAccepted results for one signature - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:twoAccepts") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Equal(t, []*Signature{expectedSig}, sigs) - - // sarAccepted+sarRejected for a signature - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:acceptReject") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // sarAccepted+sarUnknown for a signature - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:acceptUnknown") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Equal(t, []*Signature{expectedSig}, sigs) - - // sarRejected+sarUnknown for a signature - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:rejectUnknown") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // sarUnknown only - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:unknown") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:unknown2") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // Empty list of requirements (invalid) - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:invalidEmptyRequirements") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - require.NoError(t, err) - assert.Empty(t, sigs) - - // Failures: Make sure we return nil sigs. - - // Unexpected state (context already destroyed) - destroyedPC, err := NewPolicyContext(pc.Policy) - require.NoError(t, err) - err = destroyedPC.Destroy() - require.NoError(t, err) - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - sigs, err = destroyedPC.GetSignaturesWithAcceptedAuthor(image) - assert.Error(t, err) - assert.Nil(t, sigs) - // Not testing the pcInUse->pcReady transition, that would require custom PolicyRequirement - // implementations meddling with the state, or threads. This is for catching trivial programmer - // mistakes only, anyway. - - // Invalid IntendedDockerReference value - image = dirImageMock("fixtures/dir-img-valid", "UPPERCASEISINVALID") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - assert.Error(t, err) - assert.Nil(t, sigs) - - // Error reading signatures. - invalidSigDir := createInvalidSigDir(t) - defer os.RemoveAll(invalidSigDir) - image = dirImageMock(invalidSigDir, "testing/manifest:latest") - sigs, err = pc.GetSignaturesWithAcceptedAuthor(image) - assert.Error(t, err) - assert.Nil(t, sigs) -} - -func TestPolicyContextIsRunningImageAllowed(t *testing.T) { - pc, err := NewPolicyContext(&Policy{ - Default: PolicyRequirements{NewPRReject()}, - Specific: map[string]PolicyRequirements{ - "docker.io/testing/manifest:latest": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchExact()), - }, - "docker.io/testing/manifest:twoAllows": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - }, - "docker.io/testing/manifest:allowDeny": { - xNewPRSignedByKeyPath(SBKeyTypeGPGKeys, "fixtures/public-key.gpg", NewPRMMatchRepository()), - NewPRReject(), - }, - "docker.io/testing/manifest:reject": { - NewPRReject(), - }, - "docker.io/testing/manifest:acceptAnything": { - NewPRInsecureAcceptAnything(), - }, - "docker.io/testing/manifest:invalidEmptyRequirements": {}, - }, - }) - require.NoError(t, err) - defer pc.Destroy() - - // Success - image := dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - res, err := pc.IsRunningImageAllowed(image) - assertRunningAllowed(t, res, err) - - // Two signatures - // FIXME? Use really different signatures for this? - image = dirImageMock("fixtures/dir-img-valid-2", "testing/manifest:latest") - res, err = pc.IsRunningImageAllowed(image) - assertRunningAllowed(t, res, err) - - // No signatures - image = dirImageMock("fixtures/dir-img-unsigned", "testing/manifest:latest") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, res, err) - - // Only invalid signatures - image = dirImageMock("fixtures/dir-img-modified-manifest", "testing/manifest:latest") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, res, err) - - // 1 invalid, 1 valid signature (in this order) - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:latest") - res, err = pc.IsRunningImageAllowed(image) - assertRunningAllowed(t, res, err) - - // Two allowed results - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:twoAllows") - res, err = pc.IsRunningImageAllowed(image) - assertRunningAllowed(t, res, err) - - // Allow + deny results - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:allowDeny") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, res, err) - - // prReject works - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:reject") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, res, err) - - // prInsecureAcceptAnything works - image = dirImageMock("fixtures/dir-img-mixed", "testing/manifest:acceptAnything") - res, err = pc.IsRunningImageAllowed(image) - assertRunningAllowed(t, res, err) - - // Empty list of requirements (invalid) - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:invalidEmptyRequirements") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejectedPolicyRequirement(t, res, err) - - // Unexpected state (context already destroyed) - destroyedPC, err := NewPolicyContext(pc.Policy) - require.NoError(t, err) - err = destroyedPC.Destroy() - require.NoError(t, err) - image = dirImageMock("fixtures/dir-img-valid", "testing/manifest:latest") - res, err = destroyedPC.IsRunningImageAllowed(image) - assertRunningRejected(t, res, err) - // Not testing the pcInUse->pcReady transition, that would require custom PolicyRequirement - // implementations meddling with the state, or threads. This is for catching trivial programmer - // mistakes only, anyway. - - // Invalid IntendedDockerReference value - image = dirImageMock("fixtures/dir-img-valid", "UPPERCASEISINVALID") - res, err = pc.IsRunningImageAllowed(image) - assertRunningRejected(t, res, err) -} - -// Helpers for validating PolicyRequirement.isSignatureAuthorAccepted results: - -// assertSARRejected verifies that isSignatureAuthorAccepted returns a consistent sarRejected result -// with the expected signature. -func assertSARAccepted(t *testing.T, sar signatureAcceptanceResult, parsedSig *Signature, err error, expectedSig Signature) { - assert.Equal(t, sarAccepted, sar) - assert.Equal(t, &expectedSig, parsedSig) - assert.NoError(t, err) -} - -// assertSARRejected verifies that isSignatureAuthorAccepted returns a consistent sarRejected result. -func assertSARRejected(t *testing.T, sar signatureAcceptanceResult, parsedSig *Signature, err error) { - assert.Equal(t, sarRejected, sar) - assert.Nil(t, parsedSig) - assert.Error(t, err) -} - -// assertSARRejectedPolicyRequiremnt verifies that isSignatureAuthorAccepted returns a consistent sarRejected resul, -// and that the returned error is a PolicyRequirementError.. -func assertSARRejectedPolicyRequirement(t *testing.T, sar signatureAcceptanceResult, parsedSig *Signature, err error) { - assertSARRejected(t, sar, parsedSig, err) - assert.IsType(t, PolicyRequirementError(""), err) -} - -// assertSARRejected verifies that isSignatureAuthorAccepted returns a consistent sarUnknown result. -func assertSARUnknown(t *testing.T, sar signatureAcceptanceResult, parsedSig *Signature, err error) { - assert.Equal(t, sarUnknown, sar) - assert.Nil(t, parsedSig) - assert.NoError(t, err) -} - -// Helpers for validating PolicyRequirement.isRunningImageAllowed results: - -// assertRunningAllowed verifies that isRunningImageAllowed returns a consistent true result -func assertRunningAllowed(t *testing.T, allowed bool, err error) { - assert.Equal(t, true, allowed) - assert.NoError(t, err) -} - -// assertRunningRejected verifies that isRunningImageAllowed returns a consistent false result -func assertRunningRejected(t *testing.T, allowed bool, err error) { - assert.Equal(t, false, allowed) - assert.Error(t, err) -} - -// assertRunningRejectedPolicyRequirement verifies that isRunningImageAllowed returns a consistent false result -// and that the returned error is a PolicyRequirementError. -func assertRunningRejectedPolicyRequirement(t *testing.T, allowed bool, err error) { - assertRunningRejected(t, allowed, err) - assert.IsType(t, PolicyRequirementError(""), err) -} diff --git a/signature/policy_reference_match_test.go b/signature/policy_reference_match_test.go deleted file mode 100644 index 3e477356..00000000 --- a/signature/policy_reference_match_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package signature - -import ( - "fmt" - "testing" - - "github.com/projectatomic/skopeo/types" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - fullRHELRef = "registry.access.redhat.com/rhel7/rhel:7.2.3" - untaggedRHELRef = "registry.access.redhat.com/rhel7/rhel" -) - -func TestParseDockerReferences(t *testing.T) { - const ( - ok1 = "busybox" - ok2 = fullRHELRef - bad1 = "UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES" - bad2 = "" - ) - - // Success - r1, r2, err := parseDockerReferences(ok1, ok2) - require.NoError(t, err) - assert.Equal(t, ok1, r1.String()) - assert.Equal(t, ok2, r2.String()) - - // Failures - for _, refs := range [][]string{ - {bad1, ok2}, - {ok1, bad2}, - {bad1, bad2}, - } { - _, _, err := parseDockerReferences(refs[0], refs[1]) - assert.Error(t, err) - } -} - -// refImageMock is a mock of types.Image which returns itself in IntendedDockerReference. -type refImageMock string - -func (ref refImageMock) IntendedDockerReference() string { - return string(ref) -} -func (ref refImageMock) Manifest() ([]byte, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) ManifestMatchesDigest(expectedDigest string) (bool, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) Signatures() ([][]byte, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) LayerDigests() ([]string, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) LayersCommand(layers ...string) error { - panic("unexpected call to a mock function") -} -func (ref refImageMock) Inspect() (*types.ImageInspectInfo, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) DockerTar() ([]byte, error) { - panic("unexpected call to a mock function") -} -func (ref refImageMock) GetRepositoryTags() ([]string, error) { - panic("unexpected call to a mock function") -} - -type prmTableTest struct { - imageRef, sigRef string - result bool -} - -// Test cases for exact reference match -var prmExactMatchTestTable = []prmTableTest{ - // Success, simple matches - {"busybox:latest", "busybox:latest", true}, - {fullRHELRef, fullRHELRef, true}, - // Non-canonical reference format is canonicalized - {"library/busybox:latest", "busybox:latest", true}, - {"busybox:latest", "library/busybox:latest", true}, - {"docker.io/library/busybox:latest", "busybox:latest", true}, - {"busybox:latest", "docker.io/library/busybox:latest", true}, - // Mismatch - {"busybox:latest", "busybox:notlatest", false}, - {"busybox:latest", "notbusybox:latest", false}, - {"busybox:latest", "hostname/library/busybox:notlatest", false}, - {"hostname/library/busybox:latest", "busybox:notlatest", false}, - {"busybox:latest", fullRHELRef, false}, - // Missing tags - {"busybox", "busybox:latest", false}, - {"busybox:latest", "busybox", false}, - {"busybox", "busybox", false}, - // Invalid format - {"UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", "busybox:latest", false}, - {"busybox:latest", "UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", false}, - {"", "UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", false}, - // Even if they are exactly equal, invalid values are rejected. - {"INVALID", "INVALID", false}, -} - -// Test cases for repository-only reference match -var prmRepositoryMatchTestTable = []prmTableTest{ - // Success, simple matches - {"busybox:latest", "busybox:latest", true}, - {fullRHELRef, fullRHELRef, true}, - // Non-canonical reference format is canonicalized - {"library/busybox:latest", "busybox:latest", true}, - {"busybox:latest", "library/busybox:latest", true}, - {"docker.io/library/busybox:latest", "busybox:latest", true}, - {"busybox:latest", "docker.io/library/busybox:latest", true}, - // The same as above, but with mismatching tags - {"busybox:latest", "busybox:notlatest", true}, - {fullRHELRef + "tagsuffix", fullRHELRef, true}, - {"library/busybox:latest", "busybox:notlatest", true}, - {"busybox:latest", "library/busybox:notlatest", true}, - {"docker.io/library/busybox:notlatest", "busybox:latest", true}, - {"busybox:notlatest", "docker.io/library/busybox:latest", true}, - // The same as above, but with defaulted tags (should not actually happen) - {"busybox", "busybox:notlatest", true}, - {fullRHELRef, untaggedRHELRef, true}, - {"library/busybox", "busybox", true}, - {"busybox", "library/busybox", true}, - {"docker.io/library/busybox", "busybox", true}, - {"busybox", "docker.io/library/busybox", true}, - // Mismatch - {"busybox:latest", "notbusybox:latest", false}, - {"hostname/library/busybox:latest", "busybox:notlatest", false}, - {"busybox:latest", fullRHELRef, false}, - // Invalid format - {"UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", "busybox:latest", false}, - {"busybox:latest", "UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", false}, - {"", "UPPERCASE_IS_INVALID_IN_DOCKER_REFERENCES", false}, - // Even if they are exactly equal, invalid values are rejected. - {"INVALID", "INVALID", false}, -} - -func TestPRMMatchExactMatchesDockerReference(t *testing.T) { - prm := NewPRMMatchExact() - for _, test := range prmExactMatchTestTable { - res := prm.matchesDockerReference(refImageMock(test.imageRef), test.sigRef) - assert.Equal(t, test.result, res, fmt.Sprintf("%s vs. %s", test.imageRef, test.sigRef)) - } -} - -func TestPRMMatchRepositoryMatchesDockerReference(t *testing.T) { - prm := NewPRMMatchRepository() - for _, test := range prmRepositoryMatchTestTable { - res := prm.matchesDockerReference(refImageMock(test.imageRef), test.sigRef) - assert.Equal(t, test.result, res, fmt.Sprintf("%s vs. %s", test.imageRef, test.sigRef)) - } -} - -// forbiddenImageMock is a mock of types.Image which ensures IntendedDockerReference is not called -type forbiddenImageMock string - -func (ref forbiddenImageMock) IntendedDockerReference() string { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) Manifest() ([]byte, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) ManifestMatchesDigest(expectedDigest string) (bool, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) Signatures() ([][]byte, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) LayerDigests() ([]string, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) LayersCommand(layers ...string) error { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) Inspect() (*types.ImageInspectInfo, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) DockerTar() ([]byte, error) { - panic("unexpected call to a mock function") -} -func (ref forbiddenImageMock) GetRepositoryTags() ([]string, error) { - panic("unexpected call to a mock function") -} - -func TestPRMExactReferenceMatchesDockerReference(t *testing.T) { - for _, test := range prmExactMatchTestTable { - // Do not use NewPRMExactReference, we want to also test the case with an invalid DockerReference, - // even though NewPRMExactReference should never let it happen. - prm := prmExactReference{DockerReference: test.imageRef} - res := prm.matchesDockerReference(forbiddenImageMock(""), test.sigRef) - assert.Equal(t, test.result, res, fmt.Sprintf("%s vs. %s", test.imageRef, test.sigRef)) - } -} - -func TestPRMExactRepositoryMatchesDockerReference(t *testing.T) { - for _, test := range prmRepositoryMatchTestTable { - // Do not use NewPRMExactRepository, we want to also test the case with an invalid DockerReference, - // even though NewPRMExactRepository should never let it happen. - prm := prmExactRepository{DockerRepository: test.imageRef} - res := prm.matchesDockerReference(forbiddenImageMock(""), test.sigRef) - assert.Equal(t, test.result, res, fmt.Sprintf("%s vs. %s", test.imageRef, test.sigRef)) - } -} diff --git a/signature/signature_test.go b/signature/signature_test.go deleted file mode 100644 index db63abee..00000000 --- a/signature/signature_test.go +++ /dev/null @@ -1,288 +0,0 @@ -package signature - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestInvalidSignatureError(t *testing.T) { - // A stupid test just to keep code coverage - s := "test" - err := InvalidSignatureError{msg: s} - assert.Equal(t, s, err.Error()) -} - -func TestMarshalJSON(t *testing.T) { - // Empty string values - s := privateSignature{Signature{DockerManifestDigest: "", DockerReference: "_"}} - _, err := s.MarshalJSON() - assert.Error(t, err) - s = privateSignature{Signature{DockerManifestDigest: "_", DockerReference: ""}} - _, err = s.MarshalJSON() - assert.Error(t, err) - - // Success - s = privateSignature{Signature{DockerManifestDigest: "digest!@#", DockerReference: "reference#@!"}} - marshaled, err := s.marshalJSONWithVariables(0, "CREATOR") - require.NoError(t, err) - assert.Equal(t, []byte("{\"critical\":{\"identity\":{\"docker-reference\":\"reference#@!\"},\"image\":{\"docker-manifest-digest\":\"digest!@#\"},\"type\":\"atomic container signature\"},\"optional\":{\"creator\":\"CREATOR\",\"timestamp\":0}}"), - marshaled) - - // We can't test MarshalJSON directly because the timestamp will keep changing, so just test that - // it doesn't fail. And call it through the JSON package for a good measure. - _, err = json.Marshal(s) - assert.NoError(t, err) -} - -// Return the result of modifying validJSON with fn and unmarshaling it into *sig -func tryUnmarshalModifiedSignature(t *testing.T, sig *privateSignature, validJSON []byte, modifyFn func(mSI)) error { - var tmp mSI - err := json.Unmarshal(validJSON, &tmp) - require.NoError(t, err) - - modifyFn(tmp) - - testJSON, err := json.Marshal(tmp) - require.NoError(t, err) - - *sig = privateSignature{} - return json.Unmarshal(testJSON, sig) -} - -func TestUnmarshalJSON(t *testing.T) { - var s privateSignature - // Invalid input. Note that json.Unmarshal is guaranteed to validate input before calling our - // UnmarshalJSON implementation; so test that first, then test our error handling for completeness. - err := json.Unmarshal([]byte("&"), &s) - assert.Error(t, err) - err = s.UnmarshalJSON([]byte("&")) - assert.Error(t, err) - - // Not an object - err = json.Unmarshal([]byte("1"), &s) - assert.Error(t, err) - - // Start with a valid JSON. - validSig := privateSignature{ - Signature{ - DockerManifestDigest: "digest!@#", - DockerReference: "reference#@!", - }, - } - validJSON, err := validSig.MarshalJSON() - require.NoError(t, err) - - // Success - s = privateSignature{} - err = json.Unmarshal(validJSON, &s) - require.NoError(t, err) - assert.Equal(t, validSig, s) - - // Various ways to corrupt the JSON - breakFns := []func(mSI){ - // A top-level field is missing - func(v mSI) { delete(v, "critical") }, - func(v mSI) { delete(v, "optional") }, - // Extra top-level sub-object - func(v mSI) { v["unexpected"] = 1 }, - // "critical" not an object - func(v mSI) { v["critical"] = 1 }, - // "optional" not an object - func(v mSI) { v["optional"] = 1 }, - // A field of "critical" is missing - func(v mSI) { delete(x(v, "critical"), "type") }, - func(v mSI) { delete(x(v, "critical"), "image") }, - func(v mSI) { delete(x(v, "critical"), "identity") }, - // Extra field of "critical" - func(v mSI) { x(v, "critical")["unexpected"] = 1 }, - // Invalid "type" - func(v mSI) { x(v, "critical")["type"] = 1 }, - func(v mSI) { x(v, "critical")["type"] = "unexpected" }, - // Invalid "image" object - func(v mSI) { x(v, "critical")["image"] = 1 }, - func(v mSI) { delete(x(v, "critical", "image"), "docker-manifest-digest") }, - func(v mSI) { x(v, "critical", "image")["unexpected"] = 1 }, - // Invalid "docker-manifest-digest" - func(v mSI) { x(v, "critical", "image")["docker-manifest-digest"] = 1 }, - // Invalid "identity" object - func(v mSI) { x(v, "critical")["identity"] = 1 }, - func(v mSI) { delete(x(v, "critical", "identity"), "docker-reference") }, - func(v mSI) { x(v, "critical", "identity")["unexpected"] = 1 }, - // Invalid "docker-reference" - func(v mSI) { x(v, "critical", "identity")["docker-reference"] = 1 }, - } - for _, fn := range breakFns { - err = tryUnmarshalModifiedSignature(t, &s, validJSON, fn) - assert.Error(t, err) - } - - // Modifications to "optional" are allowed and ignored - allowedModificationFns := []func(mSI){ - // Add an optional field - func(v mSI) { x(v, "optional")["unexpected"] = 1 }, - // Delete an optional field - func(v mSI) { delete(x(v, "optional"), "creator") }, - } - for _, fn := range allowedModificationFns { - err = tryUnmarshalModifiedSignature(t, &s, validJSON, fn) - require.NoError(t, err) - assert.Equal(t, validSig, s) - } -} - -func TestSign(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - - sig := privateSignature{ - Signature{ - DockerManifestDigest: "digest!@#", - DockerReference: "reference#@!", - }, - } - - // Successful signing - signature, err := sig.sign(mech, TestKeyFingerprint) - require.NoError(t, err) - - verified, err := verifyAndExtractSignature(mech, signature, signatureAcceptanceRules{ - validateKeyIdentity: func(keyIdentity string) error { - if keyIdentity != TestKeyFingerprint { - return fmt.Errorf("Unexpected keyIdentity") - } - return nil - }, - validateSignedDockerReference: func(signedDockerReference string) error { - if signedDockerReference != sig.DockerReference { - return fmt.Errorf("Unexpected signedDockerReference") - } - return nil - }, - validateSignedDockerManifestDigest: func(signedDockerManifestDigest string) error { - if signedDockerManifestDigest != sig.DockerManifestDigest { - return fmt.Errorf("Unexpected signedDockerManifestDigest") - } - return nil - }, - }) - require.NoError(t, err) - - assert.Equal(t, sig.Signature, *verified) - - // Error creating blob to sign - _, err = privateSignature{}.sign(mech, TestKeyFingerprint) - assert.Error(t, err) - - // Error signing - _, err = sig.sign(mech, "this fingerprint doesn't exist") - assert.Error(t, err) -} - -func TestVerifyAndExtractSignature(t *testing.T) { - mech, err := newGPGSigningMechanismInDirectory(testGPGHomeDirectory) - require.NoError(t, err) - - type triple struct{ keyIdentity, signedDockerReference, signedDockerManifestDigest string } - var wanted, recorded triple - // recordingRules are a plausible signatureAcceptanceRules implementations, but equally - // importantly record that we are passing the correct values to the rule callbacks. - recordingRules := signatureAcceptanceRules{ - validateKeyIdentity: func(keyIdentity string) error { - recorded.keyIdentity = keyIdentity - if keyIdentity != wanted.keyIdentity { - return fmt.Errorf("keyIdentity mismatch") - } - return nil - }, - validateSignedDockerReference: func(signedDockerReference string) error { - recorded.signedDockerReference = signedDockerReference - if signedDockerReference != wanted.signedDockerReference { - return fmt.Errorf("signedDockerReference mismatch") - } - return nil - }, - validateSignedDockerManifestDigest: func(signedDockerManifestDigest string) error { - recorded.signedDockerManifestDigest = signedDockerManifestDigest - if signedDockerManifestDigest != wanted.signedDockerManifestDigest { - return fmt.Errorf("signedDockerManifestDigest mismatch") - } - return nil - }, - } - - signature, err := ioutil.ReadFile("./fixtures/image.signature") - require.NoError(t, err) - signatureData := triple{ - keyIdentity: TestKeyFingerprint, - signedDockerReference: TestImageSignatureReference, - signedDockerManifestDigest: TestImageManifestDigest, - } - - // Successful verification - wanted = signatureData - recorded = triple{} - sig, err := verifyAndExtractSignature(mech, signature, recordingRules) - require.NoError(t, err) - assert.Equal(t, TestImageSignatureReference, sig.DockerReference) - assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest) - assert.Equal(t, signatureData, recorded) - - // For extra paranoia, test that we return a nil signature object on error. - - // Completely invalid signature. - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, []byte{}, recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, triple{}, recorded) - - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, []byte("invalid signature"), recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, triple{}, recorded) - - // Valid signature of non-JSON: asked for keyIdentity, only - invalidBlobSignature, err := ioutil.ReadFile("./fixtures/invalid-blob.signature") - require.NoError(t, err) - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, invalidBlobSignature, recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, triple{keyIdentity: signatureData.keyIdentity}, recorded) - - // Valid signature with a wrong key: asked for keyIdentity, only - wanted = signatureData - wanted.keyIdentity = "unexpected fingerprint" - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, signature, recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, triple{keyIdentity: signatureData.keyIdentity}, recorded) - - // Valid signature with a wrong manifest digest: asked for keyIdentity and signedDockerManifestDigest - wanted = signatureData - wanted.signedDockerManifestDigest = "invalid digest" - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, signature, recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, triple{ - keyIdentity: signatureData.keyIdentity, - signedDockerManifestDigest: signatureData.signedDockerManifestDigest, - }, recorded) - - // Valid signature with a wrong image reference - wanted = signatureData - wanted.signedDockerReference = "unexpected docker reference" - recorded = triple{} - sig, err = verifyAndExtractSignature(mech, signature, recordingRules) - assert.Error(t, err) - assert.Nil(t, sig) - assert.Equal(t, signatureData, recorded) -} diff --git a/vendor/github.com/containers/image/LICENSE b/vendor/github.com/containers/image/LICENSE new file mode 100644 index 00000000..95356353 --- /dev/null +++ b/vendor/github.com/containers/image/LICENSE @@ -0,0 +1,189 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + 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 + + https://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. diff --git a/directory/directory.go b/vendor/github.com/containers/image/directory/directory.go similarity index 98% rename from directory/directory.go rename to vendor/github.com/containers/image/directory/directory.go index cfe5d394..6e3ca638 100644 --- a/directory/directory.go +++ b/vendor/github.com/containers/image/directory/directory.go @@ -8,7 +8,7 @@ import ( "path/filepath" "strings" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/types" ) // manifestPath returns a path for the manifest within a directory using our conventions. diff --git a/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go similarity index 100% rename from docker/docker_client.go rename to vendor/github.com/containers/image/docker/docker_client.go diff --git a/docker/docker_image.go b/vendor/github.com/containers/image/docker/docker_image.go similarity index 94% rename from docker/docker_image.go rename to vendor/github.com/containers/image/docker/docker_image.go index f449ca89..a4ce9743 100644 --- a/docker/docker_image.go +++ b/vendor/github.com/containers/image/docker/docker_image.go @@ -5,8 +5,8 @@ import ( "fmt" "net/http" - "github.com/projectatomic/skopeo/image" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/image" + "github.com/containers/image/types" ) // Image is a Docker-specific implementation of types.Image with a few extra methods diff --git a/docker/docker_image_dest.go b/vendor/github.com/containers/image/docker/docker_image_dest.go similarity index 96% rename from docker/docker_image_dest.go rename to vendor/github.com/containers/image/docker/docker_image_dest.go index 77dcae12..be49f684 100644 --- a/docker/docker_image_dest.go +++ b/vendor/github.com/containers/image/docker/docker_image_dest.go @@ -8,9 +8,9 @@ import ( "net/http" "github.com/Sirupsen/logrus" - "github.com/projectatomic/skopeo/manifest" - "github.com/projectatomic/skopeo/reference" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/manifest" + "github.com/containers/image/reference" + "github.com/containers/image/types" ) type dockerImageDestination struct { diff --git a/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go similarity index 97% rename from docker/docker_image_src.go rename to vendor/github.com/containers/image/docker/docker_image_src.go index b9be1ba9..ceca2957 100644 --- a/docker/docker_image_src.go +++ b/vendor/github.com/containers/image/docker/docker_image_src.go @@ -8,9 +8,9 @@ import ( "strconv" "github.com/Sirupsen/logrus" - "github.com/projectatomic/skopeo/manifest" - "github.com/projectatomic/skopeo/reference" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/manifest" + "github.com/containers/image/reference" + "github.com/containers/image/types" ) type errFetchManifest struct { diff --git a/docker/docker_utils.go b/vendor/github.com/containers/image/docker/docker_utils.go similarity index 89% rename from docker/docker_utils.go rename to vendor/github.com/containers/image/docker/docker_utils.go index 5a46dce9..2bfc117a 100644 --- a/docker/docker_utils.go +++ b/vendor/github.com/containers/image/docker/docker_utils.go @@ -1,6 +1,6 @@ package docker -import "github.com/projectatomic/skopeo/reference" +import "github.com/containers/image/reference" // parseDockerImageName converts a string into a reference and tag value. func parseDockerImageName(img string) (reference.Named, string, error) { diff --git a/image/image.go b/vendor/github.com/containers/image/image/image.go similarity index 98% rename from image/image.go rename to vendor/github.com/containers/image/image/image.go index aced0802..3b110f6c 100644 --- a/image/image.go +++ b/vendor/github.com/containers/image/image/image.go @@ -12,9 +12,9 @@ import ( "strings" "time" - "github.com/projectatomic/skopeo/directory" - "github.com/projectatomic/skopeo/manifest" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/directory" + "github.com/containers/image/manifest" + "github.com/containers/image/types" ) var ( diff --git a/manifest/manifest.go b/vendor/github.com/containers/image/manifest/manifest.go similarity index 100% rename from manifest/manifest.go rename to vendor/github.com/containers/image/manifest/manifest.go diff --git a/openshift/openshift-copies.go b/vendor/github.com/containers/image/openshift/openshift-copies.go similarity index 100% rename from openshift/openshift-copies.go rename to vendor/github.com/containers/image/openshift/openshift-copies.go diff --git a/openshift/openshift.go b/vendor/github.com/containers/image/openshift/openshift.go similarity index 98% rename from openshift/openshift.go rename to vendor/github.com/containers/image/openshift/openshift.go index 7bf31984..632bd1c5 100644 --- a/openshift/openshift.go +++ b/vendor/github.com/containers/image/openshift/openshift.go @@ -13,10 +13,10 @@ import ( "strings" "github.com/Sirupsen/logrus" - "github.com/projectatomic/skopeo/docker" - "github.com/projectatomic/skopeo/manifest" - "github.com/projectatomic/skopeo/types" - "github.com/projectatomic/skopeo/version" + "github.com/containers/image/docker" + "github.com/containers/image/manifest" + "github.com/containers/image/types" + "github.com/containers/image/version" ) // openshiftClient is configuration for dealing with a single image stream, for reading or writing. diff --git a/reference/reference.go b/vendor/github.com/containers/image/reference/reference.go similarity index 100% rename from reference/reference.go rename to vendor/github.com/containers/image/reference/reference.go diff --git a/signature/docker.go b/vendor/github.com/containers/image/signature/docker.go similarity index 93% rename from signature/docker.go rename to vendor/github.com/containers/image/signature/docker.go index f3cf0985..9f8ad619 100644 --- a/signature/docker.go +++ b/vendor/github.com/containers/image/signature/docker.go @@ -5,7 +5,7 @@ package signature import ( "fmt" - "github.com/projectatomic/skopeo/manifest" + "github.com/containers/image/manifest" ) // SignDockerManifest returns a signature for manifest as the specified dockerReference, @@ -48,7 +48,7 @@ func VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest []byt return err } if !matches { - return InvalidSignatureError{msg: fmt.Sprintf("Signature for docker digest %s does not match", signedDockerManifestDigest, signedDockerManifestDigest)} + return InvalidSignatureError{msg: fmt.Sprintf("Signature for docker digest %q does not match", signedDockerManifestDigest)} } return nil }, diff --git a/signature/json.go b/vendor/github.com/containers/image/signature/json.go similarity index 100% rename from signature/json.go rename to vendor/github.com/containers/image/signature/json.go diff --git a/signature/mechanism.go b/vendor/github.com/containers/image/signature/mechanism.go similarity index 100% rename from signature/mechanism.go rename to vendor/github.com/containers/image/signature/mechanism.go diff --git a/signature/policy_config.go b/vendor/github.com/containers/image/signature/policy_config.go similarity index 99% rename from signature/policy_config.go rename to vendor/github.com/containers/image/signature/policy_config.go index 7fc5a382..767e02a9 100644 --- a/signature/policy_config.go +++ b/vendor/github.com/containers/image/signature/policy_config.go @@ -18,7 +18,7 @@ import ( "fmt" "io/ioutil" - "github.com/projectatomic/skopeo/reference" + "github.com/containers/image/reference" ) // InvalidPolicyFormatError is returned when parsing an invalid policy configuration. diff --git a/signature/policy_eval.go b/vendor/github.com/containers/image/signature/policy_eval.go similarity index 99% rename from signature/policy_eval.go rename to vendor/github.com/containers/image/signature/policy_eval.go index c62328ed..a7d89d78 100644 --- a/signature/policy_eval.go +++ b/vendor/github.com/containers/image/signature/policy_eval.go @@ -11,8 +11,8 @@ import ( "github.com/Sirupsen/logrus" distreference "github.com/docker/distribution/reference" - "github.com/projectatomic/skopeo/reference" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/reference" + "github.com/containers/image/types" ) // PolicyRequirementError is an explanatory text for rejecting a signature or an image. diff --git a/signature/policy_eval_baselayer.go b/vendor/github.com/containers/image/signature/policy_eval_baselayer.go similarity index 93% rename from signature/policy_eval_baselayer.go rename to vendor/github.com/containers/image/signature/policy_eval_baselayer.go index 61b62e08..8e5e628a 100644 --- a/signature/policy_eval_baselayer.go +++ b/vendor/github.com/containers/image/signature/policy_eval_baselayer.go @@ -4,7 +4,7 @@ package signature import ( "github.com/Sirupsen/logrus" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/types" ) func (pr *prSignedBaseLayer) isSignatureAuthorAccepted(image types.Image, sig []byte) (signatureAcceptanceResult, *Signature, error) { diff --git a/signature/policy_eval_signedby.go b/vendor/github.com/containers/image/signature/policy_eval_signedby.go similarity index 97% rename from signature/policy_eval_signedby.go rename to vendor/github.com/containers/image/signature/policy_eval_signedby.go index 761693ab..9f9bef82 100644 --- a/signature/policy_eval_signedby.go +++ b/vendor/github.com/containers/image/signature/policy_eval_signedby.go @@ -9,8 +9,8 @@ import ( "os" "strings" - "github.com/projectatomic/skopeo/manifest" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/manifest" + "github.com/containers/image/types" ) func (pr *prSignedBy) isSignatureAuthorAccepted(image types.Image, sig []byte) (signatureAcceptanceResult, *Signature, error) { diff --git a/signature/policy_eval_simple.go b/vendor/github.com/containers/image/signature/policy_eval_simple.go similarity index 95% rename from signature/policy_eval_simple.go rename to vendor/github.com/containers/image/signature/policy_eval_simple.go index 53530353..0ad2b2e2 100644 --- a/signature/policy_eval_simple.go +++ b/vendor/github.com/containers/image/signature/policy_eval_simple.go @@ -2,7 +2,7 @@ package signature -import "github.com/projectatomic/skopeo/types" +import "github.com/containers/image/types" func (pr *prInsecureAcceptAnything) isSignatureAuthorAccepted(image types.Image, sig []byte) (signatureAcceptanceResult, *Signature, error) { // prInsecureAcceptAnything semantics: Every image is allowed to run, diff --git a/signature/policy_reference_match.go b/vendor/github.com/containers/image/signature/policy_reference_match.go similarity index 96% rename from signature/policy_reference_match.go rename to vendor/github.com/containers/image/signature/policy_reference_match.go index b1d2caea..8c700e6c 100644 --- a/signature/policy_reference_match.go +++ b/vendor/github.com/containers/image/signature/policy_reference_match.go @@ -3,8 +3,8 @@ package signature import ( - "github.com/projectatomic/skopeo/reference" - "github.com/projectatomic/skopeo/types" + "github.com/containers/image/reference" + "github.com/containers/image/types" ) // parseDockerReferences converts two reference strings into parsed entities, failing on any error diff --git a/signature/policy_types.go b/vendor/github.com/containers/image/signature/policy_types.go similarity index 100% rename from signature/policy_types.go rename to vendor/github.com/containers/image/signature/policy_types.go diff --git a/signature/signature.go b/vendor/github.com/containers/image/signature/signature.go similarity index 99% rename from signature/signature.go rename to vendor/github.com/containers/image/signature/signature.go index bf1c63e9..adc15b29 100644 --- a/signature/signature.go +++ b/vendor/github.com/containers/image/signature/signature.go @@ -8,7 +8,7 @@ import ( "fmt" "time" - "github.com/projectatomic/skopeo/version" + "github.com/containers/image/version" ) const ( diff --git a/types/types.go b/vendor/github.com/containers/image/types/types.go similarity index 100% rename from types/types.go rename to vendor/github.com/containers/image/types/types.go diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go new file mode 100644 index 00000000..ea7c9d9e --- /dev/null +++ b/vendor/github.com/containers/image/version/version.go @@ -0,0 +1,4 @@ +package version + +// Version is the version of the build. +const Version = "0.1.14-dev"