github.com/ruphin/docker@v1.10.1/integration-cli/trust_server.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "net/http" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 "time" 13 14 "github.com/docker/docker/cliconfig" 15 "github.com/docker/docker/pkg/tlsconfig" 16 "github.com/docker/notary/client" 17 "github.com/docker/notary/passphrase" 18 "github.com/docker/notary/tuf/data" 19 "github.com/go-check/check" 20 ) 21 22 var notaryBinary = "notary-server" 23 var notaryClientBinary = "notary" 24 25 type testNotary struct { 26 cmd *exec.Cmd 27 dir string 28 } 29 30 const notaryHost = "localhost:4443" 31 const notaryURL = "https://" + notaryHost 32 33 func newTestNotary(c *check.C) (*testNotary, error) { 34 // generate server config 35 template := `{ 36 "server": { 37 "http_addr": "%s", 38 "tls_key_file": "%s", 39 "tls_cert_file": "%s" 40 }, 41 "trust_service": { 42 "type": "local", 43 "hostname": "", 44 "port": "", 45 "key_algorithm": "ed25519" 46 }, 47 "logging": { 48 "level": "debug" 49 }, 50 "storage": { 51 "backend": "memory" 52 } 53 }` 54 tmp, err := ioutil.TempDir("", "notary-test-") 55 if err != nil { 56 return nil, err 57 } 58 confPath := filepath.Join(tmp, "config.json") 59 config, err := os.Create(confPath) 60 defer config.Close() 61 if err != nil { 62 return nil, err 63 } 64 65 workingDir, err := os.Getwd() 66 if err != nil { 67 return nil, err 68 } 69 if _, err := fmt.Fprintf(config, template, notaryHost, filepath.Join(workingDir, "fixtures/notary/localhost.key"), filepath.Join(workingDir, "fixtures/notary/localhost.cert")); err != nil { 70 os.RemoveAll(tmp) 71 return nil, err 72 } 73 74 // generate client config 75 clientConfPath := filepath.Join(tmp, "client-config.json") 76 clientConfig, err := os.Create(clientConfPath) 77 defer clientConfig.Close() 78 if err != nil { 79 return nil, err 80 } 81 template = `{ 82 "trust_dir" : "%s", 83 "remote_server": { 84 "url": "%s", 85 "skipTLSVerify": true 86 } 87 }` 88 if _, err = fmt.Fprintf(clientConfig, template, filepath.Join(cliconfig.ConfigDir(), "trust"), notaryURL); err != nil { 89 os.RemoveAll(tmp) 90 return nil, err 91 } 92 93 // run notary-server 94 cmd := exec.Command(notaryBinary, "-config", confPath) 95 if err := cmd.Start(); err != nil { 96 os.RemoveAll(tmp) 97 if os.IsNotExist(err) { 98 c.Skip(err.Error()) 99 } 100 return nil, err 101 } 102 103 testNotary := &testNotary{ 104 cmd: cmd, 105 dir: tmp, 106 } 107 108 // Wait for notary to be ready to serve requests. 109 for i := 1; i <= 5; i++ { 110 if err = testNotary.Ping(); err == nil { 111 break 112 } 113 time.Sleep(10 * time.Millisecond * time.Duration(i*i)) 114 } 115 116 if err != nil { 117 c.Fatalf("Timeout waiting for test notary to become available: %s", err) 118 } 119 120 return testNotary, nil 121 } 122 123 func (t *testNotary) Ping() error { 124 tlsConfig := tlsconfig.ClientDefault 125 tlsConfig.InsecureSkipVerify = true 126 client := http.Client{ 127 Transport: &http.Transport{ 128 Proxy: http.ProxyFromEnvironment, 129 Dial: (&net.Dialer{ 130 Timeout: 30 * time.Second, 131 KeepAlive: 30 * time.Second, 132 }).Dial, 133 TLSHandshakeTimeout: 10 * time.Second, 134 TLSClientConfig: &tlsConfig, 135 }, 136 } 137 resp, err := client.Get(fmt.Sprintf("%s/v2/", notaryURL)) 138 if err != nil { 139 return err 140 } 141 if resp.StatusCode != 200 { 142 return fmt.Errorf("notary ping replied with an unexpected status code %d", resp.StatusCode) 143 } 144 return nil 145 } 146 147 func (t *testNotary) Close() { 148 t.cmd.Process.Kill() 149 os.RemoveAll(t.dir) 150 } 151 152 func (s *DockerTrustSuite) trustedCmd(cmd *exec.Cmd) { 153 pwd := "12345678" 154 trustCmdEnv(cmd, notaryURL, pwd, pwd) 155 } 156 157 func (s *DockerTrustSuite) trustedCmdWithServer(cmd *exec.Cmd, server string) { 158 pwd := "12345678" 159 trustCmdEnv(cmd, server, pwd, pwd) 160 } 161 162 func (s *DockerTrustSuite) trustedCmdWithPassphrases(cmd *exec.Cmd, rootPwd, repositoryPwd string) { 163 trustCmdEnv(cmd, notaryURL, rootPwd, repositoryPwd) 164 } 165 166 func (s *DockerTrustSuite) trustedCmdWithDeprecatedEnvPassphrases(cmd *exec.Cmd, offlinePwd, taggingPwd string) { 167 trustCmdDeprecatedEnv(cmd, notaryURL, offlinePwd, taggingPwd) 168 } 169 170 func trustCmdEnv(cmd *exec.Cmd, server, rootPwd, repositoryPwd string) { 171 env := []string{ 172 "DOCKER_CONTENT_TRUST=1", 173 fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server), 174 fmt.Sprintf("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=%s", rootPwd), 175 fmt.Sprintf("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=%s", repositoryPwd), 176 } 177 cmd.Env = append(os.Environ(), env...) 178 } 179 180 // Helper method to test the old env variables OFFLINE and TAGGING that will 181 // be deprecated by 1.10 182 func trustCmdDeprecatedEnv(cmd *exec.Cmd, server, offlinePwd, taggingPwd string) { 183 env := []string{ 184 "DOCKER_CONTENT_TRUST=1", 185 fmt.Sprintf("DOCKER_CONTENT_TRUST_SERVER=%s", server), 186 fmt.Sprintf("DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE=%s", offlinePwd), 187 fmt.Sprintf("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE=%s", taggingPwd), 188 } 189 cmd.Env = append(os.Environ(), env...) 190 } 191 192 func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string { 193 repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, name) 194 // tag the image and upload it to the private registry 195 dockerCmd(c, "tag", "busybox", repoName) 196 197 pushCmd := exec.Command(dockerBinary, "push", repoName) 198 s.trustedCmd(pushCmd) 199 out, _, err := runCommandWithOutput(pushCmd) 200 if err != nil { 201 c.Fatalf("Error running trusted push: %s\n%s", err, out) 202 } 203 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 204 c.Fatalf("Missing expected output on trusted push:\n%s", out) 205 } 206 207 if out, status := dockerCmd(c, "rmi", repoName); status != 0 { 208 c.Fatalf("Error removing image %q\n%s", repoName, out) 209 } 210 211 return repoName 212 } 213 214 func notaryClientEnv(cmd *exec.Cmd, rootPwd, repositoryPwd string) { 215 env := []string{ 216 fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", rootPwd), 217 fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", repositoryPwd), 218 fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", repositoryPwd), 219 } 220 cmd.Env = append(os.Environ(), env...) 221 } 222 223 func (s *DockerTrustSuite) setupDelegations(c *check.C, repoName, pwd string) { 224 initCmd := exec.Command(notaryClientBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "init", repoName) 225 notaryClientEnv(initCmd, pwd, pwd) 226 out, _, err := runCommandWithOutput(initCmd) 227 if err != nil { 228 c.Fatalf("Error initializing notary repository: %s\n", out) 229 } 230 231 // no command line for this, so build by hand 232 nRepo, err := client.NewNotaryRepository(filepath.Join(cliconfig.ConfigDir(), "trust"), repoName, notaryURL, nil, passphrase.ConstantRetriever(pwd)) 233 if err != nil { 234 c.Fatalf("Error creating notary repository: %s\n", err) 235 } 236 delgKey, err := nRepo.CryptoService.Create("targets/releases", data.ECDSAKey) 237 if err != nil { 238 c.Fatalf("Error creating delegation key: %s\n", err) 239 } 240 err = nRepo.AddDelegation("targets/releases", 1, []data.PublicKey{delgKey}, []string{""}) 241 if err != nil { 242 c.Fatalf("Error creating delegation: %s\n", err) 243 } 244 245 // publishing first simulates the client pushing to a repo that they have been given delegated access to 246 pubCmd := exec.Command(notaryClientBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "publish", repoName) 247 notaryClientEnv(pubCmd, pwd, pwd) 248 out, _, err = runCommandWithOutput(pubCmd) 249 if err != nil { 250 c.Fatalf("Error publishing notary repository: %s\n", out) 251 } 252 }