เมื่อสร้างแอปพลิเคชันที่แสดงต่อสาธารณะ คุณต้องปกป้องข้อมูลที่จัดเก็บไว้ในระบบของคุณ ในส่วนของ LLM นั้น คุณต้องใช้ความระมัดระวังเป็นพิเศษเพื่อให้แน่ใจว่าโมเดลเข้าถึงเฉพาะข้อมูลที่ควรเข้าถึง การเรียกใช้เครื่องมือมีขอบเขตที่ถูกต้องสำหรับผู้ใช้ที่เรียกใช้ LLM และมีการเรียกใช้ขั้นตอนโดยแอปพลิเคชันไคลเอ็นต์ที่ยืนยันแล้วเท่านั้น
Firebase Genkit มีกลไกในการจัดการนโยบายการให้สิทธิ์และบริบท ขั้นตอนที่ทำงานใน Firebase สามารถใช้การเรียกกลับนโยบายการตรวจสอบสิทธิ์ (หรือตัวช่วย) หรือ Firebase จะให้บริบทการตรวจสอบสิทธิ์ในขั้นตอนที่สามารถทำการตรวจสอบของตนเองได้ สำหรับโฟลว์ที่ไม่ใช่ของ Functions คุณจะจัดการและตั้งค่าการตรวจสอบสิทธิ์ได้ผ่านมิดเดิลแวร์
ให้สิทธิ์ภายในโฟลว
ขั้นตอนการตรวจสอบการให้สิทธิ์ทำได้ 2 วิธี ได้แก่ การเชื่อมโยงคําขอ (เช่น onCallGenkit
สําหรับ Cloud Functions สําหรับ Firebase หรือ express
) สามารถบังคับใช้การให้สิทธิ์ หรือเฟรมเวิร์กเหล่านั้นสามารถส่งนโยบายการให้สิทธิ์ไปยังขั้นตอนได้โดยตรง โดยที่ขั้นตอนมีสิทธิ์เข้าถึงข้อมูลสําหรับการให้สิทธิ์ที่จัดการภายในขั้นตอน
import { genkit, z, UserFacingError } from 'genkit';
const ai = genkit({ ... });
export const selfSummaryFlow = ai.defineFlow( {
name: 'selfSummaryFlow',
inputSchema: z.object({ uid: z.string() }),
outputSchema: z.string(),
}, async (input, { context }) => {
if (!context.auth) {
throw new UserFacingErrorError('UNAUTHENTICATED', 'Unauthenticated');
}
if (input.uid !== context.auth.uid) {
throw new UserFacingError('PERMISSION_DENIED', 'You may only summarize your own profile data.');
}
// Flow logic here...
});
ในกรณีนี้ context.auth
จะขึ้นอยู่กับการเชื่อมโยงคําขอ เช่น onCallGenkit
จะป้อนข้อมูล context.auth
(การตรวจสอบสิทธิ์ Firebase), context.app
(Firebase App Check) และ context.instanceIdToken
(Firebase Cloud Messaging) โดยอัตโนมัติ เมื่อเรียกใช้ขั้นตอนด้วยตนเอง คุณสามารถเพิ่มบริบทการตรวจสอบสิทธิ์ของคุณเองได้
// Error: Authorization required.
await selfSummaryFlow({ uid: 'abc-def' });
// Error: You may only summarize your own profile data.
await selfSummaryFlow.run(
{ uid: 'abc-def' },
{
context: { auth: { uid: 'hij-klm' } },
}
);
// Success
await selfSummaryFlow(
{ uid: 'abc-def' },
{
context: { auth: { uid: 'abc-def' } },
}
);
เมื่อเรียกใช้กับ UI การพัฒนา Genkit คุณสามารถส่งออบเจ็กต์ Auth โดยป้อน JSON ในแท็บ "Auth JSON" {"uid": "abc-def"}
นอกจากนี้ คุณยังเรียกข้อมูลบริบทการตรวจสอบสิทธิ์สำหรับขั้นตอนได้ทุกเมื่อภายในขั้นตอนนั้น โดยเรียกใช้ ai.currentContext()
ซึ่งรวมถึงในฟังก์ชันที่เรียกใช้โดยขั้นตอน
import { genkit, z } from 'genkit';
const ai = genkit({ ... });;
async function readDatabase(uid: string) {
const auth = ai.currentContext()?.auth;
// Note: the shape of context.auth depends on the provider. onCallGenkit puts
// claims information in auth.token
if (auth?.token?.admin) {
// Do something special if the user is an admin
} else {
// Otherwise, use the `uid` variable to retrieve the relevant document
}
}
export const selfSummaryFlow = ai.defineFlow(
{
name: 'selfSummaryFlow',
inputSchema: z.object({ uid: z.string() }),
outputSchema: z.string(),
authPolicy: ...
},
async (input) => {
await readDatabase(input.uid);
}
);
เมื่อทดสอบขั้นตอนด้วยเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ Genkit คุณจะระบุออบเจ็กต์การตรวจสอบสิทธิ์นี้ได้ใน UI หรือในบรรทัดคําสั่งโดยใช้แฟล็ก --context
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --context '{"auth": {"email_verified": true}}'
ให้สิทธิ์โดยใช้ Cloud Functions for Firebase
Cloud Functions for Firebase SDK รองรับ Genkit รวมถึงการผสานรวมกับ Firebase Auth / Google Cloud Identity Platform ตลอดจนการรองรับ Firebase App Check ในตัว
การตรวจสอบสิทธิ์ของผู้ใช้
onCallGenkit()
Wrapper ที่ไลบรารี Firebase Functions มีให้รองรับSDK ของไคลเอ็นต์ Cloud Functions for Firebase ในตัว
เมื่อคุณใช้ SDK เหล่านี้ ระบบจะรวมส่วนหัว Firebase Auth โดยอัตโนมัติ ตราบใดที่ไคลเอ็นต์แอปของคุณใช้ Firebase Auth SDK ด้วย
คุณใช้ Firebase Auth เพื่อปกป้องขั้นตอนที่กําหนดด้วย onCallGenkit()
ได้ดังนี้
import { genkit } from 'genkit';
import { onCallGenkit } from 'firebase-functions/https';
const ai = genkit({ ... });;
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
authPolicy: (auth) => auth?.token?.['email_verified'] && auth?.token?.['admin'],
}, selfSummaryFlow);
เมื่อคุณใช้ onCallGenkit
ระบบจะแสดงผล context.auth
เป็นออบเจ็กต์ที่มี uid
สำหรับรหัสผู้ใช้ และ token
ซึ่งเป็น DecodedIdToken
คุณสามารถเรียกข้อมูลออบเจ็กต์นี้ได้ทุกเมื่อโดยใช้ ai.currentContext()
ตามที่ระบุไว้ก่อนหน้านี้ เมื่อเรียกใช้ขั้นตอนนี้ระหว่างการพัฒนา คุณจะต้องส่งออบเจ็กต์ผู้ใช้ด้วยวิธีเดียวกัน
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --context '{"auth": {"admin": true}}'
เมื่อใดก็ตามที่คุณเปิดเผยฟังก์ชัน Cloud ไปยังอินเทอร์เน็ตวงกว้าง คุณต้องใช้กลไกการให้สิทธิ์ประเภทใดประเภทหนึ่งเพื่อปกป้องข้อมูลของคุณและข้อมูลของลูกค้า อย่างไรก็ตาม บางครั้งคุณอาจต้องทำให้ Cloud Function ใช้งานได้โดยไม่มีการตรวจสอบการให้สิทธิ์ตามโค้ด (เช่น ฟังก์ชันของคุณไม่สามารถเรียกใช้ได้จากทุกที่ แต่ได้รับการปกป้องโดย Cloud IAM)
Cloud Functions for Firebase ช่วยให้คุณทําสิ่งนี้ได้โดยใช้พร็อพเพอร์ตี้ invoker
ซึ่งควบคุมการเข้าถึง IAM ค่าพิเศษ 'private'
จะทําให้ฟังก์ชันเป็นการตั้งค่า IAM เริ่มต้น ซึ่งหมายความว่ามีเพียงผู้เรียกที่มีบทบาทผู้เรียกใช้ Cloud Run เท่านั้นที่จะเรียกใช้ฟังก์ชันได้ คุณระบุอีเมลของผู้ใช้หรือบัญชีบริการที่ควรได้รับสิทธิ์เรียกใช้ฟังก์ชันนี้แทนได้
import { onCallGenkit } from 'firebase-functions/https'
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
invoker: 'private',
}, selfSummaryFlow);
ความสมบูรณ์ของไคลเอ็นต์
การตรวจสอบสิทธิ์เพียงอย่างเดียวช่วยปกป้องแอปของคุณได้เป็นอย่างมาก แต่การตรวจสอบสิทธิ์ยังช่วยตรวจสอบว่ามีเพียงแอปไคลเอ็นต์ของคุณเท่านั้นที่เรียกใช้ฟังก์ชันของคุณ ปลั๊กอิน Firebase สำหรับ genkit มีการรองรับFirebase App Check ชั้นยอด โดยเพิ่มตัวเลือกการกําหนดค่าต่อไปนี้ลงใน onCallGenkit()
import { onCallGenkit } from 'firebase-functions/https';
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
// These two fields for app check. The consumeAppCheckToken option is for
// replay protection, and requires additional client configuration. See the
// App Check docs.
enforceAppCheck: true,
consumeAppCheckToken: true,
authPolicy: ...,
}, selfSummaryFlow);
การให้สิทธิ์ HTTP ที่ไม่ใช่ Firebase
เมื่อทําให้ใช้งานได้ในบริบทเซิร์ฟเวอร์นอก Cloud Functions สําหรับ Firebase คุณควรมีวิธีตั้งค่าการตรวจสอบการให้สิทธิ์ของคุณเองควบคู่ไปกับขั้นตอนที่มาพร้อมกับระบบ
ใช้ ContextProvider
เพื่อป้อนค่าบริบท เช่น auth
และเพื่อระบุนโยบายแบบประกาศหรือนโยบายการเรียกกลับ Genkit
SDK มี ContextProvider
เช่น apiKey
และปลั๊กอินอาจแสดง ContextProvider
เหล่านี้ด้วย เช่น ปลั๊กอิน @genkit-ai/firebase/context
จะแสดงผู้ให้บริการบริบทสําหรับยืนยันข้อมูลเข้าสู่ระบบ Firebase Auth และป้อนข้อมูลเข้าสู่บริบท
ด้วยโค้ดต่อไปนี้ ซึ่งอาจปรากฏในแอปพลิเคชันต่างๆ
// Express app with a simple API key
import { genkit, z } from 'genkit';
const ai = genkit({ ... });;
export const selfSummaryFlow = ai.defineFlow(
{
name: 'selfSummaryFlow',
inputSchema: z.object({ uid: z.string() }),
outputSchema: z.string(),
},
async (input) => {
// Flow logic here...
}
);
คุณสามารถรักษาความปลอดภัยให้กับแอป Express "flow server" แบบง่ายได้ด้วยการเขียนโค้ดดังนี้
import { apiKey } from "genkit";
import { startFlowServer, withContext } from "@genkit-ai/express";
startFlowServer({
flows: [
withContext(selfSummaryFlow, apiKey(process.env.REQUIRED_API_KEY))
],
});
หรือจะสร้างแอปพลิเคชัน Express ที่กําหนดเองโดยใช้เครื่องมือเดียวกันก็ได้
import { apiKey } from "genkit";
import * as express from "express";
import { expressHandler } from "@genkit-ai/express;
const app = express();
// Capture but don't validate the API key (or its absence)
app.post('/summary', expressHandler(selfSummaryFlow, { contextProvider: apiKey()}))
app.listen(process.env.PORT, () => {
console.log(`Listening on port ${process.env.PORT}`);
})
ContextProvider
แยกเฟรมเวิร์กเว็บออกเพื่อให้เครื่องมือเหล่านี้ทำงานในเฟรมเวิร์กอื่นๆ เช่น Next.js ได้ด้วย ต่อไปนี้คือตัวอย่างแอป Firebase ที่สร้างขึ้นบน Next.js
import { appRoute } from "@genkit-ai/express";
import { firebaseContext } from "@genkit-ai/firebase";
export const POST = appRoute(selfSummaryFlow, { contextProvider: firebaseContext })
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Express ได้ที่วิธีการของ Cloud Run