Serving the WebAgent softphone from Amazon S3 and CloudFront

In an earlier post, I mentioned that the softphone scripts used by WebAgent Navigator are all HTML/JavaScript files. They are considered “static” meaning that there is no server-side code (i.e. PHP). The scripts are intended (though not required) to run from their own sub-domain making it easy to share with multiple instances of WebAgent. Because of this, I had the softphone scripts installed and running from their own sub-domain on the Bitnami web server at phone.webagentnavigator.com.

However, this is a perfect use-case for serving these scripts from an Amazon S3 bucket using the CloudFront Content Delivery Network.

Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance. Amazon S3 allows you to store any kind of file (or object) in any number of buckets. A bucket is simply an addressable container used to store files and control access to those files.

Amazon CloudFront is a fast content delivery network (CDN) that works seamlessly with other Amazon services, including S3. CloudFront distributes content (html, javascript, image files, videos, etc.) through a worldwide network of servers known as edge locations. Content is delivered to the end user from the closest edge location with the lowest latency (delay).

This combination is a fast and inexpensive way to deliver static web content while offloading the work from a busy application server.

For the WebAgent Navigator softphone scripts, I use Amazon S3 to host the scripts and Amazon CloudFront to deliver them over https.

The first step is to create the S3 bucket

  1. Log in to the Amazon Management console, go to the S3 service, and click “Create bucket”.
    Enter a bucket name that is unique and DNS compliant (meaning a name that can be used in a domain name or url address).

  2. Select your region.

  3. Click “Next”.

  4. Configuration Options… this screen has several options to use for the S3 bucket, for my case, I left them all off (un-checked).

  5. Clcik “Next”.

  6. Set Permissions… Since we’ll be using CloudFront to deliver the S3 content, we don’t want to give public access to the S3 bucket. On this screen I unchecked “Block all public access“ and checked the first 2 options, “Block public access to buckets and objects granted through new access control lists (ACLs)“ and “Block public access to buckets and objects granted through any access control lists (ACLs)“. This will allow CloudFront to create an Access Control List giving it access to the S3 bucket while preventing any public access not through CloudFront.

  7. Click “Next”.

  8. Review… review the selected options and click “Create bucket”.

  9. You should be returned to the Amazon S3 console. Click on the newly created bucket name.

  10. From the “Overview” tab, you can click on “Upload” and upload your site’s content. However, I prefer to use an FTP client application to manage the content.

  11. Click on “Static website hosting”.

  12. Select “Use this bucket to host a website” and enter an index and (optionally) an error document name. The index name is required even if you don’t use an index page, which I do not.

  13. Note the endpoint address (e.g. http://webagentdemo.s3-website-us-east-1.amazonaws.com), this is the url for the S3 website… but we’ll be using the CloudFront url.

  14. Click “Save”.

  15. We’re done with the S3 bucket.

 

Next we go to CloudFront
As a content delivery network, CloudFront takes the content from the S3 bucket and copies it to servers around the world thus making that content local, and faster, to the users accessing it.

  1. From the CloudFront Distributions console, click “Create Distribution”.

  2. From “Select a delivery method for your content”, under “Web”, click “Get Started”.

  3. From “Create Distribution”, “Origin Settings”…

    1. For “Select Origin Domain Name” from the drop-down which should be your S3 endpoint.

    2. “Restrict Bucket Access” should be Yes since we’re not allowing access other than from CloudFront.

    3. For “Origin Access Identity”, select “Create a New Identity”.

    4. For “Grant Read Permissions on Bucket”, select “Yes, Update Bucket Policy“.

  4. From “Create Distribution”, “Default Cache Behavior Settings”. These options are specific to your use case. In my case I’m only using https and I’m in a development phase so I don’t want my content cached, I want it refreshed when accessed.

    1. For “Viewer Protocol Policy”, I selected “HTTPS Only“ since the url will be embedded in my application code and will only use https.

    2. For “Object Caching”, I selected “Customize” and I set the “Maximum TTL” (time to live) to 86,400 (1 day) and the “Default TTL” to 0. I did this because I’m in a testing phase and uploading content frequently. In a production environment you’d want the default ttl set at 86,400 or higher and leave the Maximum at 31,536,000 or set it to a time (in minutes) that you’re comfortable with.

    3. The remaining options I left as-is.

  5. From “Distribution Settings“, I’m using the CloudFront distribution with the CloudFront SSL certificate. You can use an Alternate Domain Name and your own certificate if you so choose. Since I’m embedding the url in my code, I’m not concerned with the actual url being used or with it being recognizable or memorable to end users.

    1. For “Price Class”, I selected “Use only U.S., Canada and Europe” since that covers my audience.

    2. For “SSL Certificate“ I left it at “Default CloudFront Certificate (*.cloudfront.net)”.

    3. All other settings I left as-is.

  6. Click “Create Distribution“ and you’re returned to the “CloudFront Distributions” screen where you’ll see your new distribution. The domain name (e.g. d2ak5kvzjwj4xb.cloudfront.net) is the url to access the web site. Once “Status” changes from “In Progress” (while the bucket is distributed around the world) to “Deployed” (which may take several minutes) you should be able to open the url in a web browser.

  • If you want to use a custom domain name/url with CloudFront, you can add an Alternate Domain Name and then a cname or alias record in your DNS service. If you’re using https, you will also need to upload your SSL certificate to CloudFront.

 

If, when trying to load your web content, you get an error like this →

It is most likely the “Origin Access Identity”.

From the CloudFront Distributions, click on your distribution’s ID, then go to “Origins and Origin Group”. Click the checkbox next to your S3 origin and click the “Edit” button above. Select “Yes'“ for “Restrict Bucket Access” and “Create a New Identity” for “Origin Access Identity“ and click the “Yes, Edit” button.

This should have been done when creating the distribution, but I found I had to go through this afterwards.

Again, once “Status” of your distribution changes from “In Progress” to “Deployed” you should be able to open the url in a web browser (assuming you’ve uploaded an index page).

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>CD3E075A59A136FC</RequestId>
    <HostId>
        mYJ4GmI17mzC8U86UqMMwdGjTaqVCiVqp8lsTtQlyhrS8osxxTRNPwfepKkwCKJOOhinrsw7Zas=
    </HostId>
</Error>
 

And then Amazon Connect

Since the WebAgent softphone scripts now served through CloudFront include the Amazon Connect CCP (Contact Control Panel), the last thing I had to do was integrate my application with Amazon Connect. I did this by going to the “Application Integration” section of my Amazon Connect instance and adding the CloudFront url.

 

The combination of Amazon S3 and CloudFront makes it easy to create and host web content and have that content delivered quickly and securely. Most, if not all, file transfer applications support S3 buckets making it easy to upload and manage your content (you’ll need your AWS access key found in your account Security Credentials). Delivering content stored in an S3 bucket using CloudFront is actually cheaper, as well as faster, than delivering that same content directly from the S3 bucket.