Muhammad Basim
Muhammad Basim

Reputation: 29

How to connect two AWS S3 Buckets from spring boot application

I want to connect two S3 Buckets from spring boot Application. I make two different beans with different credentials and make one @primary now my application runs properly but when I tried to access second bucket which is not @primary It gives me 403 Access Denied Exception

com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied;

Below is my code any help will be highly appreciated Thanks in Advance

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class AWSConfiguration {

    @Value("${One.cloud.aws.credentials.accessKey}")
    private String accessKeyOne;

    @Value("${One.cloud.aws.credentials.secretKey}")
    private String secretKeyOne;

    @Value("${One.cloud.aws.region}")
    private String regionOne;

    @Value("${Two.bucket.accessKey}")
    private String accessKeyTwo;

    @Value("${Two.bucket.secretKey}")
    private String secretKeyTwo;

    @Value("${Two.bucket.region}")
    private String regionTwo;

    @Bean
    @Primary
    public BasicAWSCredentials basicAWSCredentialsOne() {
        return new BasicAWSCredentials(accessKeyOne, secretKeyOne);
    }

    @Bean
    @Primary
    public AmazonS3 amazonS3ClientOne(AWSCredentials awsCredentials) {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
        builder.setRegion(regionOne);
        AmazonS3 amazonS3 = builder.build();
        return amazonS3;
    }

    @Bean
    public BasicAWSCredentials basicAWSCredentialsTwo() {
        return new BasicAWSCredentials(accessKeyTwo, secretKeyTwo);
    }

    @Bean
    public AmazonS3 amazonS3ClientTwo(AWSCredentials awsCredentials) {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
        builder.setRegion(regionTwo);
        AmazonS3 amazonS3 = builder.build();
        return amazonS3;
    }
}

Upvotes: 1

Views: 2425

Answers (1)

rieckpil
rieckpil

Reputation: 12041

Is it necessary to expose both BasicAWSCredentials as beans for your application? Can't you just inline the credentials like the following?

@Configuration
public class AWSConfiguration {

    @Value("${One.cloud.aws.credentials.accessKey}")
    private String accessKeyOne;

    @Value("${One.cloud.aws.credentials.secretKey}")
    private String secretKeyOne;

    @Value("${One.cloud.aws.region}")
    private String regionOne;

    @Value("${Two.bucket.accessKey}")
    private String accessKeyTwo;

    @Value("${Two.bucket.secretKey}")
    private String secretKeyTwo;

    @Value("${Two.bucket.region}")
    private String regionTwo;

    @Bean
    @Primary
    public AmazonS3 amazonS3ClientOne(AWSCredentials awsCredentials) {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        builder.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKeyOne, secretKeyOne)));
        builder.setRegion(regionOne);
        AmazonS3 amazonS3 = builder.build();
        return amazonS3;
    }

    @Bean
    public AmazonS3 amazonS3ClientTwo(AWSCredentials awsCredentials) {
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        builder.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKeyTwo, secretKeyTwo)));
        builder.setRegion(regionTwo);
        AmazonS3 amazonS3 = builder.build();
        return amazonS3;
    }
}

If you want to stick to your current approach with exposing both credentials as beans, you can have a look at the @Qualifier annotation to specify the correct Credentials/AmzonS3 bucket instance while injecting them, e.g.

@Bean
public AmazonS3 amazonS3ClientTwo(@Qualifier("basicAWSCredentialsTwo") AWSCredentials awsCredentials) {
    AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
    builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials));
    builder.setRegion(regionTwo);
    AmazonS3 amazonS3 = builder.build();
    return amazonS3;
}

There is a good tutorial on Baeldung available for this.

Upvotes: 1

Related Questions