Configura la autenticación para aplicaciones de producción de servidor a servidor

En esta guía, se explica cómo configurar la autenticación y la autorización para las aplicaciones de producción de servidor a servidor en las API de Google Cloud. La autenticación hace referencia al proceso de determinar la identidad de un cliente. La autorización hace referencia al proceso de determinar los permisos que un cliente autenticado tiene para un recurso específico. Es decir, la autenticación identifica quién eres, y la autorización determina qué es lo que puedes hacer. Para obtener más información sobre los métodos de autenticación compatibles y cómo elegirlos, consulta Descripción general de la autenticación.

Google usa credenciales para identificar las cuotas y la facturación de tus aplicaciones. Tus credenciales también se usan para autorizar el acceso a las API, los recursos y las funciones de Google Cloud.

Proporciona credenciales para tu aplicación

Encuentra credenciales de forma automática

Para encontrar las credenciales, las bibliotecas cliente de Google Cloud usan una estrategia llamada credenciales predeterminadas de la aplicación (ADC). Si tu código usa una biblioteca cliente, la estrategia comprueba las credenciales en el siguiente orden:

  1. Primero, ADC comprueba si se configuró la variable GOOGLE_APPLICATION_CREDENTIALS del entorno. Si está configurada, ADC usa el archivo de cuenta de servicio al que apunta la variable. En la siguiente sección, se describe cómo configurar la variable de entorno.

  2. Si no se configuró la variable de entorno, ADC usa la cuenta de servicio predeterminada que Compute Engine, Google Kubernetes Engine, Cloud Run, App Engine y Cloud Functions proporcionan para las aplicaciones que se ejecutan en esos servicios.

  3. Se mostrará un error si ADC no puede usar ninguna de las credenciales ya mencionadas.

Esta estrategia se describe en el siguiente ejemplo de código, pero no se especifican las credenciales de la aplicación de forma explícita. Sin embargo, ADC puede encontrar las credenciales de manera implícita solo si configuraste la variable de entorno GOOGLE_APPLICATION_CREDENTIALS o si la aplicación se ejecuta en Compute Engine, GKE, App Engine o Cloud Functions.

Instala la biblioteca cliente de Cloud Storage para ejecutar el siguiente ejemplo.

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

Esta estrategia es útil cuando se realizan pruebas y experimentos, pero puede dificultar saber qué credenciales está usando la aplicación. Recomendamos especificar de forma explícita qué credenciales debe usar la aplicación, como se describe en la siguiente sección.

Obtén y proporciona credenciales de la cuenta de servicio de forma manual

Si desarrollas código de manera local y, además, implementas tu aplicación de manera local o en otra nube pública, puedes crear y obtener las credenciales de la cuenta de servicio de forma manual.

Crea una cuenta de servicio

Mediante los siguientes pasos se describe cómo crear una cuenta de servicio. Sin embargo, en lugar de configurar permisos a nivel de propietario, debes restringir el acceso a los permisos, tal como se describe en la sección Restringe el acceso que se muestra a continuación.

Cloud Console

  1. En Cloud Console, ve a la página Crear una clave de cuenta de servicio.

    Ir a la página Crear clave de la cuenta de servicio
  2. En la lista Cuenta de servicio, selecciona Cuenta de servicio nueva.
  3. Ingresa un nombre en el campo Nombre de cuenta de servicio.
  4. En la lista Función, selecciona Proyecto > Propietario.

    Nota: El campo Función autoriza tu cuenta de servicio para acceder a los recursos. Puedes ver y cambiar este campo más adelante mediante Cloud Console. Si desarrollas una app de producción, especifica permisos más detallados que Proyecto > Propietario. Para obtener más información, consulta Cómo otorgar funciones a las cuentas de servicio.
  5. Haz clic en Crear. Se descargará un archivo JSON que contiene tus claves a tu computadora.

Línea de comandos

Puedes ejecutar los siguientes comandos mediante el SDK de Cloud en tu máquina local o en Cloud Shell.

  1. Crea la cuenta de servicio. Reemplaza [NAME] por un nombre para la cuenta de servicio.

    gcloud iam service-accounts create [NAME]
  2. Otorga permisos a la cuenta de servicio. Reemplaza [PROJECT_ID] por el ID del proyecto.

    gcloud projects add-iam-policy-binding [PROJECT_ID] --member "serviceAccount:[NAME]@[PROJECT_ID].iam.gserviceaccount.com" --role "roles/owner"
    Nota: El campo Función autoriza a la cuenta de servicio a acceder a los recursos. Puedes ver y cambiar este campo más adelante mediante Cloud Console. Si desarrollas una app de producción, especifica permisos más detallados que Proyecto > Propietario. Para obtener más información, consulta Otorga funciones a las cuentas de servicio.
  3. Genera el archivo de claves. Reemplaza [FILE_NAME] por un nombre para el archivo de claves.

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

Proporciona credenciales de la cuenta de servicio

