fix(authorization): subject wildcard domain rule not matching (#4187)
This fixes an issue where the subject wildcard domain rules (those containing {user} and {group}) are not considered matches even though they may be once a user authenticates. Fixes #4186pull/4167/head^2
parent
bcdbedee11
commit
a4edf21320
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// NewAccessControlDomain creates a new SubjectObjectMatcher that matches the domain as a basic string.
|
||||
func NewAccessControlDomain(domain string) AccessControlDomain {
|
||||
func NewAccessControlDomain(domain string) (subjcets bool, rule AccessControlDomain) {
|
||||
m := &AccessControlDomainMatcher{}
|
||||
domain = strings.ToLower(domain)
|
||||
|
||||
|
@ -19,15 +19,15 @@ func NewAccessControlDomain(domain string) AccessControlDomain {
|
|||
m.Name = domain[1:]
|
||||
case strings.HasPrefix(domain, "{user}"):
|
||||
m.UserWildcard = true
|
||||
m.Name = domain[7:]
|
||||
m.Name = domain[6:]
|
||||
case strings.HasPrefix(domain, "{group}"):
|
||||
m.GroupWildcard = true
|
||||
m.Name = domain[8:]
|
||||
m.Name = domain[7:]
|
||||
default:
|
||||
m.Name = domain
|
||||
}
|
||||
|
||||
return AccessControlDomain{m}
|
||||
return m.UserWildcard || m.GroupWildcard, AccessControlDomain{m}
|
||||
}
|
||||
|
||||
// NewAccessControlDomainRegex creates a new SubjectObjectMatcher that matches the domain either in a basic way or
|
||||
|
@ -65,11 +65,19 @@ func (m AccessControlDomainMatcher) IsMatch(domain string, subject Subject) (mat
|
|||
case m.Wildcard:
|
||||
return strings.HasSuffix(domain, m.Name)
|
||||
case m.UserWildcard:
|
||||
return domain == fmt.Sprintf("%s.%s", subject.Username, m.Name)
|
||||
case m.GroupWildcard:
|
||||
prefix, suffix := domainToPrefixSuffix(domain)
|
||||
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
|
||||
return true
|
||||
}
|
||||
|
||||
return suffix == m.Name && utils.IsStringInSliceFold(prefix, subject.Groups)
|
||||
return domain == fmt.Sprintf("%s%s", subject.Username, m.Name)
|
||||
case m.GroupWildcard:
|
||||
if subject.IsAnonymous() && strings.HasSuffix(domain, m.Name) {
|
||||
return true
|
||||
}
|
||||
|
||||
i := strings.Index(domain, ".")
|
||||
|
||||
return domain[i:] == m.Name && utils.IsStringInSliceFold(domain[:i], subject.Groups)
|
||||
default:
|
||||
return strings.EqualFold(domain, m.Name)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ func NewAccessControlRules(config schema.AccessControlConfiguration) (rules []*A
|
|||
func NewAccessControlRule(pos int, rule schema.ACLRule, networksMap map[string][]*net.IPNet, networksCacheMap map[string]*net.IPNet) *AccessControlRule {
|
||||
r := &AccessControlRule{
|
||||
Position: pos,
|
||||
Domains: schemaDomainsToACL(rule.Domains),
|
||||
Methods: schemaMethodsToACL(rule.Methods),
|
||||
Networks: schemaNetworksToACL(rule.Networks, networksMap, networksCacheMap),
|
||||
Subjects: schemaSubjectsToACL(rule.Subjects),
|
||||
|
@ -33,6 +32,7 @@ func NewAccessControlRule(pos int, rule schema.ACLRule, networksMap map[string][
|
|||
r.HasSubjects = true
|
||||
}
|
||||
|
||||
ruleAddDomain(rule.Domains, r)
|
||||
ruleAddDomainRegex(rule.DomainsRegex, r)
|
||||
ruleAddResources(rule.Resources, r)
|
||||
|
||||
|
|
|
@ -151,17 +151,17 @@ func (s *AuthorizerSuite) TestShouldCheckDynamicDomainRules() {
|
|||
WithDefaultPolicy(deny).
|
||||
WithRule(schema.ACLRule{
|
||||
Domains: []string{"{user}.example.com"},
|
||||
Policy: bypass,
|
||||
Policy: oneFactor,
|
||||
}).
|
||||
WithRule(schema.ACLRule{
|
||||
Domains: []string{"{group}.example.com"},
|
||||
Policy: bypass,
|
||||
Policy: oneFactor,
|
||||
}).
|
||||
Build()
|
||||
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://john.example.com/", "GET", Bypass)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://dev.example.com/", "GET", Bypass)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://admins.example.com/", "GET", Bypass)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://john.example.com/", "GET", OneFactor)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://dev.example.com/", "GET", OneFactor)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://admins.example.com/", "GET", OneFactor)
|
||||
tester.CheckAuthorizations(s.T(), UserWithGroups, "https://othergroup.example.com/", "GET", Denied)
|
||||
}
|
||||
|
||||
|
|
|
@ -70,12 +70,16 @@ func schemaSubjectToACLSubject(subjectRule string) (subject SubjectMatcher) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func schemaDomainsToACL(domainRules []string) (domains []AccessControlDomain) {
|
||||
func ruleAddDomain(domainRules []string, rule *AccessControlRule) {
|
||||
for _, domainRule := range domainRules {
|
||||
domains = append(domains, NewAccessControlDomain(domainRule))
|
||||
}
|
||||
subjects, r := NewAccessControlDomain(domainRule)
|
||||
|
||||
return domains
|
||||
rule.Domains = append(rule.Domains, r)
|
||||
|
||||
if !rule.HasSubjects && subjects {
|
||||
rule.HasSubjects = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ruleAddDomainRegex(exps []regexp.Regexp, rule *AccessControlRule) {
|
||||
|
|
Loading…
Reference in New Issue