Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 7 additions & 1 deletion src/iceberg/catalog/rest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
# specific language governing permissions and limitations
# under the License.

# Include auth subdirectory
add_subdirectory(auth)

set(ICEBERG_REST_SOURCES
catalog_properties.cc
endpoint.cc
Expand All @@ -24,7 +27,10 @@ set(ICEBERG_REST_SOURCES
resource_paths.cc
rest_catalog.cc
rest_util.cc
types.cc)
types.cc
auth/auth_manager.cc
auth/auth_managers.cc
auth/auth_session.cc)

set(ICEBERG_REST_STATIC_BUILD_INTERFACE_LIBS)
set(ICEBERG_REST_SHARED_BUILD_INTERFACE_LIBS)
Expand Down
18 changes: 18 additions & 0 deletions src/iceberg/catalog/rest/auth/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

iceberg_install_all_headers(iceberg/catalog/rest/auth)
41 changes: 41 additions & 0 deletions src/iceberg/catalog/rest/auth/auth_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

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

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

namespace iceberg::rest::auth {

Result<std::unique_ptr<AuthSession>> AuthManager::InitSession(
HttpClient& init_client,
const std::unordered_map<std::string, std::string>& properties) {
// By default, use the catalog session for initialization
return CatalogSession(init_client, properties);
}

Result<std::unique_ptr<AuthSession>> AuthManager::TableSession(
[[maybe_unused]] const TableIdentifier& table,
[[maybe_unused]] const std::unordered_map<std::string, std::string>& properties,
[[maybe_unused]] const AuthSession& parent) {
// By default, return nullptr to indicate the parent session should be reused.
return nullptr;
}

} // namespace iceberg::rest::auth
80 changes: 80 additions & 0 deletions src/iceberg/catalog/rest/auth/auth_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#pragma once

#include <memory>
#include <string>
#include <unordered_map>

#include "iceberg/catalog/rest/iceberg_rest_export.h"
#include "iceberg/catalog/rest/type_fwd.h"
#include "iceberg/result.h"
#include "iceberg/table_identifier.h"

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

namespace iceberg::rest::auth {

/// \brief Produces authentication sessions for catalog and table requests.
class ICEBERG_REST_EXPORT AuthManager {
public:
virtual ~AuthManager() = default;

/// \brief Create a short-lived session used to contact the configuration endpoint.
///
/// \param init_client HTTP client used for initialization requests.
/// \param properties Client configuration supplied by the catalog.
/// \return Session for initialization or an error if credentials cannot be acquired.
virtual Result<std::unique_ptr<AuthSession>> InitSession(
HttpClient& init_client,
const std::unordered_map<std::string, std::string>& properties);

/// \brief Create the long-lived catalog session that acts as the parent session.
///
/// \param shared_client HTTP client owned by the catalog and reused for auth calls.
/// \param properties Catalog properties (client config + server defaults).
/// \return Session for catalog operations or an error if authentication cannot be set
/// up.
virtual Result<std::unique_ptr<AuthSession>> CatalogSession(
HttpClient& shared_client,
const std::unordered_map<std::string, std::string>& properties) = 0;

/// \brief Create or reuse a session scoped to a single table/view.
///
/// This method can return a new table-specific session or indicate that the parent
/// catalog session should be reused by returning nullptr.
///
/// \param table Target table identifier.
/// \param properties Table-specific auth properties returned by the server.
/// \param parent Catalog session to read information from.
/// \return A new session for the table, nullptr to reuse parent, or an error.
virtual Result<std::unique_ptr<AuthSession>> TableSession(
const TableIdentifier& table,
const std::unordered_map<std::string, std::string>& properties,
const AuthSession& parent);

/// \brief Release resources held by the manager.
///
/// \return Status of the close operation.
virtual Status Close() { return {}; }
};

} // namespace iceberg::rest::auth
85 changes: 85 additions & 0 deletions src/iceberg/catalog/rest/auth/auth_managers.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

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

#include <algorithm>
#include <cctype>

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

namespace iceberg::rest::auth {

namespace {

/// \brief Infer the authentication type from properties.
///
/// If no explicit auth type is set, this function tries to infer it from
/// other properties. If "credential" or "token" is present, it implies
/// OAuth2 authentication. Otherwise, defaults to no authentication.
///
/// This behavior is consistent with Java Iceberg's AuthManagers.
std::string InferAuthType(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a enum class for the auth type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auth types come from external config files/properties as strings, so the string-based approach allows users to register custom auth types without modifying core code. It also matches the Iceberg REST spec.

const std::unordered_map<std::string, std::string>& properties) {
// Check for explicit auth type first
auto it = properties.find(std::string(AuthProperties::kAuthType));
if (it != properties.end() && !it->second.empty()) {
return StringUtils::ToLower(it->second);
}

// Infer from OAuth2 properties (credential or token)
bool has_credential =
properties.contains(std::string(AuthProperties::kOAuth2Credential));
bool has_token = properties.contains(std::string(AuthProperties::kOAuth2Token));
if (has_credential || has_token) {
return std::string(AuthProperties::kAuthTypeOAuth2);
}

// Default to no authentication
return std::string(AuthProperties::kAuthTypeNone);
}

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

} // namespace

void AuthManagers::Register(std::string_view auth_type, AuthManagerFactory factory) {
GetRegistry()[StringUtils::ToLower(std::string(auth_type))] = std::move(factory);
}

Result<std::unique_ptr<AuthManager>> AuthManagers::Load(
std::string_view name,
const std::unordered_map<std::string, std::string>& properties) {
std::string auth_type = InferAuthType(properties);

auto& registry = GetRegistry();
auto it = registry.find(auth_type);
if (it == registry.end()) {
return NotImplemented("Authentication type '{}' is not supported", auth_type);
}

return it->second(name, properties);
}

} // namespace iceberg::rest::auth
70 changes: 70 additions & 0 deletions src/iceberg/catalog/rest/auth/auth_managers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#pragma once

