test(authorization): add missing tests (#5478)

Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
pull/5479/head
James Elliott 2023-05-24 19:23:46 +10:00 committed by GitHub
parent b1109203ab
commit e784a72735
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 311 additions and 10 deletions

View File

@ -66,13 +66,13 @@ func (m AccessControlDomainMatcher) IsMatch(domain string, subject Subject) (mat
return strings.HasSuffix(domain, m.Name) return strings.HasSuffix(domain, m.Name)
case m.UserWildcard: case m.UserWildcard:
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) { if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
return true return len(domain) > len(m.Name)
} }
return domain == fmt.Sprintf("%s%s", subject.Username, m.Name) return domain == fmt.Sprintf("%s%s", subject.Username, m.Name)
case m.GroupWildcard: case m.GroupWildcard:
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) { if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
return true return len(domain) > len(m.Name)
} }
i := strings.Index(domain, ".") i := strings.Index(domain, ".")

View File

@ -0,0 +1,64 @@
package authorization
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAccessControlDomain_IsMatch(t *testing.T) {
testCases := []struct {
name string
have *AccessControlDomainMatcher
domain string
subject Subject
expected bool
}{
{
"ShouldMatchDomainSuffixUserWildcard",
&AccessControlDomainMatcher{
Name: "-user.domain.com",
UserWildcard: true,
},
"a-user.domain.com",
Subject{},
true,
},
{
"ShouldMatchDomainSuffixGroupWildcard",
&AccessControlDomainMatcher{
Name: "-group.domain.com",
GroupWildcard: true,
},
"a-group.domain.com",
Subject{},
true,
},
{
"ShouldNotMatchExactDomainWithUserWildcard",
&AccessControlDomainMatcher{
Name: "-user.domain.com",
UserWildcard: true,
},
"-user.domain.com",
Subject{},
false,
},
{
"ShouldMatchWildcard",
&AccessControlDomainMatcher{
Name: "user.domain.com",
Wildcard: true,
},
"abc.user.domain.com",
Subject{},
true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, tc.have.IsMatch(tc.domain, tc.subject))
})
}
}

View File

@ -0,0 +1,62 @@
package authorization
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/authelia/authelia/v4/internal/configuration/schema"
)
func TestNewAccessControlQuery(t *testing.T) {
testCases := []struct {
name string
have [][]schema.ACLQueryRule
expected []AccessControlQuery
matches [][]Object
}{
{
"ShouldSkipInvalidTypeEqual",
[][]schema.ACLQueryRule{
{
{Operator: operatorEqual, Key: "example", Value: 1},
},
},
[]AccessControlQuery{{Rules: []ObjectMatcher(nil)}},
[][]Object{{{}}},
},
{
"ShouldSkipInvalidTypePattern",
[][]schema.ACLQueryRule{
{
{Operator: operatorPattern, Key: "example", Value: 1},
},
},
[]AccessControlQuery{{Rules: []ObjectMatcher(nil)}},
[][]Object{{{}}},
},
{
"ShouldSkipInvalidOperator",
[][]schema.ACLQueryRule{
{
{Operator: "nop", Key: "example", Value: 1},
},
},
[]AccessControlQuery{{Rules: []ObjectMatcher(nil)}},
[][]Object{{{}}},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actual := NewAccessControlQuery(tc.have)
assert.Equal(t, tc.expected, actual)
for i, rule := range actual {
for _, object := range tc.matches[i] {
assert.True(t, rule.IsMatch(object))
}
}
})
}
}

View File

@ -0,0 +1,33 @@
package authorization
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAccessControlRule_MatchesSubjectExact(t *testing.T) {
testCases := []struct {
name string
have *AccessControlRule
subject Subject
expected bool
}{
{
"ShouldNotMatchAnonymous",
&AccessControlRule{
Subjects: []AccessControlSubjects{
{[]SubjectMatcher{schemaSubjectToACLSubject("user:john")}},
},
},
Subject{},
false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, tc.have.MatchesSubjectExact(tc.subject))
})
}
}

View File

