Core: [Demonstration only] handle hybrid mode encryption with REST Catalog - #18081
singhpk234 wants to merge 21 commits into
Conversation
…cherry-pick # Conflicts: # spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/sql/TestTableEncryption.java # spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/sql/TestTableEncryption.java
Generated-by: Codex
Use client-side storage and KMS credentials by default for encrypted REST tables, with an opt-in for client-side KMS credentials alongside vended storage credentials. Generated-by: Codex
smaheshwar-pltr
left a comment
There was a problem hiding this comment.
Thanks a lot @singhpk234 for putting this up, realise this is a draft but provides a great way to express some high-level thoughts on this approach so I've done so (sorry!)
Mainly resurfaced #13225 (comment), please LMKWYT of the higher-level comments here (cc @szlta too).
| && tableMetadata.properties().containsKey(TableProperties.ENCRYPTION_TABLE_KEY); | ||
| } | ||
|
|
||
| private void validateNoServerSideStorageAccess( |
There was a problem hiding this comment.
As per #13225 (comment), this PR checks storage credentials + signing config, but what about
- returned
LoadTableResponseconfig? Those configs configure IO too from the server, from before we had thestorage-credentialsfield - server
/configdefaults/overrides also still flow through
Also, remote signing can be configured through IO properties too for both these cases. Is it intentional to only cover the storageCredentials and remoteSigningConfig case?
There was a problem hiding this comment.
we can handle these as well, though how about if X-Iceberg-Access-delegation : vended-creds is set fail it ... even before making request ?
There was a problem hiding this comment.
I'd argue against that - "X-Iceberg-Access-delegation : vended-creds" is only part of the spec change proposal at this time - I'm not sure it makes sense for the code to express uncommitted spec details.
| return table().io(); | ||
| } | ||
|
|
||
| Preconditions.checkState( |
There was a problem hiding this comment.
We probably want to clean up plan resources if we throw this. Otherwise with the current implementation, clean up won't happen
There was a problem hiding this comment.
we can fail where and make sure where the close is called ?
| List<Credential> storageCredentials, | ||
| RemoteSigningConfig remoteSigningConfig) { | ||
| if (useClientSideStorageAccessForEncryptedTable(tableMetadata)) { | ||
| validateNoServerSideStorageAccess(tableIdentifier, storageCredentials, remoteSigningConfig); |
There was a problem hiding this comment.
As per #13225 (comment), what about when create / register table throws because of this but the creation has succeeded in the catalog given we can only do the checks after? Have we thought about this case?
At the least, I think the client should know about the side-effect. Trying to "undo" the creation sounds questionable to me
|
|
||
| if (props.containsKey(CatalogProperties.ENCRYPTION_KMS_TYPE) | ||
| || props.containsKey(CatalogProperties.ENCRYPTION_KMS_IMPL)) { | ||
| this.keyManagementClient = EncryptionUtil.createKmsClient(props); |
There was a problem hiding this comment.
This PR now changes to not use the merged props, but just props if I'm understanding right. I think there is something to be discussed here on server-returned configs (defaults + overrides) which are would be ignored with this change e.g.
"defaults": {
"encryption.kms-type": "aws"
},
There was a problem hiding this comment.
I guess for now that should be fine, that default property announcement only matters with vended credentials mode.
| TableIdentifier tableIdentifier, | ||
| List<Credential> storageCredentials, | ||
| RemoteSigningConfig remoteSigningConfig) { | ||
| Preconditions.checkState( |
There was a problem hiding this comment.
(Noting that users will likely run into this given current docs, maybe worth updating the docs)
| .addCredential(credential) | ||
| .withRemoteSigningConfig(TEST_REMOTE_SIGNING_CONFIG) |
There was a problem hiding this comment.
Nit for when we do this properly, probably worth testing cred-only + signing-only independently
| | `rest-page-size` | null | The page size to use when listing namespaces, tables, or other paginated resources. | | ||
| | `namespace-separator` | `%1F` | The separator character used for namespace levels when communicating with the REST server. | | ||
| | `scan-planning-mode` | `client` | Controls where scan planning is performed. Supported values: `client` (client-side planning), `server` (server-side planning). Can be overridden per-table by the server in LoadTableResponse. | | ||
| | `rest.encryption.use-client-kms-creds` | `false` | Whether encrypted REST tables may use client-side KMS credentials together with REST-provided storage access, including vended storage credentials and remote signing. When `false`, encrypted tables reject REST-provided storage access. | |
There was a problem hiding this comment.
For when we do this properly, this name feels misleading. Client KMS is used when set to true and when set to false. Maybe rest.encryption.allow-hybrid-credentials is more accurate
There was a problem hiding this comment.
hybrid means nothing unless we explain what its implies ... may always-use-client-side-kms creds ?
There was a problem hiding this comment.
To me "static credentials" say more than "client side credentials" - as they're actually not ephemeral in nature / not vended
| public static final long REST_SCAN_PLANNING_POLL_TIMEOUT_MS_DEFAULT = | ||
| TimeUnit.MINUTES.toMillis(5); | ||
|
|
||
| // Allow REST-provided storage access for encrypted tables that use client-side KMS. |
There was a problem hiding this comment.
IMHO: not "use client-side KMS" but rather "KMS configured with client-side credentials" (or static credentials)
Summary
Adds REST support for encrypted tables using client-side KMS credentials, with an
opt-in hybrid mode for REST-provided storage access.
By default, encrypted REST tables reject server-provided storage access because
the server-side KMS credential spec is not ready. A new catalog property,
rest.encryption.use-client-kms-creds, allows clients to explicitly opt intousing REST-provided storage access while still using client-side KMS credentials.
Behavior
KMS credentials.
unless
rest.encryption.use-client-kms-creds=true.storage-credentialsremote-signing-configstill loaded only from client-side catalog properties.
Tests
and remote signing config.
credentials.
instead of server-returned config.
Validation run: