אימות לצורך שימוש בספריות לקוח

בדף הזה נסביר איך להשתמש בספריות לקוח כדי לגשת ל-Google APIs.

ספריות לקוח מאפשרות לגשת בקלות ל-Google Cloud APIs בשפה נתמכת. אפשר להשתמש ישירות ב- Google Cloud APIs על ידי יצירת בקשות גולמיות חדשות לשרת, אבל ספריות לקוח מפשטות את התהליך ומפחיתות באופן משמעותי את כמות הקוד שתצטרכו לכתוב. זה נכון במיוחד לאימות, כי ספריות הלקוח תומכות ב-Application Default Credentials ‏ (ADC).

אם אתם מקבלים הגדרות של פרטי כניסה (JSON, קבצים או סטרימינג) ממקור חיצוני (לדוגמה, מלקוח), כדאי לעיין בדרישות האבטחה כשמשתמשים בהגדרות של פרטי כניסה ממקור חיצוני.

שימוש ב-Application Default Credentials עם ספריות לקוח

קודם כול צריך להגדיר את השירות Application Default Credentials בסביבה שבה האפליקציה פועלת, כדי שתוכלו להשתמש בו לאימות האפליקציה שלכם. לאחר מכן, כשיוצרים לקוח באמצעות ספריית הלקוח, היא מחפשת באופן אוטומטי את פרטי הכניסה שסיפקתם ל-ADC ומשתמשת בהם כדי לאמת את ממשקי ה-API שבהם הקוד שלכם משתמש. אין צורך לאמת ולנהל אסימונים באופן מפורש. הדרישות האלו מנוהלות אוטומטית על ידי ספריות האימות.

בסביבת פיתוח מקומית, אפשר להגדיר את ADC עם פרטי הכניסה של המשתמש או עם התחזות לחשבון שירות באמצעות ה-CLI של gcloud. בסביבות ייצור, אפשר להגדיר את ADC באמצעות צירוף של חשבון שירות.

דוגמה ליצירת לקוח

דוגמאות הקוד הבאות מדגימות יצירה של לקוח לשירות Cloud Storage. סביר להניח שבקוד שלכם תשתמשו בלקוחות אחרים. הדוגמאות האלו נועדו רק כדי להמחיש איך יוצרים לקוח ומשתמשים בו ללא קוד שמבצע אימות באופן מפורש.

כדי להריץ את הדוגמאות הבאות, צריך לבצע את השלבים הבאים:

Go

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/storage"
	"google.golang.org/api/iterator"
)

// authenticateImplicitWithAdc uses Application Default Credentials
// to automatically find credentials and authenticate.
func authenticateImplicitWithAdc(w io.Writer, projectId string) error {
	// projectId := "your_project_id"

	ctx := context.Background()

	// NOTE: Replace the client created below with the client required for your application.
	// Note that the credentials are not specified when constructing the client.
	// The client library finds your credentials using ADC.
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	it := client.Buckets(ctx, projectId)
	for {
		bucketAttrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Fprintf(w, "Bucket: %v\n", bucketAttrs.Name)
	}

	fmt.Fprintf(w, "Listed all storage buckets.\n")

	return nil
}

Java


import com.google.api.gax.paging.Page;
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;

public class AuthenticateImplicitWithAdc {

  public static void main(String[] args) throws IOException {
    // TODO(Developer):
    //  1. Before running this sample,
    //  set up Application Default Credentials as described in
    //  https://cloud.google.com/docs/authentication/external/set-up-adc
    //  2. Replace the project variable below.
    //  3. Make sure you have the necessary permission to list storage buckets
    //  "storage.buckets.list"
    String projectId = "your-google-cloud-project-id";
    authenticateImplicitWithAdc(projectId);
  }

  // When interacting with Google Cloud Client libraries, the library can auto-detect the
  // credentials to use.
  public static void authenticateImplicitWithAdc(String project) throws IOException {

    // *NOTE*: Replace the client created below with the client required for your application.
    // Note that the credentials are not specified when constructing the client.
    // Hence, the client library will look for credentials using ADC.
    //
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    Storage storage = StorageOptions.newBuilder().setProjectId(project).build().getService();

    System.out.println("Buckets:");
    Page<Bucket> buckets = storage.list();
    for (Bucket bucket : buckets.iterateAll()) {
      System.out.println(bucket.toString());
    }
    System.out.println("Listed all storage buckets.");
  }
}

