अनुमति देना और उसका रखरखाव करना

सार्वजनिक रूप से उपलब्ध कोई भी ऐप्लिकेशन बनाते समय, अपने सिस्टम में सेव किए गए डेटा की सुरक्षा करना बहुत ज़रूरी है. एलएलएम के मामले में, ज़्यादा बारीकी से यह पक्का करने की ज़रूरत होती है कि मॉडल डेटा को ऐक्सेस कर रहा हो. साथ ही, टूल कॉल एलएलएम का इस्तेमाल करने वाले उपयोगकर्ता के दायरे में हों. साथ ही, इस फ़्लो को सिर्फ़ पुष्टि किए गए क्लाइंट ऐप्लिकेशन पर ही शुरू किया जा रहा हो.

Firebase Genkit, अनुमति देने से जुड़ी नीतियों और कॉन्टेक्स्ट को मैनेज करने के लिए मैकेनिज़्म उपलब्ध कराता है. 'Firebase के लिए Cloud Functions' पर चलने वाले फ़्लो के लिए, डेवलपर को पुष्टि करने से जुड़ी नीति देनी होगी या साफ़ तौर पर यह स्वीकार करना होगा कि कोई नीति मौजूद नहीं है. गैर-फ़ंक्शन फ़्लो के लिए, पुष्टि करने की प्रक्रिया को मैनेज और सेट भी किया जा सकता है. हालांकि, इसके लिए कुछ और मैन्युअल इंटिग्रेशन की ज़रूरत होती है.

बेसिक फ़्लो की अनुमति देना

सभी फ़्लो अपने कॉन्फ़िगरेशन में authPolicy को तय कर सकते हैं. पुष्टि करने से जुड़ी नीति एक ऐसा फ़ंक्शन है जो यह जांच करता है कि आपकी तय की गई कोई शर्त पूरी हुई है या नहीं. साथ ही, अगर कोई जांच फ़ेल हो जाती है, तो उसे अपवाद के तौर पर अनुमति दी जाती है. अगर इस फ़ील्ड को सेट किया जाता है, तो इसे फ़्लो के शुरू होने से पहले एक्ज़ीक्यूट किया जाता है:

import { defineFlow, runFlow } from '@genkit-ai/flow';

export const selfSummaryFlow = defineFlow(
  {
    name: 'selfSummaryFlow',
    inputSchema: z.object({uid: z.string()}),
    outputSchema: z.string(),
    authPolicy: (auth, input) => {
      if (!auth) {
        throw new Error('Authorization required.');
      }
      if (input.uid !== auth.uid) {
        throw new Error('You may only summarize your own profile data.');
      }
    }
  },
  async (input) => { ... });

इस फ़्लो को एक्ज़ीक्यूट करते समय, आपको withLocalAuthContext का इस्तेमाल करके पुष्टि करने वाला एक ऑब्जेक्ट देना ज़रूरी है. ऐसा न करने पर, आपको कोई गड़बड़ी दिखेगी:

// Error: Authorization required.
await runFlow(selfSummaryFlow, { uid: 'abc-def' });

// Error: You may only summarize your own profile data.
await runFlow(
  selfSummaryFlow,
  { uid: 'abc-def' },
  {
    withLocalAuthContext: { uid: 'hij-klm' },
  }
);

// Success
await runFlow(
  selfSummaryFlow,
  { uid: 'abc-def' },
  {
    withLocalAuthContext: { uid: 'abc-def' },
  }
);

Genkit डेवलपमेंट यूज़र इंटरफ़ेस (यूआई) के साथ चलाते समय, "Auth JSON" टैब में JSON डालकर, Auth ऑब्जेक्ट पास किया जा सकता है: {"uid": "abc-def"}.

getFlowAuth() को कॉल करके, फ़्लो में किसी भी समय फ़्लो के लिए, पुष्टि करने का कॉन्टेक्स्ट फिर से पाया जा सकता है. इसमें फ़्लो से शुरू किए गए फ़ंक्शन भी शामिल हैं:

import { getFlowAuth, defineFlow } from '@genkit-ai/flow';

async function readDatabase(uid: string) {
  if (getFlowAuth().admin) {
    // Do something special if the user is an admin:
    ...
  } else {
    // Otherwise, use the `uid` variable to retrieve the relevant document
    ...
  }
}

export const selfSummaryFlow = defineFlow(
  {
    name: 'selfSummaryFlow',
    inputSchema: z.object({uid: z.string()}),
    outputSchema: z.string(),
    authPolicy: ...
  },
  async (input) => {
    ...
    await readDatabase(input.uid);
  });

Genkit Dev टूल के साथ फ़्लो का टेस्ट करते समय, यूज़र इंटरफ़ेस (यूआई) में या कमांड लाइन पर --auth फ़्लैग के साथ इस ऑब्जेक्ट के बारे में जानकारी दी जा सकती है:

genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"uid": "abc-def"}'

Firebase इंटिग्रेशन के लिए Cloud Functions

Firebase प्लगिन, Firebase पुष्टि / Google Cloud Identity Platform के साथ-साथ पहले से मौजूद Firebase ऐप्लिकेशन जांच की सहायता के साथ आसानी से इंटिग्रेशन करने की सुविधा देता है.

अनुमति देना

Firebase प्लगिन से मिला onFlow() रैपर, 'Firebase के लिए Cloud Functions' क्लाइंट SDK टूल के साथ नेटिव तौर पर काम करता है. SDK टूल का इस्तेमाल करते समय, जब तक आपका ऐप्लिकेशन क्लाइंट भी Firebase पुष्टि SDK टूल का इस्तेमाल कर रहा है, तब तक Firebase में पुष्टि वाला हेडर अपने-आप शामिल हो जाएगा. onFlow() में तय किए गए फ़्लो को सुरक्षित रखने के लिए, Firebase ऑथराइज़ेशन का इस्तेमाल किया जा सकता है:

