diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 994f848875..908e058e9e 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -284,29 +284,41 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio } func (cli *DaemonCli) reloadConfig() { - reload := func(config *config.Config) { + reload := func(c *config.Config) { // Revalidate and reload the authorization plugins - if err := validateAuthzPlugins(config.AuthorizationPlugins, cli.d.PluginStore); err != nil { + if err := validateAuthzPlugins(c.AuthorizationPlugins, cli.d.PluginStore); err != nil { logrus.Fatalf("Error validating authorization plugin: %v", err) return } - cli.authzMiddleware.SetPlugins(config.AuthorizationPlugins) + cli.authzMiddleware.SetPlugins(c.AuthorizationPlugins) - if err := cli.d.Reload(config); err != nil { + // The namespaces com.docker.*, io.docker.*, org.dockerproject.* have been documented + // to be reserved for Docker's internal use, but this was never enforced. Allowing + // configured labels to use these namespaces are deprecated for 18.05. + // + // The following will check the usage of such labels, and report a warning for deprecation. + // + // TODO: At the next stable release, the validation should be folded into the other + // configuration validation functions and an error will be returned instead, and this + // block should be deleted. + if err := config.ValidateReservedNamespaceLabels(c.Labels); err != nil { + logrus.Warnf("Configured labels using reserved namespaces is deprecated: %s", err) + } + + if err := cli.d.Reload(c); err != nil { logrus.Errorf("Error reconfiguring the daemon: %v", err) return } - if config.IsValueSet("debug") { + if c.IsValueSet("debug") { debugEnabled := debug.IsEnabled() switch { - case debugEnabled && !config.Debug: // disable debug + case debugEnabled && !c.Debug: // disable debug debug.Disable() - case config.Debug && !debugEnabled: // enable debug + case c.Debug && !debugEnabled: // enable debug debug.Enable() } - } } @@ -406,6 +418,18 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) { if err != nil { return nil, err } + // The namespaces com.docker.*, io.docker.*, org.dockerproject.* have been documented + // to be reserved for Docker's internal use, but this was never enforced. Allowing + // configured labels to use these namespaces are deprecated for 18.05. + // + // The following will check the usage of such labels, and report a warning for deprecation. + // + // TODO: At the next stable release, the validation should be folded into the other + // configuration validation functions and an error will be returned instead, and this + // block should be deleted. + if err := config.ValidateReservedNamespaceLabels(newLabels); err != nil { + logrus.Warnf("Configured labels using reserved namespaces is deprecated: %s", err) + } conf.Labels = newLabels // Regardless of whether the user sets it to true or false, if they diff --git a/daemon/config/config.go b/daemon/config/config.go index bc4dea9c3c..6cda223a11 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -262,6 +262,25 @@ func GetConflictFreeLabels(labels []string) ([]string, error) { return newLabels, nil } +// ValidateReservedNamespaceLabels errors if the reserved namespaces com.docker.*, +// io.docker.*, org.dockerproject.* are used in a configured engine label. +// +// TODO: This is a separate function because we need to warn users first of the +// deprecation. When we return an error, this logic can be added to Validate +// or GetConflictFreeLabels instead of being here. +func ValidateReservedNamespaceLabels(labels []string) error { + for _, label := range labels { + lowered := strings.ToLower(label) + if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") || + strings.HasPrefix(lowered, "org.dockerproject.") { + return fmt.Errorf( + "label %s not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for Docker's internal use", + label) + } + } + return nil +} + // Reload reads the configuration in the host and reloads the daemon and server. func Reload(configFile string, flags *pflag.FlagSet, reload func(*Config)) error { logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile) diff --git a/daemon/config/config_test.go b/daemon/config/config_test.go index f884b4cccf..a18b84da97 100644 --- a/daemon/config/config_test.go +++ b/daemon/config/config_test.go @@ -193,6 +193,40 @@ func TestFindConfigurationConflictsWithMergedValues(t *testing.T) { } } +func TestValidateReservedNamespaceLabels(t *testing.T) { + for _, validLabels := range [][]string{ + nil, // no error if there are no labels + { // no error if there aren't any reserved namespace labels + "hello=world", + "label=me", + }, + { // only reserved namespaces that end with a dot are invalid + "com.dockerpsychnotreserved.label=value", + "io.dockerproject.not=reserved", + "org.docker.not=reserved", + }, + } { + assert.Check(t, ValidateReservedNamespaceLabels(validLabels)) + } + + for _, invalidLabel := range []string{ + "com.docker.feature=enabled", + "io.docker.configuration=0", + "org.dockerproject.setting=on", + // casing doesn't matter + "COM.docker.feature=enabled", + "io.DOCKER.CONFIGURATION=0", + "Org.Dockerproject.Setting=on", + } { + err := ValidateReservedNamespaceLabels([]string{ + "valid=label", + invalidLabel, + "another=valid", + }) + assert.Check(t, is.ErrorContains(err, invalidLabel)) + } +} + func TestValidateConfigurationErrors(t *testing.T) { minusNumber := -10 testCases := []struct {