Explicitly disable wildcard Common Name constraint

This commit is contained in:
Herman Slatman 2022-05-06 13:58:48 +02:00
parent 0f4ffa504a
commit cc26a0b394
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F
4 changed files with 92 additions and 2 deletions

View file

@ -2492,6 +2492,7 @@ func TestNamePolicyEngine_X509_AllAllowed(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
engine, err := New(tt.options...) engine, err := New(tt.options...)
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, engine)
gotErr := engine.IsX509CertificateAllowed(tt.cert) gotErr := engine.IsX509CertificateAllowed(tt.cert)
wantErr := tt.wantErr != nil wantErr := tt.wantErr != nil

View file

@ -28,14 +28,30 @@ func WithAllowLiteralWildcardNames() NamePolicyOption {
func WithPermittedCommonNames(commonNames ...string) NamePolicyOption { func WithPermittedCommonNames(commonNames ...string) NamePolicyOption {
return func(g *NamePolicyEngine) error { return func(g *NamePolicyEngine) error {
g.permittedCommonNames = commonNames normalizedCommonNames := make([]string, len(commonNames))
for i, commonName := range commonNames {
normalizedCommonName, err := normalizeAndValidateCommonName(commonName)
if err != nil {
return fmt.Errorf("cannot parse permitted common name constraint %q: %w", commonName, err)
}
normalizedCommonNames[i] = normalizedCommonName
}
g.permittedCommonNames = normalizedCommonNames
return nil return nil
} }
} }
func WithExcludedCommonNames(commonNames ...string) NamePolicyOption { func WithExcludedCommonNames(commonNames ...string) NamePolicyOption {
return func(g *NamePolicyEngine) error { return func(g *NamePolicyEngine) error {
g.excludedCommonNames = commonNames normalizedCommonNames := make([]string, len(commonNames))
for i, commonName := range commonNames {
normalizedCommonName, err := normalizeAndValidateCommonName(commonName)
if err != nil {
return fmt.Errorf("cannot parse excluded common name constraint %q: %w", commonName, err)
}
normalizedCommonNames[i] = normalizedCommonName
}
g.excludedCommonNames = normalizedCommonNames
return nil return nil
} }
} }
@ -242,6 +258,17 @@ func isIPv4(ip net.IP) bool {
return ip.To4() != nil return ip.To4() != nil
} }
func normalizeAndValidateCommonName(constraint string) (string, error) {
normalizedConstraint := strings.ToLower(strings.TrimSpace(constraint))
if normalizedConstraint == "" {
return "", fmt.Errorf("contraint %q can not be empty or white space string", constraint)
}
if normalizedConstraint == "*" {
return "", fmt.Errorf("wildcard constraint %q is not supported", constraint)
}
return normalizedConstraint, nil
}
func normalizeAndValidateDNSDomainConstraint(constraint string) (string, error) { func normalizeAndValidateDNSDomainConstraint(constraint string) (string, error) {
normalizedConstraint := strings.ToLower(strings.TrimSpace(constraint)) normalizedConstraint := strings.ToLower(strings.TrimSpace(constraint))
if normalizedConstraint == "" { if normalizedConstraint == "" {

View file

@ -8,6 +8,46 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func Test_normalizeAndValidateCommonName(t *testing.T) {
tests := []struct {
name string
constraint string
want string
wantErr bool
}{
{
name: "fail/empty-constraint",
constraint: "",
want: "",
wantErr: true,
},
{
name: "fail/wildcard",
constraint: "*",
want: "",
wantErr: true,
},
{
name: "ok",
constraint: "step",
want: "step",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := normalizeAndValidateCommonName(tt.constraint)
if (err != nil) != tt.wantErr {
t.Errorf("normalizeAndValidateCommonName() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("normalizeAndValidateCommonName() = %v, want %v", got, tt.want)
}
})
}
}
func Test_normalizeAndValidateDNSDomainConstraint(t *testing.T) { func Test_normalizeAndValidateDNSDomainConstraint(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -196,6 +236,24 @@ func TestNew(t *testing.T) {
wantErr bool wantErr bool
} }
var tests = map[string]func(t *testing.T) test{ var tests = map[string]func(t *testing.T) test{
"fail/with-permitted-common-name": func(t *testing.T) test {
return test{
options: []NamePolicyOption{
WithPermittedCommonNames("*"),
},
want: nil,
wantErr: true,
}
},
"fail/with-excluded-common-name": func(t *testing.T) test {
return test{
options: []NamePolicyOption{
WithExcludedCommonNames(""),
},
want: nil,
wantErr: true,
}
},
"fail/with-permitted-dns-domains": func(t *testing.T) test { "fail/with-permitted-dns-domains": func(t *testing.T) test {
return test{ return test{
options: []NamePolicyOption{ options: []NamePolicyOption{

View file

@ -639,5 +639,9 @@ func matchPrincipalConstraint(principal, constraint string) (bool, error) {
// matchCommonNameConstraint performs a string literal equality check against constraint. // matchCommonNameConstraint performs a string literal equality check against constraint.
func matchCommonNameConstraint(commonName, constraint string) (bool, error) { func matchCommonNameConstraint(commonName, constraint string) (bool, error) {
// wildcard constraint is (currently) not supported for common names
if constraint == "*" {
return false, nil
}
return strings.EqualFold(commonName, constraint), nil return strings.EqualFold(commonName, constraint), nil
} }