Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add S3 Http Proxy configuration support #11255

Merged
merged 1 commit into from
Mar 3, 2022
Merged
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
16 changes: 16 additions & 0 deletions docs/src/main/sphinx/connector/hive-s3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ Property Name Description
without staging file to be created in the local file system.

``hive.s3.streaming.part-size`` The part size for S3 streaming upload. Defaults to ``16MB``.

``hive.s3.proxy.host`` Proxy host to use if connecting through a proxy

``hive.s3.proxy.port`` Proxy port to use if connecting through a proxy

``hive.s3.proxy.protocol`` Proxy protocol. HTTP or HTTPS , defaults to ``HTTPS``.

``hive.s3.proxy.non-proxy-hosts`` Hosts list to access without going through the proxy.

``hive.s3.proxy.username`` Proxy user name to use if connecting through a proxy

``hive.s3.proxy.password`` Proxy password name to use if connecting through a proxy

``hive.s3.proxy.preemptive-basic-auth`` Whether to attempt to authenticate preemptively against proxy
when using base authorization, defaults to ``false``.

============================================ =================================================================

.. _hive-s3-credentials:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package io.trino.plugin.hive.s3;

import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.ImmutableList;
import io.airlift.configuration.Config;
import io.airlift.configuration.ConfigDescription;
import io.airlift.configuration.ConfigSecuritySensitive;
Expand All @@ -29,9 +30,12 @@
import javax.validation.constraints.NotNull;

import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static io.airlift.units.DataSize.Unit.MEGABYTE;
import static java.util.Locale.ENGLISH;
import static java.util.Objects.requireNonNull;

@DefunctConfig("hive.s3.use-instance-credentials")
public class HiveS3Config
Expand Down Expand Up @@ -68,6 +72,13 @@ public class HiveS3Config
private boolean requesterPaysEnabled;
private boolean s3StreamingUploadEnabled = true;
private DataSize s3StreamingPartSize = DataSize.of(16, MEGABYTE);
private String s3proxyHost;
private Integer s3proxyPort = -1;
private TrinoS3Protocol s3ProxyProtocol = TrinoS3Protocol.HTTPS;
private List<String> s3nonProxyHosts = ImmutableList.of();
private String s3proxyUsername;
private String s3proxyPassword;
private boolean s3preemptiveBasicProxyAuth;

public String getS3AwsAccessKey()
{
Expand Down Expand Up @@ -493,4 +504,90 @@ public HiveS3Config setS3StreamingPartSize(DataSize s3StreamingPartSize)
this.s3StreamingPartSize = s3StreamingPartSize;
return this;
}

public String getS3ProxyHost()
{
return s3proxyHost;
}

@Config("hive.s3.proxy.host")
public HiveS3Config setS3ProxyHost(String s3proxyHost)
{
this.s3proxyHost = s3proxyHost;
return this;
}

public int getS3ProxyPort()
{
return s3proxyPort;
}

@Config("hive.s3.proxy.port")
public HiveS3Config setS3ProxyPort(int s3proxyPort)
{
this.s3proxyPort = s3proxyPort;
return this;
}

public TrinoS3Protocol getS3ProxyProtocol()
{
return s3ProxyProtocol;
}

@Config("hive.s3.proxy.protocol")
public HiveS3Config setS3ProxyProtocol(String s3ProxyProtocol)
{
this.s3ProxyProtocol = TrinoS3Protocol.valueOf(
requireNonNull(s3ProxyProtocol, "s3ProxyProtocol is null")
.toUpperCase(ENGLISH));
return this;
}

public List<String> getS3NonProxyHosts()
{
return s3nonProxyHosts;
}

@Config("hive.s3.proxy.non-proxy-hosts")
public HiveS3Config setS3NonProxyHosts(List<String> s3nonProxyHosts)
{
this.s3nonProxyHosts = ImmutableList.copyOf(s3nonProxyHosts);
return this;
}

public String getS3ProxyUsername()
{
return s3proxyUsername;
}

@Config("hive.s3.proxy.username")
public HiveS3Config setS3ProxyUsername(String s3proxyUsername)
{
this.s3proxyUsername = s3proxyUsername;
return this;
}

public String getS3ProxyPassword()
{
return s3proxyPassword;
}

@Config("hive.s3.proxy.password")
public HiveS3Config setS3ProxyPassword(String s3proxyPassword)
{
this.s3proxyPassword = s3proxyPassword;
return this;
}

public boolean getS3PreemptiveBasicProxyAuth()
{
return s3preemptiveBasicProxyAuth;
}

