Als Dienstkonto authentifizieren

In diesem Thema wird erklärt, wie Sie eine Anwendung als Dienstkonto authentifizieren können. Allgemeine Informationen zur Authentifizierung bei Google Cloud APIs, einschließlich gängiger Authentifizierungsszenarien und -strategien, finden Sie in der Übersicht zu Authentifizierung. Weitere Informationen zu Dienstkonten finden Sie in der Dokumentation zu Identitäts- und Zugriffsverwaltung unter Dienstkonten.

Anmeldedaten automatisch finden

Wenn Ihre Anwendung in einer Google Cloud-Umgebung mit einem Standarddienstkonto ausgeführt wird, kann die Anwendung die Anmeldedaten des Dienstkontos abrufen, um Google Cloud APIs aufzurufen. Zu diesen Umgebungen gehören Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run und Cloud Functions. Wir empfehlen diese Strategie, da sie praktischer und sicherer ist, als die Anmeldedaten manuell zu übergeben.

Darüber hinaus empfehlen wir die Verwendung von Google Cloud-Clientbibliotheken für Ihre Anwendung. Google Cloud-Clientbibliotheken verwenden eine Bibliothek namens "Standardanmeldedaten für Anwendungen" (Application Default Credentials, ADC), um die Anmeldedaten Ihres Dienstkontos automatisch zu finden. ADC sucht in der folgenden Reihenfolge nach Anmeldedaten für Dienstkonten:

  1. Wenn die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS festgelegt ist, verwendet ADC die Dienstkontodatei, auf die diese Variable verweist.

  2. Wenn die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS nicht festgelegt ist, verwendet ADC das Standarddienstkonto, das von Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run und Cloud Functions bereitgestellt wird.

  3. Wenn die Anmeldedaten weder im ersten noch im zweiten Schritt ermittelt werden können, tritt ein Fehler auf.

Das folgende Codebeispiel zeigt, wie Sie die ADC-Bibliothek in Ihrem Anwendungscode verwenden können:

C#

public object AuthImplicit(string projectId)
{
    // If you don't specify credentials when constructing the client, the
    // client library will look for credentials in the environment.
    var credential = GoogleCredential.GetApplicationDefault();
    var storage = StorageClient.Create(credential);
    // Make an authenticated API request.
    var buckets = storage.ListBuckets(projectId);
    foreach (var bucket in buckets)
    {
        Console.WriteLine(bucket.Name);
    }
    return null;
}

Go


// implicit uses Application Default Credentials to authenticate.
func implicit() {
	ctx := context.Background()

	// For API packages whose import path is starting with "cloud.google.com/go",
	// such as cloud.google.com/go/storage in this case, if there are no credentials
	// provided, the client library will look for credentials in the environment.
	storageClient, err := storage.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}

	it := storageClient.Buckets(ctx, "project-id")
	for {
		bucketAttrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(bucketAttrs.Name)
	}

	// For packages whose import path is starting with "google.golang.org/api",
	// such as google.golang.org/api/cloudkms/v1, use NewService to create the client.
	kmsService, err := cloudkms.NewService(ctx)
	if err != nil {
		log.Fatal(err)
	}

	_ = kmsService
}

Java