Node.js

/**
 * TODO(developer):
 *  1. Uncomment and replace these variables before running the sample.
 *  2. Set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc
 *  3. Make sure you have the necessary permission to list storage buckets "storage.buckets.list"
 *    (https://cloud.google.com/storage/docs/access-control/iam-permissions#bucket_permissions)
 */
// const projectId = 'YOUR_PROJECT_ID';

const {Storage} = require('@google-cloud/storage');

async function authenticateImplicitWithAdc() {
  // This snippet demonstrates how to list buckets.
  // NOTE: Replace the client created below with the client required for your application.
  // Note that the credentials are not specified when constructing the client.
  // The client library finds your credentials using ADC.
  const storage = new Storage({
    projectId,
  });
  const [buckets] = await storage.getBuckets();
  console.log('Buckets:');

  for (const bucket of buckets) {
    console.log(`- ${bucket.name}`);
  }

  console.log('Listed all storage buckets.');
}

authenticateImplicitWithAdc();

PHP

// Imports the Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

/**
 * Authenticate to a cloud client library using a service account implicitly.
 *
 * @param string $projectId The Google project ID.
 */
function auth_cloud_implicit($projectId)
{
    $config = [
        'projectId' => $projectId,
    ];

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python


from google.cloud import storage


def authenticate_implicit_with_adc(project_id: str = "your-google-cloud-project-id") -> None:
    """
    When interacting with Google Cloud Client libraries, the library can auto-detect the
    credentials to use.

    // TODO(Developer):
    //  1. Before running this sample,
    //  set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc
    //  2. Replace the project variable.
    //  3. Make sure that the user account or service account that you are using
    //  has the required permissions. For this sample, you must have "storage.buckets.list".
    Args:
        project_id: The project id of your Google Cloud project.
    """

    # This snippet demonstrates how to list buckets.
    # *NOTE*: Replace the client created below with the client required for your application.
    # Note that the credentials are not specified when constructing the client.
    # Hence, the client library will look for credentials using ADC.
    storage_client = storage.Client(project=project_id)
    buckets = storage_client.list_buckets()
    print("Buckets:")
    for bucket in buckets:
        print(bucket.name)
    print("Listed all storage buckets.")

Ruby

def authenticate_implicit_with_adc project_id:
  # The ID of your Google Cloud project
  # project_id = "your-google-cloud-project-id"

  ###
  # When interacting with Google Cloud Client libraries, the library can auto-detect the
  # credentials to use.
  # TODO(Developer):
  #   1. Before running this sample,
  #      set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc
  #   2. Replace the project variable.
  #   3. Make sure that the user account or service account that you are using
  #      has the required permissions. For this sample, you must have "storage.buckets.list".
  ###

  require "google/cloud/storage"

  # This sample demonstrates how to list buckets.
  # *NOTE*: Replace the client created below with the client required for your application.
  # Note that the credentials are not specified when constructing the client.
  # Hence, the client library will look for credentials using ADC.
  storage = Google::Cloud::Storage.new project_id: project_id
  buckets = storage.buckets
  puts "Buckets: "
  buckets.each do |bucket|
    puts bucket.name
  end
  puts "Plaintext: Listed all storage buckets."
end

שימוש במפתחות API עם ספריות לקוח

אפשר להשתמש במפתחות API רק עם ספריות לקוח של ממשקי API שמקבלים מפתחות API. בנוסף, למפתח ה-API אסור שתהיה הגבלת API שמונעת את השימוש בו עבור ה-API.

מידע נוסף על מפתחות API שנוצרו במצב אקספרס זמין בשאלות הנפוצות על מצב אקספרס ב-Google Cloud.

כדי להדגים איך מספקים מפתח API לספרייה, בדוגמה הזו נשתמש ב-Cloud Natural Language API שתומך במפתחות API.

C#‎

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.


using Google.Cloud.Language.V1;
using System;

public class UseApiKeySample
{
    public void AnalyzeSentiment(string apiKey)
    {
        LanguageServiceClient client = new LanguageServiceClientBuilder
        {
            ApiKey = apiKey
        }.Build();

        string text = "Hello, world!";

        AnalyzeSentimentResponse response = client.AnalyzeSentiment(Document.FromPlainText(text));
        Console.WriteLine($"Text: {text}");
        Sentiment sentiment = response.DocumentSentiment;
        Console.WriteLine($"Sentiment: {sentiment.Score}, {sentiment.Magnitude}");
        Console.WriteLine("Successfully authenticated using the API key");
    }
}

C++‎

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.

#include "google/cloud/language/v1/language_client.h"
#include "google/cloud/credentials.h"
#include "google/cloud/options.h"

void AuthenticateWithApiKey(std::vector<std::string> const& argv) {
  if (argv.size() != 2) {
    throw google::cloud::testing_util::Usage{
        "authenticate-with-api-key <project-id> <api-key>"};
  }
  namespace gc = ::google::cloud;
  auto options = gc::Options{}.set<gc::UnifiedCredentialsOption>(
      gc::MakeApiKeyCredentials(argv[1]));
  auto client = gc::language_v1::LanguageServiceClient(
      gc::language_v1::MakeLanguageServiceConnection(options));

  auto constexpr kText = "Hello, world!";

  google::cloud::language::v1::Document d;
  d.set_content(kText);
  d.set_type(google::cloud::language::v1::Document::PLAIN_TEXT);

  auto response = client.AnalyzeSentiment(d, {});
  if (!response) throw std::move(response.status());
  auto const& sentiment = response->document_sentiment();
  std::cout << "Text: " << kText << "\n";
  std::cout << "Sentiment: " << sentiment.score() << ", "
            << sentiment.magnitude() << "\n";
  std::cout << "Successfully authenticated using the API key\n";
}

Go

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.

import (
	"context"
	"fmt"
	"io"

	language "cloud.google.com/go/language/apiv1"
	"cloud.google.com/go/language/apiv1/languagepb"
	"google.golang.org/api/option"
)

// authenticateWithAPIKey authenticates with an API key for Google Language
// service.
func authenticateWithAPIKey(w io.Writer, apiKey string) error {
	// apiKey := "api-key-string"

	ctx := context.Background()

	// Initialize the Language Service client and set the API key.
	client, err := language.NewClient(ctx, option.WithAPIKey(apiKey))
	if err != nil {
		return fmt.Errorf("NewClient: %w", err)
	}
	defer client.Close()

	text := "Hello, world!"
	// Make a request to analyze the sentiment of the text.
	res, err := client.AnalyzeSentiment(ctx, &languagepb.AnalyzeSentimentRequest{
		Document: &languagepb.Document{
			Source: &languagepb.Document_Content{
				Content: text,
			},
			Type: languagepb.Document_PLAIN_TEXT,
		},
	})
	if err != nil {
		return fmt.Errorf("AnalyzeSentiment: %w", err)
	}

	fmt.Fprintf(w, "Text: %s\n", text)
	fmt.Fprintf(w, "Sentiment score: %v\n", res.DocumentSentiment.Score)
	fmt.Fprintln(w, "Successfully authenticated using the API key.")

	return nil
}

Node.js

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.


const {
  v1: {LanguageServiceClient},
} = require('@google-cloud/language');

/**
 * Authenticates with an API key for Google Language service.
 *
 * @param {string} apiKey An API Key to use
 */
async function authenticateWithAPIKey(apiKey) {
  const language = new LanguageServiceClient({apiKey});

  // Alternatively:
  // const {GoogleAuth} = require('google-auth-library');
  // const auth = new GoogleAuth({apiKey});
  // const language = new LanguageServiceClient({auth});

  const text = 'Hello, world!';

  const [response] = await language.analyzeSentiment({
    document: {
      content: text,
      type: 'PLAIN_TEXT',
    },
  });

  console.log(`Text: ${text}`);
  console.log(
    `Sentiment: ${response.documentSentiment.score}, ${response.documentSentiment.magnitude}`,
  );
  console.log('Successfully authenticated using the API key');
}

authenticateWithAPIKey();

Python

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.


from google.cloud import language_v1


def authenticate_with_api_key(api_key_string: str) -> None:
    """
    Authenticates with an API key for Google Language service.

    TODO(Developer): Replace this variable before running the sample.

    Args:
        api_key_string: The API key to authenticate to the service.
    """

    # Initialize the Language Service client and set the API key
    client = language_v1.LanguageServiceClient(
        client_options={"api_key": api_key_string}
    )

    text = "Hello, world!"
    document = language_v1.Document(
        content=text, type_=language_v1.Document.Type.PLAIN_TEXT
    )

    # Make a request to analyze the sentiment of the text.
    sentiment = client.analyze_sentiment(
        request={"document": document}
    ).document_sentiment

    print(f"Text: {text}")
    print(f"Sentiment: {sentiment.score}, {sentiment.magnitude}")
    print("Successfully authenticated using the API key")

Ruby

כדי להריץ את הדוגמה הזו, צריך להתקין את ספריית הלקוח של שפה טבעית.

require "googleauth"
require "google/cloud/language/v1"

def authenticate_with_api_key api_key_string
  # Authenticates with an API key for Google Language service.
  #
  # TODO(Developer): Uncomment the following line and set the value before running this sample.
  #
  # api_key_string = "mykey12345"
  #
  # Note: You can also set the API key via environment variable:
  #   export GOOGLE_API_KEY=your-api-key
  # and use Google::Auth::APIKeyCredentials.from_env method to load it.
  # Example:
  #   credentials = Google::Auth::APIKeyCredentials.from_env
  #   if credentials.nil?
  #     puts "No API key found in environment"
  #     exit
  #   end

  # Initialize API key credentials using the class factory method
  credentials = Google::Auth::APIKeyCredentials.make_creds api_key: api_key_string

  # Initialize the Language Service client with the API key credentials
  client = Google::Cloud::Language::V1::LanguageService::Client.new do |config|
    config.credentials = credentials
  end

  # Create a document to analyze
  text = "Hello, world!"
  document = {
    content: text,
    type: :PLAIN_TEXT
  }

  # Make a request to analyze the sentiment of the text
  sentiment = client.analyze_sentiment(document: document).document_sentiment

  puts "Text: #{text}"
  puts "Sentiment: #{sentiment.score}, #{sentiment.magnitude}"
  puts "Successfully authenticated using the API key"
end

בזמן השימוש במפתחות API באפליקציות שלכם, צריך לוודא שהן מאובטחות במהלך האחסון ובמהלך ההעברה. חשיפת מפתחות ה-API באופן ציבורי עלולה לגרום לחיובים לא צפויים בחשבון שלכם. מידע נוסף זמין במאמר שיטות מומלצות לניהול מפתחות API.

דרישות אבטחה כשמשתמשים בהגדרות של פרטי כניסה ממקור חיצוני

בדרך כלל, יוצרים הגדרות של פרטי כניסה באמצעות פקודות של ה-CLI של gcloud או באמצעות Google Cloud המסוף. לדוגמה, אפשר להשתמש ב-CLI של gcloud כדי ליצור קובץ ADC מקומי או קובץ הגדרות כניסה. באופן דומה, אפשר להשתמש במסוף Google Cloud כדי ליצור מפתח של חשבון שירות ולהוריד אותו.

עם זאת, בחלק ממקרי השימוש, ישויות חיצוניות מספקות לכם הגדרות של פרטי כניסה, וההגדרות האלה מיועדות לאימות מול Google APIs.

חלק מהסוגים של הגדרות פרטי כניסה כוללים נקודות קצה ונתיבי קבצים, שספריות האימות משתמשות בהם כדי לקבל אסימון. כשמאשרים הגדרות של פרטי כניסה ממקור חיצוני, צריך לאמת את ההגדרה לפני שמשתמשים בה. אם לא מאמתים את ההגדרה, גורם זדוני עלול להשתמש בהרשאה כדי לפגוע במערכות ובנתונים שלכם.

אימות הגדרות של פרטי כניסה ממקורות חיצוניים

האופן שבו צריך לאמת את פרטי הכניסה החיצוניים תלוי בסוגי פרטי הכניסה שהאפליקציה מקבלת.

אימות מפתחות של חשבונות שירות

אם האפליקציה מקבלת רק מפתחות של חשבונות שירות, צריך להשתמש בטוען פרטי כניסה שספציפי למפתחות של חשבונות שירות, כמו בדוגמאות הבאות. רכיב טעינת האישורים הספציפי לסוג מנתח רק את השדות שקיימים במפתחות של חשבונות שירות, שלא חושפים נקודות חולשה.

C#‎

var saCredential = CredentialFactory.FromStream<ServiceAccountCredential>(stream);

C++‎

auto cred = google::cloud::MakeServiceAccountCredentials(json)

Java

ServiceAccountCredentials credentials =
      ServiceAccountCredentials.fromStream(credentialsStream);

Node.js

const keys = JSON.parse(json_input)
const authClient = JWT.fromJSON(keys);

PHP

$cred = new Google\Auth\Credentials\ServiceAccountCredentials($scope, $jsonKey);

Python

cred = service_account.Credentials.from_service_account_info(json_data)

Ruby

creds = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: json_stream)

אם אי אפשר להשתמש בטוען פרטי כניסה ספציפי לסוג, צריך לאמת את פרטי הכניסה על ידי אישור שהערך בשדה type הוא service_account. אם הערך בשדה type הוא ערך אחר, אל תשתמשו במפתח של חשבון השירות.

אימות הגדרות אישיות אחרות של פרטי הכניסה

אם האפליקציה שלכם מקבלת כל סוג של פרטי כניסה מלבד מפתח של חשבון שירות, אתם צריכים לבצע אימות נוסף. דוגמאות לסוגים אחרים של הגדרות פרטי כניסה כוללות קובצי פרטי כניסה של ADC, קובצי פרטי כניסה של איחוד שירותי אימות הזהות של עומסי עבודה או קובצי הגדרות כניסה של איחוד שירותי אימות הזהות של כוח עבודה.

בטבלה הבאה מפורטים השדות שצריך לאמת, אם הם מופיעים בפרטי הכניסה. לא כל השדות האלה מופיעים בכל תצורות האישורים.

שדה מטרה הערך הצפוי
service_account_impersonation_url ספריות האימות משתמשות בשדה הזה כדי לגשת לנקודת קצה וליצור אסימון גישה לחשבון השירות שאליו מתחזים. https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service account email:generateAccessToken
token_url ספריות האימות שולחות אסימון חיצוני לנקודת הקצה הזו כדי להמיר אותו לאסימון גישה מאוחד. https://sts.googleapis.com/v1/token
credential_source.file ספריות האימות קוראות אסימון חיצוני מהקובץ במיקום שצוין בשדה הזה ושולחות אותו לנקודת הקצה token_url. הנתיב לקובץ שמכיל טוקן חיצוני. הנתיב הזה אמור להיות מוכר לכם.
credential_source.url נקודת קצה שמחזירה אסימון חיצוני. ספריות האימות שולחות בקשה לכתובת ה-URL הזו ושולחות את התגובה לנקודת הקצה token_url.

