diff --git a/README.md b/README.md index b70d69a71..d6e705ac1 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ as 2nd factor. * User-defined access control per subdomain and resource. * Support of [basic authentication] for endpoints protected by single factor. * High-availability using a highly-available distributed database and KV store. +* Compatible with Kubernetes ingress-nginx controller out of the box. ## 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. +### With Kubernetes + + + +Please refer to the following [README](./example/kube/README.md). + ## Getting started The provided example is docker-based so that you can deploy and test it very diff --git a/example/authelia/docker-compose.dev.yml b/example/compose/authelia/docker-compose.dev.yml similarity index 100% rename from example/authelia/docker-compose.dev.yml rename to example/compose/authelia/docker-compose.dev.yml diff --git a/example/authelia/docker-compose.test.yml b/example/compose/authelia/docker-compose.test.yml similarity index 100% rename from example/authelia/docker-compose.test.yml rename to example/compose/authelia/docker-compose.test.yml diff --git a/example/docker-compose.base.yml b/example/compose/docker-compose.base.yml similarity index 100% rename from example/docker-compose.base.yml rename to example/compose/docker-compose.base.yml diff --git a/example/httpbin/docker-compose.yml b/example/compose/httpbin/docker-compose.yml similarity index 100% rename from example/httpbin/docker-compose.yml rename to example/compose/httpbin/docker-compose.yml diff --git a/example/ldap/access.rules b/example/compose/ldap/access.rules similarity index 100% rename from example/ldap/access.rules rename to example/compose/ldap/access.rules diff --git a/example/ldap/base.ldif b/example/compose/ldap/base.ldif similarity index 100% rename from example/ldap/base.ldif rename to example/compose/ldap/base.ldif diff --git a/example/ldap/docker-compose.admin.yml b/example/compose/ldap/docker-compose.admin.yml similarity index 100% rename from example/ldap/docker-compose.admin.yml rename to example/compose/ldap/docker-compose.admin.yml diff --git a/example/ldap/docker-compose.yml b/example/compose/ldap/docker-compose.yml similarity index 71% rename from example/ldap/docker-compose.yml rename to example/compose/ldap/docker-compose.yml index e991df60b..41de32b2d 100644 --- a/example/ldap/docker-compose.yml +++ b/example/compose/ldap/docker-compose.yml @@ -11,8 +11,8 @@ services: - SLAPD_ADDITIONAL_SCHEMAS=openldap - SLAPD_FORCE_RECONFIGURE=true volumes: - - ./example/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif - - ./example/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules + - ./example/compose/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif + - ./example/compose/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules networks: - example-network diff --git a/example/mongo/docker-compose.yml b/example/compose/mongo/docker-compose.yml similarity index 100% rename from example/mongo/docker-compose.yml rename to example/compose/mongo/docker-compose.yml diff --git a/example/nginx/authelia/docker-compose.yml b/example/compose/nginx/authelia/docker-compose.yml similarity index 61% rename from example/nginx/authelia/docker-compose.yml rename to example/compose/nginx/authelia/docker-compose.yml index cd590620e..66994ce2a 100644 --- a/example/nginx/authelia/docker-compose.yml +++ b/example/compose/nginx/authelia/docker-compose.yml @@ -3,6 +3,6 @@ services: nginx-authelia: image: nginx:alpine volumes: - - ./example/nginx/authelia/nginx.conf:/etc/nginx/nginx.conf + - ./example/compose/nginx/authelia/nginx.conf:/etc/nginx/nginx.conf networks: - example-network diff --git a/example/nginx/authelia/nginx.conf b/example/compose/nginx/authelia/nginx.conf similarity index 100% rename from example/nginx/authelia/nginx.conf rename to example/compose/nginx/authelia/nginx.conf diff --git a/example/compose/nginx/backend/docker-compose.yml b/example/compose/nginx/backend/docker-compose.yml new file mode 100644 index 000000000..6b5856dcb --- /dev/null +++ b/example/compose/nginx/backend/docker-compose.yml @@ -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 diff --git a/example/nginx/backend/html/admin/secret.html b/example/compose/nginx/backend/html/admin/secret.html similarity index 100% rename from example/nginx/backend/html/admin/secret.html rename to example/compose/nginx/backend/html/admin/secret.html diff --git a/example/nginx/backend/html/dev/groups/admin/secret.html b/example/compose/nginx/backend/html/dev/groups/admin/secret.html similarity index 100% rename from example/nginx/backend/html/dev/groups/admin/secret.html rename to example/compose/nginx/backend/html/dev/groups/admin/secret.html diff --git a/example/nginx/backend/html/dev/groups/dev/secret.html b/example/compose/nginx/backend/html/dev/groups/dev/secret.html similarity index 100% rename from example/nginx/backend/html/dev/groups/dev/secret.html rename to example/compose/nginx/backend/html/dev/groups/dev/secret.html diff --git a/example/nginx/backend/html/dev/users/bob/secret.html b/example/compose/nginx/backend/html/dev/users/bob/secret.html similarity index 100% rename from example/nginx/backend/html/dev/users/bob/secret.html rename to example/compose/nginx/backend/html/dev/users/bob/secret.html diff --git a/example/nginx/backend/html/dev/users/harry/secret.html b/example/compose/nginx/backend/html/dev/users/harry/secret.html similarity index 100% rename from example/nginx/backend/html/dev/users/harry/secret.html rename to example/compose/nginx/backend/html/dev/users/harry/secret.html diff --git a/example/nginx/backend/html/dev/users/john/secret.html b/example/compose/nginx/backend/html/dev/users/john/secret.html similarity index 100% rename from example/nginx/backend/html/dev/users/john/secret.html rename to example/compose/nginx/backend/html/dev/users/john/secret.html diff --git a/example/nginx/backend/html/home/index.html b/example/compose/nginx/backend/html/home/index.html similarity index 97% rename from example/nginx/backend/html/home/index.html rename to example/compose/nginx/backend/html/home/index.html index 49f2dde04..5dd4295af 100644 --- a/example/nginx/backend/html/home/index.html +++ b/example/compose/nginx/backend/html/home/index.html @@ -56,7 +56,7 @@ - You can also log off by visiting the following link. + You can also log off by visiting the following link.

