From 37679bfc855d1382b41e261c6e0e7124d74c3efc Mon Sep 17 00:00:00 2001 From: glefloch Date: Wed, 7 Nov 2018 13:42:43 +0100 Subject: [PATCH] Add missing test Signed-off-by: glefloch --- e2e/compose-env.yaml | 8 +++ e2e/container/create_test.go | 70 ++++++++++++++++++++- e2e/internal/fixtures/fixtures.go | 15 ++++- e2e/testdata/Dockerfile.evil-notary-server | 4 ++ e2e/testdata/notary-evil/notary-config.json | 19 ++++++ e2e/testdata/notary-evil/notary-server.cert | 64 +++++++++++++++++++ e2e/testdata/notary-evil/notary-server.key | 28 +++++++++ e2e/testdata/notary-evil/root-ca.cert | 32 ++++++++++ 8 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 e2e/testdata/Dockerfile.evil-notary-server create mode 100644 e2e/testdata/notary-evil/notary-config.json create mode 100644 e2e/testdata/notary-evil/notary-server.cert create mode 100644 e2e/testdata/notary-evil/notary-server.key create mode 100644 e2e/testdata/notary-evil/root-ca.cert diff --git a/e2e/compose-env.yaml b/e2e/compose-env.yaml index 76eda15a8c..dd7b5a649a 100644 --- a/e2e/compose-env.yaml +++ b/e2e/compose-env.yaml @@ -16,3 +16,11 @@ services: ports: - 4443:4443 command: ['notary-server', '-config=/fixtures/notary-config.json'] + evil-notary-server: + build: + context: ./testdata + dockerfile: Dockerfile.evil-notary-server + ports: + - 4444:4443 + command: ['notary-server', '-config=/fixtures/notary-config.json'] + diff --git a/e2e/container/create_test.go b/e2e/container/create_test.go index 9733808604..38e632a290 100644 --- a/e2e/container/create_test.go +++ b/e2e/container/create_test.go @@ -32,4 +32,72 @@ func TestCreateWithContentTrust(t *testing.T) { }) } -// FIXME(vdemeester) TestTrustedCreateFromBadTrustServer needs to be backport too (see https://github.com/moby/moby/pull/36515/files#diff-4b1e56bb77ac16f2ccf956fc24cf0a82L331) +func TestTrustedCreateFromUnreachableTrustServer(t *testing.T) { + dir := fixtures.SetupConfigFile(t) + defer dir.Remove() + image := fixtures.CreateMaskedTrustedRemoteImage(t, registryPrefix, "trust-create", "latest") + + result := icmd.RunCmd( + icmd.Command("docker", "create", image), + fixtures.WithConfig(dir.Path()), + fixtures.WithTrust, + fixtures.WithNotaryServer("https://notary.invalid"), + ) + result.Assert(t, icmd.Expected{ + ExitCode: 1, + Err: "error contacting notary server", + }) +} + +func TestTrustedCreateFromBadTrustServer(t *testing.T) { + evilImageName := "registry:5000/evil-alpine:latest" + dir := fixtures.SetupConfigFile(t) + defer dir.Remove() + + // tag the image and upload it to the private registry + icmd.RunCmd(icmd.Command("docker", "tag", fixtures.AlpineImage, evilImageName), + fixtures.WithConfig(dir.Path()), + ).Assert(t, icmd.Success) + icmd.RunCmd(icmd.Command("docker", "image", "push", evilImageName), + fixtures.WithConfig(dir.Path()), + fixtures.WithPassphrase("root_password", "repo_password"), + fixtures.WithTrust, + fixtures.WithNotary, + ).Assert(t, icmd.Success) + icmd.RunCmd(icmd.Command("docker", "image", "rm", evilImageName)).Assert(t, icmd.Success) + + // try create + icmd.RunCmd(icmd.Command("docker", "create", evilImageName), + fixtures.WithConfig(dir.Path()), + fixtures.WithTrust, + fixtures.WithNotary, + ).Assert(t, icmd.Success) + icmd.RunCmd(icmd.Command("docker", "image", "rm", evilImageName)).Assert(t, icmd.Success) + + // init a client with the evil-server and a new trust dir + evilNotaryDir := fixtures.SetupConfigWithNotaryURL(t, "evil-test", fixtures.EvilNotaryURL) + defer evilNotaryDir.Remove() + + // tag the same image and upload it to the private registry but signed with evil notary server + icmd.RunCmd(icmd.Command("docker", "tag", fixtures.AlpineImage, evilImageName), + fixtures.WithConfig(evilNotaryDir.Path()), + ).Assert(t, icmd.Success) + icmd.RunCmd(icmd.Command("docker", "image", "push", evilImageName), + fixtures.WithConfig(evilNotaryDir.Path()), + fixtures.WithPassphrase("root_password", "repo_password"), + fixtures.WithTrust, + fixtures.WithNotaryServer(fixtures.EvilNotaryURL), + ).Assert(t, icmd.Success) + icmd.RunCmd(icmd.Command("docker", "image", "rm", evilImageName)).Assert(t, icmd.Success) + + // try creating with the original client from the evil notary server. This should failed + // because the new root is invalid + icmd.RunCmd(icmd.Command("docker", "create", evilImageName), + fixtures.WithConfig(dir.Path()), + fixtures.WithTrust, + fixtures.WithNotaryServer(fixtures.EvilNotaryURL), + ).Assert(t, icmd.Expected{ + ExitCode: 1, + Err: "could not rotate trust to a new trusted root", + }) +} diff --git a/e2e/internal/fixtures/fixtures.go b/e2e/internal/fixtures/fixtures.go index 99343f6541..a06cf53db6 100644 --- a/e2e/internal/fixtures/fixtures.go +++ b/e2e/internal/fixtures/fixtures.go @@ -12,6 +12,8 @@ import ( const ( //NotaryURL is the location of the notary server NotaryURL = "https://notary-server:4443" + //EvilNotaryURL is the location of the evil notary server + EvilNotaryURL = "https://evil-notary-server:4444" //AlpineImage is an image in the test registry AlpineImage = "registry:5000/alpine:3.6" //AlpineSha is the sha of the alpine image @@ -25,19 +27,26 @@ const ( //SetupConfigFile creates a config.json file for testing func SetupConfigFile(t *testing.T) fs.Dir { t.Helper() - dir := fs.NewDir(t, "trust_test", fs.WithMode(0700), fs.WithFile("config.json", ` + return SetupConfigWithNotaryURL(t, "trust_test", NotaryURL) +} + +//SetupConfigWithNotaryURL creates a config.json file for testing in the given path +//with the given notaryURL +func SetupConfigWithNotaryURL(t *testing.T, path, notaryURL string) fs.Dir { + t.Helper() + dir := fs.NewDir(t, path, fs.WithMode(0700), fs.WithFile("config.json", fmt.Sprintf(` { "auths": { "registry:5000": { "auth": "ZWlhaXM6cGFzc3dvcmQK" }, - "https://notary-server:4443": { + "%s": { "auth": "ZWlhaXM6cGFzc3dvcmQK" } }, "experimental": "enabled" } - `), fs.WithDir("trust", fs.WithDir("private"))) + `, notaryURL)), fs.WithDir("trust", fs.WithDir("private"))) return *dir } diff --git a/e2e/testdata/Dockerfile.evil-notary-server b/e2e/testdata/Dockerfile.evil-notary-server new file mode 100644 index 0000000000..0b8ff85fda --- /dev/null +++ b/e2e/testdata/Dockerfile.evil-notary-server @@ -0,0 +1,4 @@ +ARG NOTARY_VERSION=0.5.0 +FROM notary:server-${NOTARY_VERSION} + +COPY ./notary-evil/ /fixtures/ diff --git a/e2e/testdata/notary-evil/notary-config.json b/e2e/testdata/notary-evil/notary-config.json new file mode 100644 index 0000000000..f3345c080a --- /dev/null +++ b/e2e/testdata/notary-evil/notary-config.json @@ -0,0 +1,19 @@ +{ + "server": { + "http_addr": "evil-notary-server:4444", + "tls_key_file": "./notary-server.key", + "tls_cert_file": "./notary-server.cert" + }, + "trust_service": { + "type": "local", + "hostname": "", + "port": "", + "key_algorithm": "ed25519" + }, + "logging": { + "level": "debug" + }, + "storage": { + "backend": "memory" + } +} diff --git a/e2e/testdata/notary-evil/notary-server.cert b/e2e/testdata/notary-evil/notary-server.cert new file mode 100644 index 0000000000..7ec83c822e --- /dev/null +++ b/e2e/testdata/notary-evil/notary-server.cert @@ -0,0 +1,64 @@ +-----BEGIN CERTIFICATE----- +MIIFKjCCAxKgAwIBAgIJAMyOpNbHzq7KMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0G +A1UECgwGRG9ja2VyMScwJQYDVQQDDB5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp +bmcgQ0EwHhcNMTgwMzA3MDk0MjAxWhcNMjAwMzI2MDk0MjAxWjBbMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzANBgNV +BAoMBkRvY2tlcjEWMBQGA1UEAwwNbm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKjbeflOtVrOv0IOeJGKfi5LHH3Di0O2nlZu8AIT +SJbDZPSXoYc+cprpoEWYncbFFC3C94z5xBW5vcAqMhLs50ml5ADl86umcLl2C/mX +8NuZnlIevMCb0mBiavDtSPV3J5DqOk+trgKEXs9g4hyh5Onh5Y5InPO1lDJ+2cEt +VGBMhhddfWRVlV9ZUWxPYVCTt6L0bD9SeyXJVB0dnFhr3xICayhDlhlvcjXVOTUs +ewJLo/L2nq0ve93Jb2smKio27ZGE79bCGqJK213/FNqfAlGUPkhYTfYJTcgjhS1p +lmtgN6KZF6RVXvOrCBMEDM2yZq1mEPWjoT0tn0MkWErDANcCAwEAAaOB3zCB3DAf +BgNVHSMEGDAWgBSIZiRbIhk/26DjfXrjiqS2UiRgEjAMBgNVHRMBAf8EAjAAMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAwXQYD +VR0RBFYwVIINbm90YXJ5LXNlcnZlcoIMbm90YXJ5c2VydmVyghJldmlsLW5vdGFy +eS1zZXJ2ZXKCEGV2aWxub3RhcnlzZXJ2ZXKCCWxvY2FsaG9zdIcEfwAAATAdBgNV +HQ4EFgQUFBwKiXKF7LSjRFMuKIYC1pGFQi4wDQYJKoZIhvcNAQELBQADggIBACE6 +Y+XRchaN7B8+z+4qXxNTTPT5WZYWU4IMddPLWPcSj9U+XFBz19nObrZLAf6Z3Te7 +6BlcVfEdIRMNCspcjX6RZjeC0iJAaDKo+SdqoajKpEwph9R4OP2I4mwcpf/oMG7p +IsNyzeA7427ignwQ+XfwSElJ5BeTUSPgkYujrTZDxRfCA01t0X0tpzv/3o4dfoZ0 +QKA+2djJagrjU82kTneWRktn6+G+zQuZdupcwUEPvlH3YdEgH22W0m0mavnJMYI/ +J/J4rmanvknLnjCmChEdpwCORL+G84Hu9hdy0WSbvQzQ9puGyukWJO/71Z0fhis2 +DuLIt2esRJoKyrnaCDA+EFJ0JkzozZfS2BcRe3UL9awnwa/iKlUcs/u4bhKu9gwL +F2dXtYPJzyr3PUdPGT4FixTpVZG37BvUSy2IH97qxgK9vn1FGTLDqQlSwCLXvrzr +g2Zz7+JpF2SK3yR1G/IYmAFa37vmbBjW7dZp2JepTMelpblxiTthH1jPN7Lf3uvd +tDe2ZLxTNOVpymDupUqOEXanvcTAkRD3ye3/yhWaXQ44lxVJqG+FNdjQCKcARHWH +H1Otd12QzOsHytUSe7n4zsT06Seyt9huq4g6h0EcuVZaJbi43u5mJtn9yZiZOLF+ +dJsYWaDeSXDnyaFl1tHwcF1tqvguI41E63QqrM0N +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +EIL7P2RDzU63 +-----END CERTIFICATE----- diff --git a/e2e/testdata/notary-evil/notary-server.key b/e2e/testdata/notary-evil/notary-server.key new file mode 100644 index 0000000000..871d41f643 --- /dev/null +++ b/e2e/testdata/notary-evil/notary-server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCo23n5TrVazr9C +DniRin4uSxx9w4tDtp5WbvACE0iWw2T0l6GHPnKa6aBFmJ3GxRQtwveM+cQVub3A +KjIS7OdJpeQA5fOrpnC5dgv5l/DbmZ5SHrzAm9JgYmrw7Uj1dyeQ6jpPra4ChF7P +YOIcoeTp4eWOSJzztZQyftnBLVRgTIYXXX1kVZVfWVFsT2FQk7ei9Gw/UnslyVQd +HZxYa98SAmsoQ5YZb3I11Tk1LHsCS6Py9p6tL3vdyW9rJioqNu2RhO/WwhqiSttd +/xTanwJRlD5IWE32CU3II4UtaZZrYDeimRekVV7zqwgTBAzNsmatZhD1o6E9LZ9D +JFhKwwDXAgMBAAECggEAbqa0PV0IlqMYze6xr53zpd5uozM61XqcM8Oq35FHZhRQ +2b9riDax3zXtYu3pplGLMZmrouQhTKNU5tI/0gsQXUCqMrR9gyQkhkQHAN5CZYU7 +LFEcG5OAvsx/i7XSs5gLg3kaERCdEOUxQ/AW+/BTE7iGN0D6KPH6VUSu6VoNCrTK +PmYvgta7hwebnvo65/OAc4inp9C19FUkhcNbaCKduWBgUt348+IzVEw9H8+PrdVZ +dYGfVXAsDFY3zz0ThUbaZ52XS1pCCQ1Df9bQnTgqJNc+u1xQHLYAageKS83uAbtS +nYjBFFuxeRR2FA1n8echCWQV+16Kqq31U1E2yLfWcQKBgQDSoT73pO9h/yN5myqu +XxhAC+Ndas0DTl4pmVPpybpenJerba/0KCfYpcSFHAdkXZ1DYL7U+9uh5NRul09f +WdjayFjn0vv63rwX+PGi1yPHTIv5kLvjYXJtaxzxSzQivYMPmD/7QX4tEsUkpJ8k +90vMSS/C5ieWbpFwWVvEjFbqHQKBgQDNOsTq6USE3R8p4lj9Ror/waUuWVdzZnm3 +uZGJw3WzvzaXmqLSfVHntUnD8TPHgk3WZxDhrF73POMADkl9IN/JPI150/Uo6YJo +qYGoZr0mmnEZxVCkwODz5C9icnyjklcRdIRM6eljhFMQDVEacDkptsntHUyIdQZc +L2eLNUfEgwKBgHxy7UNg3lemag110rgIU8mzvHj7m3oymYw2nc/qcwVnvG17d5Tp +DPICr6R+NRfl//9JcDdjQBfdnm5hVHJgIbLS4UTH8j390GDRo+O0/dzJq4KfM4Rb +lUJ1ITqoVnuYQZG7QUJxJd330yedZLJwswZWz7N2TTmixqf9BC2TRd85AoGAN+Qh +bLhKaMSvkACMq61ifXSHP7AlGNB3pYlsEVCh5WnVvEPow9pNTAUbKbmumE7sU8+N +0WfYFQ0H5SP+74zcZTmQbfVDdvjhAw/mt64DJVg6JQKPi87bdJBYNz9mokVgYOiS +fz/Ux71pwZ1e0QxvBOU66NBp31+/c6uVT1wbR3ECgYAdye1+UPpS9Dn89g6Ks0kv +UaFKykXu7vY2uxiNqhmWzze4iq5wmIHmEwc6+rVMluXQPAME7Iya3mBmto9AHQ/n +/ka+fGoaUgAojCLZW5DZcelIETw+Dk+95vyyAUsWfAvn4nKo4/rkBXcSHlvgElzq +SorPiBWYosFB6jqUTXew2w== +-----END PRIVATE KEY----- diff --git a/e2e/testdata/notary-evil/root-ca.cert b/e2e/testdata/notary-evil/root-ca.cert new file mode 100644 index 0000000000..474c693420 --- /dev/null +++ b/e2e/testdata/notary-evil/root-ca.cert @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFhjCCA26gAwIBAgIJAMruCvHIncnwMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0G +A1UECgwGRG9ja2VyMRowGAYDVQQDDBFOb3RhcnkgVGVzdGluZyBDQTAeFw0xODAz +MDcwOTQyMDFaFw0yODAzMDQwOTQyMDFaMF8xCzAJBgNVBAYTAlVTMQswCQYDVQQI +DAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0GA1UECgwGRG9ja2VyMRow +GAYDVQQDDBFOb3RhcnkgVGVzdGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAL6okGWkuBefYLyybKhArkttwjznr0Wqew47JSpVzUzX6O+5gqwi +knttFU3pAG3K4N00vVncYforxKRIfFnldUag+70ga3wBX7Cb+YcjbsrCueJqaAs/ +Fe32yeg5icGLD5ndKiJXjswUZdW1rjIV9wBomh/4TLn6m4e64Ggrb5G+660yRHgQ +rlHBPFxMTB6nQptDsrZdyVMjcIiKXfacT/hz/ghSqQyYyFUyjz3dY8g1YEbyHK84 +zfxRGuSaSRnn5GnmvDG3Nw56vlrJFWwyFbIBfT4dVuEvXKDtPyDwh00S9eQ8htrq +i00NjnmSf3ouM/RkXr/+ROBYKMp0jWcmgK7nPr3mi33O9z41pZ2gQEpGJHRzGke2 +StpvFOCxonB/aNQqx+GTZkYBl2kQgE7YEQJ5xt73nCZqIOYhU4rbz8XrGdsCYn/1 +7YYWRjYS5JkqKXSotJdsUQLw/9rYRHoJMjKaXe9d81oFpR4onGOqA74CwCeyKK26 +L1/ywSwgcdOZi8dkXxmGHFQiR7Fwd2ntKxRd7Vm2gloYlHj6lFFQdg8fo/DZYXZ1 +xjWAm/CCZQPs1qneVdRcF6YUt53xk65YN/GIV59zqqc7nCXPfiGLauwEW2lnfrQf +WQrL6NtI71qL3vz0eCQp1NhYU4Ddo+gPCeVNzhtjkK5V538d+gTmhaZzAgMBAAGj +RTBDMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgFGMB0GA1UdDgQW +BBQyxRHvZYEh7fu2SrRRryxYOpwEDTANBgkqhkiG9w0BAQsFAAOCAgEAId82/czt +JDGMjdY62c36fU1USWy28vL0w8sZsOmgC1iWEwCD5PqC77aVRoJ4T/zKdrLE+jrv +2fdcePzbNhj0kzfbAQZ69c1Abyo+Z/EaVpzWj2qYFN9UQoN5+64xAFVjXVQSQBS6 +DXl2ggEyIc7IfnkCE7x0t5ClDtZUKpBuDIMzu5cLmf2/uhHiJsbtToRfqDRO9l6h +3XZ3dSaEVeV6CozNWywaNXl6F8Ep8xrh8V/LL6sT/EGtxhuFx5qmSenZQTZJcIbt +Qf0DsB1aTe2v10i9c3Ulc8H23ALYb93HqEXq+SeOkVHn+7MWMrfuYKd/OugfTqOz +ByGkraIP5GvZbVANnrg8hW+5+4eiRgIiDXhQgFQKNmVKDOSYtHZpe6yMiMfAtlIV +WDSfA899X/JkjdK/RK6W5eFIzV9jSbfUuaYmdwCHkR1v5bLAVLnMHT34sTnQi/3O +Op1FuuZIzeH4LHfSm34XQa25w+p5JZkhYHr8diJfIaU5rcXieFMUkRGkazpHdbul +EvDKlB/VbNTeAxFM/cF6ico7vtNcL04eZexQxDCm5MK008/abBj6e0NmFFs408uX +ii5imQtK/8pumA2+84HhWkAiNRYxe/vqim1l6IDl1Ss5p8r2Y+3/8c0QTJrkbq6n +Kq+PFV31ZYMnY6ZeGY8LdIJ/L7/2xndikJE= +-----END CERTIFICATE-----