import {firebaseAuth} from "@genkit-ai/firebase/auth";
import {onFlow} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      if (!user.email_verified && !user.admin) {
        throw new Error("Email not verified");
      }
    }),
  }, (subject) => {...})

Firebase पुष्टि प्लगिन का इस्तेमाल करने पर, user को DecodeIdToken के तौर पर दिखाया जाएगा. जैसा कि ऊपर बताया गया है, इस ऑब्जेक्ट को getFlowAuth() की मदद से कभी भी वापस लाया जा सकता है. डेवलपमेंट के दौरान इस फ़्लो को चलाते समय, आपको उपयोगकर्ता ऑब्जेक्ट को इसी तरह पास करना होगा:

genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"admin": true}'

डिफ़ॉल्ट रूप से, Firebase पुष्टि प्लग इन के लिए क्लाइंट को पुष्टि करने वाला हेडर भेजना ज़रूरी होता है. हालांकि, अगर आप पुष्टि किए गए उपयोगकर्ताओं (अपसेल करने वाली सुविधाएं जैसे) के लिए खास हैंडलिंग की मदद से, बिना पुष्टि वाले ऐक्सेस की अनुमति देना चाहते हैं, तो नीति को इस तरह कॉन्फ़िगर किया जा सकता है:

authPolicy: firebaseAuth((user) => {
  if (user && !user.email_verified) {
    throw new Error("Logged in users must have verified emails");
  }
}, {required: false}),

जब भी आप किसी Cloud Function को पूरे इंटरनेट पर सार्वजनिक करते हैं, तो यह बेहद ज़रूरी है कि आप अपने डेटा और अपने ग्राहकों के डेटा को सुरक्षित रखने के लिए अनुमति देने के किसी तरीके का इस्तेमाल करें. हालांकि, कई बार आपको ऐसा क्लाउड फ़ंक्शन डिप्लॉय करना पड़ता है, जिसमें अनुमति देने के लिए कोड आधारित जांच के बिना ही ऐसा किया जाता है. उदाहरण के लिए, आपके फ़ंक्शन को दुनिया भर में कॉल करने लायक नहीं बनाया जा सकता, बल्कि Cloud IAM से इसकी सुरक्षा की जा सकती है. onFlow() का इस्तेमाल करते समय authPolicy फ़ील्ड की ज़रूरत हमेशा होती है. हालांकि, noAuth() फ़ंक्शन का इस्तेमाल करके लाइब्रेरी को यह बताया जा सकता है कि आपसे अनुमति लेने की प्रक्रिया शुरू हो रही है:

import {onFlow, noAuth} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    // WARNING: Only do this if you have some other gatekeeping in place, like
    // Cloud IAM!
    authPolicy: noAuth(),
  }, (subject) => {...})

क्लाइंट इंटिग्रिटी

अपने-आप पुष्टि करने से, आपके ऐप्लिकेशन को सुरक्षित रखने में काफ़ी मदद मिलती है. हालांकि, यह पक्का करना भी ज़रूरी है कि सिर्फ़ आपके क्लाइंट ऐप्लिकेशन ही आपके फ़ंक्शन को कॉल कर रहे हैं. genkit के लिए Firebase प्लगिन में Firebase App Check के लिए फ़र्स्ट क्लास सहायता उपलब्ध होती है. अपने onFlow() में ये कॉन्फ़िगरेशन जोड़ें:

import {onFlow} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),

    // 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: ...,
  }, (subject) => {...})

Firebase के अलावा, एचटीटीपी ऑथराइज़ेशन

'Firebase के लिए Cloud Functions' के बाहर के सर्वर कॉन्टेक्स्ट में फ़्लो को डिप्लॉय करते समय, नेटिव फ़्लो के साथ-साथ आपको अनुमति वाली जांच सेट अप करने का तरीका भी चाहिए. आपके पास दो विकल्प हैं:

  1. अपनी पसंद का सर्वर फ़्रेमवर्क इस्तेमाल करें. साथ ही, ऊपर बताए गए तरीके से runFlow() के ज़रिए पुष्टि करने का कॉन्टेक्स्ट पास करें.

  2. पहले से मौजूद startFlowsServer() का इस्तेमाल करें और फ़्लो कॉन्फ़िगरेशन में एक्सप्रेस मिडलवेयर की जानकारी दें:

    export const selfSummaryFlow = defineFlow(
    {
      name: 'selfSummaryFlow',
      inputSchema: z.object({uid: z.string()}),
      outputSchema: z.string(),
      middleware: [
        (req, res, next) => {
          const token = req.headers['authorization'];
          const user = yourVerificationLibrary(token);
    
          // This is what will get passed to your authPolicy
          req.auth = user;
          next();
        }
      ],
      authPolicy: (auth, input) => {
        if (!auth) {
          throw new Error('Authorization required.');
        }
        if (input.uid !== auth.uid) {
          throw new Error('You may only summarize your own profile data.');
        }
      }
    },
    async (input) => { ... });
    
    startFlowsServer();  // This will register the middleware
    

    Express का इस्तेमाल करने के बारे में ज़्यादा जानकारी के लिए, Cloud Run के लिए दिए निर्देश देखें.

कृपया ध्यान दें, अगर (1) का इस्तेमाल किया जाता है, तो middleware कॉन्फ़िगरेशन विकल्प को runFlow() नज़रअंदाज़ कर देगा.