Skip to content

Commit bc398e6

Browse files
committed
Add RemoteS3ConnectionProvider plugin implementations
1 parent 00c4af6 commit bc398e6

14 files changed

+653
-1
lines changed

trino-aws-proxy-spi/src/main/java/io/trino/aws/proxy/spi/credentials/CredentialsProvider.java

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import java.util.Optional;
1717

18-
// TODO: Add back file-based provider
1918
public interface CredentialsProvider
2019
{
2120
CredentialsProvider NOOP = (_, _) -> Optional.empty();

trino-aws-proxy-spi/src/main/java/io/trino/aws/proxy/spi/remote/RemoteS3Connection.java

+5
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,9 @@ public record RemoteS3Connection(
3232
requireNonNull(remoteSessionRole, "remoteSessionRole is null");
3333
remoteS3FacadeConfiguration = requireNonNull(remoteS3FacadeConfiguration, "remoteS3FacadeConfiguration is null").map(ImmutableMap::copyOf);
3434
}
35+
36+
public RemoteS3Connection(Credential remoteCredential)
37+
{
38+
this(remoteCredential, Optional.empty(), Optional.empty());
39+
}
3540
}

trino-aws-proxy/src/main/java/io/trino/aws/proxy/server/TrinoAwsProxyServerModule.java

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
import io.trino.aws.proxy.server.credentials.http.HttpCredentialsModule;
3535
import io.trino.aws.proxy.server.remote.DefaultRemoteS3Module;
3636
import io.trino.aws.proxy.server.remote.RemoteS3ConnectionController;
37+
import io.trino.aws.proxy.server.remote.provider.config.ConfigRemoteS3ConnectionProviderModule;
38+
import io.trino.aws.proxy.server.remote.provider.file.FileBasedRemoteS3ConnectionModule;
39+
import io.trino.aws.proxy.server.remote.provider.http.HttpRemoteS3ConnectionProviderConfigModule;
3740
import io.trino.aws.proxy.server.rest.LimitStreamController;
3841
import io.trino.aws.proxy.server.rest.ResourceSecurityDynamicFeature;
3942
import io.trino.aws.proxy.server.rest.RestModule;
@@ -140,6 +143,9 @@ protected void setup(Binder binder)
140143
install(new FileBasedCredentialsModule());
141144
install(new OpaS3SecurityModule());
142145
install(new HttpCredentialsModule());
146+
install(new FileBasedRemoteS3ConnectionModule());
147+
install(new ConfigRemoteS3ConnectionProviderModule());
148+
install(new HttpRemoteS3ConnectionProviderConfigModule());
143149

