Browse code

Merge pull request #32587 from dmcgowan/trust-key-config

Expose trust key path in config

Sebastiaan van Stijn authored on 2017/05/12 04:03:47
Showing 6 changed files
... ...
@@ -13,8 +13,6 @@ import (
13 13
 )
14 14
 
15 15
 const (
16
-	// DefaultTrustKeyFile is the default filename for the trust key
17
-	DefaultTrustKeyFile = "key.json"
18 16
 	// DefaultCaFile is the default filename for the CA pem file
19 17
 	DefaultCaFile = "ca.pem"
20 18
 	// DefaultKeyFile is the default filename for the key pem file
... ...
@@ -38,7 +36,6 @@ type CommonOptions struct {
38 38
 	TLS        bool
39 39
 	TLSVerify  bool
40 40
 	TLSOptions *tlsconfig.Options
41
-	TrustKey   string
42 41
 }
43 42
 
44 43
 // NewCommonOptions returns a new CommonOptions
... ...
@@ -9,6 +9,8 @@ import (
9 9
 const (
10 10
 	// defaultShutdownTimeout is the default shutdown timeout for the daemon
11 11
 	defaultShutdownTimeout = 15
12
+	// defaultTrustKeyFile is the default filename for the trust key
13
+	defaultTrustKeyFile = "key.json"
12 14
 )
13 15
 
14 16
 // installCommonConfigFlags adds flags to the pflag.FlagSet to configure the daemon
... ...
@@ -53,6 +55,13 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
53 53
 
54 54
 	flags.StringVar(&conf.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on")
55 55
 
56
+	// "--deprecated-key-path" is to allow configuration of the key used
57
+	// for the daemon ID and the deprecated image signing. It was never
58
+	// exposed as a command line option but is added here to allow
59
+	// overriding the default path in configuration.
60
+	flags.Var(opts.NewQuotedString(&conf.TrustKeyPath), "deprecated-key-path", "Path to key file for ID and image signing")
61
+	flags.MarkHidden("deprecated-key-path")
62
+
56 63
 	conf.MaxConcurrentDownloads = &maxConcurrentDownloads
57 64
 	conf.MaxConcurrentUploads = &maxConcurrentUploads
58 65
 }
... ...
@@ -3,10 +3,8 @@ package main
3 3
 import (
4 4
 	"crypto/tls"
5 5
 	"fmt"
6
-	"io"
7 6
 	"os"
8 7
 	"path/filepath"
9
-	"runtime"
10 8
 	"strings"
11 9
 	"time"
12 10
 
... ...
@@ -27,7 +25,6 @@ import (
27 27
 	swarmrouter "github.com/docker/docker/api/server/router/swarm"
28 28
 	systemrouter "github.com/docker/docker/api/server/router/system"
29 29
 	"github.com/docker/docker/api/server/router/volume"
30
-	"github.com/docker/docker/cli"
31 30
 	"github.com/docker/docker/cli/debug"
32 31
 	cliflags "github.com/docker/docker/cli/flags"
33 32
 	"github.com/docker/docker/daemon"
... ...
@@ -43,7 +40,6 @@ import (
43 43
 	"github.com/docker/docker/pkg/pidfile"
44 44
 	"github.com/docker/docker/pkg/plugingetter"
45 45
 	"github.com/docker/docker/pkg/signal"
46
-	"github.com/docker/docker/pkg/system"
47 46
 	"github.com/docker/docker/plugin"
48 47
 	"github.com/docker/docker/registry"
49 48
 	"github.com/docker/docker/runconfig"
... ...
@@ -67,52 +63,6 @@ func NewDaemonCli() *DaemonCli {
67 67
 	return &DaemonCli{}
68 68
 }
69 69
 
70
-func migrateKey(config *config.Config) (err error) {
71
-	// No migration necessary on Windows
72
-	if runtime.GOOS == "windows" {
73
-		return nil
74
-	}
75
-
76
-	// Migrate trust key if exists at ~/.docker/key.json and owned by current user
77
-	oldPath := filepath.Join(cli.ConfigurationDir(), cliflags.DefaultTrustKeyFile)
78
-	newPath := filepath.Join(getDaemonConfDir(config.Root), cliflags.DefaultTrustKeyFile)
79
-	if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
80
-		defer func() {
81
-			// Ensure old path is removed if no error occurred
82
-			if err == nil {
83
-				err = os.Remove(oldPath)
84
-			} else {
85
-				logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
86
-				os.Remove(newPath)
87
-			}
88
-		}()
89
-
90
-		if err := system.MkdirAll(getDaemonConfDir(config.Root), os.FileMode(0644)); err != nil {
91
-			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
92
-		}
93
-
94
-		newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
95
-		if err != nil {
96
-			return fmt.Errorf("error creating key file %q: %s", newPath, err)
97
-		}
98
-		defer newFile.Close()
99
-
100
-		oldFile, err := os.Open(oldPath)
101
-		if err != nil {
102
-			return fmt.Errorf("error opening key file %q: %s", oldPath, err)
103
-		}
104
-		defer oldFile.Close()
105
-
106
-		if _, err := io.Copy(newFile, oldFile); err != nil {
107
-			return fmt.Errorf("error copying key: %s", err)
108
-		}
109
-
110
-		logrus.Infof("Migrated key from %s to %s", oldPath, newPath)
111
-	}
112
-
113
-	return nil
114
-}
115
-
116 70
 func (cli *DaemonCli) start(opts daemonOptions) (err error) {
117 71
 	stopc := make(chan bool)
118 72
 	defer close(stopc)
... ...
@@ -128,12 +78,6 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
128 128
 	cli.configFile = &opts.configFile
129 129
 	cli.flags = opts.flags
130 130
 
131
-	if opts.common.TrustKey == "" {
132
-		opts.common.TrustKey = filepath.Join(
133
-			getDaemonConfDir(cli.Config.Root),
134
-			cliflags.DefaultTrustKeyFile)
135
-	}
136
-
137 131
 	if cli.Config.Debug {
138 132
 		debug.Enable()
139 133
 	}
... ...
@@ -242,13 +186,6 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
242 242
 		api.Accept(addr, ls...)
243 243
 	}
244 244
 
245
-	if err := migrateKey(cli.Config); err != nil {
246
-		return err
247
-	}
248
-
249
-	// FIXME: why is this down here instead of with the other TrustKey logic above?
250
-	cli.TrustKeyPath = opts.common.TrustKey
251
-
252 245
 	registryService := registry.NewService(cli.Config.ServiceOptions)
253 246
 	containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)
254 247
 	if err != nil {
... ...
@@ -424,6 +361,12 @@ func loadDaemonCliConfig(opts daemonOptions) (*config.Config, error) {
424 424
 		conf.CommonTLSOptions.KeyFile = opts.common.TLSOptions.KeyFile
425 425
 	}
426 426
 
427
+	if conf.TrustKeyPath == "" {
428
+		conf.TrustKeyPath = filepath.Join(
429
+			getDaemonConfDir(conf.Root),
430
+			defaultTrustKeyFile)
431
+	}
432
+
427 433
 	if flags.Changed("graph") && flags.Changed("data-root") {
428 434
 		return nil, fmt.Errorf(`cannot specify both "--graph" and "--data-root" option`)
429 435
 	}
... ...
@@ -14,23 +14,11 @@ import (
14 14
 	"github.com/docker/docker/cmd/dockerd/hack"
15 15
 	"github.com/docker/docker/daemon"
16 16
 	"github.com/docker/docker/libcontainerd"
17
-	"github.com/docker/docker/pkg/system"
18 17
 	"github.com/docker/libnetwork/portallocator"
19 18
 )
20 19
 
21 20
 const defaultDaemonConfigFile = "/etc/docker/daemon.json"
22 21
 
23
-// currentUserIsOwner checks whether the current user is the owner of the given
24
-// file.
25
-func currentUserIsOwner(f string) bool {
26
-	if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil {
27
-		if int(fileInfo.UID()) == os.Getuid() {
28
-			return true
29
-		}
30
-	}
31
-	return false
32
-}
33
-
34 22
 // setDefaultUmask sets the umask to 0022 to avoid problems
35 23
 // caused by custom umask
36 24
 func setDefaultUmask() error {
... ...
@@ -102,10 +102,15 @@ type CommonConfig struct {
102 102
 	RootDeprecated       string                    `json:"graph,omitempty"`
103 103
 	Root                 string                    `json:"data-root,omitempty"`
104 104
 	SocketGroup          string                    `json:"group,omitempty"`
105
-	TrustKeyPath         string                    `json:"-"`
106 105
 	CorsHeaders          string                    `json:"api-cors-header,omitempty"`
107 106
 	EnableCors           bool                      `json:"api-enable-cors,omitempty"`
108 107
 
108
+	// TrustKeyPath is used to generate the daemon ID and for signing schema 1 manifests
109
+	// when pushing to a registry which does not support schema 2. This field is marked as
110
+	// deprecated because schema 1 manifests are deprecated in favor of schema 2 and the
111
+	// daemon ID will use a dedicated identifier not shared with exported signatures.
112
+	TrustKeyPath string `json:"deprecated-key-path,omitempty"`
113
+
109 114
 	// LiveRestoreEnabled determines whether we should keep containers
110 115
 	// alive upon daemon shutdown/start
111 116
 	LiveRestoreEnabled bool `json:"live-restore,omitempty"`
... ...
@@ -535,32 +535,6 @@ func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) {
535 535
 	}
536 536
 }
537 537
 
538
-func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) {
539
-	// TODO: skip or update for Windows daemon
540
-	os.Remove("/etc/docker/key.json")
541
-	k1, err := libtrust.GenerateECP256PrivateKey()
542
-	if err != nil {
543
-		c.Fatalf("Error generating private key: %s", err)
544
-	}
545
-	if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil {
546
-		c.Fatalf("Error creating .docker directory: %s", err)
547
-	}
548
-	if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil {
549
-		c.Fatalf("Error saving private key: %s", err)
550
-	}
551
-
552
-	s.d.Start(c)
553
-	s.d.Stop(c)
554
-
555
-	k2, err := libtrust.LoadKeyFile("/etc/docker/key.json")
556
-	if err != nil {
557
-		c.Fatalf("Error opening key file")
558
-	}
559
-	if k1.KeyID() != k2.KeyID() {
560
-		c.Fatalf("Key not migrated")
561
-	}
562
-}
563
-
564 538
 // GH#11320 - verify that the daemon exits on failure properly
565 539
 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means
566 540
 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required