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
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ project(':iceberg-core') {
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
}

// OAuth2
implementation libs.nimbus.oauth2.oidc.sdk
implementation libs.nimbus.jose.jwt

testImplementation libs.jetty.servlet
testImplementation libs.jakarta.servlet
testImplementation libs.jetty.server
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ public static Consumer<ErrorResponse> defaultErrorHandler() {
return DefaultErrorHandler.INSTANCE;
}

/**
* The OAuth error handler.
*
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Manager} instead.
*/
@Deprecated
public static Consumer<ErrorResponse> oauthErrorHandler() {
return OAuthErrorHandler.INSTANCE;
}
Expand Down Expand Up @@ -339,6 +346,11 @@ public void accept(ErrorResponse error) {
}
}

/**
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Manager} instead.
*/
@Deprecated
private static class OAuthErrorHandler extends ErrorHandler {
private static final ErrorHandler INSTANCE = new OAuthErrorHandler();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@
/**
* The purpose of this class is to hold OAuth configuration options for {@link
* OAuth2Util.AuthSession}.
*
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Config} instead.
*/
@Value.Style(redactedMask = "****")
@Value.Immutable
@SuppressWarnings({"ImmutablesStyle", "SafeLoggingPropagation"})
@Deprecated
public interface AuthConfig {
@Nullable
@Value.Redacted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,16 @@ public static AuthManager loadAuthManager(String name, Map<String, String> prope
impl = authType;
}

LOG.info("Loading AuthManager implementation: {}", impl);
if (impl.equals(AuthProperties.AUTH_MANAGER_IMPL_OAUTH2_LEGACY)) {
LOG.warn(
"The AuthManager implementation {} is deprecated and will be removed in a future release. "
+ "Please migrate to {}.",
AuthProperties.AUTH_MANAGER_IMPL_OAUTH2_LEGACY,
AuthProperties.AUTH_MANAGER_IMPL_OAUTH2_NEW);
} else {
LOG.info("Loading AuthManager implementation: {}", impl);
}

DynConstructors.Ctor<AuthManager> ctor;
try {
ctor =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ private AuthProperties() {}
"org.apache.iceberg.rest.auth.NoopAuthManager";
public static final String AUTH_MANAGER_IMPL_BASIC =
"org.apache.iceberg.rest.auth.BasicAuthManager";
public static final String AUTH_MANAGER_IMPL_OAUTH2 =
static final String AUTH_MANAGER_IMPL_OAUTH2_LEGACY =
"org.apache.iceberg.rest.auth.OAuth2Manager";
static final String AUTH_MANAGER_IMPL_OAUTH2_NEW =
"org.apache.iceberg.rest.auth.oauth2.OAuth2Manager";
public static final String AUTH_MANAGER_IMPL_OAUTH2 =
AUTH_MANAGER_IMPL_OAUTH2_LEGACY; // TODO switch to new manager
public static final String AUTH_MANAGER_IMPL_SIGV4 =
"org.apache.iceberg.aws.RESTSigV4AuthManager";
public static final String AUTH_MANAGER_IMPL_GOOGLE =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** A cache for {@link AuthSession} instances. */
/**
* A cache for {@link AuthSession} instances.
*
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Manager} instead.
*/
@Deprecated
public class AuthSessionCache implements AutoCloseable {

private static final Logger LOG = LoggerFactory.getLogger(AuthSessionCache.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
*/
package org.apache.iceberg.rest.auth;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
import org.apache.iceberg.rest.HTTPHeaders;
import org.apache.iceberg.rest.RESTClient;

Expand All @@ -43,7 +46,12 @@ public AuthSession catalogSession(RESTClient sharedClient, Map<String, String> p
String username = properties.get(AuthProperties.BASIC_USERNAME);
String password = properties.get(AuthProperties.BASIC_PASSWORD);
String credentials = username + ":" + password;
return DefaultAuthSession.of(HTTPHeaders.of(OAuth2Util.basicAuthHeaders(credentials)));
// Note: RFC 7617 specifies ISO-8859-1 as the default encoding for Basic authentication
// credentials. This implementation uses UTF-8 for backwards compatibility.
String encoded =
Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
return DefaultAuthSession.of(
HTTPHeaders.of(ImmutableMap.of("Authorization", "Basic " + encoded)));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Manager} instead.
*/
@Deprecated
public class OAuth2Manager implements AuthManager {

private static final Logger LOG = LoggerFactory.getLogger(OAuth2Manager.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
*/
package org.apache.iceberg.rest.auth;

/**
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Config} instead.
*/
@Deprecated
public class OAuth2Properties {
private OAuth2Properties() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @deprecated will be removed in 1.14.0, use {@link
* org.apache.iceberg.rest.auth.oauth2.OAuth2Manager} instead.
*/
@Deprecated
public class OAuth2Util {
private OAuth2Util() {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.
*/
package org.apache.iceberg.rest.auth.oauth2;

import com.nimbusds.oauth2.sdk.GrantType;
import java.util.Map;
import org.apache.iceberg.rest.auth.oauth2.config.BasicConfig;
import org.apache.iceberg.rest.auth.oauth2.config.ConfigValidator;
import org.apache.iceberg.rest.auth.oauth2.config.ImmutableTokenExchangeConfig;
import org.apache.iceberg.rest.auth.oauth2.config.ImmutableTokenRefreshConfig;
import org.apache.iceberg.rest.auth.oauth2.config.TokenExchangeConfig;
import org.apache.iceberg.rest.auth.oauth2.config.TokenRefreshConfig;
import org.immutables.value.Value;

/** The configuration for the OAuth2 AuthManager. */
@Value.Immutable
public interface OAuth2Config {

String PREFIX = "rest.auth.oauth2.";

/**
* The basic configuration, including token endpoint, grant type, client id and client secret.
* Required.
*/
BasicConfig basicConfig();

/** The token refresh configuration. Optional. */
@Value.Default
default TokenRefreshConfig tokenRefreshConfig() {
return ImmutableTokenRefreshConfig.builder().build();
}

/**
* The token exchange configuration. Required for the {@link GrantType#TOKEN_EXCHANGE} grant type.
*/
@Value.Default
default TokenExchangeConfig tokenExchangeConfig() {
return ImmutableTokenExchangeConfig.builder().build();
}

@Value.Check
default void validate() {
// At this level, we only need to validate constraints that span multiple
// configuration classes; individual configuration classes are validated
// internally in their respective validate() methods.
ConfigValidator validator = new ConfigValidator();

if (basicConfig().grantType().equals(GrantType.TOKEN_EXCHANGE)) {
validator.check(
tokenExchangeConfig().subjectTokenString().isPresent(),
TokenExchangeConfig.SUBJECT_TOKEN,
"subject token must be set if grant type is '%s'",
GrantType.TOKEN_EXCHANGE.getValue());
}

validator.validate();
}

/** Creates an {@link OAuth2Config} from the given properties map. */
static OAuth2Config of(Map<String, String> properties) {
return ImmutableOAuth2Config.builder()
.basicConfig(BasicConfig.parse(properties).build())
.tokenRefreshConfig(TokenRefreshConfig.parse(properties).build())
.tokenExchangeConfig(TokenExchangeConfig.parse(properties).build())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.
*/
package org.apache.iceberg.rest.auth.oauth2;

import java.util.Map;
import org.apache.iceberg.catalog.SessionCatalog.SessionContext;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.rest.RESTClient;
import org.apache.iceberg.rest.auth.AuthManager;
import org.apache.iceberg.rest.auth.AuthSession;

public class OAuth2Manager implements AuthManager {

public OAuth2Manager(String name) {}

@Override
public AuthSession initSession(RESTClient initClient, Map<String, String> initProperties) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public AuthSession catalogSession(
RESTClient sharedClient, Map<String, String> catalogProperties) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public AuthSession contextualSession(SessionContext context, AuthSession parent) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public AuthSession tableSession(
TableIdentifier table, Map<String, String> properties, AuthSession parent) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public AuthSession tableSession(RESTClient sharedClient, Map<String, String> properties) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public void close() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.
*/
package org.apache.iceberg.rest.auth.oauth2;

import org.apache.iceberg.rest.HTTPRequest;
import org.apache.iceberg.rest.auth.AuthSession;

public class OAuth2Session implements AuthSession {

private final OAuth2Config config;

public OAuth2Session(OAuth2Config config) {
this.config = config;
}

public OAuth2Config config() {
return config;
}

@Override
public HTTPRequest authenticate(HTTPRequest request) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public void close() {}
}
Loading
Loading