Merge pull request #209 from clems4ever/kube

Create configurations to run Authelia on Kube
pull/219/head
Clément Michaud 2018-04-26 09:03:35 +02:00 committed by GitHub
commit a1786d8108
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
103 changed files with 1473 additions and 152 deletions

View File

@ -43,6 +43,7 @@ as 2nd factor.
* User-defined access control per subdomain and resource. * User-defined access control per subdomain and resource.
* Support of [basic authentication] for endpoints protected by single factor. * Support of [basic authentication] for endpoints protected by single factor.
* High-availability using a highly-available distributed database and KV store. * High-availability using a highly-available distributed database and KV store.
* Compatible with Kubernetes ingress-nginx controller out of the box.
## Deployment ## Deployment
@ -66,6 +67,12 @@ own the configuration file from [config.template.yml] at the root of the repo.
where **/path/to/data/dir** is the directory where all user data will be stored. where **/path/to/data/dir** is the directory where all user data will be stored.
### With Kubernetes
<img src="/images/kube-logo.png" width="24" align="left">
Please refer to the following [README](./example/kube/README.md).
## Getting started ## Getting started
The provided example is docker-based so that you can deploy and test it very The provided example is docker-based so that you can deploy and test it very

View File

@ -11,8 +11,8 @@ services:
- SLAPD_ADDITIONAL_SCHEMAS=openldap - SLAPD_ADDITIONAL_SCHEMAS=openldap
- SLAPD_FORCE_RECONFIGURE=true - SLAPD_FORCE_RECONFIGURE=true
volumes: volumes:
- ./example/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif - ./example/compose/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif
- ./example/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules - ./example/compose/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules
networks: networks:
- example-network - example-network

View File

@ -3,6 +3,6 @@ services:
nginx-authelia: nginx-authelia:
image: nginx:alpine image: nginx:alpine
volumes: volumes:
- ./example/nginx/authelia/nginx.conf:/etc/nginx/nginx.conf - ./example/compose/nginx/authelia/nginx.conf:/etc/nginx/nginx.conf
networks: networks:
- example-network - example-network

View File

@ -0,0 +1,9 @@
version: '2'
services:
nginx-backend:
image: nginx:alpine
volumes:
- ./example/compose/nginx/backend/html:/usr/share/nginx/html
- ./example/compose/nginx/backend/nginx.conf:/etc/nginx/nginx.conf
networks:
- example-network

View File

@ -56,7 +56,7 @@
</li> </li>
</ul> </ul>
You can also log off by visiting the following <a href="https://login.example.com:8080/logout?redirect=https://home.example.com:8080/">link</a>. You can also log off by visiting the following <a href="https://login.example.com:8080/logout?rd=https://home.example.com:8080/">link</a>.
<h1>List of users</h1> <h1>List of users</h1>
Here is the list of credentials you can log in with to test access control.<br/> Here is the list of credentials you can log in with to test access control.<br/>

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -3,8 +3,8 @@ services:
nginx-portal: nginx-portal:
image: nginx:alpine image: nginx:alpine
volumes: volumes:
- ./example/nginx/portal/nginx.conf:/etc/nginx/nginx.conf - ./example/compose/nginx/portal/nginx.conf:/etc/nginx/nginx.conf
- ./example/nginx/portal/ssl:/etc/ssl - ./example/compose/nginx/portal/ssl:/etc/ssl
ports: ports:
- "8080:443" - "8080:443"
networks: networks:

View File

@ -74,11 +74,15 @@ http {
location /auth_verify { location /auth_verify {
internal; internal;
proxy_set_header Host $http_host; 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-Original-URI $request_uri;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass $upstream_verify; proxy_pass $upstream_verify;
} }
@ -96,7 +100,7 @@ http {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
@ -113,7 +117,7 @@ http {
auth_request_set $groups $upstream_http_remote_groups; auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Custom-Forwarded-Groups $groups; proxy_set_header Custom-Forwarded-Groups $groups;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_headers; proxy_pass $upstream_headers;
@ -137,11 +141,15 @@ http {
location /auth_verify { location /auth_verify {
internal; internal;
proxy_set_header Host $http_host; 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-Original-URI $request_uri;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass $upstream_verify; proxy_pass $upstream_verify;
} }
@ -159,7 +167,7 @@ http {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
@ -183,11 +191,15 @@ http {
location /auth_verify { location /auth_verify {
internal; internal;
proxy_set_header Host $http_host; 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-Original-URI $request_uri;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass $upstream_verify; proxy_pass $upstream_verify;
} }
@ -205,7 +217,7 @@ http {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
@ -229,11 +241,15 @@ http {
location /auth_verify { location /auth_verify {
internal; internal;
proxy_set_header Host $http_host; 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-Original-URI $request_uri;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass $upstream_verify; proxy_pass $upstream_verify;
} }
@ -251,7 +267,7 @@ http {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
@ -276,12 +292,18 @@ http {
location /auth_verify { location /auth_verify {
internal; internal;
proxy_set_header Host $http_host; 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-Original-URI $request_uri;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Proxy-Authorization $http_authorization; proxy_set_header X-Forwarded-Proto $scheme;
# This header is required for basic authentication.
proxy_set_header Proxy-Authorization $http_authorization;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass $upstream_verify; proxy_pass $upstream_verify;
} }
@ -299,7 +321,7 @@ http {
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
@ -316,7 +338,7 @@ http {
auth_request_set $groups $upstream_http_remote_groups; auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Custom-Forwarded-Groups $groups; proxy_set_header Custom-Forwarded-Groups $groups;
error_page 401 =302 https://login.example.com:8080?redirect=$redirect; error_page 401 =302 https://login.example.com:8080?rd=$redirect;
error_page 403 = https://login.example.com:8080/error/403; error_page 403 = https://login.example.com:8080/error/403;
proxy_pass $upstream_headers; proxy_pass $upstream_headers;

View File

@ -0,0 +1,114 @@
# Authelia on Kubernetes
Authelia is now available on Kube in order to protect your most critical
applications using 2-factor authentication and Single Sign-On.
This example leverages [ingress-nginx](https://github.com/kubernetes/ingress-nginx)
v0.13.0 to delegate authentications and authorizations to Authelia within
the cluster.
## Getting started
In order to deploy Authelia on Kube, you must have a cluster at hand. If you
don't, please follow the next section otherwise skip it and go
to the next.
### Set up a Kube cluster
Hopefully, spawning a development cluster from scratch has become very
easy lately with the use of **minikube**. This project creates a VM on your
computer and start a Kube cluster inside it. It also configure a CLI called
kubectl so that you can deploy applications in the cluster right away.
Basically, you need to follow the instruction from the [repository](https://github.com/kubernetes/minikube).
It should be a matter of downloading the binary and start the cluster with
two commands:
```
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
minikube start # you can use --vm-driver flag for selecting your hypervisor (virtualbox by default otherwise)
```
After few seconds, your cluster should be working and you should be able to
get access to the cluster by creating a proxy with
```
kubectl proxy
```
and visiting `http://localhost:8001/ui`
### Deploy Authelia
Once the cluster is ready and you can access it, run the following command to
deploy Authelia:
```
./bootstrap.sh
```
In order to visit the test applications that have been deployed to test
Authelia, edit your /etc/hosts and add the following lines replacing the IP
with the IP of your VM given by minikube:
```
192.168.39.26 login.kube.example.com
192.168.39.26 app1.kube.example.com
192.168.39.26 app2.kube.example.com
192.168.39.26 mail.kube.example.com
192.168.39.26 home.kube.example.com
# The domain of the private docker registry holding dev version of Authelia
192.168.39.26 registry.kube.example.com
```
Once done, you can visit http://home.kube.example.com and follow the
instructions written in the page.
## How does it work?
### Authentication via Authelia
In a Kube clusters, the routing logic of requests is handled by ingress
controllers following rules provided by ingress configurations.
In this example, [ingress-nginx](https://github.com/kubernetes/ingress-nginx)
controller has been installed to handle the incoming requests. Some of them
(specified in the ingress configuration) are forwarded to Authelia so that
it can verify whether they are allowed and should reach the protected endpoint.
The authentication is provided at the ingress level by an annotation called
`nginx.ingress.kubernetes.io/auth-url` that is filled with the URL of
Authelia's verification endpoint.
The ingress controller also requires the URL to the
authentication portal so that the user can be redirected in case she is not
yet authenticated.
Those annotations can be seen in `apps/secure-ingress.yml` configuration.
### Production grade infrastructure
What is great with using [ingress-nginx](https://github.com/kubernetes/ingress-nginx)
is that it is compatible with [kube-lego](https://github.com/jetstack/kube-lego)
which removes the usual pain of manual SSL certificate renewals. It uses
letsencrypt to issue and renew certificates every three month without any
manual intervention.
## What do I need know to deploy it in my cluster?
Given your cluster is already made of an LDAP server, a Redis cluster, a Mongo
cluster and a SMTP server, you'll only need to install the ingress-controller
and Authelia whose kubernetes deployment configurations are respectively in
`ingress-controller` and `authelia` directories. A template configuration
is provided there, you just need to create the configmap to use it within
the cluster.
### I'm already using ingress-nginx
If you're already using ingress-nginx as your ingress controller, you only
need to install Authelia with its configuration and that's it!
## Questions
If you have questions about the implementation, please post them on
[![Gitter](https://img.shields.io/gitter/room/badges/shields.svg)](https://gitter.im/authelia/general?utm_source=share-link&utm_medium=link&utm_campaign=share-link)

View File

@ -0,0 +1,33 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: test-app-home
namespace: authelia
labels:
app: test-app-home
spec:
replicas: 1
selector:
matchLabels:
app: test-app-home
template:
metadata:
labels:
app: test-app-home
spec:
containers:
- name: test-app-home
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: app-home-page
mountPath: /usr/share/nginx/html
volumes:
- name: app-home-page
configMap:
name: app-home-page
items:
- key: index.html
path: index.html

View File

@ -0,0 +1,35 @@
<html>
<head>
<title>Authelia Home</title>
</head>
<body>
<h1>Authelia on Kube</h1>
In this example, two applications have been deployed along with Authelia and a fake mailbox in order to confirm your secret registration to Authelia:
<ul>
<li><a href="https://app1.kube.example.com">https://app1.kube.example.com</a></li>
<li><a href="https://app2.kube.example.com">https://app2.kube.example.com</a></li>
<li><a href="http://mail.kube.example.com">http://mail.kube.example.com</a></li>
</ul>
<p>
Please note that <b>app1</b> is publicly available and <b>app2</b> is protected by Authelia.<br/>
<br/>
You can start by visiting <b>app1</b> and then try to access <b>app2</b>. Since <b>app2</b> is protected by Authelia, you will be redirected to Authelia's portal.<br/>
<br/>
If it's the first time you login in this cluster, you'll need to choose your authentication method and follow Authelia's instructions.<br/>
<br/>
Once done, you'll be able to authenticate with your selected second factor method.
</p>
<p>
Here is the list of available users in the LDAP
<ul>
<li><strong>john / password</strong>
<li><strong>bob / password</strong>
<li><strong>harry / password</strong>
</ul>
</p>
<p>
You can always log off by clicking <a href="https://login.kube.example.com/logout?rd=http://home.kube.example.com">here</a>
</p>
</body>
</html>

View File

@ -0,0 +1,12 @@
---
apiVersion: v1
kind: Service
metadata:
name: test-app-home-service
namespace: authelia
spec:
selector:
app: test-app-home
ports:
- protocol: TCP
port: 80

View File

@ -0,0 +1,33 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: test-app1
namespace: authelia
labels:
app: test-app1
spec:
replicas: 1
selector:
matchLabels:
app: test-app1
template:
metadata:
labels:
app: test-app1
spec:
containers:
- name: test-app1
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: app1-page
mountPath: /usr/share/nginx/html
volumes:
- name: app1-page
configMap:
name: app1-page
items:
- key: index.html
path: index.html

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Application 1</title>
</head>
<body>
<h1>Application 1</h1>
<p><a href="http://home.kube.example.com">Go Home</a></p>
</body>
</html>

View File

@ -0,0 +1,12 @@
---
apiVersion: v1
kind: Service
metadata:
name: test-app1-service
namespace: authelia
spec:
selector:
app: test-app1
ports:
- protocol: TCP
port: 80

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvDCCAaQCCQD9zdaObelW0jANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVh
cHAxLmt1YmUuZXhhbXBsZS5jb20wHhcNMTgwMzA0MTUxMDUxWhcNMjgwMzAxMTUx
MDUxWjAgMR4wHAYDVQQDDBVhcHAxLmt1YmUuZXhhbXBsZS5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+v2s9ABHFgxuYFyGkqlbNQ5OtzHAB79lM
sbAMJ9pnMTBA4FXdHgQuQ6Z4F233hMokVfnX9C2KxuLLOQMXJdoVQGytkbGGCzoz
Hz1qXBjDCwQtUGgLJ6zc3C8QKx90zmY0NmH55ttFCQKPHaaxgrS2YXsPzMlQKrgH
drRklfCpnRZWG9/M1YzXOKeT4VuwTsHyeI8tnco11WJLsZwRxc6TjEgNwwBnct8R
/cDhl5guDhqFPgMuBtzRlTVOeZS8NraHL5GRswoUeFJfS2VA3FTABwRWV3J6d5gl
oXpvMzCB01u2jVKLq75g91lGT6I+AVMgSOJG4Nezum7brS7jJjVFAgMBAAEwDQYJ
KoZIhvcNAQELBQADggEBAIFox2Ox/hJqmaSAyE0TqCaLf3UK78z9m/FYUzWoupGE
JAJ83wghVcj7XLKG4x6wN+v342JVa0mQ5X773kqNidHmSdWFPd/hGtx+0dQK3BVV
4CmQCNfA7BZDuxWPW0mcrkKun2aSCq0zjK0f/CzPXZxyPW18EmzSNGkmkXCesM5i
aevdE5PBKikGz4EfzieVTsImdHDfh2/azdRrmSh22x9/tpZy3mMkc5ERpgL2ll+m
HZuZ9FEBQHj92pk2aMBVdxPYpgzWAWbuRUs3vfTIhPlzHcI/ZpE60Ete+yY5lBw/
Gf+ph3HPB8gzSOH/hmcmerX9h6E3MFAncdC4hH3R0j8=
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICZTCCAU0CAQAwIDEeMBwGA1UEAwwVYXBwMS5rdWJlLmV4YW1wbGUuY29tMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvr9rPQARxYMbmBchpKpWzUOT
rcxwAe/ZTLGwDCfaZzEwQOBV3R4ELkOmeBdt94TKJFX51/QtisbiyzkDFyXaFUBs
rZGxhgs6Mx89alwYwwsELVBoCyes3NwvECsfdM5mNDZh+ebbRQkCjx2msYK0tmF7
D8zJUCq4B3a0ZJXwqZ0WVhvfzNWM1zink+FbsE7B8niPLZ3KNdViS7GcEcXOk4xI
DcMAZ3LfEf3A4ZeYLg4ahT4DLgbc0ZU1TnmUvDa2hy+RkbMKFHhSX0tlQNxUwAcE
VldyeneYJaF6bzMwgdNbto1Si6u+YPdZRk+iPgFTIEjiRuDXs7pu260u4yY1RQID
AQABoAAwDQYJKoZIhvcNAQELBQADggEBALcwQAjNjyhMAbGNpFl6iYhzdhUjz02p
hTpc15T+S4PatbgeERYAIuSGxomPHfh+30udxGDCSy730V2urC0eGPjRpnJpGHNG
1Dau0sgi28TQPOqhBcZm0GNHMocc5iG+AxWAsxNwtSH3wRoeUGYXavcm9/tWvYbi
RIKmzXTQKsmY+qhBo3e/phUFuSU8GARYkfDSVqcTM7C3xswgXYcImrkbHAxvsC7+
3nr8ir2K9t2M3QxV7lTybNacuOF84wL93AZDvJ04HctXXgtt2rSI6vxxt18jyrxJ
yHX9ADrAa+jhPAM664SZs/+l0fBbil2UaMPOKXOCmYGuERpWh1HLHKo=
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvr9rPQARxYMbmBchpKpWzUOTrcxwAe/ZTLGwDCfaZzEwQOBV
3R4ELkOmeBdt94TKJFX51/QtisbiyzkDFyXaFUBsrZGxhgs6Mx89alwYwwsELVBo
Cyes3NwvECsfdM5mNDZh+ebbRQkCjx2msYK0tmF7D8zJUCq4B3a0ZJXwqZ0WVhvf
zNWM1zink+FbsE7B8niPLZ3KNdViS7GcEcXOk4xIDcMAZ3LfEf3A4ZeYLg4ahT4D
Lgbc0ZU1TnmUvDa2hy+RkbMKFHhSX0tlQNxUwAcEVldyeneYJaF6bzMwgdNbto1S
i6u+YPdZRk+iPgFTIEjiRuDXs7pu260u4yY1RQIDAQABAoIBAQCwn3ahCUtrZDdM
4T5ZxxCRCJ3aNI8SfBDuHyowV0a4fqd7qz5WfNDKNgIS+T7uDptOgf3SpVr2QasH
GkduS7JgM0NuhJWo1QSTCb5Imfajw7OecfGlQpuh9o/tnMCH3AZvGlwmlkk651jj
REVx4OGMbz8QJkPSY3v8DUKEUQKDSkRhZRhRGDZqbOSeERhOo2O3MqcBaVossYRw
+2Apth2XHg+7mgQjQF+8Z/DeXtLZgOB4VwQ0vkJmSu+FLhWDJqA+WH5JaOrmS3SN
lrPeIEwQMGHmwmIUAaQ7Akkow2xx4VuDRQUcUlitAM21x/MjBdTFbFx975svOiuE
vePNasYBAoGBAOK8e8x0OrqhgsVGWLvJjHnhzTePpemCCB9jRRnTcmMUxXR7moCh
WGgbyQ3+pU15WMxaIpVrGlV3LOwqSEXYspIpBQKv5+kSAaJf/Op3rtuzo57JLMYP
YokMu43ewtSF0CE/7h98vruAYCcDJZs+T7K0lHCBS9pcjhU2MS/ktW2lAoGBANdd
2a1dkEbZyD9NMGD+wWTkctrML3r1ZLy2gq1AX/oyKzdtD6T1nob435RVkyqPGLhr
tEHJuxLiaJlCk5Kd8V84ps0J9SlZTkLzf2ixb06f1YI9ye37UzBr13H59+N6w8Zu
24Gv12ht+WBecWKHgtF16LaCDPYORUMOa3CpgFchAoGBAN6M0Rr6jta3R0tpZBlW
mErd5vd9SQWtO1nLr3zM/f7g2XsfA6T0OXlepHbXFtu3mwBiDIYK7XssEezxB6V/
MK+kEaX0kTZFFVOS0gY2WWyOo7BsmEUDvtz0oXd8SlId0g+A17MSV4hlVnuUbCo3
/DRVaUoQrypzJIcPfTIcVDR9AoGAY3uNrqB2odO9xUfhnhxvtywzxc/l6tVp6CYi
bOc8rnT4M40kWd2/kbdqh7mT1mftUlsmE/GcgZemG41+X46nzYV8v1/nKGeBWDnk
U7cKpHX+iUADg/PBNK/MAHEoSaMOxh21Nc3FIg8Sz6owlAPmsNzXV17xn8NtyRDj
HlKd3yECgYBvB0bV1yXOvfoqGXAyadNJM9eKOuQwhrOJCXzCeMInhUtLpH35kC17
e8rOmoBhV1rLpxlMLV8giyJSRUPoN/TfUHfS2pWfKPobrp50vaUn1hYp6EEr85Qs
DdV2VilJsJN49sMg67GV3Zi4lnjVzYNFegw6y5Xi8l8ulYtzxJnemA==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,33 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: test-app2
namespace: authelia
labels:
app: test-app2
spec:
replicas: 1
selector:
matchLabels:
app: test-app2
template:
metadata:
labels:
app: test-app2
spec:
containers:
- name: test-app2
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: app2-page
mountPath: /usr/share/nginx/html
volumes:
- name: app2-page
configMap:
name: app2-page
items:
- key: index.html
path: index.html

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Application 2</title>
</head>
<body>
<h1>Application 2</h2>
<p><a href="http://home.kube.example.com">Go Home</a></p>
</body>
</html>

View File

@ -0,0 +1,12 @@
---
apiVersion: v1
kind: Service
metadata:
name: test-app2-service
namespace: authelia
spec:
selector:
app: test-app2
ports:
- protocol: TCP
port: 80

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvDCCAaQCCQCE6h+pwV+OTTANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVh
cHAyLmt1YmUuZXhhbXBsZS5jb20wHhcNMTgwMzA0MTUwODUyWhcNMjgwMzAxMTUw
ODUyWjAgMR4wHAYDVQQDDBVhcHAyLmt1YmUuZXhhbXBsZS5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDuVrXRL0i75y0QpbkFM7h1jIwbKOQYdkCR
tAp4aFjRAnHE1DtiXuexoyhs0hbwtxmFF0RpPjOVLvLl/AZt6i65dC5gl1czLmmH
nzjBzUF4jM5qJioP867vR2+SDnD6YWCQrwYG8bHeFKvppAlTY7g8YoTD/b3JNnV1
t+uaPyNKvu33pOP2vP/w/709WFVEwd/334RFF6fjAyYrOgYgvqcgyJ6E6T4cf/Vl
psgLZpJ7o4VoFHq1MdP6Ro+HzKwHUsDbH53U6wISe3dRBmHjTJH2sp1KuJ5gR1Ko
CiiVfq+CCPOxGKNngQe2EqDHmuVuXu30VFu82hznfkXdlhuzTGSfAgMBAAEwDQYJ
KoZIhvcNAQELBQADggEBAEWeTkGmuXnAPU8JGTa+O00kI9nFy10inbiU8O+XuwUL
Cj53CRffbzlsCDRDDxxoBuJ5EvWho5F7MR7A8ZRDfWqLTogvjpVp2YJ+jK/iTbqU
95tCVMByZufa4bHPWmngeYsSu0s0+qRYOeyiCbiFzlzFP3nLSS6aMPwrMUz7/Qp1
XUE1YfyqjKDkvFN4Wq1GKOUZEh4CJh3SuOE/FrRAiaAWnOH4LVDn5TFEbLyEqZLd
BrYEDopRsTpJck/ZEF43GZ0t8Y8CKffpWGV4PvSiUnl/7mKd+i+QsTx8CnnlR9y/
ZvwNRwvRw3uXwkgRinE8wwONAfwB2nIYKyuU9/ODAPs=
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICZTCCAU0CAQAwIDEeMBwGA1UEAwwVYXBwMi5rdWJlLmV4YW1wbGUuY29tMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7la10S9Iu+ctEKW5BTO4dYyM
GyjkGHZAkbQKeGhY0QJxxNQ7Yl7nsaMobNIW8LcZhRdEaT4zlS7y5fwGbeouuXQu
YJdXMy5ph584wc1BeIzOaiYqD/Ou70dvkg5w+mFgkK8GBvGx3hSr6aQJU2O4PGKE
w/29yTZ1dbfrmj8jSr7t96Tj9rz/8P+9PVhVRMHf99+ERRen4wMmKzoGIL6nIMie
hOk+HH/1ZabIC2aSe6OFaBR6tTHT+kaPh8ysB1LA2x+d1OsCEnt3UQZh40yR9rKd
SrieYEdSqAoolX6vggjzsRijZ4EHthKgx5rlbl7t9FRbvNoc535F3ZYbs0xknwID
AQABoAAwDQYJKoZIhvcNAQELBQADggEBANqbKTFSeOf9GRgrNuqRGYYdqSPaoXpu
iSKhJRABj4zMOCJlfDpeMQ8mGfmBUV+IHr+X8/nbMt+OMEf4u1+7Mmz4Zfvkt5gP
MBlYbauVxn/uIYp7aZgBUABC7SvLeITRz4rnQW5SvCNyuJAKQh84uF82g47S7Oaz
2dp6NO1nQ/N9SD6y0CyuIXf1KbSk4+lXa3+rGyqpF1aovpXCgvcA3tWrI/Lg2t5E
uPoiHegKGKyWUZeVh8eKY2ZBCl+uRmwLqTTdzj1HcoK5T1slg0X+K9Q1UsGy23Pw
RHFtGuel8msESgTnspzQF3T1uOscOOiQFG3xnoZtxH92gFT+pI7DoEY=
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA7la10S9Iu+ctEKW5BTO4dYyMGyjkGHZAkbQKeGhY0QJxxNQ7
Yl7nsaMobNIW8LcZhRdEaT4zlS7y5fwGbeouuXQuYJdXMy5ph584wc1BeIzOaiYq
D/Ou70dvkg5w+mFgkK8GBvGx3hSr6aQJU2O4PGKEw/29yTZ1dbfrmj8jSr7t96Tj
9rz/8P+9PVhVRMHf99+ERRen4wMmKzoGIL6nIMiehOk+HH/1ZabIC2aSe6OFaBR6
tTHT+kaPh8ysB1LA2x+d1OsCEnt3UQZh40yR9rKdSrieYEdSqAoolX6vggjzsRij
Z4EHthKgx5rlbl7t9FRbvNoc535F3ZYbs0xknwIDAQABAoIBAFcXgGDsMlvXYfRP
Woi4GZN6xEe4bYEy1O1pKNpO5wWZKxGNrBWKMIgM4tzA+HkFr2Ge2vTKMfc1rLS1
n3PSuzgxaDELnGWrdAyG9ip7Yo02hsbrIzupBCeTpwVsGYSkyLCWBFHNR/2q+Bbs
RiweqFgIeBNWSV+ZctqNVp6Kq87HuYfm/ka8ewVnPYhEMewuE0vqfVjc+fdPr/5I
4uQCCw0/ZTFFP++hkyNsH1ZCdUeT83xbgUwFA0M/3ckjMhzcP7lncq6Gvy8NpBhI
mle/Ev82yaDRl5VKoenpy2d8L+qvIjRbhZiZuTAU9AWRvOKrTMtzKSpyMgWAQZ64
69ResmECgYEA+2Ws4qBiYd3BKF5tc0fWbS0omThT60oLc6aLu5NoryogHHNwPOud
69nCDHSyYp+PqK1HLrOAVoTLmuwyys15juizewO809gYRgXlNZ9TKED8Znyg004o
EQVYxMevq2kfDOBJkMphLXAvFrRFQVB2Km8EfKkrI++1rhxKGJD+FzMCgYEA8rPU
G1v3/uemBxYO/bEmdjvsDfLI7FBYNmjgvBGJocSwb2sG/tRr0imZBPAuDlCKcZ1E
G3rZOJ0VsLzxX5RCVYFKRQvUtbaNO+uDJjChxQ/fQQdbIoaIMjyAVLI7t3Ei4+nY
7eHYjcHeMX54drO8YqQ6OoWZ4x8DI8KNcxBnzOUCgYA+uMRkmn1RS4For/6At5ih
DpZFfA878fJffVr5hrKkmU7/qjGDkYmKEX9fmjHzdznhbLIIzdIkQ+eElI+rl45P
gHFfLLSM6ipMNiZUtZaKwYP3kfqSHbrTXFEkb2m9y3Fqxf60uDl8m7Oz53Ar9oY0
2hP1gkN4KNNcSESYUnyCjwKBgAR9+ZYMDLoGFZeZ++sMJVcY4tSbQsbE8e0H4ej5
Nh/tYQqe44FB80Dvjip+O4v+R6G0tHcBvhWDKsyboqgPOW8Vtocyodw/JbwPLt09
FzFrislMVo58CPdNEV7/8YUCrg+j22UDwhtVlEQ8QASKbRkySvWcVW3TvB4kUrPn
gNRVAoGAI99QzqSRBSLeDgxxRgTM7l5wzyVEmJfmMqQsIbHvYy6zG9iYjFI6UZ8I
U3C/Sdnq7wCWa70b3L8A1iN2fYVwvkEH5WGbEp5B2Cye50avegbPi1FgGw2VSIuS
ysAkWaVJXsb2oQNtjidRuEflhy4nr7eybwa6cgarh7ci3JB+tQ8=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,28 @@
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: insecure-ingress
namespace: authelia
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- secretName: app1-tls
hosts:
- app1.kube.example.com
rules:
- host: app1.kube.example.com
http:
paths:
- path: /
backend:
serviceName: test-app1-service
servicePort: 80
- host: home.kube.example.com
http:
paths:
- path: /
backend:
serviceName: test-app-home-service
servicePort: 80

View File

@ -0,0 +1,23 @@
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: secure-ingress
namespace: authelia
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/auth-url: "http://authelia-service.authelia.svc.cluster.local/api/verify"
nginx.ingress.kubernetes.io/auth-signin: "https://login.kube.example.com"
spec:
tls:
- secretName: app2-tls
hosts:
- app2.kube.example.com
rules:
- host: app2.kube.example.com
http:
paths:
- path: /
backend:
serviceName: test-app2-service
servicePort: 80

View File

@ -0,0 +1,211 @@
###############################################################
# Authelia configuration #
###############################################################
# The port to listen on
port: 80
# Log level
#
# Level of verbosity for logs
logs_level: debug
# Default redirection URL
#
# If user tries to authenticate without any referer, Authelia
# does not know where to redirect the user to at the end of the
# authentication process.
# This parameter allows you to specify the default redirection
# URL Authelia will use in such a case.
#
# Note: this parameter is optional. If not provided, user won't
# be redirected upon successful authentication.
default_redirection_url: https://login.kube.example.com
# LDAP configuration
#
# Example: for user john, the DN will be cn=john,ou=users,dc=example,dc=com
ldap:
# The url of the ldap server
url: ldap://ldap-service
# The base dn for every entries
base_dn: dc=example,dc=com
# An additional dn to define the scope to all users
additional_users_dn: ou=users
# The users filter used to find the user DN
# {0} is a matcher replaced by username.
# 'cn={0}' by default.
users_filter: cn={0}
# An additional dn to define the scope of groups
additional_groups_dn: ou=groups
# The groups filter used for retrieving groups of a given user.
# {0} is a matcher replaced by username.
# {dn} is a matcher replaced by user DN.
# 'member={dn}' by default.
groups_filter: (&(member={dn})(objectclass=groupOfNames))
# The attribute holding the name of the group
group_name_attribute: cn
# The attribute holding the mail address of the user
mail_attribute: mail
# The username and password of the admin user.
user: cn=admin,dc=example,dc=com
password: password
# Authentication methods
#
# Authentication methods can be defined per subdomain.
# There are currently two available methods: "single_factor" and "two_factor"
#
# Note: by default a domain uses "two_factor" method.
#
# Note: 'per_subdomain_methods' is a dictionary where keys must be subdomains and
# values must be one of the two possible methods.
#
# Note: 'per_subdomain_methods' is optional.
#
# Note: authentication_methods is optional. If it is not set all sub-domains
# are protected by two factors.
authentication_methods:
default_method: two_factor
# per_subdomain_methods:
# single_factor.example.com: single_factor
# Access Control
#
# Access control is a set of rules you can use to restrict user access to certain
# resources.
# Any (apply to anyone), per-user or per-group rules can be defined.
#
# If 'access_control' is not defined, ACL rules are disabled and the `allow` default
# policy is applied, i.e., access is allowed to anyone. Otherwise restrictions follow
# the rules defined.
#
# Note: One can use the wildcard * to match any subdomain.
# It must stand at the beginning of the pattern. (example: *.mydomain.com)
#
# Note: You must put the pattern in simple quotes when using the wildcard for the YAML
# to be syntaxically correct.
#
# Definition: A `rule` is an object with the following keys: `domain`, `policy`
# and `resources`.
# - `domain` defines which domain or set of domains the rule applies to.
# - `policy` is the policy to apply to resources. It must be either `allow` or `deny`.
# - `resources` is a list of regular expressions that matches a set of resources to
# apply the policy to.
#
# Note: Rules follow an order of priority defined as follows:
# In each category (`any`, `groups`, `users`), the latest rules have the highest
# priority. In other words, it means that if a given resource matches two rules in the
# same category, the latest one overrides the first one.
# Each category has also its own priority. That is, `users` has the highest priority, then
# `groups` and `any` has the lowest priority. It means if two rules in different categories
# match a given resource, the one in the category with the highest priority overrides the
# other one.
#
access_control:
# Default policy can either be `allow` or `deny`.
# It is the policy applied to any resource if it has not been overriden
# in the `any`, `groups` or `users` category.
default_policy: deny
# The rules that apply to anyone.
# The value is a list of rules.
any:
- domain: '*.example.com'
policy: allow
# Group-based rules. The key is a group name and the value
# is a list of rules.
groups: {}
# User-based rules. The key is a user name and the value
# is a list of rules.
users: {}
# Configuration of session cookies
#
# The session cookies identify the user once logged in.
session:
# The secret to encrypt the session cookie.
secret: unsecure_password
# The time in ms before the cookie expires and session is reset.
expiration: 3600000 # 1 hour
# The inactivity time in ms before the session is reset.
inactivity: 300000 # 5 minutes
# The domain to protect.
# Note: the authenticator must also be in that domain. If empty, the cookie
# is restricted to the subdomain of the issuer.
domain: example.com
# The redis connection details
redis:
host: redis-service
port: 6379
# Configuration of the authentication regulation mechanism.
#
# This mechanism prevents attackers from brute forcing the first factor.
# It bans the user if too many attempts are done in a short period of
# time.
regulation:
# The number of failed login attempts before user is banned.
# Set it to 0 for disabling regulation.
max_retries: 3
# The length of time between login attempts before user is banned.
find_time: 120
# The length of time before a banned user can login again.
ban_time: 300
# Configuration of the storage backend used to store data and secrets.
#
# You must use only an available configuration: local, mongo
storage:
# The directory where the DB files will be saved
# local: /var/lib/authelia/store
# Settings to connect to mongo server
mongo:
url: mongodb://mongo-service
database: authelia
# Configuration of the notification system.
#
# Notifications are sent to users when they require a password reset, a u2f
# registration or a TOTP registration.
# Use only an available configuration: filesystem, gmail
notifier:
# For testing purpose, notifications can be sent in a file
# filesystem:
# filename: /tmp/authelia/notification.txt
# Use your email account to send the notifications. You can use an app password.
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
# email:
# username: authelia@gmail.com
# password: password
# sender: authelia@example.com
# service: gmail
# Use a SMTP server for sending notifications
smtp:
username: test
password: password
secure: false
host: 'mailcatcher-service'
port: 1025
sender: admin@example.com

View File

@ -0,0 +1,34 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: authelia
namespace: authelia
labels:
app: authelia
spec:
replicas: 1
selector:
matchLabels:
app: authelia
template:
metadata:
labels:
app: authelia
spec:
containers:
- name: authelia
image: localhost:5000/authelia:latest
imagePullPolicy: Always
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/authelia
volumes:
- name: config-volume
configMap:
name: authelia-config
items:
- key: config.yml
path: config.yml

View File

@ -0,0 +1,22 @@
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: authelia-ingress
namespace: authelia
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- secretName: authelia-tls
hosts:
- login.kube.example.com
rules:
rules:
- host: login.kube.example.com
http:
paths:
- path: /
backend:
serviceName: authelia-service
servicePort: 80

View File

@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Service
metadata:
name: authelia-service
namespace: authelia
spec:
selector:
app: authelia
ports:
- protocol: TCP
port: 80
targetPort: 80

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICvjCCAaYCCQCJYt0VhOelKjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZs
b2dpbi5rdWJlLmV4YW1wbGUuY29tMB4XDTE4MDMwNDE1MTQzMVoXDTE5MDMwNDE1
MTQzMVowITEfMB0GA1UEAwwWbG9naW4ua3ViZS5leGFtcGxlLmNvbTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIlUUppqDLXQCey+OqC4YIhsZFhus0S
0OcNKBhMcUpKdaqtMf8n8mUtGCByUTf+LMBOyv/WrdcGH5pwlylyERPfDsUFF+5W
LjhHGjMZVKWHOadb25HpO9IZUyyC+5PepfrHlxS5EhTQXymA7yjaXSizfH0uF9Le
mF/RoqArtDfq/2/golcX5YkRt6FwbGrypHG0MuREyMN7H+XmKyC4Cwc1ECbROrWv
C5491Fvw4fW0zWa6M1z56kzA+X7ZleiemiY0vm7hzlm8qztd449pJzweb/Gl2r7n
LdFK+H2jbkn07Z//rwlm8Wlwtb3GLOTgisNv5jALpCDdgiSmUc+G+f0CAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEAUm+gRqlUIGK3UKA+z1Si2EpFeOpSkfBbMjwWQAea
yEY+XtUxQSWmbTx6Cp1miVwSp4ldd0nYVCpesv94FoI3ahktZGafcfviYgyCNPXl
QBREQ3NU9TBLHOmCygL8JlzKLtKABKTiGsDahPmBaMogCbvswFqccZ1EtLRcrI48
FFGS7K4ku561AK+WqFS8yxFKcudJSfmLeEZ0uNazEbh8kIgA5dXtapv6lBhPQ6nN
MPZO321PWGysvj3RXDagYQOPBLX7NhnoFDCoeJKbPQ9lTLOAI0aQnpNoFZnoiWc3
NNLboVSTPQ3jyumAAm7tXS/KWI5Samfp8Cgu7uqhPLdHYg==
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICZjCCAU4CAQAwITEfMB0GA1UEAwwWbG9naW4ua3ViZS5leGFtcGxlLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIlUUppqDLXQCey+OqC4YIh
sZFhus0S0OcNKBhMcUpKdaqtMf8n8mUtGCByUTf+LMBOyv/WrdcGH5pwlylyERPf
DsUFF+5WLjhHGjMZVKWHOadb25HpO9IZUyyC+5PepfrHlxS5EhTQXymA7yjaXSiz
fH0uF9LemF/RoqArtDfq/2/golcX5YkRt6FwbGrypHG0MuREyMN7H+XmKyC4Cwc1
ECbROrWvC5491Fvw4fW0zWa6M1z56kzA+X7ZleiemiY0vm7hzlm8qztd449pJzwe
b/Gl2r7nLdFK+H2jbkn07Z//rwlm8Wlwtb3GLOTgisNv5jALpCDdgiSmUc+G+f0C
AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCHO3wzf1jCOcTmo5NBnCendtEb/IAl
aTBCW3b2+QDRQBGgpQb+JeDjHjIzp5FgzzJVF0XTA8H8jmR56lPTXNlWESzUh1oV
on8QcbPi97nuhIEJNfk7K6gAiK11fULBoNUgI7PsRvAneo2PsCEHGtNsdoU4Ii7A
CuUtKeeZCdbxVM2HradSJ9vvxRmOuIfsQJbUaH0F/Z3A0l0UQbp1AUOWFcJ6XDkX
SgDkMCkXJV53SlwGZm8q6Hj8zwP7Tlk6Nkzcn3ZMDB76o92QSVoi1V07NrvRUvcc
2/eekJBWfpzy1LkaovYGBow4ose8V5nMyH9feXlReCVk2aHYTYbEmQRj
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwiVRSmmoMtdAJ7L46oLhgiGxkWG6zRLQ5w0oGExxSkp1qq0x
/yfyZS0YIHJRN/4swE7K/9at1wYfmnCXKXIRE98OxQUX7lYuOEcaMxlUpYc5p1vb
kek70hlTLIL7k96l+seXFLkSFNBfKYDvKNpdKLN8fS4X0t6YX9GioCu0N+r/b+Ci
VxfliRG3oXBsavKkcbQy5ETIw3sf5eYrILgLBzUQJtE6ta8Lnj3UW/Dh9bTNZroz
XPnqTMD5ftmV6J6aJjS+buHOWbyrO13jj2knPB5v8aXavuct0Ur4faNuSfTtn/+v
CWbxaXC1vcYs5OCKw2/mMAukIN2CJKZRz4b5/QIDAQABAoIBAQCkTwLqcFs6k/Om
5ZBGoPgLs0pdmRGIR7lnIjphvihPUI8fIK9km8FIoY5+v2E/ey0SoFyrg1vi1Drg
8RLtr60GXUxZsALd4jABzyM8Rd7erIA9xL8iUPsgx/Adhsk2D0P35v1VO4Ay/1ra
fFVsBMq9DJJ6Ow1MmLjqtzfkSLigbRRSPwaS081oW570cg9ABc1Cpp9sdLjG2Il0
Eyet0qe0fiJAOlnE+tMRls9AoGYLG61msb1OhkpKfaNdw6IolkSGQZDqqsf1cSE3
I7ypsE0LLtDeCU/jsUMjDHBwerqTANUHO5Y4PZ3hSJN55p/IGEiUeAMYs+dqtFx8
xc/KfV2BAoGBAP+2nR73QjWdqJ0A4IdRq811eZM+NTWbobKRSay+T3Ve8QcRqc41
YXJYqRhX23me3p9CxHDMVoXYtWS1nlXnsOxk60idffEIf5tbjzEYi1dIdLoCfbVW
dZS1ZsZh4GZ3If8e78R+9IBQ6+SFvsVocRXpkf6VHp6jB3mXH0XCyNXdAoGBAMJd
CORqmdrmCbfZnn7G3cZ7kTS05inMkj/svtDb+tkcy2x+pfL9y+SfeAf+o5AGl6pN
CsiiGJTVj/Wtic572zdT198UFyWjDrgYUMNzvL9430hnZkySF/E8f1XHD8Sb4P65
CVGJeVKuEHTXcas9F3VYln/87WGDVrtVowO408KhAoGACFiSej9BtvRFW5J6wY/l
1pfd9vNR00UYGvbo+61edIs7vKpT63oMiynfov7DGA4aYAJS3QeeT1IKYZYX69/b
A2wrzbvuL17Co3RykPynF5syzBtmtPN0dP0StKjfJRkAUA5XbwdhvYpmmJfQ6SqG
fluYO0HstOrHRK2tBJ7d5TUCgYBt9mDPihgdpkQdRfvL0gsq/kH6xdXqFBkyHWkf
lTVonEfizAxrW3d9k1M/gqtbEr+/0/Kj7EFoAyN9ZX8v2Rb/SGo7hYxK+OOc9/TJ
f7NryKDav9U6wPTWwNlx2DttiptSwbEp9lMzmdMpp7JhpSCefU44fwp2Pu5U8nBV
7L2xwQKBgHln1Y4EZ9SQDA0jFiSUNoCkkUJFox8752FsPolCna3GmBAYJn8+Oumj
VbLPJvJxHmXMn+JN+rxxFve/DxV1TJqsan5F7i5xp0Ck4rm+TU0ZxvHW75yNG8ER
bNGkvo1dme3fh8YETH6sqePTtbJ04hMfNhn1/iu89s6+ft4cqnpk
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,61 @@
#!/bin/bash
start_apps() {
# Create the test application pages
kubectl create configmap app1-page --namespace=authelia --from-file=apps/app1/index.html
kubectl create configmap app2-page --namespace=authelia --from-file=apps/app2/index.html
kubectl create configmap app-home-page --namespace=authelia --from-file=apps/app-home/index.html
# Create TLS certificate and key for HTTPS termination
kubectl create secret generic app1-tls --namespace=authelia --from-file=apps/app1/ssl/tls.key --from-file=apps/app1/ssl/tls.crt
kubectl create secret generic app2-tls --namespace=authelia --from-file=apps/app2/ssl/tls.key --from-file=apps/app2/ssl/tls.crt
kubectl create secret generic authelia-tls --namespace=authelia --from-file=authelia/ssl/tls.key --from-file=authelia/ssl/tls.crt
# Spawn the applications
kubectl apply -f apps
kubectl apply -f apps/app1
kubectl apply -f apps/app2
kubectl apply -f apps/app-home
}
start_ingress_controller() {
kubectl apply -f ingress-controller
}
start_authelia() {
kubectl create configmap authelia-config --namespace=authelia --from-file=authelia/configs/config.yml
kubectl apply -f authelia
}
# Spawn Redis and Mongo as backend for Authelia
# Please note they are not configured to be distributed on several machines
start_storage() {
kubectl apply -f storage
}
# Create a fake mailbox to catch emails sent by Authelia
start_mailcatcher() {
kubectl apply -f mailcatcher
}
start_ldap() {
kubectl apply -f ldap
}
start_docker_registry() {
kubectl apply -f docker-registry
}
# Create the Authelia namespace in the cluster
create_namespace() {
kubectl apply -f namespace.yml
}
create_namespace
start_docker_registry
start_storage
start_ldap
start_mailcatcher
start_ingress_controller
start_authelia
start_apps

View File

@ -0,0 +1,9 @@
#!/bin/bash
build_and_push_authelia() {
cd ../../
docker build -t registry.kube.example.com:80/authelia .
docker push registry.kube.example.com:80/authelia
}
build_and_push_authelia

View File

@ -0,0 +1,35 @@
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: kube-registry-proxy
namespace: kube-system
labels:
k8s-app: kube-registry-proxy
kubernetes.io/cluster-service: "true"
version: v0.4
spec:
template:
metadata:
labels:
k8s-app: kube-registry-proxy
kubernetes.io/name: "kube-registry-proxy"
kubernetes.io/cluster-service: "true"
version: v0.4
spec:
containers:
- name: kube-registry-proxy
image: gcr.io/google_containers/kube-registry-proxy:0.4
resources:
limits:
cpu: 100m
memory: 50Mi
env:
- name: REGISTRY_HOST
value: kube-registry.kube-system.svc.cluster.local
- name: REGISTRY_PORT
value: "5000"
ports:
- name: registry
containerPort: 80
hostPort: 5000

View File

@ -0,0 +1,18 @@
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: registry-ingress
namespace: kube-system
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-body-size: 100m # Avoid 413 Request entity too large
spec:
rules:
- host: registry.kube.example.com
http:
paths:
- path: /
backend:
serviceName: kube-registry
servicePort: 5000

View File

@ -0,0 +1,44 @@
---
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-registry-v0
namespace: kube-system
labels:
k8s-app: kube-registry-upstream
version: v0
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-registry-upstream
version: v0
template:
metadata:
labels:
k8s-app: kube-registry-upstream
version: v0
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: registry
image: registry:2
resources:
limits:
cpu: 100m
memory: 100Mi
env:
- name: REGISTRY_HTTP_ADDR
value: :5000
- name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
value: /var/lib/registry
volumeMounts:
- name: image-store
mountPath: /var/lib/registry
ports:
- containerPort: 5000
name: registry
protocol: TCP
volumes:
- name: image-store
emptyDir: {}

View File

@ -0,0 +1,17 @@
---
apiVersion: v1
kind: Service
metadata:
name: kube-registry
namespace: kube-system
labels:
k8s-app: kube-registry-upstream
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeRegistry"
spec:
selector:
k8s-app: kube-registry-upstream
ports:
- name: registry
port: 5000
protocol: TCP

View File

@ -0,0 +1,48 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: default-http-backend
labels:
app: default-http-backend
namespace: authelia
spec:
replicas: 1
template:
metadata:
labels:
app: default-http-backend
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
image: gcr.io/google_containers/defaultbackend:1.4
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: authelia
labels:
app: default-http-backend
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: default-http-backend

View File

@ -0,0 +1,42 @@
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller-external
namespace: authelia
labels:
k8s-app: nginx-ingress-controller-external
spec:
replicas: 1
revisionHistoryLimit: 0
template:
metadata:
labels:
k8s-app: nginx-ingress-controller-external
name: nginx-ingress-controller-external
annotations:
prometheus.io/port: '10254'
prometheus.io/scrape: 'true'
spec:
terminationGracePeriodSeconds: 60
containers:
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.13.0
name: nginx-ingress-controller-external
imagePullPolicy: Always
ports:
- containerPort: 80
- containerPort: 443
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args:
- /nginx-ingress-controller
- --ingress-class=nginx
- --election-id=ingress-controller-leader-external
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend

View File

@ -0,0 +1,18 @@
---
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller-external-service
namespace: authelia
labels:
k8s-app: nginx-ingress-controller-external
spec:
selector:
k8s-app: nginx-ingress-controller-external
ports:
- port: 80
name: http
- port: 443
name: https
externalIPs:
- 192.168.39.26

View File

@ -0,0 +1,12 @@
FROM clems4ever/openldap
ENV SLAPD_ORGANISATION=MyCompany
ENV SLAPD_DOMAIN=example.com
ENV SLAPD_PASSWORD=password
ENV SLAPD_CONFIG_PASSWORD=password
ENV SLAPD_ADDITIONAL_MODULES=memberof
ENV SLAPD_ADDITIONAL_SCHEMAS=openldap
ENV SLAPD_FORCE_RECONFIGURE=true
ADD base.ldif /etc/ldap.dist/prepopulate/base.ldif
ADD access.rules /etc/ldap.dist/prepopulate/access.rules

View File

@ -0,0 +1,23 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: ldap
namespace: authelia
labels:
app: ldap
spec:
replicas: 1
selector:
matchLabels:
app: ldap
template:
metadata:
labels:
app: ldap
spec:
containers:
- name: ldap
image: clems4ever/authelia-test-ldap
ports:
- containerPort: 389

View File

@ -0,0 +1,12 @@
---
apiVersion: v1
kind: Service
metadata:
name: ldap-service
namespace: authelia
spec:
selector:
app: ldap
ports:
- protocol: TCP
port: 389

View File

@ -0,0 +1,25 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: mailcatcher
namespace: authelia
labels:
app: mailcatcher
spec:
replicas: 1
selector:
matchLabels:
app: mailcatcher
template:
metadata:
labels:
app: mailcatcher
spec:
containers:
- name: mailcatcher
image: schickling/mailcatcher
ports:
- containerPort: 1025
- containerPort: 1080

View File

@ -0,0 +1,17 @@
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mailcatcher-ingress
namespace: authelia
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: mail.kube.example.com
http:
paths:
- path: /
backend:
serviceName: mailcatcher-service
servicePort: 1080

View File

@ -0,0 +1,16 @@
---
apiVersion: v1
kind: Service
metadata:
name: mailcatcher-service
namespace: authelia
spec:
selector:
app: mailcatcher
ports:
- protocol: TCP
port: 1080
name: ui
- protocol: TCP
port: 1025
name: smtp

View File

@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: authelia

View File

@ -0,0 +1,48 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: mongo
namespace: authelia
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo:3.4
ports:
- containerPort: 27017
volumeMounts:
- name: data-volume
mountPath: /data/db
- name: config-volume
mountPath: /data/configdb
volumes:
- name: data-volume
hostPath:
path: /data/storage/mongo/data
- name: config-volume
hostPath:
path: /data/storage/mongo/config
---
apiVersion: v1
kind: Service
metadata:
name: mongo-service
namespace: authelia
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: 27017

View File

@ -0,0 +1,36 @@
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: redis
namespace: authelia
labels:
app: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:3.2.11-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: authelia
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379

View File

@ -1,9 +0,0 @@
version: '2'
services:
nginx-backend:
image: nginx:alpine
volumes:
- ./example/nginx/backend/html:/usr/share/nginx/html
- ./example/nginx/backend/nginx.conf:/etc/nginx/nginx.conf
networks:
- example-network

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

View File

@ -4,14 +4,14 @@ set -e
docker-compose \ docker-compose \
-f docker-compose.yml \ -f docker-compose.yml \
-f example/docker-compose.base.yml \ -f example/compose/docker-compose.base.yml \
-f example/authelia/docker-compose.dev.yml \ -f example/compose/authelia/docker-compose.dev.yml \
-f example/mongo/docker-compose.yml \ -f example/compose/mongo/docker-compose.yml \
-f example/redis/docker-compose.yml \ -f example/compose/redis/docker-compose.yml \
-f example/nginx/authelia/docker-compose.yml \ -f example/compose/nginx/authelia/docker-compose.yml \
-f example/nginx/backend/docker-compose.yml \ -f example/compose/nginx/backend/docker-compose.yml \
-f example/nginx/portal/docker-compose.yml \ -f example/compose/nginx/portal/docker-compose.yml \
-f example/smtp/docker-compose.yml \ -f example/compose/smtp/docker-compose.yml \
-f example/httpbin/docker-compose.yml \ -f example/compose/httpbin/docker-compose.yml \
-f example/ldap/docker-compose.admin.yml \ -f example/compose/ldap/docker-compose.admin.yml \
-f example/ldap/docker-compose.yml $* -f example/compose/ldap/docker-compose.yml $*

View File

@ -4,12 +4,12 @@ set -e
docker-compose \ docker-compose \
-f docker-compose.yml \ -f docker-compose.yml \
-f example/docker-compose.base.yml \ -f example/compose/docker-compose.base.yml \
-f example/mongo/docker-compose.yml \ -f example/compose/mongo/docker-compose.yml \
-f example/redis/docker-compose.yml \ -f example/compose/redis/docker-compose.yml \
-f example/nginx/authelia/docker-compose.yml \ -f example/compose/nginx/authelia/docker-compose.yml \
-f example/nginx/backend/docker-compose.yml \ -f example/compose/nginx/backend/docker-compose.yml \
-f example/nginx/portal/docker-compose.yml \ -f example/compose/nginx/portal/docker-compose.yml \
-f example/smtp/docker-compose.yml \ -f example/compose/smtp/docker-compose.yml \
-f example/httpbin/docker-compose.yml \ -f example/compose/httpbin/docker-compose.yml \
-f example/ldap/docker-compose.yml $* -f example/compose/ldap/docker-compose.yml $*

View File

@ -4,12 +4,12 @@ set -e
docker-compose \ docker-compose \
-f docker-compose.dockerhub.yml \ -f docker-compose.dockerhub.yml \
-f example/docker-compose.base.yml \ -f example/compose/docker-compose.base.yml \
-f example/mongo/docker-compose.yml \ -f example/compose/mongo/docker-compose.yml \
-f example/redis/docker-compose.yml \ -f example/compose/redis/docker-compose.yml \
-f example/nginx/authelia/docker-compose.yml \ -f example/compose/nginx/authelia/docker-compose.yml \
-f example/nginx/backend/docker-compose.yml \ -f example/compose/nginx/backend/docker-compose.yml \
-f example/nginx/portal/docker-compose.yml \ -f example/compose/nginx/portal/docker-compose.yml \
-f example/smtp/docker-compose.yml \ -f example/compose/smtp/docker-compose.yml \
-f example/httpbin/docker-compose.yml \ -f example/compose/httpbin/docker-compose.yml \
-f example/ldap/docker-compose.yml $* -f example/compose/ldap/docker-compose.yml $*

View File

@ -20,8 +20,9 @@ function redirectToSecondFactorPage(req: express.Request, res: express.Response)
if (!redirectUrl) if (!redirectUrl)
res.redirect(Endpoints.SECOND_FACTOR_GET); res.redirect(Endpoints.SECOND_FACTOR_GET);
else else
res.redirect(Util.format("%s?redirect=%s", Endpoints.SECOND_FACTOR_GET, res.redirect(Util.format("%s?%s=%s", Endpoints.SECOND_FACTOR_GET,
encodeURIComponent(redirectUrl))); Constants.REDIRECT_QUERY_PARAM,
redirectUrl));
} }
function redirectToService(req: express.Request, res: express.Response) { function redirectToService(req: express.Request, res: express.Response) {

View File

@ -75,7 +75,7 @@ export default function (vars: ServerVariables) {
let newRedirectUrl = Endpoint.SECOND_FACTOR_GET; let newRedirectUrl = Endpoint.SECOND_FACTOR_GET;
if (redirectUrl) { if (redirectUrl) {
newRedirectUrl += "?" + Constants.REDIRECT_QUERY_PARAM + "=" newRedirectUrl += "?" + Constants.REDIRECT_QUERY_PARAM + "="
+ encodeURIComponent(redirectUrl); + redirectUrl;
} }
vars.logger.debug(req, "Redirect to '%s'", newRedirectUrl); vars.logger.debug(req, "Redirect to '%s'", newRedirectUrl);
res.send({ res.send({

View File

@ -1,10 +1,20 @@
import express = require("express"); import express = require("express");
import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler";
import Constants = require("../../../../../shared/constants");
import { ServerVariables } from "../../ServerVariables";
export default function(req: express.Request, res: express.Response) { function getRedirectParam(req: express.Request) {
const redirect_param = req.query.redirect; return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined"
const redirect_url = redirect_param || "/"; ? req.query[Constants.REDIRECT_QUERY_PARAM]
AuthenticationSessionHandler.reset(req); : undefined;
res.redirect(redirect_url); }
export default function (vars: ServerVariables) {
return function(req: express.Request, res: express.Response) {
const redirect_param = getRedirectParam(req);
const redirect_url = redirect_param || "/";
AuthenticationSessionHandler.reset(req);
res.redirect(redirect_url);
};
} }

View File

@ -6,6 +6,7 @@ import { ServerVariables } from "../../ServerVariables";
import GetWithSessionCookieMethod from "./get_session_cookie"; import GetWithSessionCookieMethod from "./get_session_cookie";
import GetWithBasicAuthMethod from "./get_basic_auth"; import GetWithBasicAuthMethod from "./get_basic_auth";
import Constants = require("../../../../../shared/constants"); import Constants = require("../../../../../shared/constants");
import ObjectPath = require("object-path");
import { AuthenticationSessionHandler } import { AuthenticationSessionHandler }
from "../../AuthenticationSessionHandler"; from "../../AuthenticationSessionHandler";
@ -30,8 +31,9 @@ function verifyWithSelectedMethod(req: Express.Request, res: Express.Response,
function setRedirectHeader(req: Express.Request, res: Express.Response) { function setRedirectHeader(req: Express.Request, res: Express.Response) {
return function () { return function () {
res.set("Redirect", encodeURIComponent("https://" + req.headers["host"] + const originalUrl = ObjectPath.get<Express.Request, string>(
req.headers["x-original-uri"])); req, "headers.x-original-url");
res.set("Redirect", originalUrl);
return BluebirdPromise.resolve(); return BluebirdPromise.resolve();
}; };
} }

View File

@ -14,12 +14,12 @@ export default function (req: Express.Request, res: Express.Response,
let username: string; let username: string;
let groups: string[]; let groups: string[];
let domain: string; let domain: string;
let path: string; let originalUri: string;
return new BluebirdPromise<[string, string]>(function (resolve, reject) { return new BluebirdPromise<[string, string]>(function (resolve, reject) {
const host = ObjectPath.get<Express.Request, string>(req, "headers.host"); const originalUrl = ObjectPath.get<Express.Request, string>(req, "headers.x-original-url");
domain = DomainExtractor.fromHostHeader(host); domain = DomainExtractor.fromUrl(originalUrl);
path = originalUri =
ObjectPath.get<Express.Request, string>(req, "headers.x-original-uri"); ObjectPath.get<Express.Request, string>(req, "headers.x-original-uri");
const authenticationMethod = const authenticationMethod =
MethodCalculator.compute(vars.config.authentication_methods, domain); MethodCalculator.compute(vars.config.authentication_methods, domain);
@ -59,7 +59,7 @@ export default function (req: Express.Request, res: Express.Response,
}) })
.then(function (groupsAndEmails) { .then(function (groupsAndEmails) {
groups = groupsAndEmails.groups; groups = groupsAndEmails.groups;
return AccessControl(req, vars, domain, path, username, groups); return AccessControl(req, vars, domain, originalUri, username, groups);
}) })
.then(function () { .then(function () {
return BluebirdPromise.resolve({ return BluebirdPromise.resolve({

View File

@ -51,7 +51,7 @@ export default function (req: Express.Request, res: Express.Response,
let username: string; let username: string;
let groups: string[]; let groups: string[];
let domain: string; let domain: string;
let path: string; let originalUri: string;
return new BluebirdPromise(function (resolve, reject) { return new BluebirdPromise(function (resolve, reject) {
username = authSession.userid; username = authSession.userid;
@ -64,15 +64,15 @@ export default function (req: Express.Request, res: Express.Response,
return; return;
} }
const host = ObjectPath.get<Express.Request, string>(req, "headers.host"); const originalUrl = ObjectPath.get<Express.Request, string>(req, "headers.x-original-url");
path = originalUri =
ObjectPath.get<Express.Request, string>(req, "headers.x-original-uri"); ObjectPath.get<Express.Request, string>(req, "headers.x-original-uri");
domain = DomainExtractor.fromHostHeader(host); domain = DomainExtractor.fromUrl(originalUrl);
const authenticationMethod = const authenticationMethod =
MethodCalculator.compute(vars.config.authentication_methods, domain); MethodCalculator.compute(vars.config.authentication_methods, domain);
vars.logger.debug(req, "domain=%s, path=%s, user=%s, groups=%s", domain, vars.logger.debug(req, "domain=%s, request_uri=%s, user=%s, groups=%s", domain,
path, username, groups.join(",")); originalUri, username, groups.join(","));
if (!authSession.first_factor) if (!authSession.first_factor)
return reject(new Exceptions.AccessDeniedError( return reject(new Exceptions.AccessDeniedError(
@ -87,7 +87,7 @@ export default function (req: Express.Request, res: Express.Response,
resolve(); resolve();
}) })
.then(function () { .then(function () {
return AccessControl(req, vars, domain, path, username, groups); return AccessControl(req, vars, domain, originalUri, username, groups);
}) })
.then(function () { .then(function () {
return verify_inactivity(req, authSession, return verify_inactivity(req, authSession,

View File

@ -3,9 +3,4 @@ export class DomainExtractor {
if (!url) return ""; if (!url) return "";
return url.match(/https?:\/\/([^\/:]+).*/)[1]; return url.match(/https?:\/\/([^\/:]+).*/)[1];
} }
static fromHostHeader(host: string): string {
if (!host) return "";
return host.split(":")[0];
}
} }

View File

@ -129,7 +129,7 @@ export class RestApi {
RequireValidatedFirstFactor.middleware(vars.logger), RequireValidatedFirstFactor.middleware(vars.logger),
SecondFactorGet.default(vars)); SecondFactorGet.default(vars));
app.get(Endpoints.LOGOUT_GET, LogoutGet.default); app.get(Endpoints.LOGOUT_GET, LogoutGet.default(vars));
app.get(Endpoints.VERIFY_GET, VerifyGet.default(vars)); app.get(Endpoints.VERIFY_GET, VerifyGet.default(vars));
app.post(Endpoints.FIRST_FACTOR_POST, FirstFactorPost.default(vars)); app.post(Endpoints.FIRST_FACTOR_POST, FirstFactorPost.default(vars));

View File

@ -27,7 +27,7 @@ describe("test /api/verify endpoint", function () {
redirect: "undefined" redirect: "undefined"
}; };
AuthenticationSessionHandler.reset(req as any); AuthenticationSessionHandler.reset(req as any);
req.headers.host = "secret.example.com"; req.headers["x-original-url"] = "https://secret.example.com/";
const s = ServerVariablesMockBuilder.build(false); const s = ServerVariablesMockBuilder.build(false);
mocks = s.mocks; mocks = s.mocks;
vars = s.variables; vars = s.variables;
@ -130,7 +130,7 @@ describe("test /api/verify endpoint", function () {
authSession.first_factor = true; authSession.first_factor = true;
authSession.second_factor = true; authSession.second_factor = true;
authSession.userid = "myuser"; authSession.userid = "myuser";
req.headers.host = "test.example.com"; req.headers["x-original-url"] = "https://test.example.com/";
mocks.accessController.isAccessAllowedMock.returns(false); mocks.accessController.isAccessAllowedMock.returns(false);
return test_unauthorized_403({ return test_unauthorized_403({
@ -147,7 +147,7 @@ describe("test /api/verify endpoint", function () {
describe("given user tries to access a single factor endpoint", function () { describe("given user tries to access a single factor endpoint", function () {
beforeEach(function () { beforeEach(function () {
req.headers["host"] = "redirect.url"; req.headers["x-original-url"] = "https://redirect.url/";
mocks.config.authentication_methods.per_subdomain_methods = { mocks.config.authentication_methods.per_subdomain_methods = {
"redirect.url": "single_factor" "redirect.url": "single_factor"
}; };
@ -238,7 +238,7 @@ describe("test /api/verify endpoint", function () {
mocks.ldapAuthenticator.authenticateStub.rejects(new Error( mocks.ldapAuthenticator.authenticateStub.rejects(new Error(
"Invalid credentials")); "Invalid credentials"));
req.headers["proxy-authorization"] = "Basic am9objpwYXNzd29yZA=="; req.headers["proxy-authorization"] = "Basic am9objpwYXNzd29yZA==";
req.query["redirect"] = REDIRECT_URL; req.query["rd"] = REDIRECT_URL;
return VerifyGet.default(vars)(req as express.Request, res as any) return VerifyGet.default(vars)(req as express.Request, res as any)
.then(function () { .then(function () {

View File

@ -18,16 +18,4 @@ describe("test DomainExtractor", function () {
Assert.equal(domain, "www.example.com"); Assert.equal(domain, "www.example.com");
}); });
}); });
describe("test fromHostHeader", function () {
it("should return domain when default port is used", function () {
const domain = DomainExtractor.fromHostHeader("www.example.com");
Assert.equal(domain, "www.example.com");
});
it("should return domain when non default port is used", function () {
const domain = DomainExtractor.fromHostHeader("www.example.com:8080");
Assert.equal(domain, "www.example.com");
});
});
}); });

View File

@ -1 +1 @@
export const REDIRECT_QUERY_PARAM = "redirect"; export const REDIRECT_QUERY_PARAM = "rd";

View File

@ -2,7 +2,7 @@ Feature: User has access restricted access to domains
@need-registered-user-john @need-registered-user-john
Scenario: User john has admin access Scenario: User john has admin access
When I visit "https://login.example.com:8080?redirect=https%3A%2F%2Fhome.example.com%3A8080%2F" When I visit "https://login.example.com:8080?rd=https://home.example.com:8080/"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"
@ -20,7 +20,7 @@ Feature: User has access restricted access to domains
@need-registered-user-bob @need-registered-user-bob
Scenario: User bob has restricted access Scenario: User bob has restricted access
When I visit "https://login.example.com:8080?redirect=https%3A%2F%2Fhome.example.com%3A8080%2F" When I visit "https://login.example.com:8080?rd=https://home.example.com:8080/"
And I login with user "bob" and password "password" And I login with user "bob" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"
@ -38,7 +38,7 @@ Feature: User has access restricted access to domains
@need-registered-user-harry @need-registered-user-harry
Scenario: User harry has restricted access Scenario: User harry has restricted access
When I visit "https://login.example.com:8080?redirect=https%3A%2F%2Fhome.example.com%3A8080%2F" When I visit "https://login.example.com:8080?rd=https://home.example.com:8080/"
And I login with user "harry" and password "password" And I login with user "harry" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"

View File

@ -3,16 +3,16 @@ Feature: User is redirected when factors are already validated
@need-registered-user-john @need-registered-user-john
Scenario: User has validated first factor and tries to access service protected by second factor. He is then redirect to second factor step. Scenario: User has validated first factor and tries to access service protected by second factor. He is then redirect to second factor step.
When I visit "https://single_factor.example.com:8080/secret.html" When I visit "https://single_factor.example.com:8080/secret.html"
And I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fsingle_factor.example.com%3A8080%2Fsecret.html" And I'm redirected to "https://login.example.com:8080/?rd=https://single_factor.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I'm redirected to "https://single_factor.example.com:8080/secret.html" And I'm redirected to "https://single_factor.example.com:8080/secret.html"
And I visit "https://public.example.com:8080/secret.html" And I visit "https://public.example.com:8080/secret.html"
Then I'm redirected to "https://login.example.com:8080/secondfactor?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Then I'm redirected to "https://login.example.com:8080/secondfactor?rd=https://public.example.com:8080/secret.html"
@need-registered-user-john @need-registered-user-john
Scenario: User who has validated second factor and access auth portal should be redirected to "Already logged in page" and redirected to default URL declared in configuration Scenario: User who has validated second factor and access auth portal should be redirected to "Already logged in page" and redirected to default URL declared in configuration
When I visit "https://public.example.com:8080/secret.html" When I visit "https://public.example.com:8080/secret.html"
And I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" And I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"
@ -25,10 +25,10 @@ Feature: User is redirected when factors are already validated
@need-registered-user-john @need-registered-user-john
Scenario: User who has validated second factor and access auth portal with rediction param should be redirected to that URL Scenario: User who has validated second factor and access auth portal with rediction param should be redirected to that URL
When I visit "https://public.example.com:8080/secret.html" When I visit "https://public.example.com:8080/secret.html"
And I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" And I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"
And I'm redirected to "https://public.example.com:8080/secret.html" And I'm redirected to "https://public.example.com:8080/secret.html"
And I visit "https://login.example.com:8080?redirect=https://public.example.com:8080/secret.html" And I visit "https://login.example.com:8080?rd=https://public.example.com:8080/secret.html"
Then I'm redirected to "https://public.example.com:8080/secret.html" Then I'm redirected to "https://public.example.com:8080/secret.html"

View File

@ -5,5 +5,5 @@ Feature: Generic tests on Authelia endpoints
Then I get error code 401 Then I get error code 401
Scenario: /api/verify redirects when redirect parameter is provided Scenario: /api/verify redirects when redirect parameter is provided
When I query "https://authelia.example.com:8080/api/verify?redirect=http://login.example.com:8080" When I query "https://authelia.example.com:8080/api/verify?rd=http://login.example.com:8080"
Then I get redirected to "http://login.example.com:8080" Then I get redirected to "http://login.example.com:8080"

View File

@ -19,7 +19,7 @@ Feature: Authentication scenarii
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I register a TOTP secret called "Sec0" And I register a TOTP secret called "Sec0"
When I visit "https://admin.example.com:8080/secret.html" When I visit "https://admin.example.com:8080/secret.html"
And I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fadmin.example.com%3A8080%2Fsecret.html" And I'm redirected to "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "Sec0" as TOTP token handle And I use "Sec0" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"
@ -27,12 +27,12 @@ Feature: Authentication scenarii
Scenario: User fails TOTP second factor Scenario: User fails TOTP second factor
When I visit "https://admin.example.com:8080/secret.html" When I visit "https://admin.example.com:8080/secret.html"
And I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fadmin.example.com%3A8080%2Fsecret.html" And I'm redirected to "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "BADTOKEN" as TOTP token And I use "BADTOKEN" as TOTP token
And I click on "Sign in" And I click on "Sign in"
Then I get a notification of type "error" with message "Authentication failed. Have you already registered your secret?" Then I get a notification of type "error" with message "Authentication failed. Have you already registered your secret?"
Scenario: Logout redirects user to redirect URL given in parameter Scenario: Logout redirects user to redirect URL given in parameter
When I visit "https://login.example.com:8080/logout?redirect=https://home.example.com:8080/" When I visit "https://login.example.com:8080/logout?rd=https://home.example.com:8080/"
Then I'm redirected to "https://home.example.com:8080/" Then I'm redirected to "https://home.example.com:8080/"

View File

@ -2,7 +2,7 @@ Feature: User is correctly redirected
Scenario: User is redirected to authelia when he is not authenticated Scenario: User is redirected to authelia when he is not authenticated
When I visit "https://public.example.com:8080" When I visit "https://public.example.com:8080"
Then I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2F" Then I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/"
@need-registered-user-john @need-registered-user-john
Scenario: User is redirected to home page after several authentication tries Scenario: User is redirected to home page after several authentication tries
@ -22,7 +22,7 @@ Feature: User is correctly redirected
Scenario: Redirection URL is propagated from restricted page to first factor Scenario: Redirection URL is propagated from restricted page to first factor
When I visit "https://public.example.com:8080/secret.html" When I visit "https://public.example.com:8080/secret.html"
Then I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Then I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"
Scenario: Redirection URL is propagated from first factor to second factor Scenario: Redirection URL is propagated from first factor to second factor
Given I visit "https://login.example.com:8080/" Given I visit "https://login.example.com:8080/"
@ -30,7 +30,7 @@ Feature: User is correctly redirected
And I register a TOTP secret called "Sec0" And I register a TOTP secret called "Sec0"
When I visit "https://public.example.com:8080/secret.html" When I visit "https://public.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
Then I'm redirected to "https://login.example.com:8080/secondfactor?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Then I'm redirected to "https://login.example.com:8080/secondfactor?rd=https://public.example.com:8080/secret.html"
Scenario: Redirection URL is used to send user from second factor to target page Scenario: Redirection URL is used to send user from second factor to target page
Given I visit "https://login.example.com:8080/" Given I visit "https://login.example.com:8080/"

View File

@ -20,7 +20,7 @@ Feature: Authelia regulates authentication to avoid brute force
@need-registered-user-blackhat @need-registered-user-blackhat
Scenario: User is unbanned after a configured amount of time Scenario: User is unbanned after a configured amount of time
Given I visit "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Given I visit "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"
And I set field "username" to "blackhat" And I set field "username" to "blackhat"
And I set field "password" to "bad-password" And I set field "password" to "bad-password"
And I click on "Sign in" And I click on "Sign in"

View File

@ -8,7 +8,7 @@ Feature: Authelia keeps user sessions despite the application restart
@need-registered-user-john @need-registered-user-john
Scenario: Secrets are stored even when Authelia restarts Scenario: Secrets are stored even when Authelia restarts
When the application restarts When the application restarts
And I visit "https://admin.example.com:8080/secret.html" and get redirected "https://login.example.com:8080/?redirect=https%3A%2F%2Fadmin.example.com%3A8080%2Fsecret.html" And I visit "https://admin.example.com:8080/secret.html" and get redirected "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html"
And I login with user "john" and password "password" And I login with user "john" and password "password"
And I use "REGISTERED" as TOTP token handle And I use "REGISTERED" as TOTP token handle
And I click on "Sign in" And I click on "Sign in"

View File

@ -6,7 +6,7 @@ Feature: Session is closed after a certain amount of time
Given I have access to "https://public.example.com:8080/secret.html" Given I have access to "https://public.example.com:8080/secret.html"
When I sleep for 6 seconds When I sleep for 6 seconds
And I visit "https://public.example.com:8080/secret.html" And I visit "https://public.example.com:8080/secret.html"
Then I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Then I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"
@need-authenticated-user-john @need-authenticated-user-john
Scenario: An authenticated user is disconnected after session expiration period Scenario: An authenticated user is disconnected after session expiration period
@ -17,4 +17,4 @@ Feature: Session is closed after a certain amount of time
And I visit "https://public.example.com:8080/secret.html" And I visit "https://public.example.com:8080/secret.html"
And I sleep for 4 seconds And I sleep for 4 seconds
And I visit "https://public.example.com:8080/secret.html" And I visit "https://public.example.com:8080/secret.html"
Then I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" Then I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html"

Some files were not shown because too many files have changed in this diff Show More