matebenyovszky opened a new issue, #45787:
URL: https://github.com/apache/superset/issues/45787

   ### Bug description
   
   Extension Storage values written with `encrypt: true` can never be read 
back. Writes succeed, but every read of that key fails. The DAO logs `Failed to 
decrypt extension storage value ... possible key rotation issue` and returns 
`None`.
   
   `_enc_type()` in `superset/extensions/storage/persistent_dao.py` wraps the 
payload in `EncryptedType(LargeBinary, ...)`. The sqlalchemy_utils engines only 
encrypt text:
   
   - **On write,** the engine receives `bytes` and encrypts `repr(value)`, i.e. 
the string `"b'...'"`.
   - **On read,** `process_result_value()` rebuilds the value with 
`LargeBinary.python_type(decrypted)`, i.e. `bytes(str)`. That raises 
`TypeError: string argument without an encoding`.
   
   This happens with both `SQLALCHEMY_ENCRYPTED_FIELD_ENGINE = "aes"` and 
`"aes-gcm"`, and for both user-scoped and shared rows. The existing unit tests 
mock `_enc_type`, so no test round-trips a real ciphertext.
   
   Minimal reproduction with only sqlalchemy-utils 0.43.0 (the version Superset 
pins):
   
   ```python
   from sqlalchemy import LargeBinary
   from sqlalchemy_utils import EncryptedType
   from sqlalchemy_utils.types.encrypted.encrypted_type import AesGcmEngine
   
   t = EncryptedType(LargeBinary, key="secret", engine=AesGcmEngine)
   stored = t.process_bind_param(b'{"a": 1}', None)
   t.engine.decrypt(stored.decode())     # 'b\'{"a": 1}\''
   t.process_result_value(stored, None)  # TypeError: string argument without 
an encoding
   ```
   
   Found while moving an extension (conversation history in the persistent 
tier) to 7.0.0rc2. We now store the value unencrypted as a workaround.
   
   ### Screenshots/recordings
   
   _No response_
   
   ### Superset version
   
   master / latest-dev (also 7.0.0rc1 and 7.0.0rc2)
   
   ### Python version
   
   3.11
   
   ### Node version
   
   I don't know
   
   ### Browser
   
   Not applicable
   
   ### Additional context
   
   A related problem, not covered by the fix I'm proposing: `superset 
re-encrypt-secrets` includes `extension_storage` through 
`CONDITIONAL_ENCRYPTED_TABLES`. It decrypts those rows with the same 
`EncryptedType(LargeBinary)` and with the plain `SECRET_KEY`. User-scoped rows, 
however, are encrypted with a key derived from `SECRET_KEY` and the user ID. So 
once a deployment holds an encrypted user-scoped row, the migrator cannot 
decrypt it, counts a failure and rolls back the whole run. That probably 
deserves its own change, since the migrator would need to know about the 
per-user key derivation.
   
   ### Checklist
   
   - [x] I have searched Superset docs and Slack and didn't find a solution to 
my problem.
   - [x] I have searched the GitHub issue tracker and didn't find a similar bug 
report.
   - [x] I have checked Superset's logs for errors and if I found a relevant 
Python stacktrace, I included it here as text in the "additional context" 
section.
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to