Skip to content

Instantly share code, notes, and snippets.

@haproxytechblog
Last active March 30, 2021 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haproxytechblog/3d15b5cd86f247353c4917a09ca1dc16 to your computer and use it in GitHub Desktop.
Save haproxytechblog/3d15b5cd86f247353c4917a09ca1dc16 to your computer and use it in GitHub Desktop.
Using HAProxy as an API Gateway, Part 5 [Monetization]
$ git clone https://github.com/haproxytechblog/haproxy-api-monetization-demo.git
$ cd haproxy-api-monetization-demo
$ sudo docker-compose up -d
$ curl --request POST \
--url 'http://localhost/auth/realms/weather-services/protocol/openid-connect/token' \
--data 'client_id=acme-corp' \
--data 'client_secret=7f2587ee-a178-4152-bd91-7b758c807759' \
--data 'grant_type=client_credentials'
{"access_token":"eyJhbGciOiJSUzI1NiIsI...","expires_in":300,"refresh_expires_in":0,"token_type":"Bearer","not-before-policy":0,"scope":"bronze"}
global
lua-load /usr/local/share/lua/5.3/jwtverify.lua
setenv OAUTH_ISSUER http://localhost/auth/realms/weather-services
setenv OAUTH_AUDIENCE http://localhost/api/weather-services
setenv OAUTH_PUBKEY_PATH /etc/haproxy/pem/pubkey.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoG0pxfK54qjF8gUzjARji3D2VZ9x7UTRE+
75SoIcSHkPWg8Dlb/DzDNpofG8bB3FyvcqihF0sFTnbQG4+2XKODuxeG2o609YhGvai0hHNZFXZEANM
AoRSEdSq3oCDiAladKez92VjxDjo3W9zLvFhAAYEGQDBvRTqbbHhsCm5fm2k7A3wMB5H0G/i2x6ZDD5
tA7LsIngyJwELSIjFzIfP8xylJdppWwQFJEjYagCXahO4WW+oOMpFs+X1gJ3xBlN6pLsVSNWrKZMe/qp
ZDzQO8qnGoVI7tkZpCkR62B7OyVGzjDB0NwJTwN787xuTURsDNF0Gm3rFgSVnVokn07rqQIDAQAB
-----END PUBLIC KEY-----
frontend fe_api
bind :80
# a stick table stores the count of requests each clients makes
stick-table type ipv6 size 100k expire 1m store http_req_cnt
# allow 'auth' request to go straight through to Keycloak
http-request allow if { path_beg /auth/ }
use_backend keycloak if { path_beg /auth/ }
# deny requests that don't send an access token
http-request deny deny_status 401 unless { req.hdr(authorization) -m found }
# verify access tokens
http-request lua.jwtverify
http-request deny deny_status 403 unless { var(txn.authorized) -m bool }
# add the client's subscription level to the access logs: bronze, silver, gold
http-request capture var(txn.oauth_scopes) len 10
# deny requests after the client exceeds their allowed requests per minute
http-request deny deny_status 429 if { var(txn.oauth_scopes) -m sub bronze } { src,table_http_req_cnt gt 10 }
http-request deny deny_status 429 if { var(txn.oauth_scopes) -m sub silver } { src,table_http_req_cnt gt 100 }
http-request deny deny_status 429 if { var(txn.oauth_scopes) -m sub gold } { src,table_http_req_cnt gt 1000 }
# track clients' request counts. This line will not be called
# once the client is denied above, which prevents them from perpetually
# locking themselves out.
http-request track-sc0 src
default_backend be_api
$ sudo docker-compose restart haproxy
$ curl --request POST \
--url 'http://localhost/auth/realms/weather-services/protocol/openid-connect/token' \
--data 'client_id=acme-corp' \
--data 'client_secret=9e9e2acc-cd15-4878-9e5a-c815d29a976f' \
--data 'grant_type=client_credentials'
$ curl --request GET \
--url http://localhost/api/weather-services/43213 \
--header 'authorization: Bearer [ACCESS_TOKEN]'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment