Skip to content

Commit 35d6c18

Browse files
enforce reserve internal labels.
The namespaces com.docker.*, io.docker.*, org.dockerproject.* have been documented to be reserved for Docker's internal use. Co-Authored-By: Sebastiaan van Stijn <thaJeztah@users.noreply.github.com> Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
1 parent c51c65a commit 35d6c18

File tree

5 files changed

+102
-91
lines changed

5 files changed

+102
-91
lines changed

cmd/dockerd/daemon.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,6 @@ func (cli *DaemonCli) reloadConfig() {
326326
}
327327
cli.authzMiddleware.SetPlugins(c.AuthorizationPlugins)
328328

329-
// The namespaces com.docker.*, io.docker.*, org.dockerproject.* have been documented
330-
// to be reserved for Docker's internal use, but this was never enforced. Allowing
331-
// configured labels to use these namespaces are deprecated for 18.05.
332-
//
333-
// The following will check the usage of such labels, and report a warning for deprecation.
334-
//
335-
// TODO: At the next stable release, the validation should be folded into the other
336-
// configuration validation functions and an error will be returned instead, and this
337-
// block should be deleted.
338-
if err := config.ValidateReservedNamespaceLabels(c.Labels); err != nil {
339-
logrus.Warnf("Configured labels using reserved namespaces is deprecated: %s", err)
340-
}
341-
342329
if err := cli.d.Reload(c); err != nil {
343330
logrus.Errorf("Error reconfiguring the daemon: %v", err)
344331
return
@@ -446,18 +433,6 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
446433
if err != nil {
447434
return nil, err
448435
}
449-
// The namespaces com.docker.*, io.docker.*, org.dockerproject.* have been documented
450-
// to be reserved for Docker's internal use, but this was never enforced. Allowing
451-
// configured labels to use these namespaces are deprecated for 18.05.
452-
//
453-
// The following will check the usage of such labels, and report a warning for deprecation.
454-
//
455-
// TODO: At the next stable release, the validation should be folded into the other
456-
// configuration validation functions and an error will be returned instead, and this
457-
// block should be deleted.
458-
if err := config.ValidateReservedNamespaceLabels(newLabels); err != nil {
459-
logrus.Warnf("Configured labels using reserved namespaces is deprecated: %s", err)
460-
}
461436
conf.Labels = newLabels
462437

463438
// Regardless of whether the user sets it to true or false, if they

daemon/config/config.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -308,25 +308,6 @@ func GetConflictFreeLabels(labels []string) ([]string, error) {
308308
return newLabels, nil
309309
}
310310

311-
// ValidateReservedNamespaceLabels errors if the reserved namespaces com.docker.*,
312-
// io.docker.*, org.dockerproject.* are used in a configured engine label.
313-
//
314-
// TODO: This is a separate function because we need to warn users first of the
315-
// deprecation. When we return an error, this logic can be added to Validate
316-
// or GetConflictFreeLabels instead of being here.
317-
func ValidateReservedNamespaceLabels(labels []string) error {
318-
for _, label := range labels {
319-
lowered := strings.ToLower(label)
320-
if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") ||
321-
strings.HasPrefix(lowered, "org.dockerproject.") {
322-
return fmt.Errorf(
323-
"label %s not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for Docker's internal use",
324-
label)
325-
}
326-
}
327-
return nil
328-
}
329-
330311
// Reload reads the configuration in the host and reloads the daemon and server.
331312
func Reload(configFile string, flags *pflag.FlagSet, reload func(*Config)) error {
332313
logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile)

daemon/config/config_test.go

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -188,40 +188,6 @@ func TestFindConfigurationConflictsWithMergedValues(t *testing.T) {
188188
}
189189
}
190190