@Config("hive.s3.proxy.preemptive-basic-auth")
public HiveS3Config setS3PreemptiveBasicProxyAuth(boolean s3preemptiveBasicProxyAuth)
{
this.s3preemptiveBasicProxyAuth = s3preemptiveBasicProxyAuth;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.inject.Inject;

import java.io.File;
import java.util.List;

import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_ACCESS_KEY;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_ACL_TYPE;
Expand All @@ -37,8 +38,15 @@
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_MAX_RETRY_TIME;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_MULTIPART_MIN_FILE_SIZE;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_MULTIPART_MIN_PART_SIZE;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_NON_PROXY_HOSTS;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PATH_STYLE_ACCESS;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PIN_CLIENT_TO_CURRENT_REGION;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PREEMPTIVE_BASIC_PROXY_AUTH;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PROXY_HOST;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PROXY_PASSWORD;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PROXY_PORT;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PROXY_PROTOCOL;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_PROXY_USERNAME;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_REQUESTER_PAYS_ENABLED;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_SECRET_KEY;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_SIGNER_CLASS;
Expand All @@ -54,6 +62,7 @@
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_STREAMING_UPLOAD_ENABLED;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_STREAMING_UPLOAD_PART_SIZE;
import static io.trino.plugin.hive.s3.TrinoS3FileSystem.S3_USER_AGENT_PREFIX;
import static java.util.stream.Collectors.joining;

public class TrinoS3ConfigurationInitializer
implements ConfigurationInitializer
Expand Down Expand Up @@ -90,6 +99,13 @@ public class TrinoS3ConfigurationInitializer
private final boolean skipGlacierObjects;
private final boolean s3StreamingUploadEnabled;
private final DataSize streamingPartSize;
private final String s3proxyHost;
private final int s3proxyPort;
private final TrinoS3Protocol s3ProxyProtocol;
private final List<String> s3nonProxyHosts;
private final String s3proxyUsername;
private final String s3proxyPassword;
private final boolean s3preemptiveBasicProxyAuth;

@Inject
public TrinoS3ConfigurationInitializer(HiveS3Config config)
Expand Down Expand Up @@ -126,6 +142,13 @@ public TrinoS3ConfigurationInitializer(HiveS3Config config)
this.requesterPaysEnabled = config.isRequesterPaysEnabled();
this.s3StreamingUploadEnabled = config.isS3StreamingUploadEnabled();
this.streamingPartSize = config.getS3StreamingPartSize();
this.s3proxyHost = config.getS3ProxyHost();
this.s3proxyPort = config.getS3ProxyPort();
this.s3ProxyProtocol = config.getS3ProxyProtocol();
this.s3nonProxyHosts = config.getS3NonProxyHosts();
this.s3proxyUsername = config.getS3ProxyUsername();
this.s3proxyPassword = config.getS3ProxyPassword();
this.s3preemptiveBasicProxyAuth = config.getS3PreemptiveBasicProxyAuth();
}

@Override
Expand Down Expand Up @@ -188,5 +211,24 @@ public void initializeConfiguration(Configuration config)
config.setBoolean(S3_REQUESTER_PAYS_ENABLED, requesterPaysEnabled);
config.setBoolean(S3_STREAMING_UPLOAD_ENABLED, s3StreamingUploadEnabled);
config.setLong(S3_STREAMING_UPLOAD_PART_SIZE, streamingPartSize.toBytes());
if (s3proxyHost != null) {
config.set(S3_PROXY_HOST, s3proxyHost);
}
if (s3proxyPort > -1) {
config.setInt(S3_PROXY_PORT, s3proxyPort);
}
if (s3ProxyProtocol != null) {
config.set(S3_PROXY_PROTOCOL, s3ProxyProtocol.name());
}
if (s3nonProxyHosts != null) {
config.set(S3_NON_PROXY_HOSTS, s3nonProxyHosts.stream().collect(joining("|")));
}
if (s3proxyUsername != null) {
config.set(S3_PROXY_USERNAME, s3proxyUsername);
}
if (s3proxyPassword != null) {
config.set(S3_PROXY_PASSWORD, s3proxyPassword);
}
config.setBoolean(S3_PREEMPTIVE_BASIC_PROXY_AUTH, s3preemptiveBasicProxyAuth);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.nio.file.Files.createDirectories;
import static java.nio.file.Files.createTempFile;
import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static java.util.concurrent.TimeUnit.SECONDS;
Expand Down Expand Up @@ -196,6 +197,13 @@ public class TrinoS3FileSystem
public static final String S3_STREAMING_UPLOAD_PART_SIZE = "trino.s3.streaming.part-size";
public static final String S3_STORAGE_CLASS = "trino.s3.storage-class";
public static final String S3_ROLE_SESSION_NAME = "trino.s3.role-session-name";
public static final String S3_PROXY_HOST = "trino.s3.proxy.host";
public static final String S3_PROXY_PORT = "trino.s3.proxy.port";
public static final String S3_PROXY_PROTOCOL = "trino.s3.proxy.protocol";
public static final String S3_NON_PROXY_HOSTS = "trino.s3.proxy.non-proxy-hosts";
public static final String S3_PROXY_USERNAME = "trino.s3.proxy.username";
public static final String S3_PROXY_PASSWORD = "trino.s3.proxy.password";
public static final String S3_PREEMPTIVE_BASIC_PROXY_AUTH = "trino.s3.proxy.preemptive-basic-auth";