Tienes dos opciones para proporcionar las credenciales a tu aplicación después de crear una cuenta de servicio. Puedes configurar la variable de entorno GOOGLE_APPLICATION_CREDENTIALS de manera explícita o pasar la ruta a la clave de la cuenta de servicio en el código.

Configura la variable de entorno

Configura la variable de entorno GOOGLE_APPLICATION_CREDENTIALS para proporcionar credenciales de autenticación al código de la aplicación. Reemplaza [PATH] por la ruta de acceso del archivo JSON que contiene la clave de tu cuenta de servicio. Esta variable solo se aplica a la sesión actual de shell. Por lo tanto, si abres una sesión nueva, deberás volver a configurar la variable.

Linux o macOS

export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"

Por ejemplo:

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

Windows

Con PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="[PATH]"

Por ejemplo:

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

Con el símbolo del sistema:

set GOOGLE_APPLICATION_CREDENTIALS=[PATH]

Cuando completes los pasos anteriores, ADC podrá determinar las credenciales de forma implícita, tal como se describió en la sección anterior Proporciona credenciales para tu aplicación. Recomendamos usar este método porque requiere menos código. Además, cuando usas la variable de entorno, tu código es más portátil porque puedes ejecutar el mismo código en varios entornos con diferentes cuentas de servicio.

Pasa la ruta a la clave de la cuenta de servicio en el código

También puedes usar el código para apuntar de forma explícita hacia el archivo de la cuenta de servicio, como se muestra en el siguiente ejemplo de código.

Instala la biblioteca cliente de Cloud Storage para ejecutar el siguiente ejemplo.

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

Obtén credenciales en Compute Engine, Kubernetes Engine, el entorno flexible de App Engine y Cloud Functions

Si la aplicación se ejecuta en Compute Engine, GKE, el entorno flexible de App Engine o Cloud Functions, no es necesario que crees tu propia cuenta de servicio. Compute Engine incluye una cuenta de servicio predeterminada que se crea de forma automática, y puedes asignar una cuenta de servicio diferente para cada instancia, si es necesario. Cuando creas una instancia nueva, esta se habilita de manera automática para ejecutarse como la cuenta de servicio predeterminada y tiene un conjunto predeterminado de permisos de autorización. Para obtener más información, consulta Cuenta de servicio predeterminada de Compute Engine.

Después de configurar una cuenta de servicio, ADC encuentra las credenciales de manera implícita sin necesidad de cambiar el código, tal como se describió en la sección anterior. Si quieres usar credenciales de Compute Engine, puedes hacerlo de forma explícita tal como se muestra en el siguiente código de ejemplo.

Instala la biblioteca cliente de Cloud Storage para ejecutar el siguiente ejemplo.

