mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
The possible values for ACL policies are now: bypass, one_factor, two_factor, deny. This change also deprecate auth_methods because the method is now associated directly to a resource in the ACLs instead of a domain.
78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
|
|
import { ACLConfiguration, ACLPolicy, ACLRule } from "../configuration/schema/AclConfiguration";
|
|
import { IAuthorizer } from "./IAuthorizer";
|
|
import { Winston } from "../../../types/Dependencies";
|
|
import { MultipleDomainMatcher } from "./MultipleDomainMatcher";
|
|
import { Level } from "./Level";
|
|
|
|
function MatchDomain(actualDomain: string) {
|
|
return function (rule: ACLRule): boolean {
|
|
return MultipleDomainMatcher.match(actualDomain, rule.domain);
|
|
};
|
|
}
|
|
|
|
function MatchResource(actualResource: string) {
|
|
return function (rule: ACLRule): boolean {
|
|
// If resources key is not provided, the rule applies to all resources.
|
|
if (!rule.resources) return true;
|
|
|
|
for (let i = 0; i < rule.resources.length; ++i) {
|
|
const regexp = new RegExp(rule.resources[i]);
|
|
if (regexp.test(actualResource)) return true;
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
|
|
export class Authorizer implements IAuthorizer {
|
|
private logger: Winston;
|
|
private readonly configuration: ACLConfiguration;
|
|
|
|
constructor(configuration: ACLConfiguration, logger_: Winston) {
|
|
this.logger = logger_;
|
|
this.configuration = configuration;
|
|
}
|
|
|
|
private getMatchingUserRules(user: string, domain: string, resource: string): ACLRule[] {
|
|
const userRules = this.configuration.users[user];
|
|
if (!userRules) return [];
|
|
return userRules.filter(MatchDomain(domain)).filter(MatchResource(resource));
|
|
}
|
|
|
|
private getMatchingGroupRules(groups: string[], domain: string, resource: string): ACLRule[] {
|
|
const that = this;
|
|
// There is no ordering between group rules. That is, when a user belongs to 2 groups, there is no
|
|
// guarantee one set of rules has precedence on the other one.
|
|
const groupRules = groups.reduce(function (rules: ACLRule[], group: string) {
|
|
const groupRules = that.configuration.groups[group];
|
|
if (groupRules) rules = rules.concat(groupRules);
|
|
return rules;
|
|
}, []);
|
|
return groupRules.filter(MatchDomain(domain)).filter(MatchResource(resource));
|
|
}
|
|
|
|
private getMatchingAllRules(domain: string, resource: string): ACLRule[] {
|
|
const rules = this.configuration.any;
|
|
if (!rules) return [];
|
|
return rules.filter(MatchDomain(domain)).filter(MatchResource(resource));
|
|
}
|
|
|
|
authorization(domain: string, resource: string, user: string, groups: string[]): Level {
|
|
if (!this.configuration) return Level.BYPASS;
|
|
|
|
const allRules = this.getMatchingAllRules(domain, resource);
|
|
const groupRules = this.getMatchingGroupRules(groups, domain, resource);
|
|
const userRules = this.getMatchingUserRules(user, domain, resource);
|
|
const rules = allRules.concat(groupRules).concat(userRules).reverse();
|
|
const policy = rules.map(r => r.policy).concat([this.configuration.default_policy])[0];
|
|
|
|
if (policy == "bypass") {
|
|
return Level.BYPASS;
|
|
} else if (policy == "one_factor") {
|
|
return Level.ONE_FACTOR;
|
|
} else if (policy == "two_factor") {
|
|
return Level.TWO_FACTOR;
|
|
}
|
|
return Level.DENY;
|
|
}
|
|
} |