Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions src/iceberg/catalog/rest/auth/auth_managers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@

#include "iceberg/catalog/rest/auth/auth_managers.h"

#include <unordered_set>

#include "iceberg/catalog/rest/auth/auth_properties.h"
#include "iceberg/catalog/rest/auth/auth_session.h"
#include "iceberg/util/string_util.h"

namespace iceberg::rest::auth {
Expand All @@ -30,6 +33,16 @@ namespace {
using AuthManagerRegistry =
std::unordered_map<std::string, AuthManagerFactory, StringHash, StringEqual>;

const std::unordered_set<std::string, StringHash, StringEqual>& KnownAuthTypes() {
static const std::unordered_set<std::string, StringHash, StringEqual> kAuthTypes = {
AuthProperties::kAuthTypeNone,
AuthProperties::kAuthTypeBasic,
AuthProperties::kAuthTypeOAuth2,
AuthProperties::kAuthTypeSigV4,
};
return kAuthTypes;
}

// Infer the authentication type from properties.
std::string InferAuthType(
const std::unordered_map<std::string, std::string>& properties) {
Expand All @@ -48,9 +61,39 @@ std::string InferAuthType(
return AuthProperties::kAuthTypeNone;
}

/// \brief Authentication manager that performs no authentication.
class NoopAuthManager : public AuthManager {
public:
static Result<std::unique_ptr<AuthManager>> Make(
[[maybe_unused]] std::string_view name,
[[maybe_unused]] const std::unordered_map<std::string, std::string>& properties) {
return std::make_unique<NoopAuthManager>();
}

Result<std::shared_ptr<AuthSession>> CatalogSession(
[[maybe_unused]] HttpClient& client,
[[maybe_unused]] const std::unordered_map<std::string, std::string>& properties)
override {
return AuthSession::MakeDefault({});
Comment thread
wgtmac marked this conversation as resolved.
}
};

template <typename T>
AuthManagerFactory MakeAuthFactory() {
return
[](std::string_view name, const std::unordered_map<std::string, std::string>& props)
-> Result<std::unique_ptr<AuthManager>> { return T::Make(name, props); };
}

AuthManagerRegistry CreateDefaultRegistry() {
return {
{AuthProperties::kAuthTypeNone, MakeAuthFactory<NoopAuthManager>()},
};
}

// Get the global registry of auth manager factories.
AuthManagerRegistry& GetRegistry() {
static AuthManagerRegistry registry;
static AuthManagerRegistry registry = CreateDefaultRegistry();
return registry;
}

Expand All @@ -68,8 +111,10 @@ Result<std::unique_ptr<AuthManager>> AuthManagers::Load(
auto& registry = GetRegistry();
auto it = registry.find(auth_type);
if (it == registry.end()) {
// TODO(Li Shuxu): Fallback to default auth manager implementations
return NotImplemented("Authentication type '{}' is not supported", auth_type);
if (KnownAuthTypes().contains(auth_type)) {
return NotImplemented("Authentication type '{}' is not yet supported", auth_type);
}
return InvalidArgument("Unknown authentication type: '{}'", auth_type);
}

return it->second(name, properties);
Expand Down
45 changes: 27 additions & 18 deletions src/iceberg/catalog/rest/http_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>

#include "iceberg/catalog/rest/auth/auth_session.h"
#include "iceberg/catalog/rest/constant.h"
#include "iceberg/catalog/rest/error_handlers.h"
#include "iceberg/catalog/rest/json_serde_internal.h"
Expand Down Expand Up @@ -146,11 +147,18 @@ HttpClient::HttpClient(std::unordered_map<std::string, std::string> default_head

HttpClient::~HttpClient() = default;

Result<std::unordered_map<std::string, std::string>> HttpClient::AuthHeaders(
auth::AuthSession& session) {
std::unordered_map<std::string, std::string> headers;
ICEBERG_RETURN_UNEXPECTED(session.Authenticate(headers));
return headers;
}

Result<HttpResponse> HttpClient::Get(
const std::string& path, const std::unordered_map<std::string, std::string>& params,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler) {
auto final_headers = MergeHeaders(default_headers_, headers);
const ErrorHandler& error_handler, auth::AuthSession& session) {
ICEBERG_ASSIGN_OR_RAISE(auto auth_headers, AuthHeaders(session));
auto final_headers = MergeHeaders(default_headers_, auth_headers);
Comment thread
lishuxu marked this conversation as resolved.
Outdated
cpr::Response response =
cpr::Get(cpr::Url{path}, GetParameters(params), final_headers, *connection_pool_);

Expand All @@ -160,11 +168,11 @@ Result<HttpResponse> HttpClient::Get(
return http_response;
}

Result<HttpResponse> HttpClient::Post(
const std::string& path, const std::string& body,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler) {
auto final_headers = MergeHeaders(default_headers_, headers);
Result<HttpResponse> HttpClient::Post(const std::string& path, const std::string& body,
const ErrorHandler& error_handler,
auth::AuthSession& session) {
ICEBERG_ASSIGN_OR_RAISE(auto auth_headers, AuthHeaders(session));
auto final_headers = MergeHeaders(default_headers_, auth_headers);
cpr::Response response =
cpr::Post(cpr::Url{path}, cpr::Body{body}, final_headers, *connection_pool_);

Expand All @@ -177,9 +185,9 @@ Result<HttpResponse> HttpClient::Post(
Result<HttpResponse> HttpClient::PostForm(
const std::string& path,
const std::unordered_map<std::string, std::string>& form_data,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler) {
auto final_headers = MergeHeaders(default_headers_, headers);
const ErrorHandler& error_handler, auth::AuthSession& session) {
ICEBERG_ASSIGN_OR_RAISE(auto auth_headers, AuthHeaders(session));
auto final_headers = MergeHeaders(default_headers_, auth_headers);
final_headers.insert_or_assign(kHeaderContentType, kMimeTypeFormUrlEncoded);
std::vector<cpr::Pair> pair_list;
pair_list.reserve(form_data.size());
Expand All @@ -196,10 +204,11 @@ Result<HttpResponse> HttpClient::PostForm(
return http_response;
}

Result<HttpResponse> HttpClient::Head(
const std::string& path, const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler) {
auto final_headers = MergeHeaders(default_headers_, headers);
Result<HttpResponse> HttpClient::Head(const std::string& path,
const ErrorHandler& error_handler,
auth::AuthSession& session) {
ICEBERG_ASSIGN_OR_RAISE(auto auth_headers, AuthHeaders(session));
auto final_headers = MergeHeaders(default_headers_, auth_headers);
cpr::Response response = cpr::Head(cpr::Url{path}, final_headers, *connection_pool_);

ICEBERG_RETURN_UNEXPECTED(HandleFailureResponse(response, error_handler));
Expand All @@ -210,9 +219,9 @@ Result<HttpResponse> HttpClient::Head(

Result<HttpResponse> HttpClient::Delete(
const std::string& path, const std::unordered_map<std::string, std::string>& params,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler) {
auto final_headers = MergeHeaders(default_headers_, headers);
const ErrorHandler& error_handler, auth::AuthSession& session) {
ICEBERG_ASSIGN_OR_RAISE(auto auth_headers, AuthHeaders(session));
auto final_headers = MergeHeaders(default_headers_, auth_headers);
cpr::Response response = cpr::Delete(cpr::Url{path}, GetParameters(params),
final_headers, *connection_pool_);

Expand Down
23 changes: 12 additions & 11 deletions src/iceberg/catalog/rest/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,33 +81,34 @@ class ICEBERG_REST_EXPORT HttpClient {
/// \brief Sends a GET request.
Result<HttpResponse> Get(const std::string& path,
const std::unordered_map<std::string, std::string>& params,
const std::unordered_map<std::string, std::string>& headers,
Comment thread
lishuxu marked this conversation as resolved.
const ErrorHandler& error_handler);
const ErrorHandler& error_handler, auth::AuthSession& session);

/// \brief Sends a POST request.
Result<HttpResponse> Post(const std::string& path, const std::string& body,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler);
const ErrorHandler& error_handler,
auth::AuthSession& session);

/// \brief Sends a POST request with form data.
Result<HttpResponse> PostForm(
const std::string& path,
const std::unordered_map<std::string, std::string>& form_data,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler);
const ErrorHandler& error_handler, auth::AuthSession& session);

/// \brief Sends a HEAD request.
Result<HttpResponse> Head(const std::string& path,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler);
Result<HttpResponse> Head(const std::string& path, const ErrorHandler& error_handler,
auth::AuthSession& session);

/// \brief Sends a DELETE request.
Result<HttpResponse> Delete(const std::string& path,
const std::unordered_map<std::string, std::string>& params,
const std::unordered_map<std::string, std::string>& headers,
const ErrorHandler& error_handler);
const ErrorHandler& error_handler,
auth::AuthSession& session);

private:
/// \brief Get authentication headers from a session.
static Result<std::unordered_map<std::string, std::string>> AuthHeaders(
auth::AuthSession& session);

std::unordered_map<std::string, std::string> default_headers_;
std::unique_ptr<cpr::ConnectionPool> connection_pool_;
};
Expand Down
Loading
Loading