authelia/internal/authorization/authorizer.go
James Elliott 1e30b00f7e
fix(validator): misleading warning for empty acl domains (#1898)
This fixes misleading errors for ACL rules with an empty list of domains. This also enables admins to have a default policy with zero ACL rules as long as the default policy is not deny or bypass. It also adds a rule number to all ACL rule related log messages which is the position in the YAML list plus 1. Lastly it adds comprehensive per rule HIT/MISS logging when Authelia trace logging is enabled. This trace logging includes the rule number.
2021-04-14 20:53:23 +10:00

68 lines
1.9 KiB
Go

package authorization
import (
"github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/logging"
)
// Authorizer the component in charge of checking whether a user can access a given resource.
type Authorizer struct {
defaultPolicy Level
rules []*AccessControlRule
}
// NewAuthorizer create an instance of authorizer with a given access control configuration.
func NewAuthorizer(configuration schema.AccessControlConfiguration) *Authorizer {
if logging.Logger().IsLevelEnabled(logrus.TraceLevel) {
return &Authorizer{
defaultPolicy: PolicyToLevel(configuration.DefaultPolicy),
rules: NewAccessControlRules(configuration),
}
}
return &Authorizer{
defaultPolicy: PolicyToLevel(configuration.DefaultPolicy),
rules: NewAccessControlRules(configuration),
}
}
// IsSecondFactorEnabled return true if at least one policy is set to second factor.
func (p *Authorizer) IsSecondFactorEnabled() bool {
if p.defaultPolicy == TwoFactor {
return true
}
for _, rule := range p.rules {
if rule.Policy == TwoFactor {
return true
}
}
return false
}
// GetRequiredLevel retrieve the required level of authorization to access the object.
func (p Authorizer) GetRequiredLevel(subject Subject, object Object) Level {
logger := logging.Logger()
logger.Debugf("Check authorization of subject %s and object %s (method %s).",
subject.String(), object.String(), object.Method)
for _, rule := range p.rules {
if rule.IsMatch(subject, object) {
logger.Tracef(traceFmtACLHitMiss, "HIT", rule.Position, subject.String(), object.String(), object.Method)
return rule.Policy
}
logger.Tracef(traceFmtACLHitMiss, "MISS", rule.Position, subject.String(), object.String(), object.Method)
}
logger.Debugf("No matching rule for subject %s and url %s... Applying default policy.",
subject.String(), object.String())
return p.defaultPolicy
}