static void authImplicit() {
  // If you don't specify credentials when constructing the client, the client library will
  // look for credentials via the environment variable GOOGLE_APPLICATION_CREDENTIALS.
  Storage storage = StorageOptions.getDefaultInstance().getService();

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

Node.js

// Imports the Google Cloud client library.
const {Storage} = require('@google-cloud/storage');

// Instantiates a client. If you don't specify credentials when constructing
// the client, the client library will look for credentials in the
// environment.
const storage = new Storage();
// Makes an authenticated API request.
async function listBuckets() {
  try {
    const results = await storage.getBuckets();

    const [buckets] = results;

    console.log('Buckets:');
    buckets.forEach((bucket) => {
      console.log(bucket.name);
    });
  } catch (err) {
    console.error('ERROR:', err);
  }
}
listBuckets();

PHP

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

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

def implicit():
    from google.cloud import storage

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    storage_client = storage.Client()

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"

require "google/cloud/storage"

# If you don't specify credentials when constructing the client, the client
# library will look for credentials in the environment.
storage = Google::Cloud::Storage.new project: project_id

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

Anmeldedaten manuell übergeben

Wenn Ihre Anwendung außerhalb von Google Cloud-Umgebungen ausgeführt wird, die ein Standarddienstkonto bereitstellen, müssen Sie manuell eines erstellen. Anschließend können Sie einen oder mehrere Dienstkontoschlüssel erstellen. Das sind dem Dienstkonto zugeordnete Anmeldedaten. Die Dienstkontoschlüssel können dann manuell an Ihre Anwendung übergeben werden.

Dienstkonto erstellen

In den folgenden Schritten wird beschrieben, wie Sie ein Dienstkonto erstellen, wenn Sie noch keines haben:

Cloud Console

  1. Wechseln Sie in der Cloud Console zur Seite Dienstkontoschlüssel erstellen.

    Zur Seite "Dienstkontoschlüssel erstellen"
  2. Wählen Sie aus der Liste Dienstkonto die Option Neues Dienstkonto aus.
  3. Geben Sie im Feld Dienstkontoname einen Namen ein.
  4. Wählen Sie in der Liste Rolle die Option Projekt > Inhaber aus.

    Hinweis: Über das Feld Rolle wird Ihr Dienstkonto für den Zugriff auf Ressourcen autorisiert. Sie können dieses Feld später in der Cloud Console aufrufen und ändern. Wenn Sie eine Produktionsanwendung entwickeln, müssen Sie detailliertere Berechtigungen als Projekt > Inhaber angeben. Weitere Informationen finden Sie unter Dienstkonten Rollen zuweisen.
  5. Klicken Sie auf Erstellen. Eine JSON-Datei mit Ihrem Schlüssel wird auf Ihren Computer heruntergeladen.

Befehlszeile

Sie können die folgenden Befehle mithilfe des Cloud SDK auf Ihrem lokalen Computer oder in Cloud Shell ausführen.

  1. Erstellen Sie das Dienstkonto. Ersetzen Sie [NAME] mit einem Namen für das Dienstkonto.

    gcloud iam service-accounts create [NAME]
  2. Gewähren Sie dem Dienstkonto Berechtigungen. Geben Sie für [PROJECT_ID] Ihre Projekt-ID an.

    gcloud projects add-iam-policy-binding [PROJECT_ID] --member "serviceAccount:[NAME]@[PROJECT_ID].iam.gserviceaccount.com" --role "roles/owner"
    Hinweis: Über das Feld Rolle wird Ihr Dienstkonto für den Zugriff auf Ressourcen autorisiert. Sie können dieses Feld später in der Cloud Console ansehen und ändern. Wenn Sie eine Produktionsanwendung entwickeln, müssen Sie detailliertere Berechtigungen als Projekt > Inhaber festlegen. Weitere Informationen finden Sie unter Dienstkonten Rollen zuweisen.
  3. Erstellen Sie die Schlüsseldatei. Geben Sie für [FILE_NAME] einen Namen für die Schlüsseldatei an.

    gcloud iam service-accounts keys create [FILE_NAME].json --iam-account [NAME]@[PROJECT_ID].iam.gserviceaccount.com

Anmeldedaten mit einer Umgebungsvariable übergeben

Die Anmeldedaten zur Authentifizierung für Ihren Anwendungscode geben Sie durch Festlegung der Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS an. Geben Sie für [PATH] den Dateipfad der JSON-Datei an, die Ihren Dienstkontoschlüssel enthält. Diese Variable gilt nur für Ihre aktuelle Shell-Sitzung. Wenn Sie eine neue Sitzung öffnen, müssen Sie die Variable neu festlegen.

Linux oder macOS

export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"

Beispiel:

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json"

Windows

Mit PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="[PATH]"

Beispiel:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\my-key.json"

Mit Eingabeaufforderung:

set GOOGLE_APPLICATION_CREDENTIALS=[PATH]

Nachdem Sie die oben genannten Schritte ausgeführt haben, kann Standardanmeldedaten für Anwendungen Ihre Anmeldedaten automatisch finden. Dies wurde im Abschnitt oben beschrieben. Wir empfehlen die Verwendung von Standardanmeldedaten für Anwendungen, da es weniger Codeeingaben erfordert und der Code in verschiedene Umgebungen portierbar ist.

Anmeldedaten mithilfe von Code übergeben

Alternativ können Sie im Code explizit auf Ihre Dienstkontodatei verweisen. Dies wird im folgenden Beispiel gezeigt. Für das folgende Beispiel müssen Sie die Cloud Storage-Clientbibliothek installieren.

C#

        // Some APIs, like Storage, accept a credential in their Create()
        // method.
        public object AuthExplicit(string projectId, string jsonPath)
        {
            // Explicitly use service account credentials by specifying
            // the private key file.
            var credential = GoogleCredential.FromFile(jsonPath);
            var storage = StorageClient.Create(credential);
            // Make an authenticated API request.
            var buckets = storage.ListBuckets(projectId);
            foreach (var bucket in buckets)
            {
                Console.WriteLine(bucket.Name);
            }
            return null;
        }
        // Other APIs, like Language, accept a channel in their Create()
        // method.
        public object AuthExplicit(string projectId, string jsonPath)
        {
            LanguageServiceClientBuilder builder = new LanguageServiceClientBuilder
            {
                CredentialsPath = jsonPath
            };

            LanguageServiceClient client = builder.Build();
            AnalyzeSentiment(client);
            return 0;
        }

Go


// explicit reads credentials from the specified path.
func explicit(jsonPath, projectID string) {
	ctx := context.Background()
	client, err := storage.NewClient(ctx, option.WithCredentialsFile(jsonPath))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Buckets:")
	it := client.Buckets(ctx, projectID)
	for {
		battrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(battrs.Name)
	}
}

Java

static void authExplicit(String jsonPath) throws IOException {
  // You can specify a credential file by providing a path to GoogleCredentials.
  // Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment variable.
  GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(jsonPath))
        .createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
  Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();

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

Node.js

// Imports the Google Cloud client library.
const {Storage} = require('@google-cloud/storage');

// Instantiates a client. Explicitly use service account credentials by
// specifying the private key file. All clients in google-cloud-node have this
// helper, see https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/docs/authentication.md
// const projectId = 'project-id'
// const keyFilename = '/path/to/keyfile.json'
const storage = new Storage({projectId, keyFilename});

// Makes an authenticated API request.
async function listBuckets() {
  try {
    const [buckets] = await storage.getBuckets();

    console.log('Buckets:');
    buckets.forEach((bucket) => {
      console.log(bucket.name);
    });
  } catch (err) {
    console.error('ERROR:', err);
  }
}
listBuckets();

PHP

namespace Google\Cloud\Samples\Auth;

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

function auth_cloud_explicit($projectId, $serviceAccountPath)
{
    # Explicitly use service account credentials by specifying the private key
    # file.
    $config = [
        'keyFilePath' => $serviceAccountPath,
        'projectId' => $projectId,
    ];
    $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

def explicit():
    from google.cloud import storage

    # Explicitly use service account credentials by specifying the private key
    # file.
    storage_client = storage.Client.from_service_account_json(
        'service_account.json')

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"
# key_file   = "path/to/service-account.json"
require "google/cloud/storage"

# Explicitly use service account credentials by specifying the private key
# file.
storage = Google::Cloud::Storage.new project: project_id, keyfile: key_file

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

Best Practices für die Verwaltung von Anmeldedaten

Anmeldedaten gewähren Zugriff auf sensible Daten. Mit den folgenden Vorgehensweisen können Sie Ihre Anmeldedaten vor unberechtigtem Zugriff schützen.

  • Betten Sie keine Schlüssel für die Authentifizierung in den Quellcode ein, z. B. API-Schlüssel, OAuth-Tokens und Dienstkontoschlüssel. Verwenden Sie dafür eine Umgebungsvariable, die auf Anmeldedaten außerhalb des Quellcodes der Anwendung verweist, beispielsweise im Cloud Key Management Service.

  • Erstellen und verwenden Sie in verschiedenen Kontexten, z. B. in Test- und Produktionsumgebungen, unterschiedliche Anmeldedaten.

  • Übertragen Sie Anmeldedaten ausschließlich über einen sicheren Kanal wie HTTPS, um zu verhindern, dass Dritte Ihre Anmeldedaten abfangen. Übertragen Sie Anmeldedaten niemals im Klartext oder als Teil der URL.

  • Betten Sie niemals langlebige Anmeldedaten in Ihre clientseitige Anwendung ein. Beispielsweise dürfen Anmeldedaten eines Dienstkontos nicht in eine mobile App eingebettet werden. Clientseitige Anwendungen können ausgewertet und Anmeldedaten auf einfache Weise von Dritten ermittelt sowie angewendet werden.

  • Widerrufen Sie ein Token, wenn Sie es nicht mehr benötigen.

API-Fehler beheben

Weitere Informationen über die Fehlerbehandlung bei fehlgeschlagenen Anfragen in Fehlerbehebung für Cloud-APIs.

Weitere Informationen