Encrypt dan Log EC2 Session

tl;dr Cara mengenkripsi dan log EC2 session menggunakan AWS Key Management Service (KMS) dan Amazon CloudWatch Logs.

Salah satu metode untuk terhubung atau akses EC2 instance yang ada di Amazon Web Services (AWS) adalah menggunakan Session Manager. Session Manager memungkinkan kita untuk melakukan remote akses ke EC2 instance tanpa melakukan SSH. Jika tertarik mengetahui lebih detail terkait Session Manager, dapat mengunjungi blog saya yang lain yaitu AWS Session Manager, Alternatif Untuk Akses Amazon EC2 Instance.

Pada blog kali ini, saya akan mencoba mendiskusikan cara mengenkripsi sesi session manager ke EC2 instance kemudian mengirimkan log sesi tersebut. Untuk enkripsi session manager akan dibantu oleh service AWS Key Management Service (KMS) dan log sesi akan disimpan ke CloudWatch Logs. KMS dan CloudWatch Logs akan dibuat/provision menggunakan Terraform dengan backend remote (Terrafom Cloud). Dan untuk konfigurasi encryption dan log session di Session Manager akan dikonfigurasi via AWS Web Console karena pada saat blog ini ditulis, Terraform AWS Provider belum mendukung provision konfigurasi tersebut. Jika digambarkan topologi pada artikel ini sebagai berikut.

topologi

Konfigurasi

Pada artikel ini, struktur file yang digunakan oleh terraform code sebagai berikut:

cloudwatch/
├─ cloudwatch-apse1/
│  ├─ data.tf
│  ├─ logs.tf
│  ├─ main.tf
│  ├─ variables.tf
kms/
├─ kms-apse1/
│  ├─ json-policies/
│  │  ├─ ec2-session.json
│  ├─ kms.tf
│  ├─ main.tf
│  ├─ outputs.tf
│  ├─ variables.tf

Directory cloudwatch dan kms akan menjadi workspace terpisah di Terraform Cloud.

  1. Sebagai langkah awal, saya akan mulai dengan membuat file-file di dalam directory kms/kms-apse1. Dimulai dengan file kms/kms-apse1/main.tf. Di file ini saya akan mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait. Di akhir saya deklarasikan region aws yang digunakan, mengacu ke variable aws_region yang ada di file variables.tf yang berikutnya akan saya jelaskan.

kms-main

# Setup terraform cloud and workspace
terraform {
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "lanandra"

    workspaces {
      name = "kms-ap-southeast-1"
    }
  }
}

# Setup terraform providers
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.14.0"
    }
  }

  required_version = ">= 1.1.9"
}

# Setup AWS provider
provider "aws" {
  region = var.aws_region
}
  1. Langkah berikutnya yaitu dengan membuat variable di file kms/kms-apse1/variables.tf. Di file ini saya deklarasikan beberapa variable seperti aws_region dan default_deletion_days.

kms-variables

# Setup AWS Region
variable "aws_region" {
  type        = string
  description = "AWS Region"
  default     = "ap-southeast-1"
}

variable "default_deletion_days" {
  type        = string
  description = "Default pending deletion days"
  default     = "7"
}
  1. Selanjutnya saya akan mendeklarasikan policy yang digunakan oleh KMS key yang akan saya gunakan nantinya. Karena key ini akan memerlukan custom policy terkait service dan user apa yang dapat menggunakan. Policy ini saya deklarasikan di dalam file kms/kms-apse1/json-policies/ec2-session.json. Pada policy ini saya akan mendefinisikan key administrators dan memberikan akses penggunakan untuk iam role, user dan cloudwatch logs
{
    "Version": "2012-10-17",
    "Id": "ec2-session-policy",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::aws-account-id:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::aws-account-id:user/luthfi"
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aws-account-id:role/ec2-admin",
                    "arn:aws:iam::aws-account-id:user/luthfi"
                ]
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key for cloudwatch logs",
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-southeast-1.amazonaws.com"
            },
            "Action": [
                "kms:Encrypt*",
                "kms:Decrypt*",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:Describe*"
            ],
            "Resource": "*",
            "Condition": {
                "ArnEquals": {
                    "kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:ap-southeast-1:aws-account-id:*"
                }
            }
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aws-account-id:role/ec2-admin",
                    "arn:aws:iam::aws-account-id:user/luthfi"
                ]
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}
  1. Berikutnya di file kms/kms-apse1/kms.tf, saya deklarasikan konfigurasi kms key dengan nama ec2-session dengan referensi policy seperti disebutkan di poin nomor 3 dan juga default deletion days mengikuti default dari variable yang sudah didefinisikan. Saya juga memberikan alias untuk key tersebut.

