Skip to content

Commit 157a788

Browse files
committed
fix(request): remove unescape operation for user-input query params when building canonical querystring
1 parent 2e622c0 commit 157a788

File tree

5 files changed

+147
-3
lines changed

5 files changed

+147
-3
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ Release process:
176176
1. upload using: `VERSION=x.y.z APIKEY=abc... make upload`
177177
1. test installing the rock from LuaRocks
178178

179+
### Unreleased
180+
181+
- fix: fix an issue when publish sns message with urlencode reserved character(+/%)
182+
[132](https://github.com/Kong/lua-resty-aws/pull/132)
179183

180184
### 1.5.4 (23-Sep-2024)
181185

spec/02-requests/02-build_request_spec.lua

+60
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,36 @@ describe("operations protocol", function()
136136
},
137137
}
138138

139+
operation_with_requestUri_params_and_query_param_input = {
140+
name = "PutObject",
141+
http = {
142+
method = "PUT",
143+
requestUri = "/{Bucket}/{Key+}?testparam=testparamvalue"
144+
},
145+
input = {
146+
type = "structure",
147+
required = {
148+
"Bucket",
149+
"Key"
150+
},
151+
members = {
152+
TestMember = {
153+
type = "string",
154+
},
155+
Bucket = {
156+
type = "string",
157+
location = "uri",
158+
locationName = "Bucket"
159+
},
160+
Key = {
161+
type = "string",
162+
location = "uri",
163+
locationName = "Key"
164+
},
165+
},
166+
},
167+
}
168+
139169
config = {
140170
apiVersion = "2011-06-15",
141171
--endpointPrefix = "sts",
@@ -184,6 +214,12 @@ describe("operations protocol", function()
184214
Body = binary_data,
185215
}
186216

217+
params_with_requestUri_params_and_query_param_input = {
218+
Bucket = "hello",
219+
Key = "world",
220+
TestMember = "testvalue",
221+
}
222+
187223
end)
188224

189225

@@ -226,6 +262,30 @@ describe("operations protocol", function()
226262
}, request)
227263
end)
228264

265+
it("query: undefined location params go into query table, with requestUri query params added", function ()
266+
config_with_payload.protocol = "query"
267+
268+
local request = build_request(operation_with_requestUri_params_and_query_param_input,
269+
config_with_payload, params_with_requestUri_params_and_query_param_input)
270+
assert.same({
271+
headers = {
272+
["X-Amz-Target"] = "s3.PutObject",
273+
["Host"] = "s3.amazonaws.com",
274+
},
275+
method = 'PUT',
276+
path = '/hello/world',
277+
host = 's3.amazonaws.com',
278+
port = 443,
279+
query = {
280+
Action = "PutObject",
281+
Version = "2006-03-01",
282+
testparam = "testparamvalue",
283+
TestMember = "testvalue",
284+
}
285+
}, request)
286+
287+
end)
288+
229289

230290
it("rest-json: querystring, uri, header and body params", function()
231291

spec/04-services/06-sns_spec.lua

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
setmetatable(_G, nil)
2+
3+
local AWS = require("resty.aws")
4+
local AWS_global_config = require("resty.aws.config").global
5+
6+
7+
local config = AWS_global_config
8+
config.tls = true
9+
local aws = AWS(config)
10+
11+
12+
aws.config.credentials = aws:Credentials {
13+
accessKeyId = "test_id",
14+
secretAccessKey = "test_key",
15+
}
16+
17+
aws.config.region = "test_region"
18+
aws.config.dry_run = true
19+
20+
describe("SNS service", function()
21+
local sns
22+
local origin_time
23+
24+
setup(function()
25+
origin_time = ngx.time
26+
ngx.time = function () --luacheck: ignore
27+
return 1667543171
28+
end
29+
end)
30+
31+
teardown(function ()
32+
ngx.time = origin_time --luacheck: ignore
33+
end)
34+
35+
before_each(function()
36+
sns = assert(aws:SNS({}))
37+
end)
38+
39+
after_each(function()
40+
end)
41+
42+
local testcases = {
43+
publish = {
44+
{
45+
TopicArn = "arn:aws:sns:test-region:000000000000:test-topic",
46+
Message = '{"timestamp":"1980-01-02T08:11:12.123+01:00","message":"test%abc%22"}', -- this is not an urlencoded message value
47+
},
48+
{
49+
['headers'] = {
50+
['Authorization'] = 'AWS4-HMAC-SHA256 Credential=test_id/20221104/test_region/sns/aws4_request, SignedHeaders=host;x-amz-date, Signature=9a83a7bafbccd6c3214091baf22eb1d1e507327be18f7ad5cf8ccc45ac335e48',
51+
['Host'] = 'sns.test_region.amazonaws.com',
52+
['X-Amz-Date'] = '20221104T062611Z',
53+
},
54+
['host'] = 'sns.test_region.amazonaws.com',
55+
['method'] = 'POST',
56+
['path'] = '/',
57+
['proxy_opts'] = {},
58+
['port'] = 443,
59+
['query'] = {
60+
['Action'] = 'Publish',
61+
['Version'] = '2010-03-31',
62+
['Message'] = '{"timestamp":"1980-01-02T08:11:12.123+01:00","message":"test%abc%22"}',
63+
['TopicArn'] = 'arn:aws:sns:test-region:000000000000:test-topic',
64+
},
65+
['tls'] = true,
66+
},
67+
},
68+
}
69+
70+
for api, test in pairs(testcases) do
71+
it("SecretsManager:" .. api, function()
72+
local param = test[1]
73+
local expected_result_aws = test[2]
74+
75+
local result_aws = assert(sns[api](sns, param))
76+
77+
assert.same(expected_result_aws, result_aws)
78+
end)
79+
end
80+
end)

src/resty/aws/request/build.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ local function build_request(operation, config, params)
202202
request.path = path
203203

204204
for k,v in pairs(parse_query(query)) do
205-
request.query[k] = v
205+
request.query[ngx.unescape_uri(k)] = ngx.unescape_uri(v)
206206
end
207207

208208
local payload_member = operation.input and operation.input.payload

src/resty/aws/request/signatures/utils.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ local function canonicalise_query_string(query)
7373

7474
elseif type(query) == "table" then
7575
for key, val in pairs(query) do
76-
key = ngx.unescape_uri(key):gsub("[^%w%-%._~]", percent_encode)
77-
val = ngx.unescape_uri(val):gsub("[^%w%-%._~]", percent_encode)
76+
key = key:gsub("[^%w%-%._~]", percent_encode)
77+
val = val:gsub("[^%w%-%._~]", percent_encode)
7878
q[#q+1] = key .. "=" .. val
7979
end
8080

0 commit comments

Comments
 (0)