-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(hmac-auth): Add validate request body for hmac auth plugin #5038
feat(hmac-auth): Add validate request body for hmac auth plugin #5038
Conversation
| max_req_body | boolean | 可选 | false | [ true, false ] | 最大允许的 body 大小 |
apisix/plugins/hmac-auth.lua
Outdated
if not req_body then | ||
req_body = "" | ||
end | ||
local digest_header = core.request.header(ctx, DIGEST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
digest
header looks not good for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I use this header is that:
The Digest HTTP header provides a digest of the requested resource.
Date: Tue, 19 Jan 2021 11:33:20 GMT | ||
Server: APISIX/2.2 | ||
...... | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you help to update the English doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will
apisix/plugins/hmac-auth.lua
Outdated
if not req_body then | ||
req_body = "" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if not req_body then | |
req_body = "" | |
end | |
req_body = req_body or "" |
apisix/plugins/hmac-auth.lua
Outdated
if not digest_header then | ||
-- it's ok if there is no digest header and no body | ||
return req_body == "" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we judge this first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe not, because we can omit digest header when body is empty.
docs/zh/latest/plugins/hmac-auth.md
Outdated
@@ -186,6 +188,16 @@ print(base64.b64encode(hash.digest())) | |||
| --------- | -------------------------------------------- | | |||
| SIGNATURE | 8XV1GB7Tq23OJcoz6wjqTs4ZLxr9DiLoY4PxzScWGYg= | | |||
|
|||
### Body 校验 | |||
|
|||
把 `validate_request_body` 设置为 true 来进行请求 body 的校验。 插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
把 `validate_request_body` 设置为 true 来进行请求 body 的校验。 插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 | |
把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Digest
in code is digest
, better to keep same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
apisix/plugins/hmac-auth.lua
Outdated
req_body = "" | ||
end | ||
local digest_header = core.request.header(ctx, DIGEST) | ||
if not digest_header then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could check this before reading the body
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe not, because we can omit digest header when body is empty.
hi @arthur-zhang, I notice this |
I Add test |
docs/zh/latest/plugins/hmac-auth.md
Outdated
@@ -186,6 +188,16 @@ print(base64.b64encode(hash.digest())) | |||
| --------- | -------------------------------------------- | | |||
| SIGNATURE | 8XV1GB7Tq23OJcoz6wjqTs4ZLxr9DiLoY4PxzScWGYg= | | |||
|
|||
### Body 校验 | |||
|
|||
把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 | |
`validate_request_body` 设置为 true 时,插件将计算请求 body 的 `hmac-sha` 值,并与请求 headers 中的 Digest 的值进行校验。 |
t/plugin/hmac-auth3.t
Outdated
|
||
|
||
|
||
=== TEST 3: missing body digest when validate_request_body is true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
=== TEST 3: missing body digest when validate_request_body is true | |
=== TEST 3: missing body digest when validate_request_body is enable |
t/plugin/hmac-auth3.t
Outdated
|
||
|
||
|
||
=== TEST 4: missing digest header and body is empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
=== TEST 4: missing digest header and body is empty | |
=== TEST 4: no digest header and request body is empty |
|
||
local code, body = t.test('/hello', | ||
ngx.HTTP_POST, | ||
body, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here body should be nil
?
docs/zh/latest/plugins/hmac-auth.md
Outdated
Digest: base64(hmac-sha(<body>)) | ||
``` | ||
|
||
当无请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,可计算长度为 0 的空字符串的 hmac-sha 值。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
当无请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,可计算长度为 0 的空字符串的 hmac-sha 值。 | |
当没有请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,插件将请求 body 默认为长度为 0 的空字符串,并参与到计算 hmac-sha 值。 |
apisix/plugins/hmac-auth.lua
Outdated
default = false, | ||
}, | ||
max_req_body = { | ||
type = "number", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type = "number", | |
type = "integer", |
docs/en/latest/plugins/hmac-auth.md
Outdated
@@ -51,6 +51,8 @@ The `consumer` then adds its key to request header to verify its request. | |||
| signed_headers | array[string] | optional | | | Restrict the headers that are added to the encrypted calculation. After the specified, the client request can only specify the headers within this range. When this item is empty, all the headers specified by the client request will be added to the encrypted calculation | | |||
| keep_headers | boolean | optional | false | [ true, false ] | Whether it is necessary to keep the request headers of `X-HMAC-SIGNATURE`, `X-HMAC-ALGORITHM` and `X-HMAC-SIGNED-HEADERS` in the http request after successful authentication. true: means to keep the http request header, false: means to remove the http request header. | | |||
| encode_uri_params | boolean | optional | true | [ true, false ] | Whether to encode the uri parameter in the signature, for example: `params1=hello%2Cworld` is encoded, `params2=hello,world` is not encoded. true: means to encode the uri parameter in the signature, false: not to encode the uri parameter in the signature. | | |||
| validate_request_body | boolean | optional | false | [ true, false ] | Whether to check request body. | | |||
| max_req_body | number | optional | 512KB | | Max allowed body size. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use a number instead of string in the doc's default value cell
-H 'Content-Type: text/plain; charset=utf-8' \ | ||
-d "{\"hello\":\"world\"}" | ||
|
||
HTTP/1.1 200 OK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to only show the first line? APISIX 2.2 doesn't support this feature. We can avoid confusing users by only show the first line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it
apisix/plugins/hmac-auth.lua
Outdated
|
||
local DIGEST = "Digest" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this header configurable and default to "X-HMAC-DIGEST"?
There is already a Digest header in the HTTP standard and it is not relative to the hmac.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
@@ -327,6 +351,18 @@ local function validate(ctx, params) | |||
return nil, {message = "Invalid signature"} | |||
end | |||
|
|||
local validate_request_body = get_conf_field(params.access_key, "validate_request_body") | |||
if validate_request_body then | |||
local max_req_body = get_conf_field(params.access_key, "max_req_body") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could return here if no params.body_digest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should check whether the params.body_digest exists or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when validate_request_body == true and no params.body_digest, why not return false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When there is no request body, the X-HMAC-DIGEST
header can be omitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Thanks for your explanation. How about when validate_request_body
is enabled, X-APISIX-HMAC-BODY-DIGEST
is required? Just pass empty strings for it when no body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix it
t/plugin/hmac-auth3.t
Outdated
headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature) | ||
headers["X-HMAC-ALGORITHM"] = "hmac-sha256" | ||
headers["Date"] = gmt | ||
headers["X-Digest"] = ngx_encode_base64(body_digest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be X-HMAC-DIGEST
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any string here is ok, I will change it to X-HMAC-DIGEST.
@@ -192,6 +194,16 @@ print(base64.b64encode(hash.digest())) | |||
| --------- | -------------------------------------------- | | |||
| SIGNATURE | 8XV1GB7Tq23OJcoz6wjqTs4ZLxr9DiLoY4PxzScWGYg= | | |||
|
|||
### Request body checking | |||
|
|||
When `validate_request_body` is assigned to `true`, the plugin will check the request body. The plugin will calculate the hmac-sha value of the request body,and check against the `X-HMAC-DIGEST` header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to mention the max_req_body limitation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add a note to that
docs/en/latest/plugins/hmac-auth.md
Outdated
X-HMAC-DIGEST: base64(hmac-sha(<body>)) | ||
``` | ||
|
||
When there is no request body, the `X-HMAC-DIGEST` header can be omitted. If you want to send request with this header whether the body is empty or not, you can set `X-HMAC-DIGEST` value to the hmac-sha of empty string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When there is no request body, the `X-HMAC-DIGEST` header can be omitted. If you want to send request with this header whether the body is empty or not, you can set `X-HMAC-DIGEST` value to the hmac-sha of empty string. | |
When there is no request body, the `X-HMAC-DIGEST` header can be omitted. If you want to send a request with this header when the body is missing, you can set `X-HMAC-DIGEST` value to the hmac-sha of empty string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
apisix/plugins/hmac-auth.lua
Outdated
}, | ||
max_req_body = { | ||
type = "integer", | ||
title = "Max request body allowed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Max request body size" would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
docs/en/latest/plugins/hmac-auth.md
Outdated
|
||
When there is no request body, the `X-HMAC-DIGEST` header can be omitted. If you want to send a request with this header when the body is missing, you can set `X-HMAC-DIGEST` value to the hmac-sha of empty string. | ||
|
||
**Note:** The plugin will load the request body to memory to calculate the digest of the request body, which wight cause high memory consumption with large bodies. You can limit the max allowed body size by the configuration of `max_req_body`(default=512KB), request body larger than that will be rejected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
**Note:** The plugin will load the request body to memory to calculate the digest of the request body, which wight cause high memory consumption with large bodies. You can limit the max allowed body size by the configuration of `max_req_body`(default=512KB), request body larger than that will be rejected. | |
**Note:** The plugin will load the request body to memory to calculate the digest of the request body, which might cause high memory consumption with large bodies. You can limit the max allowed body size by the configuration of `max_req_body`(default=512KB), request body larger than that will be rejected. |
What this PR does / why we need it:
Add validate request body for hmac auth plugin, by calculate body hmac hash and put it in Digest Header
Pre-submission checklist: