This is an automated email from the ASF dual-hosted git repository.

yqm pushed a commit to branch 35.0.0
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/35.0.0 by this push:
     new 7b0ed737585 Add sessionToken support for S3InputSource (#18609)
7b0ed737585 is described below

commit 7b0ed73758596e8a5519bdf8ca7d5230bed2a455
Author: jtuglu1 <[email protected]>
AuthorDate: Thu Oct 9 12:49:20 2025 -0700

    Add sessionToken support for S3InputSource (#18609)
    
    Allows Druid to use an AWS_SESSION_TOKEN (and skip assuming a role to fetch 
a token) if provided in the spec. No explicit assumptions are made with the 
input (e.g. that adding sessionToken and assumeRoleAre are mutually exclusive).
    
    This support falls in line with how other engines use things like external 
catalogs, etc. to vend temporary credentials to access S3, while leaving things 
like the exact ARN opaque to the caller.
---
 docs/ingestion/input-sources.md                    |   5 +-
 .../catalog/model/table/S3InputSourceDefn.java     |   9 +-
 .../apache/druid/data/input/s3/S3InputSource.java  |  23 +++-
 .../druid/data/input/s3/S3InputSourceConfig.java   |  25 +++-
 .../catalog/model/table/S3InputSourceDefnTest.java |   3 +-
 .../data/input/s3/S3InputSourceConfigTest.java     |   6 +-
 .../druid/data/input/s3/S3InputSourceTest.java     | 151 ++++++++++++++++++++-
 .../druid/msq/util/MSQTaskQueryMakerUtils.java     |   2 +-
 .../druid/msq/util/MSQTaskQueryMakerUtilsTest.java |   4 +-
 website/.spelling                                  |   1 +
 10 files changed, 206 insertions(+), 23 deletions(-)

diff --git a/docs/ingestion/input-sources.md b/docs/ingestion/input-sources.md
index 3066ba7386d..49cf90cdbf5 100644
--- a/docs/ingestion/input-sources.md
+++ b/docs/ingestion/input-sources.md
@@ -204,8 +204,9 @@ Properties Object:
 
 |Property|Description|Default|Required|
 |--------|-----------|-------|---------|
-|accessKeyId|The [Password Provider](../operations/password-provider.md) or 
plain text string of this S3 input source access key|None|yes if 
secretAccessKey is given|
-|secretAccessKey|The [Password Provider](../operations/password-provider.md) 
or plain text string of this S3 input source secret key|None|yes if accessKeyId 
is given|
+|accessKeyId|The [Password Provider](../operations/password-provider.md) or 
plain text string of this S3 input source access key|None|Yes, if 
`secretAccessKey` or `sessionToken` is given.|
+|secretAccessKey|The [Password Provider](../operations/password-provider.md) 
or plain text string of this S3 input source secret key|None|Yes, if 
`accessKeyId` or `sessionToken` is given.|
+|sessionToken|The [Password Provider](../operations/password-provider.md) or 
plain text string of this S3 input source session token|None|no|
 |assumeRoleArn|AWS ARN of the role to assume 
[see](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html).
 **assumeRoleArn** can be used either with the ingestion spec AWS credentials 
or with the default S3 credentials|None|no|
 |assumeRoleExternalId|A unique identifier that might be required when you 
assume a role in another account 
[see](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)|None|no|
 
diff --git 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/catalog/model/table/S3InputSourceDefn.java
 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/catalog/model/table/S3InputSourceDefn.java
index 358862d0332..ca84236d14a 100644
--- 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/catalog/model/table/S3InputSourceDefn.java
+++ 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/catalog/model/table/S3InputSourceDefn.java
@@ -79,6 +79,7 @@ public class S3InputSourceDefn extends 
FormattedInputSourceDefn
   public static final String ACCESS_KEY_ID_PARAMETER = "accessKeyId";
   public static final String SECRET_ACCESS_KEY_PARAMETER = "secretAccessKey";
   public static final String ASSUME_ROLE_ARN_PARAMETER = "assumeRoleArn";
+  public static final String SESSION_TOKEN_PARAMETER = "sessionToken";
 
   /**
    * The {@code objectGlob} property exists in S3, but is not documented. The 
corresponding
@@ -102,7 +103,8 @@ public class S3InputSourceDefn extends 
FormattedInputSourceDefn
   private static final List<ParameterDefn> SECURITY_PARAMS = Arrays.asList(
       new Parameter(ACCESS_KEY_ID_PARAMETER, ParameterType.VARCHAR, true),
       new Parameter(SECRET_ACCESS_KEY_PARAMETER, ParameterType.VARCHAR, true),
-      new Parameter(ASSUME_ROLE_ARN_PARAMETER, ParameterType.VARCHAR, true)
+      new Parameter(ASSUME_ROLE_ARN_PARAMETER, ParameterType.VARCHAR, true),
+      new Parameter(SESSION_TOKEN_PARAMETER, ParameterType.VARCHAR, true)
   );
 
   // Field names in the S3InputSource
@@ -114,6 +116,7 @@ public class S3InputSourceDefn extends 
FormattedInputSourceDefn
   private static final String ACCESS_KEY_ID_FIELD = "accessKeyId";
   private static final String SECRET_ACCESS_KEY_FIELD = "secretAccessKey";
   private static final String ASSUME_ROLE_ARN_FIELD = "assumeRoleArn";
+  private static final String SESSION_TOKEN_FIELD = "sessionToken";
 
   @Override
   public String typeValue()
@@ -250,6 +253,7 @@ public class S3InputSourceDefn extends 
FormattedInputSourceDefn
     final String accessKeyId = CatalogUtils.getNonBlankString(args, 
ACCESS_KEY_ID_PARAMETER);
     final String secretAccessKey = CatalogUtils.getNonBlankString(args, 
SECRET_ACCESS_KEY_PARAMETER);
     final String assumeRoleArn = CatalogUtils.getNonBlankString(args, 
ASSUME_ROLE_ARN_PARAMETER);
+    final String sessionToken = CatalogUtils.getNonBlankString(args, 
SESSION_TOKEN_PARAMETER);
     if (accessKeyId != null || secretAccessKey != null || assumeRoleArn != 
null) {
       Map<String, Object> properties = new HashMap<>();
       if (accessKeyId != null) {
@@ -258,6 +262,9 @@ public class S3InputSourceDefn extends 
FormattedInputSourceDefn
       if (secretAccessKey != null) {
         properties.put(SECRET_ACCESS_KEY_FIELD, secretAccessKey);
       }
+      if (sessionToken != null) {
+        properties.put(SESSION_TOKEN_FIELD, sessionToken);
+      }
       if (assumeRoleArn != null) {
         properties.put(ASSUME_ROLE_ARN_FIELD, assumeRoleArn);
       }
diff --git 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSource.java
 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSource.java
index 69f97c24669..df0c69c8e56 100644
--- 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSource.java
+++ 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSource.java
@@ -21,8 +21,10 @@ package org.apache.druid.data.input.s3;
 
 import com.amazonaws.Protocol;
 import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.AWSSessionCredentials;
 import com.amazonaws.auth.AWSStaticCredentialsProvider;
 import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.auth.BasicSessionCredentials;
 import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
 import com.amazonaws.client.builder.AwsClientBuilder;
 import com.amazonaws.services.s3.model.ObjectMetadata;
@@ -282,12 +284,21 @@ public class S3InputSource extends CloudObjectInputSource
   @Nonnull
   private AWSStaticCredentialsProvider 
createStaticCredentialsProvider(S3InputSourceConfig s3InputSourceConfig)
   {
-    return new AWSStaticCredentialsProvider(
-        new BasicAWSCredentials(
-            s3InputSourceConfig.getAccessKeyId().getPassword(),
-            s3InputSourceConfig.getSecretAccessKey().getPassword()
-        )
-    );
+    if (s3InputSourceConfig.getSessionToken() != null) {
+      AWSSessionCredentials sessionCredentials = new BasicSessionCredentials(
+          s3InputSourceConfig.getAccessKeyId().getPassword(),
+          s3InputSourceConfig.getSecretAccessKey().getPassword(),
+          s3InputSourceConfig.getSessionToken().getPassword()
+      );
+      return new AWSStaticCredentialsProvider(sessionCredentials);
+    } else {
+      return new AWSStaticCredentialsProvider(
+          new BasicAWSCredentials(
+              s3InputSourceConfig.getAccessKeyId().getPassword(),
+              s3InputSourceConfig.getSecretAccessKey().getPassword()
+          )
+      );
+    }
   }
 
   @Nullable
diff --git 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSourceConfig.java
 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSourceConfig.java
index e46a095dec7..e7698a6264d 100644
--- 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSourceConfig.java
+++ 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/data/input/s3/S3InputSourceConfig.java
@@ -39,24 +39,27 @@ public class S3InputSourceConfig
   private final String assumeRoleExternalId;
   private final PasswordProvider accessKeyId;
   private final PasswordProvider secretAccessKey;
+  private final PasswordProvider sessionToken;
 
   @JsonCreator
   public S3InputSourceConfig(
       @JsonProperty("accessKeyId") @Nullable PasswordProvider accessKeyId,
       @JsonProperty("secretAccessKey") @Nullable PasswordProvider 
secretAccessKey,
       @JsonProperty("assumeRoleArn") @Nullable String assumeRoleArn,
-      @JsonProperty("assumeRoleExternalId") @Nullable String 
assumeRoleExternalId
+      @JsonProperty("assumeRoleExternalId") @Nullable String 
assumeRoleExternalId,
+      @JsonProperty("sessionToken") @Nullable PasswordProvider sessionToken
   )
   {
     this.assumeRoleArn = assumeRoleArn;
     this.assumeRoleExternalId = assumeRoleExternalId;
-    if (accessKeyId != null || secretAccessKey != null) {
-      this.accessKeyId = Preconditions.checkNotNull(accessKeyId, "accessKeyId 
cannot be null if secretAccessKey is given");
-      this.secretAccessKey = Preconditions.checkNotNull(secretAccessKey, 
"secretAccessKey cannot be null if accessKeyId is given");
+    if (sessionToken != null || accessKeyId != null || secretAccessKey != 
null) {
+      this.accessKeyId = Preconditions.checkNotNull(accessKeyId, 
"'accessKeyId' cannot be null if 'secretAccessKey' or 'sessionToken' is given");
+      this.secretAccessKey = Preconditions.checkNotNull(secretAccessKey, 
"'secretAccessKey' cannot be null if 'accessKeyId' or 'sessionToken' is given");
     } else {
       this.accessKeyId = null;
       this.secretAccessKey = null;
     }
+    this.sessionToken = sessionToken;
   }
 
   @Nullable
@@ -91,6 +94,14 @@ public class S3InputSourceConfig
     return secretAccessKey;
   }
 
+  @Nullable
+  @JsonProperty
+  @JsonInclude(JsonInclude.Include.NON_NULL)
+  public PasswordProvider getSessionToken()
+  {
+    return sessionToken;
+  }
+
   @JsonIgnore
   public boolean isCredentialsConfigured()
   {
@@ -106,6 +117,7 @@ public class S3InputSourceConfig
            ", secretAccessKey=" + secretAccessKey +
            ", assumeRoleArn=" + assumeRoleArn +
            ", assumeRoleExternalId=" + assumeRoleExternalId +
+           ", sessionToken=" + sessionToken +
            '}';
   }
 
@@ -122,12 +134,13 @@ public class S3InputSourceConfig
     return Objects.equals(accessKeyId, that.accessKeyId) &&
            Objects.equals(secretAccessKey, that.secretAccessKey) &&
            Objects.equals(assumeRoleArn, that.assumeRoleArn) &&
-           Objects.equals(assumeRoleExternalId, that.assumeRoleExternalId);
+           Objects.equals(assumeRoleExternalId, that.assumeRoleExternalId) &&
+           Objects.equals(sessionToken, that.sessionToken);
   }
 
   @Override
   public int hashCode()
   {
-    return Objects.hash(accessKeyId, secretAccessKey, assumeRoleArn, 
assumeRoleExternalId);
+    return Objects.hash(accessKeyId, secretAccessKey, assumeRoleArn, 
assumeRoleExternalId, sessionToken);
   }
 }
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/catalog/model/table/S3InputSourceDefnTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/catalog/model/table/S3InputSourceDefnTest.java
index c35bc1824bc..0aa21a478b8 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/catalog/model/table/S3InputSourceDefnTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/catalog/model/table/S3InputSourceDefnTest.java
@@ -42,7 +42,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 import javax.annotation.Nullable;
-
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -558,7 +557,7 @@ public class S3InputSourceDefnTest
   @Test
   public void testFullTableSpecHappyPath()
   {
-    S3InputSourceConfig config = new S3InputSourceConfig(null, null, "foo", 
null);
+    S3InputSourceConfig config = new S3InputSourceConfig(null, null, "foo", 
null, null);
     S3InputSource s3InputSource = s3InputSource(
         Arrays.asList("s3://foo/bar/", "s3://mumble/"), null, null, "*.csv", 
config);
     TableMetadata table = TableBuilder.external("foo")
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceConfigTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceConfigTest.java
index fbec6f8f3e8..cdcd0167f60 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceConfigTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceConfigTest.java
@@ -36,7 +36,8 @@ public class S3InputSourceConfigTest
         new DefaultPasswordProvider("the-access-key"),
         new DefaultPasswordProvider("the-secret-key"),
         null,
-        null
+        null,
+        new DefaultPasswordProvider("the-secret-token")
     );
 
     Assert.assertEquals(
@@ -53,7 +54,8 @@ public class S3InputSourceConfigTest
         null,
         null,
         "the-role-arn",
-        "the-role-external-id"
+        "the-role-external-id",
+        null
     );
 
     Assert.assertEquals(
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
index d2c2a33293f..d4891f0195e 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
@@ -158,7 +158,10 @@ public class S3InputSourceTest extends 
InitializedNullHandlingTest
   );
 
   private static final S3InputSourceConfig CLOUD_CONFIG_PROPERTIES = new 
S3InputSourceConfig(
-      new DefaultPasswordProvider("myKey"), new 
DefaultPasswordProvider("mySecret"), null, null);
+      new DefaultPasswordProvider("myKey"), new 
DefaultPasswordProvider("mySecret"), null, null, null);
+  private static final S3InputSourceConfig 
CLOUD_CONFIG_PROPERTIES_WITH_SESSION_TOKEN = new S3InputSourceConfig(
+      new DefaultPasswordProvider("myKey"), new 
DefaultPasswordProvider("mySecret"), null, null,
+      new DefaultPasswordProvider("mySessionToken"));
   private static final AWSEndpointConfig ENDPOINT_CONFIG = new 
AWSEndpointConfig();
   private static final AWSProxyConfig PROXY_CONFIG = new AWSProxyConfig();
   private static final AWSClientConfig CLIENT_CONFIG = new AWSClientConfig();
@@ -370,6 +373,152 @@ public class S3InputSourceTest extends 
InitializedNullHandlingTest
     EasyMock.verify(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
   }
 
+  @Test
+  public void testSerdeWithCloudConfigPropertiesWithSessionToken() throws 
Exception
+  {
+    EasyMock.reset(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+    
EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.getAmazonS3ClientBuilder())
+            .andStubReturn(AMAZON_S3_CLIENT_BUILDER);
+    AMAZON_S3_CLIENT_BUILDER.withClientConfiguration(CLIENT_CONFIGURATION);
+    EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.build())
+            .andReturn(SERVICE);
+    EasyMock.replay(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+    final S3InputSource withSessionToken = new S3InputSource(
+        SERVICE,
+        SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER,
+        INPUT_DATA_CONFIG,
+        null,
+        null,
+        EXPECTED_LOCATION,
+        null,
+        CLOUD_CONFIG_PROPERTIES_WITH_SESSION_TOKEN,
+        null,
+        null,
+        null
+    );
+    final S3InputSource serdeWithSessionToken =
+        MAPPER.readValue(MAPPER.writeValueAsString(withSessionToken), 
S3InputSource.class);
+    // This is to force the s3ClientSupplier to initialize the 
ServerSideEncryptingAmazonS3
+    serdeWithSessionToken.createEntity(new CloudObjectLocation("bucket", 
"path"));
+    Assert.assertEquals(withSessionToken, serdeWithSessionToken);
+    // Verify that the session token is properly set
+    Assert.assertNotNull(serdeWithSessionToken.getS3InputSourceConfig());
+    
Assert.assertNotNull(serdeWithSessionToken.getS3InputSourceConfig().getSessionToken());
+    Assert.assertEquals("mySessionToken", 
serdeWithSessionToken.getS3InputSourceConfig().getSessionToken().getPassword());
+    EasyMock.verify(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+  }
+
+  @Test
+  public void testGetSetSessionToken()
+  {
+    // Test that session token getter/setter work correctly
+    final S3InputSource inputSourceWithSessionToken = new S3InputSource(
+        SERVICE,
+        SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER,
+        INPUT_DATA_CONFIG,
+        EXPECTED_URIS,
+        null,
+        null,
+        null,
+        CLOUD_CONFIG_PROPERTIES_WITH_SESSION_TOKEN,
+        null,
+        null,
+        null
+    );
+    
+    Assert.assertNotNull(inputSourceWithSessionToken.getS3InputSourceConfig());
+    
Assert.assertNotNull(inputSourceWithSessionToken.getS3InputSourceConfig().getSessionToken());
+    Assert.assertEquals(
+        "mySessionToken",
+        
inputSourceWithSessionToken.getS3InputSourceConfig().getSessionToken().getPassword()
+    );
+    
+    // Test without session token
+    final S3InputSource inputSourceWithoutSessionToken = new S3InputSource(
+        SERVICE,
+        SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER,
+        INPUT_DATA_CONFIG,
+        EXPECTED_URIS,
+        null,
+        null,
+        null,
+        CLOUD_CONFIG_PROPERTIES,
+        null,
+        null,
+        null
+    );
+    
+    
Assert.assertNotNull(inputSourceWithoutSessionToken.getS3InputSourceConfig());
+    
Assert.assertNull(inputSourceWithoutSessionToken.getS3InputSourceConfig().getSessionToken());
+  }
+
+  @Test
+  public void testSessionCredentialsUsedWhenSessionTokenProvided() throws 
IOException
+  {
+    // This test verifies that when session token is provided, the 
S3InputSource
+    // correctly uses BasicSessionCredentials instead of BasicAWSCredentials
+    EasyMock.reset(S3_CLIENT);
+    expectListObjects(PREFIXES.get(0), ImmutableList.of(EXPECTED_URIS.get(0)), 
CONTENT);
+    expectGetObject(EXPECTED_URIS.get(0));
+    EasyMock.replay(S3_CLIENT);
+
+    EasyMock.reset(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+    
EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.getAmazonS3ClientBuilder())
+            .andStubReturn(AMAZON_S3_CLIENT_BUILDER);
+    EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.build())
+            .andReturn(SERVICE);
+    EasyMock.replay(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+
+    // Create S3InputSource with session token
+    S3InputSource inputSource = new S3InputSource(
+        SERVICE,
+        SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER,
+        INPUT_DATA_CONFIG,
+        null,
+        ImmutableList.of(PREFIXES.get(0)),
+        null,
+        null,
+        CLOUD_CONFIG_PROPERTIES_WITH_SESSION_TOKEN,
+        null,
+        null,
+        null
+    );
+
+    // Verify session token is set
+    Assert.assertNotNull(inputSource.getS3InputSourceConfig());
+    
Assert.assertNotNull(inputSource.getS3InputSourceConfig().getSessionToken());
+    Assert.assertEquals(
+        "mySessionToken",
+        inputSource.getS3InputSourceConfig().getSessionToken().getPassword()
+    );
+
+    // Create a reader which will trigger the s3ClientSupplier and use the 
session credentials
+    InputRowSchema someSchema = new InputRowSchema(
+        new TimestampSpec("time", "auto", null),
+        new 
DimensionsSpec(DimensionsSpec.getDefaultSchemas(ImmutableList.of("dim1", 
"dim2"))),
+        ColumnsFilter.all()
+    );
+
+    InputSourceReader reader = inputSource.reader(
+        someSchema,
+        new CsvInputFormat(ImmutableList.of("time", "dim1", "dim2"), "|", 
false, null, 0, null),
+        temporaryFolder.newFolder()
+    );
+
+    // Read data - this exercises the session credentials path
+    CloseableIterator<InputRow> iterator = reader.read();
+    
+    while (iterator.hasNext()) {
+      InputRow nextRow = iterator.next();
+      Assert.assertEquals(NOW, nextRow.getTimestamp());
+      Assert.assertEquals("hello", nextRow.getDimension("dim1").get(0));
+      Assert.assertEquals("world", nextRow.getDimension("dim2").get(0));
+    }
+
+    EasyMock.verify(S3_CLIENT);
+    EasyMock.verify(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+  }
+
   @Test
   public void testGetTypes()
   {
diff --git 
a/multi-stage-query/src/main/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtils.java
 
b/multi-stage-query/src/main/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtils.java
index 2e9e67a7534..955bc3483c1 100644
--- 
a/multi-stage-query/src/main/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtils.java
+++ 
b/multi-stage-query/src/main/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtils.java
@@ -40,7 +40,7 @@ import java.util.stream.Collectors;
 public class MSQTaskQueryMakerUtils
 {
 
-  public static final Set<String> SENSISTIVE_JSON_KEYS = 
ImmutableSet.of("accessKeyId", "secretAccessKey");
+  public static final Set<String> SENSISTIVE_JSON_KEYS = 
ImmutableSet.of("accessKeyId", "secretAccessKey", "sessionToken");
   public static final Set<Pattern> SENSITIVE_KEYS_REGEX_PATTERNS = 
SENSISTIVE_JSON_KEYS.stream()
                                                                                
        .map(sensitiveKey ->
                                                                                
                  Pattern.compile(
diff --git 
a/multi-stage-query/src/test/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtilsTest.java
 
b/multi-stage-query/src/test/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtilsTest.java
index bb0bdcd34d1..8febf4bfdc2 100644
--- 
a/multi-stage-query/src/test/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtilsTest.java
+++ 
b/multi-stage-query/src/test/java/org/apache/druid/msq/util/MSQTaskQueryMakerUtilsTest.java
@@ -57,7 +57,7 @@ public class MSQTaskQueryMakerUtilsTest
                   + "OVERWRITE ALL\\n"
                   + "WITH ext AS "
                   + "(SELECT *\\nFROM TABLE(\\n  "
-                  + "EXTERN(\\n    
'{\\\"type\\\":\\\"s3\\\",\\\"prefixes\\\":[\\\"s3://prefix\\\"],\\\"properties\\\":{\\\"accessKeyId\\\":{\\\"type\\\":\\\"default\\\",\\\"password\\\":\\\"secret_pass\\\"},\\\"secretAccessKey\\\":{\\\"type\\\":\\\"default\\\",\\\"password\\\":\\\"secret_pass\\\"}}}',\\n"
+                  + "EXTERN(\\n    
'{\\\"type\\\":\\\"s3\\\",\\\"prefixes\\\":[\\\"s3://prefix\\\"],\\\"properties\\\":{\\\"accessKeyId\\\":{\\\"type\\\":\\\"default\\\",\\\"password\\\":\\\"secret_pass\\\"},\\\"secretAccessKey\\\":{\\\"type\\\":\\\"default\\\",\\\"password\\\":\\\"secret_pass\\\"},\\\"sessionToken\\\":{\\\"type\\\":\\\"default\\\",\\\"password\\\":\\\"secret_pass\\\"}}}',\\n"
                   + "'{\\\"type\\\":\\\"json\\\"}',\\n"
                   + 
"'[{\\\"name\\\":\\\"time\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"}]'\\n
  )\\n))\\n"
                   + "SELECT\\n  TIME_PARSE(\\\"time\\\") AS __time,\\n  
name,\\n  country "
@@ -113,7 +113,7 @@ public class MSQTaskQueryMakerUtilsTest
         + "OVERWRITE ALL\\n"
         + "WITH ext AS "
         + "(SELECT *\\nFROM TABLE(\\n  "
-        + "EXTERN(\\n    
'{\\\"type\\\":\\\"s3\\\",\\\"prefixes\\\":[\\\"s3://prefix\\\"],\\\"properties\\\":{\\\"accessKeyId\\\":<masked>,\\\"secretAccessKey\\\":<masked>}}',\\n"
+        + "EXTERN(\\n    
'{\\\"type\\\":\\\"s3\\\",\\\"prefixes\\\":[\\\"s3://prefix\\\"],\\\"properties\\\":{\\\"accessKeyId\\\":<masked>,\\\"secretAccessKey\\\":<masked>,\\\"sessionToken\\\":<masked>}}',\\n"
         + "'{\\\"type\\\":\\\"json\\\"}',\\n"
         + 
"'[{\\\"name\\\":\\\"time\\\",\\\"type\\\":\\\"string\\\"},{\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"}]'\\n
  )\\n))\\n"
         + "SELECT\\n  TIME_PARSE(\\\"time\\\") AS __time,\\n  name,\\n  
country "
diff --git a/website/.spelling b/website/.spelling
index 767ef4249ab..82711ff8442 100644
--- a/website/.spelling
+++ b/website/.spelling
@@ -1481,6 +1481,7 @@ httpAuthenticationPassword
 accessKeyId
 secretAccessKey
 accessKeyId
+sessionToken
 httpAuthenticationPassword
 countryName
 appendToExisting


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to