AlinsRan opened a new pull request, #14162:
URL: https://github.com/apache/apisix/pull/14162

   ### Description
   
   Whether a stored plugin value is ciphertext is decided only by the reader's 
own `encrypt_fields`. After upgrading to a release that adds a field to an 
existing plugin's `encrypt_fields`, every resource re-saved there stores that 
field encrypted; rolling back to the previous release then uses the ciphertext 
as the value (e.g. Redis authentication fails) until each resource is re-saved. 
Turning off `enable_encrypt_fields` does the same to existing ciphertext.
   
   This PR adds a self-describing marker so that every release that recognizes 
it decrypts the value regardless of its own list.
   
   #### Format
   
   `$ENC$v1$` followed by the existing ciphertext (same cipher, encoding and 
`data_encryption.keyring`).
   
   #### Reader
   
   - `plugin_checker` (routes, services, plugin configs, consumers, 
credentials, consumer groups, global rules), `check_plugin_metadata` and 
`stream_plugin_checker` decrypt every string value starting with `$ENC$v1$` 
before validation, independent of `encrypt_fields` and of 
`enable_encrypt_fields`.
   - A marked value that fails to decrypt makes the resource invalid (same 
handling as any other invalid resource). Decryption of a resource is 
all-or-nothing, so the "failed to check item data" log never carries plaintexts 
decrypted before the failing value.
   - Positions decrypted through the marker skip the `encrypt_fields` logic, so 
a plaintext that happens to be valid ciphertext is not decrypted twice. 
Unmarked values keep the current `encrypt_fields` behaviour.
   - Marked values are decrypted in place even with `enable_encrypt_fields: 
false`, so the info logs that used to dump a whole conf now print only ids or 
plugin names: the stream plugin schema check, `merge_service_route`, 
`merge_service_stream_route`, `merge_consumer_route`, `matched route` (HTTP and 
stream), `insert uri route`, `filter service`, and the plugin metadata lookup 
of the logger utilities (plugin name and whether metadata was found).
   - Outside the checkers, plugin confs are decrypted in the Admin API: read 
responses (now including the plugin metadata list) return marked values as 
plaintext, and PATCH decrypts the stored conf before merging; every marked 
position the PATCH does not modify keeps its stored value byte for byte, 
whatever `write_marker` is, and only modified positions follow `write_marker`. 
If a stored marked value cannot be decrypted, the read returns it as stored 
(and logs an error) and PATCH fails with 400.
   - The yaml/json config providers use the same checkers, so marked values in 
a standalone configuration are decrypted with the local keyring too.
   
   #### Writer
   
   New option `apisix.data_encryption.write_marker` (default `false`, effective 
only with `enable_encrypt_fields: true`). When on, the Admin API writes every 
plugin conf and plugin metadata value it encrypts today in marked form. It does 
not change which fields are encrypted; SSL keys, upstream TLS keys and 
`/secrets` are unchanged. Enable it only once every node runs a release that 
recognizes the marker and you will not roll back below that release.
   
   #### Input validation
   
   The Admin API rejects with 400 any user-supplied string starting with 
`$ENC$` (the whole reserved prefix, not only `v1`) in plugin confs and plugin 
metadata, including PATCH bodies written under `plugins/...`, whatever 
`write_marker` is. Values already stored and merged on PATCH are not user input 
and are not checked.
   
   ### Checklist
   
   - [x] I have explained the need for this PR and the problem it solves
   - [x] I have explained the changes or the new features added to this PR
   - [x] I have added tests corresponding to this change
   - [x] I have updated the documentation to reflect this change
   - [x] I have verified that this change is backward compatible (If not, 
please discuss on the [APISIX mailing 
list](https://github.com/apache/apisix/tree/master#community) first)
   
   Tests: `t/node/data_encrypt_marker.t` writes resources straight to etcd and 
covers decryption in routes, services, global rules, consumers, plugin metadata 
and stream routes, failures, double-decryption avoidance and 
`enable_encrypt_fields: false`. `t/admin/data_encrypt_marker.t` covers the 
writer on and off, `write_marker` without `enable_encrypt_fields`, Admin API 
reads and PATCH, and the rejection.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to