Skip to content

[#10684] feat(iceberg-rest): Support vended credentials on registerTable endpoint - #10699

Merged
roryqi merged 1 commit into
apache:mainfrom
sachinnn99:feat/10684-register-table-credential-vending
Apr 29, 2026
Merged

[#10684] feat(iceberg-rest): Support vended credentials on registerTable endpoint#10699
roryqi merged 1 commit into
apache:mainfrom
sachinnn99:feat/10684-register-table-credential-vending

Conversation

@sachinnn99

@sachinnn99 sachinnn99 commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Resubmitting per @laserninja's comment on #10684. This revision aligns the implementation with the established createTable/loadTable credential-vending pattern in CatalogWrapperForREST: the new 3-arg registerTable calls super.registerTable(2-arg) and uses the same inline shouldGenerateCredential / injectCredentialConfig conditional that createTable and loadTable already use, and CatalogWrapperForTest now overrides at the 3-arg level (matching how it overrides createTable).

What changes were proposed in this pull request?

Add X-Iceberg-Access-Delegation header support to the registerTable endpoint, enabling credential vending in the response. Mirrors the existing pattern from createTable and loadTable.

Changes:

  • IcebergNamespaceOperations.registerTable: add @HeaderParam(X_ICEBERG_ACCESS_DELEGATION), compute isCredentialVending, build the 3-arg IcebergRequestContext
  • CatalogWrapperForREST: add 3-arg registerTable that calls super.registerTable(2-arg) then conditionally injects credentials inline — structurally identical to the existing 3-arg createTable and loadTable
  • CatalogWrapperForREST: widen shouldGenerateCredential and injectCredentialConfig from private to protected so subclasses (e.g. test wrappers that mock the underlying table operation) can participate in the credential vending flow
  • IcebergNamespaceOperationExecutor.registerTable: pass context.requestCredentialVending() through to the 3-arg wrapper form
  • IcebergTableOperations.isCredentialVending: widen private → package-private static so IcebergNamespaceOperations can reuse it without duplicating the validation logic
  • CatalogWrapperForTest: override the 3-arg registerTable (matching the 3-arg createTable override level), build the mock response, and inline the same shouldGenerateCredential / injectCredentialConfig conditional. Honors cloud URIs in metadataLocation so vending tests can verify the vended path. The legacy 2-arg override is removed (no longer reachable via the dispatcher chain).

Why are the changes needed?

The Iceberg REST spec defines X-Iceberg-Access-Delegation as a valid header on registerTable, but the current implementation does not accept it or vend credentials. Clients that register a table and immediately attempt to read its data must make a separate loadTable call to obtain credentials.

Fix: #10684

Does this PR introduce any user-facing change?

Yes. The registerTable REST endpoint now accepts the X-Iceberg-Access-Delegation header and returns vended credentials in the response config when requested. Backward compatible — clients that do not send the header get existing behavior.

How was this patch tested?

Added unit tests in TestIcebergNamespaceOperations:

  • testRegisterTableWithCredentialVending — verifies no vending without header, no vending for local URI, vending for s3:// URI
  • testRegisterTableRemoteSigningNotSupported — verifies 406 response for remote-signing
  • testRegisterTableInvalidAccessDelegation — verifies 400 response for invalid header values

All existing TestIcebergNamespaceOperations tests still pass with no regressions.

@roryqi

roryqi commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

@laserninja @bharos Could u help me review this pull request/

@roryqi
roryqi requested review from bharos and laserninja April 7, 2026 07:35
"register_cred_foo2", Namespace.of("register_cred_ns2"), "mock");
Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
LoadTableResponse loadTableResponse = response.readEntity(LoadTableResponse.class);
Assertions.assertTrue(!loadTableResponse.config().containsKey(Credential.CREDENTIAL_TYPE));

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.

assertFalse ?

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.

Fixed — replaced assertTrue(!...) with assertFalse(...).

}

