ภาษาของนิพจน์ทั่วไป (CEL)

Common Expression Language (CEL) เป็นภาษาที่ใช้เขียนนิพจน์แบบอเนกประสงค์ ซึ่งออกแบบมาให้รวดเร็ว พกพาสะดวก และปลอดภัยในการดำเนินการ คุณใช้ CEL แยกต่างหาก หรือฝังไว้ในผลิตภัณฑ์ที่ใหญ่ขึ้นก็ได้ CEL เหมาะอย่างยิ่งสำหรับการใช้งานที่หลากหลาย ตั้งแต่การกำหนดเส้นทางการเรียกใช้โพรซีเยอร์ระยะไกล (RPC) ไปจนถึงการกำหนดนโยบายความปลอดภัย CEL ขยายได้ ไม่ขึ้นอยู่กับแพลตฟอร์ม และได้รับการเพิ่มประสิทธิภาพสำหรับ เวิร์กโฟลว์คอมไพล์ครั้งเดียว/ประเมินหลายครั้ง

CEL ออกแบบมาโดยเฉพาะเพื่อให้ปลอดภัยสำหรับการเรียกใช้โค้ดของผู้ใช้ แม้ว่าการเรียกใช้ eval() ในโค้ด Python ของผู้ใช้โดยไม่พิจารณาอาจเป็นอันตราย แต่คุณก็สามารถเรียกใช้โค้ด CEL ของผู้ใช้ได้อย่างปลอดภัย และเนื่องจาก CEL ป้องกันพฤติกรรมที่จะทําให้ประสิทธิภาพลดลง จึงประเมินได้อย่างปลอดภัยในระดับนาโนวินาทีหรือไมโครวินาที ความเร็ว และความปลอดภัยของ CEL ทำให้เหมาะสำหรับแอปพลิเคชันที่ต้องการประสิทธิภาพสูง

CEL ประเมินนิพจน์ที่คล้ายกับฟังก์ชันบรรทัดเดียวหรือนิพจน์ Lambda แม้ว่าโดยทั่วไปแล้ว CEL จะใช้สำหรับการตัดสินใจแบบบูลีน แต่คุณก็ใช้ เพื่อสร้างออบเจ็กต์ที่ซับซ้อนมากขึ้น เช่น ข้อความ JSON หรือ Protocol Buffer ได้เช่นกัน

ทำไมต้อง CEL

บริการและแอปพลิเคชันจำนวนมากประเมินการกำหนดค่าแบบประกาศ ตัวอย่างเช่น การควบคุมการเข้าถึงตามบทบาท (RBAC) คือการกำหนดค่าแบบประกาศที่สร้าง การตัดสินการเข้าถึงตามบทบาทของผู้ใช้และชุดผู้ใช้ แม้ว่าการกำหนดค่าแบบประกาศจะเพียงพอสำหรับกรณีส่วนใหญ่ แต่บางครั้งคุณก็ต้องการความสามารถในการแสดงออกที่มากขึ้น ตรงนี้เองที่ CEL จะเข้ามามีบทบาท

ตัวอย่างการขยายการกำหนดค่าแบบประกาศด้วย CEL ให้พิจารณาความสามารถของ Identity and Access Management (IAM) ของ Google Cloud แม้ว่า RBAC จะเป็นกรณีที่พบบ่อย แต่ IAM ก็มีนิพจน์ CEL เพื่อให้ผู้ใช้สามารถ จำกัดขอบเขตของการให้สิทธิ์ตามบทบาทเพิ่มเติมตาม Proto คุณสมบัติข้อความของคำขอหรือทรัพยากรที่กำลังเข้าถึง การอธิบาย เงื่อนไขดังกล่าวผ่านโมเดลข้อมูลจะส่งผลให้เกิด API ที่ซับซ้อน ซึ่งใช้งานได้ยาก แต่การใช้ CEL กับการควบคุมการเข้าถึงตามแอตทริบิวต์ (ABAC) เป็นส่วนขยายที่มีประสิทธิภาพและทรงพลังของ RBAC

แนวคิดหลักของ CEL

ใน CEL ระบบจะคอมไพล์นิพจน์กับสภาพแวดล้อม ขั้นตอนการคอมไพล์ จะสร้าง Abstract Syntax Tree (AST) ในรูปแบบProtocol Buffer ระบบจะจัดเก็บนิพจน์ที่คอมไพล์แล้วไว้ใช้ในอนาคตเพื่อให้การประเมินเป็นไปอย่างรวดเร็วที่สุด นิพจน์ที่คอมไพล์แล้วรายการเดียวสามารถประเมินได้ด้วยอินพุตที่แตกต่างกันหลายรายการ

มาดูรายละเอียดเกี่ยวกับแนวคิดเหล่านี้กัน

นิพจน์

ผู้ใช้เป็นผู้เขียนนิพจน์ นิพจน์จะคล้ายกับเนื้อหาของฟังก์ชันแบบบรรทัดเดียวหรือนิพจน์แลมบ์ดา ลายเซ็นฟังก์ชันที่ประกาศอินพุตจะเขียนอยู่นอกนิพจน์ CEL และระบบจะนำเข้าไลบรารีของฟังก์ชันที่ใช้ได้กับ CEL โดยอัตโนมัติ

เช่น นิพจน์ CEL ต่อไปนี้จะใช้ออบเจ็กต์คำขอ และคำขอมีโทเค็น claims นิพจน์จะแสดงผลค่าบูลีนที่ ระบุว่าโทเค็น claims ยังคงใช้งานได้หรือไม่

