2019-04-24 21:52:08 +00:00
|
|
|
package authorization
|
|
|
|
|
|
|
|
import (
|
2022-09-26 04:33:08 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
2021-08-11 01:04:35 +00:00
|
|
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
|
|
|
"github.com/authelia/authelia/v4/internal/logging"
|
2019-04-24 21:52:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Authorizer the component in charge of checking whether a user can access a given resource.
|
|
|
|
type Authorizer struct {
|
2021-03-05 04:18:31 +00:00
|
|
|
defaultPolicy Level
|
|
|
|
rules []*AccessControlRule
|
2022-07-26 05:43:39 +00:00
|
|
|
mfa bool
|
2022-09-26 04:33:08 +00:00
|
|
|
config *schema.Configuration
|
|
|
|
log *logrus.Logger
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
// NewAuthorizer create an instance of authorizer with a given access control config.
|
|
|
|
func NewAuthorizer(config *schema.Configuration) (authorizer *Authorizer) {
|
2022-07-26 05:43:39 +00:00
|
|
|
authorizer = &Authorizer{
|
2022-09-26 04:33:08 +00:00
|
|
|
defaultPolicy: StringToLevel(config.AccessControl.DefaultPolicy),
|
|
|
|
rules: NewAccessControlRules(config.AccessControl),
|
|
|
|
config: config,
|
|
|
|
log: logging.Logger(),
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
|
|
|
|
2022-07-26 05:43:39 +00:00
|
|
|
if authorizer.defaultPolicy == TwoFactor {
|
|
|
|
authorizer.mfa = true
|
|
|
|
|
|
|
|
return authorizer
|
2020-03-06 00:31:09 +00:00
|
|
|
}
|
|
|
|
|
2022-07-26 05:43:39 +00:00
|
|
|
for _, rule := range authorizer.rules {
|
2021-03-05 04:18:31 +00:00
|
|
|
if rule.Policy == TwoFactor {
|
2022-07-26 05:43:39 +00:00
|
|
|
authorizer.mfa = true
|
|
|
|
|
|
|
|
return authorizer
|
2020-03-06 00:31:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
if authorizer.config.IdentityProviders.OIDC != nil {
|
|
|
|
for _, client := range authorizer.config.IdentityProviders.OIDC.Clients {
|
2021-06-18 01:38:01 +00:00
|
|
|
if client.Policy == twoFactor {
|
2022-07-26 05:43:39 +00:00
|
|
|
authorizer.mfa = true
|
|
|
|
|
|
|
|
return authorizer
|
2021-06-18 01:38:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-26 05:43:39 +00:00
|
|
|
return authorizer
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsSecondFactorEnabled return true if at least one policy is set to second factor.
|
|
|
|
func (p Authorizer) IsSecondFactorEnabled() bool {
|
|
|
|
return p.mfa
|
2020-03-06 00:31:09 +00:00
|
|
|
}
|
|
|
|
|
2019-04-24 21:52:08 +00:00
|
|
|
// GetRequiredLevel retrieve the required level of authorization to access the object.
|
2022-09-26 04:33:08 +00:00
|
|
|
func (p Authorizer) GetRequiredLevel(subject Subject, object Object) (hasSubjects bool, level Level) {
|
|
|
|
p.log.Debugf("Check authorization of subject %s and object %s (method %s).",
|
2021-04-14 10:53:23 +00:00
|
|
|
subject.String(), object.String(), object.Method)
|
2019-04-24 21:52:08 +00:00
|
|
|
|
2021-03-05 04:18:31 +00:00
|
|
|
for _, rule := range p.rules {
|
|
|
|
if rule.IsMatch(subject, object) {
|
2022-09-26 04:33:08 +00:00
|
|
|
p.log.Tracef(traceFmtACLHitMiss, "HIT", rule.Position, subject, object, object.Method)
|
2021-04-14 10:53:23 +00:00
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
return rule.HasSubjects, rule.Policy
|
2021-03-05 04:18:31 +00:00
|
|
|
}
|
2021-04-14 10:53:23 +00:00
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
p.log.Tracef(traceFmtACLHitMiss, "MISS", rule.Position, subject, object, object.Method)
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
2020-05-05 19:35:32 +00:00
|
|
|
|
2022-09-26 04:33:08 +00:00
|
|
|
p.log.Debugf("No matching rule for subject %s and url %s (method %s) applying default policy", subject, object, object.Method)
|
2020-02-18 22:15:09 +00:00
|
|
|
|
2022-09-04 22:21:30 +00:00
|
|
|
return false, p.defaultPolicy
|
2019-04-24 21:52:08 +00:00
|
|
|
}
|
2022-02-28 03:15:01 +00:00
|
|
|
|
|
|
|
// GetRuleMatchResults iterates through the rules and produces a list of RuleMatchResult provided a subject and object.
|
|
|
|
func (p Authorizer) GetRuleMatchResults(subject Subject, object Object) (results []RuleMatchResult) {
|
|
|
|
skipped := false
|
|
|
|
|
|
|
|
results = make([]RuleMatchResult, len(p.rules))
|
|
|
|
|
|
|
|
for i, rule := range p.rules {
|
|
|
|
results[i] = RuleMatchResult{
|
|
|
|
Rule: rule,
|
|
|
|
Skipped: skipped,
|
|
|
|
|
2022-10-19 03:09:22 +00:00
|
|
|
MatchDomain: rule.MatchesDomains(subject, object),
|
|
|
|
MatchResources: rule.MatchesResources(subject, object),
|
|
|
|
MatchQuery: rule.MatchesQuery(object),
|
|
|
|
MatchMethods: rule.MatchesMethods(object),
|
|
|
|
MatchNetworks: rule.MatchesNetworks(subject),
|
|
|
|
MatchSubjects: rule.MatchesSubjects(subject),
|
|
|
|
MatchSubjectsExact: rule.MatchesSubjectExact(subject),
|
2022-02-28 03:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
skipped = skipped || results[i].IsMatch()
|
|
|
|
}
|
|
|
|
|
|
|
|
return results
|
|
|
|
}
|