เข้าใจความเสี่ยงของ policy สอบถามเรื่อง policy ได้ด้วยภาษาทั่วไป ขอชมการสาธิต →

Published:

ความซับซ้อนเกินจำเป็นของการทำงานร่วมกันระหว่าง CloudTrail และ CloudWatch Events

by FireMon

หนึ่งในเรื่องที่น่าปวดหัวที่สุดตลอดเส้นทางการทำงานบนคลาวด์ของผมคือการทำความเข้าใจว่า CloudTrail กับ CloudWatch Events ทำงานร่วมกันอย่างไร ด้วยเหตุผลบางอย่าง ผมใช้เวลาหลายปี (และการทดสอบจำนวนมาก) กว่าจะเข้าใจว่าการเชื่อมต่อนี้ทำงานอย่างไรจริง ๆ โดยเฉพาะเมื่อเกี่ยวข้องกับแนวคิด multi-region และ AWS Organization trail และเมื่อเข้าใจทั้งหมดแล้ว ผมก็คิดไปเองว่าทุกคนรู้อยู่แล้ว แต่จากการพูดคุยช่วงหลังมานี้ชัดเจนว่าความสับสนเรื่องนี้เกิดขึ้นบ่อยมาก นี่จึงเป็นความพยายามอย่างเต็มที่ของผมในการทำให้เรื่องนี้เข้าใจง่ายขึ้น

เริ่มจากโจทย์ที่เราต้องการแก้: สร้าง CloudWatch Rules จาก CloudTrail Events แล้วใช้ส่งการแจ้งเตือนหรือทริกเกอร์ Lambda function

เท่านั้นเอง - ผมแค่ต้องการส่งการแจ้งเตือนสำหรับเรื่องง่าย ๆ อย่างการเรียก API เพื่อเปิด security group rule ใหม่ (AuthorizeSecurityGroupIngress หากคุณสงสัย)

สิ่งที่ต้องมีเพื่อให้ทำงานได้มีดังนี้:

  • เปิดใช้งาน CloudTrail ใน region ที่มีการเรียก API
  • CloudTrail ส่งสตรีมข้อมูลไปยัง CloudWatch
  • CloudWatch Rule ใน region ที่มีการเรียก API ซึ่งคอยตรวจจับการเรียก API นั้นโดยเฉพาะ หรือการเรียก API ทั้งหมดของ CloudTrail

ทีนี้มาถึงจุดที่ทำให้สับสน:

  • เมื่อคุณสร้าง CloudTrail แบบ multi-region หรือ Organization trail เบื้องหลังนั้น AWS กำลังสร้าง trail ขึ้นในทุก ๆ region (และทุกบัญชี ในกรณีของ Org trail) ทั้งหมดนี้เป็น trail แยกจากกัน แต่แต่ละตัวถูกตั้งค่าให้ส่งผลลัพธ์ไปยัง S3 bucket ที่ใช้ร่วมกัน และคุณจัดการแต่ละตัวได้เฉพาะในบัญชีและ region ต้นทางของมันเท่านั้น
  • อย่างไรก็ตาม CloudWatch events สำหรับการเรียก API นั้นถูกสร้างขึ้นเฉพาะใน region ที่มีการเรียก API เท่านั้น
  • ดังนั้น หากคุณสร้าง trail แบบ multi-region ข้อมูลจะถูกรวบรวมไว้ที่ส่วนกลางทั้งหมด แต่ event จะปรากฏเฉพาะในระดับ region นั้น ๆ CloudWatch Rule ใน region ของ trail หลักจะทริกเกอร์เฉพาะการเรียก API ที่เกิดขึ้นใน region นั้น (region หลัก) เท่านั้น ดังนั้นหากคุณสร้างการแจ้งเตือนสำหรับการเปลี่ยนแปลง security group มันจะทำงานเฉพาะใน region หลักเท่านั้น ไม่ใช่ใน region อื่น ๆ แม้ว่า CloudTrail จะเปิดใช้งานอยู่ก็ตาม
  • CloudWatch Log Group/Stream จะปรากฏใน region หลัก ไม่ใช่ใน region อื่น ๆ แต่ Event แต่ละรายการจะถูกสร้างขึ้นใน region ที่ทริกเกอร์ event นั้น
  • หากคุณต้องการเก็บรวบรวม event ทั้งหมดของการเรียก API คุณต้องใช้นิยาม event ที่ไม่มีอยู่ในเอกสาร (ซึ่งผมวางไว้ด้านล่างนี้)
  • หากคุณอ่านเอกสารของ Amazon... พวกเขาไม่เคยอธิบายเรื่องเหล่านี้ไว้อย่างชัดเจน อย่างน้อยก็เท่าที่ผมหาเจอ อันที่จริง ครั้งหนึ่งผมเคยอยู่ในสายซัพพอร์ตตอนที่ผมหาคำตอบได้ และตัวแทนของ AWS ก็พึมพำอยู่เรื่อยว่า "ผมไม่คิดว่ามันทำงานแบบนั้นนะ" ขณะที่ event ของผมเริ่มไหลเข้ามา คืนนั้นคงเป็นคืนที่หนักหนาสำหรับเขา

