Skip to content

Commit

Permalink
feat: reserved-labels rule
Browse files Browse the repository at this point in the history
  • Loading branch information
jimschubert committed Oct 3, 2021
1 parent c1bd9bf commit 69ea38d
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 1 deletion.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* ~COPY: avoid copying entire context (`.`)~. See [this](https://devopsbootcamp.org/dockerfile-security-best-practices/#3-3-build-context-and-dockerignore).
* ~LABEL: recommended open container labels~
* LABEL: correct formatting for container labels. See [this](https://docs.docker.com/config/labels-custom-metadata/)
* `com.docker.*`, `io.docker.*`, and `org.dockerproject.*` namespaces are reserved by Docker for internal use
* ~`com.docker.*`, `io.docker.*`, and `org.dockerproject.*` namespaces are reserved by Docker for internal use~
* Label keys should begin and end with a lower-case letter and should only contain lower-case alphanumeric characters, the period character (.), and the hyphen character (-). Consecutive periods or hyphens are not allowed.
* The period character (.) separates namespace “fields”. Label keys without namespaces are reserved for CLI use, allowing users of the CLI to interactively label Docker objects using shorter typing-friendly strings.
* ENV: recommend single-env formatting
Expand Down
28 changes: 28 additions & 0 deletions docked_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,34 @@ func TestDocked_AnalyzeWithRuleList(t *testing.T) {
want: AnalysisResult{Evaluated: singleValidationSlice("DC:apt-get-update-install", model.Skipped)},
},
// endregion minimize-layers

// region reserved-labels
{
name: "reserved-labels",
args: args{
config: Config{SkipDefaultRules: true, IncludeRules: []string{"D9:reserved-labels"}},
location: "./testdata/reserved_labels.dockerfile",
},
want: AnalysisResult{Evaluated: singleValidationSlice("D9:reserved-labels", model.Failure)},
},
{
name: "reserved-labels [valid]",
args: args{
config: Config{SkipDefaultRules: true, IncludeRules: []string{"D9:reserved-labels"}},
location: "./testdata/minimal_label.dockerfile",
},
want: AnalysisResult{Evaluated: singleValidationSlice("D9:reserved-labels", model.Success)},
},
{
name: "reserved-labels [minimal]",
args: args{
config: Config{SkipDefaultRules: true, IncludeRules: []string{"D9:reserved-labels"}},
location: "./testdata/minimal.dockerfile",
},
// skipped here, because minimal has no labels
want: AnalysisResult{NotEvaluated: singleValidationSlice("D9:reserved-labels", model.Skipped)},
},
// endregion reserved-labels
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ require (
require (
github.com/containerd/typeurl v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,15 @@ github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r
github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible h1:J2OhsbfqoBRRT048iD/tqXBvEQWQATQ8vew6LqQmDSU=
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20200917202933-d0951081b35f/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
Expand Down
65 changes: 65 additions & 0 deletions model/rules/reserved_labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package rules

import (
"strings"

"github.com/jimschubert/docked/model"
"github.com/jimschubert/docked/model/docker/commands"
"github.com/jimschubert/docked/model/validations"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
log "github.com/sirupsen/logrus"
)

func reservedLabels() validations.Rule {
r := validations.MultiContextRule{
Name: "reserved-labels",
Summary: "You can't define labels which are reserved by docker.",
Details: "Docker reserves the following namespaces in labels: `com.docker.*`, `io.docker.*`, and `org.dockerproject.*`.",
Priority: model.CriticalPriority,
Commands: []commands.DockerCommand{commands.Label},
Evaluator: validations.MultiContextFullEvaluator{
Fn: func(mcr *validations.MultiContextRule) *validations.ValidationResult {
if mcr == nil || mcr.ContextCache == nil {
return &validations.ValidationResult{
Result: model.Skipped,
Details: mcr.GetSummary(),
}
}

result := model.Success
validationContexts := make([]validations.ValidationContext, 0)

for _, nodeValidationContext := range *mcr.ContextCache {
which, err := instructions.ParseCommand(&nodeValidationContext.Node)
if err != nil {
log.Warnf("unabel to parse label: %s", nodeValidationContext.Node.Value)
continue
}

if labelCommand, ok := which.(*instructions.LabelCommand); ok && labelCommand != nil {
for _, label := range labelCommand.Labels {
if strings.Contains(label.Key, "com.docker.") ||
strings.Contains(label.Key, "io.docker.") ||
strings.Contains(label.Key, "org.dockerproject.") {
result = model.Failure
nodeValidationContext.Context.CausedFailure = true
}
}
}

validationContexts = append(validationContexts, nodeValidationContext.Context)
}
return &validations.ValidationResult{
Result: result,
Details: mcr.GetSummary(),
Contexts: validationContexts,
}
},
},
}
return &r
}

func init() {
AddRule(reservedLabels())
}
3 changes: 3 additions & 0 deletions testdata/minimal_label.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM scratch

LABEL us.jimschuebrt.yep="YEP"
4 changes: 4 additions & 0 deletions testdata/reserved_labels.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM scratch

LABEL us.jimschuebrt.yep="YEP"
LABEL io.docker.nope="NOPE"

0 comments on commit 69ea38d

Please sign in to comment.