Skip to content

Commit

Permalink
Merge f2b7223 into 2510459
Browse files Browse the repository at this point in the history
  • Loading branch information
Darguelles committed Mar 23, 2021
2 parents 2510459 + f2b7223 commit bcecd92
Show file tree
Hide file tree
Showing 19 changed files with 239 additions and 139 deletions.
7 changes: 4 additions & 3 deletions .env
Expand Up @@ -2,17 +2,18 @@ BUILD_IMG_NAME=nokia/kong-oidc
INTEGRATION_PATH=test/docker/integration
UNIT_PATH=test/docker/unit

KONG_BASE_TAG=:1.0-centos
KONG_BASE_TAG=:2.2.1-centos
KONG_TAG=
KONG_DB_TAG=:10.1
KONG_DB_TAG=:12
KONG_DB_PORT=5432
KONG_DB_USER=kong
KONG_DB_PW=kong
KONG_DB_NAME=kong
KONG_SESSION_STORE_PORT=6379
KONG_HTTP_PROXY_PORT=8000
KONG_HTTP_ADMIN_PORT=8001

KEYCLOAK_TAG=:4.8.3.Final
KEYCLOAK_PORT=8080
KEYCLOAK_PORT=8081
KEYCLOAK_USER=admin
KEYCLOAK_PW=password
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,5 +2,6 @@
*~
\#*\#
.\#*
.idea
lua_install
luacov.stats.out
5 changes: 1 addition & 4 deletions .travis.yml
Expand Up @@ -5,10 +5,7 @@ language: python
sudo: true

env:
- LUA_VERSION="5.1" KONG_VERSION="0.13.0-0" LUA_RESTY_OPENIDC_VERSION="1.6.1-1"
- LUA_VERSION="5.1" KONG_VERSION="0.12.3-0" LUA_RESTY_OPENIDC_VERSION="1.6.1-1"
- LUA_VERSION="5.1" KONG_VERSION="0.11.2-0" LUA_RESTY_OPENIDC_VERSION="1.6.1-1"
- LUA_VERSION="5.1" KONG_VERSION="1.0.2-0" LUA_RESTY_OPENIDC_VERSION="1.6.1-1"
- LUA_VERSION="5.1" KONG_VERSION="1.5.0-0" LUA_RESTY_OPENIDC_VERSION="1.7.2-1"

script:
- sudo -E bash ci/root.sh
Expand Down
2 changes: 1 addition & 1 deletion ci/setup.sh
Expand Up @@ -3,7 +3,7 @@ set -e

export LUA_VERSION=${LUA_VERSION:-5.1}
export KONG_VERSION=${KONG_VERSION:-0.13.1-0}
export LUA_RESTY_OPENIDC_VERSION=${LUA_RESTY_OPENIDC_VERSION:-1.6.1-1}
export LUA_RESTY_OPENIDC_VERSION=${LUA_RESTY_OPENIDC_VERSION:-1.7.1-1}

