Skip to main content

Command Palette

Search for a command to run...

Scenario: Deploying Secure E-Commerce Frontend (React SPA) to EKS behind CloudFront + WAF

Published
β€’3 min read
S

AWS Certified Solutions Architect with 7 years of experience, along with Certified Kubernetes Administrator (CKA) and Certified Kubernetes Application Developer (CKAD) certifications. Specialized in designing cloud-native architectures, managing large-scale Kubernetes clusters, and building fully automated CI/CD pipelines. Proficient in EKS, Helm, Terraform, GitLab/Jenkins pipelines, Argo CD, Docker, and Linux administration. Experienced in observability and monitoring using Datadog, CloudWatch, and Prometheus. Proven track record of troubleshooting complex production issues, optimizing cloud costs, improving system reliability, and delivering secure, scalable deployments across microservices-based applications.

Customer: 50M USD revenue e-commerce β†’ 99.99% SLA β†’ PCI-DSS compliance required.

Step 1: GitLab Repository Structure

textπŸ“ ecommerce-platform/
β”œβ”€β”€ terraform/           # CloudFront, WAF, VPC, EKS
β”œβ”€β”€ helm-charts/         # React SPA + API
β”œβ”€β”€ jenkins-pipelines/   # CI/CD stages
└── argocd-apps/         # GitOps manifests

Step 2: Terraform Infrastructure (CloudFront + WAF + EKS)

text# terraform/main.tf
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  name = "ecommerce-vpc"
  cidr = "10.0.0.0/16"
}

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  cluster_name = "ecommerce-prod"
  vpc_id = module.vpc.vpc_id
}

# CloudFront + WAF (PCI-DSS compliance)
resource "aws_cloudfront_distribution" "ecommerce" {
  origin {
    domain_name = module.alb.dns_name
    origin_id   = "EKS-ALB"
  }

  default_cache_behavior {
    target_origin_id = "EKS-ALB"
    viewer_protocol_policy = "redirect-to-https"
  }

  web_acl_id = aws_wafv2_web_acl.ecommerce.arn
}

resource "aws_wafv2_web_acl" "ecommerce" {
  name  = "ecommerce-waf"
  scope = "CLOUDFRONT"

  default_action {
    allow {}
  }

  rule {
    name     = "PCI-DSS-SQLi"
    priority = 1
    action {
      block {}
    }
    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesSQLiRuleSet"
        vendor_name = "AWS"
      }
    }
  }
}

# Route53 + ACM
resource "aws_route53_record" "www" {
  zone_id = data.aws_route53_zone.main.zone_id
  name    = "shop.example.com"
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.ecommerce.domain_name
    zone_id                = aws_cloudfront_distribution.ecommerce.hosted_zone_id
    evaluate_target_health = false
  }
}

Step 3: Lambda@Edge for Geo-Blocking

javascript// lambda-edge/geo-block.js
exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const country = request.headers['cloudfront-viewer-country'][0].value;

  // Block high-risk regions
  if (['RU', 'CN', 'KP'].includes(country)) {
    return {
      status: '403',
      statusDescription: 'Access Denied'
    };
  }

  return request;
};

Step 4: Jenkins Pipeline (Security + Deploy)

groovypipeline {
  agent { label 'linux-jenkins-agent' }

  stages {
    stage('Security Scan') {
      steps {
        sh '''
          trivy fs . --exit-code 1 --no-progress
          sonar-scanner -Dsonar.projectKey=ecommerce
        '''
      }
    }

    stage('Terraform Plan') {
      steps {
        sh '''
          terraform init -backend-config=prod-backend.hcl
          terraform plan -var-file="prod.tfvars" -out=tfplan
        '''
      }
    }

    stage('Terraform Apply') {
      when { branch 'release-*' }
      steps {
        sh 'terraform apply -auto-approve tfplan'
      }
    }

    stage('Helm Deploy') {
      steps {
        sh '''
          helm upgrade --install ecommerce-frontend helm-charts/frontend \
            --values=helm-charts/frontend/values-prod.yaml \
            --set ingress.host=shop.example.com
        '''
      }
    }

    stage('ArgoCD Sync') {
      steps {
        sh '''
          argocd app sync ecommerce-prod --selector env=prod
          argocd app wait ecommerce-prod --health --timeout 600
        '''
      }
    }
  }
}

Step 5: GitOps ArgoCD Application

text# argocd-apps/ecommerce-prod.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ecommerce-prod
  namespace: argocd
spec:
  project: ecommerce
  source:
    repoURL: git@gitlab.com:yourorg/ecommerce-platform.git
    targetRevision: release-v2.1.0
    path: helm-charts/frontend
  destination:
    server: https://eks-cluster.amazonaws.com
    namespace: ecommerce-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Step 6: Bash Automation Script

bash#!/bin/bash
# deploy-ecommerce.sh
set -euo pipefail

export TF_VAR_environment=prod
export TF_VAR_dns_domain=shop.example.com

echo "πŸ”„ Deploying secure e-commerce stack..."

# Parallel execution
terraform apply -parallelism=20 -auto-approve prod.tfplan &
helm upgrade ecommerce helm-charts/frontend --wait &

wait
echo "βœ… CloudFront DNS: $(terraform output cloudfront_url)"
echo "βœ… ArgoCD Status: $(argocd app get ecommerce-prod -o jsonpath='{.status.health.status}')"

Step 7: Linux Jenkins Agent Setup

bash# jenkins-agent.Dockerfile
FROM amazonlinux:2023
RUN yum install -y docker.io terraform git jq python3
RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
  && chmod +x kubectl && mv kubectl /usr/local/bin/
USER 1000

Execution Flow (15-minute Deploy)

text1. GitLab MR β†’ main (triggers Jenkins)
2. Security: Trivy + SonarQube β†’ 100% pass
3. Terraform: VPC β†’ EKS β†’ ALB β†’ CloudFront + WAF
4. Route53: shop.example.com β†’ CloudFront alias
5. ArgoCD: Syncs Helm chart β†’ EKS namespace
6. Lambda@Edge: Activates (5min propagation)
7. Datadog: Monitors 99.99% SLA

Metrics Achieved

MetricBeforeAfter
Deploy time2h 15m15m
WAF Block rate0%2.3%
CloudFront TTFB450ms89ms
PCI-DSS findings170