191-
func TestValidateReservedNamespaceLabels(t *testing.T) {
192-
for _, validLabels := range [][]string{
193-
nil, // no error if there are no labels
194-
{ // no error if there aren't any reserved namespace labels
195-
"hello=world",
196-
"label=me",
197-
},
198-
{ // only reserved namespaces that end with a dot are invalid
199-
"com.dockerpsychnotreserved.label=value",
200-
"io.dockerproject.not=reserved",
201-
"org.docker.not=reserved",
202-
},
203-
} {
204-
assert.Check(t, ValidateReservedNamespaceLabels(validLabels))
205-
}
206-
207-
for _, invalidLabel := range []string{
208-
"com.docker.feature=enabled",
209-
"io.docker.configuration=0",
210-
"org.dockerproject.setting=on",
211-
// casing doesn't matter
212-
"COM.docker.feature=enabled",
213-
"io.DOCKER.CONFIGURATION=0",
214-
"Org.Dockerproject.Setting=on",
215-
} {
216-
err := ValidateReservedNamespaceLabels([]string{
217-
"valid=label",
218-
invalidLabel,
219-
"another=valid",
220-
})
221-
assert.Check(t, is.ErrorContains(err, invalidLabel))
222-
}
223-
}
224-
225191
func TestValidateConfigurationErrors(t *testing.T) {
226192
intPtr := func(i int) *int { return &i }
227193

opts/opts.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,23 @@ func validateDomain(val string) (string, error) {
254254
return "", fmt.Errorf("%s is not a valid domain", val)
255255
}
256256

257-
// ValidateLabel validates that the specified string is a valid label, and returns it.
257+
// ValidateLabel validates that the specified string is a valid label,
258+
// it does not use the reserved namespaces com.docker.*, io.docker.*, org.dockerproject.*
259+
// and returns it.
258260
// Labels are in the form on key=value.
259261
func ValidateLabel(val string) (string, error) {
260262
if strings.Count(val, "=") < 1 {
261263
return "", fmt.Errorf("bad attribute format: %s", val)
262264
}
265+
266+
lowered := strings.ToLower(val)
267+
if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") ||
268+
strings.HasPrefix(lowered, "org.dockerproject.") {
269+
return "", fmt.Errorf(
270+
"label %s is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
271+
val)
272+
}
273+
263274
return val, nil
264275
}
265276

opts/opts_test.go

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import (
44
"fmt"
55
"strings"
66
"testing"
7+
8+
"gotest.tools/v3/assert"
9+
is "gotest.tools/v3/assert/cmp"
710
)
811

912
func TestValidateIPAddress(t *testing.T) {
@@ -174,19 +177,94 @@ func TestValidateDNSSearch(t *testing.T) {
174177
}
175178

176179
func TestValidateLabel(t *testing.T) {
177-
if _, err := ValidateLabel("label"); err == nil || err.Error() != "bad attribute format: label" {
178-
t.Fatalf("Expected an error [bad attribute format: label], go %v", err)
179-
}
180-
if actual, err := ValidateLabel("key1=value1"); err != nil || actual != "key1=value1" {
181-
t.Fatalf("Expected [key1=value1], got [%v,%v]", actual, err)
182-
}
183-
// Validate it's working with more than one =
184-
if actual, err := ValidateLabel("key1=value1=value2"); err != nil {
185-
t.Fatalf("Expected [key1=value1=value2], got [%v,%v]", actual, err)
180+
testCases := []struct {
181+
name string
182+
label string
183+
expectedResult string
184+
expectedErr string
185+
}{
186+
{
187+
name: "lable with bad attribute format",
188+
label: "label",
189+
expectedErr: "bad attribute format: label",
190+
},
191+
{
192+
name: "label with general format",
193+
label: "key1=value1",
194+
expectedResult: "key1=value1",
195+
},
196+
{
197+
name: "label with more than one =",
198+
label: "key1=value1=value2",
199+
expectedResult: "key1=value1=value2",
200+
},
201+
{
202+
name: "label with one more",
203+
label: "key1=value1=value2=value3",
204+
expectedResult: "key1=value1=value2=value3",
205+
},
206+
{
207+
name: "label with no reserved com.docker.*",
208+
label: "com.dockerpsychnotreserved.label=value",
209+
expectedResult: "com.dockerpsychnotreserved.label=value",
210+
},
211+
{
212+
name: "label with no reserved io.docker.*",
213+
label: "io.dockerproject.not=reserved",
214+
expectedResult: "io.dockerproject.not=reserved",
215+
},
216+
{
217+
name: "label with no reserved org.dockerproject.*",
218+
label: "org.docker.not=reserved",
219+
expectedResult: "org.docker.not=reserved",
220+
},
221+
{
222+
name: "label with reserved com.docker.*",
223+
label: "com.docker.feature=enabled",
224+
expectedErr: "label com.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
225+
},
226+
{
227+
name: "label with reserved upcase com.docker.* ",
228+
label: "COM.docker.feature=enabled",
229+
expectedErr: "label COM.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
230+
},
231+
{
232+
name: "label with reserved io.docker.*",
233+
label: "io.docker.configuration=0",
234+
expectedErr: "label io.docker.configuration=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
235+
},
236+
{
237+
name: "label with reserved upcase io.docker.*",
238+
label: "io.DOCKER.CONFIGURATion=0",
239+
expectedErr: "label io.DOCKER.CONFIGURATion=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
240+
},
241+
{
242+
name: "label with reserved org.dockerproject.*",
243+
label: "org.dockerproject.setting=on",
244+
expectedErr: "label org.dockerproject.setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
245+
},
246+
{
247+
name: "label with reserved upcase org.dockerproject.*",
248+
label: "Org.Dockerproject.Setting=on",
249+
expectedErr: "label Org.Dockerproject.Setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
250+
},
186251
}
187-
// Validate it's working with one more
188-
if actual, err := ValidateLabel("key1=value1=value2=value3"); err != nil {
189-
t.Fatalf("Expected [key1=value1=value2=value2], got [%v,%v]", actual, err)
252+
253+
for _, testCase := range testCases {
254+
testCase := testCase
255+
t.Run(testCase.name, func(t *testing.T) {
256+
result, err := ValidateLabel(testCase.label)
257+
258+
if testCase.expectedErr != "" {
259+
assert.Error(t, err, testCase.expectedErr)
260+
} else {
261+
assert.NilError(t, err)
262+
}
263+
if testCase.expectedResult != "" {
264+
assert.Check(t, is.Equal(result, testCase.expectedResult))
265+
}
266+
})
267+
190268
}
191269
}
192270

0 commit comments

Comments
 (0)