Skip to content

Commit 437f252

Browse files
authored
feat: add restcatalog authentication api (#479)
1 parent 20a961a commit 437f252

File tree

12 files changed

+546
-0
lines changed

12 files changed

+546
-0
lines changed

src/iceberg/catalog/rest/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18+
add_subdirectory(auth)
19+
1820
set(ICEBERG_REST_SOURCES
21+
auth/auth_manager.cc
22+
auth/auth_managers.cc
23+
auth/auth_session.cc
1924
catalog_properties.cc
2025
endpoint.cc
2126
error_handlers.cc
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
iceberg_install_all_headers(iceberg/catalog/rest/auth)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/catalog/rest/auth/auth_manager.h"
21+
22+
#include "iceberg/catalog/rest/auth/auth_session.h"
23+
24+
namespace iceberg::rest::auth {
25+
26+
Result<std::shared_ptr<AuthSession>> AuthManager::InitSession(
27+
HttpClient& init_client,
28+
const std::unordered_map<std::string, std::string>& properties) {
29+
// By default, use the catalog session for initialization
30+
return CatalogSession(init_client, properties);
31+
}
32+
33+
Result<std::shared_ptr<AuthSession>> AuthManager::ContextualSession(
34+
[[maybe_unused]] const std::unordered_map<std::string, std::string>& context,
35+
std::shared_ptr<AuthSession> parent) {
36+
// By default, return the parent session as-is
37+
return parent;
38+
}
39+
40+
Result<std::shared_ptr<AuthSession>> AuthManager::TableSession(
41+
[[maybe_unused]] const TableIdentifier& table,
42+
[[maybe_unused]] const std::unordered_map<std::string, std::string>& properties,
43+
std::shared_ptr<AuthSession> parent) {
44+
// By default, return the parent session as-is
45+
return parent;
46+
}
47+
48+
} // namespace iceberg::rest::auth
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
#include <memory>
23+
#include <string>
24+
#include <unordered_map>
25+
26+
#include "iceberg/catalog/rest/iceberg_rest_export.h"
27+
#include "iceberg/catalog/rest/type_fwd.h"
28+
#include "iceberg/result.h"
29+
#include "iceberg/type_fwd.h"
30+
31+
/// \file iceberg/catalog/rest/auth/auth_manager.h
32+
/// \brief Authentication manager interface for REST catalog.
33+
34+
namespace iceberg::rest::auth {
35+
36+
/// \brief Produces authentication sessions for catalog and table requests.
37+
class ICEBERG_REST_EXPORT AuthManager {
38+
public:
39+
virtual ~AuthManager() = default;
40+
41+
/// \brief Create a short-lived session used to contact the configuration endpoint.
42+
///
43+
/// This session is used only during catalog initialization to fetch server
44+
/// configuration and perform initial authentication. It is typically discarded after
45+
/// initialization.
46+
///
47+
/// \param init_client HTTP client used for initialization requests.
48+
/// \param properties Client configuration supplied by the catalog.
49+
/// \return Session for initialization or an error if credentials cannot be acquired.
50+
virtual Result<std::shared_ptr<AuthSession>> InitSession(
51+
HttpClient& init_client,
52+
const std::unordered_map<std::string, std::string>& properties);
53+
54+
/// \brief Create the long-lived catalog session that acts as the parent session.
55+
///
56+
/// This session is used for all catalog-level operations (list namespaces, list tables,
57+
/// etc.) and serves as the parent session for contextual and table-specific sessions.
58+
/// It is owned by the catalog and reused throughout the catalog's lifetime.
59+
///
60+
/// \param shared_client HTTP client owned by the catalog and reused for auth calls.
61+
/// \param properties Catalog properties (client config + server defaults).
62+
/// \return Session for catalog operations or an error if authentication cannot be set
63+
/// up.
64+
virtual Result<std::shared_ptr<AuthSession>> CatalogSession(
65+
HttpClient& shared_client,
66+
const std::unordered_map<std::string, std::string>& properties) = 0;
67+
68+
/// \brief Create or reuse a session for a specific context.
69+
///
70+
/// This method is used by SessionCatalog to create sessions for different contexts
71+
/// (e.g., different users or tenants).
72+
///
73+
/// \param context Context properties (e.g., user credentials, tenant info).
74+
/// \param parent Catalog session to inherit from or return as-is.
75+
/// \return A context-specific session, or the parent session if no context-specific
76+
/// session is needed, or an error if session creation fails.
77+
virtual Result<std::shared_ptr<AuthSession>> ContextualSession(
78+
const std::unordered_map<std::string, std::string>& context,
79+
std::shared_ptr<AuthSession> parent);
80+
81+
/// \brief Create or reuse a session scoped to a single table/view.
82+
///
83+
/// This method is called when loading a table that may have table-specific auth
84+
/// properties returned by the server.
85+
///
86+
/// \param table Target table identifier.
87+
/// \param properties Table-specific auth properties returned by the server.
88+
/// \param parent Catalog or contextual session to inherit from or return as-is.
89+
/// \return A table-specific session, or the parent session if no table-specific
90+
/// session is needed, or an error if session creation fails.
91+
virtual Result<std::shared_ptr<AuthSession>> TableSession(
92+
const TableIdentifier& table,
93+
const std::unordered_map<std::string, std::string>& properties,
94+
std::shared_ptr<AuthSession> parent);
95+
96+
/// \brief Release resources held by the manager.
97+
///
98+
/// \return Status of the close operation.
99+
virtual Status Close() { return {}; }
100+
};
101+
102+
} // namespace iceberg::rest::auth
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/catalog/rest/auth/auth_managers.h"
21+
22+
#include <algorithm>
23+
#include <cctype>
24+
25+
#include "iceberg/catalog/rest/auth/auth_properties.h"
26+
#include "iceberg/util/string_util.h"
27+
28+
namespace iceberg::rest::auth {
29+
30+
namespace {
31+
32+
/// \brief Registry type for AuthManager factories with heterogeneous lookup support.
33+
using AuthManagerRegistry =
34+
std::unordered_map<std::string, AuthManagerFactory, StringHash, StringEqual>;
35+
36+
// Infer the authentication type from properties.
37+
std::string InferAuthType(
38+
const std::unordered_map<std::string, std::string>& properties) {
39+
auto it = properties.find(AuthProperties::kAuthType);
40+
if (it != properties.end() && !it->second.empty()) {
41+
return StringUtils::ToLower(it->second);
42+
}
43+
44+
// Infer from OAuth2 properties (credential or token)
45+
bool has_credential = properties.contains(AuthProperties::kOAuth2Credential);
46+
bool has_token = properties.contains(AuthProperties::kOAuth2Token);
47+
if (has_credential || has_token) {
48+
return AuthProperties::kAuthTypeOAuth2;
49+
}
50+
51+
return AuthProperties::kAuthTypeNone;
52+
}
53+
54+
// Get the global registry of auth manager factories.
55+
AuthManagerRegistry& GetRegistry() {
56+
static AuthManagerRegistry registry;
57+
return registry;
58+
}
59+
60+
} // namespace
61+
62+
void AuthManagers::Register(std::string_view auth_type, AuthManagerFactory factory) {
63+
GetRegistry()[StringUtils::ToLower(auth_type)] = std::move(factory);
64+
}
65+
66+
Result<std::unique_ptr<AuthManager>> AuthManagers::Load(
67+
std::string_view name,
68+
const std::unordered_map<std::string, std::string>& properties) {
69+
std::string auth_type = InferAuthType(properties);
70+
71+
auto& registry = GetRegistry();
72+
auto it = registry.find(auth_type);
73+
if (it == registry.end()) {
74+
// TODO(Li Shuxu): Fallback to default auth manager implementations
75+
return NotImplemented("Authentication type '{}' is not supported", auth_type);
76+
}
77+
78+
return it->second(name, properties);
79+
}
80+
81+
} // namespace iceberg::rest::auth
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
#include <functional>
23+
#include <memory>
24+
#include <string>
25+
#include <string_view>
26+
#include <unordered_map>
27+
28+
#include "iceberg/catalog/rest/auth/auth_manager.h"
29+
#include "iceberg/catalog/rest/iceberg_rest_export.h"
30+
#include "iceberg/result.h"
31+
32+
/// \file iceberg/catalog/rest/auth/auth_managers.h
33+
/// \brief Factory for creating authentication managers.
34+
35+
namespace iceberg::rest::auth {
36+
37+
/// \brief Function that creates an AuthManager from its name.
38+
///
39+
/// \param name Name of the auth manager.
40+
/// \param properties Properties required by the auth manager.
41+
/// \return Newly created manager instance or an error if creation fails.
42+
using AuthManagerFactory = std::function<Result<std::unique_ptr<AuthManager>>(
43+
std::string_view name,
44+
const std::unordered_map<std::string, std::string>& properties)>;
45+
46+
/// \brief Registry-backed factory for AuthManager implementations.
47+
class ICEBERG_REST_EXPORT AuthManagers {
48+
public:
49+
/// \brief Load a manager by consulting the "rest.auth.type" configuration.
50+
///
51+
/// \param name Name of the auth manager.
52+
/// \param properties Catalog properties used to determine auth type.
53+
/// \return Manager instance or an error if no factory matches.
54+
static Result<std::unique_ptr<AuthManager>> Load(
55+
std::string_view name,
56+
const std::unordered_map<std::string, std::string>& properties);
57+
58+
/// \brief Register or override the factory for a given auth type.
59+
///
60+
/// This method is not thread-safe. All registrations should be done during
61+
/// application startup before any concurrent access to Load().
62+
///
63+
/// \param auth_type Case-insensitive type identifier (e.g., "basic").
64+
/// \param factory Factory function that produces the manager.
65+
static void Register(std::string_view auth_type, AuthManagerFactory factory);
66+
};
67+
68+
} // namespace iceberg::rest::auth

0 commit comments

Comments
 (0)