Skip to content

Commit 54b4868

Browse files
author
shuxu.li
committed
feat: add restcatalog authentication api
1 parent 72df76d commit 54b4868

File tree

10 files changed

+93
-206
lines changed

10 files changed

+93
-206
lines changed

src/iceberg/catalog/rest/CMakeLists.txt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@ set(ICEBERG_REST_SOURCES
2727
resource_paths.cc
2828
rest_catalog.cc
2929
rest_util.cc
30-
types.cc)
31-
32-
# Add auth sources with proper path prefix
33-
foreach(AUTH_SOURCE ${ICEBERG_REST_AUTH_SOURCES})
34-
list(APPEND ICEBERG_REST_SOURCES "auth/${AUTH_SOURCE}")
35-
endforeach()
30+
types.cc
31+
auth/auth_manager.cc
32+
auth/auth_managers.cc
33+
auth/auth_session.cc)
3634

3735
set(ICEBERG_REST_STATIC_BUILD_INTERFACE_LIBS)
3836
set(ICEBERG_REST_SHARED_BUILD_INTERFACE_LIBS)

src/iceberg/catalog/rest/auth/CMakeLists.txt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,4 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
set(ICEBERG_REST_AUTH_SOURCES auth_session.cc auth_manager.cc auth_managers.cc)
19-
20-
# Expose sources to parent scope for inclusion in iceberg_rest library
21-
set(ICEBERG_REST_AUTH_SOURCES
22-
${ICEBERG_REST_AUTH_SOURCES}
23-
PARENT_SCOPE)
18+
iceberg_install_all_headers(iceberg/catalog/rest/auth)

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,23 @@
1919

2020
#include "iceberg/catalog/rest/auth/auth_manager.h"
2121

