AWS Serverless Web Sayfası Yayınlama ve Dinamik İletişim Formu Oluşturma [CodePipeline, S3, API Gateway, Lambda, SES ve SNS]

Serkan Bingöl
Cloud Türkiye
Published in
21 min readJan 24, 2021

--

görsel kaynağı https://wpklik.com

Merhaba bu yazımız ile birlikte AWS tam yönetilebilir servislerini kullanarak statik web sayfamızı yayınlamak, yayınladığımız web sayfası üzerinden bir iletişim formu oluşturmak ve bu form üzerinden maillerimizi dinamik şekilde alıp yönetmek için serverless bir mimari oluşturacağız.

Bu mimari içinde bir çok AWS servisini kullanarak hem uygulama yayınlama süreçlerimizi otomatize edeceğiz hem de yayınladığımız web sayfası içinde oluşturacağımız iletişim formu üzerinden mail ve bildirim almayı sağlayacağız.

Uygulama Mimarisi ve Kullanılan AWS Servisleri

AWS üzerindeki kurgumuzu gerçekleştirirken kullandığımız servisleri ve ne için kullanıldıklarını kısaca aşağıda açıklamaya çalışalım.

  • AWS CodePipeline : Hızlı ve güvenilir uygulama ve altyapı güncellemeleri için yayın işlem hatlarımızı otomatikleştirmemize yardımcı olan ve tam olarak yönetilen sürekli teslim hizmetidir. Bu uygulama üzerinde GitHub Reposu içerisinde sakladığımız uygulama koları üzerinde yapmış olduğumuz tüm geliştirmeleri , statik sayfasını yayınlayacağımız AWS depolama hizmetine aktarmak için kullanacağız
  • Amazon Simple Storage Service S3 : Internet’te her yerden, her boyutta veri almak ve depolamak için oluşturulmuş bir nesne depolama hizmetidir. Biz bu uygulama üzerinde statik web sayfamızı host edeceğimiz alan ve bizlere gelen emailleri depolayacağımız alan olmak üzere 3adet S3 Bucket oluşturacağız.
  • AWS Lambda : Sunucu tedarik etmek veya yönetmek zorunda kalmadan kod çalıştırmamıza olanak tanıyan bir sunucusuz işlem hizmetidir.Bu uygulama üzerinde iletişim sayfası üzerinden alınan bilgilerden, mail oluşturma ve yönetmek üzere bir backend uygulamasını Lambda kullanarak gerçekleştireceğiz. Ayrıca oluşan mail sonrasında mailin geldiğini SMS yolu ile site yöneticisine bildirim olarak göndereceğimiz 2. bir lambda fonksiyonu geliştireceğiz.
  • Amazon API Gateway: İstenen ölçekte API’ler oluşturulup yayımlanmamızı mümkün kılan, tam olarak yönetilen bir API hizmetidir. Bu uygulama içinde mail oluşturma ve alma işlemleri için lambda fonksiyonumuzu tetiklemek üzere kullanacağımız endpointlerimizi API gateway yardımı ile oluşturacağız.
  • Amazon Simple Email Service (SES): Herhangi bir uygulamadan posta göndermemize olanak tanıyan uygun maliyetli, esnek ve ölçeklenebilir bir e-posta hizmetidir. Bu uygulamada bir mail sunucusu kurup yönetip konfigurasyonlar ile uğraşmak yerine bu servisten faydalanacağız.
  • Amazon Simple Notification Service (Amazon SNS): Uygulamadan uygulamaya (A2A) hem de uygulamadan kişiye (A2P) iletişim için tam olarak yönetilen bir mesajlaşma hizmetidir. Oluşturduğumuz mailleri AWS’in pub-sub hizmetini kullanarak SMS yolu ile ilgili site yöneticisine bildirim olarak göndereceğiz.
  • Amazon Route 53 : Yüksek oranda erişilebilir ve ölçeklenebilir bir bulut Etki Alanı Adı Sistemi (DNS) web hizmetidir. Burada uygulamamız için kullanıcı dostu bir domain adı üzerinden web sayfalarımızın yayınlanmasını gerçekleştireceğiz.

AWS Hizmet Bileşenlerini Oluşturma

ÖNEMLİ : İleride SES servisi içinde anlatacağımız bazı özellikleri kullanmak için İrlanda (eu-west-1) bölgesi içinde çalışacağız.

Artık AWS konsolu üzerinde gerekli bileşenleri oluşturmaya başlayabiliriz. Aşağıda sırası ile bir çok bileşen oluşturucağız.

S3 (Simple Storage Service)

Statik web içeriklerimizin AWS servislerini kullanarak yayınlamak için öncelikle S3 servisi üzerinde gerekli adımları tamamlıyacağız. Konsol üzerindeki “Services” sekmesi üzerinden “Storage” başlığı altındaki “S3” hizmetini seçerek işlemlerimizi başlatıyoruz.

S3-Simple Storage Service