#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>

#include "iceberg/catalog/rest/auth/auth_manager.h"
#include "iceberg/catalog/rest/iceberg_rest_export.h"
#include "iceberg/result.h"
#include "iceberg/util/string_util.h"

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

namespace iceberg::rest::auth {

/// \brief Function that builds an AuthManager for a given catalog.
///
/// \param name Catalog name passed to the manager.
/// \param properties Consolidated catalog configuration.
/// \return Newly created manager instance.
using AuthManagerFactory = std::function<std::unique_ptr<AuthManager>(
std::string_view name,
const std::unordered_map<std::string, std::string>& properties)>;

/// \brief Registry type for AuthManager factories with heterogeneous lookup support.
using AuthManagerRegistry =
std::unordered_map<std::string, AuthManagerFactory, StringHash, StringEqual>;

/// \brief Registry-backed factory for AuthManager implementations.
class ICEBERG_REST_EXPORT AuthManagers {
public:
/// \brief Load a manager by consulting the "rest.auth.type" configuration.
///
/// \param name Catalog name passed to the manager.
/// \param properties Catalog properties used to determine auth type.
/// \return Manager instance or an error if no factory matches.
static Result<std::unique_ptr<AuthManager>> Load(
std::string_view name,
const std::unordered_map<std::string, std::string>& properties);

/// \brief Register or override the factory for a given auth type.
///
/// \param auth_type Case-insensitive type identifier (e.g., "basic").
/// \param factory Factory function that produces the manager.
static void Register(std::string_view auth_type, AuthManagerFactory factory);
};

} // namespace iceberg::rest::auth
69 changes: 69 additions & 0 deletions src/iceberg/catalog/rest/auth/auth_properties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#pragma once

#include <string_view>

/// \file iceberg/catalog/rest/auth/auth_properties.h
/// \brief Property keys and constants for REST catalog authentication.

namespace iceberg::rest::auth {

/// \brief Property keys and constants for authentication configuration.
///
/// This struct defines all the property keys used to configure authentication
/// for the REST catalog. It follows the same naming conventions as Java Iceberg.
struct AuthProperties {
/// \brief Property key for specifying the authentication type.
static constexpr std::string_view kAuthType = "rest.auth.type";
/// \brief Authentication type: no authentication.
static constexpr std::string_view kAuthTypeNone = "none";
/// \brief Authentication type: HTTP Basic authentication.
static constexpr std::string_view kAuthTypeBasic = "basic";
/// \brief Authentication type: OAuth2 authentication.
static constexpr std::string_view kAuthTypeOAuth2 = "oauth2";
/// \brief Authentication type: AWS SigV4 authentication.
static constexpr std::string_view kAuthTypeSigV4 = "sigv4";
/// \brief Property key for Basic auth username.
static constexpr std::string_view kBasicUsername = "rest.auth.basic.username";
/// \brief Property key for Basic auth password.
static constexpr std::string_view kBasicPassword = "rest.auth.basic.password";
/// \brief Property key for OAuth2 token (bearer token).
static constexpr std::string_view kOAuth2Token = "token";
/// \brief Property key for OAuth2 credential (client_id:client_secret).
static constexpr std::string_view kOAuth2Credential = "credential";
/// \brief Property key for OAuth2 scope.
static constexpr std::string_view kOAuth2Scope = "scope";
/// \brief Property key for OAuth2 server URI.
static constexpr std::string_view kOAuth2ServerUri = "oauth2-server-uri";
/// \brief Property key for enabling token refresh.
static constexpr std::string_view kOAuth2TokenRefreshEnabled = "token-refresh-enabled";
/// \brief Default OAuth2 scope for catalog operations.
static constexpr std::string_view kOAuth2DefaultScope = "catalog";
/// \brief Property key for SigV4 region.
static constexpr std::string_view kSigV4Region = "rest.auth.sigv4.region";
/// \brief Property key for SigV4 service name.
static constexpr std::string_view kSigV4Service = "rest.auth.sigv4.service";
/// \brief Property key for SigV4 delegate auth type.
static constexpr std::string_view kSigV4DelegateAuthType =
"rest.auth.sigv4.delegate-auth-type";
};

} // namespace iceberg::rest::auth
Loading
Loading