func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegation(c *check.C) { repoName := fmt.Sprintf("%v/dockerclireleasedelegation/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) pwd := "12345678" s.setupDelegations(c, repoName, pwd) // tag the image and upload it to the private registry dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "-D", "push", targetName) s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) // Try pull after push pullCmd := exec.Command(dockerBinary, "pull", targetName) s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) // check to make sure that the target has been added to targets/releases and not targets contents, err := ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets.json")) c.Assert(err, check.IsNil, check.Commentf("Unable to read targets metadata")) c.Assert(strings.Contains(string(contents), `"latest"`), checker.False, check.Commentf(string(contents))) contents, err = ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets/releases.json")) c.Assert(err, check.IsNil, check.Commentf("Unable to read targets/releases metadata")) c.Assert(string(contents), checker.Contains, `"latest"`, check.Commentf(string(contents))) }
// GetDefaultDockerConfig checks relevant Docker environment variables to // provide defaults for our command line flags func GetDefaultDockerConfig() *api.DockerConfig { cfg := &api.DockerConfig{} if cfg.Endpoint = os.Getenv("DOCKER_HOST"); cfg.Endpoint == "" { cfg.Endpoint = client.DefaultDockerHost // TODO: remove this when we bump engine-api to >= cf82c64276ebc2501e72b241f9fdc1e21e421743 if runtime.GOOS == "darwin" { cfg.Endpoint = "unix:///var/run/docker.sock" } } certPath := os.Getenv("DOCKER_CERT_PATH") if certPath == "" { certPath = cliconfig.ConfigDir() } cfg.CertFile = filepath.Join(certPath, "cert.pem") cfg.KeyFile = filepath.Join(certPath, "key.pem") cfg.CAFile = filepath.Join(certPath, "ca.pem") if tlsVerify := os.Getenv("DOCKER_TLS_VERIFY"); tlsVerify != "" { cfg.TLSVerify = true } return cfg }
func init() { client := clientFlags.FlagSet client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files") clientFlags.PostParse = func() { clientFlags.Common.PostParse() if clientFlags.ConfigDir != "" { cliconfig.SetConfigDir(clientFlags.ConfigDir) } if clientFlags.Common.TrustKey == "" { clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), defaultTrustKeyFile) } } }
// InitCommonFlags initializes flags common to both client and daemon func InitCommonFlags() *cli.CommonFlags { var commonFlags = &cli.CommonFlags{FlagSet: new(flag.FlagSet)} if dockerCertPath == "" { dockerCertPath = cliconfig.ConfigDir() } commonFlags.PostParse = func() { postParseCommon(commonFlags) } cmd := commonFlags.FlagSet cmd.BoolVar(&commonFlags.Debug, []string{"D", "-debug"}, false, "Enable debug mode") cmd.StringVar(&commonFlags.LogLevel, []string{"l", "-log-level"}, "info", "Set the logging level") cmd.BoolVar(&commonFlags.TLS, []string{"-tls"}, false, "Use TLS; implied by --tlsverify") cmd.BoolVar(&commonFlags.TLSVerify, []string{"-tlsverify"}, dockerTLSVerify, "Use TLS and verify the remote") // TODO use flag flag.String([]string{"i", "-identity"}, "", "Path to libtrust key file") var tlsOptions tlsconfig.Options commonFlags.TLSOptions = &tlsOptions cmd.StringVar(&tlsOptions.CAFile, []string{"-tlscacert"}, filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA") cmd.StringVar(&tlsOptions.CertFile, []string{"-tlscert"}, filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file") cmd.StringVar(&tlsOptions.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file") cmd.Var(opts.NewNamedListOptsRef("hosts", &commonFlags.Hosts, opts.ValidateHost), []string{"H", "-host"}, "Daemon socket(s) to connect to") return commonFlags }
// Initialize the dockerCli runs initialization that must happen after command // line flags are parsed. func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error { cli.configFile = LoadDefaultConfigFile(cli.err) client, err := NewAPIClientFromFlags(opts.Common, cli.configFile) if err != nil { return err } cli.client = client if cli.in != nil { cli.inFd, cli.isTerminalIn = term.GetFdInfo(cli.in) } if cli.out != nil { cli.outFd, cli.isTerminalOut = term.GetFdInfo(cli.out) } if opts.Common.TrustKey == "" { cli.keyFile = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) } else { cli.keyFile = opts.Common.TrustKey } return nil }
func getDaemonConfDir() string { // TODO: update for Windows daemon if runtime.GOOS == "windows" { return cliconfig.ConfigDir() } return "/etc/docker" }
func (s *DockerTrustSuite) setupDelegations(c *check.C, repoName, pwd string) { initCmd := exec.Command(notaryClientBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "init", repoName) notaryClientEnv(initCmd, pwd, pwd) out, _, err := runCommandWithOutput(initCmd) if err != nil { c.Fatalf("Error initializing notary repository: %s\n", out) } // no command line for this, so build by hand nRepo, err := client.NewNotaryRepository(filepath.Join(cliconfig.ConfigDir(), "trust"), repoName, notaryURL, nil, passphrase.ConstantRetriever(pwd)) if err != nil { c.Fatalf("Error creating notary repository: %s\n", err) } delgKey, err := nRepo.CryptoService.Create("targets/releases", data.ECDSAKey) if err != nil { c.Fatalf("Error creating delegation key: %s\n", err) } err = nRepo.AddDelegation("targets/releases", []data.PublicKey{delgKey}, []string{""}) if err != nil { c.Fatalf("Error creating delegation: %s\n", err) } // publishing first simulates the client pushing to a repo that they have been given delegated access to pubCmd := exec.Command(notaryClientBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "publish", repoName) notaryClientEnv(pubCmd, pwd, pwd) out, _, err = runCommandWithOutput(pubCmd) if err != nil { c.Fatalf("Error publishing notary repository: %s\n", out) } }
// Initialize the dockerCli runs initialization that must happen after command // line flags are parsed. func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error { cli.configFile = LoadDefaultConfigFile(cli.err) var err error cli.client, err = NewAPIClientFromFlags(opts.Common, cli.configFile) if err != nil { return err } cli.defaultVersion = cli.client.ClientVersion() if opts.Common.TrustKey == "" { cli.keyFile = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) } else { cli.keyFile = opts.Common.TrustKey } if ping, err := cli.client.Ping(context.Background()); err == nil { cli.hasExperimental = ping.Experimental // since the new header was added in 1.25, assume server is 1.24 if header is not present. if ping.APIVersion == "" { ping.APIVersion = "1.24" } // if server version is lower than the current cli, downgrade if versions.LessThan(ping.APIVersion, cli.client.ClientVersion()) { cli.client.UpdateClientVersion(ping.APIVersion) } } return nil }
func init() { initEnvs() dockerCertPath = os.Getenv("DOCKER_CERT_PATH") dockerTLSVerify = os.Getenv("DOCKER_TLS_VERIFY") != "" if dockerCertPath == "" { dockerCertPath = cliconfig.ConfigDir() } commonFlags.PostParse = postParseCommon cmd := commonFlags.FlagSet cmd.BoolVar(&commonFlags.Debug, []string{"D", "-debug"}, false, "Enable debug mode") cmd.StringVar(&commonFlags.LogLevel, []string{"l", "-log-level"}, "info", "Set the logging level") cmd.BoolVar(&commonFlags.TLS, []string{"-tls"}, false, "Use TLS; implied by --tlsverify") cmd.BoolVar(&commonFlags.TLSVerify, []string{"-tlsverify"}, dockerTLSVerify, "Use TLS and verify the remote") // TODO use flag flag.String([]string{"i", "-identity"}, "", "Path to libtrust key file") var tlsOptions tlsconfig.Options commonFlags.TLSOptions = &tlsOptions cmd.StringVar(&tlsOptions.CAFile, []string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust certs signed only by this CA") cmd.StringVar(&tlsOptions.CertFile, []string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file") cmd.StringVar(&tlsOptions.KeyFile, []string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file") cmd.Var(opts.NewListOptsRef(&commonFlags.Hosts, opts.ValidateHost), []string{"H", "-host"}, "Daemon socket(s) to connect to") }
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. // The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config // is set the client scheme will be set to https. // The client will be given a 32-second timeout (see https://github.com/docker/docker/pull/8035). func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cli.ClientFlags) *DockerCli { //创建cli对象 cli := &DockerCli{ in: in, out: out, err: err, keyFile: clientFlags.Common.TrustKey, } //docker客户端模式的创建过程,如果需要安全认证,需要加载安全认证的证书。 cli.init = func() error { clientFlags.PostParse() configFile, e := cliconfig.Load(cliconfig.ConfigDir()) if e != nil { fmt.Fprintf(cli.err, "WARNING: Error loading config file:%v\n", e) } if !configFile.ContainsAuth() { credentials.DetectDefaultStore(configFile) } cli.configFile = configFile host, err := getServerHost(clientFlags.Common.Hosts, clientFlags.Common.TLSOptions) if err != nil { return err } customHeaders := cli.configFile.HTTPHeaders if customHeaders == nil { customHeaders = map[string]string{} } customHeaders["User-Agent"] = clientUserAgent() verStr := api.DefaultVersion.String() if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { verStr = tmpStr } httpClient, err := newHTTPClient(host, clientFlags.Common.TLSOptions) if err != nil { return err } client, err := client.NewClient(host, verStr, httpClient, customHeaders) if err != nil { return err } cli.client = client if cli.in != nil { cli.inFd, cli.isTerminalIn = term.GetFdInfo(cli.in) } if cli.out != nil { cli.outFd, cli.isTerminalOut = term.GetFdInfo(cli.out) } return nil } return cli }
func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) { testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) s.notaryInitRepo(c, repoName) s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) s.notaryPublish(c, repoName) s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) // tag the image and upload it to the private registry dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) // check to make sure that the target has been added to targets/releases and not targets s.assertTargetInRoles(c, repoName, "latest", "targets/releases") s.assertTargetNotInRoles(c, repoName, "latest", "targets") // Try pull after push os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) pullCmd := exec.Command(dockerBinary, "pull", targetName) s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) }
// certificateDirectory returns the directory containing // TLS certificates for the given server. An error is // returned if there was an error parsing the server string. func (cli *DockerCli) certificateDirectory(server string) (string, error) { u, err := url.Parse(server) if err != nil { return "", err } return filepath.Join(cliconfig.ConfigDir(), "tls", u.Host), nil }
func setDefaultConfFlag(flag *string, def string) { if *flag == "" { if *flDaemon { *flag = filepath.Join(getDaemonConfDir(), def) } else { *flag = filepath.Join(cliconfig.ConfigDir(), def) } } }
// getDockerClient obtains a new Docker client from the environment or // from a Docker machine, starting it if necessary and permitted func getDockerClient(out io.Writer, dockerMachine string, canStartDockerMachine bool) (*docker.Client, *dockerclient.Client, error) { if len(dockerMachine) > 0 { glog.V(2).Infof("Getting client for Docker machine %q", dockerMachine) dockerClient, engineAPIClient, err := getDockerMachineClient(dockerMachine, out, canStartDockerMachine) if err != nil { return nil, nil, errors.ErrNoDockerMachineClient(dockerMachine, err) } return dockerClient, engineAPIClient, nil } dockerTLSVerify := os.Getenv("DOCKER_TLS_VERIFY") dockerCertPath := os.Getenv("DOCKER_CERT_PATH") if len(dockerTLSVerify) > 0 && len(dockerCertPath) == 0 { dockerCertPath = cliconfig.ConfigDir() os.Setenv("DOCKER_CERT_PATH", dockerCertPath) } if glog.V(4) { dockerHost := os.Getenv("DOCKER_HOST") if len(dockerHost) == 0 && len(dockerTLSVerify) == 0 && len(dockerCertPath) == 0 { glog.Infof("No Docker environment variables found. Will attempt default socket.") } if len(dockerHost) > 0 { glog.Infof("Will try Docker connection with host (DOCKER_HOST) %q", dockerHost) } else { glog.Infof("No Docker host (DOCKER_HOST) configured. Will attempt default socket.") } if len(dockerTLSVerify) > 0 { glog.Infof("DOCKER_TLS_VERIFY=%s", dockerTLSVerify) } if len(dockerCertPath) > 0 { glog.Infof("DOCKER_CERT_PATH=%s", dockerCertPath) } } dockerClient, _, err := dockerutil.NewHelper().GetClient() if err != nil { return nil, nil, errors.ErrNoDockerClient(err) } // FIXME: Workaround for docker engine API client on OS X - sets the default to // the wrong DOCKER_HOST string if runtime.GOOS == "darwin" { dockerHost := os.Getenv("DOCKER_HOST") if len(dockerHost) == 0 { os.Setenv("DOCKER_HOST", "unix:///var/run/docker.sock") } } engineAPIClient, err := dockerclient.NewEnvClient() if err != nil { return nil, nil, errors.ErrNoDockerClient(err) } if err = dockerClient.Ping(); err != nil { return nil, nil, errors.ErrCannotPingDocker(err) } glog.V(4).Infof("Docker ping succeeded") return dockerClient, engineAPIClient, nil }
func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command { opts := cliflags.NewClientOptions() var flags *pflag.FlagSet cmd := &cobra.Command{ Use: "docker [OPTIONS] COMMAND [ARG...]", Short: "A self-sufficient runtime for containers", SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, Args: noArgs, RunE: func(cmd *cobra.Command, args []string) error { if opts.Version { showVersion() return nil } cmd.SetOutput(dockerCli.Err()) cmd.HelpFunc()(cmd, args) return nil }, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { // flags must be the top-level command flags, not cmd.Flags() opts.Common.SetDefaultOptions(flags) dockerPreRun(opts) return dockerCli.Initialize(opts) }, } cli.SetupRootCommand(cmd) cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) { var err error if dockerCli.Client() == nil { // flags must be the top-level command flags, not cmd.Flags() opts.Common.SetDefaultOptions(flags) dockerPreRun(opts) err = dockerCli.Initialize(opts) } if err != nil || !dockerCli.HasExperimental() { hideExperimentalFeatures(ccmd) } if err := ccmd.Help(); err != nil { ccmd.Println(err) } }) flags = cmd.Flags() flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit") flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files") opts.Common.InstallFlags(flags) cmd.SetOutput(dockerCli.Out()) cmd.AddCommand(newDaemonCommand()) commands.AddCommands(cmd, dockerCli) return cmd }
// LoadDefaultConfigFile attempts to load the default config file and returns // an initialized ConfigFile struct if none is found. func LoadDefaultConfigFile(err io.Writer) *configfile.ConfigFile { configFile, e := cliconfig.Load(cliconfig.ConfigDir()) if e != nil { fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e) } if !configFile.ContainsAuth() { credentials.DetectDefaultStore(configFile) } return configFile }
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. // The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config // is set the client scheme will be set to https. // The client will be given a 32-second timeout (see https://github.com/docker/docker/pull/8035). func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cli.ClientFlags) *DockerCli { cli := &DockerCli{ in: in, out: out, err: err, keyFile: clientFlags.Common.TrustKey, } cli.init = func() error { clientFlags.PostParse() configFile, e := cliconfig.Load(cliconfig.ConfigDir()) if e != nil { fmt.Fprintf(cli.err, "WARNING: Error loading config file:%v\n", e) } cli.configFile = configFile host, err := getServerHost(clientFlags.Common.Hosts, clientFlags.Common.TLSOptions) if err != nil { return err } customHeaders := cli.configFile.HTTPHeaders if customHeaders == nil { customHeaders = map[string]string{} } customHeaders["User-Agent"] = "Docker-Client/" + dockerversion.Version + " (" + runtime.GOOS + ")" verStr := api.DefaultVersion.String() if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { verStr = tmpStr } clientTransport, err := newClientTransport(clientFlags.Common.TLSOptions) if err != nil { return err } client, err := client.NewClient(host, verStr, clientTransport, customHeaders) if err != nil { return err } cli.client = client if cli.in != nil { cli.inFd, cli.isTerminalIn = term.GetFdInfo(cli.in) } if cli.out != nil { cli.outFd, cli.isTerminalOut = term.GetFdInfo(cli.out) } return nil } return cli }
func (s *DockerTrustSuite) TearDownTest(c *check.C) { if s.reg != nil { s.reg.Close() } if s.not != nil { s.not.Close() } // Remove trusted keys and metadata after test os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) s.ds.TearDownTest(c) }
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. // The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config // is set the client scheme will be set to https. // The client will be given a 32-second timeout (see https://github.com/docker/docker/pull/8035). func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig *tls.Config) *DockerCli { var ( inFd uintptr outFd uintptr isTerminalIn = false isTerminalOut = false scheme = "http" ) if tlsConfig != nil { scheme = "https" } if in != nil { inFd, isTerminalIn = term.GetFdInfo(in) } if out != nil { outFd, isTerminalOut = term.GetFdInfo(out) } if err == nil { err = out } // The transport is created here for reuse during the client session. tr := &http.Transport{ TLSClientConfig: tlsConfig, } sockets.ConfigureTCPTransport(tr, proto, addr) configFile, e := cliconfig.Load(cliconfig.ConfigDir()) if e != nil { fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e) } return &DockerCli{ proto: proto, addr: addr, configFile: configFile, in: in, out: out, err: err, keyFile: keyFile, inFd: inFd, outFd: outFd, isTerminalIn: isTerminalIn, isTerminalOut: isTerminalOut, tlsConfig: tlsConfig, scheme: scheme, transport: tr, } }
func initClientFlags(commonFlags *cliflags.CommonFlags) *cliflags.ClientFlags { clientFlags := &cliflags.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags} client := clientFlags.FlagSet client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files") clientFlags.PostParse = func() { clientFlags.Common.PostParse() if clientFlags.ConfigDir != "" { cliconfig.SetConfigDir(clientFlags.ConfigDir) } if clientFlags.Common.TrustKey == "" { clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) } if clientFlags.Common.Debug { utils.EnableDebug() } } return clientFlags }
// Initialize the dockerCli runs initialization that must happen after command // line flags are parsed. func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error { cli.configFile = LoadDefaultConfigFile(cli.err) var err error cli.client, err = NewAPIClientFromFlags(opts.Common, cli.configFile) if err != nil { return err } if opts.Common.TrustKey == "" { cli.keyFile = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) } else { cli.keyFile = opts.Common.TrustKey } return nil }
func migrateKey(config *daemon.Config) (err error) { // No migration necessary on Windows if runtime.GOOS == "windows" { return nil } // Migrate trust key if exists at ~/.docker/key.json and owned by current user oldPath := filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile) newPath := filepath.Join(getDaemonConfDir(config.Root), cliflags.DefaultTrustKeyFile) if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) { defer func() { // Ensure old path is removed if no error occurred if err == nil { err = os.Remove(oldPath) } else { logrus.Warnf("Key migration failed, key file not removed at %s", oldPath) os.Remove(newPath) } }() if err := system.MkdirAll(getDaemonConfDir(config.Root), os.FileMode(0644)); err != nil { return fmt.Errorf("Unable to create daemon configuration directory: %s", err) } newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return fmt.Errorf("error creating key file %q: %s", newPath, err) } defer newFile.Close() oldFile, err := os.Open(oldPath) if err != nil { return fmt.Errorf("error opening key file %q: %s", oldPath, err) } defer oldFile.Close() if _, err := io.Copy(newFile, oldFile); err != nil { return fmt.Errorf("error copying key: %s", err) } logrus.Infof("Migrated key from %s to %s", oldPath, newPath) } return nil }
func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) { testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) s.notaryInitRepo(c, repoName) s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public) s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public) // import everything except the third key s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) s.notaryCreateDelegation(c, repoName, "targets/role1/subrole", s.not.keys[3].Public) s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private) s.notaryPublish(c, repoName) // tag the image and upload it to the private registry dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) // check to make sure that the target has been added to targets/role1 and targets/role2, and // not targets (because there are delegations) or targets/role3 (due to missing key) or // targets/role1/subrole (due to it being a second level delegation) s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role2") s.assertTargetNotInRoles(c, repoName, "latest", "targets") // Try pull after push os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) // pull should fail because none of these are the releases role pullCmd := exec.Command(dockerBinary, "pull", targetName) s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.NotNil, check.Commentf(out)) }
// InstallFlags adds flags for the common options on the FlagSet func (commonOpts *CommonOptions) InstallFlags(flags *pflag.FlagSet) { if dockerCertPath == "" { dockerCertPath = cliconfig.ConfigDir() } flags.BoolVarP(&commonOpts.Debug, "debug", "D", false, "Enable debug mode") flags.StringVarP(&commonOpts.LogLevel, "log-level", "l", "info", "Set the logging level") flags.BoolVar(&commonOpts.TLS, "tls", false, "Use TLS; implied by --tlsverify") flags.BoolVar(&commonOpts.TLSVerify, FlagTLSVerify, dockerTLSVerify, "Use TLS and verify the remote") // TODO use flag flags.String("identity"}, "i", "", "Path to libtrust key file") commonOpts.TLSOptions = &tlsconfig.Options{} tlsOptions := commonOpts.TLSOptions flags.StringVar(&tlsOptions.CAFile, "tlscacert", filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA") flags.StringVar(&tlsOptions.CertFile, "tlscert", filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file") flags.StringVar(&tlsOptions.KeyFile, "tlskey", filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file") hostOpt := opts.NewNamedListOptsRef("hosts", &commonOpts.Hosts, opts.ValidateHost) flags.VarP(hostOpt, "host", "H", "Daemon socket(s) to connect to") }
// GetDefaultDockerConfig checks relevant Docker environment variables to // provide defaults for our command line flags func GetDefaultDockerConfig() *api.DockerConfig { cfg := &api.DockerConfig{} if cfg.Endpoint = os.Getenv("DOCKER_HOST"); cfg.Endpoint == "" { cfg.Endpoint = client.DefaultDockerHost } certPath := os.Getenv("DOCKER_CERT_PATH") if certPath == "" { certPath = cliconfig.ConfigDir() } cfg.CertFile = filepath.Join(certPath, "cert.pem") cfg.KeyFile = filepath.Join(certPath, "key.pem") cfg.CAFile = filepath.Join(certPath, "ca.pem") if tlsVerify := os.Getenv("DOCKER_TLS_VERIFY"); tlsVerify != "" { cfg.TLSVerify = true } return cfg }
func newDockerCommand(dockerCli *client.DockerCli) *cobra.Command { opts := cliflags.NewClientOptions() var flags *pflag.FlagSet cmd := &cobra.Command{ Use: "docker [OPTIONS] COMMAND [arg...]", Short: "A self-sufficient runtime for containers.", SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, Args: noArgs, RunE: func(cmd *cobra.Command, args []string) error { if opts.Version { showVersion() return nil } fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString()) return nil }, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { // flags must be the top-level command flags, not cmd.Flags() opts.Common.SetDefaultOptions(flags) dockerPreRun(opts) return dockerCli.Initialize(opts) }, } cli.SetupRootCommand(cmd) flags = cmd.Flags() flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit") flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files") opts.Common.InstallFlags(flags) cmd.SetOutput(dockerCli.Out()) cmd.AddCommand(newDaemonCommand()) command.AddCommands(cmd, dockerCli) return cmd }
//getAuthConfig return the auth config if it exists. Nil and false otherwise func getAuthConfig(remoteRepo string) (*types.AuthConfig, bool) { configFile, e := cliconfig.Load(cliconfig.ConfigDir()) //ou if e != nil { LogWarn.Printf("Error loading config file:%v\n", e) //no auth, return an empty auth return nil, false } for hostName, config := range configFile.AuthConfigs { if strings.Contains(hostName, remoteRepo) { return &config, true } } return nil, false }
func CompatLoad() (*CompatConfigFile, error) { dockerCfg := cliconfig.NewConfigFile(filepath.Join(cliconfig.ConfigDir(), cliconfig.ConfigFileName)) configFile := CompatConfigFile{ dockerCfg, dockerCfg.Filename(), } // Try .docker/config.json first if _, err := os.Stat(configFile.filename); err == nil { file, err := os.Open(configFile.filename) if err != nil { return &configFile, err } defer file.Close() err = configFile.LoadFromReader(file) return &configFile, err } else if !os.IsNotExist(err) { return &configFile, err } // Try the old .dockercfg homeDir, _ := homedir.Dir() configFile.filename = filepath.Join(homeDir, ".dockercfg") if _, err := os.Stat(configFile.filename); err != nil { return &configFile, nil //missing file is not an error } file, err := os.Open(configFile.filename) if err != nil { return &configFile, err } defer file.Close() err = configFile.LegacyLoadFromReader(file) if err != nil { return &configFile, err } return &configFile, nil }
func main() { app := cli.NewApp() app.Name = "skopeo" app.Version = version app.Usage = usage app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "debug", Usage: "enable debug output", }, cli.StringFlag{ Name: "username", Value: "", Usage: "registry username", }, cli.StringFlag{ Name: "password", Value: "", Usage: "registry password", }, cli.StringFlag{ Name: "docker-cfg", Value: cliconfig.ConfigDir(), Usage: "Docker's cli config for auth", }, } app.Before = func(c *cli.Context) error { if c.GlobalBool("debug") { logrus.SetLevel(logrus.DebugLevel) } return nil } app.Action = inspectCmd if err := app.Run(os.Args); err != nil { logrus.Fatal(err) } }
func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { repoName := fmt.Sprintf("%v/dockerclitrusted/pushtest: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) c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push")) // Try pull after push pullCmd := exec.Command(dockerBinary, "pull", repoName) s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) // Assert that we rotated the snapshot key to the server by checking our local keystore contents, err := ioutil.ReadDir(filepath.Join(cliconfig.ConfigDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest")) c.Assert(err, check.IsNil, check.Commentf("Unable to read local tuf key files")) // Check that we only have 1 key (targets key) c.Assert(contents, checker.HasLen, 1) }