You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/10/24 23:33:23 UTC

[apisix] branch master updated: feat(hmac-auth): remove auth headers for hmac-auth plugin. (#2491)

This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 853a7be  feat(hmac-auth): remove auth headers for hmac-auth plugin. (#2491)
853a7be is described below

commit 853a7be0f4f81cf080a52c13e2a284b3e0b2e5a2
Author: Firstsawyou <52...@users.noreply.github.com>
AuthorDate: Sun Oct 25 07:33:11 2020 +0800

    feat(hmac-auth): remove auth headers for hmac-auth plugin. (#2491)
    
    fix #2490
---
 apisix/plugins/hmac-auth.lua   |  34 ++++
 doc/plugins/hmac-auth.md       |  11 +-
 doc/zh-cn/plugins/hmac-auth.md |   1 +
 t/plugin/hmac-auth.t           | 385 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 426 insertions(+), 5 deletions(-)

diff --git a/apisix/plugins/hmac-auth.lua b/apisix/plugins/hmac-auth.lua
index edb3a78..57160d7 100644
--- a/apisix/plugins/hmac-auth.lua
+++ b/apisix/plugins/hmac-auth.lua
@@ -67,6 +67,11 @@ local consumer_schema = {
                 maxLength = 50,
             }
         },
+        keep_headers = {
+            type = "boolean",
+            title = "whether to keep the http request header",
+            default = false,
+        }
     },
     required = {"access_key", "secret_key"},
     additionalProperties = false,
@@ -118,6 +123,17 @@ local function array_to_map(arr)
 end
 
 
+local function remove_headers(...)
+    local headers = { ... }
+    if headers and #headers > 0 then
+        for _, header in ipairs(headers) do
+            core.log.info("remove_header: ", header)
+            core.request.set_header(header, nil)
+        end
+    end
+end
+
+
 local create_consumer_cache
 do
     local consumer_ids = {}
@@ -291,6 +307,17 @@ local function validate(ctx, params)
     return consumer
 end
 
+
+local function get_keep_headers(access_key)
+    local consumer, err = get_consumer(access_key)
+    if err then
+        return false, err
+    end
+
+    return consumer.auth_conf.keep_headers
+end
+
+
 local function get_params(ctx)
     local params = {}
     local local_conf = core.config.local_conf()
@@ -343,6 +370,13 @@ local function get_params(ctx)
     params.date  = date or ""
     params.signed_headers = signed_headers and ngx_re.split(signed_headers, ";")
 
+    local keep_headers = get_keep_headers(params.access_key)
+    core.log.info("keep_headers: ", keep_headers)
+
+    if not keep_headers then
+        remove_headers(signature_key, algorithm_key, signed_headers_key)
+    end
+
     core.log.info("params: ", core.json.delay_encode(params))
 
     return params
diff --git a/doc/plugins/hmac-auth.md b/doc/plugins/hmac-auth.md
index 753addd..8c1bf10 100644
--- a/doc/plugins/hmac-auth.md
+++ b/doc/plugins/hmac-auth.md
@@ -21,11 +21,11 @@
 
 # Summary
 
-- [**Name**](#name)
-- [**Attributes**](#attributes)
-- [**How To Enable**](#how-to-enable)
-- [**Test Plugin**](#test-plugin)
-- [**Disable Plugin**](#disable-plugin)
+  - [**Name**](#name)
+  - [**Attributes**](#attributes)
+  - [**How To Enable**](#how-to-enable)
+  - [**Test Plugin**](#test-plugin)
+  - [**Disable Plugin**](#disable-plugin)
 
 ## Name
 
@@ -42,6 +42,7 @@ The `consumer` then adds its key to request header to verify its request.
 | algorithm      | string        | optional    | "hmac-sha256" | ["hmac-sha1", "hmac-sha256", "hmac-sha512"] | Encryption algorithm.                                                                                                                                                                                                                                                         |
 | clock_skew     | integer       | optional    | 0           |                                             | The clock skew allowed by the signature in seconds. For example, if the time is allowed to skew by 10 seconds, then it should be set to `10`. especially, `0` means not checking `Date`                                                                                    |
 | 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. |
 
 ## How To Enable
 
diff --git a/doc/zh-cn/plugins/hmac-auth.md b/doc/zh-cn/plugins/hmac-auth.md
index 8ce726f..82a873f 100644
--- a/doc/zh-cn/plugins/hmac-auth.md
+++ b/doc/zh-cn/plugins/hmac-auth.md
@@ -42,6 +42,7 @@
 | algorithm      | string        | 可选   | "hmac-sha256" | ["hmac-sha1", "hmac-sha256", "hmac-sha512"] | 加密算法。                                                                                                                                                                              |
 | clock_skew     | integer       | 可选   | 0           |                                             | 签名允许的时间偏移,以秒为单位的计时。比如允许时间偏移 10 秒钟,那么就应设置为 `10`。特别地,`0` 表示不对 `Date` 进行检查。                                                        |
 | signed_headers | array[string] | 可选   |               |                                             | 限制加入加密计算的 headers ,指定后客户端请求只能在此范围内指定 headers ,此项为空时将把所有客户端请求指定的 headers 加入加密计算。如: ["User-Agent", "Accept-Language", "x-custom-a"] |
+| keep_headers | boolean | 可选   |      false        |           [ true, false ]                             | 认证成功后的 http 请求中是否需要保留 `X-HMAC-SIGNATURE`、`X-HMAC-ALGORITHM` 和 `X-HMAC-SIGNED-HEADERS` 的请求头。true: 表示保留 http 请求头,false: 表示移除 http 请求头。 |
 
 ## 如何启用
 
diff --git a/t/plugin/hmac-auth.t b/t/plugin/hmac-auth.t
index a91f4d0..42ca212 100644
--- a/t/plugin/hmac-auth.t
+++ b/t/plugin/hmac-auth.t
@@ -873,3 +873,388 @@ GET /t
 qr/\{"error_msg":"invalid plugins configuration: failed to check the configuration of plugin hmac-auth err: property \\"secret_key\\" is required"\}/
 --- no_error_log
 [error]
+
+
+
+=== TEST 25: enable the hmac auth plugin
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "hmac-auth": {}
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/uri"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 26: keep_headers field is empty
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "james",
+                    "plugins": {
+                        "hmac-auth": {
+                            "access_key": "my-access-key4",
+                            "secret_key": "my-secret-key4"                           
+                        }
+                    }
+                }]]
+                )
+            
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 27: verify pass(keep_headers field is empty), remove http request header
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time = ngx.time
+        local ngx_http_time = ngx.http_time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_re = require("ngx.re")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local data = {cert = "ssl_cert", key = "ssl_key", sni = "test.com"}
+        local req_body = core.json.encode(data)
+        req_body = req_body or ""
+
+        local secret_key = "my-secret-key4"
+        local timestamp = ngx_time()
+        local gmt = ngx_http_time(timestamp)
+        local access_key = "my-access-key4"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = {
+            "PUT",
+            "/uri",
+            "",
+            access_key,
+            gmt,
+            "x-custom-header-a:" .. custom_header_a,
+            "x-custom-header-b:" .. custom_header_b
+        }
+        signing_string = core.table.concat(signing_string, "\n")
+        core.log.info("signing_string:", signing_string)
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["Date"] = gmt
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, _, body = t.test('/uri',
+            ngx.HTTP_PUT,
+            req_body,
+            nil,
+            headers
+        )
+        
+        if code >= 300 then
+            ngx.status = code
+        end
+
+        local headers_arr = ngx_re.split(body, "\n")
+        for i, v in ipairs(headers_arr) do
+            if i ~= 4 then      -- skip date
+                ngx.say(v)
+            end
+        end
+    }
+}
+--- request
+GET /t
+--- response_body
+uri: /uri
+host: 127.0.0.1
+content-type: application/x-www-form-urlencoded
+x-real-ip: 127.0.0.1
+content-length: 52
+x-custom-header-b: 23879fmsldfk
+x-hmac-access-key: my-access-key4
+user-agent: lua-resty-http/0.14 (Lua) ngx_lua/10017
+x-custom-header-a: asld$%dfasf
+--- no_error_log
+[error]
+
+
+
+=== TEST 28: keep_headers field is false
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "james",
+                    "plugins": {
+                        "hmac-auth": {
+                            "access_key": "my-access-key4",
+                            "secret_key": "my-secret-key4",
+                            "keep_headers": false
+                        }
+                    }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 29: verify pass(keep_headers field is false), remove http request header
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time = ngx.time
+        local ngx_http_time = ngx.http_time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_re = require("ngx.re")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local data = {cert = "ssl_cert", key = "ssl_key", sni = "test.com"}
+        local req_body = core.json.encode(data)
+        req_body = req_body or ""
+
+        local secret_key = "my-secret-key4"
+        local timestamp = ngx_time()
+        local gmt = ngx_http_time(timestamp)
+        local access_key = "my-access-key4"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = {
+            "PUT",
+            "/uri",
+            "",
+            access_key,
+            gmt,
+            "x-custom-header-a:" .. custom_header_a,
+            "x-custom-header-b:" .. custom_header_b
+        }
+        signing_string = core.table.concat(signing_string, "\n")
+        core.log.info("signing_string:", signing_string)
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["Date"] = gmt
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, _, body = t.test('/uri',
+            ngx.HTTP_PUT,
+            req_body,
+            nil,
+            headers
+        )
+
+        if code >= 300 then
+            ngx.status = code
+        end
+
+        local headers_arr = ngx_re.split(body, "\n")
+        for i, v in ipairs(headers_arr) do
+            if i ~= 4 then      -- skip date
+                ngx.say(v)
+            end
+        end
+    }
+}
+--- request
+GET /t
+--- response_body
+uri: /uri
+host: 127.0.0.1
+content-type: application/x-www-form-urlencoded
+x-real-ip: 127.0.0.1
+content-length: 52
+x-custom-header-b: 23879fmsldfk
+x-hmac-access-key: my-access-key4
+user-agent: lua-resty-http/0.14 (Lua) ngx_lua/10017
+x-custom-header-a: asld$%dfasf
+--- no_error_log
+[error]
+
+
+
+=== TEST 30: keep_headers field is true
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "james",
+                    "plugins": {
+                        "hmac-auth": {
+                            "access_key": "my-access-key4",
+                            "secret_key": "my-secret-key4",
+                            "keep_headers": true
+                        }
+                    }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 31: verify pass(keep_headers field is true), keep http request header
+--- config
+location /t {
+    content_by_lua_block {
+        local ngx_time = ngx.time
+        local ngx_http_time = ngx.http_time
+        local core = require("apisix.core")
+        local t = require("lib.test_admin")
+        local hmac = require("resty.hmac")
+        local ngx_re = require("ngx.re")
+        local ngx_encode_base64 = ngx.encode_base64
+
+        local data = {cert = "ssl_cert", key = "ssl_key", sni = "test.com"}
+        local req_body = core.json.encode(data)
+        req_body = req_body or ""
+
+        local secret_key = "my-secret-key4"
+        local timestamp = ngx_time()
+        local gmt = ngx_http_time(timestamp)
+        local access_key = "my-access-key4"
+        local custom_header_a = "asld$%dfasf"
+        local custom_header_b = "23879fmsldfk"
+
+        local signing_string = {
+            "PUT",
+            "/uri",
+            "",
+            access_key,
+            gmt,
+            "x-custom-header-a:" .. custom_header_a,
+            "x-custom-header-b:" .. custom_header_b
+        }
+        signing_string = core.table.concat(signing_string, "\n")
+        core.log.info("signing_string:", signing_string)
+
+        local signature = hmac:new(secret_key, hmac.ALGOS.SHA256):final(signing_string)
+        core.log.info("signature:", ngx_encode_base64(signature))
+        local headers = {}
+        headers["X-HMAC-SIGNATURE"] = ngx_encode_base64(signature)
+        headers["X-HMAC-ALGORITHM"] = "hmac-sha256"
+        headers["Date"] = gmt
+        headers["X-HMAC-ACCESS-KEY"] = access_key
+        headers["X-HMAC-SIGNED-HEADERS"] = "x-custom-header-a;x-custom-header-b"
+        headers["x-custom-header-a"] = custom_header_a
+        headers["x-custom-header-b"] = custom_header_b
+
+        local code, _, body = t.test('/uri',
+            ngx.HTTP_PUT,
+            req_body,
+            nil,
+            headers
+        )
+
+        if code >= 300 then
+            ngx.status = code
+        end
+        
+        local headers_arr = ngx_re.split(body, "\n")
+        for i, v in ipairs(headers_arr) do
+            if i ~= 4 and i ~= 12 then      -- skip date and x-hmac-signature
+                ngx.say(v)
+            end
+        end
+    }
+}
+--- request
+GET /t
+--- response_body
+uri: /uri
+host: 127.0.0.1
+content-type: application/x-www-form-urlencoded
+x-real-ip: 127.0.0.1
+user-agent: lua-resty-http/0.14 (Lua) ngx_lua/10017
+content-length: 52
+x-hmac-signed-headers: x-custom-header-a;x-custom-header-b
+x-custom-header-b: 23879fmsldfk
+x-hmac-algorithm: hmac-sha256
+x-hmac-access-key: my-access-key4
+x-custom-header-a: asld$%dfasf
+--- no_error_log
+[error]