diff --git a/apisix/admin/resource.lua b/apisix/admin/resource.lua index 35fe3bba2476..b03f1b069ea6 100644 --- a/apisix/admin/resource.lua +++ b/apisix/admin/resource.lua @@ -19,6 +19,7 @@ local utils = require("apisix.admin.utils") local apisix_ssl = require("apisix.ssl") local setmetatable = setmetatable local tostring = tostring +local ipairs = ipairs local type = type @@ -49,7 +50,38 @@ local function split_typ_and_id(id, sub_path) end -function _M:check_conf(id, conf, need_id, typ) +local function check_forbidden_properties(conf, forbidden_properties) + local not_allow_properties = "the property is forbidden: " + + if conf then + for _, v in ipairs(forbidden_properties) do + if conf[v] then + return not_allow_properties .. " " .. v + end + end + + if conf.upstream then + for _, v in ipairs(forbidden_properties) do + if conf.upstream[v] then + return not_allow_properties .. " upstream." .. v + end + end + end + + if conf.plugins then + for _, v in ipairs(forbidden_properties) do + if conf.plugins[v] then + return not_allow_properties .. " plugins." .. v + end + end + end + end + + return nil +end + + +function _M:check_conf(id, conf, need_id, typ, allow_time) if self.name == "secrets" then id = typ .. "/" .. id end @@ -76,6 +108,15 @@ function _M:check_conf(id, conf, need_id, typ) conf.id = id end + -- check create time and update time + if not allow_time then + local forbidden_properties = {"create_time", "update_time"} + local err = check_forbidden_properties(conf, forbidden_properties) + if err then + return nil, {error_msg = err} + end + end + core.log.info("conf : ", core.json.delay_encode(conf)) -- check the resource own rules @@ -355,7 +396,7 @@ function _M:patch(id, conf, sub_path, args) core.log.info("new conf: ", core.json.delay_encode(node_value, true)) - local ok, err = self:check_conf(id, node_value, true, typ) + local ok, err = self:check_conf(id, node_value, true, typ, true) if not ok then return 400, err end diff --git a/docs/en/latest/admin-api.md b/docs/en/latest/admin-api.md index 6f96e18abd88..396365f45e0f 100644 --- a/docs/en/latest/admin-api.md +++ b/docs/en/latest/admin-api.md @@ -325,8 +325,6 @@ ID's as a text string must be of a length between 1 and 64 characters and they s | timeout | False | Auxiliary | Sets the timeout (in seconds) for connecting to, and sending and receiving messages between the Upstream and the Route. This will overwrite the `timeout` value configured in your [Upstream](#upstream). | {"connect": 3, "send": 3, "read": 3} | | enable_websocket | False | Auxiliary | Enables a websocket. Set to `false` by default. | | | status | False | Auxiliary | Enables the current Route. Set to `1` (enabled) by default. | `1` to enable, `0` to disable | -| create_time | False | Auxiliary | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Auxiliary | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | Example configuration: @@ -630,8 +628,6 @@ Service resource request address: /apisix/admin/services/{id} | labels | False | Match Rules | Attributes of the Service specified as key-value pairs. | {"version":"v2","build":"16","env":"production"} | | enable_websocket | False | Auxiliary | Enables a websocket. Set to `false` by default. | | | hosts | False | Match Rules | Matches with any one of the multiple `host`s specified in the form of a non-empty list. | ["foo.com", "*.bar.com"] | -| create_time | False | Auxiliary | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Auxiliary | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | Example configuration: @@ -815,8 +811,6 @@ Consumer resource request address: /apisix/admin/consumers/{username} | plugins | False | Plugin | Plugins that are executed during the request/response cycle. See [Plugin](terminology/plugin.md) for more. | | | desc | False | Auxiliary | Description of usage scenarios. | customer xxxx | | labels | False | Match Rules | Attributes of the Consumer specified as key-value pairs. | {"version":"v2","build":"16","env":"production"} | -| create_time | False | Auxiliary | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Auxiliary | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | Example Configuration: @@ -911,8 +905,6 @@ In addition to the equalization algorithm selections, Upstream also supports pas | upstream_host | optional | Specifies the host of the Upstream request. This is only valid if the `pass_host` is set to `rewrite`. | | | scheme | optional | The scheme used when communicating with the Upstream. For an L7 proxy, this value can be one of `http`, `https`, `grpc`, `grpcs`. For an L4 proxy, this value could be one of `tcp`, `udp`, `tls`. Defaults to `http`. | | | labels | optional | Attributes of the Upstream specified as `key-value` pairs. | {"version":"v2","build":"16","env":"production"} | -| create_time | optional | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | optional | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | | tls.client_cert | optional, can't be used with `tls.client_cert_id` | Sets the client certificate while connecting to a TLS Upstream. | | | tls.client_key | optional, can't be used with `tls.client_cert_id` | Sets the client private key while connecting to a TLS Upstream. | | | tls.client_cert_id | optional, can't be used with `tls.client_cert` and `tls.client_key` | Set the referenced [SSL](#ssl) id. | | @@ -1210,8 +1202,6 @@ For notes on ID syntax please refer to: [ID Syntax](#quick-note-on-id-syntax) | client.skip_mtls_uri_regex | False | An array of regular expressions, in PCRE format | Used to match URI, if matched, this request bypasses the client certificate checking, i.e. skip the MTLS. | ["/hello[0-9]+", "/foobar"] | | snis | True, only if `type` is `server` | Match Rules | A non-empty array of HTTPS SNI | | | labels | False | Match Rules | Attributes of the resource specified as key-value pairs. | {"version":"v2","build":"16","env":"production"} | -| create_time | False | Auxiliary | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Auxiliary | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | | type | False | Auxiliary | Identifies the type of certificate, default `server`. | `client` Indicates that the certificate is a client certificate, which is used when APISIX accesses the upstream; `server` Indicates that the certificate is a server-side certificate, which is used by APISIX when verifying client requests. | | status | False | Auxiliary | Enables the current SSL. Set to `1` (enabled) by default. | `1` to enable, `0` to disable | | ssl_protocols | False | An array of ssl protocols | It is used to control the SSL/TLS protocol version used between servers and clients. See [SSL Protocol](./ssl-protocol.md) for more examples. | `["TLSv1.2", "TLSv2.3"]` | @@ -1253,8 +1243,6 @@ Global Rule resource request address: /apisix/admin/global_rules/{id} | Parameter | Required | Description | Example | | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------ | ---------- | | plugins | True | Plugins that are executed during the request/response cycle. See [Plugin](terminology/plugin.md) for more. | | -| create_time | False | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | ## Consumer group @@ -1282,8 +1270,6 @@ Consumer group resource request address: /apisix/admin/consumer_groups/{id} | plugins | True | Plugins that are executed during the request/response cycle. See [Plugin](terminology/plugin.md) for more. | | | desc | False | Description of usage scenarios. | customer xxxx | | labels | False | Attributes of the Consumer group specified as key-value pairs. | {"version":"v2","build":"16","env":"production"} | -| create_time | False | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | ## Plugin config @@ -1311,8 +1297,6 @@ Plugin Config resource request address: /apisix/admin/plugin_configs/{id} | plugins | True | Plugins that are executed during the request/response cycle. See [Plugin](terminology/plugin.md) for more. | | | desc | False | Description of usage scenarios. | customer xxxx | | labels | False | Attributes of the Plugin config specified as key-value pairs. | {"version":"v2","build":"16","env":"production"} | -| create_time | False | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | ## Plugin Metadata @@ -1528,11 +1512,9 @@ Proto resource request address: /apisix/admin/protos/{id} ### Request Body Parameters -| Parameter | Required | Type | Description | Example | -| ----------- | -------- | -------- | ------------------------------------------------------------------- | ----------------------------- | -| content | True | String | content of `.proto` or `.pb` files | See [here](./plugins/grpc-transcode.md#enabling-the-plugin) | -| create_time | False | Epoch timestamp (in seconds) of the created time. If missing, this field will be populated automatically. | 1602883670 | -| update_time | False | Epoch timestamp (in seconds) of the updated time. If missing, this field will be populated automatically. | 1602883670 | +| Parameter | Required | Type | Description | Example | +|-----------|----------|---------|--------------------------------------| ----------------------------- | +| content | True | String | content of `.proto` or `.pb` files | See [here](./plugins/grpc-transcode.md#enabling-the-plugin) | ## Schema validation diff --git a/docs/zh/latest/admin-api.md b/docs/zh/latest/admin-api.md index acef9a2ad107..dd2d257a4043 100644 --- a/docs/zh/latest/admin-api.md +++ b/docs/zh/latest/admin-api.md @@ -326,8 +326,6 @@ Route 也称之为路由,可以通过定义一些规则来匹配客户端的 | timeout | 否 | 辅助 | 为 Route 设置 Upstream 连接、发送消息和接收消息的超时时间(单位为秒)。该配置将会覆盖在 Upstream 中配置的 [timeout](#upstream) 选项。 | {"connect": 3, "send": 3, "read": 3} | | enable_websocket | 否 | 辅助 | 当设置为 `true` 时,启用 `websocket`(boolean), 默认值为 `false`。 | | | status | 否 | 辅助 | 当设置为 `1` 时,启用该路由,默认值为 `1`。 | `1` 表示启用,`0` 表示禁用。 | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | :::note 注意 @@ -637,8 +635,6 @@ Service 是某类 API 的抽象(也可以理解为一组 Route 的抽象)。 | labels | 否 | 匹配规则 | 标识附加属性的键值对。 | {"version":"v2","build":"16","env":"production"} | | enable_websocket | 否 | 辅助 | `websocket`(boolean) 配置,默认值为 `false`。 | | | hosts | 否 | 匹配规则 | 非空列表形态的 `host`,表示允许有多个不同 `host`,匹配其中任意一个即可。| ["foo.com", "\*.bar.com"] | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | Service 对象 JSON 配置示例: @@ -822,8 +818,6 @@ Consumer 资源请求地址:/apisix/admin/consumers/{username} | plugins | 否 | Plugin | 该 Consumer 对应的插件配置,它的优先级是最高的:Consumer > Route > Plugin Config > Service。对于具体插件配置,请参考 [Plugins](#plugin)。 | | | desc | 否 | 辅助 | consumer 描述。 | | | labels | 否 | 匹配规则 | 标识附加属性的键值对。 | {"version":"v2","build":"16","env":"production"} | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | Consumer 对象 JSON 配置示例: @@ -919,8 +913,6 @@ APISIX 的 Upstream 除了基本的负载均衡算法选择外,还支持对上 | upstream_host | 否 | 辅助 | 指定上游请求的 host,只在 `pass_host` 配置为 `rewrite` 时有效。 | | | scheme | 否 | 辅助 | 跟上游通信时使用的 scheme。对于 7 层代理,可选值为 [`http`, `https`, `grpc`, `grpcs`]。对于 4 层代理,可选值为 [`tcp`, `udp`, `tls`]。默认值为 `http`,详细信息请参考下文。 | | labels | 否 | 匹配规则 | 标识附加属性的键值对。 | {"version":"v2","build":"16","env":"production"} | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | | tls.client_cert | 否,不能和 `tls.client_cert_id` 一起使用 | https 证书 | 设置跟上游通信时的客户端证书,详细信息请参考下文。 | | | tls.client_key | 否,不能和 `tls.client_cert_id` 一起使用 | https 证书私钥 | 设置跟上游通信时的客户端私钥,详细信息请参考下文。 | | | tls.client_cert_id | 否,不能和 `tls.client_cert`、`tls.client_key` 一起使用 | SSL | 设置引用的 SSL id,详见 [SSL](#ssl)。 | | @@ -1210,8 +1202,6 @@ SSL 资源请求地址:/apisix/admin/ssls/{id} | client.skip_mtls_uri_regex | 否 | PCRE 正则表达式数组 | 用来匹配请求的 URI,如果匹配,则该请求将绕过客户端证书的检查,也就是跳过 MTLS。 | ["/hello[0-9]+", "/foobar"] | | snis | 是 | 匹配规则 | 非空数组形式,可以匹配多个 SNI。 | | | labels | 否 | 匹配规则 | 标识附加属性的键值对。 | {"version":"v2","build":"16","env":"production"} | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒。如果不指定则自动创建。 | 1602883670 | | type | 否 | 辅助 | 标识证书的类型,默认值为 `server`。 | `client` 表示证书是客户端证书,APISIX 访问上游时使用;`server` 表示证书是服务端证书,APISIX 验证客户端请求时使用。 | | status | 否 | 辅助 | 当设置为 `1` 时,启用此 SSL,默认值为 `1`。 | `1` 表示启用,`0` 表示禁用 | | ssl_protocols | 否 | tls 协议字符串数组 | 用于控制服务器与客户端之间使用的 SSL/TLS 协议版本。更多的配置示例,请参考[SSL 协议](./ssl-protocol.md)。 | | @@ -1253,8 +1243,6 @@ Global Rule 资源请求地址:/apisix/admin/global_rules/{id} | 名称 | 必选项 | 类型 | 描述 | 示例值 | | ----------- | ------ | ------ | ------------------------------------------------- | ---------- | | plugins | 是 | Plugin | 插件配置。详细信息请参考 [Plugin](terminology/plugin.md)。 | | -| create_time | 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 | 1602883670 | -| update_time | 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 | 1602883670 | ## Consumer Group @@ -1282,8 +1270,6 @@ Consumer Group 资源请求地址:/apisix/admin/consumer_groups/{id} |plugins | 是 |Plugin| 插件配置。详细信息请参考 [Plugin](terminology/plugin.md)。 | | |desc | 否 | 辅助 | 标识描述、使用场景等。 | Consumer 测试。| |labels | 否 | 辅助 | 标识附加属性的键值对。 |{"version":"v2","build":"16","env":"production"}| -|create_time| 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 |1602883670| -|update_time| 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 |1602883670| ## Plugin Config @@ -1311,8 +1297,6 @@ Plugin Config 资源请求地址:/apisix/admin/plugin_configs/{id} |plugins | 是 |Plugin| 更多信息请参考 [Plugin](terminology/plugin.md)。|| |desc | 否 | 辅助 | 标识描述、使用场景等。 |customer xxxx| |labels | 否 | 辅助 | 标识附加属性的键值对。 |{"version":"v2","build":"16","env":"production"}| -|create_time| 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 |1602883670| -|update_time| 否 | 辅助 | epoch 时间戳,单位为秒,如果不指定则自动创建。 |1602883670| ## Plugin Metadata diff --git a/t/admin/consumers.t b/t/admin/consumers.t index 23f3cffcc2b1..916f2a960bb9 100644 --- a/t/admin/consumers.t +++ b/t/admin/consumers.t @@ -335,26 +335,6 @@ GET /t } --- request GET /t ---- response_body -passed - - - -=== TEST 11: delete test consumer(pony) ---- config - location /t { - content_by_lua_block { - ngx.sleep(0.3) - local t = require("lib.test_admin").test - local code, body = t('/apisix/admin/consumers/pony', - ngx.HTTP_DELETE - ) - - ngx.status = code - ngx.say(body) - } - } ---- request -GET /t ---- response_body -passed +--- error_code: 400 +--- response_body eval +qr/\{"error_msg":"the property is forbidden:.*"\}/ diff --git a/t/admin/routes4.t b/t/admin/routes4.t index ba9ff44142e3..0bab4506b520 100644 --- a/t/admin/routes4.t +++ b/t/admin/routes4.t @@ -790,21 +790,6 @@ passed ngx.say(body) } } ---- response_body -passed - - - -=== TEST 23: delete test route(id : 1) ---- config - location /t { - content_by_lua_block { - local t = require("lib.test_admin").test - local code, message = t('/apisix/admin/routes/1', - ngx.HTTP_DELETE - ) - ngx.say("[delete] code: ", code, " message: ", message) - } - } ---- response_body -[delete] code: 200 message: passed +--- error_code: 400 +--- response_body eval +qr/\{"error_msg":"the property is forbidden:.*"\}/ diff --git a/t/admin/services.t b/t/admin/services.t index b2383ddc934b..90a5e9271a0f 100644 --- a/t/admin/services.t +++ b/t/admin/services.t @@ -1171,54 +1171,53 @@ GET /t local code, body = t('/apisix/admin/services/1', ngx.HTTP_PUT, [[{ - "upstream": { - "nodes": { - "127.0.0.1:8080": 1 - }, - "type": "roundrobin", - "create_time": 1602883670, - "update_time": 1602893670 - } - }]], - [[{ - "value": { - "upstream": { - "nodes": { - "127.0.0.1:8080": 1 - }, - "type": "roundrobin", - "create_time": 1602883670, - "update_time": 1602893670 - } + "upstream": { + "nodes": { + "127.0.0.1:8080": 1 }, - "key": "/apisix/services/1" - }]] - ) - + "type": "roundrobin" + }, + "create_time": 1602883670, + "update_time": 1602893670 + }]]) ngx.status = code ngx.say(body) } } --- request GET /t ---- response_body -passed +--- error_code: 400 +--- response_body eval +qr/\{"error_msg":"the property is forbidden:.*"\}/ -=== TEST 35: delete test service(id: 1) +=== TEST 35: create service and the built-in resource with create_time and update_time(id: 1) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test - local code, message = t('/apisix/admin/services/1', ngx.HTTP_DELETE) - ngx.say("[delete] code: ", code, " message: ", message) + local code, body = t('/apisix/admin/services/1', + ngx.HTTP_PUT, + [[{ + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:8080": 1 + }, + "create_time": 1602883670, + "update_time": 1602893670 + } + }]]) + ngx.status = code + ngx.say(body) } } --- request GET /t ---- response_body -[delete] code: 200 message: passed +--- error_code: 400 +--- response_body eval +qr/\{"error_msg":"the property is forbidden:.*"\}/ diff --git a/t/admin/ssl.t b/t/admin/ssl.t index 2e69e0b4671f..6b259b25ee4d 100644 --- a/t/admin/ssl.t +++ b/t/admin/ssl.t @@ -555,8 +555,6 @@ GET /t cert = ssl_cert, key = ssl_key, sni = "test.com", - create_time = 1602883670, - update_time = 1602893670, validity_start = 1602873670, validity_end = 1603893670 } @@ -567,8 +565,6 @@ GET /t [[{ "value": { "sni": "test.com", - "create_time": 1602883670, - "update_time": 1602893670, "validity_start": 1602873670, "validity_end": 1603893670 }, diff --git a/t/admin/upstream4.t b/t/admin/upstream4.t index b657edc6e731..411252486ca0 100644 --- a/t/admin/upstream4.t +++ b/t/admin/upstream4.t @@ -489,26 +489,13 @@ passed ngx.say(body) } } ---- response_body -passed - - - -=== TEST 15: delete test upstream ---- config - location /t { - content_by_lua_block { - local t = require("lib.test_admin").test - local code, message = t('/apisix/admin/upstreams/up_create_update_time', ngx.HTTP_DELETE) - ngx.say("[delete] code: ", code, " message: ", message) - } - } ---- response_body -[delete] code: 200 message: passed +--- error_code: 400 +--- response_body eval +qr/\{"error_msg":"the property is forbidden:.*"\}/ -=== TEST 16: patch upstream with sub_path, the data is number +=== TEST 15: patch upstream with sub_path, the data is number --- config location /t { content_by_lua_block { @@ -551,7 +538,7 @@ passed -=== TEST 17: set upstream(id: 1) +=== TEST 16: set upstream(id: 1) --- config location /t { content_by_lua_block { @@ -575,7 +562,7 @@ passed -=== TEST 18: set service(id: 1) +=== TEST 17: set service(id: 1) --- config location /t { content_by_lua_block { @@ -598,7 +585,7 @@ passed -=== TEST 19: set route(id: 1) +=== TEST 18: set route(id: 1) --- config location /t { content_by_lua_block { @@ -622,7 +609,7 @@ passed -=== TEST 20: delete upstream(id: 1) +=== TEST 19: delete upstream(id: 1) --- config location /t { content_by_lua_block { @@ -637,7 +624,7 @@ passed -=== TEST 21: delete route(id: 1) +=== TEST 20: delete route(id: 1) --- config location /t { content_by_lua_block { @@ -652,7 +639,7 @@ passed -=== TEST 22: delete service(id: 1) +=== TEST 21: delete service(id: 1) --- config location /t { content_by_lua_block { @@ -667,7 +654,7 @@ passed -=== TEST 23: delete upstream(id: 1) +=== TEST 22: delete upstream(id: 1) --- config location /t { content_by_lua_block {