Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,38 @@ Fulfillment : Roadmap Item
classpath:/bl-amazon-applicationContext.xml
```
> Note: This line should go before the `classpath:/applicationContext.xml` line

## Enable S3 module

Configuration can be done by setting specific variables in `common.properties`.

`aws.s3.enabled=true`

If it this variable is missing, not set or false, S3 storage is not active and the default file provider remains unchanged.

## Authentication Configuration

There are several login mechanisms that can be used in AWS.

Three credentials mechanisms from the ![AWS credentials chain](https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html) are available for usage and configuration.

### Amazon AWS S3 Key + Secret Authentication

```
aws.s3.accessKeyId=
aws.s3.secretKey=
```

### EC2 Instance Profile Authentication

```
aws.s3.useInstanceProfile=true
```

### ECS or Fargate Container Authentication

Note that EC2 Instance Profile Authentication has precedence over ECS and Fargate. If both are set to true, Container Credentials will be ignored.

```
aws.s3.useContainerCredentials=true
```
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class S3Configuration {
private String endpointURI;
private String bucketSubDirectory;
private Boolean useInstanceProfileCredentials;
private Boolean useContainerCredentials;
private Boolean enableSSE;

public String getAwsSecretKey() {
Expand Down Expand Up @@ -106,6 +107,12 @@ public void setUseInstanceProfileCredentials(Boolean useInstanceProfileCredentia
this.useInstanceProfileCredentials = useInstanceProfileCredentials;
}

public void setUseContainerCredentials(Boolean useContainerCredentials) {
this.useContainerCredentials = useContainerCredentials;
}

public Boolean getUseContainerCredentials() { return useContainerCredentials; }

public Boolean getEnableSSE() {
return enableSSE;
}
Expand All @@ -124,6 +131,7 @@ public int hashCode() {
.append(endpointURI)
.append(bucketSubDirectory)
.append(useInstanceProfileCredentials)
.append(useContainerCredentials)
.append(enableSSE)
.build();
}
Expand All @@ -140,6 +148,7 @@ public boolean equals(Object obj) {
.append(this.endpointURI, that.endpointURI)
.append(this.bucketSubDirectory, that.bucketSubDirectory)
.append(this.useInstanceProfileCredentials, that.useInstanceProfileCredentials)
.append(this.useContainerCredentials, that.useContainerCredentials)
.append(this.enableSSE, that.enableSSE)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ public S3Configuration lookupS3Configuration() {
s3config.setEndpointURI(lookupProperty("aws.s3.endpointURI"));
s3config.setBucketSubDirectory(lookupProperty("aws.s3.bucketSubDirectory"));
s3config.setUseInstanceProfileCredentials(Boolean.parseBoolean(lookupProperty("aws.s3.useInstanceProfile")));
s3config.setUseContainerCredentials(Boolean.parseBoolean(lookupProperty("aws.s3.useContainerProfile")));
s3config.setEnableSSE(Boolean.parseBoolean(lookupProperty("aws.s3.sse")));

boolean accessSecretKeyBlank = StringUtils.isEmpty(s3config.getAwsSecretKey());
boolean accessKeyIdBlank = StringUtils.isEmpty(s3config.getGetAWSAccessKeyId());
boolean bucketNameBlank = StringUtils.isEmpty(s3config.getDefaultBucketName());
boolean useInstanceProfile = s3config.getUseInstanceProfileCredentials();
boolean useContainerCredentials = s3config.getUseContainerCredentials();
Region region = RegionUtils.getRegion(s3config.getDefaultBucketRegion());
boolean canRetrieveCredentials = !(accessSecretKeyBlank || accessKeyIdBlank) || useInstanceProfile;
boolean canRetrieveCredentials = !(accessSecretKeyBlank || accessKeyIdBlank) || useInstanceProfile || useContainerCredentials;

if (region == null || !canRetrieveCredentials || bucketNameBlank) {
StringBuilder errorMessage = new StringBuilder("Amazon S3 Configuration Error : ");
Expand All @@ -77,6 +79,10 @@ public S3Configuration lookupS3Configuration() {
errorMessage.append("aws.s3.useInstanceProfile was blank or false,");
}

if (!useContainerCredentials) {
errorMessage.append("aws.s3.useContainerCredentials was blank or false,");
}

if (region == null) {
errorMessage.append("aws.s3.defaultBucketRegion was set to an invalid value of "
+ s3config.getDefaultBucketRegion());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import javax.annotation.Resource;

import com.amazonaws.auth.ContainerCredentialsProvider;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -340,6 +341,9 @@ protected AmazonS3 getAmazonS3ClientFromConfiguration(S3Configuration s3config)
if(s3config.getUseInstanceProfileCredentials()) {
builder = AmazonS3ClientBuilder.standard()
.withCredentials(new InstanceProfileCredentialsProvider(false));
} else if(s3config.getUseContainerCredentials()) {
builder = AmazonS3ClientBuilder.standard()
.withCredentials(new ContainerCredentialsProvider());
} else {
builder = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(getAWSCredentials(s3config)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
*/
package org.broadleafcommerce.vendor.amazon.s3.config;

import org.broadleafcommerce.common.file.service.FileSystemFileServiceProvider;
import org.broadleafcommerce.common.logging.LifeCycleEvent;
import org.broadleafcommerce.common.logging.ModuleLifecycleLoggingBean;
import org.broadleafcommerce.vendor.amazon.s3.S3FileServiceProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

Expand All @@ -32,4 +35,11 @@ public class AmazonS3Configuration {
public ModuleLifecycleLoggingBean blAmazonS3ModuleLifecycle() {
return new ModuleLifecycleLoggingBean(AmazonS3ModuleRegistration.MODULE_NAME, LifeCycleEvent.LOADING);
}

@Bean
@ConditionalOnProperty(prefix = "aws.s3", name = "enabled", havingValue = "true", matchIfMissing = false)
public S3FileServiceProvider blDefaultFileServiceProvider() {
return new S3FileServiceProvider();
}

}
2 changes: 0 additions & 2 deletions src/main/resources/bl-amazon-applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,5 @@
http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<context:component-scan base-package="org.broadleafcommerce.vendor.amazon"/>

<bean id="blDefaultFileServiceProvider" class="org.broadleafcommerce.vendor.amazon.s3.S3FileServiceProvider" />

</beans>
3 changes: 3 additions & 0 deletions src/main/resources/config/bc/amazon/common.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ aws.s3.secretKey=
# Get credentials from instance if on EC2
aws.s3.useInstanceProfile=false

# Get credentials from instance if on ECS or Fargate
aws.s3.useContainerCredentials=false

# Enable or disable server side encryption for S3 Uploads
aws.s3.sse=false

Expand Down