Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lukaszbudnik/haproxy-auth-gateway
haproxy-auth-gateway is an authentication and authorization gateway for cloud native apps.
https://github.com/lukaszbudnik/haproxy-auth-gateway
authentication authentication-middleware authorization docker haproxy keycloak
Last synced: 3 months ago
JSON representation
haproxy-auth-gateway is an authentication and authorization gateway for cloud native apps.
- Host: GitHub
- URL: https://github.com/lukaszbudnik/haproxy-auth-gateway
- Owner: lukaszbudnik
- License: apache-2.0
- Created: 2021-02-18T11:39:46.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2021-08-24T10:08:55.000Z (over 3 years ago)
- Last Synced: 2024-05-02T06:09:12.004Z (10 months ago)
- Topics: authentication, authentication-middleware, authorization, docker, haproxy, keycloak
- Language: Lua
- Homepage:
- Size: 23.4 KB
- Stars: 15
- Watchers: 4
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# haproxy-auth-gateway ![Docker](https://github.com/lukaszbudnik/haproxy-auth-gateway/workflows/Docker%20Image%20CI/badge.svg)
haproxy-auth-gateway is an authentication and authorization gateway for cloud native apps.
haproxy-auth-gateway features include:
- parsing JWT token from the HTTP Authorization header
- Keycloak realm roles support
- RS256, HS256, HS512 signature verification
- expiration time verification
- issuer verification
- audience verificationhaproxy-auth-gateway can be configured with the following env variables:
- `OAUTH_PUBKEY_PATH` - contains location to issuer public key (mandatory)
- `OAUTH_ISSUER` - contains name of the issuer (optional)
- `OAUTH_AUDIENCE` - contains name of the audience (optional)# Docker image
haproxy-auth-gateway is available on docker hub:
```
docker pull lukasz/haproxy-auth-gateway
```or on ghcr.io:
```
docker pull ghcr.io/lukaszbudnik/haproxy-auth-gateway
```# Example
The below example shows how to deploy & configure `lukasz/haproxy-auth-gateway` in Kubernetes. It also shows how to invoke the Lua verify script and write ACLs.
> If you are interested in running a complete distributed demo app on Kubernetes check out: [lukaszbudnik/keycloak-kubernetes](https://github.com/lukaszbudnik/keycloak-kubernetes). This demo app uses Keycloak as Identity and Access Management solution and haproxy-auth-gateway for transparent authentication and authorization for backend services.
## Kubernetes deployment
haproxy-auth-gateway requires:
- your haproxy config (_file_)
- public key of the JWT issuer (_file_)
- `OAUTH_PUBKEY_PATH` set to the path of the public key of the JWT issuer (_env variable_)
- `OAUTH_ISSUER` and `OAUTH_AUDIENCE` are optional should you want a more fine-grained JWT verification (_env variable_)You can create haproxy config and public key files as config maps:
```bash
kubectl create configmap haproxy-auth-gateway-iss-cert --from-file=config/hotel.pem
kubectl create configmap haproxy-auth-gateway-haproxy-cfg --from-file=config/haproxy.cfg
```Then you can map them to volumes and then mount them into haproxy-auth-gateway container. In the container spec you also set the env variables:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
labels:
app.kubernetes.io/name: gateway
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: gateway
template:
metadata:
labels:
app.kubernetes.io/name: gateway
spec:
containers:
- name: gateway
image: lukasz/haproxy-auth-gateway
env:
- name: OAUTH_PUBKEY_PATH
value: /etc/certs/hotel.pem
- name: OAUTH_ISSUER
value: issuer_is_optional
- name: OAUTH_AUDIENCE
value: audience_is_optional
ports:
- containerPort: 80
volumeMounts:
- name: iss-cert
mountPath: /etc/certs
- name: haproxy-cfg
mountPath: /usr/local/etc/haproxy
volumes:
- name: haproxy-cfg
configMap:
name: haproxy-auth-gateway-haproxy-cfg
- name: iss-cert
configMap:
name: haproxy-auth-gateway-iss-cert
---
apiVersion: v1
kind: Service
metadata:
name: gateway
labels:
app.kubernetes.io/name: gateway
spec:
type: ClusterIP
clusterIP: None
selector:
app.kubernetes.io/name: gateway
ports:
- protocol: TCP
port: 80
```Then we are ready to deploy haproxy-auth-gateway:
```
kubectl apply -f gateway.yaml
```## haproxy ACL
haproxy-auth-gateway will verify passed JWT and will (if all good):
- set `txn.authorized` variable to `true`
- set `txn.roles` variable to a comma separated list of `realm_access.roles`Above variables can be used in haproxy ACLs.
For example:
```
# deny if no Authorization header sent
http-request deny unless { req.hdr(authorization) -m found }
# invoke the jwtverify Lua script
http-request lua.jwtverify
# check if authorized successfully
http-request deny unless { var(txn.authorized) -m bool }
# check roles
http-request deny if PATH_camarero ! { var(txn.roles) -m sub camarero }
```# Troubleshooting
The script outputs many useful debug messages. To enable debug add the following configuration to you `haproxy.cfg`:
```
global
log stdout local0 debugdefaults
log global
```## Sample JWT
A sample JWT token generated by Keycloak looks like this:
```
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXejFuaDNCWDI4UHMxVEMzSDRoOW52Q1VWRXpjVVBzQms4Z1NmeEp4ZS1JIn0.eyJleHAiOjE2MTM4NTQ3OTgsImlhdCI6MTYxMzg1Mzg5OCwiYXV0aF90aW1lIjoxNjEzODUzNjk2LCJqdGkiOiIxMmI1YTMxYS1hYjM1LTQxMDMtYTkxNC0wZjRlODUzMzg4ZjUiLCJpc3MiOiJodHRwczovL2F1dGgubG9jYWx0ZXN0Lm1lL2F1dGgvcmVhbG1zL2hvdGVsIiwic3ViIjoiMWE1NWUxMjktZjliYi00ZDYwLWJlZDEtMGJhYmIwOWJlZTNlIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicmVhY3QiLCJub25jZSI6Ijg4NGNiMzY1LTRjMTQtNDZhYS04ZTBjLWViM2Q3ZjBjYTRmMCIsInNlc3Npb25fc3RhdGUiOiI3NDZhNDZhZC1hY2Y3LTRhMTYtYWI2Yy1iMWZhNWE1YTgxZDMiLCJhY3IiOiIwIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY29jaW5lcmEiLCJkb25jZWxsYSIsImNhbWFyZXJvIl19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiQW5nZWxhIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYW5nZWxhIiwiZ2l2ZW5fbmFtZSI6IkFuZ2VsYSJ9.kkv2K-XYpHexnKmCoyNED_pO7G8hNI8hi2WCUzhpErkvrazNNZmUYZ8ZAjiybpi1u6ouc2EsHGykTNhUBD2jRhb2dWHYqcEEDaIn9MUq62B-nbTIcB-6vf1SrKnY_Vdnq_olmV_MhIJSQjPbDfcCVKKiUxHYmSBc9Vuno-enPehfUb_EpoRaM24SfJ0WDU281rTPxsgAJBdB4Yg0E9KMfCgaXkwRaHXMEGVpzHHqdi8S1lWwxs12Par-Qz4HqP-Tsw6KqNPU11dG3v6H_Q2fWmDsX5vvMqnmWkMQOFzco2fffsx7lcClPxNw3VghSVT-qB_7dMKUoT-DfyIo1Rcbqw
```When parsed and decoded becomes the following.
Header:
```json
{
"alg": "RS256",
"typ": "JWT",
"kid": "Wz1nh3BX28Ps1TC3H4h9nvCUVEzcUPsBk8gSfxJxe-I"
}
```Payload:
```json
{
"exp": 1613854798,
"iat": 1613853898,
"auth_time": 1613853696,
"jti": "12b5a31a-ab35-4103-a914-0f4e853388f5",
"iss": "https://auth.localtest.me/auth/realms/hotel",
"sub": "1a55e129-f9bb-4d60-bed1-0babb09bee3e",
"typ": "Bearer",
"azp": "react",
"nonce": "884cb365-4c14-46aa-8e0c-eb3d7f0ca4f0",
"session_state": "746a46ad-acf7-4a16-ab6c-b1fa5a5a81d3",
"acr": "0",
"allowed-origins": ["http://localhost:3000"],
"realm_access": {
"roles": ["cocinera", "doncella", "camarero"]
},
"scope": "openid email profile",
"email_verified": false,
"name": "Angela",
"preferred_username": "angela",
"given_name": "Angela"
}
```Public key:
```
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn1SYrKiXgJembEG1emG
lUw/NliK0tOTeKr8eBp7TZxI8D9k9FUkfzEeQyWekShPt3yTG9boZ9Sq/K7FAfs7
vXFG+kTKYYXysvfdkHHKJnPWEAJgqj3vDEpHB/Xqw5OtqOkSNPNYOxJ65ZmmZVNB
77NpGK5xW5s7xc7XXvLuILhfbOQXlObPbMnjVcnQSGHjmfbtTKsQ/im6ayxtShsL
FQgEJycplJU21WRy3T9cDHpGOMF3LehFIOmsxspcuC/idS0Nber3Fuw9QndSHZQL
KPTkDlyacPu9SyOJiMmD9S4QOZo9UVQWA8JlKa+KuL6TXyZ1OZdSkPSX1o1xeH7L
ewIDAQAB
-----END PUBLIC KEY-----
```# Original project
haproxy-auth-gateway is based on great project from haproxytech folks: https://github.com/haproxytech/haproxy-lua-oauth.
haproxy-auth-gateway contains changes to support Keycloak realm roles out of the box.