@ -16,7 +16,8 @@ type RegexpGroupStringSubjectMatcher struct {
// IsMatch returns true if the underlying pattern matches the input given the subject. // IsMatch returns true if the underlying pattern matches the input given the subject.
func (r RegexpGroupStringSubjectMatcher) IsMatch(input string, subject Subject) (match bool) { func (r RegexpGroupStringSubjectMatcher) IsMatch(input string, subject Subject) (match bool) {
if !r.Pattern.MatchString(input) { matches := r.Pattern.FindStringSubmatch(input)
if matches == nil {
return false return false
} }
@ -24,16 +25,11 @@ func (r RegexpGroupStringSubjectMatcher) IsMatch(input string, subject Subject)
return true return true
} }
matches := r.Pattern.FindAllStringSubmatch(input, -1) if r.SubexpNameUser != -1 && !strings.EqualFold(subject.Username, matches[r.SubexpNameUser]) {
if matches == nil {
return false return false
} }
if r.SubexpNameUser != -1 && !strings.EqualFold(subject.Username, matches[0][r.SubexpNameUser]) { if r.SubexpNameGroup != -1 && !utils.IsStringInSliceFold(matches[r.SubexpNameGroup], subject.Groups) {
return false
}
if r.SubexpNameGroup != -1 && !utils.IsStringInSliceFold(matches[0][r.SubexpNameGroup], subject.Groups) {
return false return false
} }

View File

@ -0,0 +1,42 @@
package authorization
import (
"regexp"
"testing"
"github.com/stretchr/testify/assert"
)
func TestRegexpGroupStringSubjectMatcher_IsMatch(t *testing.T) {
testCases := []struct {
name string
have *RegexpGroupStringSubjectMatcher
input string
subject Subject
expected bool
}{
{
"Abc",
&RegexpGroupStringSubjectMatcher{
MustCompileRegexNoPtr(`^(?P<User>[a-zA-Z0-9]+)\.regex.com$`),
1,
0,
},
"example.com",
Subject{Username: "a-user"},
false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, tc.have.IsMatch(tc.input, tc.subject))
})
}
}
func MustCompileRegexNoPtr(input string) regexp.Regexp {
out := regexp.MustCompile(input)
return *out
}

View File

@ -85,3 +85,33 @@ func TestShouldCleanURL(t *testing.T) {
}) })
} }
} }
func TestRuleMatchResult_IsPotentialMatch(t *testing.T) {
testCases := []struct {
name string
have RuleMatchResult
expected bool
}{
{
"ShouldNotMatch",
RuleMatchResult{},
false,
},
{
"ShouldMatch",
RuleMatchResult{nil, true, true, true, true, true, true, true, false},
true,
},
{
"ShouldMatchExact",
RuleMatchResult{nil, true, true, true, true, true, true, true, true},
false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, tc.have.IsPotentialMatch())
})
}
}

View File

@ -2,6 +2,7 @@ package authorization
import ( import (
"net" "net"
"regexp"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -217,3 +218,76 @@ func TestIsAuthLevelSufficient(t *testing.T) {
assert.False(t, IsAuthLevelSufficient(authentication.OneFactor, TwoFactor)) assert.False(t, IsAuthLevelSufficient(authentication.OneFactor, TwoFactor))
assert.True(t, IsAuthLevelSufficient(authentication.TwoFactor, TwoFactor)) assert.True(t, IsAuthLevelSufficient(authentication.TwoFactor, TwoFactor))
} }
func TestStringSliceToRegexpSlice(t *testing.T) {
testCases := []struct {
name string
have []string
expected []regexp.Regexp
err string
}{
{
"ShouldNotParseBadRegex",
[]string{`\q`},
[]regexp.Regexp(nil),
"error parsing regexp: invalid escape sequence: `\\q`",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actual, theError := stringSliceToRegexpSlice(tc.have)
assert.Equal(t, tc.expected, actual)
if tc.err == "" {
assert.NoError(t, theError)
} else {
assert.EqualError(t, theError, tc.err)
}
})
}
}
func TestSchemaNetworksToACL(t *testing.T) {
testCases := []struct {
name string
have []string
globals map[string][]*net.IPNet
cache map[string]*net.IPNet
expected []*net.IPNet
}{
{
"ShouldLoadFromCache",
[]string{"192.168.0.0/24"},
nil,
map[string]*net.IPNet{"192.168.0.0/24": MustParseCIDR("192.168.0.0/24")},
[]*net.IPNet{MustParseCIDR("192.168.0.0/24")},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.globals == nil {
tc.globals = map[string][]*net.IPNet{}
}
if tc.cache == nil {
tc.cache = map[string]*net.IPNet{}
}
actual := schemaNetworksToACL(tc.have, tc.globals, tc.cache)
assert.Equal(t, tc.expected, actual)
})
}
}
func MustParseCIDR(input string) *net.IPNet {
_, out, err := net.ParseCIDR(input)
if err != nil {
panic(err)
}
return out
}