Skip to content

Commit 9b9765f

Browse files
committed
feat(rest): add session-aware REST catalog
Add SessionContext and SessionCatalog APIs, make RestCatalog a session-aware root, and bind REST catalog operations through default, contextual, and table-scoped catalog views. Route contextual and table auth through AuthManager, preserve table response config for scoped catalogs, and fail closed on unsupported table FileIO config.
1 parent 8d576ed commit 9b9765f

18 files changed

Lines changed: 878 additions & 164 deletions

src/iceberg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(ICEBERG_SOURCES
2121
arrow_c_data_util.cc
2222
arrow_c_data_guard_internal.cc
2323
catalog/memory/in_memory_catalog.cc
24+
catalog/session_context.cc
2425
delete_file_index.cc
2526
expression/aggregate.cc
2627
expression/binder.cc

src/iceberg/catalog/meson.build

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717

1818
subdir('memory')
1919

20+
install_headers(
21+
['session_catalog.h', 'session_context.h'],
22+
subdir: 'iceberg/catalog',
23+
)
24+
2025
if get_option('rest').enabled()
2126
subdir('rest')
2227
endif

src/iceberg/catalog/rest/auth/auth_manager.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ Result<std::shared_ptr<AuthSession>> AuthManager::InitSession(
3838
}
3939

4040
Result<std::shared_ptr<AuthSession>> AuthManager::ContextualSession(
41-
[[maybe_unused]] const std::unordered_map<std::string, std::string>& context,
42-
std::shared_ptr<AuthSession> parent) {
41+
[[maybe_unused]] const SessionContext& context, std::shared_ptr<AuthSession> parent) {
4342
// By default, return the parent session as-is
4443
return parent;
4544
}

src/iceberg/catalog/rest/auth/auth_manager.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,13 @@ class ICEBERG_REST_EXPORT AuthManager {
7070
/// This method is used by SessionCatalog to create sessions for different contexts
7171
/// (e.g., different users or tenants).
7272
///
73-
/// \param context Context properties (e.g., user credentials, tenant info).
73+
/// \param context Session context (e.g., session ID, identity, credentials,
74+
/// properties).
7475
/// \param parent Catalog session to inherit from or return as-is.
7576
/// \return A context-specific session, or the parent session if no context-specific
7677
/// session is needed, or an error if session creation fails.
7778
virtual Result<std::shared_ptr<AuthSession>> ContextualSession(
78-
const std::unordered_map<std::string, std::string>& context,
79-
std::shared_ptr<AuthSession> parent);
79+
const SessionContext& context, std::shared_ptr<AuthSession> parent);
8080

8181
/// \brief Create or reuse a session scoped to a single table/view.
8282
///

src/iceberg/catalog/rest/auth/oauth2_util.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <nlohmann/json.hpp>
2323

24+
#include "iceberg/catalog/rest/auth/auth_properties.h"
2425
#include "iceberg/catalog/rest/auth/auth_session.h"
2526
#include "iceberg/catalog/rest/error_handlers.h"
2627
#include "iceberg/catalog/rest/http_client.h"

src/iceberg/catalog/rest/auth/sigv4_auth_manager_internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ class ICEBERG_REST_EXPORT SigV4AuthManager : public AuthManager {
126126
const std::unordered_map<std::string, std::string>& properties) override;
127127

128128
Result<std::shared_ptr<AuthSession>> ContextualSession(
129-
const std::unordered_map<std::string, std::string>& context,
130-
std::shared_ptr<AuthSession> parent) override;
129+
const SessionContext& context, std::shared_ptr<AuthSession> parent) override;
131130

132131
Result<std::shared_ptr<AuthSession>> TableSession(
133132
const TableIdentifier& table,

src/iceberg/catalog/rest/auth/sigv4_manager.cc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "iceberg/catalog/rest/auth/auth_manager_internal.h"
2121
#include "iceberg/catalog/rest/auth/sigv4_auth_manager_internal.h"
22+
#include "iceberg/catalog/session_context.h"
2223
#include "iceberg/result.h"
2324

2425
#if ICEBERG_SIGV4_ENABLED
@@ -146,6 +147,19 @@ std::unordered_map<std::string, std::string> MergeProperties(
146147
return merged;
147148
}
148149

150+
Result<std::unordered_map<std::string, std::string>> ContextProperties(
151+
const SessionContext& context) {
152+
auto merged = context.properties;
153+
for (const auto& [key, value] : context.credentials) {
154+
auto [it, inserted] = merged.emplace(key, value);
155+
if (!inserted && it->second != value) {
156+
return InvalidArgument("Session context has conflicting values for property '{}'",
157+
key);
158+
}
159+
}
160+
return merged;
161+
}
162+
149163
/// Matches Java RESTSigV4AuthSession: canonical headers carry
150164
/// Base64(SHA256(body)), canonical request trailer uses hex.
151165
class RestSigV4Signer : public Aws::Client::AWSAuthV4Signer {
@@ -386,19 +400,19 @@ Result<std::shared_ptr<AuthSession>> SigV4AuthManager::CatalogSession(
386400
}
387401

388402
Result<std::shared_ptr<AuthSession>> SigV4AuthManager::ContextualSession(
389-
const std::unordered_map<std::string, std::string>& context,
390-
std::shared_ptr<AuthSession> parent) {
403+
const SessionContext& context, std::shared_ptr<AuthSession> parent) {
391404
auto sigv4_parent = std::dynamic_pointer_cast<SigV4AuthSession>(std::move(parent));
392405
ICEBERG_PRECHECK(sigv4_parent != nullptr,
393406
"SigV4AuthManager parent must be a SigV4AuthSession");
394407

395408
ICEBERG_ASSIGN_OR_RAISE(auto delegate_session, delegate_->ContextualSession(
396409
context, sigv4_parent->delegate()));
397410

398-
auto merged = MergeProperties(catalog_properties_, context);
411+
ICEBERG_ASSIGN_OR_RAISE(auto context_properties, ContextProperties(context));
412+
auto merged = MergeProperties(catalog_properties_, context_properties);
399413
ICEBERG_ASSIGN_OR_RAISE(
400-
auto credentials,
401-
ResolveCredentialsProvider(context, sigv4_parent->credentials_provider()));
414+
auto credentials, ResolveCredentialsProvider(context_properties,
415+
sigv4_parent->credentials_provider()));
402416
return WrapSession(std::move(delegate_session), merged, std::move(credentials));
403417
}
404418

0 commit comments

Comments
 (0)