Skip to content

Commit

Permalink
[oidc] fix passing wrong credentials to 3scale [THREESCALE-1080]
Browse files Browse the repository at this point in the history
  • Loading branch information
mikz committed Jun 20, 2018
1 parent 9170208 commit 2031991
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 51 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Do not crash when initializing unreachable/invalid DNS resolver [PR #730](https://github.com/3scale/apicast/pull/730)
- Reporting only 50% calls to 3scale backend when using OIDC [PR #774](https://github.com/3scale/apicast/pull/774)

## [3.2.0-rc2] - 2018-05-11

Expand Down
9 changes: 3 additions & 6 deletions gateway/src/apicast/proxy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,6 @@ function _M:rewrite(service, context)
ctx.usage = context.usage
ctx.credentials = credentials

self.credentials = credentials
self.usage = context.usage

var.cached_key = concat(cached_key, ':')

if debug_header_enabled(service) then
Expand Down Expand Up @@ -347,7 +344,7 @@ local function async_post_action(self, cached_key, service, credentials, formatt
end
end

function _M:post_action(_)
function _M:post_action(context)
local cached_key = ngx.var.cached_key

if not cached_key or cached_key == "null" or cached_key == '' then
Expand All @@ -360,8 +357,8 @@ function _M:post_action(_)
local service_id = ngx.var.service_id
local service = ngx.ctx.service or self.configuration:find_by_id(service_id)

local credentials = self.credentials
local formatted_usage = format_usage(self.usage)
local credentials = context.credentials
local formatted_usage = format_usage(context.usage)

if using_sync_post_action then
sync_post_action(self, cached_key, service, credentials, formatted_usage)
Expand Down
133 changes: 88 additions & 45 deletions t/apicast-oidc.t
Original file line number Diff line number Diff line change
@@ -1,72 +1,115 @@
use lib 't';
use Test::APIcast 'no_plan';
use Test::APIcast::Blackbox 'no_plan';

$ENV{TEST_NGINX_LUA_PATH} = "$Test::APIcast::spec/?.lua;$ENV{TEST_NGINX_LUA_PATH}";
$ENV{TEST_NGINX_REDIS_HOST} ||= $ENV{REDIS_HOST} || "127.0.0.1";
$ENV{TEST_NGINX_RESOLVER} ||= `grep nameserver /etc/resolv.conf | awk '{print \$2}' | head -1 | tr '\n' ' '`;
$ENV{BACKEND_ENDPOINT_OVERRIDE} ||= "http://127.0.0.1:$Test::Nginx::Util::ServerPortForClient/backend";
our $private_key = `cat t/fixtures/rsa.pem`;

our $rsa = `cat t/fixtures/rsa.pem`;
my $public_key = `cat t/fixtures/rsa.pub`;

env_to_nginx('BACKEND_ENDPOINT_OVERRIDE');
our $public_key_oneline = join('', grep { length($_) eq 64 } split(/\R/, $public_key));

repeat_each(1);
run_tests();

__DATA__
=== TEST 1: verify JWT
--- http_config
lua_package_path "$TEST_NGINX_LUA_PATH";
include $TEST_NGINX_UPSTREAM_CONFIG;
init_by_lua_block {
require('apicast.configuration_loader').mock({
services = {
{ id = 42,
backend_version = 'oauth',
backend_authentication_type = 'provider_key',
backend_authentication_value = 'fookey',
=== TEST 1: Verify JWT
--- configuration env eval
use JSON qw(to_json);
proxy = {
authentication_method = 'oidc',
oidc_issuer_endpoint = 'https://example.com/auth/realms/apicast',
api_backend = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT/api-backend/",
proxy_rules = {
{ pattern = '/', http_method = 'GET', metric_system_name = 'hits', delta = 1 }
}
}
}
},
oidc = {
{
issuer = 'https://example.com/auth/realms/apicast',
config = { public_key = require('fixtures.rsa').pub, openid = { id_token_signing_alg_values_supported = { 'RS256' } } }
},
}
})
}
--- config
include $TEST_NGINX_APICAST_CONFIG;
location /api-backend/ {
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 => [{
issuer => 'https://example.com/auth/realms/apicast',
config => { public_key => $::public_key_oneline, openid => { id_token_signing_alg_values_supported => [ 'RS256' ] } }
}]
});
--- upstream
location /test {
echo "yes";
}
location = /backend/transactions/oauth_authrep.xml {
--- backend
location = /transactions/oauth_authrep.xml {
content_by_lua_block {
local expected = "provider_key=fookey&service_id=42&usage%5Bhits%5D=1&app_id=appid"
require('luassert').same(ngx.decode_args(expected), ngx.req.get_uri_args(0))
}
}
--- request
GET /test
--- request: GET /test
--- error_code: 200
--- more_headers eval
use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(payload => {
aud => 'appid',
nbf => 0,
iss => 'https://example.com/auth/realms/apicast',
exp => time + 10 }, key => \$::rsa, alg => 'RS256');
exp => time + 10 }, key => \$::private_key, alg => 'RS256');
"Authorization: Bearer $jwt"
--- no_error_log
[error]
=== TEST 2: Report calls to 3scale backend (same as TEST 1, but with two requests to trigger async reporting)
This is the same test as TEST 1, but done twice to trigger asynchronous reporting from post_action to
test https://issues.jboss.org/browse/THREESCALE-1080.
--- 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 => [{
issuer => 'https://example.com/auth/realms/apicast',
config => { public_key => $::public_key_oneline, openid => { id_token_signing_alg_values_supported => [ 'RS256' ] } }
}]
});
--- upstream
location /test {
echo "yes";
}
--- backend
location = /transactions/oauth_authrep.xml {
content_by_lua_block {
local expected = "provider_key=fookey&service_id=42&usage%5Bhits%5D=1&app_id=appid"
require('luassert').same(ngx.decode_args(expected), ngx.req.get_uri_args(0))
}
}
--- request eval
[ "GET /test", "GET /test" ]
--- error_code eval
[ 200, 200 ]
--- more_headers eval
use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(payload => {
aud => 'appid',
nbf => 0,
iss => 'https://example.com/auth/realms/apicast',
exp => time + 10 }, key => \$::private_key, alg => 'RS256');
["Authorization: Bearer $jwt", "Authorization: Bearer $jwt"]
--- no_error_log
[error]

0 comments on commit 2031991

Please sign in to comment.