ข้ามไปยังเนื้อหา

Security & Auth

security ใน gRPC ตอบคำถามที่ต่างกันสองข้อ และสำคัญมากที่จะไม่รวมสองข้อนี้เข้าด้วยกัน:

  • connection เป็นส่วนตัวไหม และ server เป็นตัวที่อ้างจริงหรือเปล่า?transport security (TLS)
  • ใครเป็นคน เรียก และเขาได้รับอนุญาตให้เรียก call นี้ไหม?call authentication (token ปกติอยู่ใน metadata)

gRPC จัดการสองอย่างนี้เป็น credentials สองชนิด: channel credentials (ชั้น transport) และ call credentials (auth ต่อ RPC) เกือบทุกครั้งคุณต้องการทั้งคู่

flowchart TB
  subgraph transport["Channel credentials — TLS"]
    t["เข้ารหัส connection
+ ยืนยันตัวตน server
(mTLS ยืนยัน client ด้วย)"]
  end
  subgraph call["Call credentials — ต่อ RPC"]
    c["แนบ token ใน metadata
ระบุตัวคนเรียก
ตรวจโดย server interceptor"]
  end
  transport --> call
transport security และ call auth เป็นชั้นที่แยกกัน

โดย default channel แบบ plaintext (insecure) โอเคสำหรับ demo บนเครื่อง แต่รับไม่ได้บน production TLS เข้ารหัส connection และให้ client ยืนยัน certificate ของ server ได้ ทำให้ไม่มีใครดักฟังหรือปลอมเป็น server ได้

mTLS (mutual TLS) ไปอีกขั้น: server ก็ยืนยัน certificate ของ client ด้วย นี่คือ pattern ที่พบบ่อยสำหรับ auth แบบ service-to-service ภายใน mesh — ทั้งสองฝั่งพิสูจน์ตัวตนด้วย certificate และไม่ต้องใช้ bearer token สำหรับ machine identity

TLS พิสูจน์ตัวตนของ server และของเครื่อง แต่บ่อยครั้งคุณต้องการตัวตนของ ผู้ใช้ ด้วย — bearer token (JWT, OAuth) ที่ส่งต่อ call gRPC แนบ token นี้เป็น call credentials: client ใส่ token authorization ใน metadata ของทุก RPC แล้ว server interceptor ตรวจสอบและ reject ตัวที่ไม่ถูกต้องด้วย UNAUTHENTICATED

call credentials เป็นแบบ ต่อ RPC ดังนั้น call ต่าง ๆ บน channel เดียวกันสามารถถือ token คนละตัวได้ (เช่น channel เดียว ผู้ใช้ปลายทางหลายคน)

// Channel credentials: TLS. Call credentials: a token on every RPC.
creds := credentials.NewClientTLSFromCert(certPool, "")
perRPC := oauth.TokenSource{TokenSource: myTokenSource}
conn, _ := grpc.NewClient(
"api.example.com:443",
grpc.WithTransportCredentials(creds), // TLS
grpc.WithPerRPCCredentials(perRPC), // token per call
)

อย่าส่ง bearer token ผ่าน channel ที่ insecure เด็ดขาด gRPC บังคับเรื่องนี้: call credentials จะไม่ยอมแนบกับ connection แบบ plaintext เพราะ token ที่ส่งแบบ cleartext คือ token ที่ใครก็ตามบนเส้นทางขโมยได้ call credentials ต้องมี channel credentials (TLS) อยู่ข้างล่าง — framework กำลังปกป้องคุณจากบั๊ก security ที่พบบ่อยที่สุดของ gRPC

channel credentials (TLS) ตอบคำถามอะไร?
mTLS เพิ่มอะไรจาก TLS ธรรมดา?
ทำไม call credentials ถึงเรียกว่าแบบต่อ RPC?
ทำไม gRPC ถึงปฏิเสธที่จะแนบ call credentials กับ channel ที่ insecure?