فهرست منبع

Add integration cli trust tests

Added notary server to docker base image.
Created trust suite which runs trust server for running trusted commands.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
Derek McGowan 10 سال پیش
والد
کامیت
58a1de9b59

+ 10 - 0
Dockerfile

@@ -136,6 +136,16 @@ RUN set -x \
 		go build -o /usr/local/bin/registry-v2 github.com/docker/distribution/cmd/registry \
 	&& rm -rf "$GOPATH"
 
+# Install notary server
+ENV NOTARY_COMMIT 77bced079e83d80f40c1f0a544b1a8a3b97fb052
+RUN set -x \
+	&& export GOPATH="$(mktemp -d)" \
+	&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
+	&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_COMMIT") \
+	&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
+		go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
+	&& rm -rf "$GOPATH"
+
 # Get the "docker-py" source so we can run their integration tests
 ENV DOCKER_PY_COMMIT 8a87001d09852058f08a807ab6e8491d57ca1e88
 RUN git clone https://github.com/docker/docker-py.git /docker-py \

+ 23 - 0
integration-cli/check_test.go

@@ -61,3 +61,26 @@ func (s *DockerDaemonSuite) TearDownTest(c *check.C) {
 	s.d.Stop()
 	s.ds.TearDownTest(c)
 }
+
+func init() {
+	check.Suite(&DockerTrustSuite{
+		ds: &DockerSuite{},
+	})
+}
+
+type DockerTrustSuite struct {
+	ds  *DockerSuite
+	reg *testRegistryV2
+	not *testNotary
+}
+
+func (s *DockerTrustSuite) SetUpTest(c *check.C) {
+	s.reg = setupRegistry(c)
+	s.not = setupNotary(c)
+}
+
+func (s *DockerTrustSuite) TearDownTest(c *check.C) {
+	s.reg.Close()
+	s.not.Close()
+	s.ds.TearDownTest(c)
+}

+ 31 - 0
integration-cli/docker_cli_pull_test.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"fmt"
+	"os/exec"
 	"strings"
 
 	"github.com/go-check/check"
@@ -151,3 +152,33 @@ func (s *DockerSuite) TestPullImageWithAllTagFromCentralRegistry(c *check.C) {
 		c.Fatalf("Pulling with all tags should get more images")
 	}
 }
+
+func (s *DockerTrustSuite) TestTrustedPull(c *check.C) {
+	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
+	// tag the image and upload it to the private registry
+	dockerCmd(c, "tag", "busybox", repoName)
+
+	pushCmd := exec.Command(dockerBinary, "push", repoName)
+	s.trustedCmd(pushCmd)
+	out, _, err := runCommandWithOutput(pushCmd)
+	if err != nil {
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
+	}
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
+	}
+
+	dockerCmd(c, "rmi", repoName)
+
+	// Try pull
+	pullCmd := exec.Command(dockerBinary, "pull", repoName)
+	s.trustedCmd(pullCmd)
+	out, _, err = runCommandWithOutput(pullCmd)
+	if err != nil {
+		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
+	}
+
+	if !strings.Contains(string(out), "Tagging") {
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
+	}
+}

+ 16 - 0
integration-cli/docker_cli_push_test.go

@@ -143,3 +143,19 @@ func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
 		c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
 	}
 }
+
+func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
+	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
+	// tag the image and upload it to the private registry
+	dockerCmd(c, "tag", "busybox", repoName)
+
+	pushCmd := exec.Command(dockerBinary, "push", repoName)
+	s.trustedCmd(pushCmd)
+	out, _, err := runCommandWithOutput(pushCmd)
+	if err != nil {
+		c.Fatalf("Error running trusted push: %s\n%s", err, out)
+	}
+	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
+		c.Fatalf("Missing expected output on trusted push:\n%s", out)
+	}
+}

+ 21 - 0
integration-cli/docker_utils.go

@@ -1260,6 +1260,27 @@ func setupRegistry(c *check.C) *testRegistryV2 {
 	return reg
 }
 
+func setupNotary(c *check.C) *testNotary {
+	testRequires(c, NotaryHosting)
+	ts, err := newTestNotary(c)
+	if err != nil {
+		c.Fatal(err)
+	}
+
+	// Wait for notary to be ready to serve requests.
+	for i := 1; i <= 5; i++ {
+		if err = ts.Ping(); err == nil {
+			break
+		}
+		time.Sleep(10 * time.Millisecond * time.Duration(i*i))
+	}
+
+	if err != nil {
+		c.Fatalf("Timeout waiting for test notary to become available: %s", err)
+	}
+	return ts
+}
+
 // appendBaseEnv appends the minimum set of environment variables to exec the
 // docker cli binary for testing with correct configuration to the given env
 // list.

+ 19 - 0
integration-cli/fixtures/notary/localhost.cert

