Aws KMS 101

aws
kms
cryptography

(Mürüvet) #1

Merhaba, bu yazımda önemli konulardan biri olan bilgi ve veri güvenliğini sağlamak amacı ile kullanılan AWS KMS hizmetinden bahsediyor olacağım. Bu hizmeti nasıl kullanacağımız ve ufak scriptler ile işlemlerimizi kolaylaştırabileceğimizi göstermeyi hedeflemekteyim. Artık blog yazıma geçebiliriz :slight_smile:

`AWS KMS Hizmeti Nedir ve Ne İşe Yarar

Herkesin bildiği üzere verileriniz nerede depolanıyor olursa olsun, bilgi güvenliği her zaman büyük önem taşımaktadır. Bu doğrultuda şifrelemenin herhangi bir veri koruma stratejisinin temel unsurlarından biri olduğunu unutmamalıyız. AWS de bu doğrultuda müşterilerine iyi bir hizmet sunabilmek için AWS KMS (Key Management Service) hizmetini geliştirmiştir. KMS verilerinizi şifrelemek için kullanılan şifreleme key’lerinizi oluşturmanızı ve kontrol etmenizi kolaylaştıran bir hizmettir. AWS KMS’de oluşturduğunuz master key’ler FIPS 140-2 onaylı kriptografik modüller tarafından korunur.

AWS KMS’yi kullanarak, şifrelediğiniz verilere erişim sürecinde daha fazla kontrol sahibi olursunuz. Uygulamalarınızda ve ya AWS üzerinde kullandığınız AWS hizmetleri ile doğrudan entegre edebilirsiniz. Ayrıca master keylerinizi kimlerin kullanabileceği ve şifrelenmiş verilerinize kimlerin erişim sağlayacağı konularını kolaylıkla yönetebilirsiniz.

AWS KMS, verilerinizi master key’leriniz ile şifreleyip kullanabileceğiniz birçok AWS hizmeti ile entegre edilmiştir. Ayrıca denetim, düzenleme ve uyumluluk gereksinimlerinizi karşılamaya yardımcı olmak için master key log dosyalarını belirlediğiniz bir Amazon S3 bucket’ında saklayan bir hizmet olan AWS CloudTrail ile entegre edilmiştir. CloudTrail’i kullanarak master key’lerinizin nasıl ve ne zaman kullanıldığını ve kimler tarafından kullanıldığını izleyebilir ve inceleyebilirsiniz.

AWS KMS master key’lerinizde aşağıdaki yönetimleri gerçekleştirebilirsiniz:

  • Master key’lerinizi oluşturma, açıklama ekleme ve listeleme
  • Master key’lerinizi etkinleştirme ve istenildiğinde devre dışı bırakma
  • Master key’leriniz için yetkiler oluşturma, yetkileri ve kontrol yönetimini listeleme
  • Master key’lerinizin kriptografik özelliklerini otomatik rotasyon ile etkinleştirme ve devre dışı bırakma
  • Kriptografik özelliklerini AWS KMS master key’lerinize aktarma
  • Master key’lerinizi tag ile tanımlama, kategorilere ayırma ve takip etmek gibi işlemleri kolaylaştırma
  • Master key’leriniz ile ilişkilendirilmiş takma isimler oluşturma, silme, listeleme ve güncelleme
  • İstenilen Master key’in geçerliliğini yitirmesi için key’inizi silme

AWS KMS ile master key’lerinizi kullanarak aşağıdaki şifreleme işlevlerini de gerçekleştirebilirsiniz:

  • Verileri şifreleyebilir, şifresini çözebilir ve yeniden şifrelebilirsiniz
  • Verilerinizi plain text veya encrypted bir şekilde bir master key ile dışa aktarabilirsiniz
  • Kriptografik uygulamalar için uygun rastgele sayılar üretebilirsiniz.
    Aşağıdaki diyagram AWS KMS’nin temel şifreleme mantığını göstermektedir. Şifreleme komutu, master key kullanarak düz metinleri şifreli metin içine şifreler.

kms-01

Customer Master Key (CMK) Oluşturma - (AWS Console)

AWS KMS hakkında bilgi sahibi olduktan sonra bir CMK oluşturarak işlemlerimize devam edebiliriz. CMK oluşturmak için aşağıdaki adımları ve görselleri takip etmeniz yeterli olacaktır.

AWS IAM sayfasında sol menü’de ‘Encryption keys’ sekmesi seçilir.

kms-02

Açılan servis başlangıç penceresinde ‘Get Started Now’ butonuna tıklanarak AWS KMS hizmetini kullanmaya başlayabiliriz.
İstenilen region seçimi yapıldıktan sonra ‘Create Key’ butonuna tıklanır.

Açılan sayfada CKM’imiz için bir alias tanımlamamız zorunludur. İsteğe göre CKM’in kullanım amacına göre bir açıklamada yazılabilir.

Not: alias aws ile başlayamaz, aws ile başlayan alias’lar AWS tarafından yönetilen CMK’leri temsil etmek için Amazon Web Services tarafından kullanılmak üzere ayrılmıştır.

Bu bölümde CMK’yı tanımalamanıza yardımcı olacak tag’ler ekleyebilirsiniz. Ben herhangi bir tag eklemeden Next Step diyerek devam ediyorum.

Aşağıdaki adımda ise hangi IAM kullanıcılarının ve rollerin CMK’yi yönetebileceğini seçmeniz isteniyor.

Hangi IAM kullanıcıların AWS KMS API’sı ile verileri şifrelemek ve şifresini çözmek için CMK’yı kullanabileceğini seçebilrisiniz.

Not: AWS account root user varsayılan olarak tam izinlere sahiptir.

Son olarak master key policy’sini gözden geçirdikten sonra ‘Finish’ butonuna tıklayabilirsiniz.

Encryption key listesinde oluşturduğunuz CMK’ı görebilirsiniz.

Customer Master Key Oluşturma (CMK) - (AWS CLI)

Şimdi de AWS CLI ile CMK oluşturacağız. Siz AWS Console ile key oluşturmak istiyorsanız yukarıdaki adımı takip edebilirsiniz yada AWS Console ile CMK oluşturuysanız bu adımı atlayabilirsiniz.

Not: Aşağıdaki adımları takip edebilmek için AWS KMS hizmeti için gerekli yetkilere sahip bir kullanıcı veya rolünüzün mevcut olması ve credential’larının aws credentials dosyasında yazıyor olması gereklidir.

İlk olarak daha önce oluşturulan CMK ları listelemek amaçlı aşağıdaki aws cli komutu çalıştırılabilir. Sonucunda daha önce oluşturulan CMK’(ları)nız var ise key id ve arn bilgilerini sırası ile verecektir.

$ aws kms list-keys
{
	"Keys": [
   	{
       	"KeyId": "1x2x3xx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
       	"KeyArn": "arn:aws:kms:eu-west-1:123456789123:key/1x2x3xx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
   	}
	]
}

Herhangi bir CMK’nız yok ise aşağıdaki komut ile hızlıca bir CMK yaratabilirsiniz.

$ aws kms create-key
{
	"KeyMetadata": {
   	"Arn": "arn:aws:kms:eu-xxxx-1:123456789123:key/a6cacxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
   	"KeyUsage": "ENCRYPT_DECRYPT",
   	"KeyState": "Enabled",
   	"AWSAccountId": "123456789123",
   	"Origin": "AWS_KMS",
   	"Description": "",
   	"CreationDate": 1527979644.994,
   	"KeyId": "a6cacxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
   	"Enabled": true,
   	"KeyManager": "CUSTOMER"
	}
}

Oluşturduğumuz CMK’ya herhangi bir alias eklemek istersek aşağıdaki komutu kullanabiliriz. target-key-id yerine yukarıda oluşan CMK’nın id sini ve alias-name alias/xxx yerine eklemek istediğimiz alias’ı yazmamız yeterli olacaktır.

$ aws kms create-alias \
 --alias-name 'alias/muslu-blog' \
 --target-key-id 'a6cacfd2-fe9d-4f49-817a-ba0c31f7c563'

AWS KMS te CMK create etme işlemini bitirdiğimize göre artık bu cmk’yı kullanmaya başlayabiliriz. Öncelikle aws cli üzerinde encrypt ve decrypt işlemlerine ufaktan değindikten sonra küçük bir python script’i ile beraber olacağız.

Not: AWS cli üzerinde oluşturulan cmk’ların key policy’si default policy’dir. Gerektiğinde bu polic’i aws kms put-key-policy komutu yardımı ile yada AWS Console’dan değiştirebilirsiniz.

Encrypt Decrypt - AWS CLI

Aşağıdaki komut ile encrypt işlemimizi gerçekleştirebiliriz. fileb://muslu.txt şeklinde file name verebileceğimiz gibi bir sonraki komutta gördüğünüz üzere açık data şeklinde de işlemimizi yapabiliriz. İşlem sonucunda oluşan encrypted data’yı muslu.key adına bir dosyaya atmaktayım. Sizler komutları kullanacağınız zaman --key-id --plaintext ve ve sonunda yer alan çıktının yazılacağı dosya ismini değiştirmelisiniz.

$ aws kms encrypt --key-id 1x2x3xxx-xxxx-xxxx-xxxx-xxxxxxxxxxx --plaintext fileb://muslu.txt --output text --query CiphertextBlob | base64 -d > muslu.key
$ aws kms encrypt --key-id 1x2x3xxx-xxxx-xxxx-xxxx-xxxxxxxxxxx --plaintext "plain text blabla" --output text --query CiphertextBlob | base64 -d > muslu.key

Decrypt işleminde ise komutu çalıştırdığınız kullanıcının encrypt edilen AWS KMS’i kullanma yetkisi olacağı için herhangi bir key id vermeden işlemimizi aşağıdaki komut ile gerçekleştirebiliyoruz. Bu komut içerisinde daha önce encrypt ettiğimiz verinin encrypted değerini sakladığımız muslu.key dosyasını --ciphertext-blob olarak vererek, verinin decrypted değerini muslu.txt içerisine yazdırıyorum. Sizler istenilen parametreleri değiştirerek işlemlerinize devam edebilirsiniz.

$ aws kms decrypt --ciphertext-blob fileb://muslu.key --output text --query Plaintext | base64 -d > muslu.txt

Python Scripts

Şimdi ise Python da yazmış olduğum encrypt ve decrypt scriptlerini sizlerle paylaşacağım.

#!/usr/local/bin/python3

import boto3
import base64

def get_kms_key(kmsAlias=None):

   kms_client = boto3.client('kms')
   aliases = kms_client.list_aliases()
   key = [ key['TargetKeyId'] for key in aliases['Aliases'] if key['AliasName'] == kmsAlias ][0]

   return key

def encrypt_data(data=None,kmsAlias=None):
   
   data = data.encode()

   kms_client = boto3.client('kms')
   kms_key = get_kms_key(kmsAlias)

   response = kms_client.encrypt(
  		 KeyId=kms_key,
  		 Plaintext=data,
  	 )

   encrypted_text = base64.b64encode(response['CiphertextBlob'])

   return encrypted_text

def s3_upload(data=None,bucket_name=None,file_path=None):

   s3 = boto3.client('s3')

   #with open('muslu', 'rb') uas data:
   response = s3.put_object(
   Bucket=bucket_name,
   Body=data,
   Key=file_path)

   #s3.upload_fileobj(data, 'muslu-bucket', 'mykey')

def main():

   data = input("data : ")
   kms_key_alias = input("kms key alias : ")
   kms_key_alias = "alias/"+kms_key_alias
   s3_bucket_name = input("s3 Bucket Name : ")
   s3_file_path = input("s3 File Path : ")

   encrypted_data = encrypt_data(data,kms_key_alias)
   s3_upload(encrypted_data,s3_bucket_name,s3_file_path)

   print ("Plain text data: {0}".format(data))
   print ("encrypted data: {0}".format(encrypted_data))
   
   print ("Encrypt file uploaded to s3://{0}/{1}".format(s3_bucket_name,s3_file_path))

if __name__ == "__main__":

   main()

Scripti çalıştırdığınızda aşağıdaki gibi istenilen veriler olduğunu görebilirsiniz. Script kısaca girilen data’yı belirtilen kms key ile şifreleyerek istenilen s3 bucket’a istenilen dosya path’i ile upload etmektedir. Girdiğiniz s3 path’inde bulunan dosyayı indirip içeriğine baktığınızda encrypted data yer aldığını göreceksiniz.

Bu sayede bizler istediğimiz verilerimizi AWS s3 bucket’ta şifrelenmiş bir şekilde saklıyor olacağız.

$ python3 python-encrypt.py
data : encrypting by muslu
kms key alias : muslu
s3 Bucket Name : muslu-bucket
s3 File Path : test/mirivix.key
Plain text data: encrypting by muslu
encrypted data: b'AQICAHg8GuingIZn7u1rJHLYeibN938gAKhDhqXcBS9Wi1h2kgHEHzqHa7ZMFTiSod8CcDaeAAAAcTBvBgkqhkiG9w0BBwagYjBgAgEAMFsGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMfmMle6Pqgt6zet/sAgEQgC6VDiWhbJ7jXPxDkEfy3dhbmGkGVUNBRK8OmmdIlSn+sBlfd86twyx1npzjHXvX'
Encrypt file uploaded to s3://muslu-bucket/test/mirivix.key

Bu verilere örneğin bir EC2 içerisinden erişmemiz gerekirse. Oluşturduğumuz CMK ve s3 için gerekli erişimleri sağlayacağımız aşağıdaki policy’leri oluşturarak, EC2’ya vereceğimiz instance role’e bu policyleri attach etmemiz yeterli olacaktır. Aşağıdaki role’ler ile instance erişimi sağlandıktan sonra python decrypt scriptimize geçebiliriz.

# KMS decrypt işlemi için gerekli olan policy aşağıda json olarak tanımlanmıştır.
{
	"Version": "2012-10-17",
	"Statement": [
   	{
       	"Effect": "Allow",
       	"Action": [
           	"kms:ListKeys",
           	"kms:Decrypt",
           	"kms:ListAliases"
       	],
       	"Resource": "*"
   	}
	]
}

# S3 erişimi için gerekli olan policy’i aşağıdaki gibi tanımlayabilirsiniz. Bucket ismini değşitirmeniz yeterli olacaktır.
{
	"Version": "2012-10-17",
	"Statement": [
   	{
       	"Effect": "Allow",
       	"Action": [
           	"s3:getObject",
           	"s3:ListBucket"
       	],
       	"Resource": [
           	"arn:aws:s3:::muslu-bucket",
           	"arn:aws:s3:::muslu-bucket/*"
       	]
   	},
   	{
       	"Effect": "Allow",
       	"Action": "s3:ListAllMyBuckets",
       	"Resource": "arn:aws:s3:::*"
   	}
	]
}

Decrypt scriptimizin içeriğide aşağıdaki gibidir.

#!/usr/local/bin/python3

import boto3
import base64

def get_body_s3file(bucket_name=None,file_path=None):
   s3 = boto3.resource('s3')
   obj = s3.Object(bucket_name, file_path)
   data = obj.get()['Body'].read().decode('utf-8')
   return decrypt_data(data)

def decrypt_data(data=None):

	data = base64.b64decode(data)

	kms_client = boto3.client('kms')

	response = kms_client.decrypt(
       	CiphertextBlob=data,
   	)

	decrypted_text = response['Plaintext']

	return decrypted_text

def main():

   s3_bucket_name = input("s3 Bucket Name : ")
   s3_file_path = input("s3 File Path : ")
   plain_text= get_body_s3file(s3_bucket_name,s3_file_path)
   
   print("palin text= {0}".format(plain_text))

if __name__ == "__main__":

	main()

Decrypt scriptimizi ec2 içerisinde aşağıdaki gibi çalıştırdığımızda ve istenilen verileri input olarak verdiğimizde daha önce encrypt edilmiş plain text veriye erişildiği gözlemlenecektir.

# python3 python-decrypt-.py
s3 Bucket Name : muslu-bucket
s3 File Path : test/mirivix.key
palin text= b'encrypting by muslu'

Ben bu postta EC2 içerisinde decrypt etme işlemini Python ile tamamen örnek olarak verdim. Sizler başka işlemler için AWS KMS i kullanarak istediğiniz programlama dilinde scriptleriniz ile çok farklı amaçlar için kullanabilirsiniz.