Skip to content

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

Open
keremoge wants to merge 9 commits into
apache:masterfrom
keremoge:xml_and_soap_plugin
Open

keremoge wants to merge 9 commits 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 thread apisix/plugins/signing/xml.lua Outdated
Comment thread apisix/plugins/soap-signer/signer.lua Outdated
Comment thread apisix/plugins/signing/request.lua
Comment thread apisix/plugins/signing/xml.lua
Comment thread apisix/plugins/soap-signer/signer.lua Outdated
Copilot AI and others added 3 commits October 5, 2026 07:53
Co-authored-by: keremoge <4692074+keremoge@users.noreply.github.com>

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

🔵 Needs a closer look

SOAP handling can accept invalid Header ordering and emit duplicate WS-Security Timestamp elements.

Review effort: Balanced
Findings: None

Resolved since last review (5)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Reject SOAP envelopes with Header after Body

apisix/​plugins/​soap-signer/​signer.lua:83

This accepts a SOAP Header that appears after the Body. SOAP 1.1 and 1.2 require the optional Header to precede the Body, so the plugin can report success while forwarding an invalid envelope that conforming upstreams reject. Reject this ordering during the existing envelope validation.

Medium severity Prevent duplicate wsu:Timestamp in WS-Security

apisix/​plugins/​soap-signer/​signer.lua:324

Because an existing wsse:Security block is reused, this unconditional append creates a second wsu:Timestamp when the incoming block already contains one. WS-Security profiles allow at most one Timestamp per Security header, and only the newly generated one is referenced by this signature, so common UsernameToken/Timestamp requests become invalid or ambiguous. Reject or replace an existing direct Timestamp before adding this one, or create a separate appropriately targeted Security block.

Harden XML/SOAP signing plugins: DTD detection, Body/Header validation, namespaces, body-read errors

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

🔵 Needs a closer look

XML diagnostics, WS-Security role handling, and per-request warning logging remain unresolved.

Review effort: Balanced
Findings: None

Previously missed (1)

In code that hasn't changed since last review

Medium severity Validate WS-Security role before selecting Security header

apisix/​plugins/​soap-signer/​signer.lua:311

This still reuses the first wsse:Security element without checking its SOAP 1.1 actor or SOAP 1.2 role, or whether multiple Security elements make selection ambiguous. If the selected block targets another role (including SOAP 1.2 role/none), the generated signature is placed in a header the intended upstream receiver must ignore. Select only an unambiguous untargeted/ultimate-receiver block, or create/reject according to an explicit role policy.

@keremoge
keremoge marked this pull request as ready for review October 5, 2026 09:51

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

Parser logging can expose request bodies, SHA-1 warning logging is unbounded, and a SOAP schema test has an incorrect expected response.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Normalize configured media types before case-insensitive comparison

apisix/​plugins/​signing/​request.lua:64

The request media type is lowercased, but configured media types are compared verbatim. Since media types are case-insensitive, a valid configuration such as Application/XML will reject an application/xml request with 415. Normalize each configured value before comparing it.

Comment thread t/plugin/soap-signer.t
@keremoge
keremoge marked this pull request as draft October 6, 2026 05:42
…ts in the expected test output'

add missing test parameters

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@keremoge
keremoge marked this pull request as ready for review October 6, 2026 06:00
@keremoge
keremoge requested a balanced review from Copilot October 6, 2026 12:19

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 diagnostics can expose request contents, and rewritten bodies retain invalid charset and integrity metadata.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Stale body integrity headers survive body replacement

apisix/​plugins/​signing/​request.lua:92

Replacing the body also invalidates end-to-end body integrity headers, but only length and transfer encoding are updated here. Requests carrying Content-MD5, Digest, Content-Digest, or Repr-Digest will reach the upstream with hashes for the pre-signing body and can be rejected or misrepresented as integrity-checked. Recompute these headers, remove them, or reject such requests according to an explicit policy.

Medium severity Content-Type charset remains inconsistent with UTF-8 serialization

apisix/​plugins/​signing/​request.lua:92

The signer serializes every successful result as UTF-8, but this rewrite preserves the original Content-Type parameters. A valid request such as text/xml; charset=iso-8859-1 is therefore forwarded with UTF-8 bytes still advertised as ISO-8859-1, so the upstream can misdecode or reject the signed document. Rewrite the charset to UTF-8 while preserving parameters such as SOAP action, or reject non-UTF-8 charset declarations before signing.

Comment thread apisix/plugins/soap-signer/signer.lua Outdated
@keremoge
keremoge marked this pull request as draft October 6, 2026 12:29

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

🔵 Needs a closer look

XML parsing, identifier validation, media-type handling, and per-request logging contain unresolved issues.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Trim media type whitespace before allowlist comparison

apisix/​plugins/​signing/​request.lua:49

The captured media type retains whitespace before the first semicolon, so a valid header such as Content-Type: application/xml ; charset=utf-8 normalizes to application/xml and is incorrectly rejected with 415. Trim trailing optional whitespace from the captured type before comparing it with the configured allowlist.

Medium severity Validate client-supplied wsu:Id values before signing

apisix/​plugins/​soap-signer/​signer.lua:149

Any non-empty client-supplied wsu:Id is reused without validating the XML ID lexical form. For example, wsu:Id="a b" produces Reference URI="#a b", which is not a valid same-document ID reference and is rejected or resolved inconsistently by WS-Security verifiers. Validate existing values as NCNames and reject malformed SOAP before signing (or safely replace them while accounting for existing references).

@keremoge
keremoge marked this pull request as ready for review October 6, 2026 12:53
@keremoge

keremoge commented Oct 6, 2026

Copy link
Copy Markdown
Author

work completed, needs review

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.

3 participants