kms-kms

# Section for KMS key
resource "aws_kms_key" "ec2_session" {
  description             = "Key for EC2 session"
  deletion_window_in_days = var.default_deletion_days

  policy = file("./json-policies/ec2-session.json")

  tags = {
    Name  = "ec2-session"
    Owner = "Luthfi"
  }
}

# Section for KMS key alias
resource "aws_kms_alias" "ec2_session" {
  name          = "alias/ec2-session"
  target_key_id = aws_kms_key.ec2_session.key_id
}
  1. Berikutnya saya definisikan outputs dari resource yang ada di workspace kms pada file kms/kms-apse1-outputs.tf. Di file ini saya mendeklarasikan output arn key ec2-session.

kms-outputs

# Set outputs
output "ec2_session_key" {
  value = aws_kms_key.ec2_session.arn
}
  1. Berikutnya adalah melakukan commit dan push terraform code ke repository. Dan lakukan terraform plan dan terraform apply di Terraform Cloud workspace agar infrastructure dapat dibuat/provisioned. Untuk bagian ini hanya saya tampilkan simulasinya saja. Jika ingin melihat lebih detail bagaimana proses provisioning resource AWS via Terraform Cloud, silahkan lihat blogpost saya berikut ini. Pertama-tama, saya menjalankan terraform plan dan apply di workspace kms.

tfc-plan-apply

  1. Setelah resource kms berhasil dibuat oleh terraform selanjutnya kita akan masuk ke konfigurasi cloudwatch logs. Konfigurasi akan berfokus pada file file yang ada di dalam directory cloudwatch/cloudwatch-apse1. Sama seperti di directory kms, di directory cloudwatch terdapat main file cloudwatch/cloudwatch-apse1/main.tf yang digunakan untuk mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait. Beserta deklarasi region aws yang digunakan, mengacu ke variable aws_region yang ada di file variables.tf.

cloudwatch-main

# Setup terraform cloud and workspace
terraform {
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "lanandra"

    workspaces {
      name = "cloudwatch-ap-southeast-1"
    }
  }
}

# Setup terraform providers
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.14.0"
    }
  }

  required_version = ">= 1.1.9"
}

# Setup AWS provider
provider "aws" {
  region = var.aws_region
}

  1. Berikutnya deklarasi variables di file cloudwatch/cloudwatch-apse1/variables.tf.

cloudwatch-variables

# Setup AWS Region
variable "aws_region" {
  type        = string
  description = "AWS Region"
  default     = "ap-southeast-1"
}
  1. Resource di workspace cloudwatch memerlukan referensi data yang berupa remote state dari workspace kms, maka saya deklarasikan referensi data tersebut pada file cloudwatch/cloudwatch-apse1/data.tf.

cloudwatch-data

# Get terraform state from other workspaces
data "terraform_remote_state" "kms_ap_southeast_1" {
  backend = "remote"

  config = {
    organization = "lanandra"
    workspaces = {
      name = "kms-ap-southeast-1"
    }
  }
}
  1. Selanjutnya pada file cloudwatch/cloudwatch-apse1/logs.tf, saya deklarasikan konfigurasi untuk membuat cloudwatch log group dengan nama ec2-session-logs. Data dalam log group ini saya atur agar memiliki retensi 14 hari dan terenkripsi menggunakan kms key ec2-session yang sudah kita buat sebelumnya.

cloudwatch-logs

# Create cloudwatch logs group
resource "aws_cloudwatch_log_group" "ec2_session_logs" {
  name              = "ec2-session-logs"
  retention_in_days = "14"
  kms_key_id        = data.terraform_remote_state.kms_ap_southeast_1.outputs.ec2_session_key

  tags = {
    Name  = "ec2-session-logs"
    Owner = "Luthfi"
  }
}
  1. Langkah berikutnya adalah melakukan push dan commit ke repository. Kemudian melakukan terraform plan dan apply di workspace cloudwatch seperti yang sudah dilakukan di poin nomor 6.

  2. Setelah provisioning resource via terraform sudah selesai. Langkah selanjutnya adalah memastikan resource-resource berhasil terbentuk. Kita dapat menggunakan AWS web console untuk memastikannya. Resource pertama yang akan kita verifikasi adalah kms key. Masuk ke halaman service KMS, kemudian masuk ke menu Customer managed keys. Pastikan kms key dengan nama yang didefinisikan di terraform code berhasil terbentuk.

verify-kms-key

  1. Kita juga dapat memastikan detail dari kms key tersebut. Dan selanjutnya pastikan konfigurasi sudah sesuai dengan yang didefinisikan di terraform code, seperti key policy.

kms-key-details

  1. Selanjutnya adalah memastikan resource cloudwatch logs. Masuk ke halaman service CloudWatch. Masuk ke menu Logs > Log groups. Pastikan log group dengan nama seperti yang didefinisikan di terraform code sudah berhasil terbentuk.

verify-cloudwatch-logs

  1. Selanjutnya kita dapat memastikan details dari log groups tersebut sudah sesuai dengan yang didefinisikan di terraform code.

cloudwatch-logs-details

  1. Langkah berikutnya adalah konfigurasi Session Manager preferences via Web Console. Masuk ke halaman service Systems Manager. Kemudian masuk ke menu Node Management > Session Manager. Masuk ke tab Preferences dan klik Edit

session-manager-preferences

  1. Selanjutnya di bagian KMS encryption pilih Enable KMS encryption. Kemudian pilih kms key ec2-session yang sudah dibuat sebelumnya.

session-manager-key

  1. Di bagian CloudWatch Logging, pilih Enable. Untuk logging options saya pilih stream session logs. Dan saya hanya mengizinkan encrypted log group yang kemudian saya pilih log group ec2-session-logs yang sudah dibuat sebelumnya.

session-manager-logs-1

session-manager-logs-2

  1. Langkah berikutnya adalah mencoba melakukan koneksi ke EC2 instance menggunakan session manager. Konfigurasi pembuatan EC2 tidak saya jelaskan lebih detail di artikel ini. Sesi koneksi session manager akan memberikan informasi bahwa sesi tersebut di-enkripsi menggunakan AWS KMS.

initite-ec2-session

  1. Selanjutnya mencoba mengirim atau mengeksekusi beberapa command di dalam EC2 instance tersebut.

send-commands-on-ec2

  1. Berikutnya adalah memastikan log berhasil terkirim ke CloudWatch Logs. Masuk ke log group ec2-session-logs yang sudah dibuat sebelumnya. Kemudian di tab Log streams, cari session id yang kita gunakan seperti tercantum di poin 19.

find-session-logs

  1. Verifikasi Log events yang ada di dalam log stream tersebut. Kita akan melihat log events dari perintah atau command yang tereksekusi di dalam EC2 instance kita.

verify-log-events

  1. Saya akan menampilkan contoh spesifik command yang sudah saya lakukan. Sebelumnya saya memasukkan perintah hostnamectl. Kita dapat memfilter command tersebut di log events dan dapat memastikan detail dari event tersebut.

log-event-detail

Kesimpulan

Akhirnya kita sampai di penghujung artikel ini. Ada beberapa kesimpulan atau key takeaways yang ingin saya sampaikan:

  • Sesi session manager ke EC2 instance dapat di-enkripsi dengan bantuan Key Management Service (KMS) dan mengirim log sesi ke CloudWatch Logs
  • Konfigurasi KMS dan CloudWatch Logs dapat dilakukan dengan pendekatan IaC. Sehingga kita memiliki state file dari infrastruktur yang sudah kita buat
  • Konfigurasi IaC dengan ClickOps via Web Console dapat dikombinasi seperti contoh di artikel ini. Misalkan provider terraform yang digunakan belum mendukung pembuatan resource via IaC.

Silahkan kunjungi GitHub repo saya untuk melihat source code konfigurasi yang digunakan dalam artikel ini. Silahkan cek folder kms untuk konfigurasi KMS dan cek folder cloudwatch untuk konfigurasi CloudWatch Logs

Sekian artikel kali ini. Jika ada saran, kritik, atau masukan silahkan tinggalkan di kolom komentar.

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s

Situs yang Didukung WordPress.com.

Atas ↑

%d blogger menyukai ini: