diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java index 28d2cc9ce694..7f3e69a8b0cc 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/S3BitStoreService.java @@ -32,6 +32,7 @@ import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.auth.BasicSessionCredentials; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; import com.amazonaws.regions.DefaultAwsRegionProviderChain; @@ -82,6 +83,7 @@ public class S3BitStoreService extends BaseBitStoreService { protected static final String DEFAULT_BUCKET_PREFIX = "dspace-asset-"; protected static final Gson GSON = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); + public static final String REGEX_SECRET = "^(.{3})(.*)(.{3})$"; // Prefix indicating a registered bitstream protected final String REGISTERED_FLAG = "-R"; /** @@ -115,6 +117,7 @@ public class S3BitStoreService extends BaseBitStoreService { private String awsAccessKey; private String awsSecretKey; private String awsRegionName; + private String awsSessionToken; private boolean useRelativePath; private Integer maxConnections; private Integer connectionTimeout; @@ -270,8 +273,8 @@ protected static Supplier getAwsCredentialsSupplie BasicAWSCredentials credentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey); log.info( "AmazonS3Client credentials - accessKey: {}, secretKey: {}", - credentials.getAWSAccessKeyId().replaceFirst("^(.{3})(.*)(.{3})$", "$1***$3"), - credentials.getAWSSecretKey().replaceFirst("^(.{3})(.*)(.{3})$", "$1***$3") + credentials.getAWSAccessKeyId().replaceFirst(REGEX_SECRET, "$1***$3"), + credentials.getAWSSecretKey().replaceFirst(REGEX_SECRET, "$1***$3") ); return getAwsCredentialsSupplier(credentials); } @@ -282,6 +285,19 @@ protected static Supplier getAwsCredentialsSupplie return () -> new AWSStaticCredentialsProvider(credentials); } + protected static Supplier getBasicCredentialsSupplier( + String awsAccessKey, String awsSecretKey, String awsSessionToken + ) { + BasicSessionCredentials credentials = new BasicSessionCredentials(awsAccessKey, awsSecretKey, awsSessionToken); + log.info( + "AmazonS3Client credentials - accessKey: {}, secretKey: {}, awsSessionToken: {}", + credentials.getAWSAccessKeyId().replaceFirst(REGEX_SECRET, "$1***$3"), + credentials.getAWSSecretKey().replaceFirst(REGEX_SECRET, "$1***$3"), + credentials.getSessionToken().replaceFirst(REGEX_SECRET, "$1***$3") + ); + return getAwsCredentialsSupplier(credentials); + } + protected static Regions getDefaultRegion() { return Optional.ofNullable(new DefaultAwsRegionProviderChain().getRegion()) .filter(StringUtils::isNotBlank) @@ -331,8 +347,15 @@ public void init() throws IOException { try { Supplier awsCredentialsSupplier; if (StringUtils.isNotBlank(getAwsAccessKey()) && StringUtils.isNotBlank(getAwsSecretKey())) { - log.warn("Use local defined S3 credentials"); - awsCredentialsSupplier = getAwsCredentialsSupplier(getAwsAccessKey(), getAwsSecretKey()); + if (StringUtils.isNotBlank(getAwsSessionToken())) { + log.warn("Use local S3 credentials with session token"); + awsCredentialsSupplier = + getBasicCredentialsSupplier(getAwsAccessKey(), getAwsSecretKey(), getAwsSessionToken()); + } else { + log.warn("Use local S3 credentials with access and secret keys"); + awsCredentialsSupplier = + getAwsCredentialsSupplier(getAwsAccessKey(), getAwsSecretKey()); + } } else { log.info("Use an IAM role or aws environment credentials"); awsCredentialsSupplier = DefaultAWSCredentialsProviderChain::new; @@ -669,6 +692,14 @@ public void setEndpoint(String endpoint) { this.endpoint = endpoint; } + public String getAwsSessionToken() { + return awsSessionToken; + } + + public void setAwsSessionToken(String awsSessionToken) { + this.awsSessionToken = awsSessionToken; + } + /** * Contains a command-line testing tool. Expects arguments: * -a accessKey -s secretKey -f assetFileName diff --git a/dspace/config/modules/assetstore.cfg b/dspace/config/modules/assetstore.cfg index fddf1d4e9e25..53834b440487 100644 --- a/dspace/config/modules/assetstore.cfg +++ b/dspace/config/modules/assetstore.cfg @@ -67,3 +67,5 @@ assetstore.s3.connectionTimeout = # If this property is set, changes the endpoint of the S3 service assetstore.s3.endpoint = +# session token +assetstore.s3.awsToken = diff --git a/dspace/config/spring/api/bitstore.xml b/dspace/config/spring/api/bitstore.xml index 5c2579e5c901..8748f6efe240 100644 --- a/dspace/config/spring/api/bitstore.xml +++ b/dspace/config/spring/api/bitstore.xml @@ -22,6 +22,7 @@ +