ด้วยเหตุผลบางอย่าง เรื่องนี้ขัดกับสัญชาตญาณของผมมาก ผมเคยคิดว่าถ้ารวมศูนย์ trail ไว้แล้ว ก็น่าจะรวมศูนย์ CloudWatch Rule เพื่อทริกเกอร์จาก event ของการเรียก API ได้ด้วย แต่น่าเสียดายที่เข้าใจผิดสิ้นเชิง แม้จะรวมศูนย์ trail แล้ว คุณก็ยังต้องสร้าง Rule ในทุก region ที่คุณสนใจอยู่ดี แม้ว่าคุณจะใช้ Event Bus เพื่อรวบรวม event จากหลายบัญชี คุณก็ยังคงต้องสร้าง CloudWatch Rule ในทุก region ของทุกบัญชีเพื่อส่ง event เข้าสู่ Bus และจากนั้นต้องสร้าง Rule ในทุก region ของ Event Bus เพื่อทริกเกอร์การแจ้งเตือนหรือการดำเนินการที่คุณต้องการ

หากคุณต้องการความสามารถในการแจ้งเตือนแบบเกือบเรียลไทม์ หรือการทำ auto-remediation/การดำเนินการอัตโนมัติที่ CloudWatch Rules รองรับ นี่คือแนวทางที่ผมแนะนำ:

  • เปิดใช้งาน trail แบบ multi-region คุณทำเพียงครั้งเดียวก็พอ และ Organization trail ก็เพียงพอแล้ว
  • วิธีนี้จะสร้าง trail ระดับ region ทั้งหมดที่คุณต้องการ ดูเผิน ๆ เหมือนเป็น trail เดียวที่ส่วนกลาง แต่จริง ๆ แล้วคือกลุ่มของ trail ระดับ region ที่ส่งข้อมูลไปยังปลายทางส่วนกลาง
  • ทางเลือกที่ 1: สร้าง CloudWatch Rule ในทุก region ที่คุณต้องการการแจ้งเตือนแบบเกือบเรียลไทม์ CloudFormation และ Terraform จะช่วยคุณได้มากในจุดนี้
  • ทางเลือกที่ 2: รวมศูนย์ event ทั้งหมดของคุณ โดยสร้าง Rule ในแต่ละ region เพื่อส่ง CloudTrail event ทั้งหมดไปยัง Lambda function หรือ SNS topic ซึ่งจะส่งต่อไปยังปลายทางของคุณอีกที เราใช้วิธีนี้เองเช่นกัน โดยส่งผ่าน API endpoint ที่สร้างขึ้นเอง แต่คุณจะสตรีมไปยัง Kinesis หรือเกือบทุกปลายทางก็ได้

เพื่อให้คุณเริ่มต้นได้เร็วขึ้น นี่คือตัวอย่างโค้ดสองชุด

filter pattern ลับสำหรับ CloudWatch Rule ของคุณ เพื่อเก็บรวบรวม event ทั้งหมดจาก CloudTrail:

{

"detail-type": [

"AWS API Call via CloudTrail"

] }

และนี่คือตัวอย่างโค้ด Lambda สำหรับส่งต่อ event ซึ่งในกรณีนี้คือส่งไปยัง Kinesis:

import json

import boto3

def lambda_handler(event, context):

kinesis = boto3.client('kinesis', region_name='us-west-2')

data = json.dumps(event)

print(data)

response = kinesis.put_record(

StreamName='cloudsec_prod_stream_alert_kinesis',

Data=data,

PartitionKey='test-client-id'

)

print(response)

return {

'statusCode': 200,

'body': json.dumps('Record added')

}

CloudTrail และ CloudWatch ทำงานร่วมกันอย่างไร | FireMon