List of users

Here is the list of credentials you can log in with to test access control.
@@ -131,4 +131,4 @@ users: - '^/users/harry/.*$' - \ No newline at end of file + diff --git a/example/nginx/backend/html/icon.png b/example/compose/nginx/backend/html/icon.png similarity index 100% rename from example/nginx/backend/html/icon.png rename to example/compose/nginx/backend/html/icon.png diff --git a/example/nginx/backend/html/mail/secret.html b/example/compose/nginx/backend/html/mail/secret.html similarity index 100% rename from example/nginx/backend/html/mail/secret.html rename to example/compose/nginx/backend/html/mail/secret.html diff --git a/example/nginx/backend/html/public/index.html b/example/compose/nginx/backend/html/public/index.html similarity index 100% rename from example/nginx/backend/html/public/index.html rename to example/compose/nginx/backend/html/public/index.html diff --git a/example/nginx/backend/html/public/secret.html b/example/compose/nginx/backend/html/public/secret.html similarity index 100% rename from example/nginx/backend/html/public/secret.html rename to example/compose/nginx/backend/html/public/secret.html diff --git a/example/nginx/backend/html/single_factor/secret.html b/example/compose/nginx/backend/html/single_factor/secret.html similarity index 100% rename from example/nginx/backend/html/single_factor/secret.html rename to example/compose/nginx/backend/html/single_factor/secret.html diff --git a/example/nginx/backend/nginx.conf b/example/compose/nginx/backend/nginx.conf similarity index 100% rename from example/nginx/backend/nginx.conf rename to example/compose/nginx/backend/nginx.conf diff --git a/example/nginx/portal/docker-compose.yml b/example/compose/nginx/portal/docker-compose.yml similarity index 53% rename from example/nginx/portal/docker-compose.yml rename to example/compose/nginx/portal/docker-compose.yml index af52f092c..d6d4bb64a 100644 --- a/example/nginx/portal/docker-compose.yml +++ b/example/compose/nginx/portal/docker-compose.yml @@ -3,8 +3,8 @@ services: nginx-portal: image: nginx:alpine volumes: - - ./example/nginx/portal/nginx.conf:/etc/nginx/nginx.conf - - ./example/nginx/portal/ssl:/etc/ssl + - ./example/compose/nginx/portal/nginx.conf:/etc/nginx/nginx.conf + - ./example/compose/nginx/portal/ssl:/etc/ssl ports: - "8080:443" networks: diff --git a/example/nginx/portal/nginx.conf b/example/compose/nginx/portal/nginx.conf similarity index 79% rename from example/nginx/portal/nginx.conf rename to example/compose/nginx/portal/nginx.conf index 1ce5fcfc9..314e00031 100644 --- a/example/nginx/portal/nginx.conf +++ b/example/compose/nginx/portal/nginx.conf @@ -74,11 +74,15 @@ http { location /auth_verify { internal; - 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 Content-Length ""; + proxy_set_header Host $http_host; + + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + 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; } @@ -96,7 +100,7 @@ http { 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; proxy_pass $upstream_endpoint; @@ -113,7 +117,7 @@ http { auth_request_set $groups $upstream_http_remote_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; proxy_pass $upstream_headers; @@ -137,11 +141,15 @@ http { location /auth_verify { internal; - 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 Content-Length ""; + proxy_set_header Host $http_host; + + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + 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; } @@ -159,7 +167,7 @@ http { 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; proxy_pass $upstream_endpoint; @@ -183,11 +191,15 @@ http { location /auth_verify { internal; - 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 Content-Length ""; + proxy_set_header Host $http_host; + + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + 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; } @@ -205,7 +217,7 @@ http { 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; proxy_pass $upstream_endpoint; @@ -229,11 +241,15 @@ http { location /auth_verify { internal; - 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 Content-Length ""; + proxy_set_header Host $http_host; + + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + 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; } @@ -251,7 +267,7 @@ http { 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; proxy_pass $upstream_endpoint; @@ -276,12 +292,18 @@ http { location /auth_verify { internal; - 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 Content-Length ""; - proxy_set_header Proxy-Authorization $http_authorization; + proxy_set_header Host $http_host; + + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Real-IP $remote_addr; + 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; } @@ -299,7 +321,7 @@ http { 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; proxy_pass $upstream_endpoint; @@ -316,7 +338,7 @@ http { auth_request_set $groups $upstream_http_remote_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; proxy_pass $upstream_headers; diff --git a/example/nginx/portal/ssl/server.crt b/example/compose/nginx/portal/ssl/server.crt similarity index 100% rename from example/nginx/portal/ssl/server.crt rename to example/compose/nginx/portal/ssl/server.crt diff --git a/example/nginx/portal/ssl/server.csr b/example/compose/nginx/portal/ssl/server.csr similarity index 100% rename from example/nginx/portal/ssl/server.csr rename to example/compose/nginx/portal/ssl/server.csr diff --git a/example/nginx/portal/ssl/server.key b/example/compose/nginx/portal/ssl/server.key similarity index 100% rename from example/nginx/portal/ssl/server.key rename to example/compose/nginx/portal/ssl/server.key diff --git a/example/redis/docker-compose.yml b/example/compose/redis/docker-compose.yml similarity index 100% rename from example/redis/docker-compose.yml rename to example/compose/redis/docker-compose.yml diff --git a/example/smtp/docker-compose.yml b/example/compose/smtp/docker-compose.yml similarity index 100% rename from example/smtp/docker-compose.yml rename to example/compose/smtp/docker-compose.yml diff --git a/example/kube/README.md b/example/kube/README.md new file mode 100644 index 000000000..7878055c6 --- /dev/null +++ b/example/kube/README.md @@ -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) diff --git a/example/kube/apps/app-home/deployment.yml b/example/kube/apps/app-home/deployment.yml new file mode 100644 index 000000000..3f88fdc13 --- /dev/null +++ b/example/kube/apps/app-home/deployment.yml @@ -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 diff --git a/example/kube/apps/app-home/index.html b/example/kube/apps/app-home/index.html new file mode 100644 index 000000000..a1e975e94 --- /dev/null +++ b/example/kube/apps/app-home/index.html @@ -0,0 +1,35 @@ + + + Authelia Home + + +

Authelia on Kube

+ + In this example, two applications have been deployed along with Authelia and a fake mailbox in order to confirm your secret registration to Authelia: + +

+ Please note that app1 is publicly available and app2 is protected by Authelia.
+
+ You can start by visiting app1 and then try to access app2. Since app2 is protected by Authelia, you will be redirected to Authelia's portal.
+
+ If it's the first time you login in this cluster, you'll need to choose your authentication method and follow Authelia's instructions.
+
+ Once done, you'll be able to authenticate with your selected second factor method. +

+

+ Here is the list of available users in the LDAP +

+

+

+ You can always log off by clicking here +

+ + diff --git a/example/kube/apps/app-home/service.yml b/example/kube/apps/app-home/service.yml new file mode 100644 index 000000000..1dd6f0148 --- /dev/null +++ b/example/kube/apps/app-home/service.yml @@ -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 diff --git a/example/kube/apps/app1/deployment.yml b/example/kube/apps/app1/deployment.yml new file mode 100644 index 000000000..883b857f3 --- /dev/null +++ b/example/kube/apps/app1/deployment.yml @@ -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 diff --git a/example/kube/apps/app1/index.html b/example/kube/apps/app1/index.html new file mode 100644 index 000000000..b9102c5e7 --- /dev/null +++ b/example/kube/apps/app1/index.html @@ -0,0 +1,9 @@ + + + Application 1 + + +

Application 1

+

Go Home

+ + diff --git a/example/kube/apps/app1/service.yml b/example/kube/apps/app1/service.yml new file mode 100644 index 000000000..3a229ad0f --- /dev/null +++ b/example/kube/apps/app1/service.yml @@ -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 diff --git a/example/kube/apps/app1/ssl/tls.crt b/example/kube/apps/app1/ssl/tls.crt new file mode 100644 index 000000000..41a0d908b --- /dev/null +++ b/example/kube/apps/app1/ssl/tls.crt @@ -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----- diff --git a/example/kube/apps/app1/ssl/tls.csr b/example/kube/apps/app1/ssl/tls.csr new file mode 100644 index 000000000..808704262 --- /dev/null +++ b/example/kube/apps/app1/ssl/tls.csr @@ -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----- diff --git a/example/kube/apps/app1/ssl/tls.key b/example/kube/apps/app1/ssl/tls.key new file mode 100644 index 000000000..c42ccf379 --- /dev/null +++ b/example/kube/apps/app1/ssl/tls.key @@ -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----- diff --git a/example/kube/apps/app2/deployment.yml b/example/kube/apps/app2/deployment.yml new file mode 100644 index 000000000..5cb7e0bb0 --- /dev/null +++ b/example/kube/apps/app2/deployment.yml @@ -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 diff --git a/example/kube/apps/app2/index.html b/example/kube/apps/app2/index.html new file mode 100644 index 000000000..0eaeb5410 --- /dev/null +++ b/example/kube/apps/app2/index.html @@ -0,0 +1,9 @@ + + + Application 2 + + +

Application 2

+

Go Home

+ + diff --git a/example/kube/apps/app2/service.yml b/example/kube/apps/app2/service.yml new file mode 100644 index 000000000..ef21e223e --- /dev/null +++ b/example/kube/apps/app2/service.yml @@ -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 diff --git a/example/kube/apps/app2/ssl/tls.crt b/example/kube/apps/app2/ssl/tls.crt new file mode 100644 index 000000000..ae5914029 --- /dev/null +++ b/example/kube/apps/app2/ssl/tls.crt @@ -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----- diff --git a/example/kube/apps/app2/ssl/tls.csr b/example/kube/apps/app2/ssl/tls.csr new file mode 100644 index 000000000..13181d9f7 --- /dev/null +++ b/example/kube/apps/app2/ssl/tls.csr @@ -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----- diff --git a/example/kube/apps/app2/ssl/tls.key b/example/kube/apps/app2/ssl/tls.key new file mode 100644 index 000000000..b57aac983 --- /dev/null +++ b/example/kube/apps/app2/ssl/tls.key @@ -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----- diff --git a/example/kube/apps/insecure-ingress.yml b/example/kube/apps/insecure-ingress.yml new file mode 100644 index 000000000..8a2c5793b --- /dev/null +++ b/example/kube/apps/insecure-ingress.yml @@ -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 diff --git a/example/kube/apps/secure-ingress.yml b/example/kube/apps/secure-ingress.yml new file mode 100644 index 000000000..2858479fb --- /dev/null +++ b/example/kube/apps/secure-ingress.yml @@ -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 diff --git a/example/kube/authelia/configs/config.yml b/example/kube/authelia/configs/config.yml new file mode 100644 index 000000000..4d37fd158 --- /dev/null +++ b/example/kube/authelia/configs/config.yml @@ -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 diff --git a/example/kube/authelia/deployment.yml b/example/kube/authelia/deployment.yml new file mode 100644 index 000000000..c0010ee3f --- /dev/null +++ b/example/kube/authelia/deployment.yml @@ -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 diff --git a/example/kube/authelia/ingress.yml b/example/kube/authelia/ingress.yml new file mode 100644 index 000000000..ec3e9e3e9 --- /dev/null +++ b/example/kube/authelia/ingress.yml @@ -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 diff --git a/example/kube/authelia/service.yml b/example/kube/authelia/service.yml new file mode 100644 index 000000000..21a6b79c2 --- /dev/null +++ b/example/kube/authelia/service.yml @@ -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 diff --git a/example/kube/authelia/ssl/tls.crt b/example/kube/authelia/ssl/tls.crt new file mode 100644 index 000000000..ab0ba6200 --- /dev/null +++ b/example/kube/authelia/ssl/tls.crt @@ -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----- diff --git a/example/kube/authelia/ssl/tls.csr b/example/kube/authelia/ssl/tls.csr new file mode 100644 index 000000000..70be16165 --- /dev/null +++ b/example/kube/authelia/ssl/tls.csr @@ -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----- diff --git a/example/kube/authelia/ssl/tls.key b/example/kube/authelia/ssl/tls.key new file mode 100644 index 000000000..3654be488 --- /dev/null +++ b/example/kube/authelia/ssl/tls.key @@ -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----- diff --git a/example/kube/bootstrap.sh b/example/kube/bootstrap.sh new file mode 100755 index 000000000..7c5493496 --- /dev/null +++ b/example/kube/bootstrap.sh @@ -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 diff --git a/example/kube/build_and_push.sh b/example/kube/build_and_push.sh new file mode 100755 index 000000000..de6310054 --- /dev/null +++ b/example/kube/build_and_push.sh @@ -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 diff --git a/example/kube/docker-registry/daemonset.yml b/example/kube/docker-registry/daemonset.yml new file mode 100644 index 000000000..3d370a30d --- /dev/null +++ b/example/kube/docker-registry/daemonset.yml @@ -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 diff --git a/example/kube/docker-registry/ingress.yml b/example/kube/docker-registry/ingress.yml new file mode 100644 index 000000000..3c71a94d6 --- /dev/null +++ b/example/kube/docker-registry/ingress.yml @@ -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 diff --git a/example/kube/docker-registry/replicationcontroller.yml b/example/kube/docker-registry/replicationcontroller.yml new file mode 100644 index 000000000..45881785c --- /dev/null +++ b/example/kube/docker-registry/replicationcontroller.yml @@ -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: {} diff --git a/example/kube/docker-registry/service.yml b/example/kube/docker-registry/service.yml new file mode 100644 index 000000000..cbadaaf9c --- /dev/null +++ b/example/kube/docker-registry/service.yml @@ -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 diff --git a/example/kube/ingress-controller/default-backend.yml b/example/kube/ingress-controller/default-backend.yml new file mode 100644 index 000000000..8bb33965e --- /dev/null +++ b/example/kube/ingress-controller/default-backend.yml @@ -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 diff --git a/example/kube/ingress-controller/deployment.yml b/example/kube/ingress-controller/deployment.yml new file mode 100644 index 000000000..f67f5f8aa --- /dev/null +++ b/example/kube/ingress-controller/deployment.yml @@ -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 diff --git a/example/kube/ingress-controller/service.yml b/example/kube/ingress-controller/service.yml new file mode 100644 index 000000000..6149ce6f1 --- /dev/null +++ b/example/kube/ingress-controller/service.yml @@ -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 diff --git a/example/kube/ldap/Dockerfile b/example/kube/ldap/Dockerfile new file mode 100644 index 000000000..c7e70e0c0 --- /dev/null +++ b/example/kube/ldap/Dockerfile @@ -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 diff --git a/example/kube/ldap/deployment.yml b/example/kube/ldap/deployment.yml new file mode 100644 index 000000000..fea1cefd2 --- /dev/null +++ b/example/kube/ldap/deployment.yml @@ -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 diff --git a/example/kube/ldap/service.yml b/example/kube/ldap/service.yml new file mode 100644 index 000000000..09f599258 --- /dev/null +++ b/example/kube/ldap/service.yml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: ldap-service + namespace: authelia +spec: + selector: + app: ldap + ports: + - protocol: TCP + port: 389 diff --git a/example/kube/mailcatcher/deployment.yml b/example/kube/mailcatcher/deployment.yml new file mode 100644 index 000000000..958c94110 --- /dev/null +++ b/example/kube/mailcatcher/deployment.yml @@ -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 + diff --git a/example/kube/mailcatcher/ingress.yml b/example/kube/mailcatcher/ingress.yml new file mode 100644 index 000000000..ce8131def --- /dev/null +++ b/example/kube/mailcatcher/ingress.yml @@ -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 diff --git a/example/kube/mailcatcher/service.yml b/example/kube/mailcatcher/service.yml new file mode 100644 index 000000000..f51d7dd98 --- /dev/null +++ b/example/kube/mailcatcher/service.yml @@ -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 diff --git a/example/kube/namespace.yml b/example/kube/namespace.yml new file mode 100644 index 000000000..9dfdb53f8 --- /dev/null +++ b/example/kube/namespace.yml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: authelia diff --git a/example/kube/storage/mongo.yml b/example/kube/storage/mongo.yml new file mode 100644 index 000000000..eb0d053a8 --- /dev/null +++ b/example/kube/storage/mongo.yml @@ -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 diff --git a/example/kube/storage/redis.yml b/example/kube/storage/redis.yml new file mode 100644 index 000000000..e9f12f8e7 --- /dev/null +++ b/example/kube/storage/redis.yml @@ -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 diff --git a/example/nginx/backend/docker-compose.yml b/example/nginx/backend/docker-compose.yml deleted file mode 100644 index 9adb9f28e..000000000 --- a/example/nginx/backend/docker-compose.yml +++ /dev/null @@ -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 diff --git a/images/kube-logo.png b/images/kube-logo.png new file mode 100644 index 000000000..05fc5e1d2 Binary files /dev/null and b/images/kube-logo.png differ diff --git a/scripts/dc-dev.sh b/scripts/dc-dev.sh index 2a04d59e4..cff64d513 100755 --- a/scripts/dc-dev.sh +++ b/scripts/dc-dev.sh @@ -4,14 +4,14 @@ set -e docker-compose \ -f docker-compose.yml \ - -f example/docker-compose.base.yml \ - -f example/authelia/docker-compose.dev.yml \ - -f example/mongo/docker-compose.yml \ - -f example/redis/docker-compose.yml \ - -f example/nginx/authelia/docker-compose.yml \ - -f example/nginx/backend/docker-compose.yml \ - -f example/nginx/portal/docker-compose.yml \ - -f example/smtp/docker-compose.yml \ - -f example/httpbin/docker-compose.yml \ - -f example/ldap/docker-compose.admin.yml \ - -f example/ldap/docker-compose.yml $* + -f example/compose/docker-compose.base.yml \ + -f example/compose/authelia/docker-compose.dev.yml \ + -f example/compose/mongo/docker-compose.yml \ + -f example/compose/redis/docker-compose.yml \ + -f example/compose/nginx/authelia/docker-compose.yml \ + -f example/compose/nginx/backend/docker-compose.yml \ + -f example/compose/nginx/portal/docker-compose.yml \ + -f example/compose/smtp/docker-compose.yml \ + -f example/compose/httpbin/docker-compose.yml \ + -f example/compose/ldap/docker-compose.admin.yml \ + -f example/compose/ldap/docker-compose.yml $* diff --git a/scripts/example-commit/dc-example.sh b/scripts/example-commit/dc-example.sh index 020bfde73..8e36b415d 100755 --- a/scripts/example-commit/dc-example.sh +++ b/scripts/example-commit/dc-example.sh @@ -4,12 +4,12 @@ set -e docker-compose \ -f docker-compose.yml \ - -f example/docker-compose.base.yml \ - -f example/mongo/docker-compose.yml \ - -f example/redis/docker-compose.yml \ - -f example/nginx/authelia/docker-compose.yml \ - -f example/nginx/backend/docker-compose.yml \ - -f example/nginx/portal/docker-compose.yml \ - -f example/smtp/docker-compose.yml \ - -f example/httpbin/docker-compose.yml \ - -f example/ldap/docker-compose.yml $* + -f example/compose/docker-compose.base.yml \ + -f example/compose/mongo/docker-compose.yml \ + -f example/compose/redis/docker-compose.yml \ + -f example/compose/nginx/authelia/docker-compose.yml \ + -f example/compose/nginx/backend/docker-compose.yml \ + -f example/compose/nginx/portal/docker-compose.yml \ + -f example/compose/smtp/docker-compose.yml \ + -f example/compose/httpbin/docker-compose.yml \ + -f example/compose/ldap/docker-compose.yml $* diff --git a/scripts/example-dockerhub/dc-example.sh b/scripts/example-dockerhub/dc-example.sh index 9ce3e2ea1..803b3d596 100755 --- a/scripts/example-dockerhub/dc-example.sh +++ b/scripts/example-dockerhub/dc-example.sh @@ -4,12 +4,12 @@ set -e docker-compose \ -f docker-compose.dockerhub.yml \ - -f example/docker-compose.base.yml \ - -f example/mongo/docker-compose.yml \ - -f example/redis/docker-compose.yml \ - -f example/nginx/authelia/docker-compose.yml \ - -f example/nginx/backend/docker-compose.yml \ - -f example/nginx/portal/docker-compose.yml \ - -f example/smtp/docker-compose.yml \ - -f example/httpbin/docker-compose.yml \ - -f example/ldap/docker-compose.yml $* + -f example/compose/docker-compose.base.yml \ + -f example/compose/mongo/docker-compose.yml \ + -f example/compose/redis/docker-compose.yml \ + -f example/compose/nginx/authelia/docker-compose.yml \ + -f example/compose/nginx/backend/docker-compose.yml \ + -f example/compose/nginx/portal/docker-compose.yml \ + -f example/compose/smtp/docker-compose.yml \ + -f example/compose/httpbin/docker-compose.yml \ + -f example/compose/ldap/docker-compose.yml $* diff --git a/server/src/lib/routes/firstfactor/get.ts b/server/src/lib/routes/firstfactor/get.ts index 14faa225e..bddba7e0e 100644 --- a/server/src/lib/routes/firstfactor/get.ts +++ b/server/src/lib/routes/firstfactor/get.ts @@ -20,8 +20,9 @@ function redirectToSecondFactorPage(req: express.Request, res: express.Response) if (!redirectUrl) res.redirect(Endpoints.SECOND_FACTOR_GET); else - res.redirect(Util.format("%s?redirect=%s", Endpoints.SECOND_FACTOR_GET, - encodeURIComponent(redirectUrl))); + res.redirect(Util.format("%s?%s=%s", Endpoints.SECOND_FACTOR_GET, + Constants.REDIRECT_QUERY_PARAM, + redirectUrl)); } function redirectToService(req: express.Request, res: express.Response) { diff --git a/server/src/lib/routes/firstfactor/post.ts b/server/src/lib/routes/firstfactor/post.ts index d72ed1da6..ecf1d85a5 100644 --- a/server/src/lib/routes/firstfactor/post.ts +++ b/server/src/lib/routes/firstfactor/post.ts @@ -75,7 +75,7 @@ export default function (vars: ServerVariables) { let newRedirectUrl = Endpoint.SECOND_FACTOR_GET; if (redirectUrl) { newRedirectUrl += "?" + Constants.REDIRECT_QUERY_PARAM + "=" - + encodeURIComponent(redirectUrl); + + redirectUrl; } vars.logger.debug(req, "Redirect to '%s'", newRedirectUrl); res.send({ diff --git a/server/src/lib/routes/logout/get.ts b/server/src/lib/routes/logout/get.ts index eb8040959..4d5112146 100644 --- a/server/src/lib/routes/logout/get.ts +++ b/server/src/lib/routes/logout/get.ts @@ -1,10 +1,20 @@ import express = require("express"); import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; +import Constants = require("../../../../../shared/constants"); +import { ServerVariables } from "../../ServerVariables"; -export default function(req: express.Request, res: express.Response) { - const redirect_param = req.query.redirect; - const redirect_url = redirect_param || "/"; - AuthenticationSessionHandler.reset(req); - res.redirect(redirect_url); +function getRedirectParam(req: express.Request) { + return req.query[Constants.REDIRECT_QUERY_PARAM] != "undefined" + ? req.query[Constants.REDIRECT_QUERY_PARAM] + : undefined; +} + +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); + }; } \ No newline at end of file diff --git a/server/src/lib/routes/verify/get.ts b/server/src/lib/routes/verify/get.ts index 79fda877e..08d094373 100644 --- a/server/src/lib/routes/verify/get.ts +++ b/server/src/lib/routes/verify/get.ts @@ -6,6 +6,7 @@ import { ServerVariables } from "../../ServerVariables"; import GetWithSessionCookieMethod from "./get_session_cookie"; import GetWithBasicAuthMethod from "./get_basic_auth"; import Constants = require("../../../../../shared/constants"); +import ObjectPath = require("object-path"); import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; @@ -30,8 +31,9 @@ function verifyWithSelectedMethod(req: Express.Request, res: Express.Response, function setRedirectHeader(req: Express.Request, res: Express.Response) { return function () { - res.set("Redirect", encodeURIComponent("https://" + req.headers["host"] + - req.headers["x-original-uri"])); + const originalUrl = ObjectPath.get( + req, "headers.x-original-url"); + res.set("Redirect", originalUrl); return BluebirdPromise.resolve(); }; } diff --git a/server/src/lib/routes/verify/get_basic_auth.ts b/server/src/lib/routes/verify/get_basic_auth.ts index 6d8dda8cb..e92160b58 100644 --- a/server/src/lib/routes/verify/get_basic_auth.ts +++ b/server/src/lib/routes/verify/get_basic_auth.ts @@ -14,12 +14,12 @@ export default function (req: Express.Request, res: Express.Response, let username: string; let groups: string[]; let domain: string; - let path: string; + let originalUri: string; return new BluebirdPromise<[string, string]>(function (resolve, reject) { - const host = ObjectPath.get(req, "headers.host"); - domain = DomainExtractor.fromHostHeader(host); - path = + const originalUrl = ObjectPath.get(req, "headers.x-original-url"); + domain = DomainExtractor.fromUrl(originalUrl); + originalUri = ObjectPath.get(req, "headers.x-original-uri"); const authenticationMethod = MethodCalculator.compute(vars.config.authentication_methods, domain); @@ -59,7 +59,7 @@ export default function (req: Express.Request, res: Express.Response, }) .then(function (groupsAndEmails) { groups = groupsAndEmails.groups; - return AccessControl(req, vars, domain, path, username, groups); + return AccessControl(req, vars, domain, originalUri, username, groups); }) .then(function () { return BluebirdPromise.resolve({ diff --git a/server/src/lib/routes/verify/get_session_cookie.ts b/server/src/lib/routes/verify/get_session_cookie.ts index e96374c65..6571e8fe8 100644 --- a/server/src/lib/routes/verify/get_session_cookie.ts +++ b/server/src/lib/routes/verify/get_session_cookie.ts @@ -51,7 +51,7 @@ export default function (req: Express.Request, res: Express.Response, let username: string; let groups: string[]; let domain: string; - let path: string; + let originalUri: string; return new BluebirdPromise(function (resolve, reject) { username = authSession.userid; @@ -64,15 +64,15 @@ export default function (req: Express.Request, res: Express.Response, return; } - const host = ObjectPath.get(req, "headers.host"); - path = + const originalUrl = ObjectPath.get(req, "headers.x-original-url"); + originalUri = ObjectPath.get(req, "headers.x-original-uri"); - domain = DomainExtractor.fromHostHeader(host); + domain = DomainExtractor.fromUrl(originalUrl); const authenticationMethod = MethodCalculator.compute(vars.config.authentication_methods, domain); - vars.logger.debug(req, "domain=%s, path=%s, user=%s, groups=%s", domain, - path, username, groups.join(",")); + vars.logger.debug(req, "domain=%s, request_uri=%s, user=%s, groups=%s", domain, + originalUri, username, groups.join(",")); if (!authSession.first_factor) return reject(new Exceptions.AccessDeniedError( @@ -87,7 +87,7 @@ export default function (req: Express.Request, res: Express.Response, resolve(); }) .then(function () { - return AccessControl(req, vars, domain, path, username, groups); + return AccessControl(req, vars, domain, originalUri, username, groups); }) .then(function () { return verify_inactivity(req, authSession, diff --git a/server/src/lib/utils/DomainExtractor.ts b/server/src/lib/utils/DomainExtractor.ts index f2e8b8886..ea162a045 100644 --- a/server/src/lib/utils/DomainExtractor.ts +++ b/server/src/lib/utils/DomainExtractor.ts @@ -3,9 +3,4 @@ export class DomainExtractor { if (!url) return ""; return url.match(/https?:\/\/([^\/:]+).*/)[1]; } - - static fromHostHeader(host: string): string { - if (!host) return ""; - return host.split(":")[0]; - } } \ No newline at end of file diff --git a/server/src/lib/web_server/RestApi.ts b/server/src/lib/web_server/RestApi.ts index ed2319971..204003c88 100644 --- a/server/src/lib/web_server/RestApi.ts +++ b/server/src/lib/web_server/RestApi.ts @@ -129,7 +129,7 @@ export class RestApi { RequireValidatedFirstFactor.middleware(vars.logger), 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.post(Endpoints.FIRST_FACTOR_POST, FirstFactorPost.default(vars)); diff --git a/server/test/routes/verify/get.test.ts b/server/test/routes/verify/get.test.ts index d46a0af6a..2baa49c3b 100644 --- a/server/test/routes/verify/get.test.ts +++ b/server/test/routes/verify/get.test.ts @@ -27,7 +27,7 @@ describe("test /api/verify endpoint", function () { redirect: "undefined" }; 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); mocks = s.mocks; vars = s.variables; @@ -130,7 +130,7 @@ describe("test /api/verify endpoint", function () { authSession.first_factor = true; authSession.second_factor = true; authSession.userid = "myuser"; - req.headers.host = "test.example.com"; + req.headers["x-original-url"] = "https://test.example.com/"; mocks.accessController.isAccessAllowedMock.returns(false); 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 () { beforeEach(function () { - req.headers["host"] = "redirect.url"; + req.headers["x-original-url"] = "https://redirect.url/"; mocks.config.authentication_methods.per_subdomain_methods = { "redirect.url": "single_factor" }; @@ -238,7 +238,7 @@ describe("test /api/verify endpoint", function () { mocks.ldapAuthenticator.authenticateStub.rejects(new Error( "Invalid credentials")); 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) .then(function () { diff --git a/server/test/utils/DomainExtractor.test.ts b/server/test/utils/DomainExtractor.test.ts index f179ba9e7..80c971d2b 100644 --- a/server/test/utils/DomainExtractor.test.ts +++ b/server/test/utils/DomainExtractor.test.ts @@ -18,16 +18,4 @@ describe("test DomainExtractor", function () { 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"); - }); - }); }); \ No newline at end of file diff --git a/shared/constants.ts b/shared/constants.ts index a566fe0b8..47d3852a8 100644 --- a/shared/constants.ts +++ b/shared/constants.ts @@ -1 +1 @@ -export const REDIRECT_QUERY_PARAM = "redirect"; \ No newline at end of file +export const REDIRECT_QUERY_PARAM = "rd"; \ No newline at end of file diff --git a/test/features/access-control.feature b/test/features/access-control.feature index 9b5cb0769..5539b5596 100644 --- a/test/features/access-control.feature +++ b/test/features/access-control.feature @@ -2,7 +2,7 @@ Feature: User has access restricted access to domains @need-registered-user-john 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" @@ -20,7 +20,7 @@ Feature: User has access restricted access to domains @need-registered-user-bob 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" @@ -38,7 +38,7 @@ Feature: User has access restricted access to domains @need-registered-user-harry 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" diff --git a/test/features/auth-portal-redirection.feature b/test/features/auth-portal-redirection.feature index a0fa36235..1fd5bb5cf 100644 --- a/test/features/auth-portal-redirection.feature +++ b/test/features/auth-portal-redirection.feature @@ -3,16 +3,16 @@ Feature: User is redirected when factors are already validated @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. 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'm redirected to "https://single_factor.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 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" - 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" @@ -25,10 +25,10 @@ Feature: User is redirected when factors are already validated @need-registered-user-john 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" - 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" 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" diff --git a/test/features/authelia.feature b/test/features/authelia.feature index 7c7f472db..dc993c2b8 100644 --- a/test/features/authelia.feature +++ b/test/features/authelia.feature @@ -5,5 +5,5 @@ Feature: Generic tests on Authelia endpoints Then I get error code 401 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" \ No newline at end of file diff --git a/test/features/authentication.feature b/test/features/authentication.feature index 79dcfaf43..851c7e5e6 100644 --- a/test/features/authentication.feature +++ b/test/features/authentication.feature @@ -19,7 +19,7 @@ Feature: Authentication scenarii And I login with user "john" and password "password" And I register a TOTP secret called "Sec0" 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 use "Sec0" as TOTP token handle And I click on "Sign in" @@ -27,12 +27,12 @@ Feature: Authentication scenarii Scenario: User fails TOTP second factor 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 use "BADTOKEN" as TOTP token And I click on "Sign in" 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 - 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/" diff --git a/test/features/redirection.feature b/test/features/redirection.feature index 978580030..e5fc36128 100644 --- a/test/features/redirection.feature +++ b/test/features/redirection.feature @@ -2,7 +2,7 @@ Feature: User is correctly redirected Scenario: User is redirected to authelia when he is not authenticated 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 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 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 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" When I visit "https://public.example.com:8080/secret.html" 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 Given I visit "https://login.example.com:8080/" @@ -67,4 +67,4 @@ Feature: User is correctly redirected When I visit "https://admin.example.com:8080/secret.html" Then I'm redirected to "https://login.example.com:8080/error/403" And I sleep for 5 seconds - And I'm redirected to "https://home.example.com:8080/" \ No newline at end of file + And I'm redirected to "https://home.example.com:8080/" diff --git a/test/features/regulation.feature b/test/features/regulation.feature index 48d5849cc..39504d7eb 100644 --- a/test/features/regulation.feature +++ b/test/features/regulation.feature @@ -20,7 +20,7 @@ Feature: Authelia regulates authentication to avoid brute force @need-registered-user-blackhat 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 "password" to "bad-password" And I click on "Sign in" @@ -36,4 +36,4 @@ Feature: Authelia regulates authentication to avoid brute force And I click on "Sign in" And I use "REGISTERED" as TOTP token handle And I click on "Sign in" - Then I'm redirected to "https://public.example.com:8080/secret.html" \ No newline at end of file + Then I'm redirected to "https://public.example.com:8080/secret.html" diff --git a/test/features/resilience.feature b/test/features/resilience.feature index b252ca66a..a110d4f85 100644 --- a/test/features/resilience.feature +++ b/test/features/resilience.feature @@ -8,8 +8,8 @@ Feature: Authelia keeps user sessions despite the application restart @need-registered-user-john Scenario: Secrets are stored even when Authelia 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 use "REGISTERED" as TOTP token handle And I click on "Sign in" - Then I'm redirected to "https://admin.example.com:8080/secret.html" \ No newline at end of file + Then I'm redirected to "https://admin.example.com:8080/secret.html" diff --git a/test/features/session-timeout.feature b/test/features/session-timeout.feature index 1d31bb9d2..09bfb1fd9 100644 --- a/test/features/session-timeout.feature +++ b/test/features/session-timeout.feature @@ -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" When I sleep for 6 seconds 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 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 sleep for 4 seconds 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" \ No newline at end of file + Then I'm redirected to "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html" diff --git a/test/features/single-factor-domain.feature b/test/features/single-factor-domain.feature index ff2ec279e..db13bb94d 100644 --- a/test/features/single-factor-domain.feature +++ b/test/features/single-factor-domain.feature @@ -1,15 +1,15 @@ Feature: User can access certain subdomains with single factor Scenario: User is redirected to service after first factor if allowed - When I visit "https://login.example.com:8080/?redirect=https%3A%2F%2Fsingle_factor.example.com%3A8080%2Fsecret.html" + When I visit "https://login.example.com:8080/?rd=https://single_factor.example.com:8080/secret.html" And I login with user "john" and password "password" Then I'm redirected to "https://single_factor.example.com:8080/secret.html" Scenario: Redirection after first factor fails if single_factor not allowed. It redirects user to first factor. - When I visit "https://login.example.com:8080/?redirect=https%3A%2F%2Fadmin.example.com%3A8080%2Fsecret.html" + When I visit "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html" And I login with user "john" and password "password" - Then I'm redirected to "https://login.example.com:8080/?redirect=https%3A%2F%2Fadmin.example.com%3A8080%2Fsecret.html" + Then I'm redirected to "https://login.example.com:8080/?rd=https://admin.example.com:8080/secret.html" Scenario: User can login using basic authentication When I request "https://single_factor.example.com:8080/secret.html" with username "john" and password "password" using basic authentication - Then I receive the secret page \ No newline at end of file + Then I receive the secret page diff --git a/test/features/single-factor-only-server.feature b/test/features/single-factor-only-server.feature index e6b8b9f08..4d3fc42f9 100644 --- a/test/features/single-factor-only-server.feature +++ b/test/features/single-factor-only-server.feature @@ -3,7 +3,7 @@ Feature: Server is configured as a single factor only server @need-registered-user-john Scenario: User is redirected to service after first factor if allowed - When I visit "https://login.example.com:8080/?redirect=https%3A%2F%2Fpublic.example.com%3A8080%2Fsecret.html" + When I visit "https://login.example.com:8080/?rd=https://public.example.com:8080/secret.html" And I login with user "john" and password "password" Then I'm redirected to "https://public.example.com:8080/secret.html" diff --git a/test/features/step_definitions/hooks.ts b/test/features/step_definitions/hooks.ts index 9e49156f0..19fb7f6c5 100644 --- a/test/features/step_definitions/hooks.ts +++ b/test/features/step_definitions/hooks.ts @@ -58,7 +58,7 @@ function declareNeedsConfiguration(tag: string, cb: () => BluebirdPromise) return cb() .then(function () { return exec("./scripts/example-commit/dc-example.sh -f " + - "./example/authelia/docker-compose.test.yml up -d authelia &&" + + "./example/compose/authelia/docker-compose.test.yml up -d authelia &&" + " sleep 1"); }) }); @@ -141,4 +141,4 @@ function declareHooksForUser(username: string) { } const users = ["harry", "john", "bob", "blackhat"]; -users.forEach(declareHooksForUser); \ No newline at end of file +users.forEach(declareHooksForUser);