144150
// RemoteS3 binder
145151
newOptionalBinder(binder, RemoteS3Facade.class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.config;
15+
16+
import io.airlift.configuration.Config;
17+
import io.airlift.configuration.ConfigSecuritySensitive;
18+
import jakarta.validation.constraints.NotEmpty;
19+
import jakarta.validation.constraints.NotNull;
20+
21+
public class ConfigRemoteS3ConnectionProviderConfig
22+
{
23+
private String accessKey;
24+
private String secretKey;
25+
26+
@NotNull
27+
@NotEmpty
28+
public String getAccessKey()
29+
{
30+
return accessKey;
31+
}
32+
33+
@Config("remote-s3-connection-provider.access-key")
34+
public ConfigRemoteS3ConnectionProviderConfig setAccessKey(String accessKey)
35+
{
36+
this.accessKey = accessKey;
37+
return this;
38+
}
39+
40+
@NotNull
41+
@NotEmpty
42+
public String getSecretKey()
43+
{
44+
return secretKey;
45+
}
46+
47+
@ConfigSecuritySensitive
48+
@Config("remote-s3-connection-provider.access-key")
49+
public ConfigRemoteS3ConnectionProviderConfig setSecretKey(String secretKey)
50+
{
51+
this.secretKey = secretKey;
52+
return this;
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.config;
15+
16+
import com.google.inject.Binder;
17+
import io.airlift.configuration.AbstractConfigurationAwareModule;
18+
import io.trino.aws.proxy.spi.credentials.Credential;
19+
import io.trino.aws.proxy.spi.plugin.config.RemoteS3ConnectionProviderConfig;
20+
import io.trino.aws.proxy.spi.remote.RemoteS3Connection;
21+
import io.trino.aws.proxy.spi.remote.RemoteS3ConnectionProvider;
22+
23+
import java.util.Optional;
24+
25+
import static com.google.inject.multibindings.OptionalBinder.newOptionalBinder;
26+
import static io.airlift.configuration.ConditionalModule.conditionalModule;
27+
28+
public class ConfigRemoteS3ConnectionProviderModule
29+
extends AbstractConfigurationAwareModule
30+
{
31+
public static final String CONFIG_REMOTE_S3_CONNECTION_PROVIDER = "config";
32+
33+
@Override
34+
protected void setup(Binder binder)
35+
{
36+
install(conditionalModule(
37+
RemoteS3ConnectionProviderConfig.class,
38+
config -> config.getPluginIdentifier().map(CONFIG_REMOTE_S3_CONNECTION_PROVIDER::equals).orElse(false),
39+
innerBinder -> {
40+
ConfigRemoteS3ConnectionProviderConfig config = buildConfigObject(ConfigRemoteS3ConnectionProviderConfig.class);
41+
newOptionalBinder(innerBinder, RemoteS3ConnectionProvider.class)
42+
.setBinding()
43+
.toInstance((_, _, _) -> Optional.of(new RemoteS3Connection(new Credential(config.getAccessKey(), config.getSecretKey()))));
44+
}));
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.file;
15+
16+
import com.google.inject.Binder;
17+
import io.airlift.configuration.AbstractConfigurationAwareModule;
18+
import io.trino.aws.proxy.spi.remote.RemoteS3Connection;
19+
20+
import static io.airlift.configuration.ConfigBinder.configBinder;
21+
import static io.airlift.json.JsonCodecBinder.jsonCodecBinder;
22+
import static io.trino.aws.proxy.spi.plugin.TrinoAwsProxyServerBinding.remoteS3ConnectionProviderModule;
23+
24+
public class FileBasedRemoteS3ConnectionModule
25+
extends AbstractConfigurationAwareModule
26+
{
27+
// set as config value for "remote-s3-connection-provider.type"
28+
public static final String FILE_BASED_REMOTE_S3_CONNECTION_PROVIDER = "file";
29+
30+
@Override
31+
protected void setup(Binder binder)
32+
{
33+
install(remoteS3ConnectionProviderModule(
34+
FILE_BASED_REMOTE_S3_CONNECTION_PROVIDER,
35+
FileBasedRemoteS3ConnectionProvider.class,
36+
innerBinder -> {
37+
configBinder(innerBinder).bindConfig(FileBasedRemoteS3ConnectionProviderConfig.class);
38+
innerBinder.bind(FileBasedRemoteS3ConnectionProvider.class);
39+
jsonCodecBinder(innerBinder).bindMapJsonCodec(String.class, RemoteS3Connection.class);
40+
}));
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.file;
15+
16+
import com.google.common.io.Files;
17+
import com.google.inject.Inject;
18+
import io.airlift.json.JsonCodec;
19+
import io.trino.aws.proxy.spi.credentials.Identity;
20+
import io.trino.aws.proxy.spi.remote.RemoteS3Connection;
21+
import io.trino.aws.proxy.spi.remote.RemoteS3ConnectionProvider;
22+
import io.trino.aws.proxy.spi.rest.ParsedS3Request;
23+
import io.trino.aws.proxy.spi.signing.SigningMetadata;
24+
25+
import java.util.Map;
26+
import java.util.Optional;
27+
28+
/**
29+
* <p>File-based RemoteS3ConnectionProvider that reads a JSON file containing a mapping from emulated access key to
30+
* RemoteS3Connection.</p>
31+
* <pre>{@code
32+
* {
33+
* "emulated-access-key-1": {
34+
* "remoteCredential": {
35+
* "accessKey": "remote-access-key",
36+
* "secretKey": "remote-secret-key"
37+
* },
38+
* "remoteSessionRole": {
39+
* "region": "us-east-1",
40+
* "roleArn": "arn:aws:iam::123456789012:role/role-name",
41+
* "externalId": "external-id",
42+
* "stsEndpoint": "https://sts.us-east-1.amazonaws.com"
43+
* },
44+
* "remoteS3FacadeConfiguration": {
45+
* "remoteS3.https": true,
46+
* "remoteS3.domain": "s3.amazonaws.com",
47+
* "remoteS3.port": 443,
48+
* "remoteS3.virtual-host-style": false,
49+
* "remoteS3.hostname.template": "${domain}"
50+
* }
51+
* }
52+
* }
53+
* }</pre>
54+
*/
55+
public class FileBasedRemoteS3ConnectionProvider
56+
implements RemoteS3ConnectionProvider
57+
{
58+
private final Map<String, RemoteS3Connection> remoteS3Connections;
59+
60+
@Inject
61+
public FileBasedRemoteS3ConnectionProvider(FileBasedRemoteS3ConnectionProviderConfig config, JsonCodec<Map<String, RemoteS3Connection>> jsonCodec)
62+
{
63+
try {
64+
this.remoteS3Connections = jsonCodec.fromJson(Files.toByteArray(config.getConnectionsFile()));
65+
}
66+
catch (Exception e) {
67+
throw new RuntimeException("Failed to read remote S3 connections file", e);
68+
}
69+
}
70+
71+
@Override
72+
public Optional<RemoteS3Connection> remoteConnection(SigningMetadata signingMetadata, Optional<Identity> identity, ParsedS3Request request)
73+
{
74+
return Optional.ofNullable(remoteS3Connections.get(signingMetadata.credential().accessKey()));
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.file;
15+
16+
import io.airlift.configuration.Config;
17+
import io.airlift.configuration.validation.FileExists;
18+
import jakarta.validation.constraints.NotNull;
19+
20+
import java.io.File;
21+
22+
public class FileBasedRemoteS3ConnectionProviderConfig
23+
{
24+
private File connectionsFile;
25+
26+
@NotNull
27+
@FileExists
28+
public File getConnectionsFile()
29+
{
30+
return connectionsFile;
31+
}
32+
33+
@Config("remote-s3.connections-file-path")
34+
public FileBasedRemoteS3ConnectionProviderConfig setConnectionsFile(File connectionsFile)
35+
{
36+
this.connectionsFile = connectionsFile;
37+
return this;
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.aws.proxy.server.remote.provider.http;
15+
16+
import com.google.inject.BindingAnnotation;
17+
18+
import java.lang.annotation.Retention;
19+
import java.lang.annotation.Target;
20+
21+
import static java.lang.annotation.ElementType.FIELD;
22+
import static java.lang.annotation.ElementType.METHOD;
23+
import static java.lang.annotation.ElementType.PARAMETER;
24+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
25+
26+
@BindingAnnotation
27+
@Target({FIELD, PARAMETER, METHOD})
28+
@Retention(RUNTIME)
29+
public @interface ForHttpRemoteS3ConnectionProvider
30+
{
31+
}

0 commit comments

Comments
 (0)