@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCTCCAfOgAwIBAgIQTOoFF+ypXwgdXnXHuCTvYDALBgkqhkiG9w0BAQswJjER
+MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE1MDcxNzE5
+NDg1M1oXDTE4MDcwMTE5NDg1M1owJzERMA8GA1UEChMIUXVpY2tUTFMxEjAQBgNV
+BAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDO
+qvTBAi0ApXLfe90ApJkdkRGwF838Qzt1UFSxomu5fHRV6l3FjX5XCVHiFQ4w3ROh
+dMOu9NahfGLJv9VvWU2MV3YoY9Y7lIXpKwnK1v064wuls4nPh13BUWKQKofcY/e2
+qaSPd6/qmSRc/kJUvOI9jZMSX6ZRPu9K4PCqm2CivlbLq9UYuo1AbRGfuqHRvTxg
+mQG7WQCzGSvSjuSg5qX3TEh0HckTczJG9ODULNRWNE7ld0W4sfv4VF8R7Uc/G7LO
+8QwLCZ9TIl3gYMPCrhUL3Q6z9Jnn1SQS4mhDnPi6ugRYO1X8k3jjdxV9C2sXwUvN
+OZI1rLEWl9TJNA7ZXtMCAwEAAaM2MDQwDgYDVR0PAQH/BAQDAgCgMAwGA1UdEwEB
+/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAsGCSqGSIb3DQEBCwOCAQEAH6iq
+kM2+UMukGDLEQKHHiauioWJlHDlLXv76bJiNfjSz94B/2XOQMb9PT04//tnGUyPK
+K8Dx7RoxSodU6T5VRiz/A36mLOvt2t3bcL/1nHf9sAOHcexGtnCbQbW91V7RKfIL
+sjiLNFDkQ9VfVNY+ynQptZoyH1sy07+dplfkIiPzRs5WuVAnEGsX3r6BrhgUITzi
+g1B4kpmGZIohP4m6ZEBY5xuo/NQ0+GhjAENQMU38GpuoMyFS0i0dGcbx8weqnI/B
+Er/qa0+GE/rBnWY8TiRow8dzpneSFQnUZpJ4EwD9IoOIDHo7k2Nbz2P50HMiCXZf
+4RqzctVssRlrRVnO5w==
+-----END CERTIFICATE-----

+ 27 - 0
integration-cli/fixtures/notary/localhost.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAwM6q9MECLQClct973QCkmR2REbAXzfxDO3VQVLGia7l8dFXq
+XcWNflcJUeIVDjDdE6F0w6701qF8Ysm/1W9ZTYxXdihj1juUhekrCcrW/TrjC6Wz
+ic+HXcFRYpAqh9xj97appI93r+qZJFz+QlS84j2NkxJfplE+70rg8KqbYKK+Vsur
+1Ri6jUBtEZ+6odG9PGCZAbtZALMZK9KO5KDmpfdMSHQdyRNzMkb04NQs1FY0TuV3
+Rbix+/hUXxHtRz8bss7xDAsJn1MiXeBgw8KuFQvdDrP0mefVJBLiaEOc+Lq6BFg7
+VfyTeON3FX0LaxfBS805kjWssRaX1Mk0Dtle0wIDAQABAoIBAHbuhNHZROhRn70O
+Ui9vOBki/dt1ThnH5AkHQngb4t6kWjrAzILvW2p1cdBKr0ZDqftz+rzCbVD/5+Rg
+Iq8bsnB9g23lWEBMHD/GJsAxmRA3hNooamk11IBmwTcVSsbnkdq5mEdkICYphjHC
+Ey0DbEf6RBxWlx3WvAWLoNmTw6iFaOCH8IyLavPpe7kLbZc219oNUw2qjCnCXCZE
+/NuViADHJBPN8r7g1gmyclJmTumdUK6oHgXEMMPe43vhReGcgcReK9QZjnTcIXPM
+4oJOraw+BtoZXVvvIPnC+5ntoLFOzjIzM0kaveReZbdgffqF4zy2vRfCHhWssanc
+7a0xR4ECgYEA3Xuvcqy5Xw+v/jVCO0VZj++Z7apA78dY4tWsPx5/0DUTTziTlXkC
+ADduEbwX6HgZ/iLvA9j4C3Z4mO8qByby/6UoBU8NEe+PQt6fT7S+dKSP4uy5ZxVM
+i5opkEyrJsMbve9Jrlj4bk5CICsydrZ+SBFHnpNGjbduGQick5LORWECgYEA3trt
+gepteDGiUYmnnBgjbYtcD11RvpKC8Z/QwGnzN5vk4eBu8r7DkMcLN+SiHjAovlJo
+r5j3EbF8sla1zBf/yySdQZFqUGcwtw7MaAKCLdhQl5WsViNMIx6p2OJapu0dzbv2
+KTXrnoRCafcH92k0dUX1ahE9eyc8KX6VhbWwXLMCgYATGCCuEDoC+gVAMzM8jOQF
+xrBMjwr+IP+GvskUv/pg5tJ9V/FRR5dmkWDJ4p9lCUWkZTqZ6FCqHFKVTLkg2LjG
+VWS34HLOAwskxrCRXJG22KEW/TWWr31j46yFpjZzJwrzOvftMfpo+BI3V8IH/f+x
+EtxLzYKdoRy6x8VH67YgwQKBgHor2vjV45142FuK83AHa6SqOZXSuvWWrGJ6Ep7p
+doSN2jRaLXi2S9AaznOdy6JxFGUCGJHrcccpXgsGrjNtFLXxJKTFa1sYtwQkALsk
+ZOltJQF09D1krGC0driHntrUMvqOiKye+sS0DRS6cIuaCUAhUiELwoC5SaoV0zKy
+IDUxAoGAOK8Xq+3/sqe79vTpw25RXl+nkAmOAeKjqf3Kh6jbnBhr81rmefyKXB9a
+uj0b980tzUnliwA5cCOsyxfN2vASvMnJxFE721QZI04arlcPFHcFqCtmNnUYTcLp
+0hgn/yLZptcoxpy+eTBu3eNsxz1Bu/Tx/198+2Wr3MbtGpLNIcA=
+-----END RSA PRIVATE KEY-----

+ 10 - 0
integration-cli/requirements.go

@@ -74,6 +74,16 @@ var (
 		},
 		fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
 	}
+	NotaryHosting = testRequirement{
+		func() bool {
+			// for now notary binary is built only if we're running inside
+			// container through `make test`. Figure that out by testing if
+			// notary-server binary is in PATH.
+			_, err := exec.LookPath(notaryBinary)
+			return err == nil
+		},
+		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
+	}
 	NativeExecDriver = testRequirement{
 		func() bool {
 			if daemonExecDriver == "" {

+ 110 - 0
integration-cli/trust_server.go

@@ -0,0 +1,110 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"time"
+
+	"github.com/docker/docker/pkg/tlsconfig"
+	"github.com/go-check/check"
+)
+
+var notaryBinary = "notary-server"
+
+type testNotary struct {
+	cmd *exec.Cmd
+	dir string
+}
+
+func newTestNotary(c *check.C) (*testNotary, error) {
+	template := `{
+	"server": {
+		"addr": "%s",
+		"tls_key_file": "fixtures/notary/localhost.key",
+		"tls_cert_file": "fixtures/notary/localhost.cert"
+	},
+	"trust_service": {
+		"type": "local",
+		"hostname": "",
+		"port": ""
+	},
+	"logging": {
+		"level": 5
+	}
+}`
+	tmp, err := ioutil.TempDir("", "notary-test-")
+	if err != nil {
+		return nil, err
+	}
+	confPath := filepath.Join(tmp, "config.json")
+	config, err := os.Create(confPath)
+	if err != nil {
+		return nil, err
+	}
+	if _, err := fmt.Fprintf(config, template, "localhost:4443"); err != nil {
+		os.RemoveAll(tmp)
+		return nil, err
+	}
+
+	cmd := exec.Command(notaryBinary, "-config", confPath)
+	if err := cmd.Start(); err != nil {
+		os.RemoveAll(tmp)
+		if os.IsNotExist(err) {
+			c.Skip(err.Error())
+		}
+		return nil, err
+	}
+	return &testNotary{
+		cmd: cmd,
+		dir: tmp,
+	}, nil
+}
+
+func (t *testNotary) address() string {
+	return "localhost:4443"
+}
+
+func (t *testNotary) Ping() error {
+	tlsConfig := tlsconfig.ClientDefault
+	tlsConfig.InsecureSkipVerify = true
+	client := http.Client{
+		Transport: &http.Transport{
+			Proxy: http.ProxyFromEnvironment,
+			Dial: (&net.Dialer{
+				Timeout:   30 * time.Second,
+				KeepAlive: 30 * time.Second,
+			}).Dial,
+			TLSHandshakeTimeout: 10 * time.Second,
+			TLSClientConfig:     &tlsConfig,
+		},
+	}
+	resp, err := client.Get(fmt.Sprintf("https://%s/v2/", t.address()))
+	if err != nil {
+		return err
+	}
+	if resp.StatusCode != 200 {
+		return fmt.Errorf("notary ping replied with an unexpected status code %d", resp.StatusCode)
+	}
+	return nil
+}
+
+func (t *testNotary) Close() {
+	t.cmd.Process.Kill()
+	os.RemoveAll(t.dir)
+}
+
+func (s *DockerTrustSuite) trustedCmd(cmd *exec.Cmd) {
+	env := []string{
+		"DOCKER_TRUST=1",
+		fmt.Sprintf("DOCKER_TRUST_SERVER=%s", s.not.address()),
+		"DOCKER_TRUST_ROOT_PASSPHRASE=12345678",
+		"DOCKER_TRUST_TARGET_PASSPHRASE=12345678",
+		"DOCKER_TRUST_SNAPSHOT_PASSPHRASE=12345678",
+	}
+	cmd.Env = append(os.Environ(), env...)
+}