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

Fix reporting only 50% of calls to 3scale backend [THREESCALE-1080] #774

Merged
merged 1 commit into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -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 @@ -358,7 +355,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 @@ -371,8 +368,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 + 3600 }, 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 + 3600 }, key => \$::private_key, alg => 'RS256');
["Authorization: Bearer $jwt", "Authorization: Bearer $jwt"]
--- no_error_log
[error]