private static final Logger log = Logger.get(TrinoS3FileSystem.class);
private static final TrinoS3FileSystemStats STATS = new TrinoS3FileSystemStats();
Expand Down Expand Up @@ -294,6 +302,30 @@ public void initialize(URI uri, Configuration conf)
.withUserAgentPrefix(userAgentPrefix)
.withUserAgentSuffix("Trino");

String proxyHost = conf.get(S3_PROXY_HOST);
if (nonNull(proxyHost)) {
configuration.setProxyHost(proxyHost);
configuration.setProxyPort(conf.getInt(S3_PROXY_PORT, defaults.getS3ProxyPort()));
String proxyProtocol = conf.get(S3_PROXY_PROTOCOL);
if (proxyProtocol != null) {
configuration.setProxyProtocol(TrinoS3Protocol.valueOf(proxyProtocol).getProtocol());
}
String nonProxyHosts = conf.get(S3_NON_PROXY_HOSTS);
if (nonProxyHosts != null) {
configuration.setNonProxyHosts(nonProxyHosts);
}
String proxyUsername = conf.get(S3_PROXY_USERNAME);
if (proxyUsername != null) {
configuration.setProxyUsername(proxyUsername);
}
String proxyPassword = conf.get(S3_PROXY_PASSWORD);
if (proxyPassword != null) {
configuration.setProxyPassword(proxyPassword);
}
configuration.setPreemptiveBasicProxyAuth(
conf.getBoolean(S3_PREEMPTIVE_BASIC_PROXY_AUTH, defaults.getS3PreemptiveBasicProxyAuth()));
}

this.credentialsProvider = createAwsCredentialsProvider(uri, conf);
this.s3 = createAmazonS3Client(conf, configuration);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed 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 io.trino.plugin.hive.s3;

import com.amazonaws.Protocol;

public enum TrinoS3Protocol
{
HTTP(Protocol.HTTP),
HTTPS(Protocol.HTTPS);

private final Protocol protocol;

TrinoS3Protocol(Protocol protocol)
{
this.protocol = protocol;
}

public Protocol getProtocol()
{
return protocol;
}

@Override
public String toString()
{
return this.protocol.name();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package io.trino.plugin.hive.s3;

import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.airlift.units.DataSize;
import io.airlift.units.DataSize.Unit;
Expand Down Expand Up @@ -68,7 +69,14 @@ public void testDefaults()
.setSkipGlacierObjects(false)
.setRequesterPaysEnabled(false)
.setS3StreamingUploadEnabled(true)
.setS3StreamingPartSize(DataSize.of(16, Unit.MEGABYTE)));
.setS3StreamingPartSize(DataSize.of(16, Unit.MEGABYTE))
.setS3ProxyHost(null)
.setS3ProxyPort(-1)
.setS3ProxyProtocol("HTTPS")
.setS3NonProxyHosts(ImmutableList.of())
.setS3ProxyUsername(null)
.setS3ProxyPassword(null)
.setS3PreemptiveBasicProxyAuth(false));
}

@Test
Expand Down Expand Up @@ -110,6 +118,13 @@ public void testExplicitPropertyMappings()
.put("hive.s3.requester-pays.enabled", "true")
.put("hive.s3.streaming.enabled", "false")
.put("hive.s3.streaming.part-size", "15MB")
.put("hive.s3.proxy.host", "localhost")
.put("hive.s3.proxy.port", "14000")
.put("hive.s3.proxy.protocol", "HTTP")
.put("hive.s3.proxy.non-proxy-hosts", "test,test2,test3")
.put("hive.s3.proxy.username", "test")
.put("hive.s3.proxy.password", "test")
.put("hive.s3.proxy.preemptive-basic-auth", "true")
.buildOrThrow();

HiveS3Config expected = new HiveS3Config()
Expand Down Expand Up @@ -144,7 +159,14 @@ public void testExplicitPropertyMappings()
.setSkipGlacierObjects(true)
.setRequesterPaysEnabled(true)
.setS3StreamingUploadEnabled(false)
.setS3StreamingPartSize(DataSize.of(15, Unit.MEGABYTE));
.setS3StreamingPartSize(DataSize.of(15, Unit.MEGABYTE))
.setS3ProxyHost("localhost")
.setS3ProxyPort(14000)
.setS3ProxyProtocol("HTTP")
.setS3NonProxyHosts(ImmutableList.of("test", "test2", "test3"))
.setS3ProxyUsername("test")
.setS3ProxyPassword("test")
.setS3PreemptiveBasicProxyAuth(true);

assertFullMapping(properties, expected);
}
Expand Down
Loading