github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/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 <= 20; 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", []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  }