11package com .slack .api .bolt .service .builtin ;
22
3- import com .amazonaws .auth .AWSCredentials ;
4- import com .amazonaws .auth .DefaultAWSCredentialsProviderChain ;
5- import com .amazonaws .services .s3 .AmazonS3 ;
6- import com .amazonaws .services .s3 .AmazonS3ClientBuilder ;
7- import com .amazonaws .services .s3 .model .AmazonS3Exception ;
8- import com .amazonaws .services .s3 .model .PutObjectResult ;
9- import com .amazonaws .services .s3 .model .S3Object ;
10- import com .amazonaws .util .IOUtils ;
113import com .slack .api .bolt .Initializer ;
124import com .slack .api .bolt .service .OAuthStateService ;
13- import com .slack .api .bolt .util .JsonOps ;
145import lombok .extern .slf4j .Slf4j ;
6+ import software .amazon .awssdk .auth .credentials .AwsCredentials ;
7+ import software .amazon .awssdk .auth .credentials .AwsCredentialsProvider ;
8+ import software .amazon .awssdk .auth .credentials .DefaultCredentialsProvider ;
9+ import software .amazon .awssdk .core .ResponseBytes ;
10+ import software .amazon .awssdk .core .sync .RequestBody ;
11+ import software .amazon .awssdk .core .sync .ResponseTransformer ;
12+ import software .amazon .awssdk .services .s3 .S3Client ;
13+ import software .amazon .awssdk .services .s3 .model .*;
1514
16- import java .io . IOException ;
15+ import java .nio . charset . StandardCharsets ;
1716
1817/**
1918 * OAuthStateService implementation using Amazon S3.
2423public class AmazonS3OAuthStateService implements OAuthStateService {
2524
2625 private final String bucketName ;
26+ private AwsCredentialsProvider credentialsProvider ;
2727
2828 public AmazonS3OAuthStateService (String bucketName ) {
2929 this .bucketName = bucketName ;
@@ -33,74 +33,91 @@ public AmazonS3OAuthStateService(String bucketName) {
3333 public Initializer initializer () {
3434 return (app ) -> {
3535 // The first access to S3 tends to be slow on AWS Lambda.
36- AWSCredentials credentials = getCredentials ();
37- if (credentials == null || credentials .getAWSAccessKeyId () == null ) {
36+ this .credentialsProvider = DefaultCredentialsProvider .create ();
37+ AwsCredentials credentials = createCredentials (credentialsProvider );
38+ if (credentials == null || credentials .accessKeyId () == null ) {
3839 throw new IllegalStateException ("AWS credentials not found" );
3940 }
4041 if (log .isDebugEnabled ()) {
41- log .debug ("AWS credentials loaded (access key id: {})" , credentials .getAWSAccessKeyId ());
42+ log .debug ("AWS credentials loaded (access key id: {})" , credentials .accessKeyId ());
43+ }
44+ boolean bucketExists = false ;
45+ Exception error = null ;
46+ try (S3Client s3 = createS3Client ()) {
47+ bucketExists = s3 .headBucket (HeadBucketRequest .builder ().bucket (bucketName ).build ()) != null ;
48+ } catch (Exception e ) { // NoSuchBucketException etc.
49+ error = e ;
4250 }
43- boolean bucketExists = createS3Client ().doesBucketExistV2 (bucketName );
4451 if (!bucketExists ) {
45- throw new IllegalStateException ("Failed to access the Amazon S3 bucket (name: " + bucketName + ")" );
52+ String message = "Failed to access the Amazon S3 bucket (name: " + bucketName + ", error: " + error + ")" ;
53+ throw new IllegalStateException (message );
4654 }
4755 };
4856 }
4957
5058 @ Override
5159 public void addNewStateToDatastore (String state ) throws Exception {
52- AmazonS3 s3 = this .createS3Client ();
53- String value = "" + (System .currentTimeMillis () + getExpirationInSeconds () * 1000 );
54- PutObjectResult putObjectResult = s3 .putObject (bucketName , getKey (state ), value );
60+ PutObjectResponse putObjectResult ;
61+ try (S3Client s3 = this .createS3Client ()) {
62+ String value = "" + (System .currentTimeMillis () + getExpirationInSeconds () * 1000 );
63+ putObjectResult = s3 .putObject (
64+ PutObjectRequest .builder ().bucket (bucketName ).key (getKey (state )).build (),
65+ RequestBody .fromString (value )
66+ );
67+ }
5568 if (log .isDebugEnabled ()) {
56- log .debug ("AWS S3 putObject result of state data - {}" , JsonOps . toJsonString ( putObjectResult ));
69+ log .debug ("AWS S3 putObject result of state data - {}" , putObjectResult . toString ( ));
5770 }
5871 }
5972
6073 @ Override
6174 public boolean isAvailableInDatabase (String state ) {
62- AmazonS3 s3 = this .createS3Client ();
63- S3Object s3Object = getObject (s3 , getKey (state ));
75+ S3Client s3 = this .createS3Client ();
76+ ResponseBytes < GetObjectResponse > s3Object = getObject (s3 , getKey (state ));
6477 if (s3Object == null ) {
6578 return false ;
6679 }
6780 String millisToExpire = null ;
6881 try {
69- millisToExpire = IOUtils .toString (s3Object .getObjectContent ());
70- return Long .valueOf (millisToExpire ) > System .currentTimeMillis ();
71- } catch (IOException e ) {
72- log .error ("Failed to load a state data for state: {}" , state , e );
73- return false ;
82+ millisToExpire = s3Object .asString (StandardCharsets .UTF_8 );
83+ return Long .parseLong (millisToExpire ) > System .currentTimeMillis ();
7484 } catch (NumberFormatException ne ) {
7585 log .error ("Invalid state value detected - state: {}, millisToExpire: {}" , state , millisToExpire );
7686 return false ;
87+ } catch (Exception e ) {
88+ log .error ("Failed to load a state data for state: {}" , state , e );
89+ return false ;
7790 }
7891 }
7992
8093 @ Override
8194 public void deleteStateFromDatastore (String state ) throws Exception {
82- AmazonS3 s3 = this .createS3Client ();
83- s3 .deleteObject (bucketName , getKey (state ));
95+ try (S3Client s3 = this .createS3Client ()) {
96+ s3 .deleteObject (DeleteObjectRequest .builder ().bucket (bucketName ).key (getKey (state )).build ());
97+ }
8498 }
8599
86- protected AWSCredentials getCredentials ( ) {
87- return DefaultAWSCredentialsProviderChain . getInstance (). getCredentials ();
100+ protected AwsCredentials createCredentials ( AwsCredentialsProvider provider ) {
101+ return provider . resolveCredentials ();
88102 }
89103
90- protected AmazonS3 createS3Client () {
91- return AmazonS3ClientBuilder . defaultClient ();
104+ protected S3Client createS3Client () {
105+ return S3Client . builder (). credentialsProvider ( this . credentialsProvider ). build ();
92106 }
93107
94108 private String getKey (String state ) {
95109 return "state/" + state ;
96110 }
97111
98- private S3Object getObject (AmazonS3 s3 , String fullKey ) {
112+ private ResponseBytes < GetObjectResponse > getObject (S3Client s3 , String fullKey ) {
99113 try {
100- return s3 .getObject (bucketName , fullKey );
101- } catch (AmazonS3Exception e ) {
114+ return s3 .getObject (
115+ GetObjectRequest .builder ().bucket (bucketName ).key (fullKey ).build (),
116+ ResponseTransformer .toBytes ()
117+ );
118+ } catch (Exception e ) {
102119 if (log .isDebugEnabled ()) {
103- log .debug ("Amazon S3 object metadata not found (key: {}, AmazonS3Exception : {})" , fullKey , e .toString ());
120+ log .debug ("Amazon S3 object metadata not found (key: {}, Exception : {})" , fullKey , e .toString ());
104121 }
105122 return null ;
106123 }
0 commit comments