
Based on feedback, a few adjustments have been made to the identifier requirements. Identifiers that have components that start with a number are now allowed. This violates RFC 1035 but does not do so for dns names practically. A total length, of 76 characters is now also enforced. This decision was completely arbitrary but satifies the requirement for a maximum length. Often, this is used as the maximum length of a line in editors, so it should be a good choice. Signed-off-by: Stephen J Day <stephen.day@docker.com>
69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
// 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.
|
|
//
|
|
// The identifier specification departs from RFC 1035 in that it allows
|
|
// "labels" to start with number and only enforces a total length restriction
|
|
// of 76 characters.
|
|
//
|
|
// While the character set may be expanded in the future, identifiers are
|
|
// guaranteed to be safely used as filesystem path components.
|
|
package identifiers
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
maxLength = 76
|
|
charclass = `[A-Za-z0-9]+`
|
|
label = charclass + `(:?[-]+` + charclass + `)*`
|
|
)
|
|
|
|
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.New("invalid identifier")
|
|
)
|
|
|
|
// 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 len(s) > maxLength {
|
|
return errors.Wrapf(errIdentifierInvalid, "identifier %q greater than maximum length (%d characters)", s, maxLength)
|
|
}
|
|
|
|
if !identifierRe.MatchString(s) {
|
|
return errors.Wrapf(errIdentifierInvalid, "identifier %q must match %v", s, identifierRe)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func reGroup(s string) string {
|
|
return `(?:` + s + `)`
|
|
}
|
|
|
|
func reAnchor(s string) string {
|
|
return `^` + s + `$`
|
|
}
|