Skip to content

Commit bd2a95c

Browse files
authored
Merge pull request #1560 from tkan145/THREESCALE-11957-2.16
THREESCALE-11957 FAPI policy uses wrong heade
2 parents fef172f + 83b1ad9 commit bd2a95c

File tree

5 files changed

+64
-31
lines changed

5 files changed

+64
-31
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Fixed
11+
- Correct FAPI header to `x-fapi-interaction-id` [PR #1557](https://github.com/3scale/APIcast/pull/1557) [THREESCALE-11957](https://issues.redhat.com/browse/THREESCALE-11957)
12+
13+
### Added
14+
- Update APIcast schema manifest [PR #1550](https://github.com/3scale/APIcast/pull/1550)
15+
- Update luarocks to v3.12.0 [PR #1555](https://github.com/3scale/APIcast/pull/1555)
16+
17+
### Removed
18+
1019
## [3.16.0] 2025-05-19
1120

1221
### Fixed

gateway/src/apicast/policy/fapi/README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
The FAPI policy supports various features of the Financial-grade API (FAPI) standard.
66

7-
* FAPI 1.0 Baseline Profile
8-
* FAPI 1.0 Advance Profile
7+
* [FAPI 1.0 Baseline Profile](https://openid.net/specs/openid-financial-api-part-1-1_0.html)
8+
* [FAPI 1.0 Advance Profile](https://openid.net/specs/openid-financial-api-part-2-1_0.html)
99

1010
## Example configuration
1111

12+
FAPI policy set the response header `x-fapi-interaction-id` to the value received from the corresponding FAPI client request header or to a RFC4122 UUID value if the request header was not provided.
13+
1214
```
1315
"policy_chain": [
1416
{ "name": "apicast.policy.fapi", "configuration": {} },
@@ -17,8 +19,24 @@ The FAPI policy supports various features of the Financial-grade API (FAPI) stan
1719
}
1820
]
1921
```
22+
### Log the value of x-fapi-interaction-id header
23+
24+
```
25+
"policy_chain": [
26+
{ "name": "apicast.policy.fapi", "configuration": {} },
27+
{
28+
"name": "apicast.policy.logging",
29+
"configuration": {
30+
"enable_access_logs": false,
31+
"custom_logging": "[{{time_local}}] {{host}}:{{server_port}} {{remote_addr}}:{{remote_port}} x-fapi-interaction-id: {{resp.headers.x-fapi-interaction-id}} \"{{request}}\" {{status}} {{body_bytes_sent}} ({{request_time}}) {{post_action_impact}} ",
32+
}
33+
}
34+
{ "name": "apicast.policy.apicast" }
35+
]
36+
```
2037

2138
### Validate x-fapi-customer-ip-address header
39+
Validate requests with a x-fapi-customer-ip-address header containing a valid IPv4 or IPv6 address
2240

2341
```
2442
"policy_chain": [
@@ -36,6 +54,13 @@ The FAPI policy supports various features of the Financial-grade API (FAPI) stan
3654

3755
### Validate certificate-bound access tokens
3856

57+
Certificate-bound access tokens, as defined in [RFC 8705](https://datatracker.ietf.org/doc/html/rfc8705), enhance security by linking tokens to clients, thereby verifying the sender's authorization to access protected resources.
58+
59+
You'll need to:
60+
* Configure an Identity Provider (IdP) such as Keycloak with mTLS and X.509 client certificate authentication.
61+
* Configure the gateway to handle mTLS client certificate authentication.
62+
* Enable `validate_oauth2_certificate_bound_access_token` in the FAPI plugin.
63+
3964
```
4065
"policy_chain": [
4166
{

gateway/src/apicast/policy/fapi/fapi.lua

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ local b64 = require('ngx.base64')
1313
local fmt = string.format
1414

1515
local new = _M.new
16-
local X_FAPI_TRANSACTION_ID_HEADER = "x-fapi-transaction-id"
16+
local X_FAPI_INTERACTION_ID_HEADER = "x-fapi-interaction-id"
1717
local X_FAPI_CUSTOMER_IP_ADDRESS = "x-fapi-customer-ip-address"
1818

1919
-- The "x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Header
@@ -98,15 +98,15 @@ end
9898
function _M:header_filter()
9999
--- 6.2.1.11
100100
-- shall set the response header x-fapi-interaction-id to the value received from the corresponding FAPI client request header or to a RFC4122 UUID value if the request header was not provided to track the interaction
101-
local transaction_id = ngx.req.get_headers()[X_FAPI_TRANSACTION_ID_HEADER]
102-
if not transaction_id or transaction_id == "" then
101+
local interaction_id = ngx.req.get_headers()[X_FAPI_INTERACTION_ID_HEADER]
102+
if not interaction_id or interaction_id == "" then
103103
-- Nothing found, generate one
104-
transaction_id = ngx.resp.get_headers()[X_FAPI_TRANSACTION_ID_HEADER]
105-
if not transaction_id or transaction_id == "" then
106-
transaction_id = uuid.generate_v4()
104+
interaction_id = ngx.resp.get_headers()[X_FAPI_INTERACTION_ID_HEADER]
105+
if not interaction_id or interaction_id == "" then
106+
interaction_id = uuid.generate_v4()
107107
end
108108
end
109-
ngx.header[X_FAPI_TRANSACTION_ID_HEADER] = transaction_id
109+
ngx.header[X_FAPI_INTERACTION_ID_HEADER] = interaction_id
110110
end
111111

112112
return _M

spec/policy/fapi/fapi_spec.lua

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ local clientCert = assert(fixture('CA', 'client.crt'))
77
local header_parameter = 'x5t#S256'
88

99
local function jwt_cnf()
10-
local cnf = b64.encode_base64url(X509.new(clientCert):digest('SHA256'))
1110
return { [header_parameter] = b64.encode_base64url(X509.new(clientCert):digest('SHA256')) }
1211
end
1312

@@ -36,31 +35,31 @@ describe('fapi_1_baseline_profile policy', function()
3635

3736
describe('.header_filter', function()
3837
it('Use value from request', function()
39-
ngx_req_headers['x-fapi-transaction-id'] = 'abc'
38+
ngx_req_headers['x-fapi-interaction-id'] = 'abc'
4039
local fapi_policy = FAPIPolicy.new({})
4140
fapi_policy:header_filter()
42-
assert.same('abc', ngx.header['x-fapi-transaction-id'])
41+
assert.same('abc', ngx.header['x-fapi-interaction-id'])
4342
end)
4443

45-
it('Only use x-fapi-transaction-id from request if the header also exist in response from upstream', function()
46-
ngx_req_headers['x-fapi-transaction-id'] = 'abc'
47-
ngx_resp_headers['x-fapi-transaction-id'] = 'bdf'
44+
it('Only use x-fapi-interaction-id from request if the header also exist in response from upstream', function()
45+
ngx_req_headers['x-fapi-interaction-id'] = 'abc'
46+
ngx_resp_headers['x-fapi-interaction-id'] = 'bdf'
4847
local fapi_policy = FAPIPolicy.new({})
4948
fapi_policy:header_filter()
50-
assert.same('abc', ngx.header['x-fapi-transaction-id'])
49+
assert.same('abc', ngx.header['x-fapi-interaction-id'])
5150
end)
5251

53-
it('Use x-fapi-transaction-id from upstream response', function()
54-
ngx_resp_headers['x-fapi-transaction-id'] = 'abc'
52+
it('Use x-fapi-interaction-id from upstream response', function()
53+
ngx_resp_headers['x-fapi-interaction-id'] = 'abc'
5554
local fapi_policy = FAPIPolicy.new({})
5655
fapi_policy:header_filter()
57-
assert.same('abc', ngx.header['x-fapi-transaction-id'])
56+
assert.same('abc', ngx.header['x-fapi-interaction-id'])
5857
end)
5958

6059
it('generate uuid if header does not exist in both request and response', function()
6160
local fapi_policy = FAPIPolicy.new({})
6261
fapi_policy:header_filter()
63-
assert.is_true(uuid.is_valid(ngx.header['x-fapi-transaction-id']))
62+
assert.is_true(uuid.is_valid(ngx.header['x-fapi-interaction-id']))
6463
end)
6564
end)
6665

t/apicast-policy-fapi.t

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ run_tests();
2323

2424
__DATA__
2525

26-
=== TEST 1: Enables fapi policy inject x-fapi-transaction-id header to the response
26+
=== TEST 1: Enables fapi policy inject x-fapi-interaction-id header to the response
2727
--- configuration
2828
{
2929
"services": [
@@ -62,9 +62,9 @@ __DATA__
6262
}
6363
}
6464
--- more_headers
65-
x-fapi-transaction-id: abc
65+
x-fapi-interaction-id: abc
6666
--- response_headers
67-
x-fapi-transaction-id: abc
67+
x-fapi-interaction-id: abc
6868
--- request
6969
GET /?user_key=value
7070
--- error_code: 200
@@ -73,7 +73,7 @@ GET /?user_key=value
7373

7474

7575

76-
=== TEST 2: When x-fapi-transaction-id exist in both request and response headers, always use
76+
=== TEST 2: When x-fapi-interaction-id exist in both request and response headers, always use
7777
value from request
7878
--- configuration
7979
{
@@ -109,23 +109,23 @@ value from request
109109
--- upstream
110110
location / {
111111
content_by_lua_block {
112-
ngx.header['x-fapi-transaction-id'] = "blah"
112+
ngx.header['x-fapi-interaction-id'] = "blah"
113113
ngx.exit(200)
114114
}
115115
}
116116
--- more_headers
117-
x-fapi-transaction-id: abc
117+
x-fapi-interaction-id: abc
118118
--- request
119119
GET /?user_key=value
120120
--- response_headers
121-
x-fapi-transaction-id: abc
121+
x-fapi-interaction-id: abc
122122
--- error_code: 200
123123
--- no_error_log
124124
[error]
125125

126126

127127

128-
=== TEST 3: Use x-fapi-transaction-id header from upstream response
128+
=== TEST 3: Use x-fapi-interaction-id header from upstream response
129129
--- configuration
130130
{
131131
"services": [
@@ -160,14 +160,14 @@ x-fapi-transaction-id: abc
160160
--- upstream
161161
location / {
162162
content_by_lua_block {
163-
ngx.header['x-fapi-transaction-id'] = "blah"
163+
ngx.header['x-fapi-interaction-id'] = "blah"
164164
ngx.exit(200)
165165
}
166166
}
167167
--- request
168168
GET /?user_key=value
169169
--- response_headers
170-
x-fapi-transaction-id: blah
170+
x-fapi-interaction-id: blah
171171
--- error_code: 200
172172
--- no_error_log
173173
[error]
@@ -215,7 +215,7 @@ x-fapi-transaction-id: blah
215215
--- request
216216
GET /?user_key=value
217217
--- response_headers_like
218-
x-fapi-transaction-id: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
218+
x-fapi-interaction-id: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
219219
--- error_code: 200
220220
--- no_error_log
221221
[error]

0 commit comments

Comments
 (0)