Overview
The Amazon S3 Utilities Plug-in leverages the Amazon AWS Java API to connect with Amazon S3 to store and retrieve files.
Key Features & Functionality
The following smart services are included:
The plug-in also includes a function:
Amazon S3 Utilities supports the following Amazon S3 features:
Note: The plug-in requires Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files when using client side encryption.
(https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)
The Appian Secure Credential Store is leveraged for the credentials to integrate with Amazon S3. Before executing the plug-in, create an new secure credential store with the following 3 attributes. These values are obtained from Amazon AWS IAM console.
Hello,
Is it possible to increase the expiration time? If we can have it as input that would be great; because due to Appian restrictions, we only have 5 seconds to generate a link and download the file.
jeank0002, in case you or anyone else is interested, I used the getawsv4signature from the Cryptographic Hash Functions plugin to create a presigned S3 URL with a custom expiration value (a constant in our case). Here's the code I used:
if(a!isNullOrEmpty(ri!fileURI), null, a!localVariables( local!resourceURI: if(left(ri!fileURI, 1) = "/", ri!fileURI, "/"&ri!fileURI), local!currentTime: now(), local!dateTimeStamp: rule!TRSY_formatXAmzDateTime(dateTime: local!currentTime, isDateOnly: false), local!dateStamp: rule!TRSY_formatXAmzDateTime(dateTime: local!currentTime, isDateOnly: true), local!bucketName: cons!AWS_S3_PROFILE_IMAGE_BUCKET_NAME, local!hostname: local!bucketName & "." & cons!AWS_S3_DOMAIN_NAME, /* CredentialScope = <dateStamp>/<aws-region>/<aws-service>/aws4_request */ local!credentialScope: joinarray( { local!dateStamp, cons!AWS_S3_REGION, cons!AWS_S3_SERVICE_NAME, cons!AWS_SIGNATURE_VERSION }, "/" ), /* Query parameters */ local!amzParams: { a!map(param: "X-Amz-Algorithm", value: cons!AWS_SIGNING_ALGORITHM), a!map(param: "X-Amz-Credential", value: cons!AWS_S3_PROFILE_IMAGE_ACCESS_KEY_ID&"/"&local!credentialScope), a!map(param: "X-Amz-Date", value: local!dateTimeStamp), a!map(param: "X-Amz-Expires", value: cons!AWS_S3_PROFILE_IMAGE_PRESIGNED_URL_EXPIRATION_TIME), a!map(param: "X-Amz-SignedHeaders", value: "host") }, local!queryString: joinarray( a!forEach( items: local!amzParams, expression: urlencode(fv!item.param)&"="&urlencode(fv!item.value) ), "&" ), /* Step 1: Canonical request */ local!canonicalRequest: a!localVariables( local!headers: "host:"&local!hostname, joinarray( { "GET", local!resourceURI, local!queryString, local!headers&char(10), "host", "UNSIGNED-PAYLOAD" }, char(10) ) ), /* Step 2: String to sign */ local!stringToSign: joinarray( { cons!AWS_SIGNING_ALGORITHM, local!dateTimeStamp, local!credentialScope, sha256hash(local!canonicalRequest) }, char(10) ), /* Step 3: Signature */ local!signature: getawsv4signature( key:"", scsValue: { cons!AWS_S3_READONLY_PROFILE_IMAGE_SCSFIELD_EXTERNALFIELD, cons!AWS_S3_READONLY_PROFILE_IMAGE_SCSFIELD_FIELDNAME_SECRETACCESSKEY }, dateStamp: local!dateStamp, regionName: cons!TRSY_SQS_AWS_REGION, serviceName: cons!AWS_S3_SERVICE_NAME, string:local!stringToSign ), /* Return the full presigned URL */ "https://"&local!hostname&local!resourceURI&"?"&local!queryString&"&X-Amz-Signature="&local!signature ) )
And here's the code for the TRSY_formatXAmzDateTime rule:
if( or( a!isNullOrEmpty(ri!isDateOnly), not(ri!isDateOnly) ), text(gmt(ri!dateTime,"America/Chicago"), "yyyymmddThhmmss")&"Z", text(gmt(ri!dateTime,"America/Chicago"), "yyyymmdd") )
Josh, what is the need for a custom timer? Is it for shortening or extending? Extending the expiration timer beyond a minimum opens up a security hole since the links can be shared and accessed by anyone. As explained in my previous response, the 5s timer is just to issue a redirect to the link once it's signed by AWS, which is more than long enough to do so (it could be argued it's too long still).