Skip to content

Commit 4e9a004

Browse files
authored
Merge pull request #956 from 3scale/fix-batcher-policy
Make 3scale batcher policy compatible with OIDC
2 parents de045f3 + f919c37 commit 4e9a004

File tree

4 files changed

+153
-2
lines changed

4 files changed

+153
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
### Fixed
1818

1919
- Fix "nil" being added to the end of URL Path in some cases when using http_proxy [PR #946](https://github.com/3scale/apicast/pull/946)
20+
- Fix 3scale Batcher policy failing to cache and report requests containing app ID only [PR #956](https://github.com/3scale/apicast/pull/956), [THREESCALE-1515](https://issues.jboss.org/browse/THREESCALE-1515)
2021

2122
## [3.4.0-beta1] - 2018-10-24
2223

gateway/src/apicast/policy/3scale_batcher/keys_helper.lua

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ local function creds_part_in_key(creds)
1616
return format("user_key:%s", creds.user_key)
1717
elseif creds.access_token then
1818
return format("access_token:%s", creds.access_token)
19+
elseif creds.app_id then
20+
return format("app_id:%s", creds.app_id)
1921
end
2022
end
2123

@@ -39,7 +41,8 @@ end
3941
local regexes_report_key = {
4042
"service_id:(?<service_id>[\\w-]+),user_key:(?<user_key>[\\w-]+),metric:(?<metric>[\\w-]+)",
4143
"service_id:(?<service_id>[\\w-]+),access_token:(?<access_token>[\\w-]+),metric:(?<metric>[\\w-]+)",
42-
"service_id:(?<service_id>[\\w-]+),app_id:(?<app_id>[\\w-]+),app_key:(?<app_key>[\\w-]+),metric:(?<metric>[\\w-]+)"
44+
"service_id:(?<service_id>[\\w-]+),app_id:(?<app_id>[\\w-]+),app_key:(?<app_key>[\\w-]+),metric:(?<metric>[\\w-]+)",
45+
"service_id:(?<service_id>[\\w-]+),app_id:(?<app_id>[\\w-]+),metric:(?<metric>[\\w-]+)"
4346
}
4447

4548
function _M.key_for_cached_auth(transaction)

spec/policy/3scale_batcher/keys_helper_spec.lua

+8-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('Keys Helper', function()
2929
end)
3030

3131
describe('.report_from_key_batched_report', function()
32-
it('returns a report given a key of a batched report with app ID', function()
32+
it('returns a report given a key of a batched report with app ID and app key', function()
3333
local key = 'service_id:s1,app_id:ai,app_key:ak,metric:m1'
3434

3535
local report = keys_helper.report_from_key_batched_report(key)
@@ -49,5 +49,12 @@ describe('Keys Helper', function()
4949
local report = keys_helper.report_from_key_batched_report(key)
5050
assert.same({ service_id = 's1', access_token = 'at', metric = 'm1' }, report)
5151
end)
52+
53+
it('returns a report given a key of a batched report with app ID only', function()
54+
local key = 'service_id:s1,app_id:ai,metric:m1'
55+
56+
local report = keys_helper.report_from_key_batched_report(key)
57+
assert.same({ service_id = 's1', app_id = 'ai', metric = 'm1'}, report)
58+
end)
5259
end)
5360
end)

t/apicast-policy-3scale-batcher.t

+140
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use lib 't';
22
use Test::APIcast 'no_plan';
33

4+
use Cwd qw(abs_path);
5+
6+
$ENV{TEST_NGINX_LUA_PATH} = "$Test::APIcast::spec/?.lua;$ENV{TEST_NGINX_LUA_PATH}";
7+
8+
our $rsa = `cat t/fixtures/rsa.pem`;
9+
410
# Can't run twice because of the report batches
511
repeat_each(1);
612

@@ -477,3 +483,137 @@ rewrite_by_lua_block {
477483
[ 429, 403, 403 ]
478484
--- no_error_log
479485
[error]
486+
487+
=== TEST 6: caches successful authorizations with app_id only
488+
This test checks that the policy a) caches successful authorizations and b) reports correctly.
489+
For a) we define a backend that makes sure that it's called only once.
490+
For b) we force the batch reporting and check that transactions.xml receive it in the expected format.
491+
--- http_config
492+
include $TEST_NGINX_UPSTREAM_CONFIG;
493+
lua_shared_dict cached_auths 1m;
494+
lua_shared_dict batched_reports 1m;
495+
lua_shared_dict batched_reports_locks 1m;
496+
lua_package_path "$TEST_NGINX_LUA_PATH";
497+
498+
init_by_lua_block {
499+
require('apicast.configuration_loader').mock({
500+
oidc = {
501+
{
502+
issuer = "https://example.com/auth/realms/apicast",
503+
config = { id_token_signing_alg_values_supported = { "RS256" } },
504+
keys = { somekid = { pem = require('fixtures.rsa').pub } },
505+
}
506+
},
507+
services = {
508+
{
509+
id = 42,
510+
backend_version = 'oauth',
511+
backend_authentication_type = 'service_token',
512+
backend_authentication_value = 'token-value',
513+
proxy = {
514+
authentication_method = 'oidc',
515+
oidc_issuer_endpoint = 'https://example.com/auth/realms/apicast',
516+
backend = { endpoint = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT" },
517+
api_backend = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT/api-backend/",
518+
proxy_rules = {
519+
{ pattern = '/', http_method = 'GET', metric_system_name = 'hits', delta = 1 }
520+
},
521+
policy_chain = {
522+
{ name = 'apicast.policy.3scale_batcher', configuration = {} },
523+
{ name = 'apicast.policy.apicast' }
524+
}
525+
}
526+
}
527+
}
528+
})
529+
}
530+
--- config
531+
include $TEST_NGINX_APICAST_CONFIG;
532+
533+
location /transactions/oauth_authorize.xml {
534+
content_by_lua_block {
535+
local test_counter = ngx.shared.test_counter or 0
536+
if test_counter == 0 then
537+
ngx.shared.test_counter = test_counter + 1
538+
ngx.exit(200)
539+
else
540+
ngx.log(ngx.ERR, 'auth should be cached but called backend anyway')
541+
ngx.exit(502)
542+
end
543+
}
544+
}
545+
location /transactions.xml {
546+
content_by_lua_block {
547+
ngx.req.read_body()
548+
local post_args = ngx.req.get_post_args()
549+
local app_id_match, usage_match
550+
for k, v in pairs(post_args) do
551+
if k == 'transactions[0][app_key]' then
552+
ngx.exit(500)
553+
elseif k == 'transactions[0][usage][hits]' then
554+
usage_match = v == '2'
555+
elseif k == 'transactions[0][app_id]' then
556+
app_id_match = v == 'appid'
557+
end
558+
end
559+
ngx.shared.result = usage_match and app_id_match
560+
}
561+
}
562+
563+
location /force_report_to_backend {
564+
content_by_lua_block {
565+
local ReportsBatcher = require ('apicast.policy.3scale_batcher.reports_batcher')
566+
local reporter = require ('apicast.policy.3scale_batcher.reporter')
567+
local http_ng_resty = require('resty.http_ng.backend.resty')
568+
local backend_client = require('apicast.backend_client')
569+
570+
local service_id = '42'
571+
572+
local reports_batcher = ReportsBatcher.new(
573+
ngx.shared.batched_reports, 'batched_reports_locks')
574+
575+
local reports = reports_batcher:get_all(service_id)
576+
577+
local backend = backend_client:new(
578+
{
579+
id = service_id,
580+
backend_authentication_type = 'service_token',
581+
backend_authentication_value = 'token-value',
582+
backend = { endpoint = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT" }
583+
}, http_ng_resty)
584+
585+
reporter.report(reports, service_id, backend, reports_batcher)
586+
ngx.print('force report OK')
587+
}
588+
}
589+
location /check_reports {
590+
content_by_lua_block {
591+
if ngx.shared.result then
592+
ngx.print('report OK')
593+
ngx.exit(ngx.HTTP_OK)
594+
else
595+
ngx.status = 400
596+
ngx.print('report not OK')
597+
ngx.exit(ngx.HTTP_OK)
598+
end
599+
}
600+
}
601+
location /api-backend {
602+
echo 'yay, api backend';
603+
}
604+
--- request eval
605+
[ "GET /test", "GET /test", "GET /force_report_to_backend", "GET /check_reports"]
606+
--- error_code eval
607+
[ 200, 200 , 200, 200 ]
608+
--- response_body eval
609+
["yay, api backend\x{0a}","yay, api backend\x{0a}","force report OK", "report OK"]
610+
--- more_headers eval
611+
use Crypt::JWT qw(encode_jwt);
612+
my $jwt = encode_jwt(payload => {
613+
aud => 'appid',
614+
sub => 'someone',
615+
iss => 'https://example.com/auth/realms/apicast',
616+
exp => time + 3600 }, key => \$::rsa, alg => 'RS256', extra_headers => { kid => 'somekid' });
617+
["Authorization: Bearer $jwt", "Authorization: Bearer $jwt", "" , ""]
618+
--- no_error_log
619+
[error]

0 commit comments

Comments
 (0)