C#

        // Some APIs, like Storage, accept a credential in their Create()
        // method.
        public object AuthExplicitComputeEngine(string projectId)
        {
            // Explicitly request service account credentials from the compute
            // engine instance.
            GoogleCredential credential =
                GoogleCredential.FromComputeCredential();
            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 AuthExplicitComputeEngine(string projectId)
        {
            LanguageServiceClientBuilder builder = new LanguageServiceClientBuilder
            {
                ChannelCredentials = GoogleCredential
                .FromComputeCredential()
                .ToChannelCredentials()
            };

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

Go


// explicitDefault finds the default credentials.
//
// It is very uncommon to need to explicitly get the default credentials in Go.
// Most of the time, client libraries can use Application Default Credentials
// without having to pass the credentials in directly. See implicit above.
func explicitDefault(projectID string) {
	ctx := context.Background()

	creds, err := google.FindDefaultCredentials(ctx, storage.ScopeReadOnly)
	if err != nil {
		log.Fatal(err)
	}
	client, err := storage.NewClient(ctx, option.WithCredentials(creds))
	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 authCompute() {
  // Explicitly request service account credentials from the compute engine instance.
  GoogleCredentials credentials = ComputeEngineCredentials.create();
  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

'use strict';

const {auth, Compute} = require('google-auth-library');

/**
 * This example directly instantiates a Compute client to acquire credentials.
 * Generally, you wouldn't directly create this class, rather call the
 * `auth.getClient()` method to automatically obtain credentials.
 */
async function main() {
  const client = new Compute({
    // Specifying the serviceAccountEmail is optional. It will use the default
    // service account if one is not defined.
    serviceAccountEmail: 'some-service-account@example.com',
  });
  const projectId = await auth.getProjectId();
  const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`;
  const res = await client.request({url});
  console.log(res.data);
}

main().catch(console.error);

PHP

namespace Google\Cloud\Samples\Auth;

// Imports GCECredentials and the Cloud Storage client library.
use Google\Auth\Credentials\GCECredentials;
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit_compute_engine($projectId)
{
    $gceCredentials = new GCECredentials();
    $config = [
        'projectId' => $projectId,
        'credentialsFetcher' => $gceCredentials,
    ];
    $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_compute_engine(project):
    from google.auth import compute_engine
    from google.cloud import storage

    # Explicitly use Compute Engine credentials. These credentials are
    # available on Compute Engine, App Engine Flexible, and Container Engine.
    credentials = compute_engine.Credentials()

    # Create the client using the credentials and specifying a project ID.
    storage_client = storage.Client(credentials=credentials, project=project)

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

Ruby

require "googleauth"
require "google/cloud/env"
require "google/cloud/storage"

# Explicitly use Compute Engine credentials and a project ID to create a new
# Cloud Storage client. These credentials are available on Compute Engine,
# App Engine Flexible, and Container Engine.
storage = Google::Cloud::Storage.new project: Google::Cloud.env.project_id,
                                     keyfile: Google::Auth::GCECredentials.new

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

Obtén credenciales en el entorno estándar de App Engine

Puedes usar la API de App Identity de App Engine para obtener credenciales si tu aplicación se ejecuta en el entorno estándar de App Engine.

Después de configurar una cuenta de servicio, ADC encuentra las credenciales de manera implícita sin necesidad de cambiar el código, tal como se describió en la sección anterior. Si quieres usar credenciales de App Engine, puedes hacerlo de forma explícita tal como se muestra en el siguiente código de ejemplo.

Instala la biblioteca cliente de Cloud Storage para ejecutar el siguiente ejemplo.

PHP

namespace Google\Cloud\Samples\Auth;

// Imports AppIdentityCredentials and the Cloud Storage client library.
use Google\Auth\Credentials\AppIdentityCredentials;
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit_app_engine($projectId)
{
    # Learn more about scopes at https://cloud.google.com/storage/docs/authentication#oauth-scopes
    $scope = 'https://www.googleapis.com/auth/devstorage.read_only';
    $gaeCredentials = new AppIdentityCredentials($scope);
    $config = [
        'projectId' => $projectId,
        'credentialsFetcher' => $gaeCredentials,
    ];
    $storage = new StorageClient($config);

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

Go


// explicitDefault finds the default credentials.
//
// It is very uncommon to need to explicitly get the default credentials in Go.
// Most of the time, client libraries can use Application Default Credentials
// without having to pass the credentials in directly. See implicit above.
func explicitDefault(projectID string) {
	ctx := context.Background()

	creds, err := google.FindDefaultCredentials(ctx, storage.ScopeReadOnly)
	if err != nil {
		log.Fatal(err)
	}
	client, err := storage.NewClient(ctx, option.WithCredentials(creds))
	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 authAppEngineStandard() throws IOException {
  // Explicitly request service account credentials from the app engine standard instance.
  GoogleCredentials credentials = AppEngineCredentials.getApplicationDefault();
  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());
  }
}

Python

def explicit_app_engine(project):
    from google.auth import app_engine
    import googleapiclient.discovery

    # Explicitly use App Engine credentials. These credentials are
    # only available when running on App Engine Standard.
    credentials = app_engine.Credentials()

    # Explicitly pass the credentials to the client library.
    storage_client = googleapiclient.discovery.build(
        'storage', 'v1', credentials=credentials)

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

Restringe el acceso

Solo debes otorgar a tu aplicación los permisos de autorización que necesita para interactuar con las API, las funciones o los recursos correspondientes de Google Cloud. Google Cloud usa Cloud Identity and Access Management (Cloud IAM) para el control de acceso. Cuando creas una cuenta de servicio, puedes elegir una función de IAM para limitar el acceso. En la explicación que aparece en Comienza a usar la autenticación, se indica que debes elegir la función Owner cuando creas una cuenta de servicio. El valor se puede cambiar en cualquier momento. Para obtener más información, consulta Asigna funciones a cuentas de servicio.

Recomendaciones para administrar las credenciales

Las credenciales permiten acceder a datos sensibles. Con las siguientes prácticas, podrás proteger el acceso a estos recursos.

  • No incorpores secretos relacionados con la autenticación en el código fuente, como claves de API, tokens de OAuth y credenciales de cuentas de servicio. Puedes usar una variable de entorno que apunte hacia las credenciales externas al código fuente de la aplicación, como Cloud Key Management Service.

  • Usa credenciales distintas para contextos diferentes, como en entornos de pruebas y de producción.

  • Solo transfiere las credenciales mediante HTTPS para evitar que las puedan intervenir terceros. Nunca las transfieras en texto claro o como parte de una URL.

  • Nunca incorpores credenciales de larga duración en la aplicación del cliente. Por ejemplo, no incorpores credenciales de cuenta de servicio en una aplicación para dispositivos móviles. Las aplicaciones del cliente se pueden examinar y un tercero puede encontrar y usar fácilmente las credenciales.

  • Revoca los token que ya no necesites.

Solución de problemas de API

Revisa la sección sobre errores de las API de Cloud para obtener más información sobre cómo solucionar problemas de las solicitudes a la API con errores.

Próximos pasos