mirror of
https://github.com/funkypenguin/geek-cookbook/
synced 2025-12-13 09:46:23 +00:00
Add Traefik Forward Auth
This commit is contained in:
110
manuscript/ha-docker-swarm/traefik-forward-auth.md
Normal file
110
manuscript/ha-docker-swarm/traefik-forward-auth.md
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Traefik Forward Auth
|
||||||
|
|
||||||
|
Now that we have Traefik deployed, automatically exposing SSL access to our Docker Swarm services using LetsEncrypt wildcard certificates, let's pause to consider that we may not _want_ some services exposed directly to the internet...
|
||||||
|
|
||||||
|
..Wait, why not? Well, Traefik doesn't provide any form of authentication, it simply secures the **transmission** of the service between Docker Swarm and the end user. If you were to deploy a service with no native security (*[Radarr](/recipes/autopirate/radarr/) or [Sonarr](/recipes/autopirate/sonarr/) come to mind*), then anybody would be able to use it! Even services which _may_ have a layer of authentication **might** not be safe to expose publically - often open source projects may be maintained by enthusiasts who happily add extra features, but just pay lip service to security, on the basis that "*it's the user's problem to secure it in their own network*".
|
||||||
|
|
||||||
|
To give us confidence that **we** can access our services, but BadGuys(tm) cannot, we'll deploy a layer of authentication **in front** of Traefik, using [Forward Authentication](https://docs.traefik.io/configuration/entrypoints/#forward-authentication).
|
||||||
|
|
||||||
|
## Ingredients
|
||||||
|
|
||||||
|
1. [Docker swarm cluster](/ha-docker-swarm/design/) with [persistent shared storage](/ha-docker-swarm/shared-storage-ceph)
|
||||||
|
2. [Traefik](/ha-docker-swarm/traefik/) configured per design
|
||||||
|
3. An account with an OpenID-Connect provider (Google, [KeyCloak](/recipes/keycloak/), Microsoft, etc..)
|
||||||
|
|
||||||
|
## Preparation
|
||||||
|
|
||||||
|
### Create OAuth credentials
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
This recipe will demonstrate using Google OAuth for traefik forward authentication, but it's also possible to use a self-hosted KeyCloak instance - see the [KeyCloak](/recipes/keycloak/) recipe for more details!
|
||||||
|
|
||||||
|
Log into https://console.developers.google.com/, create a new project then search for and select "Credentials" in the search bar.
|
||||||
|
|
||||||
|
Fill out the "OAuth Consent Screen" tab, and then click, "**Create Credentials**" > "**OAuth client ID**". Select "**Web Application**", fill in the name of your app, skip "**Authorized JavaScript origins**" and fill "**Authorized redirect URIs**" with either all the domains you will allow authentication from, appended with the url-path (*e.g. https://radarr.example.com/_oauth, https://radarr.example.com/_oauth, etc*), or if you don't like frustration, use a "auth host" URL instead, like "*https://auth.example.com/_oauth*" (see below for details)
|
||||||
|
|
||||||
|
Store your client ID and secret safely - you'll need them for the next step.
|
||||||
|
|
||||||
|
|
||||||
|
### Prepare environment
|
||||||
|
|
||||||
|
Create `traefik-forward-auth.env` as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
CLIENT_ID=<your client id>
|
||||||
|
CLIENT_SECRET=<your client secret>
|
||||||
|
OIDC_ISSUER=https://accounts.google.com
|
||||||
|
SECRET=<a random string, make it up>
|
||||||
|
# uncomment this to use a single auth host instead of individual redirect_uris (recommended but advanced)
|
||||||
|
#AUTH_HOST=auth.example.com
|
||||||
|
COOKIE_DOMAINS=example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prepare the docker service config
|
||||||
|
|
||||||
|
This is a small container, you can simply add the following content to the existing `traefik.yml` deployed in the previous [Traefik](/recipes/traefik/) recipe:
|
||||||
|
|
||||||
|
```
|
||||||
|
traefik-forward-auth:
|
||||||
|
image: thomseddon/traefik-forward-auth
|
||||||
|
env_file: /var/data/config/keycloak/traefik-forward-auth.env
|
||||||
|
networks:
|
||||||
|
- public
|
||||||
|
# Uncomment these lines if you're using auth host mode
|
||||||
|
#deploy:
|
||||||
|
# labels:
|
||||||
|
# - traefik.port=4181
|
||||||
|
# - traefik.frontend.rule=Host:auth.example.com
|
||||||
|
# - traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
|
||||||
|
# - traefik.frontend.auth.forward.trustForwardHeader=true
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're not confident that forward authentication is working, add a simple "whoami" test container, to help debug traefik forward auth, before attempting to add it to a more complex container.
|
||||||
|
|
||||||
|
```
|
||||||
|
# This simply validates that traefik forward authentication is working
|
||||||
|
whoami:
|
||||||
|
image: containous/whoami
|
||||||
|
networks:
|
||||||
|
- public
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
- traefik.frontend.rule=Host:whoami.example.com
|
||||||
|
- traefik.port=80
|
||||||
|
- traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
|
||||||
|
- traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User
|
||||||
|
- traefik.frontend.auth.forward.trustForwardHeader=true
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
I share (_with my [patreon patrons](https://www.patreon.com/funkypenguin)_) a private "_premix_" git repository, which includes necessary docker-compose and env files for all published recipes. This means that patrons can launch any recipe with just a ```git pull``` and a ```docker stack deploy``` 👍
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Serving
|
||||||
|
|
||||||
|
### Launch
|
||||||
|
|
||||||
|
Redeploy traefik with ```docker stack deploy traefik -c /var/data/traefik/docker-compose.yml```, to launch the traefik-forward-auth container.
|
||||||
|
|
||||||
|
### Test
|
||||||
|
|
||||||
|
Browse to https://whoami.example.com (*obviously, customized for your domain and having created a DNS record*), and all going according to plan, you should be redirected to a Google login. Once successfully logged in, you'll be directed to the basic whoami page.
|
||||||
|
|
||||||
|
### Dessert
|
||||||
|
|
||||||
|
What have we achieved? By adding an additional three simple labels to any service, we can secure any service behind our choice of OAuth provider, with minimal processing / handling overhead.
|
||||||
|
|
||||||
|
|
||||||
|
## Chef's Notes
|
||||||
|
|
||||||
|
1. Traefik forward auth replaces the use of [oauth_proxy containers](/reference/oauth_proxy/) found in some of the existing recipes
|
||||||
|
2. [@thomaseddon's original version](https://github.com/thomseddon/traefik-forward-auth) of traefik-forward-auth only works with Google currently, but I've created a [fork](https://www.github.com/funkypenguin/traefik-forward-auth) of a [fork](https://github.com/noelcatt/traefik-forward-auth), which implements generic OIDC providers.
|
||||||
|
3. I reviewed several implementations of forward authenticators for Traefik, but found most to be rather heavy-handed, or specific to a single auth provider. @thomaseddon's go-based docker image is 7MB in size, and with the generic OIDC patch (above), it can be extended to work with any OIDC provider.
|
||||||
|
4. No, not github natively, but you can ferderate GitHub into KeyCloak, and then use KeyCloak as the OIDC provider.
|
||||||
|
|
||||||
|
### Tip your waiter (donate) 👏
|
||||||
|
|
||||||
|
Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏
|
||||||
|
|
||||||
|
### Your comments? 💬
|
||||||
@@ -55,8 +55,10 @@ acmeLogging = true
|
|||||||
onDemand = true
|
onDemand = true
|
||||||
OnHostRule = true
|
OnHostRule = true
|
||||||
|
|
||||||
|
# Request wildcard certificates per https://docs.traefik.io/configuration/acme/#wildcard-domains
|
||||||
[[acme.domains]]
|
[[acme.domains]]
|
||||||
main = "<your primary domain>"
|
main = "*.example.com"
|
||||||
|
sans = ["example.com"]
|
||||||
|
|
||||||
# Redirect all HTTP to HTTPS (why wouldn't you?)
|
# Redirect all HTTP to HTTPS (why wouldn't you?)
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
@@ -74,7 +76,7 @@ watch = true
|
|||||||
|
|
||||||
[docker]
|
[docker]
|
||||||
endpoint = "tcp://127.0.0.1:2375"
|
endpoint = "tcp://127.0.0.1:2375"
|
||||||
domain = "<your primary domain>"
|
domain = "example.com"
|
||||||
watch = true
|
watch = true
|
||||||
swarmmode = true
|
swarmmode = true
|
||||||
```
|
```
|
||||||
@@ -94,7 +96,7 @@ version: "3"
|
|||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik
|
image: traefik
|
||||||
command: --web --docker --docker.swarmmode --docker.watch --docker.domain=funkypenguin.co.nz --logLevel=DEBUG
|
command: --web --docker --docker.swarmmode --docker.watch --docker.domain=example.com --logLevel=DEBUG
|
||||||
ports:
|
ports:
|
||||||
- target: 80
|
- target: 80
|
||||||
published: 80
|
published: 80
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ I like to protect my public-facing web UIs with an [oauth_proxy](/reference/oaut
|
|||||||
## Ingredients
|
## Ingredients
|
||||||
|
|
||||||
1. [Docker swarm cluster](/ha-docker-swarm/design/) with [persistent shared storage](/ha-docker-swarm/shared-storage-ceph.md)
|
1. [Docker swarm cluster](/ha-docker-swarm/design/) with [persistent shared storage](/ha-docker-swarm/shared-storage-ceph.md)
|
||||||
2. [Traefik](/ha-docker-swarm/traefik_public) configured per design
|
2. [Traefik](/ha-docker-swarm/traefik/) configured per design
|
||||||
3. DNS entry for the hostname you intend to use, pointed to your [keepalived](ha-docker-swarm/keepalived/) IP
|
3. DNS entry for the hostname you intend to use, pointed to your [keepalived](ha-docker-swarm/keepalived/) IP
|
||||||
|
|
||||||
## Preparation
|
## Preparation
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ nav:
|
|||||||
- Keepalived: ha-docker-swarm/keepalived.md
|
- Keepalived: ha-docker-swarm/keepalived.md
|
||||||
- Docker Swarm Mode: ha-docker-swarm/docker-swarm-mode.md
|
- Docker Swarm Mode: ha-docker-swarm/docker-swarm-mode.md
|
||||||
- Traefik: ha-docker-swarm/traefik.md
|
- Traefik: ha-docker-swarm/traefik.md
|
||||||
|
- Traefik Forward Auth: ha-docker-swarm/traefik-forward-auth.md
|
||||||
- Registry: ha-docker-swarm/registry.md
|
- Registry: ha-docker-swarm/registry.md
|
||||||
- Mail Server: recipes/mail.md
|
- Mail Server: recipes/mail.md
|
||||||
- Duplicity: recipes/duplicity.md
|
- Duplicity: recipes/duplicity.md
|
||||||
@@ -69,6 +70,7 @@ nav:
|
|||||||
- iBeacon: recipes/homeassistant/ibeacon.md
|
- iBeacon: recipes/homeassistant/ibeacon.md
|
||||||
- Huginn: recipes/huginn.md
|
- Huginn: recipes/huginn.md
|
||||||
- Kanboard: recipes/kanboard.md
|
- Kanboard: recipes/kanboard.md
|
||||||
|
- KeyCloak: recipes/keycloak.md
|
||||||
- Miniflux: recipes/miniflux.md
|
- Miniflux: recipes/miniflux.md
|
||||||
- Munin: recipes/munin.md
|
- Munin: recipes/munin.md
|
||||||
- NextCloud: recipes/nextcloud.md
|
- NextCloud: recipes/nextcloud.md
|
||||||
@@ -104,7 +106,6 @@ nav:
|
|||||||
- GitLab Runner: recipes/gitlab-runner.md
|
- GitLab Runner: recipes/gitlab-runner.md
|
||||||
- Gollum: recipes/gollum.md
|
- Gollum: recipes/gollum.md
|
||||||
- InstaPy: recipes/instapy.md
|
- InstaPy: recipes/instapy.md
|
||||||
- KeyCloak: recipes/keycloak.md
|
|
||||||
- Minio: recipes/minio.md
|
- Minio: recipes/minio.md
|
||||||
- OpenLDAP: recipes/openldap.md
|
- OpenLDAP: recipes/openldap.md
|
||||||
- Piwik: recipes/piwik.md
|
- Piwik: recipes/piwik.md
|
||||||
|
|||||||
Reference in New Issue
Block a user