diff --git a/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java b/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
index dfbbc863851d9..64b92c3a21282 100644
--- a/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
+++ b/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
@@ -36,6 +36,7 @@
import com.facebook.presto.spi.connector.ConnectorSplitManager;
import com.facebook.presto.spi.connector.ConnectorSplitManager.SplitSchedulingContext;
import com.facebook.presto.spi.connector.ConnectorTransactionHandle;
+import com.facebook.presto.spi.security.ConnectorIdentity;
import com.facebook.presto.testing.TestingConnectorContext;
import com.facebook.presto.testing.TestingConnectorSession;
import com.google.common.collect.ImmutableList;
@@ -80,6 +81,7 @@ public class TestCassandraConnector
private static final Date DATE = new Date();
private static final ConnectorSession SESSION = new TestingConnectorSession(
"user",
+ new ConnectorIdentity("user", Optional.empty(), Optional.empty()),
Optional.of("test"),
Optional.empty(),
UTC_KEY,
diff --git a/presto-docs/src/main/sphinx/connector/hive.rst b/presto-docs/src/main/sphinx/connector/hive.rst
index bfb4dd9618961..869da01652b5f 100644
--- a/presto-docs/src/main/sphinx/connector/hive.rst
+++ b/presto-docs/src/main/sphinx/connector/hive.rst
@@ -383,6 +383,90 @@ or credentials for a specific use case (e.g., bucket/user specific credentials).
This Hadoop configuration property must be set in the Hadoop configuration
files referenced by the ``hive.config.resources`` Hive connector property.
+AWS Security Mapping
+^^^^^^^^^^^^^^^^^^^^
+
+Presto supports flexible mapping for AWS Lake Formation and AWS S3 API calls, allowing for separate
+credentials or IAM roles for specific users.
+
+The mappings can be of two types: ``S3`` or ``LAKEFORMATION``.
+
+The mapping entries are processed in the order listed in the configuration
+file. More specific mappings should be specified before less specific mappings.
+You can set default configuration by not including any match criteria for the last
+entry in the list.
+
+Each mapping entry when mapping type is ``S3`` may specify one match criteria. Available match criteria:
+
+* ``user``: Regular expression to match against username. Example: ``alice|bob``
+
+The mapping must provide one or more configuration settings:
+
+* ``accessKey`` and ``secretKey``: AWS access key and secret key. This overrides
+ any globally configured credentials, such as access key or instance credentials.
+
+* ``iamRole``: IAM role to use. This overrides any globally configured IAM role.
+
+Example JSON configuration file for s3:
+
+.. code-block:: json
+
+ {
+ "mappings": [
+ {
+ "user": "admin",
+ "accessKey": "AKIAxxxaccess",
+ "secretKey": "iXbXxxxsecret"
+ },
+ {
+ "user": "analyst|scientist",
+ "iamRole": "arn:aws:iam::123456789101:role/analyst_and_scientist_role"
+ },
+ {
+ "iamRole": "arn:aws:iam::123456789101:role/default"
+ }
+ ]
+ }
+
+Each mapping entry when mapping type is ``LAKEFORMATION`` may specify one match criteria. Available match criteria:
+
+* ``user``: Regular expression to match against username. Example: ``alice|bob``
+
+The mapping must provide one configuration setting:
+
+* ``iamRole``: IAM role to use. This overrides any globally configured IAM role.
+
+Example JSON configuration file for lakeformation:
+
+.. code-block:: json
+
+ {
+ "mappings": [
+ {
+ "user": "admin",
+ "iamRole": "arn:aws:iam::123456789101:role/admin_role"
+ },
+ {
+ "user": "analyst",
+ "iamRole": "arn:aws:iam::123456789101:role/analyst_role"
+ },
+ {
+ "iamRole": "arn:aws:iam::123456789101:role/default_role"
+ }
+ ]
+ }
+
+======================================================= =================================================================
+Property Name Description
+======================================================= =================================================================
+``hive.aws.security-mapping.type`` AWS Security Mapping Type. Possible values: S3 or LAKEFORMATION
+
+``hive.aws.security-mapping.config-file`` JSON configuration file containing AWS IAM Security mappings
+
+``hive.aws.security-mapping.refresh-period`` Time interval after which AWS IAM security mapping configuration
+ will be refreshed
+======================================================= =================================================================
+
Tuning Properties
^^^^^^^^^^^^^^^^^
diff --git a/presto-hive-common/pom.xml b/presto-hive-common/pom.xml
index 4e28ffce9e903..27b647d9a5cce 100644
--- a/presto-hive-common/pom.xml
+++ b/presto-hive-common/pom.xml
@@ -29,6 +29,11 @@
configuration
+
+ com.facebook.airlift
+ log
+
+
com.google.code.findbugs
jsr305
@@ -50,6 +55,11 @@
presto-orc
+
+ com.facebook.presto
+ presto-plugin-toolkit
+
+
com.facebook.presto.hadoop
hadoop-apache2
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMapping.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMapping.java
new file mode 100644
index 0000000000000..98987fa8c2923
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMapping.java
@@ -0,0 +1,81 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class AWSSecurityMapping
+{
+ private final Predicate user;
+ private final Optional iamRole;
+ private final Optional credentials;
+
+ @JsonCreator
+ public AWSSecurityMapping(
+ @JsonProperty("user") Optional user,
+ @JsonProperty("iamRole") Optional iamRole,
+ @JsonProperty("accessKey") Optional accessKey,
+ @JsonProperty("secretKey") Optional secretKey)
+ {
+ this.user = requireNonNull(user, "user is null")
+ .map(AWSSecurityMapping::toPredicate)
+ .orElse(x -> true);
+
+ this.iamRole = requireNonNull(iamRole, "iamRole is null");
+
+ requireNonNull(accessKey, "accessKey is null");
+ requireNonNull(secretKey, "secretKey is null");
+ checkArgument(accessKey.isPresent() == secretKey.isPresent(), "accessKey and secretKey must be provided together");
+ this.credentials = accessKey.map(access -> new BasicAWSCredentials(access, secretKey.get()));
+ }
+
+ public boolean matches(String user)
+ {
+ return this.user.test(user);
+ }
+
+ public Optional getIamRole()
+ {
+ return iamRole;
+ }
+
+ public Optional getCredentials()
+ {
+ return credentials;
+ }
+
+ @Override
+ public String toString()
+ {
+ return toStringHelper(this)
+ .add("user", user)
+ .add("iamRole", iamRole)
+ .add("credentials", credentials)
+ .toString();
+ }
+
+ private static Predicate toPredicate(Pattern pattern)
+ {
+ return value -> pattern.matcher(value).matches();
+ }
+}
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingConfig.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingConfig.java
new file mode 100644
index 0000000000000..e66bc59b757b2
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingConfig.java
@@ -0,0 +1,85 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.facebook.airlift.configuration.Config;
+import com.facebook.airlift.configuration.ConfigDescription;
+import io.airlift.units.Duration;
+import io.airlift.units.MinDuration;
+
+import javax.annotation.Nullable;
+import javax.validation.constraints.AssertTrue;
+
+import java.io.File;
+import java.util.Optional;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+public class AWSSecurityMappingConfig
+{
+ private static final String MAPPING_TYPE = "hive.aws.security-mapping.type";
+ private static final String CONFIG_FILE = "hive.aws.security-mapping.config-file";
+ private static final String REFRESH_PERIOD = "hive.aws.security-mapping.refresh-period";
+ private AWSSecurityMappingType mappingType;
+ private File configFile;
+ private Duration refreshPeriod = new Duration(30, SECONDS);
+
+ public AWSSecurityMappingType getMappingType()
+ {
+ return mappingType;
+ }
+
+ @Config(MAPPING_TYPE)
+ @ConfigDescription("AWS Security Mapping Type. Possible values: S3 or LAKEFORMATION")
+ public AWSSecurityMappingConfig setMappingType(AWSSecurityMappingType mappingType)
+ {
+ this.mappingType = mappingType;
+ return this;
+ }
+
+ public Optional getConfigFile()
+ {
+ return Optional.ofNullable(configFile);
+ }
+
+ @Nullable
+ @Config(CONFIG_FILE)
+ @ConfigDescription("JSON configuration file containing AWS IAM Security mappings")
+ public AWSSecurityMappingConfig setConfigFile(File configFile)
+ {
+ this.configFile = configFile;
+ return this;
+ }
+
+ public Duration getRefreshPeriod()
+ {
+ return refreshPeriod;
+ }
+
+ @MinDuration("0ms")
+ @Config(REFRESH_PERIOD)
+ @ConfigDescription("Time interval after which AWS IAM security mapping configuration will be refreshed")
+ public AWSSecurityMappingConfig setRefreshPeriod(Duration refreshPeriod)
+ {
+ this.refreshPeriod = requireNonNull(refreshPeriod, "refreshPeriod is null");
+ return this;
+ }
+
+ @AssertTrue(message = "MAPPING TYPE(" + MAPPING_TYPE + ") must be configured when AWS Security Mapping Config File(" + CONFIG_FILE + ") is set and vice versa")
+ public boolean isValidConfiguration()
+ {
+ return (getConfigFile().isPresent() && getMappingType() != null) || (!getConfigFile().isPresent() && getMappingType() == null);
+ }
+}
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingType.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingType.java
new file mode 100644
index 0000000000000..fdede13c3c375
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingType.java
@@ -0,0 +1,20 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+public enum AWSSecurityMappingType
+{
+ S3,
+ LAKEFORMATION,
+}
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappings.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappings.java
new file mode 100644
index 0000000000000..875d985a363fc
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappings.java
@@ -0,0 +1,66 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.facebook.presto.spi.security.AccessDeniedException;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Verify.verify;
+
+public class AWSSecurityMappings
+{
+ private final List awsSecurityMappings;
+
+ @JsonCreator
+ public AWSSecurityMappings(@JsonProperty("mappings") List awsSecurityMappings)
+ {
+ checkArgument(awsSecurityMappings != null, "No AWS Security mappings configured");
+
+ this.awsSecurityMappings = ImmutableList.copyOf(awsSecurityMappings);
+ }
+
+ public AWSSecurityMapping getAWSLakeFormationSecurityMapping(String user)
+ {
+ Optional awsSecurityMapping = awsSecurityMappings.stream()
+ .filter(mapping -> (mapping.matches(user)))
+ .findFirst();
+
+ if (!awsSecurityMapping.isPresent()) {
+ throw new AccessDeniedException("No matching AWS Lake Formation Security Mapping");
+ }
+
+ verify(!awsSecurityMapping.get().getCredentials().isPresent(),
+ "Basic AWS Credentials are not supported for AWS Lake Formation Security Mapping");
+
+ verify(awsSecurityMapping.get().getIamRole().isPresent(),
+ "iamRole is mandatory for AWS Lake Formation Security Mapping");
+
+ return awsSecurityMapping.get();
+ }
+
+ public AWSSecurityMapping getAWSS3SecurityMapping(String user)
+ {
+ Optional awsSecurityMapping = awsSecurityMappings.stream()
+ .filter(mapping -> mapping.matches(user))
+ .findFirst();
+
+ return awsSecurityMapping.orElseThrow(() -> new AccessDeniedException("No matching AWS S3 Security Mapping"));
+ }
+}
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingsSupplier.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingsSupplier.java
new file mode 100644
index 0000000000000..73d6052d01586
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/AWSSecurityMappingsSupplier.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.facebook.airlift.log.Logger;
+import com.google.common.base.Suppliers;
+import io.airlift.units.Duration;
+
+import java.io.File;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import static com.facebook.presto.plugin.base.JsonUtils.parseJson;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+public class AWSSecurityMappingsSupplier
+{
+ private static final Logger log = Logger.get(AWSSecurityMappingsSupplier.class);
+ private final Supplier mappingsSupplier;
+
+ public AWSSecurityMappingsSupplier(Optional configFile, Duration refreshPeriod)
+ {
+ requireNonNull(configFile, "configFile is null");
+ requireNonNull(refreshPeriod, "refreshPeriod is null");
+
+ this.mappingsSupplier = getMappings(configFile, refreshPeriod);
+ }
+
+ private static Supplier getMappings(Optional configFile, Duration refreshPeriod)
+ {
+ if (!configFile.isPresent()) {
+ return null;
+ }
+
+ checkArgument(configFile.get().exists() && configFile.get().isFile(), "AWS Security Mapping config file does not exist: %s", configFile.get());
+
+ Supplier supplier = () -> parseJson(configFile.get().toPath(), AWSSecurityMappings.class);
+
+ return Suppliers.memoizeWithExpiration(
+ () -> {
+ log.debug("Refreshing AWS security mapping configuration from %s", configFile);
+ return supplier.get();
+ },
+ refreshPeriod.toMillis(),
+ MILLISECONDS);
+ }
+
+ public Supplier getMappingsSupplier()
+ {
+ return mappingsSupplier;
+ }
+}
diff --git a/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/BasicAWSCredentials.java b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/BasicAWSCredentials.java
new file mode 100644
index 0000000000000..ecdca1b5c95e0
--- /dev/null
+++ b/presto-hive-common/src/main/java/com/facebook/presto/hive/aws/security/BasicAWSCredentials.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import static java.util.Objects.requireNonNull;
+
+public class BasicAWSCredentials
+{
+ private final String accessKey;
+ private final String secretKey;
+
+ public BasicAWSCredentials(String accessKey, String secretKey)
+ {
+ this.accessKey = requireNonNull(accessKey, "Access key cannot be null");
+ this.secretKey = requireNonNull(secretKey, "Secret key cannot be null");
+ }
+
+ public String getAWSAccessKeyId()
+ {
+ return this.accessKey;
+ }
+
+ public String getAWSSecretKey()
+ {
+ return this.secretKey;
+ }
+}
diff --git a/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappingConfig.java b/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappingConfig.java
new file mode 100644
index 0000000000000..c1d730d980ef4
--- /dev/null
+++ b/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappingConfig.java
@@ -0,0 +1,59 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.google.common.collect.ImmutableMap;
+import io.airlift.units.Duration;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+
+import static com.facebook.airlift.configuration.testing.ConfigAssertions.assertFullMapping;
+import static com.facebook.airlift.configuration.testing.ConfigAssertions.assertRecordedDefaults;
+import static com.facebook.airlift.configuration.testing.ConfigAssertions.recordDefaults;
+
+public class TestAWSSecurityMappingConfig
+{
+ @Test
+ public void testDefaults()
+ {
+ assertRecordedDefaults(recordDefaults(AWSSecurityMappingConfig.class)
+ .setMappingType(null)
+ .setConfigFile(null)
+ .setRefreshPeriod(Duration.valueOf("30s")));
+ }
+
+ @Test
+ public void testExplicitPropertyMappings()
+ throws IOException
+ {
+ Path securityMappingConfigFile = Files.createTempFile(null, null);
+
+ Map properties = new ImmutableMap.Builder()
+ .put("hive.aws.security-mapping.type", "S3")
+ .put("hive.aws.security-mapping.config-file", securityMappingConfigFile.toString())
+ .put("hive.aws.security-mapping.refresh-period", "60s")
+ .build();
+
+ AWSSecurityMappingConfig expected = new AWSSecurityMappingConfig()
+ .setMappingType(AWSSecurityMappingType.S3)
+ .setConfigFile(securityMappingConfigFile.toFile())
+ .setRefreshPeriod(Duration.valueOf("60s"));
+
+ assertFullMapping(properties, expected);
+ }
+}
diff --git a/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappings.java b/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappings.java
new file mode 100644
index 0000000000000..f5e8f060ae1b3
--- /dev/null
+++ b/presto-hive-common/src/test/java/com/facebook/presto/hive/aws/security/TestAWSSecurityMappings.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.facebook.presto.hive.aws.security;
+
+import com.google.common.base.VerifyException;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+import static com.facebook.presto.plugin.base.JsonUtils.parseJson;
+import static java.util.Objects.requireNonNull;
+import static org.testng.Assert.assertEquals;
+
+public class TestAWSSecurityMappings
+{
+ private static final String DEFAULT_USER = "defaultUser";
+
+ @Test
+ public void testValidAWSLakeFormationMapping()
+ {
+ String lakeFormationSecurityMappingConfigPath =
+ this.getClass().getClassLoader().getResource("com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-valid.json").getPath();
+
+ AWSSecurityMappings mappings = parseJson(new File(lakeFormationSecurityMappingConfigPath).toPath(), AWSSecurityMappings.class);
+
+ assertEquals(MappingResult.role("arn:aws:iam::123456789101:role/admin_role").getIamRole(),
+ mappings.getAWSLakeFormationSecurityMapping(MappingSelector.empty().withUser("admin").getUser()).getIamRole().get());
+ assertEquals(MappingResult.role("arn:aws:iam::123456789101:role/analyst_role").getIamRole(),
+ mappings.getAWSLakeFormationSecurityMapping(MappingSelector.empty().withUser("analyst").getUser()).getIamRole().get());
+ assertEquals(MappingResult.role("arn:aws:iam::123456789101:role/default_role").getIamRole(),
+ mappings.getAWSLakeFormationSecurityMapping(MappingSelector.empty().getUser()).getIamRole().get());
+ }
+
+ @Test(
+ expectedExceptions = VerifyException.class,
+ expectedExceptionsMessageRegExp =
+ "(iamRole is mandatory for AWS Lake Formation Security Mapping|Basic AWS Credentials are not supported for AWS Lake Formation Security Mapping)")
+ public void testInvalidAWSLakeFormationMapping()
+ {
+ String lakeFormationSecurityMappingConfigPath =
+ this.getClass().getClassLoader().getResource("com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-invalid.json").getPath();
+
+ AWSSecurityMappings mappings = parseJson(new File(lakeFormationSecurityMappingConfigPath).toPath(), AWSSecurityMappings.class);
+
+ // Fails with VerifyException: iamRole is mandatory for AWS Lake Formation Security Mapping
+ mappings.getAWSLakeFormationSecurityMapping(MappingSelector.empty().withUser("admin").getUser());
+
+ // Fails with VerifyException: Basic AWS Credentials are not supported for AWS Lake Formation Security Mapping
+ mappings.getAWSLakeFormationSecurityMapping(MappingSelector.empty().withUser("analyst").getUser());
+ }
+
+ private static class MappingSelector
+ {
+ private static MappingSelector empty()
+ {
+ return new MappingSelector(DEFAULT_USER);
+ }
+
+ private final String user;
+
+ private MappingSelector(String user)
+ {
+ this.user = requireNonNull(user, "user is null");
+ }
+
+ private MappingSelector withUser(String user)
+ {
+ return new MappingSelector(user);
+ }
+
+ private String getUser()
+ {
+ return user;
+ }
+ }
+
+ private static class MappingResult
+ {
+ private static MappingResult role(String role)
+ {
+ return new MappingResult(role);
+ }
+
+ private final String iamRole;
+
+ private MappingResult(String iamRole)
+ {
+ this.iamRole = requireNonNull(iamRole, "role is null");
+ }
+
+ private String getIamRole()
+ {
+ return iamRole;
+ }
+ }
+}
diff --git a/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-invalid.json b/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-invalid.json
new file mode 100644
index 0000000000000..709c943f2e7c4
--- /dev/null
+++ b/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-invalid.json
@@ -0,0 +1,12 @@
+{
+ "mappings": [
+ {
+ "user": "admin"
+ },
+ {
+ "user": "analyst",
+ "accessKey": "AKIAxxxaccess",
+ "secretKey": "iXbXxxxsecret"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-valid.json b/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-valid.json
new file mode 100644
index 0000000000000..8c2c87eff1adc
--- /dev/null
+++ b/presto-hive-common/src/test/resources/com.facebook.presto.hive.aws.security/aws-security-mapping-lakeformation-valid.json
@@ -0,0 +1,15 @@
+{
+ "mappings": [
+ {
+ "user": "admin",
+ "iamRole": "arn:aws:iam::123456789101:role/admin_role"
+ },
+ {
+ "user": "analyst",
+ "iamRole": "arn:aws:iam::123456789101:role/analyst_role"
+ },
+ {
+ "iamRole": "arn:aws:iam::123456789101:role/default_role"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/s3/HiveS3Module.java b/presto-hive/src/main/java/com/facebook/presto/hive/s3/HiveS3Module.java
index 0862713d4fe2c..7b671f8bc4989 100644
--- a/presto-hive/src/main/java/com/facebook/presto/hive/s3/HiveS3Module.java
+++ b/presto-hive/src/main/java/com/facebook/presto/hive/s3/HiveS3Module.java
@@ -14,13 +14,22 @@
package com.facebook.presto.hive.s3;
import com.facebook.airlift.configuration.AbstractConfigurationAwareModule;
+import com.facebook.presto.hive.DynamicConfigurationProvider;
import com.facebook.presto.hive.HiveClientConfig;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingConfig;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingsSupplier;
+import com.facebook.presto.hive.s3.security.AWSS3SecurityMappingConfigurationProvider;
+import com.facebook.presto.hive.s3.security.ForAWSS3DynamicConfigurationProvider;
import com.google.inject.Binder;
+import com.google.inject.Provides;
import com.google.inject.Scopes;
+import com.google.inject.Singleton;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.common.JavaUtils;
import static com.facebook.airlift.configuration.ConfigBinder.configBinder;
+import static com.facebook.presto.hive.aws.security.AWSSecurityMappingType.S3;
+import static com.google.inject.multibindings.Multibinder.newSetBinder;
import static java.util.Objects.requireNonNull;
import static org.weakref.jmx.ObjectNames.generatedNameOf;
import static org.weakref.jmx.guice.ExportBinder.newExporter;
@@ -42,6 +51,8 @@ protected void setup(Binder binder)
{
S3FileSystemType type = buildConfigObject(HiveClientConfig.class).getS3FileSystemType();
if (type == S3FileSystemType.PRESTO) {
+ bindSecurityMapping(binder);
+
binder.bind(S3ConfigurationUpdater.class).to(PrestoS3ConfigurationUpdater.class).in(Scopes.SINGLETON);
configBinder(binder).bindConfig(HiveS3Config.class);
@@ -61,6 +72,23 @@ else if (type == S3FileSystemType.HADOOP_DEFAULT) {
}
}
+ @Provides
+ @Singleton
+ @ForAWSS3DynamicConfigurationProvider
+ public AWSSecurityMappingsSupplier provideAWSSecurityMappingsSupplier(AWSSecurityMappingConfig config)
+ {
+ return new AWSSecurityMappingsSupplier(config.getConfigFile(), config.getRefreshPeriod());
+ }
+
+ private void bindSecurityMapping(Binder binder)
+ {
+ if (buildConfigObject(AWSSecurityMappingConfig.class).getConfigFile().isPresent() &&
+ buildConfigObject(AWSSecurityMappingConfig.class).getMappingType().equals(S3)) {
+ newSetBinder(binder, DynamicConfigurationProvider.class).addBinding()
+ .to(AWSS3SecurityMappingConfigurationProvider.class).in(Scopes.SINGLETON);
+ }
+ }
+
private static void validateEmrFsClass()
{
// verify that the class exists
diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/AWSS3SecurityMappingConfigurationProvider.java b/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/AWSS3SecurityMappingConfigurationProvider.java
new file mode 100644
index 0000000000000..a09e391377376
--- /dev/null
+++ b/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/AWSS3SecurityMappingConfigurationProvider.java
@@ -0,0 +1,77 @@
+/*
+ * 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 com.facebook.presto.hive.s3.security;
+
+import com.facebook.presto.hive.DynamicConfigurationProvider;
+import com.facebook.presto.hive.HdfsContext;
+import com.facebook.presto.hive.aws.security.AWSSecurityMapping;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappings;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingsSupplier;
+import com.google.common.collect.ImmutableSet;
+import org.apache.hadoop.conf.Configuration;
+
+import javax.inject.Inject;
+
+import java.net.URI;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_ACCESS_KEY;
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_IAM_ROLE;
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_SECRET_KEY;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+public class AWSS3SecurityMappingConfigurationProvider
+ implements DynamicConfigurationProvider
+{
+ private static final Set SCHEMES = ImmutableSet.of("s3", "s3a", "s3n");
+
+ private final Supplier mappings;
+
+ @Inject
+ public AWSS3SecurityMappingConfigurationProvider(
+ @ForAWSS3DynamicConfigurationProvider AWSSecurityMappingsSupplier awsSecurityMappingsSupplier)
+ {
+ this(requireNonNull(awsSecurityMappingsSupplier, "awsSecurityMappingsSupplier is null").getMappingsSupplier());
+ }
+
+ private AWSS3SecurityMappingConfigurationProvider(Supplier mappings)
+ {
+ this.mappings = requireNonNull(mappings, "mappings is null");
+ }
+
+ @Override
+ public void updateConfiguration(Configuration configuration, HdfsContext context, URI uri)
+ {
+ if (!SCHEMES.contains(uri.getScheme())) {
+ return;
+ }
+
+ AWSSecurityMapping awsS3SecurityMapping = mappings.get().getAWSS3SecurityMapping(context.getIdentity().getUser());
+
+ checkArgument(
+ awsS3SecurityMapping.getIamRole().isPresent() || awsS3SecurityMapping.getCredentials().isPresent(),
+ "AWS S3 security mapping must have role or credentials");
+
+ awsS3SecurityMapping.getCredentials().ifPresent(credentials -> {
+ configuration.set(S3_ACCESS_KEY, credentials.getAWSAccessKeyId());
+ configuration.set(S3_SECRET_KEY, credentials.getAWSSecretKey());
+ });
+
+ awsS3SecurityMapping.getIamRole().ifPresent(role -> {
+ configuration.set(S3_IAM_ROLE, role);
+ });
+ }
+}
diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/ForAWSS3DynamicConfigurationProvider.java b/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/ForAWSS3DynamicConfigurationProvider.java
new file mode 100644
index 0000000000000..446032ade96c0
--- /dev/null
+++ b/presto-hive/src/main/java/com/facebook/presto/hive/s3/security/ForAWSS3DynamicConfigurationProvider.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.facebook.presto.hive.s3.security;
+
+import javax.inject.Qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(RUNTIME)
+@Target({PARAMETER, METHOD, FIELD})
+@Qualifier
+public @interface ForAWSS3DynamicConfigurationProvider
+{
+}
diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/s3/security/TestAWSS3SecurityMapping.java b/presto-hive/src/test/java/com/facebook/presto/hive/s3/security/TestAWSS3SecurityMapping.java
new file mode 100644
index 0000000000000..0041e89942b52
--- /dev/null
+++ b/presto-hive/src/test/java/com/facebook/presto/hive/s3/security/TestAWSS3SecurityMapping.java
@@ -0,0 +1,192 @@
+/*
+ * 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 com.facebook.presto.hive.s3.security;
+
+import com.facebook.presto.cache.CacheConfig;
+import com.facebook.presto.hive.DynamicConfigurationProvider;
+import com.facebook.presto.hive.HdfsContext;
+import com.facebook.presto.hive.HiveClientConfig;
+import com.facebook.presto.hive.HiveSessionProperties;
+import com.facebook.presto.hive.OrcFileWriterConfig;
+import com.facebook.presto.hive.ParquetFileWriterConfig;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingConfig;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingType;
+import com.facebook.presto.hive.aws.security.AWSSecurityMappingsSupplier;
+import com.facebook.presto.spi.ConnectorSession;
+import com.facebook.presto.spi.security.AccessDeniedException;
+import com.facebook.presto.spi.security.ConnectorIdentity;
+import com.facebook.presto.testing.TestingConnectorSession;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.Optional;
+
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_ACCESS_KEY;
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_IAM_ROLE;
+import static com.facebook.presto.hive.s3.S3ConfigurationUpdater.S3_SECRET_KEY;
+import static com.google.common.io.Resources.getResource;
+import static java.util.Objects.requireNonNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+public class TestAWSS3SecurityMapping
+{
+ private static final String DEFAULT_USER = "defaultUser";
+
+ @Test
+ public void testAWSS3SecurityMapping()
+ {
+ AWSSecurityMappingConfig mappingConfig = new AWSSecurityMappingConfig()
+ .setMappingType(AWSSecurityMappingType.S3)
+ .setConfigFile(new File(getResource(getClass(), "aws-security-mapping-with-default-role.json").getPath()));
+
+ AWSSecurityMappingsSupplier awsSecurityMappingsSupplier =
+ new AWSSecurityMappingsSupplier(mappingConfig.getConfigFile(), mappingConfig.getRefreshPeriod());
+
+ DynamicConfigurationProvider provider = new AWSS3SecurityMappingConfigurationProvider(awsSecurityMappingsSupplier);
+
+ // matches user -- mapping provides credentials
+ assertMapping(
+ provider,
+ MappingSelector.empty().withUser("admin"),
+ MappingResult.credentials("AKIAxxxaccess", "iXbXxxxsecret"));
+
+ // matches user regex -- mapping provides iam role
+ assertMapping(
+ provider,
+ MappingSelector.empty().withUser("analyst"),
+ MappingResult.role("arn:aws:iam::123456789101:role/analyst_and_scientist_role"));
+
+ // matches empty rule at end -- default role used
+ assertMapping(
+ provider,
+ MappingSelector.empty().withUser("defaultUser"),
+ MappingResult.role("arn:aws:iam::123456789101:role/default"));
+ }
+
+ @Test(
+ expectedExceptions = AccessDeniedException.class,
+ expectedExceptionsMessageRegExp = "Access Denied: No matching AWS S3 Security Mapping")
+ public void testFailAWSS3SecurityMapping()
+ {
+ AWSSecurityMappingConfig mappingConfig = new AWSSecurityMappingConfig()
+ .setMappingType(AWSSecurityMappingType.S3)
+ .setConfigFile(new File(getResource(getClass(), "aws-security-mapping-without-default-role.json").getPath()));
+
+ AWSSecurityMappingsSupplier awsSecurityMappingsSupplier =
+ new AWSSecurityMappingsSupplier(mappingConfig.getConfigFile(), mappingConfig.getRefreshPeriod());
+
+ DynamicConfigurationProvider provider = new AWSS3SecurityMappingConfigurationProvider(awsSecurityMappingsSupplier);
+
+ // matches no security mapping -- access denied
+ Configuration configuration = new Configuration(false);
+ applyMapping(provider, MappingSelector.empty().withUser("defaultUser"), configuration);
+ }
+
+ private static void assertMapping(DynamicConfigurationProvider provider, MappingSelector selector, MappingResult mappingResult)
+ {
+ Configuration configuration = new Configuration(false);
+
+ assertNull(configuration.get(S3_ACCESS_KEY));
+ assertNull(configuration.get(S3_SECRET_KEY));
+ assertNull(configuration.get(S3_IAM_ROLE));
+
+ applyMapping(provider, selector, configuration);
+
+ if (mappingResult.getAccessKey().isPresent()) {
+ assertEquals(configuration.get(S3_ACCESS_KEY), mappingResult.getAccessKey().get());
+ assertEquals(configuration.get(S3_SECRET_KEY), mappingResult.getSecretKey().get());
+ }
+ else {
+ assertEquals(configuration.get(S3_IAM_ROLE), mappingResult.getRole().get());
+ }
+ }
+
+ private static void applyMapping(DynamicConfigurationProvider provider, MappingSelector selector, Configuration configuration)
+ {
+ provider.updateConfiguration(configuration, selector.getHdfsContext(), new Path("s3://defaultBucket/").toUri());
+ }
+
+ private static class MappingSelector
+ {
+ private final String user;
+
+ private MappingSelector(String user)
+ {
+ this.user = requireNonNull(user, "user is null");
+ }
+
+ private static MappingSelector empty()
+ {
+ return new MappingSelector(DEFAULT_USER);
+ }
+
+ private MappingSelector withUser(String user)
+ {
+ return new MappingSelector(user);
+ }
+
+ private HdfsContext getHdfsContext()
+ {
+ ConnectorSession connectorSession = new TestingConnectorSession(
+ new ConnectorIdentity(
+ user, Optional.empty(), Optional.empty()),
+ new HiveSessionProperties(
+ new HiveClientConfig(), new OrcFileWriterConfig(), new ParquetFileWriterConfig(), new CacheConfig()
+ ).getSessionProperties());
+ return new HdfsContext(connectorSession, "schema");
+ }
+ }
+
+ private static class MappingResult
+ {
+ private static MappingResult credentials(String accessKey, String secretKey)
+ {
+ return new MappingResult(Optional.of(accessKey), Optional.of(secretKey), Optional.empty());
+ }
+
+ private static MappingResult role(String role)
+ {
+ return new MappingResult(Optional.empty(), Optional.empty(), Optional.of(role));
+ }
+
+ private final Optional accessKey;
+ private final Optional secretKey;
+ private final Optional role;
+
+ private MappingResult(Optional accessKey, Optional secretKey, Optional role)
+ {
+ this.accessKey = accessKey;
+ this.secretKey = secretKey;
+ this.role = role;
+ }
+
+ private Optional getAccessKey()
+ {
+ return accessKey;
+ }
+
+ private Optional getSecretKey()
+ {
+ return secretKey;
+ }
+
+ private Optional getRole()
+ {
+ return role;
+ }
+ }
+}
diff --git a/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-with-default-role.json b/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-with-default-role.json
new file mode 100644
index 0000000000000..504541348c4cf
--- /dev/null
+++ b/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-with-default-role.json
@@ -0,0 +1,16 @@
+{
+ "mappings": [
+ {
+ "user": "admin",
+ "accessKey": "AKIAxxxaccess",
+ "secretKey": "iXbXxxxsecret"
+ },
+ {
+ "user": "analyst|scientist",
+ "iamRole": "arn:aws:iam::123456789101:role/analyst_and_scientist_role"
+ },
+ {
+ "iamRole": "arn:aws:iam::123456789101:role/default"
+ }
+ ]
+}
diff --git a/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-without-default-role.json b/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-without-default-role.json
new file mode 100644
index 0000000000000..86a3441a0dae4
--- /dev/null
+++ b/presto-hive/src/test/resources/com/facebook/presto/hive/s3/security/aws-security-mapping-without-default-role.json
@@ -0,0 +1,13 @@
+{
+ "mappings": [
+ {
+ "user": "admin",
+ "accessKey": "AKIAxxxaccess",
+ "secretKey": "iXbXxxxsecret"
+ },
+ {
+ "user": "analyst|scientist",
+ "iamRole": "arn:aws:iam::123456789101:role/analyst_and_scientist_role"
+ }
+ ]
+}
diff --git a/presto-main/src/main/java/com/facebook/presto/testing/TestingConnectorSession.java b/presto-main/src/main/java/com/facebook/presto/testing/TestingConnectorSession.java
index 3bb4c3e9089fc..ca2470f0ec2e7 100644
--- a/presto-main/src/main/java/com/facebook/presto/testing/TestingConnectorSession.java
+++ b/presto-main/src/main/java/com/facebook/presto/testing/TestingConnectorSession.java
@@ -65,26 +65,32 @@ public class TestingConnectorSession
public TestingConnectorSession(List> properties)
{
- this("user", Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), Optional.empty(), ImmutableMap.of());
+ this("user", new ConnectorIdentity("user", Optional.empty(), Optional.empty()), Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), Optional.empty(), ImmutableMap.of());
+ }
+
+ public TestingConnectorSession(ConnectorIdentity identity, List> properties)
+ {
+ this(identity.getUser(), identity, Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), Optional.empty(), ImmutableMap.of());
}
public TestingConnectorSession(List> properties, Set clientTags)
{
- this("user", Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), clientTags, Optional.empty(), ImmutableMap.of());
+ this("user", new ConnectorIdentity("user", Optional.empty(), Optional.empty()), Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), clientTags, Optional.empty(), ImmutableMap.of());
}
public TestingConnectorSession(List> properties, Map propertyValues)
{
- this("user", Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, propertyValues, new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), Optional.empty(), ImmutableMap.of());
+ this("user", new ConnectorIdentity("user", Optional.empty(), Optional.empty()), Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, propertyValues, new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), Optional.empty(), ImmutableMap.of());
}
public TestingConnectorSession(List> properties, Optional schema)
{
- this("user", Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), schema, ImmutableMap.of());
+ this("user", new ConnectorIdentity("user", Optional.empty(), Optional.empty()), Optional.of("test"), Optional.empty(), UTC_KEY, ENGLISH, System.currentTimeMillis(), properties, ImmutableMap.of(), new FeaturesConfig().isLegacyTimestamp(), Optional.empty(), ImmutableSet.of(), schema, ImmutableMap.of());
}
public TestingConnectorSession(
String user,
+ ConnectorIdentity identity,
Optional source,
Optional traceToken,
TimeZoneKey timeZoneKey,
@@ -99,7 +105,7 @@ public TestingConnectorSession(
Map sessionFunctions)
{
this.queryId = queryIdGenerator.createNextQueryId().toString();
- this.identity = new ConnectorIdentity(requireNonNull(user, "user is null"), Optional.empty(), Optional.empty());
+ this.identity = requireNonNull(identity, "identity is null");
this.source = requireNonNull(source, "source is null");
this.traceToken = requireNonNull(traceToken, "traceToken is null");
this.timeZoneKey = requireNonNull(timeZoneKey, "timeZoneKey is null");
diff --git a/presto-main/src/test/java/com/facebook/presto/operator/scalar/TestDateTimeFunctionsBase.java b/presto-main/src/test/java/com/facebook/presto/operator/scalar/TestDateTimeFunctionsBase.java
index 2f3be9168f9af..7a782eb6a8018 100644
--- a/presto-main/src/test/java/com/facebook/presto/operator/scalar/TestDateTimeFunctionsBase.java
+++ b/presto-main/src/test/java/com/facebook/presto/operator/scalar/TestDateTimeFunctionsBase.java
@@ -26,6 +26,7 @@
import com.facebook.presto.common.type.TimestampType;
import com.facebook.presto.common.type.Type;
import com.facebook.presto.spi.StandardErrorCode;
+import com.facebook.presto.spi.security.ConnectorIdentity;
import com.facebook.presto.testing.TestingConnectorSession;
import com.facebook.presto.testing.TestingSession;
import com.facebook.presto.type.SqlIntervalDayTime;
@@ -165,6 +166,7 @@ private void assertCurrentDateAtInstant(TimeZoneKey timeZoneKey, long instant)
long dateTimeCalculation = currentDate(
new TestingConnectorSession(
"test",
+ new ConnectorIdentity("test", Optional.empty(), Optional.empty()),
Optional.empty(),
Optional.empty(),
timeZoneKey,
diff --git a/presto-pinot-toolkit/src/test/java/com/facebook/presto/pinot/TestPinotSplitManager.java b/presto-pinot-toolkit/src/test/java/com/facebook/presto/pinot/TestPinotSplitManager.java
index daa98d7a87a4e..3ee64e600415f 100644
--- a/presto-pinot-toolkit/src/test/java/com/facebook/presto/pinot/TestPinotSplitManager.java
+++ b/presto-pinot-toolkit/src/test/java/com/facebook/presto/pinot/TestPinotSplitManager.java
@@ -18,6 +18,7 @@
import com.facebook.presto.spi.ConnectorSplitSource;
import com.facebook.presto.spi.plan.AggregationNode;
import com.facebook.presto.spi.plan.PlanNode;
+import com.facebook.presto.spi.security.ConnectorIdentity;
import com.facebook.presto.sql.analyzer.FeaturesConfig;
import com.facebook.presto.sql.planner.iterative.rule.test.PlanBuilder;
import com.facebook.presto.testing.TestingConnectorSession;
@@ -224,6 +225,7 @@ public static ConnectorSession createSessionWithNumSplits(int numSegmentsPerSpli
{
return new TestingConnectorSession(
"user",
+ new ConnectorIdentity("user", Optional.empty(), Optional.empty()),
Optional.of("test"),
Optional.empty(),
UTC_KEY,
@@ -246,6 +248,7 @@ public static ConnectorSession createSessionWithLimitLarge(int limitLarge, Pinot
{
return new TestingConnectorSession(
"user",
+ new ConnectorIdentity("user", Optional.empty(), Optional.empty()),
Optional.of("test"),
Optional.empty(),
UTC_KEY,
@@ -266,6 +269,7 @@ public static ConnectorSession createSessionWithTopNLarge(int topNLarge, PinotCo
{
return new TestingConnectorSession(
"user",
+ new ConnectorIdentity("user", Optional.empty(), Optional.empty()),
Optional.of("test"),
Optional.empty(),
UTC_KEY,