Skip to content

Commit a6777be

Browse files
Added an example
1 parent b8ada2a commit a6777be

13 files changed

+715
-13
lines changed

README.md

+45-11
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,7 @@ chmod +x ./install.sh
2020
sudo ./install.sh luaoauth
2121
```
2222

23-
You have several installation modes:
24-
25-
| Command | Meaning |
26-
|---------------------------|-------------------------------------------------------------------------------------------|
27-
| `sudo install.sh luaoauth` | Installs jwtverify.lua and its dependencies to **/usr/local/share/lua/5.3/jwtverify.lua** |
28-
| `sudo install.sh haproxy` | Installs HAProxy |
29-
| `sudo install.sh all` | Installs HAProxy and jwtverify.lua and its dependencies |
30-
31-
## Sample
32-
33-
A sample application can be found at https://github.com/haproxytechblog/haproxy-jwt-vagrant.
23+
This installs jwtverify.lua and its dependencies to **/usr/local/share/lua/5.3/jwtverify.lua**.
3424

3525
## Usage
3626

@@ -72,3 +62,47 @@ After calling `http-request lua.jwtverify`, you get access to variables for each
7262
* `var(txn.oauth.scope)`
7363

7464
For example, you could track rate limiting based on the clientId or set different rate limit thresholds based on the scope.
65+
66+
## Example
67+
68+
Try it out using the Docker Compose.
69+
70+
1. Sign up for a free account at https://auth0.com/ and create a new API.
71+
1. Give the API any name, such as "My OAuth Test" and set the identifier to "https://api.mywebsite.com".
72+
1. Once created, go to the API's "Permissions" tab and add permissions (aka scopes) that grant users different levels of access. The colon syntax is just a personal style, and colons do not mean anything special.
73+
74+
| permission | description |
75+
|-------------|-----------------------|
76+
| read:myapp | Read access to my app |
77+
| write:myapp | Write access to myapp |
78+
79+
1. Now that you have an API defined in Auth0, add an application that is allowed to authenticate to it. Go to the "Applications" tab and add a new "Machine to Machine Application" and select the API you just created. Give it the "read:myapp" and "write:myapp"permissions (or only one or the other).
80+
1. On the Settings page for the new application, go to **Advanced Settings > Certificates** and download the certificate in PEM format. HAProxy will validate the access tokens against this certificate, which was signed by the OAuth provider, Auth0.
81+
82+
1. Convert it first using `openssl x509 -pubkey -noout -in ./mycert.pem > pubkey.pem` and save **pubkey.pem** to **/example/haproxy/pem/pubkey.pem**.
83+
1. Edit **example/haproxy/haproxy.cfg**:
84+
85+
* replace the `OAUTH_ISSUER` variable in the global section with the Auth0 domain URL with your own, such as https://myaccount.auth0.com/.
86+
* replace the `OAUTH_AUDIENCE` variable with your API name in Auth0, such as "https://api.mywebsite.com".
87+
* replace the `OAUTH_PUBKEY_PATH` variable with the path to your PEM certificate. (also update the docker-compose file)
88+
89+
1. Create the environment with Docker Compose:
90+
```
91+
$ docker-compose -f docker-compose.ubuntu.example.yml build
92+
$ docker-compose -f docker-compose.ubuntu.example.yml up
93+
```
94+
1. Get a JSON web token (JWT) from your authentication server by going to your application on the Auth0 website and following the *Quick Start*.
95+
1. Make requests to https://localhost/api/myapp and attach the JWT in the Authorization header. You should get a successful response.
96+
97+
```
98+
$ curl --request GET \
99+
-k \
100+
--url https://localhost/api/myapp \
101+
--header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJEVkNSVFZHTmpZNU5rVTJSVUV3TnpoRk56UkJRalU0TjBFeU5EWTNSRU01TWtaRFJqTkNNUSJ9.eyJpc3MiOiJodHRwczovL25pY2tyYW00NC5hdXRoMC5jb20vIiwic3ViIjoicm9DTHRDTlZycW0zNmVYTzJxcE84cjEzeFBmQno1NklAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vYXBpLm15d2Vic2l0ZS5jb20iLCJpYXQiOjE2NDgzMTQ2NjAsImV4cCI6MTY0ODQwMTA2MCwiYXpwIjoicm9DTHRDTlZycW0zNmVYTzJxcE84cjEzeFBmQno1NkkiLCJzY29wZSI6InJlYWQ6bXlhcHAgd3JpdGU6bXlhcHAiLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.tEhJ0hKlqy9KRrS00we1Z6Y0CwGg5tAOmZ3qQYLYEwl1uymZ8OfJD9iGgPe5QhLJCTD-iwC18hWSwBMzNRLrjcjp1__hHOOyJRRoqekezS7NoHCMOKGLRis5EcfXMyb58yVxwrKIovHSRaEf0emg5NovQ2bdI3UpMThXnzlLhIH_SX5yRUtTxQ_qvO7xS9lZBNVYG9lYlNtU_Ih6dKCKNRUrMm8xsj2jLyR5_v3LcxgwzhK2VF01DZ9wyEgfHgs3H2AP6yJEZkmd9B1chO5Xf3f4klujsxvAb6RqTCwpGWmjRPY6SENkY2QX-PHOYVAc4zPvuauwx9Ojd4khA_KKfA'
102+
```
103+
104+
A successful response:
105+
106+
```
107+
["robo-hamster","space-hamster","commando-hamster","pirate-hmaster"]
108+
```

docker-compose.ubuntu.example.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
version: "3"
3+
services:
4+
5+
server1:
6+
image: example/web:latest
7+
build:
8+
context: example/web
9+
environment:
10+
- "name=server1"
11+
12+
haproxy:
13+
image: example/haproxy-ubuntu
14+
build:
15+
context: example/haproxy
16+
dockerfile: Dockerfile-ubuntu
17+
volumes:
18+
- ./example/haproxy/haproxy.cfg:/etc/haproxy/haproxy.cfg
19+
- ./example/haproxy/pem/pubkey.pem:/etc/haproxy/pem/pubkey.pem
20+
- ./example/haproxy/pem/test.com.pem:/etc/haproxy/pem/test.com.pem
21+
ports:
22+
- "80:80"
23+
- "443:443"
24+
- "8080:8080"
25+
- "9000:9000"
26+
depends_on:
27+
- server1

example/haproxy/Dockerfile-ubuntu

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM haproxytech/haproxy-ubuntu:2.5
2+
WORKDIR /usr/src
3+
COPY . .
4+
RUN ./install.sh luaoauth

example/haproxy/haproxy.cfg

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
global
2+
log stdout format raw local0
3+
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
4+
ssl-default-bind-options ssl-min-ver TLSv1.1
5+
chroot /var/lib/haproxy
6+
user haproxy
7+
group haproxy
8+
lua-load /usr/local/share/lua/5.3/jwtverify.lua
9+
10+
# Replace the Auth0 URL with your own:
11+
setenv OAUTH_ISSUER https://nickram44.auth0.com/
12+
setenv OAUTH_AUDIENCE https://api.mywebsite.com
13+
setenv OAUTH_PUBKEY_PATH /etc/haproxy/pem/pubkey.pem
14+
15+
defaults
16+
log global
17+
mode http
18+
option httplog
19+
timeout connect 10s
20+
timeout client 30s
21+
timeout server 30s
22+
option http-buffer-request
23+
24+
frontend api_gateway
25+
bind :443 ssl crt /etc/haproxy/pem/test.com.pem alpn h2,http1.1
26+
default_backend apiservers
27+
http-request deny unless { req.hdr(authorization) -m found }
28+
http-request lua.jwtverify
29+
http-request deny unless { var(txn.authorized) -m bool }
30+
http-request deny if { path_beg /api/myapp } { method GET } ! { var(txn.oauth.scope) -m sub read:myapp }
31+
http-request deny if { path_beg /api/myapp } { method POST PUT DELETE } ! { var(txn.oauth.scope) -m sub write:myapp }
32+
33+
backend apiservers
34+
balance roundrobin
35+
server server1 server1:80

example/haproxy/install.sh

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/bin/bash
2+
SOURCE_DIR=/usr/src
3+
LUA_VERSION=5.3.5
4+
5+
install_luaoauth_var=false
6+
rhel_based=false
7+
debian_based=false
8+
lua_installed=false
9+
lua_dep_dir=/usr/local/share/lua/5.3/
10+
11+
if [ -f /etc/redhat-release ]; then
12+
rhel_based=true
13+
elif [ -f /etc/debian_version ]; then
14+
debian_based=true
15+
fi
16+
17+
cd $SOURCE_DIR
18+
19+
display_working() {
20+
pid=$1
21+
spin='-\|/'
22+
i=0
23+
while kill -0 $pid 2>/dev/null
24+
do
25+
i=$(( (i+1) %4 ))
26+
printf "\r${spin:$i:1}"
27+
sleep .1
28+
done
29+
}
30+
31+
download_rhel_lua() {
32+
printf "\r[+] Downloading Lua\n"
33+
curl -sLO https://www.lua.org/ftp/lua-$LUA_VERSION.tar.gz
34+
tar xf lua-$LUA_VERSION.tar.gz && rm lua-$LUA_VERSION.tar.gz
35+
}
36+
37+
install_yum_deps() {
38+
printf "\r[+] Installing yum dependencies\n"
39+
yum -y install gcc openssl-devel readline-devel systemd-devel unzip >/dev/null 2>&1
40+
}
41+
42+
build_lua() {
43+
printf "\r[+] Building Lua\n"
44+
cd $SOURCE_DIR/lua-$LUA_VERSION
45+
make linux test >/dev/null
46+
}
47+
48+
install_rhel_lua() {
49+
printf "\r[+] Installing Lua\n"
50+
cd $SOURCE_DIR/lua-$LUA_VERSION
51+
make install >/dev/null
52+
}
53+
54+
install_deb_lua() {
55+
printf "\r[+] Installing Lua\n"
56+
apt-get update >/dev/null 2>&1
57+
apt-get install -y software-properties-common unzip build-essential libssl-dev lua5.3 liblua5.3-dev >/dev/null 2>&1
58+
}
59+
60+
install_luaoauth_deps() {
61+
printf "\r[+] Installing haproxy-lua-oauth dependencies\n"
62+
63+
if [ ! -e $lua_dep_dir ]; then
64+
mkdir -p $lua_dep_dir;
65+
fi;
66+
67+
apt-get update >/dev/null 2>&1
68+
apt-get install -y build-essential liblua5.3-dev libssl-dev unzip >/dev/null 2>&1
69+
70+
cd $SOURCE_DIR
71+
72+
curl -sLO https://github.com/rxi/json.lua/archive/refs/heads/master.zip
73+
unzip -qo master.zip && rm master.zip
74+
mv json.lua-master/json.lua $lua_dep_dir
75+
76+
curl -sLO https://github.com/lunarmodules/luasocket/archive/refs/heads/master.zip
77+
unzip -qo master.zip && rm master.zip
78+
cd luasocket-master/
79+
make clean all install-both LUAINC=/usr/include/lua5.3/ >/dev/null
80+
cd ..
81+
82+
curl -sLO https://github.com/wahern/luaossl/archive/refs/heads/master.zip
83+
unzip -qo master.zip && rm master.zip
84+
cd luaossl-master/
85+
make install >/dev/null
86+
cd ..
87+
}
88+
89+
install_luaoauth() {
90+
printf "\r[+] Installing haproxy-lua-oauth\n"
91+
if [ ! -e $lua_dep_dir ]; then
92+
mkdir -p $lua_dep_dir;
93+
fi;
94+
95+
cd $SOURCE_DIR
96+
97+
mv ./lib/*.lua $lua_dep_dir
98+
}
99+
100+
case $1 in
101+
luaoauth)
102+
install_luaoauth_var=true
103+
;;
104+
*)
105+
echo "Usage: install.sh luaoauth"
106+
esac
107+
108+
if $install_luaoauth_var; then
109+
# Install Lua JWT
110+
# if ! $lua_installed; then
111+
# if $rhel_based; then
112+
# download_and_install_lua=(install_yum_deps download_rhel_lua build_lua install_rhel_lua)
113+
# elif $debian_based; then
114+
# download_and_install_lua=(install_deb_lua)
115+
# fi
116+
# for func in ${download_and_install_lua[*]}; do
117+
# $func &
118+
# display_working $!
119+
# done
120+
# fi
121+
download_and_install_luaoauth=(install_luaoauth_deps install_luaoauth)
122+
for func in ${download_and_install_luaoauth[*]}; do
123+
$func &
124+
display_working $!
125+
done
126+
fi

example/haproxy/lib/base64.lua

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--
2+
-- base64.lua
3+
--
4+
-- URL safe base64 encoder/decoder
5+
--
6+
7+
-- https://github.com/diegonehab/luasocket
8+
local mime = require 'mime'
9+
local _M = {}
10+
11+
--- base64 encoder
12+
--
13+
-- @param s String to encode (can be binary data)
14+
-- @return Encoded string
15+
function _M.encode(s)
16+
local u
17+
local padding_len = 2 - ((#s-1) % 3)
18+
19+
if padding_len > 0 then
20+
u = mime.b64(s):sub(1, - padding_len - 1)
21+
else
22+
u = mime.b64(s)
23+
end
24+
25+
if u then
26+
return u:gsub('[+]', '-'):gsub('[/]', '_')
27+
else
28+
return nil
29+
end
30+
end
31+
32+
--- base64 decoder
33+
--
34+
-- @param s String to decode
35+
-- @return Decoded string (can be binary data)
36+
function _M.decode(s)
37+
local e = s:gsub('[-]', '+'):gsub('[_]', '/')
38+
local u, _ = mime.unb64(e .. string.rep('=', 3 - ((#s - 1) % 4)))
39+
40+
return u
41+
end
42+
43+
return _M

0 commit comments

Comments
 (0)