gaborkaszab commented on code in PR #17523:
URL: https://github.com/apache/iceberg/pull/17523#discussion_r3729393240
##########
api/src/main/java/org/apache/iceberg/encryption/EncryptingFileIO.java:
##########
@@ -120,15 +121,24 @@ public InputFile newInputFile(ManifestFile manifest) {
}
@Override
- public InputFile newInputFile(ManifestListFile manifestList) {
- if (manifestList.encryptionKeyID() != null) {
- ByteBuffer keyMetadata = manifestList.decryptKeyMetadata(em);
- return newDecryptingInputFile(manifestList.location(), keyMetadata);
+ public InputFile newInputFile(SnapshotFile snapshotFile) {
Review Comment:
I was poking this code for `StatisticsFile` encryption recently and I had
the impression that these `newInputFile` function parameters are maybe too
narrow.
The things we need here aren't really specific to manifest list or snapshot
file or any other file:
1) What we need is the `encryptionKeyId`, the `location` and raw
`key-metadata`.
2) calling `snapshotFile.decryptKeyMetadata` is somewhat misleading because
there is nothing specific happens internally to SnapshotFile or
BaseManifestListFile.
I'm wondering if we want to scratch this question within this PR, but might
be the right time to introduce a more general way of implementing
`newInputFile(location, encryptionKeyId, key_metadata)`
##########
core/src/main/java/org/apache/iceberg/SnapshotsTable.java:
##########
@@ -37,7 +37,8 @@ public class SnapshotsTable extends BaseMetadataTable {
Types.NestedField.optional(
6,
"summary",
- Types.MapType.ofRequired(7, 8, Types.StringType.get(),
Types.StringType.get())));
+ Types.MapType.ofRequired(7, 8, Types.StringType.get(),
Types.StringType.get())),
+ Types.NestedField.optional(9, "snapshot_file",
Types.StringType.get()));
Review Comment:
Do we want to change the snapshots metadata table with this PR? I think
metadata tables are orthogonal and can be taken care separately. This PR is to
introduce another level of abstraction, but how to visualize it in the snapshot
table is a different topic IMO.
##########
api/src/main/java/org/apache/iceberg/encryption/EncryptingFileIO.java:
##########
@@ -120,15 +121,24 @@ public InputFile newInputFile(ManifestFile manifest) {
}
@Override
- public InputFile newInputFile(ManifestListFile manifestList) {
- if (manifestList.encryptionKeyID() != null) {
- ByteBuffer keyMetadata = manifestList.decryptKeyMetadata(em);
- return newDecryptingInputFile(manifestList.location(), keyMetadata);
+ public InputFile newInputFile(SnapshotFile snapshotFile) {
+ if (snapshotFile.encryptionKeyID() != null) {
+ ByteBuffer keyMetadata = snapshotFile.decryptKeyMetadata(em);
+ return newDecryptingInputFile(snapshotFile.location(), keyMetadata);
} else {
- return newInputFile(manifestList.location());
+ return newInputFile(snapshotFile.location());
}
}
+ /**
+ * @deprecated since 1.13.0; use {@link #newInputFile(SnapshotFile)}.
Review Comment:
2 comments:
1) Next release is 1.12.0. Shouldn't we target that with the deprecation?
2) Shouldn't we also articulate when it will be dropped? Since it's in
`api/`, `2.0.0`, I guess
This goes for all deprecation in this PR, except that in `core/` we can drop
earlier, in `1.13.0`
##########
api/src/main/java/org/apache/iceberg/SnapshotFile.java:
##########
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iceberg;
+
+import java.nio.ByteBuffer;
+import org.apache.iceberg.encryption.EncryptionManager;
+
+/**
+ * The top-level file that a {@link Snapshot} points at. For v3 and earlier
this is a manifest list
+ * (see {@link ManifestListFile}); for v4+ it is a root manifest carrying a
mix of data-file entries
Review Comment:
I'm wondering if we want to take this one step further and making even more
general: I was examining encryption/decryption for `StatisticsFile` and
`PartitionStatistics` recently, and I found that we have many specializations
for the relevant `EncryptiongFileIO`, `FileIO` and `EncryptionUtil` functions
for `ManifestListFile`, but in fact that contains nothing that is manifest list
specific.
I think all this boils down to having the necessary fields to create either
a regular Input/Output file or the encrypting/decryption versions. The code for
this is general: you need a location, an encryption key ID that refers to some
encryption key in `TableMetadata.encryptionKeys` and a mechanism to decrypt the
`key-metadata` referred by the key id. Even this mechanism is not specific to
manifest lists or V4 snapshot files.
My point is that I think whatever structure we introduce now to serve a
general purpose than `ManifestListFile`, it should be even more general than
`SnapshotFile` and could cover all file types that are keeping their encryption
keys within `TableMetadata.encryptionKeys`. I'm in trouble with the naming of
such a common interface, though.
Just for the record, [here is the
PR](https://github.com/apache/iceberg/pull/17417) where I introduce the same
for `StatisticsFile`.
If you want, I can explore the more general approach in a separate PR, but
it has a direct effect on this one too.
##########
core/src/main/java/org/apache/iceberg/encryption/EncryptionUtil.java:
##########
@@ -134,25 +135,44 @@ public static ByteBuffer setFileLength(ByteBuffer
keyMetadata, long fileLength)
return
StandardKeyMetadata.parse(keyMetadata).copyWithLength(fileLength).buffer();
}
+ /**
+ * Decrypt the key metadata for the top-level file that a snapshot points at
(a v3 manifest list
+ * or a v4+ root manifest).
+ *
+ * @param snapshotFile a SnapshotFile
+ * @param em the table's EncryptionManager
+ * @return a decrypted key metadata buffer
+ */
+ public static ByteBuffer decryptSnapshotFileKeyMetadata(
+ SnapshotFile snapshotFile, EncryptionManager em) {
+ return decryptSnapshotFileKeyMetadata(snapshotFile.encryptionKeyID(), em);
+ }
+
/**
* Decrypt the key metadata for a manifest list.
*
* @param manifestList a ManifestListFile
* @param em the table's EncryptionManager
* @return a decrypted key metadata buffer
+ * @deprecated since 1.13.0; use {@link
#decryptSnapshotFileKeyMetadata(SnapshotFile,
+ * EncryptionManager)}.
*/
+ @Deprecated
public static ByteBuffer decryptManifestListKeyMetadata(
ManifestListFile manifestList, EncryptionManager em) {
+ return decryptSnapshotFileKeyMetadata(manifestList.encryptionKeyID(), em);
+ }
+
+ private static ByteBuffer decryptSnapshotFileKeyMetadata(String keyId,
EncryptionManager em) {
Review Comment:
This doesn't have to be snapshot file specific. The algorithm is pretty
general to all files referenced in table metadata. [See
here](https://github.com/apache/iceberg/pull/17417/changes#diff-d5672d217e4ba33b04085c007604bd32ebf266837e713988d69b6967940be72fR205).
##########
api/src/main/java/org/apache/iceberg/ManifestFile.java:
##########
@@ -29,6 +29,12 @@
public interface ManifestFile {
int PARTITION_SUMMARIES_ELEMENT_ID = 508;
+ /**
+ * Sentinel returned by {@link Snapshot#formatVersion()} for snapshots that
do not report a format
+ * version — e.g. v3-and-earlier snapshots whose top-level file is a
manifest list.
+ */
+ int LEGACY_FORMAT_VERSION = 0;
Review Comment:
In case this PR gets merged earlier: I prefer the shorter comment as it is
in the other PR:
`/** Format version for pre-v4 manifest files. */`
Also, shouldn't this be static final? (true for the linked PR as well)
--
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]