Appian Community and Appian Academy are being upgraded. As a part of the upgrade, Appian Community is currently in read-only mode, and user registration is disabled until August 3. We apologize for any inconvenience this may cause, but a more secure, stable, and performant Community experience is coming soon!

The new Appian Community launches August 3, followed by Appian Academy on August 7. During the migration, Appian Community Edition, Appian Academy, Documentation, Certifications, Instructor-led Customer Training, Partner Sales Training & Accreditation, and Forum (for Appian Partners and Customers only) will remain available.

Amazon S3 Utilities

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:

  • Upload documents to AWS S3
  • Download documents from AWS S3
  • Create Folders in AWS S3
  • Delete documents from AWS S3

The plug-in also includes a function:

  • getPreSignedURLForS3 that generates a V4 pre signed url that expires after 5s. This allows for a short term access grant to a secured resource. It can be used in a WebAPI object to redirect a user from Appian to a resource on S3.

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.

  • accesskeyid: this is the access key id for connecting to AWS S3
  • accesskeysecret: this is the access key secret for connecting to AWS S3
  • kmscmkid: this attribute is only required if using AWS Client Side Encryption
Anonymous
Parents
  • 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).

Comment
  • 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).

Children
No Data