אחד מהפריטים הבאים:

  • נקודת קצה מוכרת שספק שירותי הענן מספק.
  • נקודת קצה שהגדרתם במפורש כדי לספק אסימונים.
credential_source.executable.command אם משתנה הסביבה GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES מוגדר ל-1, ספריות האימות מריצות את הפקודה הזו או את קובץ ההפעלה הזה. קובץ הפעלה או פקודה שמחזירים טוקן חיצוני. צריך לזהות את הפקודה הזו ולוודא שהיא בטוחה.
credential_source.aws.url ספריות האימות שולחות בקשה לכתובת ה-URL הזו כדי לאחזר אסימון אבטחה של AWS.

אחד מהערכים הבאים:

  • http://169.254.169.254/latest/meta-data/iam/security-credentials
  • http://[fd00:ec2::254]/latest/meta-data/iam/security-credentials
credential_source.aws.region_url ספריות האימות שולחות בקשה לכתובת ה-URL הזו כדי לאחזר את אזור AWS הפעיל.

אחד מהערכים הבאים:

  • http://169.254.169.254/latest/meta-data/placement/availability-zone
  • http://[fd00:ec2::254]/latest/meta-data/placement/availability-zone
credential_source.aws.imdsv2_session_token_url ספריות האימות שולחות בקשה לכתובת ה-URL הזו כדי לאחזר את אסימון הסשן של AWS.

אחד מהערכים הבאים:

  • http://169.254.169.254/latest/api/token
  • http://[fd00:ec2::254]/latest/api/token

המאמרים הבאים