Burada dikkat edilmesi gereken 2 kısım bulunmakta. S3 başlığı altında açacağımız object tipinde dosyaları tutmamıza yarayan “Bucket” isimdeki yapıların hepsinini isimlendirmelerinde benzersiz bir değerler kullanılması gerektiğidir.

Ayrıca web sitesi için hosting olarak kullanacağımız 2 bucket için alan adımız ne ise bucketların isimlendirmelerinin o şekilde verilmesi gerekiyor. Örneğin google.com alan adı üzerinden bir web sitesi yayınlamak istiyorsak bucketlar google.com ve www.google.com olarak isimlendirilmelidir.

Ben burada cloudlyze.com alan adına sahip olduğum için “cloudlyze.com-mail”, “cloudlyze.com” ve “www.cloudlyze.com” isimli 3 adet bucket oluşturuyorum. “cloudlyze.com-mail” bucketini ileride SES üzerinden oluşturacağımız epostaları arşivlemek için kullanacağım.

Oluşturduğumuz S3 Buckets

Oluşturduğumuz bucketlar içinde “cloudlyze.com” u statik web dosyalarımızı barındırmak için kullanacağız. İleri kısımlarda Route53 ile domain yönlendirmesi yapacağımız “www.cloudlyze.com” bucket’ından faydalanarak asıl statik sayfalarımızın barındırıldığı S3 bucket (cloudlyze.com) üzerine yönlendirme gerçekleştireceğiz. Son olarak SES ve Lambda servisleri ile entegre şekilde çalışacak iletişim sayfası üzerinden aldığımız bilgilere göre oluşturduğumuz mailleri “cloudlyze.com-mail” S3 bucket’ı üzerinde arşivleyeceğiz.

  • cloudlyze.com : Bu bucket üzerinde statik içeriklerimizi yayınlamadan önce birkaç ayarlamayı gerçekleştirmemiz gerekmekte. İlk olarak S3 servisi üzerinden bu ad ile oluşturduğumuz bucket’ı seçerek Properties tabını seçiyoruz.

Properties alanı üzerinden bizlere açılan sayfadan “Static Website Hosting” alanından edit diyerek web sayfamızı yayınlamak için gereken ayarlamaları yapıyoruz. Burada “Static website hosting” kısmını enable edip hosting type olarak “Host a static website” tipini seçiyoruz. Ana sayfamız ve hata sayfamız için index document alanına ana sayfamızın , error document alanına ise hata sayfamızın dosya isimlerini veriyoruz. Burada eğer yayınladığınız statik içerik için klasör sisteminiz var ise bu isimlendirmelerde buna dikkat etmeniz gerekmektedir.

Daha detaylı bilgi için aşağıdaki referanslar alanında bulunan “Hosting a static website using Amazon S3” başlıklı yazıyı inceleyebilirsiniz.

Yayınladığımız statik içeriklerin herkes tarafından ulaşılabilmesi ve görüntülenebilmesi için yayın yaptığımız S3 bucket üzerinde bazı ayarlar yapmamız gerekmektedir. Burada öncelikle bir S3 bucket oluşturduğumuz zaman varsayılan olarak kapalı olan 4 ayarı bilgimiz dahilinde açtığımıza yönelik bir onay vermemiz gerekmekte. Bucket içindeki Permissions alanı üzerinden “Block public access” kısmında edit diyerek tüm kapalı olan ayarlamaları aktif hale getiriyoruz.

Bucket için public olarak erişilebilirlik bloğunu kaldırdıktan sonra hemen aşağıda bulunan “Bucket policy” alanında bu bucket üzerine yüklenen tüm dosyalarımız için tek tek görüntülenebilir yetkisi vermek yerine tüm bucket üzerinden dosyalanalara görüntülenebilir yetkisini vermemiz gerekmektedir. Bunun için json formatında aşağıdaki kod bloğunu ekliyoruz. Resource alanı içinde kendi bucket arn (aws resource name) tanımını girmeyi unutmamamız gerekmekte.

