From 8b21bc1454a97c14421c2f753b1696cceb5ac2c9 Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Tue, 19 Jun 2018 14:28:50 +0200 Subject: [PATCH] [oidc] fix passing wrong credentials to 3scale [THREESCALE-1080] --- CHANGELOG.md | 1 + gateway/src/apicast/proxy.lua | 9 +-- t/apicast-oidc.t | 133 ++++++++++++++++++++++------------ 3 files changed, 92 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b72d5b699..c00f582f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/gateway/src/apicast/proxy.lua b/gateway/src/apicast/proxy.lua index ada9d63f2..173b4e127 100644 --- a/gateway/src/apicast/proxy.lua +++ b/gateway/src/apicast/proxy.lua @@ -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 @@ -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 @@ -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) diff --git a/t/apicast-oidc.t b/t/apicast-oidc.t index de7677ee9..797c0d489 100644 --- a/t/apicast-oidc.t +++ b/t/apicast-oidc.t @@ -1,64 +1,53 @@ 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); @@ -66,7 +55,61 @@ 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]