pip install hererocks
hererocks lua_install -r^ --lua=${LUA_VERSION}
Expand Down
2 changes: 1 addition & 1 deletion kong-oidc-1.1.0-0.rockspec
Expand Up @@ -22,7 +22,7 @@ description = {
license = "Apache 2.0"
}
dependencies = {
"lua-resty-openidc ~> 1.6.1-1"
"lua-resty-openidc ~> 1.7.4-1"
}
build = {
type = "builtin",
Expand Down
14 changes: 7 additions & 7 deletions kong/plugins/oidc/handler.lua
Expand Up @@ -14,18 +14,18 @@ end
function OidcHandler:access(config)
OidcHandler.super.access(self)
local oidcConfig = utils.get_options(config, ngx)
local sessionConfig = utils.get_session_options(config, ngx)

if filter.shouldProcessRequest(oidcConfig) then
ngx.log(ngx.DEBUG, "Handling request: " .. ngx.var.request_uri)
session.configure(config)
handle(oidcConfig)
handle(oidcConfig, sessionConfig)
else
ngx.log(ngx.DEBUG, "OidcHandler ignoring request, path: " .. ngx.var.request_uri)
end

ngx.log(ngx.DEBUG, "OidcHandler done")
end

function handle(oidcConfig)
function handle(oidcConfig, sessionConfig)
local response
if oidcConfig.introspection_endpoint then
response = introspect(oidcConfig)
Expand All @@ -35,7 +35,7 @@ function handle(oidcConfig)
end

if response == nil then
response = make_oidc(oidcConfig)
response = make_oidc(oidcConfig, sessionConfig)
if response then
if (response.user) then
utils.injectUser(response.user)
Expand All @@ -50,9 +50,9 @@ function handle(oidcConfig)
end
end

function make_oidc(oidcConfig)
function make_oidc(oidcConfig, sessionConfig)
ngx.log(ngx.DEBUG, "OidcHandler calling authenticate, requested path: " .. ngx.var.request_uri)
local res, err = require("resty.openidc").authenticate(oidcConfig)
local res, err = require("resty.openidc").authenticate(oidcConfig, nil, nil, sessionConfig)
if err then
if oidcConfig.recovery_page_path then
ngx.log(ngx.DEBUG, "Entering recovery page: " .. oidcConfig.recovery_page_path)
Expand Down
29 changes: 26 additions & 3 deletions kong/plugins/oidc/schema.lua
Expand Up @@ -2,22 +2,45 @@ return {
no_consumer = true,
fields = {
client_id = { type = "string", required = true },
client_secret = { type = "string", required = true },
client_secret = { type = "string", required = false },
discovery = { type = "string", required = true, default = "https://.well-known/openid-configuration" },
introspection_endpoint = { type = "string", required = false },
timeout = { type = "number", required = false },
introspection_endpoint_auth_method = { type = "string", required = false },
introspection_expiry_claim = { type = "string", required = false, default = "exp" },
introspection_interval = { type = "number", required = false, default = 0 },
introspection_cache_ignore = { type = "boolean", required = false, default = false },
bearer_only = { type = "string", required = true, default = "no" },
realm = { type = "string", required = true, default = "kong" },
redirect_uri_path = { type = "string" },
redirect_uri = { type = "string" },
scope = { type = "string", required = true, default = "openid" },
response_type = { type = "string", required = true, default = "code" },
ssl_verify = { type = "string", required = true, default = "no" },
token_endpoint_auth_method = { type = "string", required = true, default = "client_secret_post" },
session_secret = { type = "string", required = false },
session_secret = { type = "string", required = false, default = "623q4hR325t36VsCD3g567922IC0073T" },
recovery_page_path = { type = "string" },
logout_path = { type = "string", required = false, default = '/logout' },
redirect_after_logout_uri = { type = "string", required = false, default = '/' },
filters = { type = "string" }
post_logout_redirect_uri = { type = "string", required = false },
redirect_after_logout_with_id_token_hint = { type = "boolean", required = false, default = true },
filters = { type = "string" },
session_name = { type = "string", required = false, default = 'session' },
session_storage = { type = "string", required = false, default = 'cookie' },
session_strategy = { type = "string", required = false, default = 'regenerate' },
session_redis_host = { type = "string", required = false, default = '127.0.0.1' },
session_redis_port = { type = "string", required = false, default = '6379' },
session_redis_server_name = { type = "string", required = false },
session_redis_auth = { type = "string", required = false },
session_redis_uselocking = { type = "string", required = false, default = 'false' },
session_redis_database = { type = "string", required = false },
session_redis_prefix = { type = "string", required = false },
session_redis_ssl = { type = "string", required = false, default = 'true' },
session_redis_ssl_verify = { type = "string", required = false, default = 'off'},
session_redis_pool_size = { type = "string", required = false, default = '10'},
session_redis_pool_backlog = { type = "string", required = false, default = '10'},
session_cookie_samesite = { type = "string", required = false, default = 'None'},
session_cookie_secure = { type = "boolean", required = false, default = true},
session_cookie_domain = { type = "string", required = false },
}
}
41 changes: 40 additions & 1 deletion kong/plugins/oidc/utils.lua
Expand Up @@ -42,14 +42,18 @@ end
function M.get_options(config, ngx)
return {
client_id = config.client_id,
client_secret = config.client_secret,
client_secret = ngx.var.client_secret or config.client_secret,
discovery = config.discovery,
introspection_endpoint = config.introspection_endpoint,
timeout = config.timeout,
introspection_endpoint_auth_method = config.introspection_endpoint_auth_method,
introspection_expiry_claim = config.introspection_expiry_claim,
introspection_interval = config.introspection_interval,
introspection_cache_ignore = config.introspection_cache_ignore,
bearer_only = config.bearer_only,
realm = config.realm,
redirect_uri_path = config.redirect_uri_path or M.get_redirect_uri_path(ngx),
redirect_uri = config.redirect_uri,
scope = config.scope,
response_type = config.response_type,
ssl_verify = config.ssl_verify,
Expand All @@ -58,9 +62,44 @@ function M.get_options(config, ngx)
filters = parseFilters(config.filters),
logout_path = config.logout_path,
redirect_after_logout_uri = config.redirect_after_logout_uri,
redirect_after_logout_with_id_token_hint = config.redirect_after_logout_with_id_token_hint,
post_logout_redirect_uri = config.post_logout_redirect_uri,
anonymous_requests_allow = config.anonymous_requests_allow,
allow_anonymous_html_request = config.allow_anonymous_html_request,
session_name = config.session_name,
}
end

function M.get_session_options(config, ngx)
return {
name = config.session_name,
storage = config.session_storage,
strategy = config.session_strategy,
redis = {
host = config.session_redis_host,
port = config.session_redis_port,
prefix = config.session_redis_prefix,
socket = config.session_redis_socket,
host = config.session_redis_host,
auth = config.session_redis_auth,
server_name = config.session_redis_server_name,
ssl = config.session_redis_ssl,
ssl_verify = config.session_redis_ssl_verify,
uselocking = config.session_redis_uselocking,
pool = {
size = config.session_redis_pool_size,
backlog = config.session_redis_pool_backlog,
}
},
cookie = {
samesite = config.session_cookie_samesite,
domain = config.session_cookie_domain,
secure = config.session_cookie_secure,
}
}
end


function M.exit(httpStatusCode, message, ngxCode)
ngx.status = httpStatusCode
ngx.say(message)
Expand Down
7 changes: 4 additions & 3 deletions test/docker/integration/Dockerfile
@@ -1,17 +1,18 @@
ARG KONG_BASE_TAG
FROM kong${KONG_BASE_TAG}
USER root

ENV LUA_PATH /usr/local/share/lua/5.1/?.lua;/usr/local/kong-oidc/?.lua;;
# For lua-cjson
ENV LUA_CPATH /usr/local/lib/lua/5.1/?.so;;

# Install unzip for luarocks, gcc for lua-cjson
RUN yum install -y unzip gcc
RUN yum install -y unzip gcc curl
RUN luarocks install luacov
RUN luarocks install luaunit
RUN luarocks install lua-cjson

# Change openidc version when version in rockspec changes
RUN luarocks install lua-resty-openidc 1.6.0
RUN luarocks install lua-resty-openidc 1.7.4-1

COPY . /usr/local/kong-oidc
COPY . /usr/local/kong-oidc
Binary file not shown.
Binary file not shown.
9 changes: 8 additions & 1 deletion test/docker/integration/docker-compose.yml
Expand Up @@ -18,6 +18,11 @@ services:
KEYCLOAK_USER: ${KEYCLOAK_USER}
KEYCLOAK_PASSWORD: ${KEYCLOAK_PW}

kong-session-store:
image: redis
ports:
- 6379:6379

kong:
image: nokia/kong-oidc${KONG_TAG}
ports:
Expand All @@ -26,6 +31,7 @@ services:
- 8001:8001
- 8444:8444
environment:
KONG_NGINX_PROXY_INCLUDE: /usr/local/kong-oidc/test/docker/integration/nginx-redis.kong.conf
KONG_DATABASE: postgres
KONG_PG_HOST: kong-db
KONG_PG_DATABASE: ${KONG_DB_NAME}
Expand All @@ -39,4 +45,5 @@ services:
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_PLUGINS: oidc
depends_on:
- kong-db
- kong-db
- kong-session-store
48 changes: 48 additions & 0 deletions test/docker/integration/keycloak_client.py
@@ -0,0 +1,48 @@
import requests

class KeycloakClient:
def __init__(self, url, realm, username, password):
self._endpoint = url
self._realm = realm
self._session = requests.session()
self._username = username
self._password = password

def discover(self, config_type = "openid-configuration"):
res = self._session.get("{}/auth/realms/{}/.well-known/{}".format(self._endpoint, self._realm, config_type))
res.raise_for_status()
return res.json()

def create_client(self, name, secret):
url = "{}/auth/admin/realms/master/clients".format(self._endpoint)
payload = {
"clientId": name,
"secret": secret,
"redirectUris": ["*"],
}

headers = self.get_auth_header()
res = self._session.post(url, json=payload, headers=headers)

if res.status_code not in [201, 409]:
raise Exception("Cannot Keycloak create client")

def get_auth_header(self):
return {
"Authorization": f'Bearer {self.get_token("admin-cli")}'
}

def get_token(self, client_id):
url = "{}/auth/realms/{}/protocol/openid-connect/token".format(self._endpoint, self._realm)

payload = f'client_id={client_id}&grant_type=password' + \
f'&username={self._username}&password={self._password}'

headers = {
"Content-Type": "application/x-www-form-urlencoded"
}

res = self._session.post(url, data=payload, headers=headers)
res.raise_for_status()

return res.json()["access_token"]
59 changes: 59 additions & 0 deletions test/docker/integration/kong_client.py
@@ -0,0 +1,59 @@
import requests

class KongClient:
def __init__(self, url):
self._endpoint = url
self._session = requests.session()

def create_service(self, name, upstream_url):
url = "{}/services".format(self._endpoint)
payload = {
"name": name,
"url": upstream_url,
}
res = self._session.post(url, json=payload)
res.raise_for_status()
return res.json()

def create_route(self, service_name, paths):
url = "{}/services/{}/routes".format(self._endpoint, service_name)
payload = {
"paths": paths,
}
res = self._session.post(url, json=payload)
res.raise_for_status()
return res.json()

def create_plugin(self, plugin_name, service_name, config):
url = "{}/services/{}/plugins".format(self._endpoint, service_name)
payload = {
"name": plugin_name,
"config": config,
}
res = self._session.post(url, json=payload)
try:
res.raise_for_status()
except Exception as e:
print(res.text)
raise e
return res.json()

def delete_service(self, name):
try:
routes = self.get_routes(name)
for route in routes:
self.delete_route(route)
except requests.exceptions.HTTPError:
pass
url = "{}/services/{}".format(self._endpoint, name)
self._session.delete(url).raise_for_status()

def delete_route(self, route_id):
url = "{}/routes/{}".format(self._endpoint, route_id)
self._session.delete(url).raise_for_status()

def get_routes(self, service_name):
url = "{}/services/{}/routes".format(self._endpoint, service_name)
res = self._session.get(url)
res.raise_for_status()
return map(lambda x: x['id'], res.json()['data'])
4 changes: 4 additions & 0 deletions test/docker/integration/nginx-redis.kong.conf
@@ -0,0 +1,4 @@
set $session_storage redis;
set $session_redis_prefix sessions;
set $session_redis_host kong-session-store;
set $session_redis_port 6379;

0 comments on commit bcecd92

Please sign in to comment.