Skip to content

External file decryptor bindings#57

Merged
sofia-tekdatum merged 13 commits into
dev_phase2from
external_file_decryptor_bindings
Aug 20, 2025
Merged

External file decryptor bindings#57
sofia-tekdatum merged 13 commits into
dev_phase2from
external_file_decryptor_bindings

Conversation

@cristekdatum

@cristekdatum cristekdatum commented Aug 13, 2025

Copy link
Copy Markdown
Collaborator

Adding code for the [31] and support the external_file_decryption_properties

@github-actions

Copy link
Copy Markdown

Thanks for opening a pull request!

If this is not a minor PR. Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose

Opening GitHub issues ahead of time contributes to the Openness of the Apache Arrow project.

Then could you also rename the pull request title in the following format?

GH-${GITHUB_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}

or

MINOR: [${COMPONENT}] ${SUMMARY}

See also:

@cristekdatum

Copy link
Copy Markdown
Collaborator Author

Hey @sofia-tekdatum following the pattern of file_decryption_properties I created a new SafeGetExternalFileDecryptionProperties which requires same methods at the cc side in order to fix this problem

[ 89%] Building CXX object CMakeFiles/_parquet_encryption.dir/_parquet_encryption.cpp.o
/Users/cristianguillenmendez/Documents/dev-phase2/python/build/temp.macosx-15.4-arm64-cpython-310/_parquet_encryption.cpp:22521:77: error: no member named 'SafeGetExternalFileDecryptionProperties' in 'arrow::py::parquet::encryption::PyCryptoFactory'; did you mean 'GetExternalFileDecryptionProperties'?
        __pyx_v_c_file_decryption_properties = __pyx_v_self->factory.get()->SafeGetExternalFileDecryptionProperties((*__pyx_t_4.get()), __pyx_v_c_decryption_config);
                                                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                            GetExternalFileDecryptionProperties
/Users/cristianguillenmendez/Documents/dev-phase2/cpp/build/install/include/parquet/encryption/crypto_factory.h:205:53: note: 'GetExternalFileDecryptionProperties' declared here
  std::shared_ptr<ExternalFileDecryptionProperties> GetExternalFileDecryptionProperties(
                                                    ^
1 error generated.

@sofia-tekdatum sofia-tekdatum left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@cristekdatum You forgot to change the ParquetReader open method in _parquet.pyx

Please add.

Comment thread python/pyarrow/src/arrow/python/parquet_encryption.cc Outdated
Comment thread python/pyarrow/src/arrow/python/parquet_encryption.h Outdated
Comment thread python/pyarrow/_parquet.pxd Outdated
Comment thread python/pyarrow/_parquet.pxd Outdated
Comment thread python/pyarrow/_parquet_encryption.pxd Outdated
Comment thread python/pyarrow/_parquet_encryption.pyx Outdated
Comment thread python/pyarrow/_parquet_encryption.pyx Outdated
Comment thread python/pyarrow/tests/parquet/test_external_encryption.py Outdated

@sofia-tekdatum sofia-tekdatum left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Careful with copy/paste errors, they may have made you spend a lot of time debugging.

Comment thread python/pyarrow/_parquet.pyx Outdated
Comment thread python/pyarrow/tests/parquet/test_external_encryption.py Outdated
Comment thread python/pyarrow/tests/parquet/test_external_encryption.py Outdated
@sofia-tekdatum

Copy link
Copy Markdown
Collaborator

I have updated the bindings code so that it forwards its property setter to the super class.

I also fixed the test, which was failing because the configs were not set up properly and were disorganized. I rewrote the fixtures to match the config settings we have in the base_app, verified everything passes.

@cristekdatum @avalerio-tkd @argmarco-tkd PTAL for final approval and merging.

@sofia-tekdatum

Copy link
Copy Markdown
Collaborator

Also, verified the values make it successfully to the C++ side by running scripts/base_app.py and printing out values on the crypto_factory.cc code.

Obviously that's not submitted, but it's the way to verify the code that originates in python makes it through to C++.

@avalerio-tkd avalerio-tkd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. Just a few comments. I tried following as much as possible. Thanks very much for this.
If the comments are not relevant or covered, feel free to merge.

super().__init__(cache_lifetime=cache_lifetime)
# Initialize the pointer first so the get/set forwards work.
self.external_configuration.reset(new CExternalDecryptionConfiguration())
super().__init__(cache_lifetime=cache_lifetime)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This change of order is a bit scary. Why is there a dependency on the subclass before calling the init of the superclass? Primarily for my understanding, but let's improve the comment.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Updated comment. Because the super class constructor will invoke the setters that are overridden below, so they need the pointer to be ready, otherwise we get a null crash.

cdef shared_ptr[CExternalDecryptionConfiguration] external_configuration
cdef inline shared_ptr[CExternalDecryptionConfiguration] unwrap_external(self) nogil

cdef shared_ptr[CCryptoFactory] pyarrow_unwrap_cryptofactory(object crypto_factory) except *

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm assuming moving the definitions here is just for readability and nothing functional, right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correct.

CFileEncryptionProperties,
CExternalFileEncryptionProperties,
CFileDecryptionProperties,
CExternalFileDecryptionProperties,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For my understanding, are the pxd modules compiled (so the change in params cause a compilation error if done wrong) or are these interpreted? If the latter, I'm assuming this is abundantly tested by unittests, right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

They are compiled. If they're not included here, we get compilation errors.

if decryption_config is None:
c_decryption_config = CExternalDecryptionConfiguration()
else:
c_decryption_config = deref(decryption_config.unwrap_external().get())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I lost a little track around here. If not can you add a comment at the if-else level on what this is doing.
If this is common pattern / boilerplate, please disregard.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Boilerplate check that we have even an empty decryption config to work with, in case none was sent.

assert read_data_table.num_rows == data_table.num_rows
assert read_data_table.num_columns == data_table.num_columns
assert read_data_table.schema.equals(data_table.schema)
assert read_data_table.column_names == data_table.column_names

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks very much for the thorough test.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is part of @cristekdatum's original test.

const CDecryptionConfiguration& decryption_config) except +*
shared_ptr[CExternalFileDecryptionProperties] GetExternalFileDecryptionProperties(
const CKmsConnectionConfig& kms_connection_config,
const CExternalDecryptionConfiguration& decryption_config) except +*

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

😮‍💨

@sofia-tekdatum sofia-tekdatum merged commit f0599e3 into dev_phase2 Aug 20, 2025
6 of 23 checks passed
@sofia-tekdatum sofia-tekdatum deleted the external_file_decryptor_bindings branch August 20, 2025 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants