Add network criteria in ACLs to specify policy based on network subnet.
parent
3c6e2ae448
commit
8a76b5118d
|
@ -35,7 +35,7 @@ Here is the list of the main available features:
|
||||||
* Password reset with identity verification using email.
|
* Password reset with identity verification using email.
|
||||||
* Single-factor only authentication method available.
|
* Single-factor only authentication method available.
|
||||||
* Access restriction after too many authentication attempts.
|
* Access restriction after too many authentication attempts.
|
||||||
* User-defined access control per subdomain and resource.
|
* Fine-grained access control per subdomain, user, resource and network.
|
||||||
* Support of [basic authentication] for endpoints protected by single factor.
|
* Support of [basic authentication] for endpoints protected by single factor.
|
||||||
* High-availability using distributed database and KV store.
|
* High-availability using distributed database and KV store.
|
||||||
* Compatible with Kubernetes ingress-nginx controller out of the box.
|
* Compatible with Kubernetes ingress-nginx controller out of the box.
|
||||||
|
|
|
@ -140,8 +140,15 @@ access_control:
|
||||||
# Rules applied to everyone
|
# Rules applied to everyone
|
||||||
- domain: public.example.com
|
- domain: public.example.com
|
||||||
policy: bypass
|
policy: bypass
|
||||||
|
|
||||||
|
- domain: secure.example.com
|
||||||
|
policy: one_factor
|
||||||
|
# Network based rule, if not provided any network matches.
|
||||||
|
networks:
|
||||||
|
- 192.168.1.0/24
|
||||||
- domain: secure.example.com
|
- domain: secure.example.com
|
||||||
policy: two_factor
|
policy: two_factor
|
||||||
|
|
||||||
- domain: singlefactor.example.com
|
- domain: singlefactor.example.com
|
||||||
policy: one_factor
|
policy: one_factor
|
||||||
|
|
||||||
|
|
|
@ -61,19 +61,8 @@ Here are the versions used for testing in Travis:
|
||||||
|
|
||||||
### How am I supposed to access the subdomains of example.com?
|
### How am I supposed to access the subdomains of example.com?
|
||||||
|
|
||||||
Well, in order to test Authelia, we will fake your browser that example.com is
|
Well, in order to test Authelia, Authelia fakes your browser by adding entries
|
||||||
served by your machine. To do that, open */etc/hosts* and append the following
|
in /etc/hosts when you first source the bootstrap.sh script.
|
||||||
lines:
|
|
||||||
|
|
||||||
127.0.0.1 home.example.com
|
|
||||||
127.0.0.1 public.example.com
|
|
||||||
127.0.0.1 secure.example.com
|
|
||||||
127.0.0.1 dev.example.com
|
|
||||||
127.0.0.1 admin.example.com
|
|
||||||
127.0.0.1 mx1.mail.example.com
|
|
||||||
127.0.0.1 mx2.mail.example.com
|
|
||||||
127.0.0.1 singlefactor.example.com
|
|
||||||
127.0.0.1 login.example.com
|
|
||||||
|
|
||||||
### What should I do if I want to contribute?
|
### What should I do if I want to contribute?
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
kubernetes:
|
||||||
|
image: nginx:alpine
|
||||||
|
volumes:
|
||||||
|
- ./example/compose/nginx/kubernetes/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
- ./example/compose/nginx/kubernetes/ssl:/etc/ssl
|
||||||
|
networks:
|
||||||
|
authelianet:
|
||||||
|
aliases:
|
||||||
|
- public.example.com
|
||||||
|
- secure.example.com
|
||||||
|
- login.example.com
|
||||||
|
- admin.example.com
|
||||||
|
- dev.example.com
|
||||||
|
- mail.example.com
|
||||||
|
# Set the IP to be able to query on port 443
|
||||||
|
ipv4_address: 192.168.240.100
|
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# You can find a documented example of configuration in ./docs/proxies/nginx.md.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
listen 8080 ssl;
|
||||||
|
|
||||||
|
resolver 127.0.0.11 ipv6=off;
|
||||||
|
|
||||||
|
ssl_certificate /etc/ssl/server.crt;
|
||||||
|
ssl_certificate_key /etc/ssl/server.key;
|
||||||
|
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_pass https://192.168.240.1:8080;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICATCCAWoCCQCvH2RvyOshNzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||||
|
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMB4XDTE3MDExNzIzMTc0M1oXDTE4MDExNzIzMTc0M1owRTELMAkG
|
||||||
|
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||||
|
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzZaE
|
||||||
|
4XE1QyFNbrHBHRhSA53anAsJ5mBeG7Om6SdQcZAYahlDWEbtdoY4hy0gPNGcITcW
|
||||||
|
eE+WA+PvNRr7PczKEhneIyUUgV+nrz010fM5JnECPxLTe1oFzl4U8dyYiBpTziNz
|
||||||
|
hiUfq733PRYjcd9BQtcKcN4LdmQvjUHnnQ73TysCAwEAATANBgkqhkiG9w0BAQsF
|
||||||
|
AAOBgQAUFICtbuqXgL4HBRAg7yGbwokoH8Ar1QKZGe+F2WTR8vaDLOYUL7VsltLE
|
||||||
|
EJIGrcfs31nItHOBcLJuflrS8y0CQqes5puRw33LL2usSvO8z2q7JhCx+DSBi6yN
|
||||||
|
RbhcrGOllIdjsrbmd/zAMBVTUyxSisq3Nmk1cZayDvKg+GSAEA==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,11 @@
|
||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEh
|
||||||
|
MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4GNADCBiQKBgQDNloThcTVDIU1uscEdGFIDndqcCwnmYF4bs6bpJ1BxkBhq
|
||||||
|
GUNYRu12hjiHLSA80ZwhNxZ4T5YD4+81Gvs9zMoSGd4jJRSBX6evPTXR8zkmcQI/
|
||||||
|
EtN7WgXOXhTx3JiIGlPOI3OGJR+rvfc9FiNx30FC1wpw3gt2ZC+NQeedDvdPKwID
|
||||||
|
AQABoAAwDQYJKoZIhvcNAQELBQADgYEAmCX60kspIw1Zfb79AQOarFW5Q2K2h5Vx
|
||||||
|
/cRbDyHlKtbmG77EtICccULyqf76B1gNRw5Zq3lSotSUcLzsWcdesXCFDC7k87Qf
|
||||||
|
mpQKPj6GdTYJvdWf8aDwt32tAqWuBIRoAbdx5WbFPPWVfDcm7zDJefBrhNUDH0Qd
|
||||||
|
vcnxjvPMmOM=
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXQIBAAKBgQDNloThcTVDIU1uscEdGFIDndqcCwnmYF4bs6bpJ1BxkBhqGUNY
|
||||||
|
Ru12hjiHLSA80ZwhNxZ4T5YD4+81Gvs9zMoSGd4jJRSBX6evPTXR8zkmcQI/EtN7
|
||||||
|
WgXOXhTx3JiIGlPOI3OGJR+rvfc9FiNx30FC1wpw3gt2ZC+NQeedDvdPKwIDAQAB
|
||||||
|
AoGBAIwGcfkO30UawJ+daDeF4g5ejI/toM+NYWuiwBNbWJoQl+Bj1o+gt4obvxKq
|
||||||
|
tKNX7OxelepZ4oZB0CIuf2LHQfU6cVGdu//or7nfS2FLBYStopZyL6KorZbkqsj1
|
||||||
|
ikQN4GosJQqaYkexnwjItMFaHaRRX6YnIXp42Jl1glitO3+5AkEA+thn/vwFo24I
|
||||||
|
fC+7ORpmLi+BVAkTuhMm+C6TIV6s64B+A5oQ82OBCYK9YCOWmS6JHHFDrxJla+3M
|
||||||
|
2U9KXky63wJBANHQCFCirfuT6esSjbqpCeqtmZG5LWHtL12V9DF7yjHPjmHL9uRu
|
||||||
|
e9W+Uz33IJbqd82gtZ/ARfpYEjD0JEieQTUCQFo872xzDTQ1qSfDo/5u2MNUo5mv
|
||||||
|
ikEuEp7FYnhmrp4poyt4iRCFgy4Ask+bfdmtO/XXaRnZ7FJfQYoLVB2ITNECQQCN
|
||||||
|
gOiauZztl4yj5heAVJFDnWF9To61BOp1C7VtyjdL8NfuTUluNrV+KqapnAp2vhue
|
||||||
|
q0zTOTH47X0XVxFBiLohAkBuQzPey5I3Ui8inE4sDt/fqX8r/GMhBTxIb9KlV/H6
|
||||||
|
jKZNs/83n5/ohaX36er8svW9PB4pcqENZ+kBpvDtKVwS
|
||||||
|
-----END RSA PRIVATE KEY-----
|
|
@ -6,8 +6,12 @@ services:
|
||||||
- ./example/compose/nginx/portal/nginx.conf:/etc/nginx/nginx.conf
|
- ./example/compose/nginx/portal/nginx.conf:/etc/nginx/nginx.conf
|
||||||
- ./example/compose/nginx/portal/ssl:/etc/ssl
|
- ./example/compose/nginx/portal/ssl:/etc/ssl
|
||||||
ports:
|
ports:
|
||||||
- "8080:443"
|
- "8080:8080"
|
||||||
networks:
|
networks:
|
||||||
authelianet:
|
authelianet:
|
||||||
|
aliases:
|
||||||
|
- public.example.com
|
||||||
|
- secure.example.com
|
||||||
|
- login.example.com
|
||||||
# Set the IP to be able to query on port 443
|
# Set the IP to be able to query on port 443
|
||||||
ipv4_address: 192.168.240.100
|
ipv4_address: 192.168.240.100
|
||||||
|
|
|
@ -12,7 +12,7 @@ events {
|
||||||
http {
|
http {
|
||||||
<% if (production) { %>
|
<% if (production) { %>
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 8080 ssl;
|
||||||
server_name login.example.com;
|
server_name login.example.com;
|
||||||
|
|
||||||
resolver 127.0.0.11 ipv6=off;
|
resolver 127.0.0.11 ipv6=off;
|
||||||
|
@ -39,6 +39,10 @@ http {
|
||||||
proxy_set_header X-Original-URI $request_uri;
|
proxy_set_header X-Original-URI $request_uri;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
# Needed for network ACLs to work. It appends the IP of the client to the list of IPs
|
||||||
|
# and allows Authelia to use it to match the network-based ACLs.
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
proxy_intercept_errors on;
|
proxy_intercept_errors on;
|
||||||
|
|
||||||
proxy_pass $backend_endpoint;
|
proxy_pass $backend_endpoint;
|
||||||
|
@ -46,7 +50,7 @@ http {
|
||||||
}
|
}
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 8080 ssl;
|
||||||
server_name login.example.com;
|
server_name login.example.com;
|
||||||
|
|
||||||
resolver 127.0.0.11 ipv6=off;
|
resolver 127.0.0.11 ipv6=off;
|
||||||
|
@ -59,6 +63,22 @@ http {
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
|
|
||||||
|
# Serve the backend API for the portal.
|
||||||
|
location /api {
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Original-URI $request_uri;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# Needed for network ACLs to work. It appends the IP of the client to the list of IPs
|
||||||
|
# and allows Authelia to use it to match the network-based ACLs.
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
|
||||||
|
proxy_pass $backend_endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
# Serves the portal application.
|
# Serves the portal application.
|
||||||
location / {
|
location / {
|
||||||
# Allow websockets for webpack to auto-reload.
|
# Allow websockets for webpack to auto-reload.
|
||||||
|
@ -68,23 +88,12 @@ http {
|
||||||
|
|
||||||
proxy_pass $frontend_endpoint;
|
proxy_pass $frontend_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Serve the backend API for the portal.
|
|
||||||
location /api {
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Original-URI $request_uri;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_intercept_errors on;
|
|
||||||
|
|
||||||
proxy_pass $backend_endpoint;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
# Serves the home page.
|
# Serves the home page.
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 8080 ssl;
|
||||||
server_name home.example.com;
|
server_name home.example.com;
|
||||||
|
|
||||||
resolver 127.0.0.11 ipv6=off;
|
resolver 127.0.0.11 ipv6=off;
|
||||||
|
@ -104,7 +113,7 @@ http {
|
||||||
|
|
||||||
# Example configuration of domains protected by Authelia.
|
# Example configuration of domains protected by Authelia.
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 8080 ssl;
|
||||||
server_name public.example.com
|
server_name public.example.com
|
||||||
admin.example.com
|
admin.example.com
|
||||||
secure.example.com
|
secure.example.com
|
||||||
|
@ -188,21 +197,9 @@ http {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Matches all domains. It redirects to the home page.
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
ssl_certificate /etc/ssl/server.crt;
|
|
||||||
ssl_certificate_key /etc/ssl/server.key;
|
|
||||||
|
|
||||||
return 301 https://home.example.com:8080/;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Fake Web Mail used to receive emails sent by Authelia.
|
# Fake Web Mail used to receive emails sent by Authelia.
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 8080 ssl;
|
||||||
server_name mail.example.com;
|
server_name mail.example.com;
|
||||||
|
|
||||||
resolver 127.0.0.11 ipv6=off;
|
resolver 127.0.0.11 ipv6=off;
|
||||||
|
@ -239,5 +236,16 @@ http {
|
||||||
proxy_pass $upstream_endpoint;
|
proxy_pass $upstream_endpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Matches all domains. It redirects to the home page.
|
||||||
|
server {
|
||||||
|
listen 8080 ssl;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
ssl_certificate /etc/ssl/server.crt;
|
||||||
|
ssl_certificate_key /etc/ssl/server.key;
|
||||||
|
|
||||||
|
return 301 https://home.example.com:8080/;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
# Simulates client 1.
|
||||||
|
client-1:
|
||||||
|
image: sameersbn/squid:3.5.27-1
|
||||||
|
volumes:
|
||||||
|
- ./example/compose/squid/squid.conf:/etc/squid/squid.conf
|
||||||
|
networks:
|
||||||
|
authelianet:
|
||||||
|
# Set the IP to be able to query on port 443
|
||||||
|
ipv4_address: 192.168.240.201
|
||||||
|
client-2:
|
||||||
|
image: sameersbn/squid:3.5.27-1
|
||||||
|
volumes:
|
||||||
|
- ./example/compose/squid/squid.conf:/etc/squid/squid.conf
|
||||||
|
networks:
|
||||||
|
authelianet:
|
||||||
|
# Set the IP to be able to query on port 443
|
||||||
|
ipv4_address: 192.168.240.202
|
File diff suppressed because it is too large
Load Diff
|
@ -4032,6 +4032,14 @@
|
||||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
|
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ip-range-check": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.0.2.tgz",
|
||||||
|
"integrity": "sha1-YFyFloeqTxhGORjUYZDYs2maKTw=",
|
||||||
|
"requires": {
|
||||||
|
"ipaddr.js": "1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ipaddr.js": {
|
"ipaddr.js": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
"express-request-id": "^1.4.0",
|
"express-request-id": "^1.4.0",
|
||||||
"express-session": "^1.14.2",
|
"express-session": "^1.14.2",
|
||||||
"helmet": "^3.12.0",
|
"helmet": "^3.12.0",
|
||||||
|
"ip-range-check": "0.0.2",
|
||||||
"ldapjs": "^1.0.2",
|
"ldapjs": "^1.0.2",
|
||||||
"mongodb": "^3.0.5",
|
"mongodb": "^3.0.5",
|
||||||
"nedb": "^1.8.0",
|
"nedb": "^1.8.0",
|
||||||
|
|
|
@ -39,18 +39,22 @@ async function checkHostsFile() {
|
||||||
const actualEntries = fs.readFileSync("/etc/hosts").toString("utf-8")
|
const actualEntries = fs.readFileSync("/etc/hosts").toString("utf-8")
|
||||||
.split("\n").filter(l => l !== '').map(l => l.split(" ").filter(w => w !== ''));
|
.split("\n").filter(l => l !== '').map(l => l.split(" ").filter(w => w !== ''));
|
||||||
|
|
||||||
await checkAndFixEntry(actualEntries, 'login.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'login.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'admin.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'admin.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'singlefactor.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'singlefactor.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'dev.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'dev.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'home.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'home.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'mx1.mail.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'mx1.mail.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'mx2.mail.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'mx2.mail.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'public.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'public.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'secure.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'secure.example.com', '192.168.240.100');
|
||||||
await checkAndFixEntry(actualEntries, 'mail.example.com', '127.0.0.1');
|
await checkAndFixEntry(actualEntries, 'mail.example.com', '192.168.240.100');
|
||||||
|
|
||||||
await checkAndFixEntry(actualEntries, 'duo.example.com', '192.168.240.100');
|
await checkAndFixEntry(actualEntries, 'duo.example.com', '192.168.240.100');
|
||||||
|
|
||||||
|
// For testing network ACLs.
|
||||||
|
await checkAndFixEntry(actualEntries, 'proxy-client1.example.com', '192.168.240.201');
|
||||||
|
await checkAndFixEntry(actualEntries, 'proxy-client2.example.com', '192.168.240.202');
|
||||||
|
await checkAndFixEntry(actualEntries, 'proxy-client3.example.com', '192.168.240.203');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkKubernetesDependencies() {
|
async function checkKubernetesDependencies() {
|
||||||
|
|
|
@ -14,10 +14,10 @@ describe("authorization/Authorizer", function () {
|
||||||
configuration = undefined;
|
configuration = undefined;
|
||||||
authorizer = new Authorizer(configuration, winston);
|
authorizer = new Authorizer(configuration, winston);
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1", "group2"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1", "group2"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc"}, {user: "user1", groups: ["group1", "group2"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc"}, {user: "user1", groups: ["group1", "group2"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user2", groups: ["group1", "group2"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user2", groups: ["group1", "group2"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "admin.example.com", resource: "/"}, {user: "user3", groups: ["group3"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "admin.example.com", resource: "/"}, {user: "user3", groups: ["group3"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ describe("authorization/Authorizer", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should deny access when no rule is provided", function () {
|
it("should deny access when no rule is provided", function () {
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should control access when multiple domain matcher is provided", function () {
|
it("should control access when multiple domain matcher is provided", function () {
|
||||||
|
@ -46,10 +46,10 @@ describe("authorization/Authorizer", function () {
|
||||||
subject: "user:user1",
|
subject: "user:user1",
|
||||||
resources: [".*"]
|
resources: [".*"]
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "mx1.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "mx1.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "mx1.server.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "mx1.server.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow access to all resources when resources is not provided", function () {
|
it("should allow access to all resources when resources is not provided", function () {
|
||||||
|
@ -58,10 +58,10 @@ describe("authorization/Authorizer", function () {
|
||||||
policy: "two_factor",
|
policy: "two_factor",
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "mx1.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "mx1.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "mx1.server.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "mx1.server.mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "mail.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("check user rules", function () {
|
describe("check user rules", function () {
|
||||||
|
@ -72,9 +72,9 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: [".*"],
|
resources: [".*"],
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/another/resource"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/another/resource"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should deny to other users", function () {
|
it("should deny to other users", function () {
|
||||||
|
@ -84,9 +84,9 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: [".*"],
|
resources: [".*"],
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user2", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user2", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/another/resource"}, {user: "user2", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/another/resource"}, {user: "user2", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"}, {user: "user2", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"}, {user: "user2", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow user access only to specific resources", function () {
|
it("should allow user access only to specific resources", function () {
|
||||||
|
@ -96,16 +96,16 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["/private/.*", "^/begin", "/end$"],
|
resources: ["/private/.*", "^/begin", "/end$"],
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/class"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/class"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/middle/private/class"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/middle/private/class"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/begin"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/begin"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/not/begin"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/not/begin"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc/end"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc/end"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc/end/x"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/abc/end/x"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow access to multiple domains", function () {
|
it("should allow access to multiple domains", function () {
|
||||||
|
@ -125,10 +125,10 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: [".*"],
|
resources: [".*"],
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home1.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.ONE_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home1.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.ONE_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home2.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home2.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home3.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home3.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should apply rules in order", function () {
|
it("should apply rules in order", function () {
|
||||||
|
@ -149,9 +149,9 @@ describe("authorization/Authorizer", function () {
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/poney"}, {user: "user1", groups: ["group1"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/poney"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/private/duck"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/private/duck"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/private/resource"}, {user: "user1", groups: ["group1"]}), Level.ONE_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/my/private/resource"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.ONE_FACTOR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -174,13 +174,13 @@ describe("authorization/Authorizer", function () {
|
||||||
subject: "group:group2"
|
subject: "group:group2"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.TWO_FACTOR);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.ONE_FACTOR);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.ONE_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.DENY);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"},
|
Assert.equal(authorizer.authorization({domain: "another.home.example.com", resource: "/"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.DENY);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -197,13 +197,13 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["^/private$"]
|
resources: ["^/private$"]
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.BYPASS);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
||||||
{user: "user1", groups: ["group1", "group2", "group3"]}), Level.DENY);
|
{user: "user1", groups: ["group1", "group2", "group3"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"},
|
||||||
{user: "user4", groups: ["group5"]}), Level.BYPASS);
|
{user: "user4", groups: ["group5"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private"},
|
||||||
{user: "user4", groups: ["group5"]}), Level.DENY);
|
{user: "user4", groups: ["group5"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -213,9 +213,9 @@ describe("authorization/Authorizer", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow access to anything when no rule is provided", function () {
|
it("should allow access to anything when no rule is provided", function () {
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"}, {user: "user1", groups: ["group1"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "user1", groups: ["group1"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should deny access to one resource when defined", function () {
|
it("should deny access to one resource when defined", function () {
|
||||||
|
@ -225,9 +225,9 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["/test"],
|
resources: ["/test"],
|
||||||
subject: "user:user1"
|
subject: "user:user1"
|
||||||
}];
|
}];
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"}, {user: "user1", groups: ["group1"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/test"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "user1", groups: ["group1"]}), Level.BYPASS);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "user1", groups: ["group1"]}, "127.0.0.1"), Level.BYPASS);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -267,32 +267,32 @@ describe("authorization/Authorizer", function () {
|
||||||
subject: "user:harry"
|
subject: "user:harry"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "admin", groups: ["admins"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "admin", groups: ["admins"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "john", groups: ["dev", "admin-private"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "john", groups: ["dev", "admin-private"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "john", groups: ["dev", "admin-private"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev", "admin-private"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "john", groups: ["dev", "admin-private"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "john", groups: ["dev", "admin-private"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "john", groups: ["dev", "admin-private"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "john", groups: ["dev", "admin-private"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "john", groups: ["dev", "admin-private"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "harry", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "harry", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/public"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "harry", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "harry", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "harry", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/admin"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "harry", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/josh"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "harry", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/john"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "harry", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/private/harry"}, {user: "harry", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow when allowed at group level and denied at user level", function () {
|
it("should allow when allowed at group level and denied at user level", function () {
|
||||||
|
@ -308,8 +308,8 @@ describe("authorization/Authorizer", function () {
|
||||||
subject: "group:dev"
|
subject: "group:dev"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow access when allowed at 'any' level and denied at user level", function () {
|
it("should allow access when allowed at 'any' level and denied at user level", function () {
|
||||||
|
@ -324,8 +324,8 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["^/dev/?.*$"]
|
resources: ["^/dev/?.*$"]
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow access when allowed at 'any' level and denied at group level", function () {
|
it("should allow access when allowed at 'any' level and denied at group level", function () {
|
||||||
|
@ -340,8 +340,8 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["^/dev/?.*$"]
|
resources: ["^/dev/?.*$"]
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}), Level.DENY);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.DENY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should respect rules precedence", function () {
|
it("should respect rules precedence", function () {
|
||||||
|
@ -364,8 +364,36 @@ describe("authorization/Authorizer", function () {
|
||||||
resources: ["^/dev/?.*$"]
|
resources: ["^/dev/?.*$"]
|
||||||
}];
|
}];
|
||||||
|
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}), Level.TWO_FACTOR);
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "127.0.0.1"), Level.TWO_FACTOR);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("check network rules", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
configuration.rules = [{
|
||||||
|
domain: "home.example.com",
|
||||||
|
policy: "one_factor",
|
||||||
|
subject: "user:john",
|
||||||
|
networks: ["192.168.0.0/24", "10.0.0.0/8"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: "home.example.com",
|
||||||
|
policy: "two_factor",
|
||||||
|
subject: "user:john",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: "public.example.com",
|
||||||
|
policy: "bypass",
|
||||||
|
networks: ["10.0.0.0/8"]
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should respect network ranges", function() {
|
||||||
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/john"}, {user: "john", groups: ["dev"]}, "192.168.4.1"), Level.TWO_FACTOR);
|
||||||
|
Assert.equal(authorizer.authorization({domain: "home.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "192.168.0.5"), Level.ONE_FACTOR);
|
||||||
|
Assert.equal(authorizer.authorization({domain: "public.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "10.1.3.0"), Level.BYPASS);
|
||||||
|
Assert.equal(authorizer.authorization({domain: "public.example.com", resource: "/dev/bob"}, {user: "john", groups: ["dev"]}, "11.1.3.0"), Level.DENY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { MultipleDomainMatcher } from "./MultipleDomainMatcher";
|
||||||
import { Level } from "./Level";
|
import { Level } from "./Level";
|
||||||
import { Object } from "./Object";
|
import { Object } from "./Object";
|
||||||
import { Subject } from "./Subject";
|
import { Subject } from "./Subject";
|
||||||
|
const IpRangeCheck = require("ip-range-check");
|
||||||
|
|
||||||
function MatchDomain(actualDomain: string) {
|
function MatchDomain(actualDomain: string) {
|
||||||
return function (rule: ACLRule): boolean {
|
return function (rule: ACLRule): boolean {
|
||||||
|
@ -44,6 +45,16 @@ function MatchSubject(subject: Subject) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function MatchNetworks(ip: string) {
|
||||||
|
return (rule: ACLRule): boolean => {
|
||||||
|
if (!rule.networks) return true; // all networks match
|
||||||
|
|
||||||
|
return rule.networks
|
||||||
|
.map(net => IpRangeCheck(ip, net) as boolean)
|
||||||
|
.reduce((acc, v) => acc || v, false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export class Authorizer implements IAuthorizer {
|
export class Authorizer implements IAuthorizer {
|
||||||
private readonly configuration: ACLConfiguration;
|
private readonly configuration: ACLConfiguration;
|
||||||
|
|
||||||
|
@ -51,13 +62,14 @@ export class Authorizer implements IAuthorizer {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMatchingRules(object: Object, subject: Subject): ACLRule[] {
|
private getMatchingRules(object: Object, subject: Subject, ip: string): ACLRule[] {
|
||||||
const rules = this.configuration.rules;
|
const rules = this.configuration.rules;
|
||||||
if (!rules) return [];
|
if (!rules) return [];
|
||||||
return rules
|
return rules
|
||||||
.filter(MatchDomain(object.domain))
|
.filter(MatchDomain(object.domain))
|
||||||
.filter(MatchResource(object.resource))
|
.filter(MatchResource(object.resource))
|
||||||
.filter(MatchSubject(subject));
|
.filter(MatchSubject(subject))
|
||||||
|
.filter(MatchNetworks(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ruleToLevel(policy: ACLPolicy): Level {
|
private ruleToLevel(policy: ACLPolicy): Level {
|
||||||
|
@ -71,10 +83,10 @@ export class Authorizer implements IAuthorizer {
|
||||||
return Level.DENY;
|
return Level.DENY;
|
||||||
}
|
}
|
||||||
|
|
||||||
authorization(object: Object, subject: Subject): Level {
|
authorization(object: Object, subject: Subject, ip: string): Level {
|
||||||
if (!this.configuration) return Level.BYPASS;
|
if (!this.configuration) return Level.BYPASS;
|
||||||
|
|
||||||
const rules = this.getMatchingRules(object, subject);
|
const rules = this.getMatchingRules(object, subject, ip);
|
||||||
|
|
||||||
return (rules.length > 0)
|
return (rules.length > 0)
|
||||||
? this.ruleToLevel(rules[0].policy) // extract the policy of the first matching rule
|
? this.ruleToLevel(rules[0].policy) // extract the policy of the first matching rule
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default class AuthorizerStub implements IAuthorizer {
|
||||||
this.authorizationMock = Sinon.stub();
|
this.authorizationMock = Sinon.stub();
|
||||||
}
|
}
|
||||||
|
|
||||||
authorization(object: Object, subject: Subject): Level {
|
authorization(object: Object, subject: Subject, ip: string): Level {
|
||||||
return this.authorizationMock(object, subject);
|
return this.authorizationMock(object, subject, ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@ import { Subject } from "./Subject";
|
||||||
import { Object } from "./Object";
|
import { Object } from "./Object";
|
||||||
|
|
||||||
export interface IAuthorizer {
|
export interface IAuthorizer {
|
||||||
authorization(object: Object, subject: Subject): Level;
|
authorization(object: Object, subject: Subject, ip: string): Level;
|
||||||
}
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
|
|
||||||
export type ACLPolicy = "deny" | "bypass" | "one_factor" | "two_factor";
|
export type ACLPolicy = "deny" | "bypass" | "one_factor" | "two_factor";
|
||||||
|
|
||||||
|
export type ACLNetwork = string[];
|
||||||
|
|
||||||
export type ACLRule = {
|
export type ACLRule = {
|
||||||
domain: string;
|
domain: string;
|
||||||
resources?: string[];
|
resources?: string[];
|
||||||
subject?: string;
|
subject?: string;
|
||||||
policy: ACLPolicy;
|
policy: ACLPolicy;
|
||||||
|
networks?: ACLNetwork;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ACLConfiguration {
|
export interface ACLConfiguration {
|
||||||
|
|
|
@ -83,7 +83,7 @@ export default function (vars: ServerVariables) {
|
||||||
groups: authSession.groups
|
groups: authSession.groups
|
||||||
};
|
};
|
||||||
|
|
||||||
const authorizationLevel = vars.authorizer.authorization(resObject, subject);
|
const authorizationLevel = vars.authorizer.authorization(resObject, subject, req.ip);
|
||||||
if (authorizationLevel <= AuthorizationLevel.ONE_FACTOR) {
|
if (authorizationLevel <= AuthorizationLevel.ONE_FACTOR) {
|
||||||
if (IsRedirectionSafe(vars, new URLParse(targetUrl))) {
|
if (IsRedirectionSafe(vars, new URLParse(targetUrl))) {
|
||||||
res.json({redirect: targetUrl});
|
res.json({redirect: targetUrl});
|
||||||
|
|
|
@ -11,21 +11,21 @@ describe('routes/verify/CheckAuthorizations', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
||||||
undefined, Level.NOT_AUTHENTICATED);
|
undefined, "127.0.0.1", Level.NOT_AUTHENTICATED);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authenticated user (1FA)', function() {
|
it('should allow an authenticated user (1FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.ONE_FACTOR);
|
["group1", "group2"], "127.0.0.1", Level.ONE_FACTOR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authenticated user (2FA)', function() {
|
it('should allow an authenticated user (2FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
authorizer.authorizationMock.returns(AuthorizationLevel.BYPASS);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.TWO_FACTOR);
|
["group1", "group2"], "127.0.0.1", Level.TWO_FACTOR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,21 +34,21 @@ describe('routes/verify/CheckAuthorizations', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
||||||
Assert.throws(() => { CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
Assert.throws(() => { CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
||||||
undefined, Level.NOT_AUTHENTICATED) }, NotAuthenticatedError);
|
undefined, "127.0.0.1", Level.NOT_AUTHENTICATED) }, NotAuthenticatedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authenticated user (1FA)', function() {
|
it('should allow an authenticated user (1FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.ONE_FACTOR);
|
["group1", "group2"], "127.0.0.1", Level.ONE_FACTOR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authenticated user (2FA)', function() {
|
it('should allow an authenticated user (2FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.ONE_FACTOR);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.TWO_FACTOR);
|
["group1", "group2"], "127.0.0.1", Level.TWO_FACTOR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -57,21 +57,21 @@ describe('routes/verify/CheckAuthorizations', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
||||||
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
||||||
undefined, Level.NOT_AUTHENTICATED), NotAuthenticatedError);
|
undefined, "127.0.0.1", Level.NOT_AUTHENTICATED), NotAuthenticatedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow an authenticated user (1FA)', function() {
|
it('should not allow an authenticated user (1FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
||||||
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.ONE_FACTOR), NotAuthenticatedError);
|
["group1", "group2"], "127.0.0.1", Level.ONE_FACTOR), NotAuthenticatedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow an authenticated user (2FA)', function() {
|
it('should allow an authenticated user (2FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
authorizer.authorizationMock.returns(AuthorizationLevel.TWO_FACTOR);
|
||||||
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.TWO_FACTOR);
|
["group1", "group2"], "127.0.0.1", Level.TWO_FACTOR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,21 +80,21 @@ describe('routes/verify/CheckAuthorizations', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
||||||
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", undefined,
|
||||||
undefined, Level.NOT_AUTHENTICATED), NotAuthenticatedError);
|
undefined, "127.0.0.1", Level.NOT_AUTHENTICATED), NotAuthenticatedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow an authenticated user (1FA)', function() {
|
it('should not allow an authenticated user (1FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
||||||
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.ONE_FACTOR), NotAuthorizedError);
|
["group1", "group2"], "127.0.0.1", Level.ONE_FACTOR), NotAuthorizedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow an authenticated user (2FA)', function() {
|
it('should not allow an authenticated user (2FA)', function() {
|
||||||
const authorizer = new AuthorizerStub();
|
const authorizer = new AuthorizerStub();
|
||||||
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
authorizer.authorizationMock.returns(AuthorizationLevel.DENY);
|
||||||
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
Assert.throws(() => CheckAuthorizations(authorizer, "public.example.com", "/index.html", "john",
|
||||||
["group1", "group2"], Level.TWO_FACTOR), NotAuthorizedError);
|
["group1", "group2"], "127.0.0.1", Level.TWO_FACTOR), NotAuthorizedError);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -25,11 +25,11 @@ function isAuthorized(
|
||||||
export default function (
|
export default function (
|
||||||
authorizer: IAuthorizer,
|
authorizer: IAuthorizer,
|
||||||
domain: string, resource: string,
|
domain: string, resource: string,
|
||||||
user: string, groups: string[],
|
user: string, groups: string[], ip: string,
|
||||||
authenticationLevel: AuthenticationLevel): AuthorizationLevel {
|
authenticationLevel: AuthenticationLevel): AuthorizationLevel {
|
||||||
|
|
||||||
const authorizationLevel = authorizer
|
const authorizationLevel = authorizer
|
||||||
.authorization({domain, resource}, {user, groups});
|
.authorization({domain, resource}, {user, groups}, ip);
|
||||||
|
|
||||||
if (authorizationLevel == AuthorizationLevel.BYPASS) {
|
if (authorizationLevel == AuthorizationLevel.BYPASS) {
|
||||||
return authorizationLevel;
|
return authorizationLevel;
|
||||||
|
|
|
@ -41,7 +41,7 @@ export default async function(req: Express.Request, res: Express.Response,
|
||||||
const uri = GetHeader(req, HEADER_X_ORIGINAL_URL);
|
const uri = GetHeader(req, HEADER_X_ORIGINAL_URL);
|
||||||
const urlDecomposition = URLDecomposer.fromUrl(uri);
|
const urlDecomposition = URLDecomposer.fromUrl(uri);
|
||||||
const authorizationLevel = CheckAuthorizations(vars.authorizer, urlDecomposition.domain, urlDecomposition.path,
|
const authorizationLevel = CheckAuthorizations(vars.authorizer, urlDecomposition.domain, urlDecomposition.path,
|
||||||
username, groupsAndEmails.groups, Level.ONE_FACTOR);
|
username, groupsAndEmails.groups, req.ip, Level.ONE_FACTOR);
|
||||||
|
|
||||||
if (authorizationLevel > AuthorizationLevel.BYPASS) {
|
if (authorizationLevel > AuthorizationLevel.BYPASS) {
|
||||||
setUserAndGroupsHeaders(res, username, groupsAndEmails.groups);
|
setUserAndGroupsHeaders(res, username, groupsAndEmails.groups);
|
||||||
|
|
|
@ -31,9 +31,9 @@ export default async function (req: Express.Request, res: Express.Response,
|
||||||
const username = authSession.userid;
|
const username = authSession.userid;
|
||||||
const groups = authSession.groups;
|
const groups = authSession.groups;
|
||||||
|
|
||||||
vars.logger.debug(req, "domain=%s, path=%s, user=%s, groups=%s", d.domain,
|
vars.logger.debug(req, "domain=%s, path=%s, user=%s, groups=%s, ip=%s", d.domain,
|
||||||
d.path, (username) ? username : "unknown", (groups instanceof Array && groups.length > 0) ? groups.join(",") : "unknown");
|
d.path, (username) ? username : "unknown", (groups instanceof Array && groups.length > 0) ? groups.join(",") : "unknown", req.ip);
|
||||||
const authorizationLevel = CheckAuthorizations(vars.authorizer, d.domain, d.path, username, groups,
|
const authorizationLevel = CheckAuthorizations(vars.authorizer, d.domain, d.path, username, groups, req.ip,
|
||||||
authSession.authentication_level);
|
authSession.authentication_level);
|
||||||
|
|
||||||
if (authorizationLevel > AuthorizationLevel.BYPASS) {
|
if (authorizationLevel > AuthorizationLevel.BYPASS) {
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
require("chromedriver");
|
require("chromedriver");
|
||||||
import chrome from 'selenium-webdriver/chrome';
|
import chrome from 'selenium-webdriver/chrome';
|
||||||
import SeleniumWebdriver, { WebDriver } from "selenium-webdriver";
|
import SeleniumWebdriver, { WebDriver, ProxyConfig } from "selenium-webdriver";
|
||||||
|
|
||||||
export async function StartDriver() {
|
export async function StartDriver(proxy?: ProxyConfig) {
|
||||||
let options = new chrome.Options();
|
let options = new chrome.Options();
|
||||||
|
|
||||||
if (process.env['HEADLESS'] == 'y') {
|
if (process.env['HEADLESS'] == 'y') {
|
||||||
options = options.headless();
|
options = options.headless();
|
||||||
}
|
}
|
||||||
|
|
||||||
const driver = new SeleniumWebdriver.Builder()
|
let driverBuilder = new SeleniumWebdriver.Builder()
|
||||||
.forBrowser("chrome")
|
.forBrowser("chrome");
|
||||||
.setChromeOptions(options)
|
|
||||||
.build();
|
if (proxy) {
|
||||||
return driver;
|
options = options.addArguments(`--proxy-server=${proxy.httpProxy}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
driverBuilder = driverBuilder.setChromeOptions(options);
|
||||||
|
return await driverBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function StopDriver(driver: WebDriver) {
|
export async function StopDriver(driver: WebDriver) {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import VerifyIsOneTimePasswordView from "../../../helpers/assertions/VerifyIsOne
|
||||||
import ClickOnLink from "../../../helpers/ClickOnLink";
|
import ClickOnLink from "../../../helpers/ClickOnLink";
|
||||||
import VerifyIsUseAnotherMethodView from "../../../helpers/assertions/VerifyIsUseAnotherMethodView";
|
import VerifyIsUseAnotherMethodView from "../../../helpers/assertions/VerifyIsUseAnotherMethodView";
|
||||||
import ClickOnButton from "../../../helpers/behaviors/ClickOnButton";
|
import ClickOnButton from "../../../helpers/behaviors/ClickOnButton";
|
||||||
import VerifyIsSecurityKeyView from "../../../helpers/assertions/VerifyIsSecurityKeyView";
|
|
||||||
import VerifyIsSecondFactorStage from "../../../helpers/assertions/VerifyIsSecondFactorStage";
|
import VerifyIsSecondFactorStage from "../../../helpers/assertions/VerifyIsSecondFactorStage";
|
||||||
import VerifyIsDuoPushNotificationView from "../../../helpers/assertions/VerifyIsDuoPushNotificationView";
|
import VerifyIsDuoPushNotificationView from "../../../helpers/assertions/VerifyIsDuoPushNotificationView";
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { spawn, execSync, ChildProcess } from 'child_process';
|
||||||
import treeKill = require('tree-kill');
|
import treeKill = require('tree-kill');
|
||||||
import Redis, { RedisClient } from 'redis';
|
import Redis, { RedisClient } from 'redis';
|
||||||
import sleep from '../../helpers/utils/sleep';
|
import sleep from '../../helpers/utils/sleep';
|
||||||
|
import DockerEnvironment from '../../helpers/context/DockerEnvironment';
|
||||||
|
|
||||||
let portFowardingProcess: ChildProcess;
|
let portFowardingProcess: ChildProcess;
|
||||||
|
|
||||||
|
@ -78,12 +79,20 @@ async function redisReady(kubernetes: Kubernetes): Promise<void> {
|
||||||
|
|
||||||
function startAutheliaPortForwarding(kubernetes: Kubernetes) {
|
function startAutheliaPortForwarding(kubernetes: Kubernetes) {
|
||||||
// Serve applications on port 8080
|
// Serve applications on port 8080
|
||||||
portFowardingProcess = spawn('kubectl',
|
portFowardingProcess = spawn('kubectl port-forward --address 0.0.0.0 -n authelia service/nginx-ingress-controller-service 8080:443', {
|
||||||
['port-forward', '-n', 'authelia', 'service/nginx-ingress-controller-service', '8080:443'], {
|
shell: true,
|
||||||
env: {KUBECONFIG: kubernetes.kubeConfig, ...process.env}
|
env: {KUBECONFIG: kubernetes.kubeConfig, ...process.env}
|
||||||
});
|
} as any);
|
||||||
|
portFowardingProcess.stdout.pipe(process.stdout);
|
||||||
|
portFowardingProcess.stderr.pipe(process.stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dockerEnv = new DockerEnvironment([
|
||||||
|
'docker-compose.yml',
|
||||||
|
'example/compose/nginx/kubernetes/docker-compose.yml',
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
async function setup() {
|
async function setup() {
|
||||||
let kubernetes: Kubernetes;
|
let kubernetes: Kubernetes;
|
||||||
if (!process.env['KUBECONFIG']) {
|
if (!process.env['KUBECONFIG']) {
|
||||||
|
@ -108,6 +117,8 @@ async function setup() {
|
||||||
});
|
});
|
||||||
await servicesReady(kubernetes);
|
await servicesReady(kubernetes);
|
||||||
|
|
||||||
|
await dockerEnv.start();
|
||||||
|
|
||||||
startAutheliaPortForwarding(kubernetes);
|
startAutheliaPortForwarding(kubernetes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +130,10 @@ async function teardown() {
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (process.env['KUBECONFIG']) return;
|
await dockerEnv.stop();
|
||||||
// await KubernetesManager.delete();
|
|
||||||
|
if (process.env['KUBECONFIG']) return;
|
||||||
|
await KubernetesManager.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
const setup_timeout = 300000;
|
const setup_timeout = 300000;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Basic suite
|
||||||
|
|
||||||
|
This suite has been created to test Authelia with basic feature in a non highly-available setup.
|
||||||
|
Authelia basically use an in-memory cache to store user sessions and persist data on disk instead
|
||||||
|
of using a remote database. Also, the user accounts are stored in file-based database.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
Authelia, nginx, fake webmail for registering devices.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Broad range of tests.
|
|
@ -0,0 +1,64 @@
|
||||||
|
###############################################################
|
||||||
|
# Authelia minimal configuration #
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
port: 9091
|
||||||
|
|
||||||
|
logs_level: debug
|
||||||
|
|
||||||
|
authentication_backend:
|
||||||
|
file:
|
||||||
|
path: ./test/suites/basic/users_database.test.yml
|
||||||
|
|
||||||
|
session:
|
||||||
|
secret: unsecure_session_secret
|
||||||
|
domain: example.com
|
||||||
|
expiration: 3600000 # 1 hour
|
||||||
|
inactivity: 300000 # 5 minutes
|
||||||
|
|
||||||
|
# Configuration of the storage backend used to store data and secrets. i.e. totp data
|
||||||
|
storage:
|
||||||
|
local:
|
||||||
|
path: /tmp/authelia/db
|
||||||
|
|
||||||
|
# Access Control
|
||||||
|
#
|
||||||
|
# Access control is a set of rules you can use to restrict user access to certain
|
||||||
|
# resources.
|
||||||
|
access_control:
|
||||||
|
default_policy: deny
|
||||||
|
rules:
|
||||||
|
- domain: secure.example.com
|
||||||
|
policy: one_factor
|
||||||
|
networks:
|
||||||
|
- 192.168.240.201/32
|
||||||
|
|
||||||
|
- domain: secure.example.com
|
||||||
|
policy: bypass
|
||||||
|
networks:
|
||||||
|
- 192.168.240.202/32
|
||||||
|
- 192.168.240.203/32
|
||||||
|
|
||||||
|
- domain: secure.example.com
|
||||||
|
policy: two_factor
|
||||||
|
|
||||||
|
|
||||||
|
# Configuration of the authentication regulation mechanism.
|
||||||
|
regulation:
|
||||||
|
# Set it to 0 to disable max_retries.
|
||||||
|
max_retries: 3
|
||||||
|
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
|
||||||
|
find_time: 300
|
||||||
|
# The length of time before a banned user can login again.
|
||||||
|
ban_time: 900
|
||||||
|
|
||||||
|
notifier:
|
||||||
|
# Use a SMTP server for sending notifications
|
||||||
|
smtp:
|
||||||
|
username: test
|
||||||
|
password: password
|
||||||
|
secure: false
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 1025
|
||||||
|
sender: admin@example.com
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import fs from 'fs';
|
||||||
|
import { exec } from "../../helpers/utils/exec";
|
||||||
|
import AutheliaServer from "../../helpers/context/AutheliaServer";
|
||||||
|
import DockerEnvironment from "../../helpers/context/DockerEnvironment";
|
||||||
|
|
||||||
|
const autheliaServer = new AutheliaServer(__dirname + '/config.yml', [__dirname + '/users_database.yml']);
|
||||||
|
const dockerEnv = new DockerEnvironment([
|
||||||
|
'docker-compose.yml',
|
||||||
|
'example/compose/nginx/backend/docker-compose.yml',
|
||||||
|
'example/compose/nginx/portal/docker-compose.yml',
|
||||||
|
'example/compose/squid/docker-compose.yml',
|
||||||
|
'example/compose/smtp/docker-compose.yml',
|
||||||
|
])
|
||||||
|
|
||||||
|
async function setup() {
|
||||||
|
await exec(`cp ${__dirname}/users_database.yml ${__dirname}/users_database.test.yml`);
|
||||||
|
await exec('mkdir -p /tmp/authelia/db');
|
||||||
|
await exec('./example/compose/nginx/portal/render.js ' + (fs.existsSync('.suite') ? '': '--production'));
|
||||||
|
await dockerEnv.start();
|
||||||
|
await autheliaServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function teardown() {
|
||||||
|
await autheliaServer.stop();
|
||||||
|
await dockerEnv.stop();
|
||||||
|
await exec('rm -rf /tmp/authelia/db');
|
||||||
|
}
|
||||||
|
|
||||||
|
const setup_timeout = 30000;
|
||||||
|
const teardown_timeout = 30000;
|
||||||
|
|
||||||
|
export {
|
||||||
|
setup,
|
||||||
|
setup_timeout,
|
||||||
|
teardown,
|
||||||
|
teardown_timeout
|
||||||
|
};
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { StartDriver, StopDriver } from "../../../helpers/context/WithDriver";
|
||||||
|
import LoginAndRegisterTotp from "../../../helpers/LoginAndRegisterTotp";
|
||||||
|
import FillLoginPageAndClick from "../../../helpers/FillLoginPageAndClick";
|
||||||
|
import ValidateTotp from "../../../helpers/ValidateTotp";
|
||||||
|
import VerifySecretObserved from "../../../helpers/assertions/VerifySecretObserved";
|
||||||
|
import VisitPageAndWaitUrlIs from "../../../helpers/behaviors/VisitPageAndWaitUrlIs";
|
||||||
|
import VerifyUrlIs from "../../../helpers/assertions/VerifyUrlIs";
|
||||||
|
import VisitPage from "../../../helpers/VisitPage";
|
||||||
|
|
||||||
|
async function createClient(id: number) {
|
||||||
|
return await StartDriver({
|
||||||
|
proxyType: "manual",
|
||||||
|
httpProxy: `http://proxy-client${id}.example.com:3128`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function() {
|
||||||
|
before(async function() {
|
||||||
|
const driver = await StartDriver();
|
||||||
|
this.secret = await LoginAndRegisterTotp(driver, "john", "password", true);
|
||||||
|
if (!this.secret) throw new Error('No secret!');
|
||||||
|
await StopDriver(driver);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Standard client (from public network)", function() {
|
||||||
|
before(async function() {
|
||||||
|
this.driver = await StartDriver();
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async function() {
|
||||||
|
await StopDriver(this.driver);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should require two factor", async function() {
|
||||||
|
await VisitPage(this.driver, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifyUrlIs(this.driver, "https://login.example.com:8080/#/?rd=https://secure.example.com:8080/secret.html");
|
||||||
|
await FillLoginPageAndClick(this.driver, 'john', 'password');
|
||||||
|
await ValidateTotp(this.driver, this.secret);
|
||||||
|
await VerifyUrlIs(this.driver, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifySecretObserved(this.driver);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Client 1 (from network 192.168.240.201/32)", function() {
|
||||||
|
before(async function() {
|
||||||
|
this.client1 = await createClient(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async function() {
|
||||||
|
await StopDriver(this.client1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should require one factor", async function() {
|
||||||
|
await VisitPage(this.client1, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifyUrlIs(this.client1, "https://login.example.com:8080/#/?rd=https://secure.example.com:8080/secret.html");
|
||||||
|
await FillLoginPageAndClick(this.client1, 'john', 'password');
|
||||||
|
await VerifyUrlIs(this.client1, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifySecretObserved(this.client1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Client 2 (from network 192.168.240.202/32)", function() {
|
||||||
|
before(async function() {
|
||||||
|
this.client2 = await createClient(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async function() {
|
||||||
|
await StopDriver(this.client2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should bypass", async function() {
|
||||||
|
await VisitPageAndWaitUrlIs(this.client2, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifyUrlIs(this.client2, "https://secure.example.com:8080/secret.html");
|
||||||
|
await VerifySecretObserved(this.client2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import AutheliaSuite from "../../helpers/context/AutheliaSuite";
|
||||||
|
import { exec } from '../../helpers/utils/exec';
|
||||||
|
import NetworkACLs from "./scenarii/NetworkACLs";
|
||||||
|
|
||||||
|
AutheliaSuite(__dirname, function() {
|
||||||
|
this.timeout(10000);
|
||||||
|
|
||||||
|
beforeEach(async function() {
|
||||||
|
await exec(`cp ${__dirname}/users_database.yml ${__dirname}/users_database.test.yml`);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Network ACLs", NetworkACLs);
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
###############################################################
|
||||||
|
# Users Database #
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
# This file can be used if you do not have an LDAP set up.
|
||||||
|
|
||||||
|
# List of users
|
||||||
|
users:
|
||||||
|
john:
|
||||||
|
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: john.doe@authelia.com
|
||||||
|
groups:
|
||||||
|
- admins
|
||||||
|
- dev
|
||||||
|
|
||||||
|
harry:
|
||||||
|
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: harry.potter@authelia.com
|
||||||
|
groups: []
|
||||||
|
|
||||||
|
bob:
|
||||||
|
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: bob.dylan@authelia.com
|
||||||
|
groups:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
james:
|
||||||
|
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: james.dean@authelia.com
|
Loading…
Reference in New Issue