Skip to content

Core: [Demonstration only] handle hybrid mode encryption with REST Catalog - #18081

Draft
singhpk234 wants to merge 21 commits into
apache:mainfrom
singhpk234:pr-13225-singhpk234-comments
Draft

singhpk234 wants to merge 21 commits into
apache:mainfrom
singhpk234:pr-13225-singhpk234-comments

Conversation

@singhpk234

@singhpk234 singhpk234 commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

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 into
using REST-provided storage access while still using client-side KMS credentials.

Behavior

  • Default: encrypted REST tables use client-side storage access and client-side
    KMS credentials.
  • If an encrypted table receives REST-provided storage access, the client fails
    unless rest.encryption.use-client-kms-creds=true.
  • REST-provided storage access includes:
    • storage-credentials
    • remote-signing-config
  • In hybrid mode, REST-provided storage access is allowed, but KMS credentials are
    still loaded only from client-side catalog properties.
  • Existing remote-signing endpoint wiring is unchanged.

Tests

  • Added REST catalog tests for encrypted tables with vended storage credentials
    and remote signing config.
  • Added REST scan-planning tests for encrypted tables with returned storage
    credentials.
  • Added coverage ensuring KMS client initialization uses client-side properties
    instead of server-returned config.

Validation run:

git diff --check
./gradlew :iceberg-core:spotlessCheck
./gradlew :iceberg-core:test --tests org.apache.iceberg.rest.TestRESTCatalog
--tests org.apache.iceberg.rest.TestRESTScanPlanning

———

AI Disclosure

- Model: GPT-5
- Platform/Tool: Codex
- Human Oversight: done
- Prompt Summary: Implemented review feedback for REST encrypted table handling
  with client-side KMS credentials and an opt-in hybrid path for REST-provided
  storage access.

@smaheshwar-pltr smaheshwar-pltr 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 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(

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.

As per #13225 (comment), this PR checks storage credentials + signing config, but what about

  1. returned LoadTableResponse config? Those configs configure IO too from the server, from before we had the storage-credentials field
  2. server /config defaults/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?

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.

we can handle these as well, though how about if X-Iceberg-Access-delegation : vended-creds is set fail it ... even before making request ?

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'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(

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 probably want to clean up plan resources if we throw this. Otherwise with the current implementation, clean up won't happen

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.

we can fail where and make sure where the close is called ?

List<Credential> storageCredentials,
RemoteSigningConfig remoteSigningConfig) {
if (useClientSideStorageAccessForEncryptedTable(tableMetadata)) {
validateNoServerSideStorageAccess(tableIdentifier, storageCredentials, remoteSigningConfig);

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.

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);

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

https://docs.google.com/document/d/1VSewbVmjukU5eTiZruCJVmUZcRZvcAsd4JOeC6Lt3fo/edit?tab=t.0#heading=h.huszjf7jg3fb mentions

"defaults": {
  "encryption.kms-type": "aws"
},

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 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(

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.

(Noting that users will likely run into this given current docs, maybe worth updating the docs)

Comment on lines +4244 to +4245
.addCredential(credential)
.withRemoteSigningConfig(TEST_REMOTE_SIGNING_CONFIG)

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 for when we do this properly, probably worth testing cred-only + signing-only independently

Comment thread docs/docs/rest-catalog.md
| `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. |

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 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

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.

hybrid means nothing unless we explain what its implies ... may always-use-client-side-kms creds ?

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.

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.

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.

IMHO: not "use client-side KMS" but rather "KMS configured with client-side credentials" (or static credentials)

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants