Merge pull request #14546 from dmcgowan/trusted-notary-integration
Notary integration Upstream-commit: 4f5b677fd9808b34382061c458e13d3930516889 Component: engine
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -5328,3 +5328,48 @@ func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
|
||||
c.Fatalf("RUN doesn't have the correct output:\nGot:%s\nExpected:%s", out, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-build")
|
||||
dockerFile := fmt.Sprintf(`
|
||||
FROM %s
|
||||
RUN []
|
||||
`, repoName)
|
||||
|
||||
name := "testtrustedbuild"
|
||||
|
||||
buildCmd := buildImageCmd(name, dockerFile, true)
|
||||
s.trustedCmd(buildCmd)
|
||||
out, _, err := runCommandWithOutput(buildCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted build: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(out, fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7])) {
|
||||
c.Fatalf("Unexpected output on trusted build:\n%s", out)
|
||||
}
|
||||
|
||||
// Build command does not create untrusted tag
|
||||
//dockerCmd(c, "rmi", repoName)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/build-untrusted-tag:latest", privateRegistryURL)
|
||||
dockerFile := fmt.Sprintf(`
|
||||
FROM %s
|
||||
RUN []
|
||||
`, repoName)
|
||||
|
||||
name := "testtrustedbuilduntrustedtag"
|
||||
|
||||
buildCmd := buildImageCmd(name, dockerFile, true)
|
||||
s.trustedCmd(buildCmd)
|
||||
out, _, err := runCommandWithOutput(buildCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Expected error on trusted build with untrusted tag: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(out, fmt.Sprintf("no trust data available")) {
|
||||
c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
repoName = fmt.Sprintf("%v/dockercli/busybox-by-dgst", privateRegistryURL)
|
||||
digestRegex = regexp.MustCompile("Digest: ([^\n]+)")
|
||||
repoName = fmt.Sprintf("%v/dockercli/busybox-by-dgst", privateRegistryURL)
|
||||
pushDigestRegex = regexp.MustCompile("[\\S]+: digest: ([\\S]+) size: [0-9]+")
|
||||
digestRegex = regexp.MustCompile("Digest: ([\\S]+)")
|
||||
)
|
||||
|
||||
func setupImage(c *check.C) (string, error) {
|
||||
@@ -45,8 +46,7 @@ func setupImageWithTag(c *check.C, tag string) (string, error) {
|
||||
return "", fmt.Errorf("error deleting images prior to real test: %s, %v", rmiout, err)
|
||||
}
|
||||
|
||||
// the push output includes "Digest: <digest>", so find that
|
||||
matches := digestRegex.FindStringSubmatch(out)
|
||||
matches := pushDigestRegex.FindStringSubmatch(out)
|
||||
if len(matches) != 2 {
|
||||
return "", fmt.Errorf("unable to parse digest from push output: %s", out)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"os/exec"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/docker/docker/pkg/nat"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
@@ -271,3 +275,177 @@ func (s *DockerSuite) TestCreateModeIpcContainer(c *check.C) {
|
||||
|
||||
dockerCmd(c, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox")
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedCreate(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-create")
|
||||
|
||||
// Try create
|
||||
createCmd := exec.Command(dockerBinary, "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted create: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Tagging") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try untrusted create to ensure we pushed the tag to the registry
|
||||
createCmd = exec.Command(dockerBinary, "create", "--disable-content-trust=true", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err = runCommandWithOutput(createCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted create: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on trusted create with --disable-content-trust:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestUntrustedCreate(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)
|
||||
dockerCmd(c, "push", repoName)
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try trusted create on untrusted tag
|
||||
createCmd := exec.Command(dockerBinary, "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error expected when running trusted create with:\n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "no trust data available") {
|
||||
c.Fatalf("Missing expected output on trusted create:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedIsolatedCreate(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-isolated-create")
|
||||
|
||||
// Try create
|
||||
createCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated-create", "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted create: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Tagging") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-create-expired")
|
||||
|
||||
// Certificates have 10 years of expiration
|
||||
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11)
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try create
|
||||
createCmd := exec.Command(dockerBinary, "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error running trusted create in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "could not validate the path to a trusted root") {
|
||||
c.Fatalf("Missing expected output on trusted create in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try create
|
||||
createCmd := exec.Command(dockerBinary, "create", "--disable-content-trust", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err := runCommandWithOutput(createCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running untrusted create in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on untrusted create in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedCreateFromBadTrustServer(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL)
|
||||
evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to create local temp dir")
|
||||
}
|
||||
|
||||
// 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 creating 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 create
|
||||
createCmd := exec.Command(dockerBinary, "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err = runCommandWithOutput(createCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error creating trusted create: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Tagging") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Kill the notary server, start a new "evil" one.
|
||||
s.not.Close()
|
||||
s.not, err = newTestNotary(c)
|
||||
if err != nil {
|
||||
c.Fatalf("Restarting notary server failed.")
|
||||
}
|
||||
|
||||
// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
|
||||
// tag an image and upload it to the private registry
|
||||
dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
|
||||
|
||||
// Push up to the new server
|
||||
pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err = runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error creating 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)
|
||||
}
|
||||
|
||||
// Now, try creating with the original client from this new trust server. This should fail.
|
||||
createCmd = exec.Command(dockerBinary, "create", repoName)
|
||||
s.trustedCmd(createCmd)
|
||||
out, _, err = runCommandWithOutput(createCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Expected to fail on this create due to different remote data: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "failed to validate data with current trusted certificates") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
|
||||
// Check each line for lots of stuff
|
||||
lines := strings.Split(out, "\n")
|
||||
for _, line := range lines {
|
||||
if len(line) > 80 {
|
||||
if len(line) > 90 {
|
||||
c.Fatalf("Help for %q is too long(%d chars):\n%s", cmd,
|
||||
len(line), line)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
@@ -151,3 +155,215 @@ 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 := s.setupTrustedImage(c, "trusted-pull")
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try untrusted pull to ensure we pushed the tag to the registry
|
||||
pullCmd = exec.Command(dockerBinary, "pull", "--disable-content-trust=true", 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), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-isolatd-pull")
|
||||
|
||||
// Try pull (run from isolated directory without trust information)
|
||||
pullCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated", "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)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestUntrustedPull(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)
|
||||
dockerCmd(c, "push", repoName)
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try trusted pull on untrusted tag
|
||||
pullCmd := exec.Command(dockerBinary, "pull", repoName)
|
||||
s.trustedCmd(pullCmd)
|
||||
out, _, err := runCommandWithOutput(pullCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error expected when running trusted pull with:\n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "no trust data available") {
|
||||
c.Fatalf("Missing expected output on trusted pull:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-cert-expired")
|
||||
|
||||
// Certificates have 10 years of expiration
|
||||
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11)
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try pull
|
||||
pullCmd := exec.Command(dockerBinary, "pull", repoName)
|
||||
s.trustedCmd(pullCmd)
|
||||
out, _, err := runCommandWithOutput(pullCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error running trusted pull in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "could not validate the path to a trusted root") {
|
||||
c.Fatalf("Missing expected output on trusted pull in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try pull
|
||||
pullCmd := exec.Command(dockerBinary, "pull", "--disable-content-trust", repoName)
|
||||
s.trustedCmd(pullCmd)
|
||||
out, _, err := runCommandWithOutput(pullCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running untrusted pull in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on untrusted pull in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL)
|
||||
evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to create local temp dir")
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Kill the notary server, start a new "evil" one.
|
||||
s.not.Close()
|
||||
s.not, err = newTestNotary(c)
|
||||
if err != nil {
|
||||
c.Fatalf("Restarting notary server failed.")
|
||||
}
|
||||
|
||||
// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
|
||||
// tag an image and upload it to the private registry
|
||||
dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
|
||||
|
||||
// Push up to the new server
|
||||
pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "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)
|
||||
}
|
||||
|
||||
// Now, try pulling with the original client from this new trust server. This should fail.
|
||||
pullCmd = exec.Command(dockerBinary, "pull", repoName)
|
||||
s.trustedCmd(pullCmd)
|
||||
out, _, err = runCommandWithOutput(pullCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Expected to fail on this pull due to different remote data: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "failed to validate data with current trusted certificates") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppull/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Push with default passphrases
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %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)
|
||||
|
||||
// Snapshots last for three years. This should be expired
|
||||
fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
|
||||
|
||||
// Should succeed because the server transparently re-signs one
|
||||
runAtDifferentDate(fourYearsLater, func() {
|
||||
// Try pull
|
||||
pullCmd := exec.Command(dockerBinary, "pull", repoName)
|
||||
s.trustedCmd(pullCmd)
|
||||
out, _, err = runCommandWithOutput(pullCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Missing expected error running trusted pull with expired snapshots")
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "repository out-of-date") {
|
||||
c.Fatalf("Missing expected output on trusted pull with expired snapshot:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -143,3 +143,214 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(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.trustedCmdWithServer(pushCmd, "example/")
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Missing error while running trusted push w/ no server")
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Error establishing connection to notary repository") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(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", "--disable-content-trust", repoName)
|
||||
s.trustedCmdWithServer(pushCmd, "example/")
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if strings.Contains(string(out), "Error establishing connection to notary repository") {
|
||||
c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(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)
|
||||
dockerCmd(c, "push", repoName)
|
||||
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Do a trusted push
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
||||
}
|
||||
|
||||
// Do another trusted push
|
||||
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err = runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
||||
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try pull to ensure the double push did not break our ability to 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), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Push with default passphrases
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %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)
|
||||
}
|
||||
|
||||
// Push with wrong passphrases
|
||||
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321", "87654321")
|
||||
out, _, err = runCommandWithOutput(pushCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "password invalid, operation has failed") {
|
||||
c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Push with default passphrases
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %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)
|
||||
}
|
||||
|
||||
// Snapshots last for three years. This should be expired
|
||||
fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
|
||||
|
||||
runAtDifferentDate(fourYearsLater, func() {
|
||||
// Push with wrong passphrases
|
||||
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err = runCommandWithOutput(pushCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "repository out-of-date") {
|
||||
c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
|
||||
// tag the image and upload it to the private registry
|
||||
dockerCmd(c, "tag", "busybox", repoName)
|
||||
|
||||
// Push with default passphrases
|
||||
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
||||
s.trustedCmd(pushCmd)
|
||||
out, _, err := runCommandWithOutput(pushCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("trusted push failed: %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)
|
||||
}
|
||||
|
||||
// The timestamps expire in two weeks. Lets check three
|
||||
threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
|
||||
|
||||
// Should succeed because the server transparently re-signs one
|
||||
runAtDifferentDate(threeWeeksLater, func() {
|
||||
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 with expired timestamp:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2549,3 +2549,159 @@ func (s *DockerSuite) TestRunNetworkFilesBindMount(c *check.C) {
|
||||
c.Fatalf("expected resolv.conf be: %q, but was: %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedRun(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-run")
|
||||
|
||||
// Try run
|
||||
runCmd := exec.Command(dockerBinary, "run", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted run: %s\n%s\n", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Tagging") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try untrusted run to ensure we pushed the tag to the registry
|
||||
runCmd = exec.Command(dockerBinary, "run", "--disable-content-trust=true", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted run: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on trusted run with --disable-content-trust:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestUntrustedRun(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)
|
||||
dockerCmd(c, "push", repoName)
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Try trusted run on untrusted tag
|
||||
runCmd := exec.Command(dockerBinary, "run", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error expected when running trusted run with:\n%s", out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "no trust data available") {
|
||||
c.Fatalf("Missing expected output on trusted run:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestRunWhenCertExpired(c *check.C) {
|
||||
repoName := s.setupTrustedImage(c, "trusted-run-expired")
|
||||
|
||||
// Certificates have 10 years of expiration
|
||||
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11)
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try run
|
||||
runCmd := exec.Command(dockerBinary, "run", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Error running trusted run in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "could not validate the path to a trusted root") {
|
||||
c.Fatalf("Missing expected output on trusted run in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
|
||||
runAtDifferentDate(elevenYearsFromNow, func() {
|
||||
// Try run
|
||||
runCmd := exec.Command(dockerBinary, "run", "--disable-content-trust", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running untrusted run in the distant future: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Status: Downloaded") {
|
||||
c.Fatalf("Missing expected output on untrusted run in the distant future:\n%s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) TestTrustedRunFromBadTrustServer(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockerclievilrun/trusted:latest", privateRegistryURL)
|
||||
evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to create local temp dir")
|
||||
}
|
||||
|
||||
// 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 run
|
||||
runCmd := exec.Command(dockerBinary, "run", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
c.Fatalf("Error running trusted run: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "Tagging") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
|
||||
dockerCmd(c, "rmi", repoName)
|
||||
|
||||
// Kill the notary server, start a new "evil" one.
|
||||
s.not.Close()
|
||||
s.not, err = newTestNotary(c)
|
||||
if err != nil {
|
||||
c.Fatalf("Restarting notary server failed.")
|
||||
}
|
||||
|
||||
// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
|
||||
// tag an image and upload it to the private registry
|
||||
dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
|
||||
|
||||
// Push up to the new server
|
||||
pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "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)
|
||||
}
|
||||
|
||||
// Now, try running with the original client from this new trust server. This should fail.
|
||||
runCmd = exec.Command(dockerBinary, "run", repoName)
|
||||
s.trustedCmd(runCmd)
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
if err == nil {
|
||||
c.Fatalf("Expected to fail on this run due to different remote data: %s\n%s", err, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(out), "failed to validate data with current trusted certificates") {
|
||||
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,14 +969,20 @@ func getContainerState(c *check.C, id string) (int, bool, error) {
|
||||
return exitStatus, running, nil
|
||||
}
|
||||
|
||||
func buildImageWithOut(name, dockerfile string, useCache bool) (string, string, error) {
|
||||
args := []string{"build", "-t", name}
|
||||
func buildImageCmd(name, dockerfile string, useCache bool) *exec.Cmd {
|
||||
args := []string{"-D", "build", "-t", name}
|
||||
if !useCache {
|
||||
args = append(args, "--no-cache")
|
||||
}
|
||||
args = append(args, "-")
|
||||
buildCmd := exec.Command(dockerBinary, args...)
|
||||
buildCmd.Stdin = strings.NewReader(dockerfile)
|
||||
return buildCmd
|
||||
|
||||
}
|
||||
|
||||
func buildImageWithOut(name, dockerfile string, useCache bool) (string, string, error) {
|
||||
buildCmd := buildImageCmd(name, dockerfile, useCache)
|
||||
out, exitCode, err := runCommandWithOutput(buildCmd)
|
||||
if err != nil || exitCode != 0 {
|
||||
return "", out, fmt.Errorf("failed to build the image: %s", out)
|
||||
@@ -989,13 +995,7 @@ func buildImageWithOut(name, dockerfile string, useCache bool) (string, string,
|
||||
}
|
||||
|
||||
func buildImageWithStdoutStderr(name, dockerfile string, useCache bool) (string, string, string, error) {
|
||||
args := []string{"build", "-t", name}
|
||||
if !useCache {
|
||||
args = append(args, "--no-cache")
|
||||
}
|
||||
args = append(args, "-")
|
||||
buildCmd := exec.Command(dockerBinary, args...)
|
||||
buildCmd.Stdin = strings.NewReader(dockerfile)
|
||||
buildCmd := buildImageCmd(name, dockerfile, useCache)
|
||||
stdout, stderr, exitCode, err := runCommandWithStdoutStderr(buildCmd)
|
||||
if err != nil || exitCode != 0 {
|
||||
return "", stdout, stderr, fmt.Errorf("failed to build the image: %s", stdout)
|
||||
@@ -1260,6 +1260,16 @@ 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)
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -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-----
|
||||
@@ -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 == "" {
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"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
|
||||
}
|
||||
|
||||
testNotary := &testNotary{
|
||||
cmd: cmd,
|
||||
dir: tmp,
|
||||
}
|
||||
|
||||
// Wait for notary to be ready to serve requests.
|
||||
for i := 1; i <= 5; i++ {
|
||||
if err = testNotary.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 testNotary, 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) {
|
||||
pwd := "12345678"
|
||||
trustCmdEnv(cmd, s.not.address(), pwd, pwd, pwd)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) trustedCmdWithServer(cmd *exec.Cmd, server string) {
|
||||
pwd := "12345678"
|
||||
trustCmdEnv(cmd, server, pwd, pwd, pwd)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) trustedCmdWithPassphrases(cmd *exec.Cmd, rootPwd, snapshotPwd, targetPwd string) {
|
||||
trustCmdEnv(cmd, s.not.address(), rootPwd, snapshotPwd, targetPwd)
|
||||
}
|
||||
|
||||
func trustCmdEnv(cmd *exec.Cmd, server, rootPwd, snapshotPwd, targetPwd string) {
|
||||
env := []string{
|
||||
"DOCKER_CONTENT_TRUST=1",
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server),
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=%s", rootPwd),
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_SNAPSHOT_PASSPHRASE=%s", snapshotPwd),
|
||||
fmt.Sprintf("DOCKER_CONTENT_TRUST_TARGET_PASSPHRASE=%s", targetPwd),
|
||||
}
|
||||
cmd.Env = append(os.Environ(), env...)
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string {
|
||||
repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, name)
|
||||
// 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)
|
||||
}
|
||||
|
||||
if out, status := dockerCmd(c, "rmi", repoName); status != 0 {
|
||||
c.Fatalf("Error removing image %q\n%s", repoName, out)
|
||||
}
|
||||
|
||||
return repoName
|
||||
}
|
||||
@@ -334,3 +334,17 @@ func (c *channelBuffer) ReadTimeout(p []byte, n time.Duration) (int, error) {
|
||||
return -1, fmt.Errorf("timeout reading from channel")
|
||||
}
|
||||
}
|
||||
|
||||
func runAtDifferentDate(date time.Time, block func()) {
|
||||
// Layout for date. MMDDhhmmYYYY
|
||||
const timeLayout = "010203042006"
|
||||
// Ensure we bring time back to now
|
||||
now := time.Now().Format(timeLayout)
|
||||
dateReset := exec.Command("date", now)
|
||||
defer runCommand(dateReset)
|
||||
|
||||
dateChange := exec.Command("date", date.Format(timeLayout))
|
||||
runCommand(dateChange)
|
||||
block()
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user