Wiring up encryption metadata to the DBPA remote and local agents.#167
Conversation
avalerio-tkd
commented
Nov 19, 2025
- Update API server to return encryption metadata in the response.
- Populate server version as encryption metadata during Encryption and check it back during Decryption.
- Updated unitests.
- Fixed hidden error when parsing empty Json strings.
- Update API server to return encryption metadata in the response. - Populate server version as encryption metadata during Encryption and check it back during Decryption. - Updated unitests. - Fixed hidden error when parsing empty Json strings.
| user_id_, | ||
| app_context_ | ||
| app_context_, | ||
| {} |
There was a problem hiding this comment.
add // encryption_metadata comment
| private: | ||
| std::vector<uint8_t> ciphertext_; | ||
| bool success_; | ||
| std::map<std::string, std::string> encryption_metadata_; |
There was a problem hiding this comment.
Not sure if it should be in this header file or in another, but can you add a comment with an example of what may be contained in here?
There was a problem hiding this comment.
Added comments on the dbpa_interface.h file.
| auto it = encryption_metadata_.find(DBPS_VERSION_KEY); | ||
| if (it == encryption_metadata_.end()) { | ||
| std::cerr << "ERROR: EncryptionSequencer - encryption_metadata must contain key '" << DBPS_VERSION_KEY << "'" << std::endl; | ||
| // ++++ remove the hard error before merging ++++ |
There was a problem hiding this comment.
Why do you want to remove this?
There was a problem hiding this comment.
This was to prevent breaking the Arrow flow until we know for sure the metadata is saved on the Parquet files correctly. But this is probably not needed since that was tested already on Arrow and this is now tested on DPBA flow, so will merge with it.
| "test_user", // user_id | ||
| "{}" // application_context | ||
| "{}", // application_context | ||
| {} // encryption_metadata |
There was a problem hiding this comment.
Not sure I could see a test where you verify that the sequencer stops if there's a mismatch in the expected encryption metadata?
There was a problem hiding this comment.
Thanks for catching the test gap. Added.
- Updated dbpa_remote_testapp to use the new version checking.
argmarco-tkd
left a comment
There was a problem hiding this comment.
Thanks for this. Overall LGTM, but left a few comments around
| user_id_, | ||
| app_context_ | ||
| app_context_, | ||
| {} |
| const auto& response_attrs = response_->GetResponseAttributes(); | ||
| if (!response_attrs.encryption_metadata_.empty()) { | ||
| cached_encryption_metadata_ = response_attrs.encryption_metadata_; | ||
| } else { | ||
| cached_encryption_metadata_ = std::nullopt; | ||
| } |
There was a problem hiding this comment.
let's document what's going on here - it's a bit hard to grasp
There was a problem hiding this comment.
Done. You can let me know if the comment is sufficient and I can expand more if needed.
There was a problem hiding this comment.
it's a clearer, thanks - but the whole concept of 'cached metadata' is a bit confusing. maybe let's add a short note on that? (in particular, why is it 'cached' ?)
There was a problem hiding this comment.
cached was probably a bad choice, so changed the variable names to parsed. I think that captures better the usage.
There was a problem hiding this comment.
thank you! it's much clearer now.
| // The caching of this is possible because the API response `response_` doesn't change after construction. | ||
| mutable std::string cached_error_message_; | ||
| mutable std::map<std::string, std::string> cached_error_fields_; | ||
| mutable std::optional<std::map<std::string, std::string>> cached_encryption_metadata_; |
There was a problem hiding this comment.
let's add a note for the future, where we state that this is cacheable only because the metadata is identical across requests (but that may change)
There was a problem hiding this comment.
Actually, this is the RemoteEncryptionResult, not the RemoteDPBA. A new instance is returned on each call to RemoteDBPA.Encrypt().
This is cached separately on each RemoteEncryptionResult instance, to avoid parsing the Json with every call to encryption_metadata(). It isn't statically cached for the class.
But let me know if something is unclear, and we can discuss.
| using namespace dbps::enum_utils; | ||
|
|
||
| namespace { | ||
| constexpr const char* DBPS_VERSION_KEY = "dbps_version"; |
There was a problem hiding this comment.
We should discuss this property name. Let's create a task to discuss the naming (or discuss offline when you have a chance). I.e. DBPS is technically 'server' related, but we have a local agent. Maybe dbpa_agent_version or similar is more appropriate.
There was a problem hiding this comment.
Renamed it to dbpa_agent_version as suggested.
| std::cerr << "ERROR: EncryptionSequencer - encryption_metadata['" << DBPS_VERSION_KEY << "'] must start with '" | ||
| << DBPS_VERSION_VALUE << "', but got '" << it->second << "'" << std::endl; |
There was a problem hiding this comment.
The 'must start' terminology may be confusing. Can we just say "must match" ?
- Updating devel branch
avalerio-tkd
left a comment
There was a problem hiding this comment.
Thanks for the reviews @argmarco-tkd @sofia-tekdatum . Could you PTAL?
| user_id_, | ||
| app_context_ | ||
| app_context_, | ||
| {} |
| private: | ||
| std::vector<uint8_t> ciphertext_; | ||
| bool success_; | ||
| std::map<std::string, std::string> encryption_metadata_; |
There was a problem hiding this comment.
Added comments on the dbpa_interface.h file.
| auto it = encryption_metadata_.find(DBPS_VERSION_KEY); | ||
| if (it == encryption_metadata_.end()) { | ||
| std::cerr << "ERROR: EncryptionSequencer - encryption_metadata must contain key '" << DBPS_VERSION_KEY << "'" << std::endl; | ||
| // ++++ remove the hard error before merging ++++ |
There was a problem hiding this comment.
This was to prevent breaking the Arrow flow until we know for sure the metadata is saved on the Parquet files correctly. But this is probably not needed since that was tested already on Arrow and this is now tested on DPBA flow, so will merge with it.
| "test_user", // user_id | ||
| "{}" // application_context | ||
| "{}", // application_context | ||
| {} // encryption_metadata |
There was a problem hiding this comment.
Thanks for catching the test gap. Added.
| // The caching of this is possible because the API response `response_` doesn't change after construction. | ||
| mutable std::string cached_error_message_; | ||
| mutable std::map<std::string, std::string> cached_error_fields_; | ||
| mutable std::optional<std::map<std::string, std::string>> cached_encryption_metadata_; |
There was a problem hiding this comment.
Actually, this is the RemoteEncryptionResult, not the RemoteDPBA. A new instance is returned on each call to RemoteDBPA.Encrypt().
This is cached separately on each RemoteEncryptionResult instance, to avoid parsing the Json with every call to encryption_metadata(). It isn't statically cached for the class.
But let me know if something is unclear, and we can discuss.
| using namespace dbps::enum_utils; | ||
|
|
||
| namespace { | ||
| constexpr const char* DBPS_VERSION_KEY = "dbps_version"; |
There was a problem hiding this comment.
Renamed it to dbpa_agent_version as suggested.
| std::cerr << "ERROR: EncryptionSequencer - encryption_metadata['" << DBPS_VERSION_KEY << "'] must start with '" | ||
| << DBPS_VERSION_VALUE << "', but got '" << it->second << "'" << std::endl; |
argmarco-tkd
left a comment
There was a problem hiding this comment.
Thanks for the changes. Left a couple of comments - in particular, I think we need a bit of clarification/improved description on the 'cache' for metadata.
| using namespace dbps::external; | ||
|
|
||
| namespace { | ||
| const std::map<std::string, std::string> VALID_ENCRYPTION_METADATA = {{"dbps_agent_version", "v0.01"}}; |
There was a problem hiding this comment.
nit: "Valid" hints that there is a counterpart, "invalid". Consider a different name. (maybe just a plain ENCRYPTION_METADATA or DBPS_ENCRYPTION_METADATA?)
| const auto& response_attrs = response_->GetResponseAttributes(); | ||
| if (!response_attrs.encryption_metadata_.empty()) { | ||
| cached_encryption_metadata_ = response_attrs.encryption_metadata_; | ||
| } else { | ||
| cached_encryption_metadata_ = std::nullopt; | ||
| } |
There was a problem hiding this comment.
it's a clearer, thanks - but the whole concept of 'cached metadata' is a bit confusing. maybe let's add a short note on that? (in particular, why is it 'cached' ?)
…tionResult for clarity. - Added DBPS_ENCRYPTION_METADATA constant to dbpa_local_test.cpp for clarity.
|
@argmarco-tkd @sofia-tekdatum could you PTAL? I renamed the |
argmarco-tkd
left a comment
There was a problem hiding this comment.
LGTM - thanks for all the changes!