private boolean isCredentialVending(String accessDelegation) {
static boolean isCredentialVending(String accessDelegation) {

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 are making this package-private
Should we annotate with @VisibleForTesting

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.

Good catch on the visibility change being undocumented, but the change is actually for production reuse rather than testing — IcebergNamespaceOperations#registerTable (in the same package) now calls this to parse the same X-Iceberg-Access-Delegation header that IcebergTableOperations#createTable and #loadTable already parse. @VisibleForTesting would be misleading because no test depends on its visibility. I've added a JavaDoc explaining the production-reuse rationale instead.

return injectCredentialConfig(
TableIdentifier.of(namespace, request.name()),
loadTableResponse,
CredentialPrivilege.WRITE);

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.

createTable hardcodes WRITE — that makes sense since the client just created the table and likely needs to write data to it. But registerTable is semantically different: the table data already exists and the client is just adding it to the catalog. The typical next action after registration is reading the data. Meanwhile, loadTable accepts the privilege as a parameter and delegates the decision to the caller.

Should registerTable similarly accept/infer the privilege, or is the WRITE default intentional here? At minimum, a brief comment explaining the choice would help future readers.

@sachinnn99 sachinnn99 Apr 8, 2026

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.

You're right, and after digging in I'm switching to READ.

Specifically:

  1. registerTable writes no files at the storage layer. Verified end-to-end: CatalogHandlers.registerTableBaseMetastoreCatalog.registerTableops.commit(null, metadata)BaseMetastoreTableOperations.writeNewMetadataIfRequired(true, metadata) early-returns the existing metadata.metadataFileLocation() without writing, then JdbcTableOperations just inserts the catalog row. So the storage-layer asymmetry you flagged with createTable is real — createTable proves write capability by writing a metadata.json file, registerTable doesn't.

  2. registerTable also doesn't set ownership. IcebergNamespaceOperationExecutor.registerTable is a straight delegation to the wrapper — unlike IcebergTableOperationExecutor.createTable and IcebergNamespaceOperationExecutor.createNamespace, which both explicitly set IcebergConstants.OWNER to context.userName(). So a user with only ANY_CREATE_TABLE privilege never becomes the table owner via register.

  3. WRITE was therefore a one-off privilege escalation. That same user cannot pass FILTER_MODIFY_TABLE_AUTHORIZATION_EXPRESSION (ANY(OWNER, METALAKE, CATALOG, SCHEMA, TABLE) || ANY_MODIFY_TABLE) on the registered table via any other API path. A follow-up loadTable with vending would return READ for them via getCredentialPrivilege. Hardcoding WRITE here was vending storage credentials that let them perform actions gravitino's authz model explicitly forbids.

Switching to READ. Higher-privileged users (catalog/metalake owners, MODIFY_TABLE holders) who legitimately need to write to a registered table can call loadTable with vending afterwards and get WRITE through the dynamic helper, or be granted MODIFY_TABLE explicitly.

I've added a code comment documenting all of this.

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 set the table owner when registering the table. So the register table requester should have write privilege. It will be consistent with our authz model. WDYT?

@sachinnn99 sachinnn99 Apr 25, 2026

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.

@roryqi Good point, you are right. IcebergNamespaceHookDispatcher.registerTable calls setTableOwner for the registering user, so the user does become the table owner. This is consistent with createTable, which also vends WRITE for the same reason.

Updated to vend WRITE and corrected the 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.

The PR's new 3-arg registerTable override in CatalogWrapperForTest duplicates the shouldGenerateCredential/injectCredentialConfig pattern from the parent CatalogWrapperForREST. This duplication is necessary because the in-memory catalog can't handle registerTable natively (unlike createTable, where the test calls super.createTable(3-arg) and the parent handles everything).

However, if the credential injection logic ever changes in CatalogWrapperForREST, this test would silently diverge. Consider adding a brief comment in the test explaining why the duplication exists, e.g.:

// Cannot delegate to super.registerTable(3-arg) because the in-memory catalog
// does not support registerTable; must inline credential injection here.

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.

Added an inline comment at the call site explaining the duplication: the in-memory test catalog cannot perform registerTable natively, so the override synthesizes a mock LoadTableResponse instead of delegating to super.registerTable. Because we never go through the parent's registerTable, we must explicitly re-run its vending logic so credential-vending tests still exercise the same code path as production. (Also updated this wrapper to use READ to match the production change.)

@@ -191,7 +204,7 @@
return false;
}

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.

These methods go from privateprotected, which makes them part of the subclass API contract. This is the cleanest option given the constraints but will need to be maintained as a stable interface going forward. A short JavaDoc note on their intended use (subclass credential injection in cases where super can't be called) would clarify intent.

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.

Added JavaDoc explaining that the protected visibility is for subclasses that synthesize a LoadTableResponse without delegating to super (test wrappers around in-memory catalogs that can't perform certain operations natively), so they can still apply the same vending and injection logic as production paths.

@@ -239,7 +252,7 @@
return credential;
}

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.

same as above

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.

Same JavaDoc rationale added on shouldGenerateCredential.

"register_cred_foo3", Namespace.of("register_cred_ns3"), s3Location);
Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
loadTableResponse = response.readEntity(LoadTableResponse.class);
Assertions.assertEquals(

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.

The S3 vending case only checks for Credential.CREDENTIAL_TYPE in the config.
Asserting on a couple more expected credential properties (e.g., whatever DummyCredentialProvider puts in the config) would make the test more robust against regressions where the type is present but the actual credential values are missing.

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.

Added an additional assertion on Credential.EXPIRE_TIME_IN_MS. DummyCredentialProvider.SimpleCredential is not one of the typed credentials in CredentialPropertyUtils.toIcebergProperties, so it falls through to Credential#toProperties(), which emits exactly credential-type and expire-time-in-ms. Asserting both confirms the full credential block is injected and guards against partial-injection regressions.

@laserninja

Copy link
Copy Markdown
Collaborator

Can you resolve the merge conflicts please

@sachinnn99
sachinnn99 force-pushed the feat/10684-register-table-credential-vending branch from 5c891db to ba22fe6 Compare April 9, 2026 06:01
@sachinnn99

sachinnn99 commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

@laserninja rebased onto main, conflicts resolved.

@roryqi
roryqi requested review from bharos and laserninja April 14, 2026 03:42
@laserninja

Copy link
Copy Markdown
Collaborator

In createTable and loadTable, CatalogWrapperForREST checks if (catalog instanceof RESTCatalog) and delegates to *Internal() methods before credential injection. The new registerTable skips this branch and calls super.registerTable() directly. Could you confirm this works correctly when the underlying catalog is a RESTCatalog (i.e., Gravitino fronting another Iceberg REST catalog)? If the upstream catalog already handles credential vending, the shouldGenerateCredential gate (getCatalog() instanceof RESTCatalog → return false) would short-circuit correctly, but it would be good to verify that RESTCatalog.registerTable properly forwards the X-Iceberg-Access-Delegation header upstream.

@sachinnn99
sachinnn99 force-pushed the feat/10684-register-table-credential-vending branch 2 times, most recently from a8248a5 to 67f0f23 Compare April 15, 2026 11:52
@sachinnn99

Copy link
Copy Markdown
Contributor Author

@laserninja Good question — the current code does include the if (catalog instanceof RESTCatalog) branch for registerTable, delegating to registerTableInternal() before credential injection, matching the same pattern as createTable and loadTable.

When the underlying catalog is a RESTCatalog, shouldGenerateCredential returns false (via the getCatalog() instanceof RESTCatalog check), so Gravitino correctly defers credential vending to the upstream catalog.

The upstream Iceberg RESTSessionCatalog.registerTable doesn't forward X-Iceberg-Access-Delegation as an explicit header — it uses mutationHeaders (idempotency headers only). But it doesn't need to: it processes the upstream response's credentials via response.credentials() and wires them into the RESTTableOperations / tableFileIO. So the chain works correctly end-to-end.

@laserninja

Copy link
Copy Markdown
Collaborator

LGTM. READ privilege is well-reasoned, RESTCatalog path added, JavaDoc and test assertions look good. Thanks for the thorough responses.

@sachinnn99
sachinnn99 force-pushed the feat/10684-register-table-credential-vending branch from 67f0f23 to dc1b30d Compare April 25, 2026 15:32
…sterTable endpoint

Wire the X-Iceberg-Access-Delegation header through the registerTable
REST endpoint so that clients can request credential vending, matching
the existing createTable and loadTable behavior.

Vend WRITE credentials because the registering user becomes the table
owner (IcebergNamespaceHookDispatcher.setTableOwner), consistent with
createTable.
@sachinnn99
sachinnn99 force-pushed the feat/10684-register-table-credential-vending branch from dc1b30d to ef91041 Compare April 25, 2026 15:37
@sachinnn99

Copy link
Copy Markdown
Contributor Author

@roryqi Updated to vend WRITE per your feedback — the registering user becomes the table owner via setTableOwner, so WRITE is consistent with createTable. Let me know if the latest revision looks good.

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

LGTM. Wait for CI.

@github-actions

Copy link
Copy Markdown

Code Coverage Report

Overall Project 65.34% -0.02% 🟢
Files changed 64.33% 🟢

Module Coverage
aliyun 1.73% 🔴
api 47.13% 🟢
authorization-common 85.96% 🟢
aws 1.1% 🔴
azure 2.6% 🔴
catalog-common 10.2% 🔴
catalog-fileset 80.02% 🟢
catalog-glue 91.48% 🟢
catalog-hive 81.83% 🟢
catalog-jdbc-clickhouse 79.06% 🟢
catalog-jdbc-common 43.93% 🟢
catalog-jdbc-doris 80.28% 🟢
catalog-jdbc-hologres 54.03% 🟢
catalog-jdbc-mysql 79.23% 🟢
catalog-jdbc-oceanbase 78.38% 🟢
catalog-jdbc-postgresql 82.05% 🟢
catalog-jdbc-starrocks 78.27% 🟢
catalog-kafka 77.01% 🟢
catalog-lakehouse-generic 45.07% 🟢
catalog-lakehouse-hudi 79.1% 🟢
catalog-lakehouse-iceberg 86.98% 🟢
catalog-lakehouse-paimon 77.71% 🟢
catalog-model 77.72% 🟢
cli 44.51% 🟢
client-java 77.63% 🟢
common 48.67% 🟢
core 81.53% -0.92% 🟢
filesystem-hadoop3 76.97% 🟢
flink 40.55% 🟢
flink-runtime 0.0% 🔴
gcp 14.2% 🔴
hadoop-common 10.39% 🔴
hive-metastore-common 46.83% 🟢
iceberg-common 55.24% 🟢
iceberg-rest-server 67.08% +0.85% 🟢
integration-test-common 0.0% 🔴
jobs 66.17% 🟢
lance-common 23.88% 🔴
lance-rest-server 57.84% 🟢
lineage 53.02% 🟢
optimizer 82.87% 🟢
optimizer-api 21.95% 🔴
server 85.46% +0.42% 🟢
server-common 69.92% +1.43% 🟢
spark 32.79% 🔴
spark-common 39.09% 🔴
trino-connector 34.27% -0.71% 🔴
Files
Module File Coverage
core OwnerMetaBaseSQLProvider.java 100.0% 🟢
SecurableObjectBaseSQLProvider.java 100.0% 🟢
OwnerMetaPostgreSQLProvider.java 100.0% 🟢
SecurableObjectPostgreSQLProvider.java 100.0% 🟢
FunctionMetaSQLProviderFactory.java 83.33% 🟢
RelationalEntityStoreIdResolver.java 83.16% 🟢
FunctionMetaService.java 74.44% 🟢
FunctionMetaBaseSQLProvider.java 73.33% 🟢
MetadataObjectService.java 68.8% 🟢
NameIdentifierUtil.java 64.32% 🟢
MetadataObjectUtil.java 47.22% 🔴
GravitinoEnv.java 11.52% 🔴
FunctionMetaMapper.java 0.0% 🔴
iceberg-rest-server IcebergNamespaceOperationExecutor.java 100.0% 🟢
IcebergTableOperations.java 81.91% 🟢
IcebergNamespaceOperations.java 77.98% 🟢
CatalogWrapperForREST.java 56.92% 🔴
server FunctionOperations.java 100.0% 🟢
server-common AuthorizationExpressionConverter.java 97.98% 🟢
AuthorizationExpressionConstants.java 0.0% 🔴
trino-connector GravitinoConnectorFactory.java 0.0% 🔴

@roryqi
roryqi merged commit e692475 into apache:main Apr 29, 2026
29 checks passed
@roryqi

roryqi commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Thanks @sachinnn99 for your contribution. Thanks @laserninja @laserninja for your review.

danhuawang pushed a commit to danhuawang/gravitino that referenced this pull request Jun 8, 2026
…sterTable endpoint (apache#10699)

Resubmitting per @laserninja's comment on apache#10684. This revision aligns
the implementation with the established `createTable`/`loadTable`
credential-vending pattern in `CatalogWrapperForREST`: the new 3-arg
`registerTable` calls `super.registerTable(2-arg)` and uses the same
inline `shouldGenerateCredential` / `injectCredentialConfig` conditional
that `createTable` and `loadTable` already use, and
`CatalogWrapperForTest` now overrides at the **3-arg** level (matching
how it overrides `createTable`).

### What changes were proposed in this pull request?

Add `X-Iceberg-Access-Delegation` header support to the `registerTable`
endpoint, enabling credential vending in the response. Mirrors the
existing pattern from `createTable` and `loadTable`.

Changes:
- `IcebergNamespaceOperations.registerTable`: add
`@HeaderParam(X_ICEBERG_ACCESS_DELEGATION)`, compute
`isCredentialVending`, build the 3-arg `IcebergRequestContext`
- `CatalogWrapperForREST`: add 3-arg `registerTable` that calls
`super.registerTable(2-arg)` then conditionally injects credentials
inline — structurally identical to the existing 3-arg `createTable` and
`loadTable`
- `CatalogWrapperForREST`: widen `shouldGenerateCredential` and
`injectCredentialConfig` from `private` to `protected` so subclasses
(e.g. test wrappers that mock the underlying table operation) can
participate in the credential vending flow
- `IcebergNamespaceOperationExecutor.registerTable`: pass
`context.requestCredentialVending()` through to the 3-arg wrapper form
- `IcebergTableOperations.isCredentialVending`: widen `private` →
package-private `static` so `IcebergNamespaceOperations` can reuse it
without duplicating the validation logic
- `CatalogWrapperForTest`: override the **3-arg** `registerTable`
(matching the 3-arg `createTable` override level), build the mock
response, and inline the same `shouldGenerateCredential` /
`injectCredentialConfig` conditional. Honors cloud URIs in
`metadataLocation` so vending tests can verify the vended path. The
legacy 2-arg override is removed (no longer reachable via the dispatcher
chain).

### Why are the changes needed?

The Iceberg REST spec defines `X-Iceberg-Access-Delegation` as a valid
header on `registerTable`, but the current implementation does not
accept it or vend credentials. Clients that register a table and
immediately attempt to read its data must make a separate `loadTable`
call to obtain credentials.

Fix: apache#10684

### Does this PR introduce _any_ user-facing change?

Yes. The `registerTable` REST endpoint now accepts the
`X-Iceberg-Access-Delegation` header and returns vended credentials in
the response config when requested. Backward compatible — clients that
do not send the header get existing behavior.

### How was this patch tested?

Added unit tests in `TestIcebergNamespaceOperations`:
- `testRegisterTableWithCredentialVending` — verifies no vending without
header, no vending for local URI, vending for `s3://` URI
- `testRegisterTableRemoteSigningNotSupported` — verifies 406 response
for `remote-signing`
- `testRegisterTableInvalidAccessDelegation` — verifies 400 response for
invalid header values

All existing `TestIcebergNamespaceOperations` tests still pass with no
regressions.
danhuawang pushed a commit to danhuawang/gravitino that referenced this pull request Jun 9, 2026
…sterTable endpoint (apache#10699)

Resubmitting per @laserninja's comment on apache#10684. This revision aligns
the implementation with the established `createTable`/`loadTable`
credential-vending pattern in `CatalogWrapperForREST`: the new 3-arg
`registerTable` calls `super.registerTable(2-arg)` and uses the same
inline `shouldGenerateCredential` / `injectCredentialConfig` conditional
that `createTable` and `loadTable` already use, and
`CatalogWrapperForTest` now overrides at the **3-arg** level (matching
how it overrides `createTable`).

### What changes were proposed in this pull request?

Add `X-Iceberg-Access-Delegation` header support to the `registerTable`
endpoint, enabling credential vending in the response. Mirrors the
existing pattern from `createTable` and `loadTable`.

Changes:
- `IcebergNamespaceOperations.registerTable`: add
`@HeaderParam(X_ICEBERG_ACCESS_DELEGATION)`, compute
`isCredentialVending`, build the 3-arg `IcebergRequestContext`
- `CatalogWrapperForREST`: add 3-arg `registerTable` that calls
`super.registerTable(2-arg)` then conditionally injects credentials
inline — structurally identical to the existing 3-arg `createTable` and
`loadTable`
- `CatalogWrapperForREST`: widen `shouldGenerateCredential` and
`injectCredentialConfig` from `private` to `protected` so subclasses
(e.g. test wrappers that mock the underlying table operation) can
participate in the credential vending flow
- `IcebergNamespaceOperationExecutor.registerTable`: pass
`context.requestCredentialVending()` through to the 3-arg wrapper form
- `IcebergTableOperations.isCredentialVending`: widen `private` →
package-private `static` so `IcebergNamespaceOperations` can reuse it
without duplicating the validation logic
- `CatalogWrapperForTest`: override the **3-arg** `registerTable`
(matching the 3-arg `createTable` override level), build the mock
response, and inline the same `shouldGenerateCredential` /
`injectCredentialConfig` conditional. Honors cloud URIs in
`metadataLocation` so vending tests can verify the vended path. The
legacy 2-arg override is removed (no longer reachable via the dispatcher
chain).

### Why are the changes needed?

The Iceberg REST spec defines `X-Iceberg-Access-Delegation` as a valid
header on `registerTable`, but the current implementation does not
accept it or vend credentials. Clients that register a table and
immediately attempt to read its data must make a separate `loadTable`
call to obtain credentials.

Fix: apache#10684

### Does this PR introduce _any_ user-facing change?

Yes. The `registerTable` REST endpoint now accepts the
`X-Iceberg-Access-Delegation` header and returns vended credentials in
the response config when requested. Backward compatible — clients that
do not send the header get existing behavior.

### How was this patch tested?

Added unit tests in `TestIcebergNamespaceOperations`:
- `testRegisterTableWithCredentialVending` — verifies no vending without
header, no vending for local URI, vending for `s3://` URI
- `testRegisterTableRemoteSigningNotSupported` — verifies 406 response
for `remote-signing`
- `testRegisterTableInvalidAccessDelegation` — verifies 400 response for
invalid header values

All existing `TestIcebergNamespaceOperations` tests still pass with no
regressions.
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.

[Improvement] registerTable endpoint should support vended credentials via X-Iceberg-Access-Delegation header

4 participants