CRC Journal (text)
The “Why”:
My reasoning for wanting to enter into the field of Cloud Computing stems from my fascination with Cloud Architecture and the multi-faceted benefits of the incorporation of Cloud-facilitated instantiation into the business and operation models of virtually any organization. Serverless architecture, for example, provides the simplicity and operational ease that any organization can use to its advantage. The “as needed” instantiation of these serverless structures gives the cost-effectiveness, precision, and extraordinarily limited attack surface that organizations need to stay safe from malicious actors in our current and forward-moving cyber environments. The high availability and fault tolerance that a full or hybrid cloud environment provides offers the stability and dependability that organizations worldwide can benefit from. Furthermore, the potentials offered by Cloud computing are virtually limitless, spanning far beyond the scope of the CRC, and my intrigue regarding these potentials has guided me to seeking my certifications (the Comptia Trifecta, the AWS-CCP, and the AWS-SAA), and now the practical experience offered by working through and completing the Cloud Resume Challenge (and beyond).
The “What”:
While completing the Cloud Resume Challenge, I have built many structures that intertwine in AWS Cloud environments as well as with external structures: I built an HTML/CSS resume that I hosted in an S3 bucket and cached on CloudFront, I utilized a functional URL, created and implemented a Lambda function to correlate between my URL and a DynamoDB visitor counter, and made use of GitHub to keep everything in line for both the front end and back end CI/CD functionality… and more.
Below is a look into the process that I followed to complete the CRC:
The Beginning of the Cloud Resume Challenge:
The first part of the challenge (which, frankly, isn’t an important part of the challenge itself) was to get my resume into and HTML formatted file (which i called “index.html” as per website/S3 configuration default conventions) and to have it formatted with CSS (a separate file that I called, simply, “style.css”). The process for formatting and styling my resume in HTML was not complicated in its functionality, but for the sake of efficiency and focus on what matters about the challenge, I used an online tool for this formatting and it’s adjustments, fully knowing that I would have some edits later that would be very easy to integrate.
With my two resume files in tow (and in the same folder on my workstation which is very important), I then logged into my AWS account and created an S3 bucket cogently named “travismohr.com” where I stored my HTML and CSS files. I made sure that my region was “us-east-1” for simplicity sake and for facilitation of later steps, and I didn’t bother with any versioning since this website would be static. I made sure to block any public access to the S3 bucket for a few reasons: if anyone could access my S3 bucket, they could do what they wanted with the files in it. And, because the public could then subsequently access the bucket “a la brute force” and rack up my AWS usage charges. This would be very unlikely to occur, but for me it was a practice in cloud security to block all public access while implementing a bucket policy that would grant access to my CloudFront via the indication of its “Distribution ID”.
(A DULY NOTED POINT: In the above, I originally had my Bucket Policy and ACL’s set to allow public access to the bucket. I thought, “Of course it’s public, the whole world should be able to see my CRC resume if they want to.” But once I got to the CloudFront step below, I realized the err of my ways on this part. I had to change my CloudFront “Origen Access” from “Public” to “Origin access control settings” to cause my bucket to restrict access to only CloudFront. Then after creating the OAC, or “origin access control” with my S3 bucket “Object URL”, my resume appeared without any problems when I refreshed the URL.)
With my S3 bucket set up, I needed to create a distribution in CloudFront to both cache the contents of my CRC files in my S3 bucket and allow access to that content via its caching mechanism. Once created, I simply pointed the origin to the S3 bucket via the dropdown menu and made sure the the bucket policy would be updated through doing so. With similar simplicity, I allowed this CloudFront distribution to make the transmission of this data to the end user secure by indicating that HTTP would be redirected to HTTPS.
At this point, I registered my domain (travismohr.com) through porkbun.com. Next, I created a hosted zone in Route 53 for the URL and replaced Porkbun’s NS Records with the ones provided in Route 53, thereby assigning the DNS Delegation to Route 53. I then created an alias record in 53 to route my domain traffic to my CloudFront distribution. To secure the URL, I requested a public certificate in the AWS Certificate Manager and then selected the certificate from the dropdown menu in CloudFront. Doing all of this transferred authoritative control of my URL from Porkbun to AWS, mapped my aliases (both my root and subdomain) to Cloudfront, and validated my ownership of travismohr.com with the SSL certificate that I created in “AWS Certificate Manager”. I made another quick stop at Route 53 to create the A and AAAA records to correlate toward my URL, and I was done with Route 53 for the time being.
And with this, I completed the public-facing network architecture of the CRC.
Visitor Counter and Back-End Connectivity:
(This part loops around and gets a bit complicated, but bear with me.)
At this point, I went to DynamoDB in AWS to create a table where my resume visitor count would be stored (as opposed to an S3 bucket which is for static data, or at the most, versioned objects). In DynamoDB, I created a table appropriately called “MyCRCresumeViewCount”, with a string called “id” for simplicity's sake. Under this attribute, I create a linked value of “views” which would ultimately keep track of how many times my resume URL had been visited. With the counter set up as a storable resource in DynamoDB, I had to then create a function using Lambda to pull the numerical view count data from DynamoDB, modify it (“+1” to whatever is in the view counter in DynamoDB), send the new number to the resume URL, and store the new number in DynamoDB.
I called the Lambda function “CRC_COUNT_UPDATER” and pasted in some Python code sampled from the boto3 library. I made sure that my region was modified to the “us-east-1” region. This Python code targeted my DynamoDB database and established a connection to the table “MyCRCResumeViewCount”. This numerical value would be added “atomically” (as expressed in the previous paragraph, meaning that even if two URL requests happened at the same time, the storing of view count would taken out of the Lambda function’s hands all together and simply aggregated appropriately to whatever was in the DynamoDB viewer, removing any chance of data overwriting or race conditions). DynamoDB would then be prompted to send back the updated view count value, pull the count number out of the dictionary that DynamoDB just returned, and then send that number back to the API Gateway (relying on the permission granted by the CORS Header to allow info to the API Gateway). With the count data, the Lambda function would then be directed to update the view count in the JSON object so that the view number could be updated in the URL counter (having been read by the frontend JavaScript).
But before any of this could happen, I had to assign permissions for the Lambda function to gain access to the DynamoDB database in the first place. So, I went to IAM and selected the policy “AmazonDynamoDBFullAccess” which grants the Lambda function “list, read, write” access to the table, and added this policy to the IAM permissions.
From there, I went back to the Lambda function to test it with a simple “ “keyX: “valueX” “ function. I hit “test” and all went through beautifully. The view count worked.
So, in order to access this data from the frontend, I would normally set up a REST API to connect the relevant parts… but in the case of the CRC URL resume that uses a simple “GET” function, a smoother and sleeker “Function URL” would do the trick nicely. I simply went to the Lambda “Configuration” section for my function and selected “Function URL” from the menu, chose “NONE” as the “auth type” since there was no need to give the function anything but fully public access, and then tested the Function URL by clicking on the link which then opened a new window showing the augmented view count. Success. From there, I added the Function URL into my “index.html” file and reloaded the file back up into my S3 bucket after deleting the old version. I made sure to invalidate my CloudFront cache at this point (inputting a simple “ /* ” would do the trick) to allow for the updated S3 object to be cached in its place.
From there, I had to get all of my Python code to be uploaded from my VSCode to my GitHub repository to accommodate all IaC changes for the front end and the back end of my CRC project. (NOTE: At this stage in the project, I encountered a significant roadblock with the backend upload to GitHub. After several hours of troubleshooting, I finally discovered that the problem was that my front end and back end code needed to be separated into two different folders within my VSCode. Once I did this, the upload went smoothly and functioned beautifully.) Once I had all of my Python transferred to my two github repositories (one for the front end and one for the back end), I went back into AWS to IAM to create a new user called “github-actions-deployer” and granted this user “AmazonS3FullAccess” and “AWSLambda_FullAccess” permissions. After creating the access keys (both the access key and the secret access key), I copied and pasted these into my Github repositories for both the front end and the back end sections by going to: Settings, Secrets and Variables, Actions, and then editing each the two access keys and pasting in the codes. NOTE: I created this user specifically for my GitHub CI/CD repository AFTER having used the access keys for my “CloudAdmin” user, but then I realized that it would not be best practices to use the keys for the “CloudAdmin” user even though GitHub encrypts these codes by default and doesn’t even allow me to see them once they are saved. But in the interest of best practices and least privileges, I decided to create the “github-actions-deployer” with access only to S3 and Lambda for the CI/CD pipeline.
Afterthoughts:
Completing the CRC was a great experience where I learned so much about the functionality and the moving parts of AWS and the associated external features highlighted here. After studying for the AWS Solutions Architect exam and passing it on the first attempt, it was great to put some of what I learned to use. I am more energized to continue learning and implementing new skills and features with AWS Cloud than ever before.
Thank you for reading.
– Travis Mohr
Top comments (0)