Skip to content

feat(plugin): add XML and SOAP request signing plugins - #14002

Draft
keremoge wants to merge 1 commit into
apache:masterfrom
keremoge:xml_and_soap_plugin
Draft

keremoge wants to merge 1 commit into
apache:masterfrom
keremoge:xml_and_soap_plugin

Conversation

@keremoge

@keremoge keremoge commented Oct 2, 2026

Copy link
Copy Markdown

Description

Some upstream XML and SOAP services require signed request bodies. This PR adds APISIX plugins to apply those signatures before proxying requests.

  • Add xml-signer for enveloped XML Digital Signatures.
  • Add soap-signer for WS-Security signatures on SOAP 1.1 and SOAP 1.2 requests.
  • Share signing, credential, and algorithm utilities between the plugins.
  • Add English and Chinese documentation, plugin configuration, and tests.

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect the changes made in this PR

@keremoge
keremoge marked this pull request as ready for review October 2, 2026 12:43
Copilot AI balanced review requested due to automatic review settings October 2, 2026 12:43
@keremoge
keremoge marked this pull request as draft October 2, 2026 12:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

XML parsing can expose request data and bypass DTD checks, while SOAP handling has signature-ambiguity risks.

Review effort: Balanced
Findings: 2 High severity · 3 Medium severity

Open (5)
What changed in this PR

Adds XMLDSig and WS-Security request-signing plugins with shared XML, credential, algorithm, and request-processing utilities.

Changes:

  • Implements XML and SOAP signing plugins.
  • Adds installation, registration, schemas, and configuration.
  • Adds bilingual documentation and signing tests.
File Description
apisix/​plugins/​xml-signer.lua Defines the XML signer plugin.
apisix/​plugins/​xml-signer/​signer.lua Implements enveloped XML signatures.
apisix/​plugins/​soap-signer.lua Defines the SOAP signer plugin.
apisix/​plugins/​soap-signer/​signer.lua Implements WS-Security signatures.
apisix/​plugins/​signing/​xml.lua Provides libxml2 utilities.
apisix/​plugins/​signing/​request.lua Handles request filtering and rewriting.
apisix/​plugins/​signing/​credentials.lua Loads and caches signing credentials.
apisix/​plugins/​signing/​algorithms.lua Defines supported algorithms.
apisix/​cli/​config.lua Registers both plugins.
conf/​config.yaml.example Adds default plugin configuration.
Makefile Installs new Lua modules.
t/​plugin/​xml-signer.t Tests XML signing behavior.
t/​plugin/​soap-signer.t Tests SOAP signing behavior.
docs/​en/​latest/​plugins/​xml-signer.md Documents XML signing.
docs/​en/​latest/​plugins/​soap-signer.md Documents SOAP signing.
docs/​zh/​latest/​plugins/​xml-signer.md Adds Chinese XML documentation.
docs/​zh/​latest/​plugins/​soap-signer.md Adds Chinese SOAP documentation.
docs/​en/​latest/​config.json Adds English navigation entries.
docs/​zh/​latest/​config.json Adds Chinese navigation entries.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +151 to +153
local upper = value:upper()
if upper:find("<!DOCTYPE", 1, true) or upper:find("<!ENTITY", 1, true) then
return nil, "DTD and entity declarations are not allowed"
Comment on lines +70 to +73
local body = xml.find_child(root, soap_namespace, "Body")
if not body then
return nil, "invalid_soap", "SOAP Body is required"
end
Comment on lines +70 to +72
if conf.signature.algorithm == "rsa-sha1" then
core.log.warn(plugin_name, " is using legacy SHA-1 cryptography")
end
return nil, "DTD and entity declarations are not allowed"
end

local doc = C.xmlReadMemory(value, #value, "document.xml", nil, XML_PARSE_NONET)
Comment on lines +297 to +300
envelope.security = xml.find_child(envelope.header, WSSE, "Security")
if not envelope.security then
envelope.security = xml.new_child(envelope.header, envelope.wsse_ns, "Security")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants