forked from containerd/containerd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
identifiers: use common package for identifier validation
A few days ago, we added validation for namespaces. We've decided to expand these naming rules to include containers. To facilitate this, a common package `identifiers` now provides a common validation area. These rules will be extended to apply to task identifiers, snapshot keys and other areas where user-provided identifiers may be used. Signed-off-by: Stephen J Day <stephen.day@docker.com>
- Loading branch information
Showing
9 changed files
with
119 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Package identifiers provides common validation for identifiers, keys and ids | ||
// across containerd. | ||
// | ||
// To allow such identifiers to be used across various contexts safely, the character | ||
// set has been restricted to that defined for domains in RFC 1035, section | ||
// 2.3.1. This will make identifiers safe for use across networks, filesystems | ||
// and other media. | ||
// | ||
// While the character set may expand in the future, we guarantee that the | ||
// identifiers will be safe for use as filesystem path components. | ||
package identifiers | ||
|
||
import ( | ||
"regexp" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
const ( | ||
label = `[A-Za-z][A-Za-z0-9]+(?:[-]+[A-Za-z0-9]+)*` | ||
) | ||
|
||
var ( | ||
// identifierRe validates that a identifier matches valid identifiers. | ||
// | ||
// Rules for domains, defined in RFC 1035, section 2.3.1, are used for | ||
// identifiers. | ||
identifierRe = regexp.MustCompile(reAnchor(label + reGroup("[.]"+reGroup(label)) + "*")) | ||
|
||
errIdentifierInvalid = errors.Errorf("invalid, must match %v", identifierRe) | ||
) | ||
|
||
// IsInvalid return true if the error was due to an invalid identifer. | ||
func IsInvalid(err error) bool { | ||
return errors.Cause(err) == errIdentifierInvalid | ||
} | ||
|
||
// Validate return nil if the string s is a valid identifier. | ||
// | ||
// identifiers must be valid domain identifiers according to RFC 1035, section 2.3.1. To | ||
// enforce case insensitvity, all characters must be lower case. | ||
// | ||
// In general, identifiers that pass this validation, should be safe for use as | ||
// a domain identifier or filesystem path component. | ||
func Validate(s string) error { | ||
if !identifierRe.MatchString(s) { | ||
return errors.Wrapf(errIdentifierInvalid, "identifier %q", s) | ||
} | ||
return nil | ||
} | ||
|
||
func reGroup(s string) string { | ||
return `(?:` + s + `)` | ||
} | ||
|
||
func reAnchor(s string) string { | ||
return `^` + s + `$` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package identifiers | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestValidIdentifiers(t *testing.T) { | ||
for _, input := range []string{ | ||
"default", | ||
"Default", | ||
t.Name(), | ||
"default-default", | ||
"default--default", | ||
"containerd.io", | ||
"foo.boo", | ||
"swarmkit.docker.io", | ||
"zn--e9.org", // or something like it! | ||
} { | ||
t.Run(input, func(t *testing.T) { | ||
if err := Validate(input); err != nil { | ||
t.Fatalf("unexpected error: %v != nil", err) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestInvalidIdentifiers(t *testing.T) { | ||
for _, input := range []string{ | ||
".foo..foo", | ||
"foo/foo", | ||
"foo/..", | ||
"foo..foo", | ||
"foo.-boo", | ||
"-foo.boo", | ||
"foo.boo-", | ||
"foo_foo.boo_underscores", // boo-urns? | ||
} { | ||
|
||
t.Run(input, func(t *testing.T) { | ||
if err := Validate(input); err == nil { | ||
t.Fatal("expected invalid error") | ||
} else if !IsInvalid(err) { | ||
t.Fatal("error should be an invalid identifier error") | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters