Skip to content

Commit

Permalink
Merge pull request #894 from 3scale/oidc-invalid-configuration
Browse files Browse the repository at this point in the history
Help debugging invalid OIDC configuration
  • Loading branch information
davidor authored Sep 13, 2018
2 parents 1d0a8c4 + 3b69f9b commit dea0960
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added

- Expose `http_method` in Liquid [PR #888](https://github.com/3scale/apicast/pull/888)
- Print error message when OIDC configuration is missing for a request [PR #894](https://github.com/3scale/apicast/pull/894)
- Print whole stderr in 4k chunks when executing external commands [PR #894](https://github.com/3scale/apicast/pull/894)

## [3.3.0-beta2] - 2018-09-03

Expand Down
12 changes: 9 additions & 3 deletions gateway/src/apicast/oauth/oidc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,22 @@ local empty = {}
function _M.new(service)
local oidc = service.oidc or empty

local issuer = oidc.issuer
local issuer = oidc.issuer or ""
local config = oidc.config or empty
local alg_values = config.id_token_signing_alg_values_supported or empty

local err
if #issuer == 0 or #alg_values == 0 then
err = 'missing OIDC configuration'
end

return setmetatable({
service = service,
config = config,
issuer = issuer,
keys = oidc.keys or empty,
clock = ngx_now,
alg_whitelist = util.to_hash(config.id_token_signing_alg_values_supported),
alg_whitelist = util.to_hash(alg_values),
-- https://tools.ietf.org/html/rfc7523#section-3
jwt_claims = {
-- 1. The JWT MUST contain an "iss" (issuer) claim that contains a
Expand Down Expand Up @@ -69,7 +75,7 @@ function _M.new(service)
-- the time at which the JWT was issued.
iat = jwt_validators.opt_greater_than(0),
},
}, mt)
}, mt), err
end

local function timestamp_to_seconds_from_now(expiry, clock)
Expand Down
6 changes: 5 additions & 1 deletion gateway/src/apicast/proxy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,14 @@ function _M.get_upstream(service)
end

local function handle_oauth(service)
local oauth = service:oauth()
local oauth, err = service:oauth()

if oauth then
ngx.log(ngx.DEBUG, 'using OAuth: ', oauth)

if err then
ngx.log(ngx.WARN, 'failed to initialize ', oauth, ' for service ', service.id, ': ', err)
end
end

if oauth and oauth.call then
Expand Down
13 changes: 11 additions & 2 deletions gateway/src/apicast/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ local _M = {
local ngx_now = ngx.now

local len = string.len
local sub = string.sub
local errlog = require('ngx.errlog')

local open = io.open
local execute = os.execute
Expand Down Expand Up @@ -34,6 +36,8 @@ local function read(file)
return output
end

local max_log_line_len = 4096-96 -- 96 chars for our error message

function _M.system(command)
local tmpout = tmpname()
local tmperr = tmpname()
Expand All @@ -57,8 +61,13 @@ function _M.system(command)
-- os.execute returns exit code as first return value on OSX
-- even though the documentation says otherwise (true/false)
if success == 0 or success == true then
if len(tmperr) > 0 then
ngx.log(ngx.WARN, 'os execute stderr: \n', tmperr)
local max = len(tmperr)
if max > 0 then
errlog.raw_log(ngx.WARN, 'os execute stderr:')

for start=0, max , max_log_line_len do
errlog.raw_log(ngx.WARN, sub(tmperr, start, start + max_log_line_len - 1))
end
end

return tmpout
Expand Down
31 changes: 31 additions & 0 deletions spec/oauth/oidc_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,37 @@ local rsa = require('fixtures.rsa')

describe('OIDC', function()

describe('.new', function()
it('returns error when issuer is missing', function()
local oidc, err = _M.new({ oidc = {
config = { id_token_signing_alg_values_supported = { 'RS256' } }
}})

assert(oidc, 'still returns oidc object')
assert.equal('missing OIDC configuration', err)
end)

it('returns error when supported algorithms are missing', function()
local oidc, err = _M.new({ oidc = {
issuer = 'http://example.com',
config = { id_token_signing_alg_values_supported = {} }
}})

assert(oidc, 'still returns oidc object')
assert.equal('missing OIDC configuration', err)
end)

it('returns no error with valid OIDC configuration', function()
local oidc, err = _M.new({ oidc = {
issuer = 'http://example.com',
config = { id_token_signing_alg_values_supported = { 'RS256' } }
}})

assert(oidc, 'still returns oidc object')
assert.falsy(err)
end)
end)

describe(':transform_credentials', function()
local service = {
id = 1,
Expand Down
40 changes: 40 additions & 0 deletions t/apicast-oidc.t
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,43 @@ my $jwt = encode_jwt(payload => {
["Authorization: Bearer $jwt", "Authorization: Bearer $jwt"]
--- no_error_log
[error]
=== TEST 3: Invalid OIDC configuration
Prints error message in the log.
--- configuration env eval
use JSON qw(to_json);
to_json({
services => [{
id => 42,
backend_version => 'oauth',
backend_authentication_type => 'provider_key',
backend_authentication_value => 'fookey',
proxy => {
authentication_method => 'oidc',
oidc_issuer_endpoint => 'https://example.com/auth/realms/apicast',
api_backend => "http://test:$TEST_NGINX_SERVER_PORT/",
proxy_rules => [
{ pattern => '/', http_method => 'GET', metric_system_name => 'hits', delta => 1 }
]
}
}],
oidc => [{
keys => { somekid => { pem => $::public_key } },
}]
});
--- request: GET /test
--- error_code: 403
--- more_headers eval
use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(payload => {
aud => 'appid',
sub => 'someone',
iss => 'https://example.com/auth/realms/apicast',
exp => time + 3600 }, key => \$::private_key, alg => 'RS256', extra_headers => { kid => 'somekid' });
"Authorization: Bearer $jwt"
--- error_log
failed to initialize OpenID Connect for service 42: missing OIDC configuration
--- log_level: warn

0 comments on commit dea0960

Please sign in to comment.