Skip to content

feat(encryption) [15/N] write encrypted parquet data files - #2701

Merged
blackmwk merged 14 commits into
apache:mainfrom
aarushigupta132:feat/encrypted-parquet-data-files
Aug 18, 2026
Merged

feat(encryption) [15/N] write encrypted parquet data files#2701
blackmwk merged 14 commits into
apache:mainfrom
aarushigupta132:feat/encrypted-parquet-data-files

Conversation

@aarushigupta132

@aarushigupta132 aarushigupta132 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Working towards #2034.

What changes are included in this PR?

Adds support for writing Iceberg data files with Parquet Modular Encryption: ParquetWriterBuilder::with_encryption_manager opts a writer into encryption, generating a per-file DEK from the table's EncryptionManager and recording its key metadata on the resulting DataFile.

Are these changes tested?

Yes, unit tests cover the encrypted write path for ParquetWriter and RollingFileWriter.

@aarushigupta132 aarushigupta132 changed the title Feat/encrypted parquet data files feat(encryption): write encrypted parquet data files Jun 23, 2026
@aarushigupta132
aarushigupta132 marked this pull request as ready for review June 23, 2026 23:45

@xanderbailey xanderbailey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks carrying the flame on the encryption work. Have made a couple of comments to get us started.

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
@aarushigupta132 aarushigupta132 changed the title feat(encryption): write encrypted parquet data files feat(encryption) [15/N] write encrypted parquet data files Jul 15, 2026
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch 2 times, most recently from 58df8f8 to 0783948 Compare July 15, 2026 16:55
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from 0783948 to b80ebbf Compare July 15, 2026 17:38
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch 3 times, most recently from cc5fca7 to 74c54db Compare July 15, 2026 23:46
type R = ParquetWriter;

async fn build(&self, output_file: OutputFile) -> Result<Self::R> {
let key_metadata = self

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed that in rolling_writer as well, we build this again with new dek for each new parquet file

Comment on lines 65 to 67
/// When writing into an existing Iceberg table, prefer
/// [`Self::from_table_properties`], which derives `WriterProperties` from
/// the table's `write.parquet.*` properties.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

curious to know if we should deprecate new and new_with_match_mode in favor of from_table_properties. Or update the comment to prefer the latter in all cases?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would add a comment in the doc here that encrypted writing is not supported with this constructor. I would honestly be in favour of removing this constructor since it's not used in this crate and nor should it be. I don't think we should do that in this PR but it would be a good follow-up IMO.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also would like to know @blackmwk's recommendation here 🙏

@xanderbailey xanderbailey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Few more comments and a test for the writer would be great. Maybe also something that shows datafusion writer works but that can be a follow up

Comment thread crates/iceberg/src/encryption/key_metadata.rs Outdated
Comment on lines 65 to 67
/// When writing into an existing Iceberg table, prefer
/// [`Self::from_table_properties`], which derives `WriterProperties` from
/// the table's `write.parquet.*` properties.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would add a comment in the doc here that encrypted writing is not supported with this constructor. I would honestly be in favour of removing this constructor since it's not used in this crate and nor should it be. I don't think we should do that in this PR but it would be a good follow-up IMO.

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch 2 times, most recently from 5a0ea6f to 9832f50 Compare July 19, 2026 21:53
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from 9832f50 to 2ba0884 Compare July 19, 2026 21:59

@mbutrovich mbutrovich 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.

First pass, thanks @aarushigupta132!

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
table.metadata().current_schema(),
)?;

// The planner encrypted the file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure what this means

@blackmwk blackmwk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @aarushigupta132 , just finished first round of review.

Comment thread crates/iceberg/src/encryption/key_metadata.rs Outdated
.build();
Self::new_with_match_mode(props, schema, FieldMatchMode::Id)

let data_encryption_key_size = table_props

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I prefer to make this part of TableProperties, e.g. add a data_entryption_key_size method

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs
}

#[tokio::test]
async fn test_iceberg_write_exec_encrypted() -> Result<()> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This only tested write, not read. I perfer to use sqllogictest to set table properties, and test read and write encrypted parquet files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I believe a complete read-write test would require removing this check (as this would be a commit)
I would like to follow-up with more round trip tests, whenever we remove this gate.
Would you recommend doing all the mentioned in this pr or should i just remove this datafusion test here and add in a follow up pr?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In this case you could crate an issue to track adding integration tests to for encryption. This test is too difficult to maintain, and I think the ParquetWriter ut is enough for this pr.

///
/// Returns `None` when the table is not configured for encryption.
/// Returns an error when `encryption.data-key-length` is not a valid AES key length.
pub(crate) fn data_encryption_key_size(props: &TableProperties) -> Result<Option<AesKeySize>> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In fact, I mean make this part of TableProperties struct, which feels more natural.

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs

/// Generates a `StandardKeyMetadata` carrying a fresh random DEK of
/// `key_size` together with a fresh random AAD prefix.
pub fn generate(key_size: AesKeySize) -> Self {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Make this crate private. StandKeyMetadata should be generated by EncryptionManager

}

#[tokio::test]
async fn test_iceberg_write_exec_encrypted() -> Result<()> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In this case you could crate an issue to track adding integration tests to for encryption. This test is too difficult to maintain, and I think the ParquetWriter ut is enough for this pr.

@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from 6f56a91 to 57f6604 Compare August 5, 2026 23:10
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
})?;

Ok(writer_properties
.clone()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Do we really need this clone if we already have into_builder?

Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
Comment thread crates/iceberg/src/encryption/manager.rs Outdated
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from 833a201 to bb90c29 Compare August 10, 2026 00:44
@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from ab6ce0b to d76ad77 Compare August 10, 2026 01:55
Comment thread crates/iceberg/src/writer/file_writer/parquet_writer.rs Outdated
Comment thread crates/iceberg/src/test_utils.rs Outdated
@aarushigupta132

Copy link
Copy Markdown
Contributor Author

thank you @blackmwk for all the reviews! apologies i was a bit preoccupied last week but it is resolved now, happy to iterate with full speed

@aarushigupta132
aarushigupta132 force-pushed the feat/encrypted-parquet-data-files branch from 1d8daea to 6015e0a Compare August 12, 2026 13:11
@aarushigupta132

Copy link
Copy Markdown
Contributor Author

@blackmwk gentle ping here 🙏

@blackmwk blackmwk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @aarushigupta132 for this pr!

@blackmwk
blackmwk merged commit 4908b0b into apache:main Aug 18, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants