From cc45c08c70762f6a4ba0a012da7af49e1745e6e4 Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Wed, 20 Jun 2018 18:08:29 +0200 Subject: [PATCH] [oidc] fix reporting to backend when using OIDC [THREESCALE-1080] --- CHANGELOG.md | 4 + gateway/src/apicast/proxy.lua | 6 +- t/apicast-oidc.t | 133 ++++++++++++++++++++++------------ 3 files changed, 95 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 270b4d7c4..6b1dc412b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed + +- Reporting only 50% calls to 3scale backend when using OIDC [PR #779](https://github.com/3scale/apicast/pull/779) + ## [3.2.0] - 2018-06-04 3.2.0-rc2 was considered final and became 3.2.0. diff --git a/gateway/src/apicast/proxy.lua b/gateway/src/apicast/proxy.lua index deec7f135..4e8a4e299 100644 --- a/gateway/src/apicast/proxy.lua +++ b/gateway/src/apicast/proxy.lua @@ -299,9 +299,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 @@ -321,6 +318,9 @@ function _M:rewrite(service, context) ctx.credentials = credentials ctx.ttl = ttl end + + self.credentials = credentials + self.usage = context.usage end function _M:access(service, usage, credentials, ttl) 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]