ตัวอย่างนิพจน์ CEL เพื่อตรวจสอบสิทธิ์โทเค็นการอ้างสิทธิ์

// Check whether a JSON Web Token has expired by inspecting the 'exp' claim.
//
// Args:
//   claims - authentication claims.
//   now    - timestamp indicating the current system time.
// Returns: true if the token has expired.
//
timestamp(claims["exp"]) < now

ในขณะที่ผู้ใช้กำหนดนิพจน์ CEL บริการและแอปพลิเคชันจะกำหนด สภาพแวดล้อมที่นิพจน์ทำงาน

สภาพแวดล้อม

สภาพแวดล้อมกำหนดโดยบริการ บริการและแอปพลิเคชันที่ฝัง CEL จะประกาศสภาพแวดล้อมของนิพจน์ สภาพแวดล้อมคือชุดของ ตัวแปรและฟังก์ชันที่ใช้ในนิพจน์ CEL ได้

ตัวอย่างเช่น โค้ด textproto ต่อไปนี้ประกาศสภาพแวดล้อมที่มีตัวแปร request และ now โดยใช้ข้อความ CompileRequest จากบริการ CEL

ตัวอย่างการประกาศสภาพแวดล้อม CEL

# Format: $SOURCE_PATH/service.proto#CompileRequest
declarations {
  name: "request"
  ident {
    type { message_type: "google.rpc.context.AttributeContext.Request" }
  }
}
declarations {
  name: "now"
  ident {
    type { well_known: "TIMESTAMP" }
  }
}

การประกาศที่อิงตาม Proto จะใช้โดยเครื่องมือตรวจสอบประเภท CEL เพื่อให้แน่ใจว่าตัวระบุและการอ้างอิงฟังก์ชันทั้งหมดภายในนิพจน์ได้รับการประกาศและใช้งานอย่างถูกต้อง

ขั้นตอนการประมวลผลนิพจน์

ระบบจะประมวลผลนิพจน์ CEL ใน 3 เฟสต่อไปนี้

  1. แยกวิเคราะห์
  2. ตรวจสอบ
  3. ประเมิน

รูปแบบการใช้งาน CEL ที่พบบ่อยที่สุดคือการแยกวิเคราะห์และตรวจสอบนิพจน์ในเวลาที่กำหนดค่า จัดเก็บ AST แล้วเรียกข้อมูลและประเมิน AST ซ้ำๆ ในเวลา รันไทม์

ภาพประกอบของขั้นตอนการประมวลผล CEL

ระบบจะแยกวิเคราะห์และตรวจสอบนิพจน์ในเส้นทางการกำหนดค่า จัดเก็บไว้ แล้ว
ประเมินกับบริบทอย่างน้อย 1 บริบทในเส้นทางการอ่าน

CEL จะได้รับการแยกวิเคราะห์จากนิพจน์ที่มนุษย์อ่านได้เป็น AST โดยใช้ไวยากรณ์ของตัวแยกคำและตัวแยกวิเคราะห์ ANTLR เฟสการแยกวิเคราะห์จะปล่อย AST ที่อิงตาม Proto ซึ่งแต่ละโหนด Expr ใน AST จะมีรหัสจำนวนเต็มที่ใช้ในการจัดทำดัชนีลงในข้อมูลเมตาที่สร้างขึ้นระหว่างการแยกวิเคราะห์และการตรวจสอบ ไฟล์ syntax.proto ที่สร้างขึ้นระหว่างการแยกวิเคราะห์จะแสดง การแสดงผลแบบนามธรรมของสิ่งที่พิมพ์ในรูปแบบสตริงของ นิพจน์

หลังจากแยกวิเคราะห์นิพจน์แล้ว ระบบจะตรวจสอบประเภทกับสภาพแวดล้อมเพื่อ ตรวจสอบว่าตัวระบุตัวแปรและฟังก์ชันทั้งหมดในนิพจน์ได้รับการ ประกาศและใช้งานอย่างถูกต้อง เครื่องมือตรวจสอบประเภทจะสร้างไฟล์ checked.proto ซึ่งมีข้อมูลเมตาประเภท ตัวแปร และฟังก์ชัน ความละเอียดที่ช่วยปรับปรุงประสิทธิภาพการประเมินได้อย่างมาก

สุดท้ายนี้ หลังจากแยกวิเคราะห์และตรวจสอบนิพจน์แล้ว ระบบจะประเมิน AST ที่จัดเก็บไว้

เครื่องมือประเมิน CEL ต้องการ 3 สิ่งต่อไปนี้

  • การเชื่อมโยงฟังก์ชันสำหรับส่วนขยายที่กำหนดเอง
  • การเชื่อมโยงตัวแปร
  • AST ที่จะประเมิน

การเชื่อมโยงฟังก์ชันและตัวแปรควรตรงกับที่ใช้ในการคอมไพล์ AST คุณสามารถนำอินพุตเหล่านี้ไปใช้ซ้ำในการประเมินหลายครั้งได้ เช่น AST ที่ได้รับการประเมินในชุดการเชื่อมโยงตัวแปรหลายชุด ตัวแปรเดียวกัน ที่ใช้กับ AST หลายรายการ หรือการเชื่อมโยงฟังก์ชันที่ใช้ตลอดอายุการใช้งานของ กระบวนการ (กรณีทั่วไป)