-- -- Licensed to the Apache Software Foundation (ASF) under one or more -- contributor license agreements. See the NOTICE file distributed with -- this work for additional information regarding copyright ownership. -- The ASF licenses this file to You under the Apache License, Version 2.0 -- (the "License"); you may not use this file except in compliance with -- the License. You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- local jsonschema = require("jsonschema") local pairs = pairs local pcall = pcall local require = require local _M = {} local etcd_schema = { type = "object", properties = { resync_delay = { type = "integer", }, user = { type = "string", }, password = { type = "string", }, tls = { type = "object", properties = { cert = { type = "string", }, key = { type = "string", }, }, }, prefix = { type = "string", }, host = { type = "array", items = { type = "string", pattern = [[^https?://]] }, minItems = 1, }, timeout = { type = "integer", default = 30, minimum = 1, description = "etcd connection timeout in seconds", }, }, required = {"prefix", "host"} } local config_schema = { type = "object", properties = { apisix = { properties = { lua_module_hook = { pattern = "^[a-zA-Z._-]+$", }, proxy_protocol = { type = "object", properties = { listen_http_port = { type = "integer", }, listen_https_port = { type = "integer", }, enable_tcp_pp = { type = "boolean", }, enable_tcp_pp_to_upstream = { type = "boolean", }, } }, proxy_cache = { type = "object", properties = { zones = { type = "array", minItems = 1, items = { type = "object", properties = { name = { type = "string", }, memory_size = { type = "string", }, disk_size = { type = "string", }, disk_path = { type = "string", }, cache_levels = { type = "string", }, }, oneOf = { { required = {"name", "memory_size"}, maxProperties = 2, }, { required = {"name", "memory_size", "disk_size", "disk_path", "cache_levels"}, } }, }, uniqueItems = true, } } }, proxy_mode = { type = "string", enum = {"http", "stream", "http&stream"}, }, stream_proxy = { type = "object", properties = { tcp = { type = "array", minItems = 1, items = { anyOf = { { type = "integer", }, { type = "string", }, { type = "object", properties = { addr = { anyOf = { { type = "integer", }, { type = "string", }, } }, tls = { type = "boolean", } }, required = {"addr"} }, }, }, uniqueItems = true, }, udp = { type = "array", minItems = 1, items = { anyOf = { { type = "integer", }, { type = "string", }, }, }, uniqueItems = true, }, } }, dns_resolver = { type = "array", minItems = 1, items = { type = "string", } }, dns_resolver_valid = { type = "integer", }, enable_http2 = { type = "boolean", default = true }, ssl = { type = "object", properties = { ssl_trusted_certificate = { type = "string", default = "system" }, listen = { type = "array", items = { type = "object", properties = { ip = { type = "string", }, port = { type = "integer", minimum = 1, maximum = 65535 }, enable_http3 = { type = "boolean", }, } } }, } }, data_encryption = { type = "object", properties = { keyring = { anyOf = { { type = "array", minItems = 1, items = { type = "string", minLength = 16, maxLength = 16 } }, { type = "string", minLength = 16, maxLength = 16 } } }, } }, } }, nginx_config = { type = "object", properties = { envs = { type = "array", minItems = 1, items = { type = "string", } } }, }, http = { type = "object", properties = { custom_lua_shared_dict = { type = "object", } } }, etcd = etcd_schema, plugins = { type = "array", default = {}, minItems = 0, items = { type = "string" } }, stream_plugins = { type = "array", default = {}, minItems = 0, items = { type = "string" } }, wasm = { type = "object", properties = { plugins = { type = "array", minItems = 1, items = { type = "object", properties = { name = { type = "string" }, file = { type = "string" }, priority = { type = "integer" }, http_request_phase = { enum = {"access", "rewrite"}, default = "access", }, }, required = {"name", "file", "priority"} } } } }, deployment = { type = "object", properties = { role = { enum = {"traditional", "control_plane", "data_plane", "standalone"}, default = "traditional" } }, }, }, required = {"apisix", "deployment"}, } local admin_schema = { type = "object", properties = { admin_key = { type = "array", properties = { items = { properties = { name = {type = "string"}, key = {type = "string"}, role = {type = "string"}, } } } }, admin_listen = { properties = { listen = { type = "string" }, port = { type = "integer" }, }, default = { listen = "0.0.0.0", port = 9180, } }, https_admin = { type = "boolean", }, admin_key_required = { type = "boolean", }, } } local deployment_schema = { traditional = { properties = { etcd = etcd_schema, admin = admin_schema, role_traditional = { properties = { config_provider = { enum = {"etcd", "yaml"} }, }, required = {"config_provider"} } }, required = {"etcd"} }, control_plane = { properties = { etcd = etcd_schema, admin = admin_schema, role_control_plane = { properties = { config_provider = { enum = {"etcd"} }, }, required = {"config_provider"} }, }, required = {"etcd", "role_control_plane"} }, data_plane = { properties = { etcd = etcd_schema, role_data_plane = { properties = { config_provider = { enum = {"etcd", "yaml", "json", "xds"} }, }, required = {"config_provider"} }, }, required = {"role_data_plane"} } } function _M.validate(yaml_conf) local validator = jsonschema.generate_validator(config_schema) local ok, err = validator(yaml_conf) if not ok then return false, "failed to validate config: " .. err end if yaml_conf.discovery then for kind, conf in pairs(yaml_conf.discovery) do local ok, schema = pcall(require, "apisix.discovery." .. kind .. ".schema") if ok then local validator = jsonschema.generate_validator(schema) local ok, err = validator(conf) if not ok then return false, "invalid discovery " .. kind .. " configuration: " .. err end end end end local role = yaml_conf.deployment.role local validator = jsonschema.generate_validator(deployment_schema[role]) local ok, err = validator(yaml_conf.deployment) if not ok then return false, "invalid deployment " .. role .. " configuration: " .. err end return true end return _M