LABS/MINI-PROJECTS Links

LAB: Serverless Pet Cuddle-O-Tron

Pet Cuddle-O-Tron – Overview

Final Architecture Diagram (Simplified) – After Stage 5

Final Architecture Diagram (Extended) – After Stage 7

STAGE 1: Set Up Amazon Simple Email Service (SES)

Note: SES handles outgoing emails. The serverless application must approve the sender and recipient addresses before sending.

STAGE 2: Create Lambda Function for Sending Emails

A Lambda function will use SES to send emails from the serverless app.

  1. Create a Lambda execution role (via IAM manually or with CloudFormation stack):
    • Grant permissions for SES, SNS, Step Functions (states) and CloudWatch logs.
  2. Create and configure the Lambda function:
    • Name: email_reminder_lambda
    • Runtime: Python 3.9
    • Execution role: the role created above
    • Update FROM_EMAIL_ADDRESS with your SES sender email.
    import boto3, jsonFROM_EMAIL_ADDRESS = ‘REPLACE_WITH_SENDER_EMAIL_ADDRESS’ses = boto3.client(‘ses’)def lambda_handler(event, context):
    print(“Received event: ” + json.dumps(event))
    ses.send_email(
    Source=FROM_EMAIL_ADDRESS,
    Destination={‘ToAddresses’: [event[‘Input’][’email’]]},
    Message={
    ‘Subject’: {‘Data’: ‘Whiskers Commands You to attend!’},
    ‘Body’: {‘Text’: {‘Data’: event[‘Input’][‘message’]}}
    }
    )
    return ‘Success!’
STAGE 3: Set Up Step Functions State Machine

The state machine manages the workflow and coordinates AWS services.

  1. Create a State Machine role (IAM or CloudFormation):
    • Allow logging to CloudWatch
    • Invoke the email Lambda
    • Use SNS for optional SMS
  2. Create the State Machine:
    • Name: Pet-Cuddle-O-Tron, Type: Standard
    • Assign the created role
    • Logging: ALL
    • Replace FunctionName with your Lambda ARN:
    {
    “Comment”: “Pet-Cuddle-o-Tron using Lambda for email.”,
    “StartAt”: “Timer”,
    “States”: {
    “Timer”: {“Type”: “Wait”, “SecondsPath”: “$.waitSeconds”, “Next”: “Email”},
    “Email”: {
    “Type”: “Task”,
    “Resource”: “arn:aws:states:::lambda:invoke”,
    “Parameters”: {“FunctionName”: “EMAIL_LAMBDA_ARN”,”Payload”: {“Input.$”: “$”}},
    “Next”: “NextState”
    },
    “NextState”: {“Type”: “Pass”, “End”: true}
    }
    }

Validate State Machine workflow:

STAGE 4: Set Up Backend API Using API Gateway and Lambda

Note: The backend of the application (state machine and supporting services) will expose an API for the frontend. This API is managed via API Gateway (APIGW), with a resource and method linked to a Lambda function. The API is deployed to the Prod stage.

STAGE 5: Set Up Frontend Using S3 Static Website

The frontend of the application will be hosted on an S3 bucket configured as a static website. This site will load an HTML page that collects input from the user and forwards it to the API.

  1. Create and configure an S3 bucket
    • Choose a globally unique name for the bucket.
    • Set the region to us-east-1.
    • Disable “Block all public access” and confirm the bucket may be public.
    • Adjust bucket permissions for public access:
      • Update the bucket policy to allow public read access (replace the Resource with your bucket’s ARN):
      {
      “Version”:”2012-10-17″,
      “Statement”:[
      {
      “Sid”:”PublicRead”,
      “Effect”:”Allow”,
      “Principal”: “*”,
      “Action”:[“s3:GetObject”],
      “Resource”:[“REPLACEME_PET_CUDDLE_O_TRON_BUCKET_ARN/*”]
      }
      ]
      }
      • Make sure the /* is included after the bucket ARN.
    • Enable static website hosting for the bucket
      • Navigate to Properties > Static website hosting > Edit > Enable > “Host a static website.”
      • Use index.html for both the index and error pages.
      • Record the Bucket Website Endpoint URL for later use.
  2. Upload frontend files to the S3 bucket
    • Download the website files from Adrian’s GitHub and update serverless.js:
      • whiskers.png → image of Whiskers the cat.
      • index.html → main webpage, containing the form and inputs for user data.
      • main.css → styles for the HTML page.
      • serverless.js → JavaScript to handle button clicks and send data to API Gateway.
        • Replace the API_ENDPOINT variable with the API Gateway URL from Stage 4.
      Example snippet from serverless.js: var API_ENDPOINT = ‘REPLACEME_API_GATEWAY_INVOKE_URL’;var errorDiv = document.getElementById(‘error-message’)
      var successDiv = document.getElementById(‘success-message’)
      var resultsDiv = document.getElementById(‘results-message’)function waitSecondsValue() { return document.getElementById(‘waitSeconds’).value }
      function messageValue() { return document.getElementById(‘message’).value }
      function emailValue() { return document.getElementById(’email’).value }function clearNotifications() {
      errorDiv.textContent = ”;
      resultsDiv.textContent = ”;
      successDiv.textContent = ”;
      }document.getElementById(’emailButton’).addEventListener(‘click’, function(e) { sendData(e, ’email’); });function sendData (e, pref) {
      e.preventDefault()
      clearNotifications()
      fetch(API_ENDPOINT, {
      headers:{
      “Content-type”: “application/json”
      },
      method: ‘POST’,
      body: JSON.stringify({
      waitSeconds: waitSecondsValue(),
      message: messageValue(),
      email: emailValue()
      }),
      mode: ‘cors’
      })
      .then((resp) => resp.json())
      .then(function(data) {
      successDiv.textContent = ‘Submission complete. Check results below.’;
      resultsDiv.textContent = JSON.stringify(data);
      })
      .catch(function(err) {
      errorDiv.textContent = ‘Error occurred:\n’ + err.toString();
      });
      };
    • After updating serverless.js, upload all frontend files to the S3 bucket.
STAGE 6: Test the Serverless Application
STAGE 7 (Optional): Add SMS Notifications

The application now fully supports notifications via both email and SMS.

STAGE 8: Clean Up AWS Resources

LAB: Adding CDN to an S3 Static Website

PART 1: Create and Deploy a CloudFront Distribution with S3 Origin
PART 2: Test the CloudFront Distribution
PART 3: Add an Alternate CNAME and SSL
  1. You must have a custom domain purchased and hosted in Route 53.
    • Optional: follow the demo video if you do not want to spend money.
  2. Edit the CloudFront distribution and add an alternate domain name (CNAME) for your custom domain.

3. Request an SSL certificate from AWS Certificate Manager (ACM):

4. After ACM issues the certificate, select it in the CloudFront distribution along with the alternate name, and save changes. Deployment may take several minutes.

5. Create a Route 53 record pointing your custom domain to the CloudFront distribution:

6. Test the custom domain in a browser; the site should load via CloudFront with HTTPS enabled.

PART 4: Secure the S3 Origin with OAC