test(authorization): add missing tests (#5478)
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/5479/head
parent
b1109203ab
commit
e784a72735
|
@ -66,13 +66,13 @@ func (m AccessControlDomainMatcher) IsMatch(domain string, subject Subject) (mat
|
|||
return strings.HasSuffix(domain, m.Name)
|
||||
case m.UserWildcard:
|
||||
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)
|
||||
case m.GroupWildcard:
|
||||
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
|
||||
return true
|
||||
return len(domain) > len(m.Name)
|
||||
}
|
||||
|
||||
i := strings.Index(domain, ".")
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -16,7 +16,8 @@ type RegexpGroupStringSubjectMatcher struct {
|
|||
|
||||
// IsMatch returns true if the underlying pattern matches the input given the subject.
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -24,16 +25,11 @@ func (r RegexpGroupStringSubjectMatcher) IsMatch(input string, subject Subject)
|
|||
return true
|
||||
}
|
||||
|
||||
matches := r.Pattern.FindAllStringSubmatch(input, -1)
|
||||
if matches == nil {
|
||||
if r.SubexpNameUser != -1 && !strings.EqualFold(subject.Username, matches[r.SubexpNameUser]) {
|
||||
return false
|
||||
}
|
||||
|
||||
if r.SubexpNameUser != -1 && !strings.EqualFold(subject.Username, matches[0][r.SubexpNameUser]) {
|
||||
return false
|
||||
}
|
||||
|
||||
if r.SubexpNameGroup != -1 && !utils.IsStringInSliceFold(matches[0][r.SubexpNameGroup], subject.Groups) {
|
||||
if r.SubexpNameGroup != -1 && !utils.IsStringInSliceFold(matches[r.SubexpNameGroup], subject.Groups) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package authorization
|
|||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -217,3 +218,76 @@ func TestIsAuthLevelSufficient(t *testing.T) {
|
|||
assert.False(t, IsAuthLevelSufficient(authentication.OneFactor, 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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue