100 days in Cloud
Part One of Cloud Resume Challenge:
The manual set-up of frontend
- API Gateway
- Certificate Manager
As I write in previous post I’m participating in Cloud Resume Challenge. I will describe the steps necessary for the first part of the deployment, mainly the manual steps to get the website running. Ordering of my steps is bit random, I was making few things at the same time, testing, adjusting the code but it’s all there. So proceed in your own fashion.
- Create website
- Make website globally and securely available
- Create a visitors counter
- Set up GitHub actions
- AWS account
- GitHub account for deploying the code
- A website of your own
- I recommend using Visual Studio Code with Live Server extension – it’ll make your life so much easier
- Postman for API testing
- I’m not going to describe the process of building the website or creating the content, it’s only up to one how she wants the Resume to look like. Here’s the code to mine. What’s important is to include a script in the html file that will make request calls to the API, it might look something like that:
What it basically does is fetching the response from API that returns json object with a value body corresponding to the visitors count logged in DynamoDB.
- At this point I started to test the website. I created a S3 bucket with Static website hosting enabled. I knew that my website would be hosted in my LightSail DNS hosted zone, so I had to call the bucket accordingly. In my case the domain for the resume is profile.cloudofthings.net so that’s how I called it. Originally I made the bucket public in order to be able to test it, but that’s not necessary with CloudFront distribution (more on that later).
- It was time to create resources necessary for the visitors counter. I started with a DynamoDB table. I have to admit that it took me couple of tries before I figured out what works best with Lambda function. But eventually I landed on having only one Item with Primary partition key id and additional Attribute visits.
- Creating Lambda function and working with the code and testing it in my opinion the fun part, even though it might be frustrating. But what doesn’t kill you makes you stronger! Anyways I created the Environment variable for the table name, something I’ve learned is a good practice at all times. In order to reduce the amount of Lambda invocations (even though I’m definitely not gonna be overflowed with visitors any time soon) I created a method within the code that returns the latest value from the table after it gets incremented. So what’s happening in the code is that first the lambda connects to the table, update the item by increment of 1 and then return API valid response with status code, headers and finally calls the earlier mentioned method to retrieve current value and pass it in response to API.
- Next step was to create and deploy Gateway API. I needed only the GET method with Lambda integration. I tried to make it as restricted as I could, so that only my page could make requests to the endpoint. Obviously the endpoint I have in index.html is the one to the API created in this step.
- At this point (not as smooth as I described though, there’s alway a policy or role that one forgets to assign, right?) the website was up, script was making request to API, that invoked the Lambda function and she did her part on DynamoDB.
- Last step in Part One, or manual deployment if you wish was to set up a CloudFront distribution. My cloudofthings.net runs on LightSail with CloudFront distribution, so I included the profile.cloudofthings.net domain as custom domain. A SSL certificate was needed but the AWS Certificate Manager makes it very easy to create one and validate domain. There’s one neat thing a found out making the CloudFront distribution, if S3 bucket is origin for one you can create Origin access identity and keep the bucket private, while CloudFront will still be able to make getS3 object requests. Another finding was that as Viewer protocol policy I needed to choose Redirect HTTP to HTTPS and couldn’t really figure out what restricted me from choosing HTTPS only. Well it works as it should.