Web server with user registration and guestbook with image upload

Overview

The users access the website where they have the option to the view the guest book, register or log in. To register the user has to provide a username, an email address and a secure password (more than 8 characters, upper and lowercase characters, numbers and special characters). Then an email with a verification link will be sent to the provided email address. Clicking this link will enable the user to login.

Upon login the user can post messages in the guest book, which will be saved to the MySQL database. In addition to a text message the user can also upload an image which will be transferred to an S3 Bucket, which in turn will trigger a Lambda. Here the image will be resized to make it suitable for displaying in the guest book and it will be transferred to another S3 Bucket and permissions will be set to make in publicly accessible. The URL to this image will also be saved in the MySQL database.

Project architecture
Project architecture (created with Cloudcraft.co)

EC2 Instance

The OS running on the EC2 instance is Amazon Linux which is based on Red Hat Enterprise Linux. This is because I created the EC2 instance at the time when I was working through the AWS tutorials and this was the recommended distribution. By the time I started with the project, I decided to stick with it, although I had no prior experience with this distribution.

With ‘yum’, the packet manager of this distribution I was only able to install PHP 5.4 with in turn only enabled me to install version 2 of the AWS SDK for PHP which led to major problems later on with Cognito.

After a long search for a possibility to install a newer version of PHP (most advise suggested adding additional repositories, which never succeeded) I  found the following solution.

sudo amazon-linux-extras install php7.2

With this command I could finally upgrade to PHP 7.2. This in turn required an upgrade to Apache 2.4 which could be achieved with the same command.

RDS

For a database system I decided on MySQL. The setup was straightforward with the exception of the firewall. My EC2 instance wouldn’t connect to the RDS instance even after I setup the security group to allow port 3306 from the public IP address of the EC2. The search for a solution led me to create another MySQL user and checking various configuration files (as sometimes the remote access for the root user may be disabled), all to no avail. In the end it turned out I had used the wrong IP address, as the public IP address isn’t the one which connects to the RDS. The correct one can be found by running the ‘ifconfig’ command on the EC2 instance.

Lambda

For the resize Lambda function I built upon a function from the AWS examples. This function is triggered by uploading a file to a S3 Bucket. The image will then be downsized if necessary, transferred to another S3 Bucket, from which it can be publicly read and subsequently deleted from the first bucket. After setting everything up and testing it I found it didn’t work.

I used CloudWatch to debug, which show an access denied error. After much testing and searching I discovered that the process of making an object publicly available requires a separate action, called “s3:PutObjectAcl”  to be allowed in the policy.

Cognito & SES

Originally I had planned to do the user registration myself and just use the SES (Simple Email Service) for the verification email, but upon discovering the Cognito feature, which has the verification system built-in,  I decided to use this instead.

As I had installed an old version of PHP (see above), the packet manager of PHP (Composer) installed the only compatible version of the AWS SDK, which was 2.x. This didn’t have the  necessary ‘CognitoIdentityProvider’ methods but instead the easy to confuse “CognitoIdentity” methods, which is used for the Federated Identities feature of Cognito instead.

After some time of trying I spotted my mistake and after some other time installing a current version of PHP I could upgrade to AWS SDK v3.

Here I discovered the needed methods for user registration and login but was unable to execute them due to a required ‘SecretHash’  attribute which wasn’t documented on how to be generated.

Eventually I found aws-cognito on GitHub. This is a PHP library which provides the Cognito functionality in simpler methods.

S3 Buckets

Working with S3 Buckets was pretty straightforward with the AWS SDK for PHP. The only real problem I’ve encountered was the constructor. In the documentation are to possible methods for creating the client.

The first and recommended one was this:

use Aws\S3\S3Client;
$client = S3Client::factory($config);

This method refused to accept my config file, no matter how I reformatted it.After I changed my code to the second method everything worked fine.

$s3 = new Aws\S3\S3Client($config);

 

The source code is available here