Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for RHSSO and OpenId Connect #283

Merged
merged 57 commits into from
Mar 16, 2017
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
0292297
Common interface for built-in and custom OAuth implementation (Keyclo…
mayorova Jan 18, 2017
18239f8
Fix oauth test
mayorova Jan 20, 2017
df65b2b
Read keycloak config file in init phase
mayorova Jan 27, 2017
6447dd6
Params checking functions for Keycloak
mayorova Jan 30, 2017
63da32f
[WIP] Keycloak token authorization working
Jan 31, 2017
4b75007
Add new environment variables for RHSSO
Feb 9, 2017
b87f577
Replace access_token in credentials with app_id extracted from jwt
Feb 9, 2017
fee2aa2
Add some keycloak tests
Feb 9, 2017
c0d8f6e
Add lua-rest-jwt to rockspec
Feb 14, 2017
aedd556
luacheck fixes
Feb 14, 2017
dcd18e2
Use same request pattern oauth_authrep as authrep for consistency and…
Mar 2, 2017
56e692f
[WIP] Add Client Registration code as an example
Mar 3, 2017
42bdbe1
Clean up
Mar 7, 2017
214b826
Get public key from realm endpoint
Mar 7, 2017
7d284d6
Update README
Mar 7, 2017
f1bca2c
Use http_ng client instead of proxy_pass
Mar 9, 2017
2219904
Update/Add dependencies
Mar 9, 2017
88857b8
Return authorization failed on failed jwt validation
Mar 9, 2017
e5c9e9e
Use redis connect from threescale_utils.lua
Mar 9, 2017
a1d1326
[doc] Update README after review
Mar 9, 2017
b346109
Fixes from review
Mar 9, 2017
5bbdda8
Revert changes to require libraries every request
Mar 10, 2017
5e39edc
Fix build
Mar 10, 2017
f904a1d
[WIP] Test case where JWT is not verified
Mar 10, 2017
09305ce
Merge from master
Mar 10, 2017
8caf31b
Fix oauth.lua
Mar 10, 2017
9ab5f3c
remove format public_key test
Mar 10, 2017
e973277
update README
Mar 10, 2017
88817f4
Move credentials check back to service.lua
Mar 13, 2017
533ad9d
Move credentials check back to service.lua: fixes for unhappy path
Mar 13, 2017
7a145fd
[WIP] get service configuration
Mar 13, 2017
0b4eb07
extract oauth credentials checking to oauth modules
Mar 14, 2017
bb9f962
Refactor
Mar 14, 2017
c4af07e
[WIP] OIDC flow working needs tests
Mar 14, 2017
da0dc81
[WIP] Working Flow after rebasing master
Mar 14, 2017
31bcafc
Add RHSSO_INITIAL_TOKEN as a custom environment variablee
Mar 14, 2017
9a5537d
Use backend client
Mar 14, 2017
69bb575
revert changes to service.lua made in branch
Mar 15, 2017
f42c19b
[WIP] Changes from refactor and some tests
Mar 16, 2017
8b93cb4
[WIP] fixes to proxy.lua
Mar 16, 2017
19729ff
[WIP] proxy to call different authorize function depending on backend…
Mar 16, 2017
347aea4
[proxy] fix proxy
mikz Mar 16, 2017
4fe0262
[keycloak] don't try to configure keycloak without config
mikz Mar 16, 2017
99bd2d8
[proxy] unify sending debug headers
mikz Mar 16, 2017
add69ad
Merge remote-tracking branch 'origin/master' into openid-connect
mikz Mar 16, 2017
1b8eec2
Fix tests
Mar 16, 2017
e163dad
Danger fixes
Mar 16, 2017
2f7df3f
fix luacheck error
mikz Mar 16, 2017
50260f0
Add RHSSO_ENDPOINT to parameters list
Mar 16, 2017
2e3bb26
Merge branch 'openid-connect' of github.com:3scale/apicast into openi…
Mar 16, 2017
d66fdd6
[proxy] reduce duplication in auth functions
mikz Mar 16, 2017
4c40fae
[keycloak] improve configuration loading
mikz Mar 16, 2017
50d71b1
Remove noisy log entry
Mar 16, 2017
efe016b
Update file locations to be more consistent with APIcast naming and R…
Mar 16, 2017
be86559
Remove redundant log entry
Mar 16, 2017
3a6a7b5
Update CHANGELOG with known issues
Mar 16, 2017
f3ffeab
Update CHANGELOG with issue number
Mar 16, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Ability to customize main section of nginx configuration (and expose more env variables) [PR #292](https://github.com/3scale/apicast/pull/292)
- Ability to lock service to specific configuration version [PR #293](https://github.com/3scale/apicast/pull/292)
- Ability to use Redis DB and password via `REDIS_URL` [PR #303](https://github.com/3scale/apicast/pull/303)
- Ability to Authenticate against API using RHSSO and OpenID Connect [PR #283](https://github.com/3scale/apicast/pull/283)

### Removed

Expand Down
3 changes: 2 additions & 1 deletion apicast/apicast-0.1-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ version = '0.1-0'
dependencies = {
'lua-resty-http == 0.09-0',
'inspect == 3.1.0-1',
'router == 2.1-0'
'router == 2.1-0',
'lua-resty-jwt == 0.1.9-0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to give heads up to @rnc and @3scale/productization about this.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. Creating jira for it

}
build = {
type = "builtin",
Expand Down
14 changes: 13 additions & 1 deletion apicast/conf.d/apicast.conf
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,23 @@ location = /_threescale/check_credentials {

location = /threescale_oauth_authrep {
internal;

set_by_lua_block $log {
local log = ngx.var.arg_log;
if log then return '&' .. ngx.unescape_uri(log) end
}
set $path /transactions/oauth_authrep.xml?$backend_authentication_type=$backend_authentication_value&service_id=$service_id&$usage&$credentials$log;
proxy_pass_request_headers off;
proxy_http_version 1.1;
proxy_pass $backend_endpoint$path;
proxy_set_header Host "$backend_host";
proxy_set_header User-Agent "$user_agent";
proxy_set_header X-3scale-User-Agent "$deployment";
proxy_set_header X-3scale-Version "$version";
proxy_set_header Connection "";
proxy_set_header X-3scale-OAuth2-Grant-Type "authorization_code";

proxy_pass $backend_endpoint/transactions/oauth_authrep.xml?$backend_authentication_type=$backend_authentication_value&service_id=$service_id&$usage&$credentials&log%5Bcode%5D=$arg_code&log%5Brequest%5D=$arg_req&log%5Bresponse%5D=$arg_resp;
rewrite_by_lua_block {
ngx.var.real_url = ngx.var.backend_endpoint .. ngx.var.path
}
}
1 change: 1 addition & 0 deletions apicast/conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ env REDIS_PORT;
env REDIS_URL;
env RESOLVER;
env BACKEND_ENDPOINT_OVERRIDE;
env RHSSO_ENDPOINT;

include ../main.d/*.conf;

Expand Down
11 changes: 11 additions & 0 deletions apicast/libexec/keycloak
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env resty

pcall(require, 'luarocks.loader')
package.path = package.path .. ";./src/?.lua"

local keycloak = require 'oauth.keycloak'
local cjson = require 'cjson'

local config = keycloak.load_configuration()

ngx.say(cjson.encode(config))
22 changes: 20 additions & 2 deletions apicast/src/configuration_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ local remote_loader_v2 = require 'configuration_loader.remote_v2'
local util = require 'util'
local env = require('resty.env')
local synchronization = require('resty.synchronization').new(1)
local keycloak = require 'oauth.keycloak'
local cjson = require 'cjson'

local error = error
local len = string.len
Expand Down Expand Up @@ -65,9 +67,9 @@ end

-- Cosocket API is not available in the init_by_lua* context (see more here: https://github.com/openresty/lua-nginx-module#cosockets-not-available-everywhere)
-- For this reason a new process needs to be started to download the configuration through 3scale API
function _M.init(cwd)
function _M.init(cwd, cmd)
cwd = cwd or env.get('TEST_NGINX_APICAST_PATH') or ngx.config.prefix()
local config, err, code = util.system("cd '" .. cwd .."' && libexec/boot")
local config, err, code = util.system("cd '" .. cwd .."' && libexec/"..(cmd or "boot"))

-- Try to read the file in current working directory before changing to the prefix.
if err then config = file_loader.call() end
Expand Down Expand Up @@ -105,6 +107,12 @@ function boot.init(configuration)
ngx.log(ngx.EMERG, 'cache is off, cannot store configuration, exiting')
os.exit(0)
end

local keycloak_config = _M.init(nil, "keycloak")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty poor interface and should be improved. Passing nil is just weird.


if keycloak_config then
configuration.keycloak = cjson.decode(keycloak_config)
end
end

local function refresh_configuration(configuration)
Expand All @@ -121,6 +129,8 @@ end
function boot.init_worker(configuration)
local interval = ttl() or 0

configuration.keycloak = keycloak.load_configuration()

local function schedule(...)
local ok, err = ngx.timer.at(...)

Expand Down Expand Up @@ -156,6 +166,12 @@ end
local lazy = { init_worker = noop }

function lazy.init(configuration)
local keycloak_config = _M.init(nil, "keycloak")

if keycloak_config then
configuration.keycloak = cjson.decode(keycloak_config)
end

configuration.configured = true
end

Expand All @@ -174,6 +190,8 @@ function lazy.rewrite(configuration, host)
_M.configure(configuration, config)
end

configuration.keycloak = keycloak.load_configuration()

if ok then
synchronization:release(host)
sema:post()
Expand Down
38 changes: 21 additions & 17 deletions apicast/src/oauth.lua
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
local get_token = require 'get_token'
local callback = require 'authorized_callback'
local authorize = require 'authorize'

local router = require 'router'
local apicast_oauth = require 'oauth.apicast_oauth'
local keycloak = require 'oauth.keycloak'

local _M = {
version = '0.0.1'
_VERSION = '0.0.2'
}

function _M.router()
-- TODO: use configuration to customize urls
local r = router:new()
function _M.new(configuration)
if configuration.keycloak then
ngx.log(ngx.INFO, "keycloak configured")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is going to print this message on every request, not really necessary no ?

return keycloak.new(configuration.keycloak)
else
return apicast_oauth.new()
end
end

r:get('/authorize', authorize.call)
r:post('/authorize', authorize.call)
function _M.router(oauth, service)
local r = router:new()
r:get('/authorize', function() oauth:authorize(service) end)
r:post('/authorize', function() oauth:authorize(service) end)

r:post('/callback', callback.call)
r:get('/callback', callback.call)
-- TODO: only applies to apicast oauth...
r:post('/callback', function() oauth:callback() end)
r:get('/callback', function() oauth:callback() end)

r:post('/oauth/token', get_token.call)
r:post('/oauth/token', function() oauth:get_token(service) end)

return r
end

function _M.call(method, uri, ...)
local r = _M.router()
function _M.call(oauth, service, method, uri, ...)
local r = _M.router(oauth, service)

local f, params = r:resolve(method or ngx.req.get_method(),
uri or ngx.var.uri,
Expand All @@ -34,5 +40,3 @@ function _M.call(method, uri, ...)
end

return _M


26 changes: 26 additions & 0 deletions apicast/src/oauth/apicast_oauth.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local get_token = require 'oauth.apicast_oauth.get_token'
local callback = require 'oauth.apicast_oauth.authorized_callback'
local authorize = require 'oauth.apicast_oauth.authorize'
local setmetatable = setmetatable

local _M = {
_VERSION = '0.1'
}

local mt = { __index = _M }

function _M.new(service)
return setmetatable(
{
authorize = authorize.call,
callback = callback.call,
get_token = get_token.call,
service = service
}, mt)
end

function _M.transform_credentials(_, credentials)
return credentials
end

return _M
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ local function check_client_credentials(params)
ctx = ngx.ctx
})

ngx.log(ngx.INFO, "[oauth] Checking client credentials, status: ", res.status, " body: ", res.body)

if res.status == 200 then
return { ["status"] = res.status, ["body"] = res.body }
else
Expand Down
Loading