Merge pull request #127 from clems4ever/adapt-acl-config
Adapt ACL configuration to make it more flexiblepull/129/head
commit
26418278bc
|
@ -7,10 +7,10 @@ import {
|
|||
UserLdapConfiguration
|
||||
} from "./Configuration";
|
||||
import Util = require("util");
|
||||
import { ACLAdapter } from "./adapters/ACLAdapter";
|
||||
|
||||
const LDAP_URL_ENV_VARIABLE = "LDAP_URL";
|
||||
|
||||
|
||||
function get_optional<T>(config: object, path: string, default_value: T): T {
|
||||
let entry = default_value;
|
||||
if (ObjectPath.has(config, path)) {
|
||||
|
@ -80,7 +80,7 @@ function adaptFromUserConfiguration(userConfiguration: UserConfiguration): AppCo
|
|||
},
|
||||
logs_level: get_optional<string>(userConfiguration, "logs_level", "info"),
|
||||
notifier: ObjectPath.get<object, NotifierConfiguration>(userConfiguration, "notifier"),
|
||||
access_control: ObjectPath.get<object, ACLConfiguration>(userConfiguration, "access_control"),
|
||||
access_control: ACLAdapter.adapt(userConfiguration.access_control),
|
||||
regulation: userConfiguration.regulation
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { ACLConfiguration } from "../Configuration";
|
||||
|
||||
function clone(obj: any): any {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
const DEFAULT_POLICY = "deny";
|
||||
|
||||
function adaptDefaultPolicy(configuration: ACLConfiguration) {
|
||||
if (!configuration.default_policy)
|
||||
configuration.default_policy = DEFAULT_POLICY;
|
||||
if (configuration.default_policy != "deny" && configuration.default_policy != "allow")
|
||||
configuration.default_policy = DEFAULT_POLICY;
|
||||
}
|
||||
|
||||
function adaptAny(configuration: ACLConfiguration) {
|
||||
if (!configuration.any || !(configuration.any.constructor === Array))
|
||||
configuration.any = [];
|
||||
}
|
||||
|
||||
function adaptGroups(configuration: ACLConfiguration) {
|
||||
if (!configuration.groups || !(configuration.groups.constructor === Object))
|
||||
configuration.groups = {};
|
||||
}
|
||||
|
||||
function adaptUsers(configuration: ACLConfiguration) {
|
||||
if (!configuration.users || !(configuration.users.constructor === Object))
|
||||
configuration.users = {};
|
||||
}
|
||||
|
||||
export class ACLAdapter {
|
||||
static adapt(configuration: ACLConfiguration): ACLConfiguration {
|
||||
if (!configuration) return;
|
||||
|
||||
const newConfiguration: ACLConfiguration = clone(configuration);
|
||||
adaptDefaultPolicy(newConfiguration);
|
||||
adaptAny(newConfiguration);
|
||||
adaptGroups(newConfiguration);
|
||||
adaptUsers(newConfiguration);
|
||||
return newConfiguration;
|
||||
}
|
||||
}
|
|
@ -173,8 +173,8 @@ describe("test access control manager", function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe("check all rules", function () {
|
||||
it("should control access when all rules are defined", function () {
|
||||
describe("check any rules", function () {
|
||||
it("should control access when any rules are defined", function () {
|
||||
configuration.any = [{
|
||||
domain: "home.example.com",
|
||||
policy: "allow",
|
||||
|
@ -307,7 +307,7 @@ describe("test access control manager", function () {
|
|||
Assert(!accessController.isAccessAllowed("home.example.com", "/dev/bob", "john", ["dev"]));
|
||||
});
|
||||
|
||||
it("should control access when allowed at all level and denied at user level", function () {
|
||||
it("should control access when allowed at 'any' level and denied at user level", function () {
|
||||
configuration.any = [{
|
||||
domain: "home.example.com",
|
||||
policy: "allow",
|
||||
|
@ -323,7 +323,7 @@ describe("test access control manager", function () {
|
|||
Assert(!accessController.isAccessAllowed("home.example.com", "/dev/bob", "john", ["dev"]));
|
||||
});
|
||||
|
||||
it("should control access when allowed at all level and denied at group level", function () {
|
||||
it("should control access when allowed at 'any' level and denied at group level", function () {
|
||||
configuration.any = [{
|
||||
domain: "home.example.com",
|
||||
policy: "allow",
|
||||
|
|
|
@ -43,18 +43,20 @@ describe("test config adapter", function () {
|
|||
return yaml_config;
|
||||
}
|
||||
|
||||
it("should read the port from the yaml file", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
yaml_config.port = 7070;
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.equal(config.port, 7070);
|
||||
});
|
||||
describe("port", function () {
|
||||
it("should read the port from the yaml file", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
yaml_config.port = 7070;
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.equal(config.port, 7070);
|
||||
});
|
||||
|
||||
it("should default the port to 8080 if not provided", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
delete yaml_config.port;
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.equal(config.port, 8080);
|
||||
it("should default the port to 8080 if not provided", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
delete yaml_config.port;
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.equal(config.port, 8080);
|
||||
});
|
||||
});
|
||||
|
||||
it("should get the session attributes", function () {
|
||||
|
@ -94,20 +96,51 @@ describe("test config adapter", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("should get the access_control config", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
yaml_config.access_control = {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
users: {},
|
||||
groups: {}
|
||||
};
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.deepEqual(config.access_control, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
users: {},
|
||||
groups: {}
|
||||
} as ACLConfiguration);
|
||||
describe("access_control", function() {
|
||||
it("should adapt access_control when it is already ok", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
yaml_config.access_control = {
|
||||
default_policy: "deny",
|
||||
any: [{
|
||||
domain: "public.example.com",
|
||||
policy: "allow"
|
||||
}],
|
||||
users: {
|
||||
"user": [{
|
||||
domain: "www.example.com",
|
||||
policy: "allow"
|
||||
}]
|
||||
},
|
||||
groups: {}
|
||||
};
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.deepEqual(config.access_control, {
|
||||
default_policy: "deny",
|
||||
any: [{
|
||||
domain: "public.example.com",
|
||||
policy: "allow"
|
||||
}],
|
||||
users: {
|
||||
"user": [{
|
||||
domain: "www.example.com",
|
||||
policy: "allow"
|
||||
}]
|
||||
},
|
||||
groups: {}
|
||||
} as ACLConfiguration);
|
||||
});
|
||||
|
||||
|
||||
it("should adapt access_control when it is empty", function () {
|
||||
const yaml_config = build_yaml_config();
|
||||
yaml_config.access_control = {} as any;
|
||||
const config = ConfigurationAdapter.adapt(yaml_config);
|
||||
Assert.deepEqual(config.access_control, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
users: {},
|
||||
groups: {}
|
||||
} as ACLConfiguration);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
import { ACLAdapter } from "../../../src/lib/configuration/adapters/ACLAdapter";
|
||||
import Assert = require("assert");
|
||||
|
||||
describe("test ACL configuration adapter", function () {
|
||||
|
||||
describe("bad default_policy", function () {
|
||||
it("should adapt a configuration missing default_policy", function () {
|
||||
const userConfiguration: any = {
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
|
||||
it("should adapt a configuration with bad default_policy value", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "anything", // it should be 'allow' or 'deny'
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
|
||||
it("should adapt a configuration with bad default_policy type", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: {}, // it should be 'allow' or 'deny'
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("bad any", function () {
|
||||
it("should adapt a configuration missing any key", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
groups: {},
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
|
||||
it("should adapt a configuration with any not being an array", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
any: "abc",
|
||||
groups: {},
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("bad groups", function () {
|
||||
it("should adapt a configuration missing groups key", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
|
||||
it("should adapt configuration with groups being of wrong type", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: [],
|
||||
users: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("bad users", function () {
|
||||
it("should adapt a configuration missing users key", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {}
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
|
||||
it("should adapt a configuration with users being of wrong type", function () {
|
||||
const userConfiguration: any = {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: []
|
||||
};
|
||||
|
||||
const appConfiguration = ACLAdapter.adapt(userConfiguration);
|
||||
Assert.deepStrictEqual(appConfiguration, {
|
||||
default_policy: "deny",
|
||||
any: [],
|
||||
groups: {},
|
||||
users: {}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,6 +8,7 @@ Feature: User is correctly redirected
|
|||
Scenario: User is redirected to home page after several authentication tries
|
||||
When I visit "https://public.test.local:8080/secret.html"
|
||||
And I login with user "john" and password "badpassword"
|
||||
And I wait for notification to disappear
|
||||
And I clear field "username"
|
||||
And I login with user "john" and password "password"
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
|
|
|
@ -37,6 +37,4 @@ Feature: Authelia regulates authentication to avoid brute force
|
|||
And I click on "Sign in"
|
||||
And I use "REGISTERED" as TOTP token handle
|
||||
And I click on "TOTP"
|
||||
Then I have access to:
|
||||
| url |
|
||||
| https://public.test.local:8080/secret.html |
|
||||
Then I'm redirected to "https://public.test.local:8080/secret.html"
|
|
@ -11,6 +11,15 @@ Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
|||
return this.visit(link);
|
||||
});
|
||||
|
||||
When("I wait for notification to disappear", function() {
|
||||
const that = this;
|
||||
const notificationEl = this.driver.findElement(seleniumWebdriver.By.className("notification"));
|
||||
return this.driver.wait(seleniumWebdriver.until.elementIsVisible(notificationEl), 15000)
|
||||
.then(function() {
|
||||
return that.driver.wait(seleniumWebdriver.until.elementIsNotVisible(notificationEl), 15000);
|
||||
})
|
||||
})
|
||||
|
||||
When("I set field {stringInDoubleQuotes} to {stringInDoubleQuotes}", function (fieldName: string, content: string) {
|
||||
return this.setFieldTo(fieldName, content);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
|||
function (notificationType: string, notificationMessage: string) {
|
||||
const that = this;
|
||||
const notificationEl = this.driver.findElement(seleniumWebdriver.By.className("notification"));
|
||||
return this.driver.wait(seleniumWebdriver.until.elementIsVisible(notificationEl), 2000)
|
||||
return this.driver.wait(seleniumWebdriver.until.elementIsVisible(notificationEl), 5000)
|
||||
.then(function () {
|
||||
return notificationEl.getText();
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue