- Implements Apache APISIX packaging for Cloudron platform. - Includes Dockerfile, CloudronManifest.json, and start.sh. - Configured to use Cloudron's etcd addon. 🤖 Generated with Gemini CLI Co-Authored-By: Gemini <noreply@google.com>
176 lines
5.3 KiB
Lua
176 lines
5.3 KiB
Lua
-- 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 common libs
|
|
local require = require
|
|
local pcall = pcall
|
|
local ffi = require("ffi")
|
|
local C = ffi.C
|
|
local get_request = require("resty.core.base").get_request
|
|
local core = require("apisix.core")
|
|
local radixtree_sni = require("apisix.ssl.router.radixtree_sni")
|
|
local apisix_ssl = require("apisix.ssl")
|
|
local _, ssl = pcall(require, "resty.apisix.ssl")
|
|
local error = error
|
|
|
|
|
|
ffi.cdef[[
|
|
unsigned long Tongsuo_version_num(void)
|
|
]]
|
|
|
|
|
|
-- local function
|
|
local function set_pem_ssl_key(sni, enc_cert, enc_pkey, sign_cert, sign_pkey)
|
|
local r = get_request()
|
|
if r == nil then
|
|
return false, "no request found"
|
|
end
|
|
|
|
local parsed_enc_cert, err = apisix_ssl.fetch_cert(sni, enc_cert)
|
|
if not parsed_enc_cert then
|
|
return false, "failed to parse enc PEM cert: " .. err
|
|
end
|
|
|
|
local parsed_sign_cert, err = apisix_ssl.fetch_cert(sni, sign_cert)
|
|
if not parsed_sign_cert then
|
|
return false, "failed to parse sign PEM cert: " .. err
|
|
end
|
|
|
|
local ok, err = ssl.set_gm_cert(parsed_enc_cert, parsed_sign_cert)
|
|
if not ok then
|
|
return false, "failed to set PEM cert: " .. err
|
|
end
|
|
|
|
local parsed_enc_pkey, err = apisix_ssl.fetch_pkey(sni, enc_pkey)
|
|
if not parsed_enc_pkey then
|
|
return false, "failed to parse enc PEM priv key: " .. err
|
|
end
|
|
|
|
local parsed_sign_pkey, err = apisix_ssl.fetch_pkey(sni, sign_pkey)
|
|
if not parsed_sign_pkey then
|
|
return false, "failed to parse sign PEM priv key: " .. err
|
|
end
|
|
|
|
ok, err = ssl.set_gm_priv_key(parsed_enc_pkey, parsed_sign_pkey)
|
|
if not ok then
|
|
return false, "failed to set PEM priv key: " .. err
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
local original_set_cert_and_key
|
|
local function set_cert_and_key(sni, value)
|
|
if value.gm then
|
|
-- process as GM certificate
|
|
-- For GM dual certificate, the `cert` and `key` will be encryption cert/key.
|
|
-- The first item in `certs` and `keys` will be sign cert/key.
|
|
local enc_cert = value.cert
|
|
local enc_pkey = value.key
|
|
local sign_cert = value.certs[1]
|
|
local sign_pkey = value.keys[1]
|
|
return set_pem_ssl_key(sni, enc_cert, enc_pkey, sign_cert, sign_pkey)
|
|
end
|
|
return original_set_cert_and_key(sni, value)
|
|
end
|
|
|
|
|
|
local original_check_ssl_conf
|
|
local function check_ssl_conf(in_dp, conf)
|
|
if conf.gm then
|
|
-- process as GM certificate
|
|
-- For GM dual certificate, the `cert` and `key` will be encryption cert/key.
|
|
-- The first item in `certs` and `keys` will be sign cert/key.
|
|
local ok, err = original_check_ssl_conf(in_dp, conf)
|
|
-- check cert/key first in the original method
|
|
if not ok then
|
|
return nil, err
|
|
end
|
|
|
|
-- Currently, APISIX doesn't check the cert type (ECDSA / RSA). So we skip the
|
|
-- check for now in this plugin.
|
|
local num_certs = conf.certs and #conf.certs or 0
|
|
local num_keys = conf.keys and #conf.keys or 0
|
|
if num_certs ~= 1 or num_keys ~= 1 then
|
|
return nil, "sign cert/key are required"
|
|
end
|
|
return true
|
|
end
|
|
return original_check_ssl_conf(in_dp, conf)
|
|
end
|
|
|
|
|
|
-- module define
|
|
local plugin_name = "gm"
|
|
|
|
-- plugin schema
|
|
local plugin_schema = {
|
|
type = "object",
|
|
properties = {
|
|
},
|
|
}
|
|
|
|
local _M = {
|
|
version = 0.1, -- plugin version
|
|
priority = -43,
|
|
name = plugin_name, -- plugin name
|
|
schema = plugin_schema, -- plugin schema
|
|
}
|
|
|
|
|
|
function _M.init()
|
|
if not pcall(function () return C.Tongsuo_version_num end) then
|
|
error("need to build Tongsuo (https://github.com/Tongsuo-Project/Tongsuo) " ..
|
|
"into the APISIX-Runtime")
|
|
end
|
|
|
|
ssl.enable_ntls()
|
|
original_set_cert_and_key = radixtree_sni.set_cert_and_key
|
|
radixtree_sni.set_cert_and_key = set_cert_and_key
|
|
original_check_ssl_conf = apisix_ssl.check_ssl_conf
|
|
apisix_ssl.check_ssl_conf = check_ssl_conf
|
|
|
|
if core.schema.ssl.properties.gm ~= nil then
|
|
error("Field 'gm' is occupied")
|
|
end
|
|
|
|
-- inject a mark to distinguish GM certificate
|
|
core.schema.ssl.properties.gm = {
|
|
type = "boolean"
|
|
}
|
|
end
|
|
|
|
|
|
function _M.destroy()
|
|
ssl.disable_ntls()
|
|
radixtree_sni.set_cert_and_key = original_set_cert_and_key
|
|
apisix_ssl.check_ssl_conf = original_check_ssl_conf
|
|
core.schema.ssl.properties.gm = nil
|
|
end
|
|
|
|
-- module interface for schema check
|
|
-- @param `conf` user defined conf data
|
|
-- @param `schema_type` defined in `apisix/core/schema.lua`
|
|
-- @return <boolean>
|
|
function _M.check_schema(conf, schema_type)
|
|
return core.schema.check(plugin_schema, conf)
|
|
end
|
|
|
|
|
|
return _M
|