feat(hmac-auth): Add validate request body for hmac auth plugin#5038
Conversation
| max_req_body | boolean | 可选 | false | [ true, false ] | 最大允许的 body 大小 |
| if not req_body then | ||
| req_body = "" | ||
| end | ||
| local digest_header = core.request.header(ctx, DIGEST) |
There was a problem hiding this comment.
digest header looks not good for me.
There was a problem hiding this comment.
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.
Can you help to update the English doc?
| if not req_body then | ||
| req_body = "" | ||
| end |
There was a problem hiding this comment.
| if not req_body then | |
| req_body = "" | |
| end | |
| req_body = req_body or "" |
| 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.
Maybe not, because we can omit digest header when body is empty.
|
|
||
| ### Body 校验 | ||
|
|
||
| 把 `validate_request_body` 设置为 true 来进行请求 body 的校验。 插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
| 把 `validate_request_body` 设置为 true 来进行请求 body 的校验。 插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 | |
| 把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
Digest in code is digest, better to keep same.
| req_body = "" | ||
| end | ||
| local digest_header = core.request.header(ctx, DIGEST) | ||
| if not digest_header then |
There was a problem hiding this comment.
we could check this before reading the body
There was a problem hiding this comment.
Maybe not, because we can omit digest header when body is empty.
|
hi @arthur-zhang, I notice this |
I Add test |
|
|
||
| ### Body 校验 | ||
|
|
||
| 把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 |
There was a problem hiding this comment.
| 把 `validate_request_body` 设置为 true 来进行请求 body 的校验。插件将计算 hmac-sha 值,对比头部中的 Digest 头部值。 | |
| `validate_request_body` 设置为 true 时,插件将计算请求 body 的 `hmac-sha` 值,并与请求 headers 中的 Digest 的值进行校验。 |
|
|
||
|
|
||
|
|
||
| === TEST 3: missing body digest when validate_request_body is true |
There was a problem hiding this comment.
| === TEST 3: missing body digest when validate_request_body is true | |
| === TEST 3: missing body digest when validate_request_body is enable |
|
|
||
|
|
||
|
|
||
| === TEST 4: missing digest header and body is empty |
There was a problem hiding this comment.
| === 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, |
| Digest: base64(hmac-sha(<body>)) | ||
| ``` | ||
|
|
||
| 当无请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,可计算长度为 0 的空字符串的 hmac-sha 值。 |
There was a problem hiding this comment.
| 当无请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,可计算长度为 0 的空字符串的 hmac-sha 值。 | |
| 当没有请求 body 时,可不传 Digest 头部,网关会校验是否确实无请求 body。如果要传 Digest 头部,插件将请求 body 默认为长度为 0 的空字符串,并参与到计算 hmac-sha 值。 |
| default = false, | ||
| }, | ||
| max_req_body = { | ||
| type = "number", |
There was a problem hiding this comment.
| type = "number", | |
| type = "integer", |
| | 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.
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.
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.
| local ngx_decode_base64 = ngx.decode_base64 | ||
| local ngx_encode_base64 = ngx.encode_base64 | ||
|
|
||
| local DIGEST = "Digest" |
There was a problem hiding this comment.
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
|
|
||
| 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.
I think we could return here if no params.body_digest.
There was a problem hiding this comment.
I think we should check whether the params.body_digest exists or not.
There was a problem hiding this comment.
when validate_request_body == true and no params.body_digest, why not return false?
There was a problem hiding this comment.
When there is no request body, the X-HMAC-DIGEST header can be omitted.
There was a problem hiding this comment.
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.
| 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.
Any string here is ok, I will change it to X-HMAC-DIGEST.
|
|
||
| ### 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.
Better to mention the max_req_body limitation
There was a problem hiding this comment.
I add a note to that
| 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.
| 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. |
| }, | ||
| max_req_body = { | ||
| type = "integer", | ||
| title = "Max request body allowed", |
There was a problem hiding this comment.
"Max request body size" would be better.
|
|
||
| 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.
| **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: