diff --git a/docs/src/main/sphinx/object-storage/metastores.md b/docs/src/main/sphinx/object-storage/metastores.md index 685dc41572929f..7ce88799cdf7e2 100644 --- a/docs/src/main/sphinx/object-storage/metastores.md +++ b/docs/src/main/sphinx/object-storage/metastores.md @@ -393,6 +393,12 @@ properties: - Fully qualified name of the Java class to use for obtaining AWS credentials. Can be used to supply a custom credentials provider. - +* - `hive.metastore.glue.use-web-identity-token-credentials-provider` + - If you are running Trino on Amazon EKS, and authenticate using a Kubernetes + service account, you can set this property to `true`. Setting to `true` forces + Trino to not try using different credential providers from the default credential + provider chain, and instead directly use credentials from the service account. + - * - `hive.metastore.glue.aws-access-key` - AWS access key to use to connect to the Glue Catalog. If specified along with `hive.metastore.glue.aws-secret-key`, this parameter takes precedence diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueHiveMetastoreConfig.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueHiveMetastoreConfig.java index 1ba4361521ecb6..ecf552d189bd51 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueHiveMetastoreConfig.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueHiveMetastoreConfig.java @@ -44,6 +44,7 @@ public class GlueHiveMetastoreConfig private Optional externalId = Optional.empty(); private Optional awsAccessKey = Optional.empty(); private Optional awsSecretKey = Optional.empty(); + private boolean useWebIdentityTokenCredentialsProvider; private Optional catalogId = Optional.empty(); private int partitionSegments = 5; private int threads = 40; @@ -208,6 +209,20 @@ public GlueHiveMetastoreConfig setAwsSecretKey(String awsSecretKey) return this; } + public boolean isUseWebIdentityTokenCredentialsProvider() + { + return useWebIdentityTokenCredentialsProvider; + } + + @Config("hive.metastore.glue.use-web-identity-token-credentials-provider") + @ConfigDescription("If true, explicitly use the WebIdentityTokenCredentialsProvider" + + " instead of the default credential provider chain.") + public GlueHiveMetastoreConfig setUseWebIdentityTokenCredentialsProvider(boolean useWebIdentityTokenCredentialsProvider) + { + this.useWebIdentityTokenCredentialsProvider = useWebIdentityTokenCredentialsProvider; + return this; + } + public Optional getCatalogId() { return catalogId; diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueMetastoreModule.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueMetastoreModule.java index ca70fea9ddc78b..2607f9b051273d 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueMetastoreModule.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/metastore/glue/GlueMetastoreModule.java @@ -40,9 +40,11 @@ import software.amazon.awssdk.services.sts.StsClient; import software.amazon.awssdk.services.sts.StsClientBuilder; import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider; +import software.amazon.awssdk.services.sts.auth.StsWebIdentityTokenFileCredentialsProvider; import java.net.URI; import java.util.EnumSet; +import java.util.Optional; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; @@ -123,35 +125,26 @@ public static GlueClient createGlueClient(GlueHiveMetastoreConfig config, OpenTe .retryPolicy(retry -> retry .numRetries(config.getMaxGlueErrorRetries()))); - if (config.getIamRole().isPresent()) { - StsClientBuilder sts = StsClient.builder(); - - if (config.getAwsAccessKey().isPresent() && config.getAwsSecretKey().isPresent()) { - sts.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAwsAccessKey().get(), config.getAwsSecretKey().get()))); - } - - if (config.getGlueStsEndpointUrl().isPresent() && config.getGlueStsRegion().isPresent()) { - sts.endpointOverride(URI.create(config.getGlueStsEndpointUrl().get())) - .region(Region.of(config.getGlueStsRegion().get())); - } - else if (config.getGlueStsRegion().isPresent()) { - sts.region(Region.of(config.getGlueStsRegion().get())); - } - else if (config.getPinGlueClientToCurrentRegion()) { - sts.region(DefaultAwsRegionProviderChain.builder().build().getRegion()); - } + Optional staticCredentialsProvider = getStaticCredentialsProvider(config); + if (config.isUseWebIdentityTokenCredentialsProvider()) { + glue.credentialsProvider(StsWebIdentityTokenFileCredentialsProvider.builder() + .stsClient(getStsClient(config, staticCredentialsProvider)) + .asyncCredentialUpdateEnabled(true) + .build()); + } + else if (config.getIamRole().isPresent()) { glue.credentialsProvider(StsAssumeRoleCredentialsProvider.builder() .refreshRequest(request -> request .roleArn(config.getIamRole().get()) .roleSessionName("trino-session") .externalId(config.getExternalId().orElse(null))) - .stsClient(sts.build()) + .stsClient(getStsClient(config, staticCredentialsProvider)) .asyncCredentialUpdateEnabled(true) .build()); } - else if (config.getAwsAccessKey().isPresent() && config.getAwsSecretKey().isPresent()) { - glue.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAwsAccessKey().get(), config.getAwsSecretKey().get()))); + else { + staticCredentialsProvider.ifPresent(glue::credentialsProvider); } ApacheHttpClient.Builder httpClient = ApacheHttpClient.builder() @@ -175,4 +168,33 @@ else if (config.getPinGlueClientToCurrentRegion()) { return glue.build(); } + + private static Optional getStaticCredentialsProvider(GlueHiveMetastoreConfig config) + { + if (config.getAwsAccessKey().isPresent() && config.getAwsSecretKey().isPresent()) { + return Optional.of(StaticCredentialsProvider.create( + AwsBasicCredentials.create(config.getAwsAccessKey().get(), config.getAwsSecretKey().get()))); + } + return Optional.empty(); + } + + private static StsClient getStsClient(GlueHiveMetastoreConfig config, + Optional staticCredentialsProvider) + { + StsClientBuilder sts = StsClient.builder(); + staticCredentialsProvider.ifPresent(sts::credentialsProvider); + + if (config.getGlueStsEndpointUrl().isPresent() && config.getGlueStsRegion().isPresent()) { + sts.endpointOverride(URI.create(config.getGlueStsEndpointUrl().get())) + .region(Region.of(config.getGlueStsRegion().get())); + } + else if (config.getGlueStsRegion().isPresent()) { + sts.region(Region.of(config.getGlueStsRegion().get())); + } + else if (config.getPinGlueClientToCurrentRegion()) { + sts.region(DefaultAwsRegionProviderChain.builder().build().getRegion()); + } + + return sts.build(); + } } diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/glue/TestGlueHiveMetastoreConfig.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/glue/TestGlueHiveMetastoreConfig.java index c18442033bfdd0..3ec8914810579b 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/glue/TestGlueHiveMetastoreConfig.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/metastore/glue/TestGlueHiveMetastoreConfig.java @@ -40,6 +40,7 @@ void testDefaults() .setExternalId(null) .setAwsAccessKey(null) .setAwsSecretKey(null) + .setUseWebIdentityTokenCredentialsProvider(false) .setCatalogId(null) .setPartitionSegments(5) .setThreads(40) @@ -62,6 +63,7 @@ void testExplicitPropertyMapping() .put("hive.metastore.glue.external-id", "external-id") .put("hive.metastore.glue.aws-access-key", "ABC") .put("hive.metastore.glue.aws-secret-key", "DEF") + .put("hive.metastore.glue.use-web-identity-token-credentials-provider", "true") .put("hive.metastore.glue.catalogid", "0123456789") .put("hive.metastore.glue.partitions-segments", "10") .put("hive.metastore.glue.threads", "77") @@ -81,6 +83,7 @@ void testExplicitPropertyMapping() .setExternalId("external-id") .setAwsAccessKey("ABC") .setAwsSecretKey("DEF") + .setUseWebIdentityTokenCredentialsProvider(true) .setCatalogId("0123456789") .setPartitionSegments(10) .setThreads(77)