22+
#include "iceberg/catalog/rest/auth/auth_session.h"
23+
2224
namespace iceberg::rest::auth {
2325

24-
Result<std::shared_ptr<AuthSession>> AuthManager::InitSession(
25-
HttpClient* init_client,
26+
Result<std::unique_ptr<AuthSession>> AuthManager::InitSession(
27+
HttpClient& init_client,
2628
const std::unordered_map<std::string, std::string>& properties) {
2729
// By default, use the catalog session for initialization
2830
return CatalogSession(init_client, properties);
2931
}
3032

31-
Result<std::shared_ptr<AuthSession>> AuthManager::TableSession(
33+
Result<std::unique_ptr<AuthSession>> AuthManager::TableSession(
3234
[[maybe_unused]] const TableIdentifier& table,
3335
[[maybe_unused]] const std::unordered_map<std::string, std::string>& properties,
34-
std::shared_ptr<AuthSession> parent) {
35-
// By default, return the parent session
36-
return parent;
36+
[[maybe_unused]] const AuthSession& parent) {
37+
// By default, return nullptr to indicate the parent session should be reused.
38+
return nullptr;
3739
}
3840

3941
} // namespace iceberg::rest::auth

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

Lines changed: 27 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -23,100 +23,58 @@
2323
#include <string>
2424
#include <unordered_map>
2525

26-
#include "iceberg/catalog/rest/auth/auth_session.h"
2726
#include "iceberg/catalog/rest/iceberg_rest_export.h"
27+
#include "iceberg/catalog/rest/type_fwd.h"
2828
#include "iceberg/result.h"
2929
#include "iceberg/table_identifier.h"
3030

3131
/// \file iceberg/catalog/rest/auth/auth_manager.h
3232
/// \brief Authentication manager interface for REST catalog.
3333

34-
namespace iceberg::rest {
35-
class HttpClient;
36-
} // namespace iceberg::rest
37-
3834
namespace iceberg::rest::auth {
3935

40-
/// \brief Manager for authentication sessions.
41-
///
42-
/// This interface is used to create sessions for the catalog, tables/views,
43-
/// and any other context that requires authentication.
44-
///
45-
/// Managers are typically stateful and may require initialization and cleanup.
46-
/// The manager is created by the catalog and is closed when the catalog is closed.
47-
///
48-
/// This interface is modeled after Java Iceberg's AuthManager interface.
36+
/// \brief Produces authentication sessions for catalog and table requests.
4937
class ICEBERG_REST_EXPORT AuthManager {
5038
public:
5139
virtual ~AuthManager() = default;
5240

53-
/// \brief Return a temporary session for contacting the configuration endpoint.
54-
///
55-
/// This session is used only during catalog initialization to fetch server
56-
/// configuration. The returned session will be closed after the configuration
57-
/// endpoint is contacted and should not be cached.
58-
///
59-
/// The provided HTTP client is a short-lived client; it should only be used
60-
/// to fetch initial credentials if required, and must be discarded after that.
41+
/// \brief Create a short-lived session used to contact the configuration endpoint.
6142
///
62-
/// By default, it returns the catalog session.
63-
///
64-
/// \param init_client A short-lived HTTP client for initialization.
65-
/// \param properties Configuration properties.
66-
/// \return A session for initialization, or an error if session creation fails.
67-
virtual Result<std::shared_ptr<AuthSession>> InitSession(
68-
HttpClient* init_client,
43+
/// \param init_client HTTP client used for initialization requests.
44+
/// \param properties Client configuration supplied by the catalog.
45+
/// \return Session for initialization or an error if credentials cannot be acquired.
46+
virtual Result<std::unique_ptr<AuthSession>> InitSession(
47+
HttpClient& init_client,
6948
const std::unordered_map<std::string, std::string>& properties);
7049

71-
/// \brief Return a long-lived session for catalog operations.
72-
///
73-
/// This session's lifetime is tied to the owning catalog. It serves as the
74-
/// parent session for all other sessions (contextual and table-specific).
75-
/// It is closed when the owning catalog is closed.
50+
/// \brief Create the long-lived catalog session that acts as the parent session.
7651
///
77-
/// The provided HTTP client is a long-lived, shared client. Implementors may
78-
/// store it and reuse it for subsequent requests to the authorization server
79-
/// (e.g., for renewing or refreshing credentials). It is not necessary to
80-
/// close it when Close() is called.
81-
///
82-
/// It is not required to cache the returned session internally, as the catalog
83-
/// will keep it alive for the lifetime of the catalog.
84-
///
85-
/// \param shared_client A long-lived, shared HTTP client.
86-
/// \param properties Configuration properties (merged with server config).
87-
/// \return A session for catalog operations, or an error if session creation fails
88-
/// (e.g., missing required credentials, network failure during token fetch).
89-
virtual Result<std::shared_ptr<AuthSession>> CatalogSession(
90-
HttpClient* shared_client,
52+
/// \param shared_client HTTP client owned by the catalog and reused for auth calls.
53+
/// \param properties Catalog properties (client config + server defaults).
54+
/// \return Session for catalog operations or an error if authentication cannot be set
55+
/// up.
56+
virtual Result<std::unique_ptr<AuthSession>> CatalogSession(
57+
HttpClient& shared_client,
9158
const std::unordered_map<std::string, std::string>& properties) = 0;
9259

93-
/// \brief Return a session for a specific table or view.
94-
///
95-
/// If the table or view requires a specific AuthSession (e.g., vended credentials),
96-
/// this method should return a new AuthSession instance. Otherwise, it should
97-
/// return the parent session.
98-
///
99-
/// By default, it returns the parent session.
60+
/// \brief Create or reuse a session scoped to a single table/view.
10061
///
101-
/// Implementors should cache table sessions internally, as the catalog will not
102-
/// cache them. Also, the owning catalog never closes table sessions; implementations
103-
/// should manage their lifecycle and close them when they are no longer needed.
62+
/// This method can return a new table-specific session or indicate that the parent
63+
/// catalog session should be reused by returning nullptr.
10464
///
105-
/// \param table The table identifier.
106-
/// \param properties Properties returned by the table/view endpoint.
107-
/// \param parent The parent session (typically the catalog session).
108-
/// \return A session for the table, or an error if session creation fails.
109-
virtual Result<std::shared_ptr<AuthSession>> TableSession(
65+
/// \param table Target table identifier.
66+
/// \param properties Table-specific auth properties returned by the server.
67+
/// \param parent Catalog session to read information from.
68+
/// \return A new session for the table, nullptr to reuse parent, or an error.
69+
virtual Result<std::unique_ptr<AuthSession>> TableSession(
11070
const TableIdentifier& table,
11171
const std::unordered_map<std::string, std::string>& properties,
112-
std::shared_ptr<AuthSession> parent);
72+
const AuthSession& parent);
11373

114-
/// \brief Close the manager and release any resources.
74+
/// \brief Release resources held by the manager.
11575
///
116-
/// This method is called when the owning catalog is closed. Implementations
117-
/// should release any resources held by the manager, such as cached sessions
118-
/// or background threads.
119-
virtual void Close() {}
76+
/// \return Status of the close operation.
77+
virtual Status Close() { return {}; }
12078
};
12179

12280
} // namespace iceberg::rest::auth

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

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,12 @@
2323
#include <cctype>
2424

2525
#include "iceberg/catalog/rest/auth/auth_properties.h"
26+
#include "iceberg/util/string_util.h"
2627

2728
namespace iceberg::rest::auth {
2829

2930
namespace {
3031

31-
/// \brief Convert a string to lowercase for case-insensitive comparison.
32-
std::string ToLower(std::string_view str) {
33-
std::string result(str);
34-
std::ranges::transform(result, result.begin(),
35-
[](unsigned char c) { return std::tolower(c); });
36-
return result;
37-
}
38-
3932
/// \brief Infer the authentication type from properties.
4033
///
4134
/// If no explicit auth type is set, this function tries to infer it from
@@ -48,7 +41,7 @@ std::string InferAuthType(
4841
// Check for explicit auth type first
4942
auto it = properties.find(std::string(AuthProperties::kAuthType));
5043
if (it != properties.end() && !it->second.empty()) {
51-
return ToLower(it->second);
44+
return StringUtils::ToLower(it->second);
5245
}
5346

5447
// Infer from OAuth2 properties (credential or token)
@@ -63,19 +56,20 @@ std::string InferAuthType(
6356
return std::string(AuthProperties::kAuthTypeNone);
6457
}
6558

66-
} // namespace
67-
68-
std::unordered_map<std::string, AuthManagerFactory>& AuthManagers::GetRegistry() {
69-
static std::unordered_map<std::string, AuthManagerFactory> registry;
59+
/// \brief Get the global registry of auth manager factories.
60+
AuthManagerRegistry& GetRegistry() {
61+
static AuthManagerRegistry registry;
7062
return registry;
7163
}
7264

73-
void AuthManagers::Register(const std::string& auth_type, AuthManagerFactory factory) {
74-
GetRegistry()[ToLower(auth_type)] = std::move(factory);
65+
} // namespace
66+
67+
void AuthManagers::Register(std::string_view auth_type, AuthManagerFactory factory) {
68+
GetRegistry()[StringUtils::ToLower(std::string(auth_type))] = std::move(factory);
7569
}
7670

7771
Result<std::unique_ptr<AuthManager>> AuthManagers::Load(
78-
const std::string& name,
72+
std::string_view name,
7973
const std::unordered_map<std::string, std::string>& properties) {
8074
std::string auth_type = InferAuthType(properties);
8175

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

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,67 +22,49 @@
2222
#include <functional>
2323
#include <memory>
2424
#include <string>
25+
#include <string_view>
2526
#include <unordered_map>
2627

2728
#include "iceberg/catalog/rest/auth/auth_manager.h"
2829
#include "iceberg/catalog/rest/iceberg_rest_export.h"
2930
#include "iceberg/result.h"
31+
#include "iceberg/util/string_util.h"
3032

3133
/// \file iceberg/catalog/rest/auth/auth_managers.h
3234
/// \brief Factory for creating authentication managers.
3335

3436
namespace iceberg::rest::auth {
3537

36-
/// \brief Factory function type for creating AuthManager instances.
38+
/// \brief Function that builds an AuthManager for a given catalog.
3739
///
38-
/// \param name The name of the manager (used for logging).
39-
/// \param properties Configuration properties.
40-
/// \return A unique pointer to the created AuthManager.
40+
/// \param name Catalog name passed to the manager.
41+
/// \param properties Consolidated catalog configuration.
42+
/// \return Newly created manager instance.
4143
using AuthManagerFactory = std::function<std::unique_ptr<AuthManager>(
42-
const std::string& name,
44+
std::string_view name,
4345
const std::unordered_map<std::string, std::string>& properties)>;
4446

45-
/// \brief Factory class for loading authentication managers.
46-
///
47-
/// This class provides a registry-based approach to create AuthManager instances
48-
/// based on the configured authentication type. It supports built-in types
49-
/// (none, basic, oauth2) and allows registration of custom types.
50-
///
51-
/// This class is modeled after Java Iceberg's AuthManagers class.
47+
/// \brief Registry type for AuthManager factories with heterogeneous lookup support.
48+
using AuthManagerRegistry =
49+
std::unordered_map<std::string, AuthManagerFactory, StringHash, StringEqual>;
50+
51+
/// \brief Registry-backed factory for AuthManager implementations.
5252
class ICEBERG_REST_EXPORT AuthManagers {
5353
public:
54-
/// \brief Load an authentication manager based on configuration.
55-
///
56-
/// This method reads the "rest.auth.type" property to determine which
57-
/// AuthManager implementation to create. Supported types include:
58-
/// - "none": NoopAuthManager (no authentication)
59-
/// - "basic": BasicAuthManager (HTTP Basic authentication)
60-
/// - "oauth2": OAuth2AuthManager (OAuth2 authentication)
61-
/// - "sigv4": SigV4AuthManager (AWS Signature V4)
54+
/// \brief Load a manager by consulting the "rest.auth.type" configuration.
6255
///
63-
/// If no auth type is specified, the method will infer the type based on
64-
/// other properties (e.g., presence of "credential" or "token" implies oauth2).
65-
/// If no auth-related properties are found, it defaults to "none".
66-
///
67-
/// \param name A name for the manager (used for logging).
68-
/// \param properties Configuration properties.
69-
/// \return A unique pointer to the created AuthManager, or an error.
56+
/// \param name Catalog name passed to the manager.
57+
/// \param properties Catalog properties used to determine auth type.
58+
/// \return Manager instance or an error if no factory matches.
7059
static Result<std::unique_ptr<AuthManager>> Load(
71-
const std::string& name,
60+
std::string_view name,
7261
const std::unordered_map<std::string, std::string>& properties);
7362

74-
/// \brief Register a custom authentication manager factory.
75-
///
76-
/// This allows users to extend the supported authentication types by
77-
/// registering their own AuthManager implementations.
63+
/// \brief Register or override the factory for a given auth type.
7864
///
79-
/// \param auth_type The authentication type name (e.g., "custom").
80-
/// \param factory The factory function to create the AuthManager.
81-
static void Register(const std::string& auth_type, AuthManagerFactory factory);
82-
83-
private:
84-
/// \brief Get the global registry of auth manager factories.
85-
static std::unordered_map<std::string, AuthManagerFactory>& GetRegistry();
65+
/// \param auth_type Case-insensitive type identifier (e.g., "basic").
66+
/// \param factory Factory function that produces the manager.
67+
static void Register(std::string_view auth_type, AuthManagerFactory factory);
8668
};
8769

8870
} // namespace iceberg::rest::auth

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,49 +33,34 @@ namespace iceberg::rest::auth {
3333
struct AuthProperties {
3434
/// \brief Property key for specifying the authentication type.
3535
static constexpr std::string_view kAuthType = "rest.auth.type";
36-
3736
/// \brief Authentication type: no authentication.
3837
static constexpr std::string_view kAuthTypeNone = "none";
39-
4038
/// \brief Authentication type: HTTP Basic authentication.
4139
static constexpr std::string_view kAuthTypeBasic = "basic";
42-
4340
/// \brief Authentication type: OAuth2 authentication.
4441
static constexpr std::string_view kAuthTypeOAuth2 = "oauth2";
45-
4642
/// \brief Authentication type: AWS SigV4 authentication.
4743
static constexpr std::string_view kAuthTypeSigV4 = "sigv4";
48-
4944
/// \brief Property key for Basic auth username.
5045
static constexpr std::string_view kBasicUsername = "rest.auth.basic.username";
51-
5246
/// \brief Property key for Basic auth password.
5347
static constexpr std::string_view kBasicPassword = "rest.auth.basic.password";
54-
5548
/// \brief Property key for OAuth2 token (bearer token).
5649
static constexpr std::string_view kOAuth2Token = "token";
57-
5850
/// \brief Property key for OAuth2 credential (client_id:client_secret).
5951
static constexpr std::string_view kOAuth2Credential = "credential";
60-
6152
/// \brief Property key for OAuth2 scope.
6253
static constexpr std::string_view kOAuth2Scope = "scope";
63-
6454
/// \brief Property key for OAuth2 server URI.
6555
static constexpr std::string_view kOAuth2ServerUri = "oauth2-server-uri";
66-
6756
/// \brief Property key for enabling token refresh.
6857
static constexpr std::string_view kOAuth2TokenRefreshEnabled = "token-refresh-enabled";
69-
7058
/// \brief Default OAuth2 scope for catalog operations.
7159
static constexpr std::string_view kOAuth2DefaultScope = "catalog";
72-
7360
/// \brief Property key for SigV4 region.
7461
static constexpr std::string_view kSigV4Region = "rest.auth.sigv4.region";
75-
7662
/// \brief Property key for SigV4 service name.
7763
static constexpr std::string_view kSigV4Service = "rest.auth.sigv4.service";
78-
7964
/// \brief Property key for SigV4 delegate auth type.
8065
static constexpr std::string_view kSigV4DelegateAuthType =
8166
"rest.auth.sigv4.delegate-auth-type";

0 commit comments

Comments
 (0)