-
-
Notifications
You must be signed in to change notification settings - Fork 41
Using nginx sso with haproxy and SPOE
- Docker
- haproxy
- nginx-sso
- haproxy-spoe-server
- A python script as glue between haproxy and nginx-sso
Two docker containers are used. One for nginx-sso itself, and the other is an SPOE agent for haproxy that can run the python script.
mkdir -p /srv/spoe-server
docker run \
--name=spoe-server \
-p 172.17.0.1:12345:12345 \
--restart=unless-stopped \
--volume="/srv/spoe-server:/data" \
-d mjbnz/haproxy-spoe-server:latestmkdir -p /srv/nginx-sso
docker run \
--name=nginx-sso \
-p 172.17.0.1:8082:8082 \
--restart=unless-stopped \
--volume="/srv/nginx-sso:/data" \
-d luzifer/nginx-sso:latestA python script is used as the glue between haproxy-spoe-server and nginx-sso. After deploying the haproxy-spoe-server docker container, replace the content of spoe_python.py in the /data volume (/srv/spoe-server/spoe_python.py if you used the above command) with the following, then restart the haproxy-spoa-server container:
import spoa
import ipaddress
import requests
auth_url = "http://172.17.0.1:8082/auth"
def check_sso_auth(args):
raw_args = args
args = dict()
for a in raw_args:
if a['value'] is not None:
args[a['name']] = str(a['value'])
authed = False
headers = {
'X-Real-IP': args['ip'],
'X-Host': args['host'],
'X-Origin-URI': args['uri']
}
if 'ff' in args: headers['X-Forwarded-For'] = args['ff']
if 'cookies' in args: headers['Cookie'] = args['cookies']
r = requests.get(auth_url, headers=headers)
if r.status_code == 200:
authed = True
spoa.set_var_str("cookie", spoa.scope_txn, r.headers['Set-Cookie'])
spoa.set_var_boolean("auth", spoa.scope_txn, authed)
return
spoa.register_message("check-sso-auth", check_sso_auth)The following contains the absolute basics, you should ensure that the rest of the configuration is fleshed out how you need it for your environment. It covers the configuration for SPOE, and how to deal with the redirects to nginx-sso for the login form. It also doesn't have any SSL configuration, that's left up to you.
Note that the filter being applied can be placed in the frontend, but you cannot selectively apply it based on the Host: header (to not apply it to the nginx-sso login domain name or path), so take care if you need to do this. The python script would need a small addition made to not bother asking nginx-sso for auth if the Host: header is the login domain for example.
frontend fe-http
mode http
bind :80
acl is_login hdr(host) -i login.yourdomain.com
use_backend be-login-nginx-sso if is_login
default_backend be-http
backend be-http
description Primary webserver
filter spoe engine spoa-server config spoa-server.spoe.conf
acl is_authed var(txn.sso.auth) -m bool
http-request set-var(req.sch) str(https) if { ssl_fc }
http-request set-var(req.sch) str(http) if !{ ssl_fc }
http-request redirect code 302 location http://login.yourdomain.com/login?go=%[var(req.sch)]://%[hdr(host)]%[url] unless is_authed
http-response add-header Set-Cookie %[var(txn.sso.cookie)] if is_authed
server webserver-1 ip.of.your.webserver:80
backend be-login-nginx-sso
description nginx-sso login page
option forwardfor
server nginx-sso 172.17.0.1:8082
backend be-spoe-server
mode tcp
server spoe-server 172.17.0.1:12345
[spoa-server]
spoe-agent spoa-server
messages check-sso-auth
option var-prefix sso
timeout hello 100ms
timeout idle 30s
timeout processing 15ms
use-backend be-spoe-server
spoe-message check-sso-auth
args ip=src ff=req.fhdr(x-forwarded-for) host=req.fhdr(host) uri=url cookies=req.fhdr(cookie)
event on-backend-http-request