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,92 @@ 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 ex = null ;
46+ try (S3Client s3 = createS3Client ()) {
47+ bucketExists = s3 .headBucket (HeadBucketRequest .builder ().bucket (bucketName ).build ()) != null ;
48+ } catch (Exception e ) { // NoSuchBucketException etc.
49+ ex = 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 error = ex != null ? ex .getClass ().getName () + ":" + ex .getMessage () : "-" ;
53+ String message = "Failed to access the Amazon S3 bucket (name: " + bucketName + ", error: " + error + ")" ;
54+ throw new IllegalStateException (message );
4655 }
4756 };
4857 }
4958
5059 @ Override
5160 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 );
61+ PutObjectResponse putObjectResult ;
62+ try (S3Client s3 = this .createS3Client ()) {
63+ String value = "" + (System .currentTimeMillis () + getExpirationInSeconds () * 1000 );
64+ putObjectResult = s3 .putObject (
65+ PutObjectRequest .builder ().bucket (bucketName ).key (getKey (state )).build (),
66+ RequestBody .fromString (value )
67+ );
68+ }
5569 if (log .isDebugEnabled ()) {
56- log .debug ("AWS S3 putObject result of state data - {}" , JsonOps . toJsonString ( putObjectResult ));
70+ log .debug ("AWS S3 putObject result of state data - {}" , putObjectResult . toString ( ));
5771 }
5872 }
5973
6074 @ Override
6175 public boolean isAvailableInDatabase (String state ) {
62- AmazonS3 s3 = this .createS3Client ();
63- S3Object s3Object = getObject (s3 , getKey (state ));
76+ S3Client s3 = this .createS3Client ();
77+ ResponseBytes < GetObjectResponse > s3Object = getObject (s3 , getKey (state ));
6478 if (s3Object == null ) {
6579 return false ;
6680 }
6781 String millisToExpire = null ;
6882 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 ;
83+ millisToExpire = s3Object .asString (StandardCharsets .UTF_8 );
84+ return Long .parseLong (millisToExpire ) > System .currentTimeMillis ();
7485 } catch (NumberFormatException ne ) {
7586 log .error ("Invalid state value detected - state: {}, millisToExpire: {}" , state , millisToExpire );
7687 return false ;
88+ } catch (Exception e ) {
89+ log .error ("Failed to load a state data for state: {}" , state , e );
90+ return false ;
7791 }
7892 }
7993
8094 @ Override
8195 public void deleteStateFromDatastore (String state ) throws Exception {
82- AmazonS3 s3 = this .createS3Client ();
83- s3 .deleteObject (bucketName , getKey (state ));
96+ try (S3Client s3 = this .createS3Client ()) {
97+ s3 .deleteObject (DeleteObjectRequest .builder ().bucket (bucketName ).key (getKey (state )).build ());
98+ }
8499 }
85100
86- protected AWSCredentials getCredentials ( ) {
87- return DefaultAWSCredentialsProviderChain . getInstance (). getCredentials ();
101+ protected AwsCredentials createCredentials ( AwsCredentialsProvider provider ) {
102+ return provider . resolveCredentials ();
88103 }
89104
90- protected AmazonS3 createS3Client () {
91- return AmazonS3ClientBuilder . defaultClient ();
105+ protected S3Client createS3Client () {
106+ return S3Client . builder (). credentialsProvider ( this . credentialsProvider ). build ();
92107 }
93108
94109 private String getKey (String state ) {
95110 return "state/" + state ;
96111 }
97112
98- private S3Object getObject (AmazonS3 s3 , String fullKey ) {
113+ private ResponseBytes < GetObjectResponse > getObject (S3Client s3 , String fullKey ) {
99114 try {
100- return s3 .getObject (bucketName , fullKey );
101- } catch (AmazonS3Exception e ) {
115+ return s3 .getObject (
116+ GetObjectRequest .builder ().bucket (bucketName ).key (fullKey ).build (),
117+ ResponseTransformer .toBytes ()
118+ );
119+ } catch (Exception e ) {
102120 if (log .isDebugEnabled ()) {
103- log .debug ("Amazon S3 object metadata not found (key: {}, AmazonS3Exception : {})" , fullKey , e .toString ());
121+ log .debug ("Amazon S3 object metadata not found (key: {}, Exception : {})" , fullKey , e .toString ());
104122 }
105123 return null ;
106124 }
0 commit comments