Skip to content

Spec: Add key-id and deprecate key-metadata in table and partition statistics - #17533

Open
gaborkaszab wants to merge 3 commits into
apache:mainfrom
gaborkaszab:main_spec_key_id_in_stats
Open

gaborkaszab wants to merge 3 commits into
apache:mainfrom
gaborkaszab:main_spec_key_id_in_stats

Conversation

@gaborkaszab

Copy link
Copy Markdown
Contributor

Storing key-metadata in TableStatistics and PartitionStatistics is unsecured, because that is persisted into table metadata, that itself is not encrypted. As an existing design for manifest list, we encrypt the key-metadata, and save the key-id of the encryption key that we used to encrypt key-metadata.

@singhpk234

Copy link
Copy Markdown
Contributor

key-metadata in TableStatistics and PartitionStatistics is unsecured, because that is persisted into table metadata

i understand the rational of using key-id but what i don't understand is why storing key-metadata unsecure ? because we contain wrapped key as if encrypted value instead of raw ?

are there more details to this ....

cc @ggershinsky

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

Hey @singhpk234 ,

The problem with key-metadata is that it is the raw, unencrypted information on how to decrypt stuff. While it's safe to keep key-metadata on e.g. the data file / manifest entry level, because those files are encrypted themselves in turn encrypting key-metadata together with the file it contains this field, it's not safe to keep it on the table metadata level because that is not encrypted. It would expose the raw key-metadata. The same goes for manifest list encryption, and I believe we should follow the same approach for statistics file linked from table metadata.

See @ggershinsky 's and @RussellSpitzer 's comments here.

@singhpk234

Copy link
Copy Markdown
Contributor

Ah i see, this is unwrapped key metadata which was used to encrypt this file, and not the encrypted keymedata, then it makes sense to have have this wrapped and then have key-id from the table.metadata_keys .... we will wrap this KEK then like we do with MLK then ?

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

@singhpk234 yes, this would work exactly the same way as manifest list encryption keys.

Comment thread format/spec.md Outdated

@RussellSpitzer RussellSpitzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks good to me, we should bring it up on the dev list before we merge the spec change

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

This looks good to me, we should bring it up on the dev list before we merge the spec change

Thanks for the reviews, @ggershinsky @singhpk234 @RussellSpitzer !
I opened the vote thread on the dev list now: https://lists.apache.org/thread/rx0tcnqkq0nzj1phwo64ng79pp51hzf9

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

+1

Comment thread format/spec.md Outdated
| _optional_ | _optional_ | **`key-metadata`** | | Base64-encoded implementation-specific key metadata for encryption. |
| _required_ | _required_ | **`blob-metadata`** | `list<blob metadata>` (see below) | A list of the blob metadata for statistics contained in the file with structure described below. |
=== "v1 - v4"
| v1 and v2 | v3 | v4 | Field name | Type | Description |

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.

We changed v2 and v3 to v1 and v2. is this intentional?

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.

That is intentional. These columns are the same between "v1" and "v2 and v3". Initially I figured we could merge all these together, but I figured we might want to deprecate key-metadata earlier in V3 so kept that version separately. I can revert if this is distracting.

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 did revert the regrouping to remove noise. I might open a follow-up refactor to merge v1-v3 cols in the table

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

@singhpk234 @RussellSpitzer @stevenzwu @ggershinsky @rdblue
I made some changes to the PR. Would you mind taking another look?

  1. I did revert the regrouping of version cols. (I think a follow-up refactor could help to merge the identical cols to make the table more readable)
  2. I kept the support of existing key-metadata in V4, but left it deprecated with a hint to use key-id instead.

@ggershinsky ggershinsky 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, LGTM

Comment thread format/spec.md Outdated
| _required_ | _required_ | **`file-footer-size-in-bytes`** | `long` | Total size of the statistics file's footer (not the footer payload size). See [Puffin file format](puffin-spec.md) for footer definition. |
| _optional_ | _optional_ | **`key-metadata`** | | Base64-encoded implementation-specific key metadata for encryption. |
| _required_ | _required_ | **`blob-metadata`** | `list<blob metadata>` (see below) | A list of the blob metadata for statistics contained in the file with structure described below. |
=== "v1 - v4"

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 think this diff is much too large. We don't need to add a v4 column that is a copy of the other two existing columns and mix those changes into this diff. If I understand the diff correctly, the only thing that should change is that key-metadata should be deprecated and key-id should be added.

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.

That's right. key-metadata is deprecated now, and there is a new field for key-id. Note, for key-metadata there was no type, I added string.
Reverted the V4 column, should be more readable now.

Comment thread format/spec.md
@@ -1239,13 +1238,14 @@
Partition statistics file must be registered in the table metadata file to be considered as a valid statistics file for the reader.

`partition-statistics` field of table metadata is an optional list of structs with the following fields:

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.

Same here. Please revert the rest of the changes so this diff doesn't include the entire table.

@rdblue

rdblue commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

@gaborkaszab, I think the changes look okay, but this isn't very reviewable because I have to manually diff the tables. Since there aren't substantive changes to the other rows, let's minimize the diff.

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

Thanks for taking a look, @rdblue !
I reverted the V4 column now. Hope it's more readable.

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

Hey @rdblue ,
Do you think you can take a look?

@gaborkaszab

Copy link
Copy Markdown
Contributor Author

@rdblue Is this something we can start a vote on?

Comment thread format/spec.md
| _required_ | _required_ | **`file-size-in-bytes`** | `long` | Size of the statistics file. |
| _required_ | _required_ | **`file-footer-size-in-bytes`** | `long` | Total size of the statistics file's footer (not the footer payload size). See [Puffin file format](puffin-spec.md) for footer definition. |
| _optional_ | _optional_ | **`key-metadata`** | | Base64-encoded implementation-specific key metadata for encryption. |
| _optional_ | _optional_ | **`key-metadata`** | `string` | Base64-encoded implementation-specific key metadata for encryption. (**Deprecated**: use `key-id` instead) |

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 think there is still a problem in that we are mixing file-level keys with table-level keys. The keys table is intended to be a small set of keys that are reused and occasionally rotated, not file-specific.

@ggershinsky, how should we handle these? Do we need a way to store encrypted key metadata? What I'm thinking is that we keep key-metadata but add an optional key-id that is used to encrypt the stats file key?

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.

for manifest lists, we did the following: #12162 #12927

An "encrypted key metadata" is a 4-field record (key-id, encrypted-key-metadata, encrypted-by-id, properties map). All of these records are kept in the TableMetadata.encryption-keys list. Some of them are reusable (key encryption keys), but most of them are specific to manifest files. Each snapshot object keeps the key-id of the "encrypted key metadata" of its manifest list file.

The situation with stats files looks similar (if not identical) to the manifest list files. A straightforward technical approach would be to do the same: write a 4-field "encrypted key metadata" record in the TableMetadata.encryption-keys list, and add pointer to the record (key-id) to the stats file object.

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.

Thanks for looking into this @rdblue and @ggershinsky !

I think the main questions here are 1) reusability of keys and 2) whether reusability requires any special care in the spec.

  1. I did an experiment the other day and for me it seems that each manifest list file adds a new EncryptedKey into the encryption-keys list. There is (are?) additional KEK entry(ies) on top of that in the list. I'm not sure about custom implementations but for me it seems that there is no reuse of EncryptedKey entries across different manifest lists, apart from the KEK used to encrypt the EncryptedKeys.
    Keys for stat files fit into this pattern, they could behave the same way as keys for manifest lists. Let me know if I miss something here.
  2. I think the spec changes in this PR can express both the reused key and the non-reused key scenario. key-id for statistics files is just an ID to be used for finding the EncryptedKey in the encryption-keys list that in turn can be used to decrypt the statistics files (after decrypting the found EncryptedFile itself using the KEK). Whether this is a reused EncryptedFile across files or not, I don't think matters in this context.

While I'm still learning this area of the project, let me know where my assumptions go wrong :)

@ggershinsky

Copy link
Copy Markdown
Contributor

these assumptions sgtm.

one general point on re-use of file encryption keys. Due to AES GCM limits, the standard practice is to create a key per file - otherwise, it's hard to guarantee the data safety. That's why our EncryptionManager generates a random key for each output file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Specification Issues that may introduce spec changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants