# Create API with AWS Lambda

![serverless-diagram](https://user-images.githubusercontent.com/118417467/263508203-fa8285d3-ff18-42c2-87ae-8dc347c462db.PNG align="left")

The best form of learning cloud is by doing hands-on projects and I came across a beginner-friendly cloud project suggested by Rishab Kumar, the co-author of Learn To Cloud. [https://www.youtube.com/watch?v=-pKrT7Ix3G0](https://www.youtube.com/watch?v=-pKrT7Ix3G0)

This project involves AWS services including API Gateway, Lambda, S3 and Infrastructure as Code (IaC) tools such as Terraform.

## **Objective**

This project aims to create a Lambda function that fetches resume data stored in S3 bucket and displays it in JSON format. Github Actions is integrated to automatically deploy the AWS resources through Terraform.

## Resume in JSON

The contents of the resume were taken from [https://jsonresume.org/schema/](https://jsonresume.org/schema/) and can be edited to your personal information.

## Lambda Function

A Lambda function is written in Python to retrieve the JSON file in S3 bucket and returns the content.

```python
import json
import boto3

s3_client = boto3.client('s3')

BUCKET_NAME = 'serverless-resume-bucket'
RESUME_FILE_KEY = 'resume.json'

def lambda_handler(event, context):
    try:
        response = s3_client.get_object(Bucket=BUCKET_NAME, Key=RESUME_FILE_KEY)
        resume_data = json.loads(response['Body'].read().decode('utf-8'))
        
        return {
            'statusCode': 200,
            'body': json.dumps(resume_data),
            'headers': {
                'Content-Type': 'application/json'
            }
        }
        
    except Exception as e:
        return {
            'statusCode': 500,
            'body': str(e)
        }
```

## Terraform to provision resources

Instead of manually clicking around the AWS console to configure resources such as API Gateway, AWS Lambda, S3 bucket, they were defined in a YAML file.

S3 bucket and object creation:

```yaml
resource "aws_s3_bucket" "serverless_bucket" {

  bucket = "serverless-resume-bucket"
  tags = {
    Name        = "serverless-resume-bucket"
    Environment = "dev"
  }
}

resource "aws_s3_object" "serverless_bucket_object" {
  bucket = aws_s3_bucket.serverless_bucket.id
  key    = "resume.json"
  source = "${path.module}/resume.json"
}
```

Creation of IAM role and IAM policy for Lambda:

```yaml
resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
        Effect = "Allow"
        Sid    = ""
      }
    ]
  })
}

resource "aws_iam_policy" "iam_policy_for_serverless_lambda" {

  name        = "aws_iam_policy_for_serverless_lambda"
  path        = "/"
  description = "AWS IAM Policy for managing the serverless lambda function"
  policy = jsonencode(
    {
      Version : "2012-10-17",
      Statement : [
        {
          Action : [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
          ]
          Resource : "arn:aws:logs:*:*:*",
          Effect : "Allow"
        },
        {
          Effect : "Allow"
          Action : [
            "s3:GetObject",
            "s3:ListBucket"
          ]
          Resource = [
            "arn:aws:s3:::serverless-resume-bucket",
            "arn:aws:s3:::serverless-resume-bucket/*"
          ]
        },
      ]
  })
}

resource "aws_iam_role_policy_attachment" "attach_iam_policy_to_iam_role" {
  role       = aws_iam_role.iam_for_lambda.name
  policy_arn = aws_iam_policy.iam_policy_for_serverless_lambda.arn
}
```

A snippet of the API Gateway resource creation:

```yaml
resource "aws_api_gateway_rest_api" "my-api-gw" {
  name        = "serverless-api-gw"
  description = "Example REST API for demonstration purposes"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}
```

## Github Actions to deploy resources

Set up Github Actions workflow to deploy the resources to AWS. Remember to include AWS Access Key and AWS Secret Key as environment variables for deployment to be successful.

```yaml
name: 'Terraform to deploy infrastructure'

on:
  push:
    paths-ignore:
      - 'README.md'

jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: ./infra

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: 1.4.2

      - name: Terraform Format
        run: terraform fmt -check

      - name: Terraform Init
        run: terraform init
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Validate
        run: terraform validate -no-color

      - name: Terraform Plan
        run: terraform plan -no-color
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

        
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve -no-color
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695190177169/07a137c4-c83b-41b0-bcdf-c3ad43565412.png align="center")

## Final result

The API Gateway with HTTP GET method is created and observed on the AWS console

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1717054865653/808be0b4-85c8-4858-9244-0a61709520c9.png align="left")

Click on the url and ....

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695190480805/c9f2aac2-5292-4ff6-a716-da4db94b4cd1.png align="left")

## Lesson learnt

It sure takes time and a fair amount of effort to complete this beginner project. With the availability of AI tools such as ChatGPT and Github Copilot, leveraging these tools can ease the learning curve for beginners and be more productive.

## My Github Repo

[https://github.com/pohwj/aws-resume-api-terraform](https://github.com/pohwj/aws-resume-api-terraform)
