DEV Community

Cover image for Cara Membangun Serverless Website dengan reCAPTCHA di AWS
Aditya Chamim Pratama
Aditya Chamim Pratama

Posted on

Cara Membangun Serverless Website dengan reCAPTCHA di AWS

Ini berdasarkan pengalaman saya menghosting static website pribadi saya (adityacprtm.com) di AWS. Saya tidak ingin menjalankan server hanya untuk menangani formulir ‘Contact Us’. Oh, dan saya juga butuh Captcha karena tidak ingin banyaknya spam yang masuk. Jadi saya menggunakan arsitektur serverless website dan google recaptcha untuk itu.

Note: Artikel ini merupakan re-upload dan terjemahan bahasa, artikel original saya bisa dilihat dilink disini.

Alt Text

Arsitektur Aplikasi

Arsitektur aplikasi yang digunakan:

  1. AWS Lambda
  2. Amazon API Gateway
  3. Amazon S3
  4. Amazon SNS
  5. Amazon CloudFront
  6. Amazon Route 53
  7. AWS Certificate Manager
  8. Google reCaptcha

Buat Bucket di Amazon S3

  1. Buka Amazon S3 console atau akses disini
  2. buat bucket dengan nama domain kamu, contohnya example.com
  3. Cukup sampai sini, kita akan upload file nanti

Buat SNS Topic dan Subscription

  1. Buka SNS Console atau akses disini
  2. Buat Topic name
  3. Buat Subscription, pilih Topic ARN sesuai yang telah dibuat pada point 2
  4. Pilih email pada protocol type, lalu create subscription
  5. Periksa email yang didaftarkan dan verify subscription dari AWS

Membuat Serverless Back-end di AWS Lambda

  1. Di Lambda Console, pilih create function
  2. Pilih Author from scratch
  3. Masukan Function name dan pilih Node.js untuk Runtime
  4. Kemudian pilih Create function

Sampai disini kita akan menggunakan lambda dengan JavaScript. Sayangnya kita tidak dapat dengan mudah memasukkan script ke editor online AWS Lambda yang memiliki dependensi eksternal seperti Axios. Jadi kita perlu membuat proyek Node dengan package.json seperti berikut:

{
   "name":"contactForm",
   "version":"0.0.1",
   "private":true,
   "scripts":{},
   "dependencies":{
      "aws-sdk":"^2.560.0",
      "axios":"^0.18.0"
   }
}
Enter fullscreen mode Exit fullscreen mode

Kita akan menggunakan Environment variable di lambda untuk mempermudah ketika ada perubahan pada Topik SNS ARN dan ecret Key dari reCaptcha, ubah index.js seperti berikut:

'use strict';
const AWS = require("aws-sdk");
const axios = require('axios');
const completeUrl = "https://www.google.com";
// verify recaptcha url
const reCapUrl = "https://www.google.com/recaptcha/api/siteverify";
const reCaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
// from Amazon SNS
const snsTopic = process.env.ARN_SNS_TOPIC;
module.exports.handler = async (event, context, callback) => {
    console.log("Starting ContactForm Processing for website form.");
    // console.log("data event: " + JSON.stringify(event));
    // verify the result by POSTing to google backend with secret and frontend recaptcha token as payload
    let verifyResult = await axios({
        method: 'post',
        url: reCapUrl,
        params: {
            secret: reCaptchaSecret,
            response: event.captcha
        }
    }) // print out the result of that. Its a bit verbose though
    // console.log("verify result: " + JSON.stringify(verifyResult.data));
    if (verifyResult.data.success) {
        let sns = new AWS.SNS();
        // The structure of the email
        let emailbody = "Someone left a message for you.\n\nName\t\t: " + event.name + "\nEmail\t\t: " + event.email + "\nSubject\t\t: " + event.subject + "\nMessage\t\t: " + event.message + "\n\nThanks!";
        let params = {
            Message: emailbody,
            Subject: "Contact Form: " + event.subject,
            TopicArn: snsTopic
        };
        // we publish the created message to Amazon SNS now…
        sns.publish(params, context.done);
        // now we return a HTTP 302 together with a URL to redirect the browser to success URL (we put in google.com for simplicty)
        callback(null, {
            statusCode: 302,
            headers: {
                Location: completeUrl,
            }
        });
        console.log("End of the ContactForm Process With Success");
    } else {
        console.log("reCaptcha check failed. Most likely SPAM.");
        callback(null, {
            statusCode: '500',
            body: JSON.stringify({
                message: 'Invalid recaptcha'
            })
        });
    }
};
Enter fullscreen mode Exit fullscreen mode

Setelah membuat proyek, kita perlu mengkompres folder tersebut dalam format ZIP untuk diunggah ke Lambda.

Saat masih di Lambda Console di Function yang telah dibuat sebelumnya, unggah ZIP dan atur environment variable seperti berikut:

environment variable

Kemudian pilih Save.

Deploy Restful API Gateway

  1. Buka API Gateway Console atau akses disini
  2. Pilih Create API dan pilih REST
  3. Pilih New API dan masukkan API Name
  4. Pilih Create API
  5. Pada navigasi kiri, Pilih Resources dibawah API kamu
  6. Dari menu dropdown Actions pilih Create Resource
  7. Masukkan Resource Name seperti contact atau prod kemudian klik Create Resource
  8. Pada Resource yang baru dibuat, dari menu Action dropdown pilih Create Method
  9. Pilih Post kemudian checkmark
  10. Pilih Lambda Function untuk integration type
  11. Pilih Region yang kamu gunakan pada AWS Lambda
  12. Masukkan nama function yang dibuat sebelumnya kemudian Save
  13. [Optional CORS] Pada resource yang baru dibuat, dari dropdown Action pilih Enable CORS kemudian klik enable and replacing
  14. Pada menu dropdown Actions pilih Deploy API, masukkan Stage Name kemudain pilih Deploy
  15. Catat dan simpan Invoke URL yang akan dipakai nanti

Mengatur serverless website

Sebelumnya, kamu dapat menggunakan reCAPTCHA dengan mendaftarkan nama domain disini.

HTML

Kita mengikuti dokumentasi Google reCaptcha, yang berarti harus memasukkan code dibawah diantara tag <head> dan </head>.

<script src="https://www.google.com/recaptcha/api.js"></script>
Enter fullscreen mode Exit fullscreen mode

dan memasukkan code berikut dibagian bawah form sebelum submit button. Jangan lupa memasukkan siteKey yang didapat setelah mendaftarkan domain pada Google reCaptcha.

<div class="g-recaptcha" data-sitekey="xxxxxxxxxxxxxxxxxxx"></div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

Kita dapat menggunakan Ajax untuk melakukan asynchronous HTTP (Ajax) request. Masukkan URL Ajax dengan URL Invoke yang kita dapatkan saat membangun API gateway.

Host Static Website

  1. Kembali ke S3 Console, pilih bucket yang dibuat sebelumnya
  2. Upload files website kamu ke dalam bucket
  3. Setelah selesai, pilih tab Properties
  4. Pilih Static website hosting
  5. Isi bagian index dan error dokumen
  6. Pastikan Block Public access tidak tercentang
  7. Masih di tab Permissions, Pilih Bucket Policy. Masukkan policy document berikut ke dalam editor bucket policy, gantikan [YOUR_BUCKET_NAME] dengan nama bucket yang telah dibuat.
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Principal":"*",
         "Action":"s3:GetObject",
         "Resource":"arn:aws:s3:::[YOUR_BUCKET_NAME]/*"
      }
   ]
}
Enter fullscreen mode Exit fullscreen mode

Konfigurasi Domain di Route 53

  1. Di Amazon Route 53 kita dapat Mendaftarkan domain baru atau menjadikan Route 53 sebagai Layanan DNS untuk domain yang sudah ada
  2. Saya sudah memiliki domain sendiri, jadi saya menjadikan Amazon Route 53 sebagai Layanan DNS untuk domain saya
  3. Di Route 53 Console, pilih Create Hosted Zone.
  4. Pada panel Create Hosted Zone, masukkan nama domain
  5. Pada bagian Type, biarkan default pada Public Hosted Zone
  6. Pilih Create.

Request SSL Certificate di AWS Certificate Manager

  1. Buka ACM Console atau akses disini
  2. pilih Request a Certificate
  3. Pilih Request a public certificate
  4. Add domain name dengan nama domain kamu, contohnya example.com atau *.example.com
  5. Kita perlu memvalidasi certificate request, caranya pilih DNS validation atau email validation. Disini saya menggunakan DNS validation karna itu lebih cepat dan mudah.
  6. Tambahkan CNAME di Amazon Route 53 atau cukup klik tombol di bawah domain kamu untuk menambahkannya secara otomatis.

Buat CloudFront Web Distribution

  1. Buka CloudFront konsol atau akses disini
  2. Buat distribution
  3. pilih Origin Domain Name dengan nama bucket yang dibuat sebelumnya.
  4. Pilih Redirect HTTP to HTTPS
  5. Pilih Yes dibagian Restrict Bucket Access
  6. Pada Distribution Settings, gunakan Custom SSL Certificate dan pilih sertifikat yang telah dibuat pada ACM
  7. Scroll dan temukan Default Root Object, masukkan default file Index.html
  8. Biarkan lainnya default dan create distribution.
  9. Tunggu sampai status Deployed, biasanya ini membutuhkan waktu beberapa menit.
  10. Catat Domain name dari cloudfront

Menggunakan Custom Domain di Route 53

  1. Kembali ke Route 53 Console
  2. Pilih domain yang telah didaftarkan
  3. Pilih Create Record Set
  4. Kita akan membuat 2 record set
  5. Pertama ialah example.com dan yang kedua adalah www.example.com
  6. Gunakan A record dan pilih CloudFront yang telah dibuat.

That’s it, Kita telah membangun serverless static website dengan perlindungan reCaptcha dan notifikasi untuk pemilik atau admin jika ada yang mengirimkan pesan pada form.


Referensi:

  1. AWS Documentations

Top comments (0)