เข้าใจความเสี่ยงของ policy สอบถามเรื่อง policy ได้ด้วยภาษาทั่วไป ขอชมการสาธิต →
Published:
AWS Permission Boundaries ฉบับเข้าใจง่าย
by Mark Byers
AWS permission boundaries เป็นเรื่องที่ชวนสับสน ผมรู้ว่ามันชวนสับสนเพราะผมเองก็เคยสับสน และใช้เวลาอยู่สองปีกว่าจะเข้าใจมัน อีกเหตุผลที่ผมรู้ว่ามันชวนสับสนก็คือCorey Quinn ก็พูดไว้เช่นกัน และขอให้มีใครสักคนช่วยอธิบายให้เข้าใจง่ายขึ้น
AWS Copilot ซึ่งเป็น CLI สำหรับแอปพลิเคชันแบบคอนเทนเนอร์ เพิ่มการรองรับ IAM permission boundaries และอื่น ๆ - สักวันคงมีใครสักคนใช้คำง่าย ๆ อธิบายให้ผมฟังว่า IAM Permission Boundaries คืออะไร วันนี้จะใช่หรือเปล่า
ผมอาจจะอธิบายไม่สำเร็จ แต่ก็ขอลองดู
สรุปสั้น ๆ: IAM policy ทั่วไปใช้อนุญาตให้ทำสิ่งต่าง ๆ ได้ และสามารถห้ามไม่ให้ทำบางอย่างได้ด้วย ส่วน permission boundaries ทำได้อย่างเดียวคือห้ามไม่ให้ทำ โดยส่วนใหญ่จะใช้เพื่อให้ใครสักคนดูแลงาน IAM บางส่วนได้ แต่ไม่มากพอที่จะยกระดับสิทธิ์ (ให้ตัวเองหรือให้คนอื่น) มันคือกลไกป้องกันความผิดพลาด หากคุณให้ใครสักคนบริหารจัดการ IAM ในบัญชีหนึ่ง และไม่ต้องการให้เขายกระดับสิทธิ์ได้ เกือบทุกกรณีคุณจำเป็นต้องใช้ permission boundary
เอกสารอย่างเป็นทางการของ AWS ให้รายละเอียดไว้มาก แต่ก็ยังค่อนข้างชวนสับสนอยู่ดี บทความนี้มีเป้าหมายช่วยให้คุณเข้าใจแนวคิดและเหตุผลที่สิ่งนี้มีอยู่ ไม่ใช่เพื่อให้รู้รายละเอียดปลีกย่อยของการเขียน policy (ยกเว้นอยู่หนึ่งกรณี)
สมมติว่าผมเป็นเด็ก ป.5 ไม่ใช่คนไม่รู้เรื่อง ช่วยอธิบายอีกครั้งได้ไหม
ได้ ถ้ายืนยันขนาดนั้น
ก่อนจะมี IAM Permission Boundaries การให้ใครสักคนจัดการสิทธิ์ IAM สำหรับงานของตัวเองโดยไม่สร้างปัญหาด้านความปลอดภัยจากการให้สิทธิ์มากเกินไปแก่สิ่งต่าง ๆ เช่น EC2 instance หรือแม้แต่ตัวเขาเอง เป็นเรื่องที่ยากมาก ปัญหาส่วนใหญ่เกิดขึ้นเมื่อคุณต้องการให้เขาเขียน IAM policy แล้วนำไปกำหนดใช้เอง นี่คือปัญหาของการมอบหมายสิทธิ์การดูแลระบบ "ให้ใครสักคนดูแลบางเรื่องที่เกี่ยวกับ IAM ได้ แต่ไม่ใช่เรื่องเหล่านั้น"
นี่เป็นสถานการณ์ที่พบได้บ่อยมาก นักพัฒนามักสร้าง role สำหรับ instance, lambda function หรือ container task ใน application stack ของตน แล้วกำหนดสิทธิ์ให้ role นั้น อาจเป็นเรื่องง่าย ๆ อย่างการให้ instance อ่านข้อมูลจาก S3 bucket แต่ในมุมมองด้านความปลอดภัยแล้ว เรื่องนี้จัดการได้ยาก:
- หากคุณให้นักพัฒนาเขียน policy เอง เขาอาจเพิ่มสิทธิ์มากเกินความจำเป็น เช่น *.*
- หากคุณให้นักพัฒนากำหนด policy ได้ เขาอาจแนบ policy ที่มีอยู่แล้วซึ่งให้สิทธิ์มากเกินไป
- หากคุณอนุญาตให้นักพัฒนาสร้าง role ใหม่และกำหนด policy ได้ด้วย ก็เจอปัญหาเดิมทั้งหมด
แน่นอนว่าคุณอาจให้ทีมความปลอดภัยหรือผู้ดูแลระบบระดับสูงจัดการทั้งหมดนี้ แต่นั่นไม่มีประสิทธิภาพ permission boundaries ช่วยให้คุณมีผู้ดูแล IAM สองระดับ คือระดับสูงที่รับผิดชอบความปลอดภัยโดยรวม และระดับรองที่ดูแลงานประจำวัน
permission boundary ก็คือ IAM policy ที่ระบุสิทธิ์สูงสุดที่บุคคลหรือสิ่งหนึ่งจะมีได้ เมื่อคุณแนบ policy นั้นแล้ว นักพัฒนาที่ดูแลสิ่งนั้นจะไม่สามารถให้สิทธิ์เกินกว่าที่ boundary อนุญาตได้เลย จากนั้นคุณยังอนุญาตให้นักพัฒนาสร้าง role และ user ใหม่พร้อมกำหนดสิทธิ์ได้ด้วย โดยกำหนดเงื่อนไขว่าทุกสิ่งที่เขาสร้างต้องมี permission boundary นั้นติดอยู่ ดังนั้นเขาจะไม่มีทางสร้างหรือแก้ไขสิ่งใดให้มีสิทธิ์เกินกว่าที่คุณต้องการได้
ยังไม่แน่ใจว่าเด็ก ป.5 จะเข้าใจ ขอตัวอย่างหน่อยได้ไหม
Alice เป็นผู้ดูแลระบบสูงสุดของ AWS organization หนึ่ง เธอต้องกำกับดูแลบัญชีหลายร้อยบัญชี และแต่ละบัญชีมีผู้ดูแลระบบและนักพัฒนาของตัวเองที่ลงมือสร้างแอปพลิเคชันจริง ๆ
Bob เป็นหนึ่งในนักพัฒนาเหล่านั้น Bob กำลังสร้างแอปพลิเคชันใหม่ และการให้ Bob สร้าง role และ policy ของตัวเองย่อมมีประสิทธิภาพมากกว่า เพราะเขารู้ว่าแอปของเขาต้องการอะไร
Alice จึงตัดสินใจให้ Bob จัดการ IAM สำหรับบางส่วนของแอปพลิเคชันของเขา โดยเฉพาะ:
- Bob สามารถเขียนและกำหนด IAM policy ใหม่ที่มีสิทธิ์ตามที่ instance และ lambda function ของเขาต้องการได้
- มีบริการอื่นของ AWS ที่ใช้งานอยู่ซึ่งคอมโพเนนต์เหล่านั้นไม่ควรเข้าถึงเลย ดังนั้นคุณจะปิดการใช้งานด้วย Service Control Policy เฉย ๆ ไม่ได้ เพราะจะทำให้คอมโพเนนต์อื่นที่ได้รับอนุญาตใช้บริการเหล่านั้นไม่ได้ไปด้วย
- Bob ไม่ได้รับอนุญาตให้กำหนด policy ใหม่ให้กับตัวเอง
นี่คือกรณีคลาสสิกของการมอบหมายสิทธิ์การดูแลระบบ Bob ได้รับอนุญาตให้ดูแล IAM เพียงบางส่วนเท่านั้น และนี่คือจุดที่คุณจะใช้ permission boundary:
- Alice สร้าง permission boundary "A" ที่อนุญาตสิทธิ์สำหรับบริการ AWS ที่ instance และ lambda function ของ Bob สามารถติดต่อได้ (เช่น S3, SNS, SQS)
- Alice สร้าง permission boundary "B" ที่อนุญาตให้ Bob สร้าง IAM role และ policy (รวมถึงกำหนดใช้งาน) ได้ แต่ห้ามกำหนดให้กับตัวเอง
- Alice ให้สิทธิ์ IAM แก่ Bob ในการสร้างและกำหนด role และ policy ใหม่ แต่ role ใหม่ทุกตัวต้องมี permission boundary "A" นั่นหมายความว่า instance และ lambda function เหล่านั้นจะไม่มีวันมีสิทธิ์เกินกว่าที่ระบุใน boundary แต่มีน้อยกว่าได้
- Alice กำหนด permission boundary "B" ให้ Bob เพื่อไม่ให้เขากำหนดสิทธิ์ให้ตัวเองได้ ตอนนี้เขาจึงไม่สามารถยกเลิกข้อกำหนดที่ว่าทุกสิ่งที่เขา deploy ต้องมี "A" ติดอยู่
ใช่ มีหลายวิธีในการจัดการปัญหานี้ แต่สรุปสั้น ๆ คือ เมื่อใดก็ตามที่คุณต้องการให้ใครสักคนดูแล IAM บางส่วนในบัญชี คุณน่าจะต้องใช้ permission boundary หากไม่ต้องการให้เขาทำได้มากเกินไป
ช่วยอธิบายอีกครั้งว่าทำไม Service Control Policy ถึงใช้ไม่ได้ในกรณีนี้
บางครั้ง SCP ก็ใช้ได้ แต่คุณจะใช้ SCP ได้ก็ต่อเมื่ออยู่ใน Organization ขณะที่ permission boundary ใช้ได้กับทุกบัญชี นอกจากนี้ SCP เหมาะมากกับงานอย่างการจำกัดว่า API call ใดบ้างที่เรียกใช้ได้ (และจึงกำหนดว่าใช้บริการ AWS ใดได้บ้าง) แต่ไม่ได้ออกแบบมาสำหรับความละเอียดและเงื่อนไขในระดับนี้
ลองนึกถึงตัวอย่างข้างต้น Alice อาจต้องรู้ resource identifier เพื่ออนุญาตการเข้าถึงบริการต่าง ๆ ในบัญชี แต่ไม่อนุญาตจากทรัพยากรที่ Bob สร้างขึ้น มีวิธีจัดการเรื่องนี้อยู่บ้าง (เช่น resource path) แต่ก็ไม่ได้ง่ายกว่าตัวอย่าง permission boundary ของเรา และไม่ได้ใช้ได้เสมอไป ขึ้นอยู่กับ condition key ที่รองรับ
ใน Incident Response Training Range ของผม ผมใช้ SCP เพื่อจำกัดไม่ให้ผู้ใช้ระดับแอดมิน (ผู้เรียน) ในบัญชีเหล่านั้นทำลายสิทธิ์การเข้าถึงระดับ Organizations ของผมและอีกไม่กี่อย่าง แต่วิธีนี้ใช้ได้เพราะผมเปิดสิทธิ์ IAM เต็มรูปแบบให้พวกเขา และพวกเขาเป็นหนึ่งในซูเปอร์แอดมินอยู่แล้ว หากผมต้องการจำกัดความสามารถในการสร้างทรัพยากรที่มีสิทธิ์เกินจำเป็น ผมจะต้องใช้ permission boundary หรือ SCP เพื่อจำกัดให้พวกเขากำหนดได้เฉพาะ policy ที่สร้างไว้ล่วงหน้าเท่านั้น
ใช้ deny policy แทนไม่ได้หรือ
ไม่ได้จริง ๆ เราเคยลองวิธีนี้ก่อนจะมี permission boundaries และนอกจากความซับซ้อนแล้ว ยังมีช่องโหว่มากเกินไป
ขอตัวอย่างง่าย ๆ อีกสักอันได้ไหม
ได้เลย นี่คือตัวอย่างที่เราใช้เอง
ผู้ใช้บางรายอนุญาตให้เราเปลี่ยนแปลง IAM ในบัญชีของพวกเขา เราใช้ cross-account role สำหรับงานนี้ เมื่อผู้ใช้ deploy role ดังกล่าว พวกเขาจะใช้ permission boundary ที่ไม่ยอมให้เราเปลี่ยนแปลงสิทธิ์ของตัวเราเองได้เลย ซึ่งช่วยป้องกันการยกระดับสิทธิ์
พอเข้าใจแล้ว แต่ IAM policy ทั้งหมดนี้ทำงานร่วมกันอย่างไร
ลองดูเอกสารของ AWS เรื่องตรรกะการประเมิน policy แต่นี่คือโน้ตย่อของผม:
- Service Control Policies จำกัดว่าใครก็ตามทำอะไรได้บ้างในบัญชีหนึ่ง (เช่น เปิดหรือปิดบริการต่าง ๆ)
- IAM permission policy อนุญาตให้ user และ role ทำสิ่งต่าง ๆ ในบัญชีได้
- IAM resource policy อนุญาตให้ user และ role โต้ตอบกับทรัพยากรที่ policy นั้นแนบอยู่
- permission boundaries กำหนดสิทธิ์สูงสุดที่ user หรือ role จะมีได้ มันไม่ได้อนุญาตให้คุณทำสิ่งใด แต่สามารถห้ามไม่ให้คุณทำได้
policy ทั้งหมดทำงานร่วมกัน การที่คุณจะทำสิ่งใดได้ คุณต้องมีสิทธิ์อนุญาตอยู่ที่ใดที่หนึ่งใน stack และต้องไม่มี deny policy ใด ๆ ที่ไหนเลยมาขัดขวางคุณ คำสั่ง Deny เพียงคำสั่งเดียวจะลบล้างคำสั่ง Allow ทั้งหมด ไม่ว่าจะกำหนดไว้ที่ใดก็ตาม
ช่วยย้ำอีกครั้งว่าควรใช้ permission boundaries เมื่อใด
เมื่อใดที่คุณต้องการอนุญาตให้ใครสักคนดูแล IAM บางส่วนในบัญชี แต่ยังต้องการจำกัดขอบเขตไว้ ให้นึกถึง permission boundary ไว้ก่อนเลย
แม้คุณจะใช้เครื่องมือ IAM ขั้นสูงอย่าง FireMon Authorization Control ตัวใหม่ของเรา คุณก็ยังอาจต้องใช้ permission boundaries อยู่ดี โดยเฉพาะในบัญชีที่มีความอ่อนไหวสูง
ตัวอย่างหนึ่งที่บอกว่าจะยกมาให้ดูคืออะไร
แม้ permission boundaries จะมีไว้เพื่อป้องกันไม่ให้คุณทำบางสิ่ง แต่ก็ยังกำหนดให้คุณต้องระบุสิทธิ์ allow ทั้งหมดอยู่ดี กล่าวคือ หากคุณเขียน permission boundary ด้วยคำสั่ง DENY เพื่อบล็อกสิ่งเดียวที่คุณไม่ต้องการให้ user/role นั้นทำ คุณก็ยังต้องมีคำสั่ง ALLOW * ด้วย มิฉะนั้นผู้ใช้รายนั้นจะทำอะไรไม่ได้เลย
ตรงนี้คือจุดที่ทำให้ผมสับสนในตอนแรก เพราะผมอ่านคำอธิบายของ Amazon ผิดไป และเข้าใจว่าสามารถใช้ permission boundary เพื่อบล็อกการกระทำได้เพียงอย่างเดียว ซึ่งทำได้จริง แต่ยกเว้นกรณีการใช้งานแบบ resource policy ที่ผมยังไม่ขอลงรายละเอียดในวันนี้ permission boundary จำเป็นต้องระบุทุกสิ่งที่คุณต้องการอนุญาตไว้ด้วย คุณไม่สามารถ DENY สิ่งหนึ่งไว้ใน permission boundary แล้วไป ALLOW สิ่งอื่นใน IAM permission policy ปกติและคาดหวังว่ามันจะทำงานได้ permission boundary ต้องมีคำสั่ง ALLOW ด้วยเช่นกัน (และใช่ ผมขอใช้ทางลัดด้วยการใส่ ALLOW * ในบางครั้ง)
ยังสับสนอยู่
ส่งอีเมลมาหาผมได้เลย เรื่องพวกนี้ชวนสับสนจริง ๆ