{
“Version”: “2012–10–17”,
“Statement”: [
{
“Sid”: “PublicReadGetObject”,
“Effect”: “Allow”,
“Principal”: “*”,
“Action”: “s3:GetObject”,
“Resource”: “arn:aws:s3:::xxxxxx.com/*”
}
]
}

NOT : Resource alanı içinde kendi bucket arn (aws resource name) tanımını girmeyi unutmamamız gerekmekte.

EXTRA : S3 üzerinden statik içerik dağıtımı sağlandığında ve bu statik web içeriklerinin başka siteler ya da farklı domain üzerinde yayında olan AWS servisleri ile iletişimini sağlarken CORS hatası alabiliriz bu sayfa üzerinden başka sayfalara içerik dağıtmak istiyorsan bucket üzerinde gerekli CORS ayarlarının yapılması gerekmektedir.

[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"POST",
"DELETE",
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]

Biz dinamik iletişim formumuz üzerinden API Gateway servisini kullanarak arka tarafta çalıştıracağımız bir Lambda fonksiyonu tetikleteceğiz. Burada CORS ayarlamalarını API Gateway üzerinden yapacağız. Bundan dolayı buradaki bucket ayarlamalarını yapmak zorunda değiliz.

  • www.cloudlyze.com : Bu bucket üzerinde statik içeriklerimizi yayınladığımız cloudlyze.com bucket’ına www.cloudlyze.com adresi üzerinden gelen web isteklerini yönlendirme yapmak için gereken ayarlamaları yapacağız. Bunun için önce birkaç ayarlamayı gerçekleştirmemiz gerekmekte. İlk olarak S3 servisi üzerinden bu ad ile oluşturduğumuz bucket’ı seçerek Properties tabını seçiyoruz.

Properties alanı üzerinden bizlere açılan sayfadan “Static Website Hosting” alanından edit diyerek web sayfamızın yönlendirmesi için gereken ayarlamaları yapıyoruz. Burada “Static website hosting” kısmını enable edip hosting type olarak “Redirect requests for an object” tipini seçiyoruz. Host-name kısmında statik web içeriklerimizin yüklendiği cloudlyze.com bucket’ını yazıyoruz ve http protokolü üzerinden gereken bucketlar arası yönlendirmeyi tamamlıyoruz. Daha detaylı bilgi için aşağıdaki referenslar alanında bulunan “Hosting a static website using Amazon S3” başlıklı yazıyı inceleyebilirsiniz.

Yukarıda yaptığımız işlemler www.cloudlyze.com bucket’ına gelen isteklerin cloudlyze.com bucket’ına yönlendirmesi için geçerlidir. Domain yönlendirmesi için gereken işlemleri Route53 servisi ile ilgili kısımda anlatacağız.

  • cloudlyze.com-mail : Son olarak açtığımız bu bucket’ı SES (simple email service) servisi üzerinden alacağımız mailleri arşivlemek için kullanacağız. Birkaç mail adresi kullanmayı planlıyorsak bu bucket üzerinde Create folder diyerek gelen mailleri arşivleyeceğimiz klasörleri oluşturuyoruz. Biz sadece contact form üzerinden info@cloudlyze.com mail adresini kullanarak işlem gerçekleştireceğimiz için info klasörünü alıyoruz.

CodePipeline

Sürekli entegrasyon ve sürekli deployment süreçlerimizi uygulamamızın içine dahil etmek için Aws CodePipeline servisi üzerinde gerekli adımları tamamlıyacağız. Konsol üzerindeki “Services” sekmesi üzerinden “Developer Tools” başlığı altındaki “CodePipeline” hizmetini seçerek işlemlerimizi başlatıyoruz. Burada Create Pipeline ile yeni bir pipeline oluşturmaya başlıyoruz.

Pipeline adını belirledikten sonra, New service role ile bu pipeline için yeni bir servis rolü oluşturma işlemini AWS tarafına bırakıyoruz. Advanced settings içinden artifact store olarak istersek belirlediğimiz bir S3 bucket içinde ilgili deployment artifactlerini tutabileceğimiz bir kurgu oluşturabiliriz fakat bu senaryoda varsayılan ayarları kullanacağız.

İkinci aşamada hangi kod kaynağını kullanacağımızı belirliyoruz. Burada ben GitHub üzerinde tek branch üzerinden çalıştığım için Github Version 2 olarak seçiyorum. GitHub hesabınızı AWS hesabınız ile eşleştimek için aşağıdaki referanslar alanında bulunan “GitHub connections” başlıklı yazıyı inceleyebilirsiniz.

Eşleştime işleminiz tamamladıktan sonra yayınlamak istediğimiz repository ve branch alanlarınızı tamamlayıp kalan adımları varsayılan alanları bırakarak ikinci adımımızı tamamlıyoruz

Üçüncü adım olan build adımını statik web sayfası yayınlayacağımız ve herhangi bir derleme işlemi yapmıyacağımızdan dolayı “Skip build stage” diyerek atlıyoruz.

Dördüncü adımımızda deployment olarak S3 bucketimizi kullanacağımızı belirliyoruz. Burada dikkat edilmesi gereken nokta S3 bucketları içinde Web Hosting ayarlarını açtığımız ama yönlendirme yapmadığımız asıl bucket’ımız olan cloudlyze.com bucket’ını seçmemiz gerektiğidir.

İşlemleri tamamladıktan sonra ilgili pipeline oluşturulmuş ve kullanıma hazır olmuş bulunmaktadır.

Oluşturduğumuz pipeline‘ ı incelediğimizde hem Source hem Deploy adımlarının başarılı şekilde oluşturulduğunu görebilmekteyiz.

Route 53

Bu kısımda www.cloudlyze.com domain adresine gelen web isteklerinin statik web sayfalarımızın yayınlandığı S3 kovasına yönlendirilmesi için Route 53 servisinden faydalanacağız.

Burada domain alan adı işlemlerimiz ile ilgili yeni alan adı alınması yada elimizde bulunan bir alan adının transferini yapmak için aşağıdaki referanslar alanında bulunan “Registering domain names using Amazon Route 53” başlıklı yazıyı inceleyebilirsiniz. Bizim kurgumuz içinde cloudlyze.com alan adı Route 53 üzerinden register edildiği için bu aşama ile ilgili herhangi bir işlem gerçekleştirmiyoruz.

Konsol üzerindeki “Services” sekmesi üzerinden “Networking & Content Delivery” başlığı altındaki “Route 53” hizmetini seçerek işlemlerimizi başlatıyoruz. Hosted zones alanı altında ilgili alan adımızı seçerek Create record ile yönlendirme için gereken adımlara başlayabiliriz. Toplamda cloudlyze.com ve www.cloudlyze.com adları olacak şekilde 2 adet record oluşturacağız.

Create record buttonu ile başlattığımız işlemler için simple routing seçeneğini seçiyoruz ve next ile işlemimize devam ediyoruz.

İlk record için cloudlyze.com record name ile value/route traffic alanında ilk kısımda “Alias to S3 website endpoint” seçeneği ile bir S3 kovası yönlendirmesi yapıyoruz. Region olarak İrlandayı seçiyoruz ve son olarak cloudlyze.com S3 bucket’ını seçiyoruz. Evaluate target health kısmını bir health check yapmak istemediğimiz için No olarak işaretliyoruz.

İkinci record için www.cloudlyze.com record name ile value/route traffic alanında ilk kısımda “Alias to S3 website endpoint” seçeneği ile bir S3 kovası yönlendirmesi yapıyoruz. Region olarak İrlandayı seçiyoruz ve son olarak www.cloudlyze.com S3 bucket’ını seçiyoruz. Evaluate target health kısmını bir health check yapmak istemediğimiz için No olarak işaretliyoruz.

Hosted zone alanı içinden alan adımızı seçerek oluşturduğumuz kayıtların başarılı şekilde gerçekleştirildiğini görüntüleyebilmekteyiz.

SES (Simple Email Service)

Dinamik iletişim sayfası formu üzerinden info@cloudlyze.com olarak belirleyeceğimiz eposta adresi ile müşterilerimizin isteklerini eposta yolu üzerinden alabilmek ve yönetmek için AWS üzerinde SES servisinden faydalanacağız. Yazımızın başında SES ile ilgili bazı özelliklerden faydalanabilmek adına İrlanda bölgesinde çalışacağımızdan bahsetmiştik. Bunun amacı SES üzerinden mail alma işlemleri sadece bazı AWS bölgelerinde aktif olarak kullanılabilmekte. Aşağıdaki resim üzerinden bu AWS bölgelerini inceleyebilirsiniz.

SES kullanımı ile ilgili daha detaylı bilgi alabilmek için aşağıdaki referanslar alanında bulunan “Amazon SES Quick start” başlıklı yazıyı inceleyebilirsiniz. Biz gerekli adımları teker teker anlatmaya çalışacağız.

Konsol üzerindeki “Services ” sekmesi üzerinden “Customer Engagement” başlığı altındaki “Simple Email Service” hizmetini seçerek işlemlerimizi başlatıyoruz.

İlk adımda domains alanı üzerinden “Verify a New Domain” diyerek öncelikle yeni bir mail domani oluşturuyoruz. Domain onaylama ile ilgili daha detaylı bilgi alabilmek aşağıdaki referanslar alanında bulunan “Verifying a domain with Amazon SES” başlıklı yazıyı inceleyebilirsiniz.

Route 53, doğruladığımız etki alanı için DNS hizmetini otomatik sağladağından dolayı ve gerekli kullanımı bizim için kolaylaştırdığından dolayı “Use Route 53” diyerek varsayılan ayarları kabul ediyoruz.

Create Record Sets” ile tüm default ayarları kabul ederek gerekli DNS hizmetini SES için ayarlıyarak kullanmaya başlayabiliriz.

Route 53 üzerinden cloudlyze.com hosted zone recordlarına bakarsak SES servisi için oluşturulmuş 2 adet kaydı görebiliriz.

Oluşturmuş olduğumuz domain üzerinden hangi mail adresini kullanmak istiyorsak “Email Addresses” alanı üzerinden “Verify a New Email Address” ile info@cloudlyze.com mail adresini tanımlıyoruz.

Artık info@cloudlyze.com mail adresini onayladığımız için mail alma ve mail yollama işlemleri için bazı ayarlamalar yapmamız gerekmektedir. Öncelikle bu mail adresi üzerinden mail atmak istedeğimiz tüm kullanıcıların mail yolu ile bildirim almak istediklerini onaylamaları gerekmektedir. Bu konu iletişim formları üzerinden çok fazla efor ve geliştirme gerektiği için SES hizmetinin bu varsayılan güvenlik alanından çıkmak gerekmektedir. Bu işlemi yapabilmek ile ilgili daha detaylı bilgi alabilmek için aşağıdaki referanslar alanında bulunan “Moving out of the Amazon SES sandbox” başlıklı yazıyı inceleyebilirsiniz. Kısaca bahsetmek gerekir ise AWS support üzerinden bu işlemi neden yapmak istediğinize dair bir form doldurmanız gerekmektedir.

Sonrasında info@cloudlyze.com adresine gelen mailleri depolamak için oluşturduğumuz cloudlyze.com-email adlı S3 bucket’ı için gereken ayarlamaları yapmaya başlayabiliriz. Konsol üzerinden SES servisi içinde sol menü üzerinden “Rule Sets” alanı üzerinden yeni bir kural seti oluşturuyoruz. Birinci adımda bu kuralın info@cloudlyze.com için kullanılacağını belirliyoruz.

İkinci aşama olan “Actions” kısmından bu kuralın bir S3 bucket için kullanılacağını belirliyoruz.

Actions” kısmında daha önceden oluşturduğumuz cloudlyze.com-mail adlı S3 bucket’ını ve bunun içinde oluşturduğumuz info klasörünü belirtiyoruz.

Oluşturduğumuz mail alma kuralı için bir isim belirleyerek default ayarları onaylayıp devam ediyoruz.

Son olarak bu oluşturduğumuz e-posta alma kuralını oluşturmak için “Create Rule” diyerek gelen maillerin cloudlyze.com-email S3 bucket’ı üzerinde depolanmasını sağlıyoruz.

Rule Sets alanı üzerinden son kontrolümüzde ilgili kuralın başarılı bir şekilde oluşturulduğunu görmekteyiz.

SNS (Simple Notification Service)

İletişim sayfası üzerinden aldığımız maillerin herhangi bir mail client programına bağlamadığımız için gelen mailleri cep telefonumuza SMS bildirimi olarak göndermek için SNS servisinden faydalanacağız.

Konsol üzerindeki “Services ” sekmesi üzerinden “Application Integration” başlığı altındaki “Simple Notififation Service” hizmetini seçerek işlemlerimizi başlatıyoruz.

İlk adım için SNS’te mesajların iletimini sağlayan bir iletişim kanalı olan topic olusturmak gerekmektedir. “Topics” alanından “Create topic” diyerek gereken işlemi başlatıyoruz

Bir SNS Topic’i oluşturmak için sadece isim vermemiz yeterli olmaktadır. Gelen ekran üzerinden Standart tip seçip, isim olarak cloudlyze-received-email-notification isimlendirmesini vererek Create topic diyoruz.

Topic kısmını başarılı şekilde oluşturduğumuzu kontrol ettikten sonra artık subscription oluşturma işlemine başlayabiliriz.

Subscription alanı üzerinden “Create subscription” diyerek nereye ve hangi tipte bir bildirim yapacağımızı belirlememiz gerekmektedir. Topic’ler Subscribe işlemi ile HTTP, SMS, Email veya Amazon SQS servislerine iletim yapabilmektedir.

Subscription için oluşturduğumuz cloudlyze-received-email-notification isimli topic’i seçiyoruz. Protocol olarak SMS ve endpoint olarak hangi telefon numarısına bildirim almak istiyorsak onun bilgilerini giriyoruz. Create subscription diyerek işlemin son adımına geçiyoruz.

Subscription kısmını başarılı şekilde oluşturduğumuzu kontrol ettikten sonra artık Lambda fonksiyonlarımızı oluşturma işlemine başlayabiliriz.

SNS topic ve subscription oluşturma ile ilgili daha detaylı bilgi alabilmek için aşağıdaki referanslar alanında bulunan “Configuring Amazon SNS” başlıklı yazıyı inceleyebilirsiniz.

Lambda

İletişim formu üzerinden alınan bilgilerden mail oluşturma ve oluşan mailleri sms bildirimi olarak almak için Lambda servisi üzerinde cloudlyze-send-mail ve cloudlyze-send-sms isimli 2 adet fonksiyon oluşturacağız.

Konsol üzerindeki “Services ” sekmesi üzerinden “Compute” başlığı altındaki “Lambda” hizmetini seçerek işlemlerimizi başlatıyoruz. Create functions üzerinden mail servisini tetikleyeceğimiz ilk fonksiyonumuzu oluşturmaya başlıyoruz.

Bu kısım içinde “Use a blueprint” içinde “hello-world” nodejs fonksiyonunu seçiyoruz. Bu sayede ön ayarlamalı yapılmış bir lambda fonksiyonu oluşturuyoruz.

Function name olarak cloudlyze-send-mail isimlendirmesi ile oluşturduğumuz fonksiyon için bir lambda execution rolü oluşturmamız gerekmekte. Bunun için “Create a new role with basic Lambda permission” diyerek rolü oluşturuyoruz. İleride bu IAM rol için genişletmeler gerçekleştireceğiz.

Functions sekmesi üzerinden lambda fonksiyonunun listelendiği ekrana giderek bu fonksiyonumuzun içeriğini hazırlamak için ilerliyoruz. Fonksiyonun içine girerek kodlarımızı oluşturmaya başlayabiliriz.

Lambda fonksiyonunun bulunduğu sayfa üzerinde Code source alanına geliyoruz.

Bu kısımda AWS‘ in JavaScript SDK sını kullanarak gelen form bilgilerine göre SES servisi üzerinden mail oluşturacağımız kod bloğunu hazırlıyoruz. Bu lambda fonksiyonunu ileride oluşturacağımız bir API Gateway ile tetikliyerek contact formu üzerinden aldığımız bilgilerden bir Email oluşturacağız.

var AWS = require('aws-sdk');
var ses = new AWS.SES();

var RECEIVER = 'xxxxxx@xxxxx.com';
var SENDER = 'xxxxxx@xxxxx.com';

var response = {
"isBase64Encoded": false,
"headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': 'example.com'},
"statusCode": 200,
"body": "{\"result\": \"Success.\"}"
};

exports.handler = function (event, context) {
console.log('Received event:', event);
sendEmail(event, function (err, data) {
context.done(err, null);
});
};

function sendEmail (event, done) {
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Referral Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
ses.sendEmail(params, done);
}

Kod bloğumuzu index.js sayfasına ekledikten sonra deploy function ile ilgili lambda fonksiyonunu yayınlıyoruz.

İkinci fonksiyonumuz içinde “Use a blueprint” içinde “hello-world” nodejs fonksiyonunu seçiyoruz. Bu sayede ön ayarlamalı yapılmış bir lambda fonksiyonu oluşturuyoruz.

Function name olarak cloudlyze-send-sms isimlendirmesini belirliyoruz. Oluşturduğumuz fonksiyon için bir lambda execution rolü kullanmamız gerekmekte. Daha önce oluşturduğumuz lambda rolünü bu fonksiyonumuz içinde kullanacağız

Lambda fonksiyonunun bulunduğu sayfa üzerinde Code source alanına geliyoruz.

Bu kısımda AWS‘ in JavaScript SDK sını kullanarak SES servisi üzerinden oluşturduğumuz mail cloudlyze.com-email S3 Bucket içine arşivlendiği takdirde , SNS üzerinden belirlediğimiz telefon numarasına mail gönderecek fonksiyonunu hazırlıyacağız. Bu lambda fonksiyonunu cloudlyze.com-email S3 bucket üzerinde bir obje oluştuğu takdirde tetiklenecektir.

console.log('Loading function');
var aws = require('aws-sdk');
exports.handler = function(event, context) {
var sns = new aws.SNS();
console.log('start of brians sns function')
sns.publish({
Message: 'You have mail from info@cloudlyze.com ! ',
TopicArn: 'arn:aws:sns:eu-west-1:xxxxxxxxxxx:cloudlyze-received-email-notificaion'
}, function(err, data) {
if (err) {
console.log(err.stack);
// Notify Lambda that we are finished, but with errors
context.done(err, 'SMS Function Finished with Errors!');
return;
}
console.log('push sent');
console.log(data);
// Notify Lambda that we are finished
context.done(null, 'SMS Function Finished!');
});
};

Kod bloğumuzu index.js sayfasına ekledikten sonra deploy function ile ilgili lambda fonksiyonunu yayınlıyoruz.

İlgili lambda fonksiyonlarına atamış olduğuz rol için SNS, SES ,S3 gibi servisleri kullanmamız gerekcektir. Bunun için öncelikle oluşturduğumuz herhangi bir fonksiyonun içine girip “Configuration” alanı üzerinden “Permissions” kısmına bakarak rol adımızı öğreniyoruz ve buradan IAM servisine geçiyoruz.

IAM servisi içinde ilgili role üzerinde Attach Policies diyerek S3, CloudWatch, SES, SNS ve Lambda servisleri için full yetki atamalarını aşağıdaki şekilde gerçekleştiriyoruz.

SMS üzerinden bildirim alabilmek için cloudlyze.com-mail bucket’ı üzerinden bir olay tetiklemesi gerçekleştimemizin gerekliliğinden bahsetmiştik. Bunun için S3 Bucket’ı içinde Properties alanına bakmamız gerekmektedir.

Alt kısımlarda bulunan Event notifications alanı içinde Create event notification diyerek gerekli S3 olay tetikleme işleminin ayarlarını yapmaya başlıyoruz.

Burada bu bucket içinde bulunan info klasöründe herhangi bir obje oluşturulduğu zaman çalışacağını aşağıdaki ayarlamaları yaparak sağlıyoruz.

Devamında bu S3 bucket’ın cloudlyze-send-sms lambda fonksiyonunu tetikleyeceğini belirtiyoruz.

İlgili lambda fonksiyonu içine gidersek burada trigger kısmında S3 Event’inin geldiğini görebilmekteyiz.

API Gateway

İletişim formu üzerinden aldığımız bilgileri ilgili lambda fonksiyonumuza göndermek ve bu fonksiyonu tetiklemek için API Gateway servisinden faydalanacağız. Bir Rest API yazmak yerine tamamen yönetilebilir bir servis olan API Gateway kullanımı bize hız ve esneklik kazandıracaktır.

Konsol üzerindeki “Services ” sekmesi üzerinden “Networking & Content Delivery” başlığı altındaki “API Gateway” hizmetini seçerek işlemlerimizi başlatıyoruz. Burada Create API diyerek ilgili işlemimizi başlatıyoruz.

Gelen ekran üzerinden API Gatewayimiz için REST API tipini seçerek Build ile devam ediyoruz.

New API diyerek cloudlyze-api isimlendirmesi ile “Endpoint Type” olarak Regional seçip devam ediyoruz.

Oluşturduğumuz cloudlyze-api içinde “Actions” alanı üzerinden Create Resource kısmını seçerek işlemimize devam ediyoruz.

Contact isminde bir resource oluştururken CORS ayarını enable etmeyi unutmuyoruz. Bu sayede browser üzerinden gönderğimiz ve cloudylze.com domaini, API gateway ve Lambda fonksiyonu arasında CORS hatalarını engellemiş olacağız. API Gateway ve CORS ile ilgili daha detaylı bilgi alabilmek için aşağıdaki referanslar alanında bulunan “Enabling CORS for a REST API resource” başlıklı yazıyı inceleyebilirsiniz.

Oluşturduğumuz cloudlyze-api içinde bulunan “Contact” resource için “Actions” alanı üzerinden Create Method kısmını seçerek işlemimize devam ediyoruz.

İlgili API methodunu PUT tipinde oluşturup cloudlyze-send-email lambda fonksiyonunu tetikleyeceğini ayarlıyoruz.

Artık aşağıdaki bir çıktı ile API Gateway PUT methodu ve lambda fonksiyonumuzu eşleştirmiş oluyoruz.

Oluşturduğumuz cloudlyze-api için “Actions” alanı üzerinden Deploy API kısmını seçerek işlemimize devam ediyoruz.

API Gatewayimiz için stage bilgilerini New Stage diyerek belirliyoruz.

Artık API Gateway kullanıma hazır hale getirilmiş bulunmakta. Stages kısmı üzerinden oluşturduğumuz PUT methodunun içini incelediğimizde bizlere kullanabileceğimiz ve lambda fonksiyonunu tetikleyebileceğimiz bir endpoint verdiğini görebilmekteyiz. bu endpointi ileride iletişim formu içinde kullanacağız.

İlgili lambda fonksiyonu içine gidersek burada trigger kısmında API Gateway’in geldiğini görebilmekteyiz.

İletişim Sayfası Oluşturma

Artık iletişim formumuzun HTML kodlarını dilediğimiz şekilde contact.html sayfamızın içine ekleyebiliriz. Burası için herkes kendine ait bir iletişim formu tasarımı kullanabilir en basit şekilde eklemek isteyenler aşağıdaki kod bloğundan faydalanabilirler.

<form id="contact-form" method="post">
<h4>Name:</h4>
<input type="text" style="height:35px;" id="name-input" placeholder="Enter name here…" class="form-control" style="width:100%;" /><br/>
<h4>Phone:</h4>
<input type="phone" style="height:35px;" id="phone-input" placeholder="Enter phone number" class="form-control" style="width:100%;"/><br/>
<h4>Email:</h4>
<input type="email" style="height:35px;" id="email-input" placeholder="Enter email here…" class="form-control" style="width:100%;"/><br/>
<h4>How can we help you?</h4>
<textarea id="description-input" rows="3" placeholder="Enter your message…" class="form-control" style="width:100%;"></textarea><br/>
<div class="g-recaptcha" data-sitekey="6Lc7cVMUAAAAAM1yxf64wrmO8gvi8A1oQ_ead1ys" class="form-control" style="width:100%;"></div>
<button type="button" onClick="submitToAPI(event)" class="btn btn-lg" style="margin-top:20px;">Submit</button>
</form>

Kod bloğumuzu contact.html sayfasına ekledikten sonra sayfamızı güncellemiş oluyoruz.

İletişim formundan gerekli bilgileri alıp API gateway içine gönderecek gerekli JavaScript kod bloğunu aşağıdaki şekilde kullanabilirsiniz. Burada dikkat edilmesi gereken kısım var URL = "https://xxxxxxx.execute-api.us-east-1.amazonaws.com/01/contact"; olarak yazılan yere oluşturduğumuz API Gateway PUT methodu için oluşturduğumuz URL in kullanılması gerekliliğidir.

function submitToAPI(e) {
e.preventDefault();
var URL = "https://xxxxxxx.execute-api.us-east-1.amazonaws.com/01/contact";

var name = $("#name-input").val();
var phone = $("#phone-input").val();
var email = $("#email-input").val();
var desc = $("#description-input").val();
var data = {
name : name,
phone : phone,
email : email,
desc : desc
};

$.ajax({
type: "POST",
url : "https://abc1234.execute-api.us-east-1.amazonaws.com/01/contact",
dataType: "json",
crossDomain: "true",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),


success: function () {
// clear form and show a success message
alert("Successfull");
document.getElementById("contact-form").reset();
location.reload();
},
error: function () {
// show an error message
alert("UnSuccessfull");
}});
}

Kod bloğumuzu istersek contact.html sayfasına <scripts></scripts> blokları arasına ekleyebilir istersek farklı bir js sayfası oluşturabilir ve burada gerekli işlemi yapabiliriz.

UYGULAMA DEMO

Artık tüm AWS servislerimizi birbiri ile entegre çalışacak şekilde tamamladık ve iletişim formunu web sayfamızın içine ekledik. Bir demo ile tüm işlemlerin kurgumuza uygun şekilde çalıştığını test edeceğiz. Bu demo 2 aşamadan oluşacak.

Yaptığımız değişikliklerin GitHub + CodePipeline ve S3 üzerinden anlık olarak canlı sisteme yansıtılabildiği aşama birinci kısımda “CodePipeline Testi“ başlığı altında ele alacağız.

İletişim formumuzun üzerinden gerekli bilgileri alıp API Gateway ve Lambda fonksiyonlarını kullanarak SES hizmeti üzerinden mail oluşturulmasını , bu mailin S3 üzerinde arşivlenmesini, devamında başka bir lambda fonksiyonun tetiklenip bir SNS bildiriminin oluşturulmasını ikinci aşama olan “API Gateway , Lambda , SES ve SNS Testi” içinde ele alacağız.

CodePipeline Testi

Öncelikle www.cloudlyze.com web sitesi üzerinden yayında olan iletişim sayfamızı kontrol ediyoruz. Burada formun üzerinde “Contact With Us” yazısını görebilmekteyiz.

İletişim web sayfamız olan contact.html sayfasında ilgili kod bloğu üzerinde bu yeri buluyorum.

Bu sayfada bir değişiklik yapıp git komutlarını kullanarak ilgili GitHub repository’imize “Contact Page Updated for CodePipeline” mesajı ile bir commit olarak gönderiyoruz.

AWS hesabımız üzerinde CodePipeline içinde cloudlyze.com-s3-deployment pipeline’ına bakınca bu pipeline2ın çalıştığını görebilmekteyiz.

GitHub hesabımıza baktığımızda ilgili commit’in “Contact Page Updated for CodePipeline” mesajı ile yansıdığını görebilmekteyiz.

AWS üzerindeki pipeline içine baktığımız da aynı commit mesajının ve numarasının burada kullanıldığını görebilmekteyiz.

S3 hizmeti üzerinden cloudlyze.com bucket’ına baktığımızda tüm dosyalarımızın bu bucket içine yüklendiğini görebilmekteyiz.

Web tarayıcısı üzerinden www.cloudlyze.com/contact.html sayfasına baktığımızda ilgili değişikliğin yansıdığını görebilmekteyiz.

Burada ilgili web sayfamız için CI / CD süreçlerimizi GitHub, CodePipeline ve S3 AWS servislerini kullanarak başarılı bir şekilde sisteme aktarabildiğimizi test etmiş bulunmaktayız.

API Gateway , Lambda , SES ve SNS Testi

Öncelikle cloudlyze.com-email S3 bucket üzerinde henüz bie email oluşturulmadığını görüntülemek için S3 servisi üzerinden bu bucket içindeki info klasörünü kontrol ediyoruz.

Daha öncesinde güncellenmiş iletişim formu sayfamızı www.cloudlyze.com/contact.html sayfası üzerinden formumuzu test bilgileri ile doldurarak “Send Message” buttonu üzerinden API Gateway servisinin endpointini kullanarak gönderiyoruz.

SNS topic üzeren subscription olarak verdiğimiz telefon numarasına SMS bildiriminin geldiğini aşağıdaki resim üzerinden kontrol edebilmekteyiz. Burada 2 lambda fonksiyonuda başarılı şekilde çalışıyor. Önce send-mail fonksiyonu ile emaili oluşturuyor ve S3 üzerinde bu mail arşivleniyor. Bu S3 üzerinde bir objenin oluşturması ile ikinci fonksiyonunun tetiklenmesi sağlanıyor ve SMS bildirimi geliyor.

Artık cloudlyze.com-email S3 bucket üzerinde ilgili emailin oluşturulduğunu görüntülemek için S3 servisi üzerinden bu bucket içindeki info klasörünü kontrol ediyoruz. Oluşan email’i “Actions” içinden “Download as” diyerek lokal makinamıza indiriyoruz. Bu indirme işleminden sonra mailin içeriğini görüntülemek adına indirilen maili .eml formatında isimlendirmemiz gerekmektedir

Mailin içeriğini açtığımızda iletişim formu üzerinden gönderdiğimiz test bilgilerinin info@cloudlyze.com mail adresine konu başlığı ve mesajı içerecek şekilde emaili oluşturulduğunu görebilmekteyiz.

SONUÇ

Uzun süren bir konfigurasyon ve entegrasyon sürecinden sonra AWS üzerinde serverless bir mimari tasarımı gerçekleştirmiş ve web sayfamız üzerine entegre etmiş bulunmaktayız. Umarım faydalı bir yazı olmuştur. Bir dahaki yazıda görüşmek dileği ile.

Referanslar

--

--

Serkan Bingöl
Cloud Türkiye

Muzur bir oğlan babası, hayvan sever, Harry Potter hayranı, bazen maceracı düz yazılımcı.