Signed-off-by: Diogo Monica <diogo@docker.com>
| ... | ... |
@@ -15,7 +15,6 @@ import ( |
| 15 | 15 |
"regexp" |
| 16 | 16 |
"sort" |
| 17 | 17 |
"strconv" |
| 18 |
- "strings" |
|
| 19 | 18 |
"time" |
| 20 | 19 |
|
| 21 | 20 |
"github.com/Sirupsen/logrus" |
| ... | ... |
@@ -79,17 +78,19 @@ func (cli *DockerCli) certificateDirectory(server string) (string, error) {
|
| 79 | 79 |
return filepath.Join(cliconfig.ConfigDir(), "tls", u.Host), nil |
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 |
-func trustServer(index *registry.IndexInfo) string {
|
|
| 82 |
+func trustServer(index *registry.IndexInfo) (string, error) {
|
|
| 83 | 83 |
if s := os.Getenv("DOCKER_CONTENT_TRUST_SERVER"); s != "" {
|
| 84 |
- if !strings.HasPrefix(s, "https://") {
|
|
| 85 |
- return "https://" + s |
|
| 84 |
+ urlObj, err := url.Parse(s) |
|
| 85 |
+ if err != nil || urlObj.Scheme != "https" {
|
|
| 86 |
+ return "", fmt.Errorf("valid https URL required for trust server, got %s", s)
|
|
| 86 | 87 |
} |
| 87 |
- return s |
|
| 88 |
+ |
|
| 89 |
+ return s, nil |
|
| 88 | 90 |
} |
| 89 | 91 |
if index.Official {
|
| 90 |
- return registry.NotaryServer |
|
| 92 |
+ return registry.NotaryServer, nil |
|
| 91 | 93 |
} |
| 92 |
- return "https://" + index.Name |
|
| 94 |
+ return "https://" + index.Name, nil |
|
| 93 | 95 |
} |
| 94 | 96 |
|
| 95 | 97 |
type simpleCredentialStore struct {
|
| ... | ... |
@@ -101,9 +102,9 @@ func (scs simpleCredentialStore) Basic(u *url.URL) (string, string) {
|
| 101 | 101 |
} |
| 102 | 102 |
|
| 103 | 103 |
func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, authConfig cliconfig.AuthConfig) (*client.NotaryRepository, error) {
|
| 104 |
- server := trustServer(repoInfo.Index) |
|
| 105 |
- if !strings.HasPrefix(server, "https://") {
|
|
| 106 |
- return nil, errors.New("unsupported scheme: https required for trust server")
|
|
| 104 |
+ server, err := trustServer(repoInfo.Index) |
|
| 105 |
+ if err != nil {
|
|
| 106 |
+ return nil, err |
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
var cfg = tlsconfig.ClientDefault |
| 110 | 110 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,55 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "testing" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/registry" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func unsetENV() {
|
|
| 10 |
+ os.Unsetenv("DOCKER_CONTENT_TRUST")
|
|
| 11 |
+ os.Unsetenv("DOCKER_CONTENT_TRUST_SERVER")
|
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+func TestENVTrustServer(t *testing.T) {
|
|
| 15 |
+ defer unsetENV() |
|
| 16 |
+ indexInfo := ®istry.IndexInfo{Name: "testserver"}
|
|
| 17 |
+ if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "https://notary-test.com:5000"); err != nil {
|
|
| 18 |
+ t.Fatal("Failed to set ENV variable")
|
|
| 19 |
+ } |
|
| 20 |
+ output, err := trustServer(indexInfo) |
|
| 21 |
+ expectedStr := "https://notary-test.com:5000" |
|
| 22 |
+ if err != nil || output != expectedStr {
|
|
| 23 |
+ t.Fatalf("Expected server to be %s, got %s", expectedStr, output)
|
|
| 24 |
+ } |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+func TestHTTPENVTrustServer(t *testing.T) {
|
|
| 28 |
+ defer unsetENV() |
|
| 29 |
+ indexInfo := ®istry.IndexInfo{Name: "testserver"}
|
|
| 30 |
+ if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "http://notary-test.com:5000"); err != nil {
|
|
| 31 |
+ t.Fatal("Failed to set ENV variable")
|
|
| 32 |
+ } |
|
| 33 |
+ _, err := trustServer(indexInfo) |
|
| 34 |
+ if err == nil {
|
|
| 35 |
+ t.Fatal("Expected error with invalid scheme")
|
|
| 36 |
+ } |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func TestOfficialTrustServer(t *testing.T) {
|
|
| 40 |
+ indexInfo := ®istry.IndexInfo{Name: "testserver", Official: true}
|
|
| 41 |
+ output, err := trustServer(indexInfo) |
|
| 42 |
+ if err != nil || output != registry.NotaryServer {
|
|
| 43 |
+ t.Fatalf("Expected server to be %s, got %s", registry.NotaryServer, output)
|
|
| 44 |
+ } |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func TestNonOfficialTrustServer(t *testing.T) {
|
|
| 48 |
+ indexInfo := ®istry.IndexInfo{Name: "testserver", Official: false}
|
|
| 49 |
+ output, err := trustServer(indexInfo) |
|
| 50 |
+ expectedStr := "https://" + indexInfo.Name |
|
| 51 |
+ if err != nil || output != expectedStr {
|
|
| 52 |
+ t.Fatalf("Expected server to be %s, got %s", expectedStr, output)
|
|
| 53 |
+ } |
|
| 54 |
+} |
| ... | ... |
@@ -148,7 +148,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) {
|
| 148 | 148 |
dockerCmd(c, "tag", "busybox", repoName) |
| 149 | 149 |
|
| 150 | 150 |
pushCmd := exec.Command(dockerBinary, "push", repoName) |
| 151 |
- s.trustedCmdWithServer(pushCmd, "example/") |
|
| 151 |
+ s.trustedCmdWithServer(pushCmd, "https://example.com:81/") |
|
| 152 | 152 |
out, _, err := runCommandWithOutput(pushCmd) |
| 153 | 153 |
if err == nil {
|
| 154 | 154 |
c.Fatalf("Missing error while running trusted push w/ no server")
|
| ... | ... |
@@ -165,7 +165,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) |
| 165 | 165 |
dockerCmd(c, "tag", "busybox", repoName) |
| 166 | 166 |
|
| 167 | 167 |
pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName) |
| 168 |
- s.trustedCmdWithServer(pushCmd, "example/") |
|
| 168 |
+ s.trustedCmdWithServer(pushCmd, "https://example.com/") |
|
| 169 | 169 |
out, _, err := runCommandWithOutput(pushCmd) |
| 170 | 170 |
if err != nil {
|
| 171 | 171 |
c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out)
|
| ... | ... |
@@ -22,6 +22,9 @@ type testNotary struct {
|
| 22 | 22 |
dir string |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 |
+const notaryHost = "localhost:4443" |
|
| 26 |
+const notaryURL = "https://" + notaryHost |
|
| 27 |
+ |
|
| 25 | 28 |
func newTestNotary(c *check.C) (*testNotary, error) {
|
| 26 | 29 |
template := `{
|
| 27 | 30 |
"server": {
|
| ... | ... |
@@ -48,7 +51,7 @@ func newTestNotary(c *check.C) (*testNotary, error) {
|
| 48 | 48 |
if err != nil {
|
| 49 | 49 |
return nil, err |
| 50 | 50 |
} |
| 51 |
- if _, err := fmt.Fprintf(config, template, "localhost:4443"); err != nil {
|
|
| 51 |
+ if _, err := fmt.Fprintf(config, template, notaryHost); err != nil {
|
|
| 52 | 52 |
os.RemoveAll(tmp) |
| 53 | 53 |
return nil, err |
| 54 | 54 |
} |
| ... | ... |
@@ -82,10 +85,6 @@ func newTestNotary(c *check.C) (*testNotary, error) {
|
| 82 | 82 |
return testNotary, nil |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
-func (t *testNotary) address() string {
|
|
| 86 |
- return "localhost:4443" |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 | 85 |
func (t *testNotary) Ping() error {
|
| 90 | 86 |
tlsConfig := tlsconfig.ClientDefault |
| 91 | 87 |
tlsConfig.InsecureSkipVerify = true |
| ... | ... |
@@ -100,7 +99,7 @@ func (t *testNotary) Ping() error {
|
| 100 | 100 |
TLSClientConfig: &tlsConfig, |
| 101 | 101 |
}, |
| 102 | 102 |
} |
| 103 |
- resp, err := client.Get(fmt.Sprintf("https://%s/v2/", t.address()))
|
|
| 103 |
+ resp, err := client.Get(fmt.Sprintf("%s/v2/", notaryURL))
|
|
| 104 | 104 |
if err != nil {
|
| 105 | 105 |
return err |
| 106 | 106 |
} |
| ... | ... |
@@ -117,7 +116,7 @@ func (t *testNotary) Close() {
|
| 117 | 117 |
|
| 118 | 118 |
func (s *DockerTrustSuite) trustedCmd(cmd *exec.Cmd) {
|
| 119 | 119 |
pwd := "12345678" |
| 120 |
- trustCmdEnv(cmd, s.not.address(), pwd, pwd) |
|
| 120 |
+ trustCmdEnv(cmd, notaryURL, pwd, pwd) |
|
| 121 | 121 |
} |
| 122 | 122 |
|
| 123 | 123 |
func (s *DockerTrustSuite) trustedCmdWithServer(cmd *exec.Cmd, server string) {
|
| ... | ... |
@@ -126,7 +125,7 @@ func (s *DockerTrustSuite) trustedCmdWithServer(cmd *exec.Cmd, server string) {
|
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
func (s *DockerTrustSuite) trustedCmdWithPassphrases(cmd *exec.Cmd, offlinePwd, taggingPwd string) {
|
| 129 |
- trustCmdEnv(cmd, s.not.address(), offlinePwd, taggingPwd) |
|
| 129 |
+ trustCmdEnv(cmd, notaryURL, offlinePwd, taggingPwd) |
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
func trustCmdEnv(cmd *exec.Cmd, server, offlinePwd, taggingPwd string) {
|