Skip to content

feat: enhance encrypt_fields to support nested structures#13192

Merged
Baoyuantop merged 3 commits intoapache:masterfrom
nic-6443:feat/encrypt-fields-nested
Apr 10, 2026
Merged

feat: enhance encrypt_fields to support nested structures#13192
Baoyuantop merged 3 commits intoapache:masterfrom
nic-6443:feat/encrypt-fields-nested

Conversation

@nic-6443
Copy link
Copy Markdown
Member

@nic-6443 nic-6443 commented Apr 9, 2026

Description

Enhance the encrypt_fields mechanism in plugin.lua to support nested and complex field structures. The current implementation only handles flat keys and 2-level dotted paths (e.g., sasl.password).

What's changed

Core: Rewrite encrypt/decrypt traversal logic (apisix/plugin.lua)

Replace the flat/2-level if/elseif logic with a recursive process_encrypt_field() helper that supports:

  1. Arbitrary depth dotted paths — e.g., auth.gcp.service_account_json traverses 3 levels deep
  2. Array traversal at intermediate nodes — when an intermediate value is an array (e.g., instances), iterate each element and continue recursion
  3. Leaf type dispatch:
    • string → encrypt/decrypt directly
    • array of strings → iterate and encrypt/decrypt each element
    • map of strings → iterate and encrypt/decrypt each value

Uses core.table.isarray() for reliable array vs map detection.

Fix: Decrypt before schema validation in plugin_checker

Reorder plugin_checker to run decrypt_conf before check_schema, matching the gateway's approach. This is necessary because plugins like ai-proxy perform content-level validation (e.g., parsing service_account_json as JSON) — without decrypting first, encrypted values fail these checks during config sync.

Plugin schema updates:

Plugin encrypt_fields added
ai-proxy auth.header, auth.query, auth.gcp.service_account_json
ai-proxy-multi instances.auth.header, instances.auth.query, instances.auth.gcp.service_account_json
ai-rag embeddings_provider.azure_openai.api_key, vector_search_provider.azure_ai_search.api_key

Backward compatibility

  • Flat keys (e.g., password) continue to work unchanged
  • Existing 2-level dotted paths (e.g., sasl.password, auth.password) continue to work
  • Regression tests included for both cases

Tests

Added t/node/data_encrypt3.t with 7 test cases covering:

  • Map of strings encryption (ai-proxy auth.header, auth.query)
  • 3-level nested string (ai-proxy auth.gcp.service_account_json, ai-rag API keys)
  • Array with nested encrypted fields (ai-proxy-multi instances[].auth.header)
  • Nil/missing field handling
  • Flat key regression (basic-auth password)
  • 2-level dotted path regression (kafka-proxy sasl.password)
  • Array of strings leaf encryption via process_encrypt_field

Enhance the encrypt_fields mechanism to support:
- Arbitrary depth dotted paths (e.g., a.b.c.d)
- Array traversal at intermediate nodes (e.g., instances[].auth.header)
- Leaf type dispatch: string, array of strings, map of strings

Add encrypt_fields to:
- ai-proxy: auth.header, auth.query, auth.gcp.service_account_json
- ai-proxy-multi: instances.auth.header, instances.auth.query,
  instances.auth.gcp.service_account_json
- ai-rag: embeddings_provider.azure_openai.api_key,
  vector_search_provider.azure_ai_search.api_key
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. enhancement New feature or request labels Apr 9, 2026
nic-6443 added 2 commits April 9, 2026 18:13
Add op_name parameter to process_encrypt_field for backward-compatible
log messages ('failed to decrypt...' / 'failed to encrypt...' instead
of generic 'failed to encrypt/decrypt...').
Reorder plugin_checker to run decrypt_conf before check_schema, matching
the gateway's approach. This fixes content-level validation failures
(e.g. ai-proxy's service_account_json JSON parsing) when fields are
encrypted — the encrypted values are now decrypted back to plaintext
before validation runs.
@nic-6443 nic-6443 requested a review from Copilot April 9, 2026 12:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Enhances APISIX data encryption support for plugin encrypt_fields by enabling recursive traversal of nested objects/arrays and ensuring decryption occurs before schema validation for content-level checks.

Changes:

  • Add recursive process_encrypt_field() traversal for arbitrarily nested dotted paths and array/map leaf handling.
  • Reorder plugin_checker to decrypt plugin configs before schema validation.
  • Extend plugin schemas to declare additional encrypt_fields, and add a new test suite covering nested/enhanced cases.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
apisix/plugin.lua Replaces flat/2-level encryption logic with recursive traversal; changes validation flow to decrypt before schema checks.
apisix/plugins/ai-proxy/schema.lua Adds encrypt_fields for nested auth header/query/GCP JSON fields (including multi-instance paths).
apisix/plugins/ai-rag.lua Adds encrypt_fields for nested Azure API keys.
t/node/data_encrypt3.t Adds integration tests covering nested paths, maps, arrays, regressions, and a direct helper test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Baoyuantop Baoyuantop merged commit 9a2380c into apache:master Apr 10, 2026
34 of 35 checks passed
@nic-6443 nic-6443 deleted the feat/encrypt-fields-nested branch April 10, 2026 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants