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)
This commit is contained in:
parent
ed13c3abfb
commit
58a1de9b59
9 changed files with 267 additions and 0 deletions
10
Dockerfile
10
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 \
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
integration-cli/fixtures/notary/localhost.cert
Normal file
19
integration-cli/fixtures/notary/localhost.cert
Normal file
|
@ -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
integration-cli/fixtures/notary/localhost.key
Normal file
27
integration-cli/fixtures/notary/localhost.key
Normal file
|
@ -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-----
|
|
@ -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
integration-cli/trust_server.go
Normal file
110
integration-cli/trust_server.go
Normal file
|
@ -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...)
|
||||
}
|
Loading…
Reference in a new issue