diff --git a/bolt-jakarta-servlet/pom.xml b/bolt-jakarta-servlet/pom.xml index 1702a947e..ceb2f1f61 100644 --- a/bolt-jakarta-servlet/pom.xml +++ b/bolt-jakarta-servlet/pom.xml @@ -61,8 +61,8 @@ test - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ${aws.s3.version} test diff --git a/bolt-kotlin-examples/pom.xml b/bolt-kotlin-examples/pom.xml index ea3fe6639..d12e0dc78 100644 --- a/bolt-kotlin-examples/pom.xml +++ b/bolt-kotlin-examples/pom.xml @@ -41,8 +41,8 @@ - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ${aws.s3.version} diff --git a/bolt-servlet/pom.xml b/bolt-servlet/pom.xml index 02ff581c0..d41fdeb43 100644 --- a/bolt-servlet/pom.xml +++ b/bolt-servlet/pom.xml @@ -66,8 +66,8 @@ test - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ${aws.s3.version} test diff --git a/bolt/pom.xml b/bolt/pom.xml index 66c0f22dc..8469330aa 100644 --- a/bolt/pom.xml +++ b/bolt/pom.xml @@ -41,8 +41,8 @@ - com.amazonaws - aws-java-sdk-s3 + software.amazon.awssdk + s3 ${aws.s3.version} provided diff --git a/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3InstallationService.java b/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3InstallationService.java index 7402f31f5..5aaa58b85 100644 --- a/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3InstallationService.java +++ b/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3InstallationService.java @@ -1,11 +1,5 @@ package com.slack.api.bolt.service.builtin; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.*; -import com.amazonaws.util.IOUtils; import com.slack.api.bolt.Initializer; import com.slack.api.bolt.model.Bot; import com.slack.api.bolt.model.Installer; @@ -14,14 +8,25 @@ import com.slack.api.bolt.service.InstallationService; import com.slack.api.bolt.util.JsonOps; import lombok.extern.slf4j.Slf4j; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.*; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.Optional; @Slf4j public class AmazonS3InstallationService implements InstallationService { private final String bucketName; + private AwsCredentialsProvider credentialsProvider; private boolean historicalDataEnabled; public AmazonS3InstallationService(String bucketName) { @@ -32,16 +37,25 @@ public AmazonS3InstallationService(String bucketName) { public Initializer initializer() { return (app) -> { // The first access to S3 tends to be slow on AWS Lambda. - AWSCredentials credentials = getCredentials(); - if (credentials == null || credentials.getAWSAccessKeyId() == null) { + this.credentialsProvider = DefaultCredentialsProvider.create(); + AwsCredentials credentials = createCredentials(credentialsProvider); + if (credentials == null || credentials.accessKeyId() == null) { throw new IllegalStateException("AWS credentials not found"); } if (log.isDebugEnabled()) { - log.debug("AWS credentials loaded (access key id: {})", credentials.getAWSAccessKeyId()); + log.debug("AWS credentials loaded (access key id: {})", credentials.accessKeyId()); + } + boolean bucketExists = false; + Exception ex = null; + try (S3Client s3 = createS3Client()) { + bucketExists = s3.headBucket(HeadBucketRequest.builder().bucket(bucketName).build()) != null; + } catch (Exception e) { // NoSuchBucketException etc. + ex = e; } - boolean bucketExists = createS3Client().doesBucketExistV2(bucketName); if (!bucketExists) { - throw new IllegalStateException("Failed to access the Amazon S3 bucket (name: " + bucketName + ")"); + String error = ex != null ? ex.getClass().getName() + ":" + ex.getMessage() : "-"; + String message = "Failed to access the Amazon S3 bucket (name: " + bucketName + ", error: " + error + ")"; + throw new IllegalStateException(message); } }; } @@ -58,60 +72,73 @@ public void setHistoricalDataEnabled(boolean isHistoricalDataEnabled) { @Override public void saveInstallerAndBot(Installer i) throws Exception { - AmazonS3 s3 = this.createS3Client(); - if (isHistoricalDataEnabled()) { - save(s3, getInstallerKey(i) + "-latest", JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); - save(s3, getBotKey(i) + "-latest", JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); - save(s3, getInstallerKey(i) + "-" + i.getInstalledAt(), JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); - save(s3, getBotKey(i) + "-" + i.getInstalledAt(), JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); - } else { - save(s3, getInstallerKey(i), JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); - save(s3, getBotKey(i), JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); + try (S3Client s3 = this.createS3Client()) { + if (isHistoricalDataEnabled()) { + save(s3, getInstallerKey(i) + "-latest", JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); + save(s3, getBotKey(i) + "-latest", JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); + save(s3, getInstallerKey(i) + "-" + i.getInstalledAt(), JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); + save(s3, getBotKey(i) + "-" + i.getInstalledAt(), JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); + } else { + save(s3, getInstallerKey(i), JsonOps.toJsonString(i), "AWS S3 putObject result of Installer data - {}, {}"); + save(s3, getBotKey(i), JsonOps.toJsonString(i.toBot()), "AWS S3 putObject result of Bot data - {}, {}"); + } } } @Override public void saveBot(Bot bot) throws Exception { - AmazonS3 s3 = this.createS3Client(); - String keyPrefix = getBotKey(bot.getEnterpriseId(), bot.getTeamId()); - if (isHistoricalDataEnabled()) { - save(s3, keyPrefix + "-latest", JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); - save(s3, keyPrefix + "-" + bot.getInstalledAt(), JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); - } else { - save(s3, keyPrefix, JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); + try (S3Client s3 = this.createS3Client()) { + String keyPrefix = getBotKey(bot.getEnterpriseId(), bot.getTeamId()); + if (isHistoricalDataEnabled()) { + save(s3, keyPrefix + "-latest", JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); + save(s3, keyPrefix + "-" + bot.getInstalledAt(), JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); + } else { + save(s3, keyPrefix, JsonOps.toJsonString(bot), "AWS S3 putObject result of Bot data - {}, {}"); + } } } - private void save(AmazonS3 s3, String s3Key, String json, String logMessage) { - PutObjectResult botPutResult = s3.putObject(bucketName, s3Key, json); + private void save(S3Client s3, String s3Key, String json, String logMessage) { + PutObjectResponse botPutResult = s3.putObject( + PutObjectRequest.builder().bucket(bucketName).key(s3Key).build(), + RequestBody.fromString(json) + ); if (log.isDebugEnabled()) { - log.debug(logMessage, s3Key, JsonOps.toJsonString(botPutResult)); + log.debug(logMessage, s3Key, botPutResult.toString()); } } @Override public void deleteBot(Bot bot) throws Exception { - AmazonS3 s3 = this.createS3Client(); - String key = getBotKey(bot.getEnterpriseId(), bot.getTeamId()); - if (isHistoricalDataEnabled()) { - key = key + "-latest"; + try (S3Client s3 = this.createS3Client()) { + String key = getBotKey(bot.getEnterpriseId(), bot.getTeamId()); + if (isHistoricalDataEnabled()) { + key = key + "-latest"; + } + if (log.isDebugEnabled()) { + log.debug("Going to delete an object (bucket: {}, key: {})", bucketName, key); + } + s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(key).build()); } - s3.deleteObject(bucketName, key); } @Override public void deleteInstaller(Installer installer) throws Exception { - AmazonS3 s3 = this.createS3Client(); - String key = getInstallerKey(installer); - if (isHistoricalDataEnabled()) { - key = key + "-latest"; + try (S3Client s3 = this.createS3Client()) { + String key = getInstallerKey(installer); + if (isHistoricalDataEnabled()) { + key = key + "-latest"; + } + if (log.isDebugEnabled()) { + log.debug("Going to delete an object (bucket: {}, key: {})", bucketName, key); + } + s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(key).build()); } - s3.deleteObject(bucketName, key); } @Override public Bot findBot(String enterpriseId, String teamId) { - AmazonS3 s3 = this.createS3Client(); + S3Client s3 = this.createS3Client(); if (enterpriseId != null) { // try finding org-level bot token first - teamId is intentionally null here String fullKey = getBotKey(enterpriseId, null); @@ -119,7 +146,7 @@ public Bot findBot(String enterpriseId, String teamId) { fullKey = fullKey + "-latest"; } if (getObjectMetadata(s3, fullKey) != null) { - S3Object s3Object = getObject(s3, fullKey); + ResponseBytes s3Object = getObject(s3, fullKey); try { return toBot(s3Object); } catch (IOException e) { @@ -137,7 +164,7 @@ public Bot findBot(String enterpriseId, String teamId) { if (isHistoricalDataEnabled()) { nonGridKey = nonGridKey + "-latest"; } - S3Object nonGridObject = getObject(s3, nonGridKey); + ResponseBytes nonGridObject = getObject(s3, nonGridKey); if (nonGridObject != null) { try { Bot bot = toBot(nonGridObject); @@ -149,7 +176,7 @@ public Bot findBot(String enterpriseId, String teamId) { } } } - S3Object s3Object = getObject(s3, fullKey); + ResponseBytes s3Object = getObject(s3, fullKey); try { return toBot(s3Object); } catch (IOException e) { @@ -160,7 +187,7 @@ public Bot findBot(String enterpriseId, String teamId) { @Override public Installer findInstaller(String enterpriseId, String teamId, String userId) { - AmazonS3 s3 = this.createS3Client(); + S3Client s3 = this.createS3Client(); if (enterpriseId != null) { // try finding org-level user token first - teamId is intentionally null here String fullKey = getInstallerKey(enterpriseId, null, userId); @@ -168,7 +195,7 @@ public Installer findInstaller(String enterpriseId, String teamId, String userId fullKey = fullKey + "-latest"; } if (getObjectMetadata(s3, fullKey) != null) { - S3Object s3Object = getObject(s3, fullKey); + ResponseBytes s3Object = getObject(s3, fullKey); try { return toInstaller(s3Object); } catch (IOException e) { @@ -186,7 +213,7 @@ public Installer findInstaller(String enterpriseId, String teamId, String userId if (isHistoricalDataEnabled()) { nonGridKey = nonGridKey + "-latest"; } - S3Object nonGridObject = getObject(s3, nonGridKey); + ResponseBytes nonGridObject = getObject(s3, nonGridKey); if (nonGridObject != null) { try { Installer installer = toInstaller(nonGridObject); @@ -199,7 +226,7 @@ public Installer findInstaller(String enterpriseId, String teamId, String userId } } } - S3Object s3Object = getObject(s3, fullKey); + ResponseBytes s3Object = getObject(s3, fullKey); try { return toInstaller(s3Object); } catch (Exception e) { @@ -211,7 +238,7 @@ public Installer findInstaller(String enterpriseId, String teamId, String userId @Override public void deleteAll(String enterpriseId, String teamId) { - AmazonS3 s3 = this.createS3Client(); + S3Client s3 = this.createS3Client(); deleteAllObjectsMatchingPrefix(s3, "installer/" + Optional.ofNullable(enterpriseId).orElse("none") + "-" @@ -222,56 +249,62 @@ public void deleteAll(String enterpriseId, String teamId) { + Optional.ofNullable(teamId).orElse("none")); } - private void deleteAllObjectsMatchingPrefix(AmazonS3 s3, String prefix) { - for (S3ObjectSummary obj : s3.listObjects(bucketName, prefix).getObjectSummaries()) { - s3.deleteObject(bucketName, obj.getKey()); + private void deleteAllObjectsMatchingPrefix(S3Client s3, String prefix) { + for (S3Object obj : s3.listObjectsV2(ListObjectsV2Request.builder().bucket(bucketName).prefix(prefix).build()).contents()) { + if (log.isDebugEnabled()) { + log.debug("Going to delete an object (bucket: {}, key: {})", bucketName, obj.key()); + } + s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(obj.key()).build()); } } - private ObjectMetadata getObjectMetadata(AmazonS3 s3, String fullKey) { + private Map getObjectMetadata(S3Client s3, String fullKey) { try { - return s3.getObjectMetadata(bucketName, fullKey); - } catch (AmazonS3Exception e) { + return s3.headObject(HeadObjectRequest.builder().bucket(bucketName).key(fullKey).build()).metadata(); + } catch (S3Exception e) { if (log.isDebugEnabled()) { - log.debug("Amazon S3 object metadata not found (key: {}, AmazonS3Exception: {})", fullKey, e.toString()); + log.debug("Amazon S3 object metadata not found (key: {}, S3Exception: {})", fullKey, e.toString()); } return null; } } - private S3Object getObject(AmazonS3 s3, String fullKey) { + private ResponseBytes getObject(S3Client s3, String fullKey) { try { - return s3.getObject(bucketName, fullKey); - } catch (AmazonS3Exception e) { + return s3.getObject( + GetObjectRequest.builder().bucket(bucketName).key(fullKey).build(), + ResponseTransformer.toBytes() + ); + } catch (S3Exception e) { if (log.isDebugEnabled()) { - log.debug("Amazon S3 object metadata not found (key: {}, AmazonS3Exception: {})", fullKey, e.toString()); + log.debug("Amazon S3 object metadata not found (key: {}, S3Exception: {})", fullKey, e.toString()); } return null; } } - private Bot toBot(S3Object s3Object) throws IOException { + private Bot toBot(ResponseBytes s3Object) throws IOException { if (s3Object == null) { return null; } - String json = IOUtils.toString(s3Object.getObjectContent()); + String json = s3Object.asString(StandardCharsets.UTF_8); return JsonOps.fromJson(json, DefaultBot.class); } - private Installer toInstaller(S3Object s3Object) throws IOException { + private Installer toInstaller(ResponseBytes s3Object) throws IOException { if (s3Object == null) { return null; } - String json = IOUtils.toString(s3Object.getObjectContent()); + String json = s3Object.asString(StandardCharsets.UTF_8); return JsonOps.fromJson(json, DefaultInstaller.class); } - protected AWSCredentials getCredentials() { - return DefaultAWSCredentialsProviderChain.getInstance().getCredentials(); + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { + return provider.resolveCredentials(); } - protected AmazonS3 createS3Client() { - return AmazonS3ClientBuilder.defaultClient(); + protected S3Client createS3Client() { + return S3Client.builder().credentialsProvider(this.credentialsProvider).build(); } private String getInstallerKey(Installer i) { diff --git a/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3OAuthStateService.java b/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3OAuthStateService.java index 6dc926a14..83760ea35 100644 --- a/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3OAuthStateService.java +++ b/bolt/src/main/java/com/slack/api/bolt/service/builtin/AmazonS3OAuthStateService.java @@ -1,19 +1,18 @@ package com.slack.api.bolt.service.builtin; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.AmazonS3Exception; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.util.IOUtils; import com.slack.api.bolt.Initializer; import com.slack.api.bolt.service.OAuthStateService; -import com.slack.api.bolt.util.JsonOps; import lombok.extern.slf4j.Slf4j; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.*; -import java.io.IOException; +import java.nio.charset.StandardCharsets; /** * OAuthStateService implementation using Amazon S3. @@ -24,6 +23,7 @@ public class AmazonS3OAuthStateService implements OAuthStateService { private final String bucketName; + private AwsCredentialsProvider credentialsProvider; public AmazonS3OAuthStateService(String bucketName) { this.bucketName = bucketName; @@ -33,74 +33,92 @@ public AmazonS3OAuthStateService(String bucketName) { public Initializer initializer() { return (app) -> { // The first access to S3 tends to be slow on AWS Lambda. - AWSCredentials credentials = getCredentials(); - if (credentials == null || credentials.getAWSAccessKeyId() == null) { + this.credentialsProvider = DefaultCredentialsProvider.create(); + AwsCredentials credentials = createCredentials(credentialsProvider); + if (credentials == null || credentials.accessKeyId() == null) { throw new IllegalStateException("AWS credentials not found"); } if (log.isDebugEnabled()) { - log.debug("AWS credentials loaded (access key id: {})", credentials.getAWSAccessKeyId()); + log.debug("AWS credentials loaded (access key id: {})", credentials.accessKeyId()); + } + boolean bucketExists = false; + Exception ex = null; + try (S3Client s3 = createS3Client()) { + bucketExists = s3.headBucket(HeadBucketRequest.builder().bucket(bucketName).build()) != null; + } catch (Exception e) { // NoSuchBucketException etc. + ex = e; } - boolean bucketExists = createS3Client().doesBucketExistV2(bucketName); if (!bucketExists) { - throw new IllegalStateException("Failed to access the Amazon S3 bucket (name: " + bucketName + ")"); + String error = ex != null ? ex.getClass().getName() + ":" + ex.getMessage() : "-"; + String message = "Failed to access the Amazon S3 bucket (name: " + bucketName + ", error: " + error + ")"; + throw new IllegalStateException(message); } }; } @Override public void addNewStateToDatastore(String state) throws Exception { - AmazonS3 s3 = this.createS3Client(); - String value = "" + (System.currentTimeMillis() + getExpirationInSeconds() * 1000); - PutObjectResult putObjectResult = s3.putObject(bucketName, getKey(state), value); + PutObjectResponse putObjectResult; + try (S3Client s3 = this.createS3Client()) { + String value = "" + (System.currentTimeMillis() + getExpirationInSeconds() * 1000); + putObjectResult = s3.putObject( + PutObjectRequest.builder().bucket(bucketName).key(getKey(state)).build(), + RequestBody.fromString(value) + ); + } if (log.isDebugEnabled()) { - log.debug("AWS S3 putObject result of state data - {}", JsonOps.toJsonString(putObjectResult)); + log.debug("AWS S3 putObject result of state data - {}", putObjectResult.toString()); } } @Override public boolean isAvailableInDatabase(String state) { - AmazonS3 s3 = this.createS3Client(); - S3Object s3Object = getObject(s3, getKey(state)); + S3Client s3 = this.createS3Client(); + ResponseBytes s3Object = getObject(s3, getKey(state)); if (s3Object == null) { return false; } String millisToExpire = null; try { - millisToExpire = IOUtils.toString(s3Object.getObjectContent()); - return Long.valueOf(millisToExpire) > System.currentTimeMillis(); - } catch (IOException e) { - log.error("Failed to load a state data for state: {}", state, e); - return false; + millisToExpire = s3Object.asString(StandardCharsets.UTF_8); + return Long.parseLong(millisToExpire) > System.currentTimeMillis(); } catch (NumberFormatException ne) { log.error("Invalid state value detected - state: {}, millisToExpire: {}", state, millisToExpire); return false; + } catch (Exception e) { + log.error("Failed to load a state data for state: {}", state, e); + return false; } } @Override public void deleteStateFromDatastore(String state) throws Exception { - AmazonS3 s3 = this.createS3Client(); - s3.deleteObject(bucketName, getKey(state)); + try (S3Client s3 = this.createS3Client()) { + s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(getKey(state)).build()); + } } - protected AWSCredentials getCredentials() { - return DefaultAWSCredentialsProviderChain.getInstance().getCredentials(); + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { + return provider.resolveCredentials(); } - protected AmazonS3 createS3Client() { - return AmazonS3ClientBuilder.defaultClient(); + protected S3Client createS3Client() { + return S3Client.builder().credentialsProvider(this.credentialsProvider).build(); } private String getKey(String state) { return "state/" + state; } - private S3Object getObject(AmazonS3 s3, String fullKey) { + private ResponseBytes getObject(S3Client s3, String fullKey) { try { - return s3.getObject(bucketName, fullKey); - } catch (AmazonS3Exception e) { + return s3.getObject( + GetObjectRequest.builder().bucket(bucketName).key(fullKey).build(), + ResponseTransformer.toBytes() + ); + } catch (Exception e) { if (log.isDebugEnabled()) { - log.debug("Amazon S3 object metadata not found (key: {}, AmazonS3Exception: {})", fullKey, e.toString()); + log.debug("Amazon S3 object metadata not found (key: {}, Exception: {})", fullKey, e.toString()); } return null; } diff --git a/bolt/src/test/java/test_locally/service/AmazonS3InstallationServiceTest.java b/bolt/src/test/java/test_locally/service/AmazonS3InstallationServiceTest.java index f347c78fc..49d739cec 100644 --- a/bolt/src/test/java/test_locally/service/AmazonS3InstallationServiceTest.java +++ b/bolt/src/test/java/test_locally/service/AmazonS3InstallationServiceTest.java @@ -1,47 +1,44 @@ package test_locally.service; -import com.amazonaws.SdkClientException; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.services.s3.AmazonS3; import com.slack.api.bolt.model.builtin.DefaultBot; import com.slack.api.bolt.model.builtin.DefaultInstaller; import com.slack.api.bolt.service.builtin.AmazonS3InstallationService; import org.junit.Test; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.*; + +import java.nio.charset.StandardCharsets; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.*; public class AmazonS3InstallationServiceTest { - @Test(expected = IllegalStateException.class) - public void initializer_no_credentials() { - AmazonS3 s3 = mock(AmazonS3.class); - AmazonS3InstallationService service = new AmazonS3InstallationService("test-bucket") { - @Override - protected AWSCredentials getCredentials() { - return null; - } - - @Override - protected AmazonS3 createS3Client() { - return s3; - } - }; - service.initializer().accept(null); + static S3Client setupMocks(S3Client s3) { + when(s3.headBucket((HeadBucketRequest) notNull())).thenReturn(HeadBucketResponse.builder().build()); + when(s3.headObject((HeadObjectRequest) notNull())).thenReturn(HeadObjectResponse.builder().build()); + when(s3.getObject((GetObjectRequest) notNull(), (ResponseTransformer>) notNull())) + .thenReturn(ResponseBytes.fromByteArray(GetObjectResponse.builder().build(), "{}".getBytes(StandardCharsets.UTF_8))); + when(s3.putObject((PutObjectRequest) notNull(), (RequestBody) notNull())).thenReturn(PutObjectResponse.builder().build()); + return s3; } @Test(expected = IllegalStateException.class) - public void initializer_no_bucket() { - AWSCredentials credentials = mock(AWSCredentials.class); - AmazonS3 s3 = mock(AmazonS3.class); + public void initializer_no_credentials() { + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3InstallationService service = new AmazonS3InstallationService("test-bucket") { @Override - protected AWSCredentials getCredentials() { - return credentials; + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { + return null; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -50,19 +47,18 @@ protected AmazonS3 createS3Client() { @Test public void initializer() { - AWSCredentials credentials = mock(AWSCredentials.class); - when(credentials.getAWSAccessKeyId()).thenReturn("valid key"); - AmazonS3 s3 = mock(AmazonS3.class); - when(s3.doesBucketExistV2(anyString())).thenReturn(true); + AwsCredentials credentials = mock(AwsCredentials.class); + when(credentials.accessKeyId()).thenReturn("valid key"); + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3InstallationService service = new AmazonS3InstallationService("test-bucket") { @Override - protected AWSCredentials getCredentials() { + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { return credentials; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -71,19 +67,18 @@ protected AmazonS3 createS3Client() { @Test public void operations() throws Exception { - AWSCredentials credentials = mock(AWSCredentials.class); - when(credentials.getAWSAccessKeyId()).thenReturn("valid key"); - AmazonS3 s3 = mock(AmazonS3.class); - when(s3.doesBucketExistV2(anyString())).thenReturn(true); + AwsCredentials credentials = mock(AwsCredentials.class); + when(credentials.accessKeyId()).thenReturn("valid key"); + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3InstallationService service = new AmazonS3InstallationService("test-bucket") { @Override - protected AWSCredentials getCredentials() { + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { return credentials; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -98,19 +93,18 @@ protected AmazonS3 createS3Client() { @Test public void operations_historical_data_enabled() throws Exception { - AWSCredentials credentials = mock(AWSCredentials.class); - when(credentials.getAWSAccessKeyId()).thenReturn("valid key"); - AmazonS3 s3 = mock(AmazonS3.class); - when(s3.doesBucketExistV2(anyString())).thenReturn(true); + AwsCredentials credentials = mock(AwsCredentials.class); + when(credentials.accessKeyId()).thenReturn("valid key"); + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3InstallationService service = new AmazonS3InstallationService("test-bucket") { @Override - protected AWSCredentials getCredentials() { + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { return credentials; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -129,32 +123,18 @@ public MyService(String bucketName) { super(bucketName); } - public AWSCredentials credentials() { - return getCredentials(); - } - - public AmazonS3 s3() { + public S3Client s3() { return createS3Client(); } } - @Test - public void credentials() { - MyService service = new MyService("test-bucket"); - try { - AWSCredentials credentials = service.credentials(); - assertNotNull(credentials); - } catch (SdkClientException ignored) { - } - } - @Test public void s3() { MyService service = new MyService("test-bucket"); try { - AmazonS3 s3 = service.s3(); + S3Client s3 = service.s3(); assertNotNull(s3); - } catch (SdkClientException ignored) { + } catch (Exception ignored) { } } diff --git a/bolt/src/test/java/test_locally/service/AmazonS3OAuthStateServiceTest.java b/bolt/src/test/java/test_locally/service/AmazonS3OAuthStateServiceTest.java index ec5678a2b..76f4631f2 100644 --- a/bolt/src/test/java/test_locally/service/AmazonS3OAuthStateServiceTest.java +++ b/bolt/src/test/java/test_locally/service/AmazonS3OAuthStateServiceTest.java @@ -1,43 +1,41 @@ package test_locally.service; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.services.s3.AmazonS3; import com.slack.api.bolt.service.builtin.AmazonS3OAuthStateService; import org.junit.Test; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.*; + +import java.nio.charset.StandardCharsets; import static org.mockito.Mockito.*; public class AmazonS3OAuthStateServiceTest { - @Test(expected = IllegalStateException.class) - public void initializer_no_credentials() { - AmazonS3 s3 = mock(AmazonS3.class); - AmazonS3OAuthStateService service = new AmazonS3OAuthStateService("test-bucket") { - @Override - protected AWSCredentials getCredentials() { - return null; - } - - @Override - protected AmazonS3 createS3Client() { - return s3; - } - }; - service.initializer().accept(null); + static S3Client setupMocks(S3Client s3) { + when(s3.headBucket((HeadBucketRequest) notNull())).thenReturn(HeadBucketResponse.builder().build()); + when(s3.headObject((HeadObjectRequest) notNull())).thenReturn(HeadObjectResponse.builder().build()); + when(s3.getObject((GetObjectRequest) notNull(), (ResponseTransformer>) notNull())) + .thenReturn(ResponseBytes.fromByteArray(GetObjectResponse.builder().build(), "{}".getBytes(StandardCharsets.UTF_8))); + when(s3.putObject((PutObjectRequest) notNull(), (RequestBody) notNull())).thenReturn(PutObjectResponse.builder().build()); + return s3; } @Test(expected = IllegalStateException.class) - public void initializer_no_bucket() { - AWSCredentials credentials = mock(AWSCredentials.class); - AmazonS3 s3 = mock(AmazonS3.class); + public void initializer_no_credentials() { + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3OAuthStateService service = new AmazonS3OAuthStateService("test-bucket") { @Override - protected AWSCredentials getCredentials() { - return credentials; + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { + return null; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -46,19 +44,18 @@ protected AmazonS3 createS3Client() { @Test public void initializer() { - AWSCredentials credentials = mock(AWSCredentials.class); - when(credentials.getAWSAccessKeyId()).thenReturn("valid key"); - AmazonS3 s3 = mock(AmazonS3.class); - when(s3.doesBucketExistV2(anyString())).thenReturn(true); + AwsCredentials credentials = mock(AwsCredentials.class); + when(credentials.accessKeyId()).thenReturn("valid key"); + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3OAuthStateService service = new AmazonS3OAuthStateService("test-bucket") { @Override - protected AWSCredentials getCredentials() { + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { return credentials; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; @@ -67,19 +64,18 @@ protected AmazonS3 createS3Client() { @Test public void operations() throws Exception { - AWSCredentials credentials = mock(AWSCredentials.class); - when(credentials.getAWSAccessKeyId()).thenReturn("valid key"); - AmazonS3 s3 = mock(AmazonS3.class); - when(s3.doesBucketExistV2(anyString())).thenReturn(true); + AwsCredentials credentials = mock(AwsCredentials.class); + when(credentials.accessKeyId()).thenReturn("valid key"); + S3Client s3 = setupMocks(mock(S3Client.class)); AmazonS3OAuthStateService service = new AmazonS3OAuthStateService("test-bucket") { @Override - protected AWSCredentials getCredentials() { + protected AwsCredentials createCredentials(AwsCredentialsProvider provider) { return credentials; } @Override - protected AmazonS3 createS3Client() { + protected S3Client createS3Client() { return s3; } }; diff --git a/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3InstallationServiceTest.java b/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3InstallationServiceTest.java index dc0be1afd..5f86e731d 100644 --- a/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3InstallationServiceTest.java +++ b/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3InstallationServiceTest.java @@ -9,6 +9,7 @@ public class AmazonS3InstallationServiceTest { @Test(expected = IllegalStateException.class) public void init() { + // To avoid accessing existing buckets String bucketName = "java-slack-sdk-test-dummy-bucket" + UUID.randomUUID(); AmazonS3InstallationService service = new AmazonS3InstallationService(bucketName); service.initializer().accept(null); diff --git a/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3OAuthStateServiceTest.java b/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3OAuthStateServiceTest.java index 7aeeb2045..523801c8d 100644 --- a/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3OAuthStateServiceTest.java +++ b/bolt/src/test/java/test_with_remote_apis/service/aws/AmazonS3OAuthStateServiceTest.java @@ -9,6 +9,7 @@ public class AmazonS3OAuthStateServiceTest { @Test(expected = IllegalStateException.class) public void init() { + // To avoid accessing existing buckets String bucketName = "java-slack-sdk-test-dummy-bucket" + UUID.randomUUID(); AmazonS3OAuthStateService service = new AmazonS3OAuthStateService(bucketName); service.initializer().accept(null); diff --git a/pom.xml b/pom.xml index 9752a3d53..f8db5dc19 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ [11.0,11.1) [4.0,5.0) - [1.12.62,1.13.0) + [2.29.24,3) 4.13.2 1.2.11 1.4.7