From dad9689f38d1ad7efa9aa18829cc069eda76a40a Mon Sep 17 00:00:00 2001 From: Andrei Miclaus Date: Mon, 13 Jan 2020 19:36:35 +0200 Subject: [PATCH 1/4] Add Container Credentials to available S3 authentication mechanism for ECS and Fargate environments --- README.md | 27 +++++++++++++++++++ .../vendor/amazon/s3/S3Configuration.java | 7 +++++ .../amazon/s3/S3ConfigurationServiceImpl.java | 8 +++++- .../amazon/s3/S3FileServiceProvider.java | 4 +++ .../config/bc/amazon/common.properties | 3 +++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42004bd..7d0232e 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,30 @@ Fulfillment : Roadmap Item classpath:/bl-amazon-applicationContext.xml ``` > Note: This line should go before the `classpath:/applicationContext.xml` line + +## Steps to configure this module + +There are several login mechanisms that can be used in AWS. + +Configuration can be done by setting specific variables in `common.properties`. 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 +``` \ No newline at end of file diff --git a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java index 713bf68..e741105 100644 --- a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java +++ b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java @@ -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() { @@ -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; } diff --git a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3ConfigurationServiceImpl.java b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3ConfigurationServiceImpl.java index 2e06016..df65aed 100644 --- a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3ConfigurationServiceImpl.java +++ b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3ConfigurationServiceImpl.java @@ -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 : "); @@ -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()); diff --git a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3FileServiceProvider.java b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3FileServiceProvider.java index aebe34d..4947135 100644 --- a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3FileServiceProvider.java +++ b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3FileServiceProvider.java @@ -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; @@ -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))); diff --git a/src/main/resources/config/bc/amazon/common.properties b/src/main/resources/config/bc/amazon/common.properties index c045a9a..0f5896b 100644 --- a/src/main/resources/config/bc/amazon/common.properties +++ b/src/main/resources/config/bc/amazon/common.properties @@ -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 From 84a483875c5835ddd087430a4d9d7b30da805cc6 Mon Sep 17 00:00:00 2001 From: danielcolgrove Date: Mon, 13 Jan 2020 13:36:49 -0600 Subject: [PATCH 2/4] Updating to latest parent module --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f96d5f..72f7181 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.broadleafcommerce broadleaf-module-parent - 3.0.0-GA + 3.0.2-GA org.broadleafcommerce From 3c3deec8d77ad36eb1e07cee2a098eec142f381b Mon Sep 17 00:00:00 2001 From: Andrei Miclaus Date: Wed, 15 Jan 2020 14:50:09 +0200 Subject: [PATCH 3/4] Add containercredentials to equals and has function --- .../org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java index e741105..f6ada86 100644 --- a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java +++ b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/S3Configuration.java @@ -131,6 +131,7 @@ public int hashCode() { .append(endpointURI) .append(bucketSubDirectory) .append(useInstanceProfileCredentials) + .append(useContainerCredentials) .append(enableSSE) .build(); } @@ -147,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(); } From bec506289aa9f35123e7f577e65384eae613a3c6 Mon Sep 17 00:00:00 2001 From: Andrei Miclaus Date: Thu, 16 Jan 2020 19:39:36 +0200 Subject: [PATCH 4/4] instantiate S3 bean only if variable is set to true --- README.md | 12 ++++++++++-- .../amazon/s3/config/AmazonS3Configuration.java | 10 ++++++++++ src/main/resources/bl-amazon-applicationContext.xml | 2 -- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7d0232e..c9ff01a 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,19 @@ Fulfillment : Roadmap Item ``` > Note: This line should go before the `classpath:/applicationContext.xml` line -## Steps to configure this module +## 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. -Configuration can be done by setting specific variables in `common.properties`. 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. +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 diff --git a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/config/AmazonS3Configuration.java b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/config/AmazonS3Configuration.java index 3731024..fe14131 100644 --- a/src/main/java/org/broadleafcommerce/vendor/amazon/s3/config/AmazonS3Configuration.java +++ b/src/main/java/org/broadleafcommerce/vendor/amazon/s3/config/AmazonS3Configuration.java @@ -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; @@ -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(); + } + } diff --git a/src/main/resources/bl-amazon-applicationContext.xml b/src/main/resources/bl-amazon-applicationContext.xml index 4fac947..9a8d56c 100644 --- a/src/main/resources/bl-amazon-applicationContext.xml +++ b/src/main/resources/bl-amazon-applicationContext.xml @@ -26,7 +26,5 @@ http://www.springframework.org/schema/context/spring-context-3.2.xsd"> - -