Controla el acceso a un trabajo con una cuenta de servicio personalizada

En este documento, se explica cómo especificar la configuración cuenta de servicio, lo que influye en la recursos y aplicaciones a los que pueden acceder las VMs de un trabajo. Si no especificas una cuenta de servicio personalizada, las tareas usarán de forma predeterminada la cuenta de servicio predeterminada de Compute Engine, que se adjunta automáticamente a todas las VMs de un proyecto. Por lo tanto, Usar una cuenta de servicio personalizada proporciona un mayor control en la administración de los permisos de un trabajo y se recomienda y las prácticas recomendadas para limitar privilegios.

Obtén más información sobre la cuenta de servicio de un trabajo.

Antes de comenzar

  1. Si nunca usaste Batch, revisa Comienza a usar Batch y habilitar Batch completando el requisitos previos para los proyectos y usuarios.
  2. Si quieres obtener los permisos que necesitas para controlar el acceso a los trabajos con cuentas de servicio personalizadas, sigue estos pasos: solicita a tu administrador que te otorgue el los siguientes roles de IAM:

    Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

    También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

  3. Identifica la cuenta de servicio que quieres usar para este trabajo. Asegúrate de que esta cuenta de servicio tiene todos los permisos necesarios para ejecutar tu trabajo.

    Obtén más información sobre visualizar cuentas de servicio y los permisos necesarios para la cuenta de servicio de un trabajo.

Crea un trabajo que use una cuenta de servicio personalizada

Para crear un trabajo que use una cuenta de servicio personalizada, selecciona una de las siguientes opciones: métodos:

  • Especifica la cuenta de servicio personalizada en la definición de tu trabajo, como se muestra en esta sección.
  • Usa un Plantilla de instancia de Compute Engine y especificar la cuenta de servicio personalizada en la plantilla de instancias y en la definición del trabajo.

En esta sección, se proporciona un ejemplo para crear un trabajo que use una cuenta de servicio personalizada. Puedes crear un trabajo que use una cuenta de servicio personalizada con con gcloud CLI, la API de Batch, Java o Python.

gcloud

Para crear un trabajo que use una cuenta de servicio personalizada con la gcloud CLI, usa el comando gcloud batch jobs submit y especificar la cuenta de servicio personalizada en el archivo de configuración del trabajo.

Por ejemplo, para crear un trabajo de secuencia de comandos que usa una cuenta de servicio personalizada, haz lo siguiente:

  1. Crea un archivo JSON en el directorio actual llamado hello-world-service-account.json con el siguiente contenido:

    {
        "taskGroups": [
            {
                "taskSpec": {
                    "runnables": [
                        {
                            "script": {
                                "text": "echo Hello World! This is task $BATCH_TASK_INDEX."
                            }
                        }
                    ]
                }
            }
        ],
        "allocationPolicy": {
            "serviceAccount": {
                "email": "SERVICE_ACCOUNT_EMAIL"
            }
        }
    }
    

    En el ejemplo anterior, SERVICE_ACCOUNT_EMAIL es la dirección de correo electrónico de la cuenta de servicio. Si no se especifica el campo serviceAccount, el valor se establece en la cuenta de servicio predeterminada de Compute Engine.

  2. Ejecuta el siguiente comando:

    gcloud batch jobs submit example-service-account-job \
      --location us-central1 \
      --config hello-world-service-account.json
    

API

Para crear un trabajo que use una cuenta de servicio personalizada con la Batch, usa el Método jobs.create y especifica tu cuenta de servicio personalizada en el campo allocationPolicy.

Por ejemplo, para crear un trabajo de secuencia de comandos que use una cuenta de servicio personalizada, crea la siguiente solicitud:

POST https://batch.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/jobs?job_id=example-service-account-job

{
    "taskGroups": [
        {
            "taskSpec": {
                "runnables": [
                    {
                        "script": {
                            "text": "echo Hello World! This is task $BATCH_TASK_INDEX."
                        }
                    }
                ]
            }
        }
    ],
    "allocationPolicy": {
        "serviceAccount": {
            "email": "SERVICE_ACCOUNT_EMAIL"
        }
    }
}

Reemplaza lo siguiente:

Java


import com.google.cloud.batch.v1.AllocationPolicy;
import com.google.cloud.batch.v1.BatchServiceClient;
import com.google.cloud.batch.v1.CreateJobRequest;
import com.google.cloud.batch.v1.Job;
import com.google.cloud.batch.v1.LogsPolicy;
import com.google.cloud.batch.v1.LogsPolicy.Destination;
import com.google.cloud.batch.v1.Runnable;
import com.google.cloud.batch.v1.Runnable.Script;
import com.google.cloud.batch.v1.ServiceAccount;
import com.google.cloud.batch.v1.TaskGroup;
import com.google.cloud.batch.v1.TaskSpec;
import com.google.protobuf.Duration;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateBatchUsingServiceAccount {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the region you want to use to run the job. Regions that are
    // available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
    String region = "europe-central2";
    // The name of the job that will be created.
    // It needs to be unique for each project and region pair.
    String jobName = "JOB_NAME";
    // The email address of your service account.
    String serviceAccountEmail = "EMAIL";

    createBatchUsingServiceAccount(projectId, region, jobName, serviceAccountEmail);
  }

  // Create a job that uses a custom service account
  public static Job createBatchUsingServiceAccount(String projectId, String region, String jobName,
                                                   String serviceAccountEmail)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (BatchServiceClient batchServiceClient = BatchServiceClient.create()) {
      // Define what will be done as part of the job.
      Runnable runnable =
          Runnable.newBuilder()
              .setScript(
                  Script.newBuilder()
                      .setText(
                          "echo Hello world! This is task ${BATCH_TASK_INDEX}. "
                                  + "This job has a total of ${BATCH_TASK_COUNT} tasks.")
                      // You can also run a script from a file. Just remember, that needs to be a
                      // script that's already on the VM that will be running the job.
                      // Using setText() and setPath() is mutually exclusive.
                      // .setPath("/tmp/test.sh")
                      .build())
              .build();

      TaskSpec task = TaskSpec.newBuilder()
              // Jobs can be divided into tasks. In this case, we have only one task.
              .addRunnables(runnable)
              .setMaxRetryCount(2)
              .setMaxRunDuration(Duration.newBuilder().setSeconds(3600).build())
              .build();

      // Tasks are grouped inside a job using TaskGroups.
      // Currently, it's possible to have only one task group.
      TaskGroup taskGroup = TaskGroup.newBuilder()
          .setTaskCount(3)
          .setParallelism(1)
          .setTaskSpec(task)
          .build();

      ServiceAccount.Builder serviceAccount = ServiceAccount.newBuilder();

      // If the serviceAccount field is not specified,
      // the value is set to the default Compute Engine service account.
      if (serviceAccountEmail != null) {
        serviceAccount.setEmail(serviceAccountEmail);
      }

      // Attach service account that VMs will run as.
      AllocationPolicy allocationPolicy = AllocationPolicy.newBuilder()
              .setServiceAccount(serviceAccount)
              .build();

      Job job =
          Job.newBuilder()
              .addTaskGroups(taskGroup)
              .setAllocationPolicy(allocationPolicy)
              .putLabels("env", "testing")
              .putLabels("type", "script")
              // We use Cloud Logging as it's an out of the box available option.
              .setLogsPolicy(
                  LogsPolicy.newBuilder().setDestination(Destination.CLOUD_LOGGING))
              .build();

      CreateJobRequest createJobRequest =
          CreateJobRequest.newBuilder()
              // The job's parent is the region in which the job will run.
              .setParent(String.format("projects/%s/locations/%s", projectId, region))
              .setJob(job)
              .setJobId(jobName)
              .build();

      Job result =
          batchServiceClient
              .createJobCallable()
              .futureCall(createJobRequest)
              .get(5, TimeUnit.MINUTES);

      System.out.printf("Successfully created the job: %s", result.getName());

      return result;
    }
  }
}

Python

from google.cloud import batch_v1


def create_with_custom_service_account_job(
    project_id: str, region: str, job_name: str, service_account_email: str
) -> batch_v1.Job:
    """
    This method shows how to create a sample Batch Job that will run
    a simple command on Cloud Compute instances with custom service account.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        region: name of the region you want to use to run the job. Regions that are
            available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
        job_name: the name of the job that will be created.
            It needs to be unique for each project and region pair.
        service_account_email: custom service account email

    Returns:
        A job object representing the job created.
    """
    client = batch_v1.BatchServiceClient()

    # Define what will be done as part of the job.
    task = batch_v1.TaskSpec()
    runnable = batch_v1.Runnable()
    runnable.script = batch_v1.Runnable.Script()
    runnable.script.text = "echo Hello world! from task ${BATCH_TASK_INDEX}. This job has a total of ${BATCH_TASK_COUNT} tasks."
    task.runnables = [runnable]
    task.max_retry_count = 2
    task.max_run_duration = "3600s"

    # Tasks are grouped inside a job using TaskGroups.
    # Currently, it's possible to have only one task group.
    group = batch_v1.TaskGroup()
    group.task_count = 4
    group.task_spec = task

    # Policies are used to define on what kind of virtual machines the tasks will run on.
    # Read more about local disks here: https://cloud.google.com/compute/docs/disks/persistent-disks
    policy = batch_v1.AllocationPolicy.InstancePolicy()
    policy.machine_type = "e2-standard-4"
    instances = batch_v1.AllocationPolicy.InstancePolicyOrTemplate()
    instances.policy = policy
    allocation_policy = batch_v1.AllocationPolicy()
    allocation_policy.instances = [instances]

    # Defines the service account for Batch-created VMs. If omitted, the [default account]
    # More details: https://cloud.google.com/compute/docs/access/service-accounts#default_service_account
    service_account = batch_v1.ServiceAccount()
    service_account.email = service_account_email
    allocation_policy.service_account = service_account

    job = batch_v1.Job()
    job.task_groups = [group]
    job.allocation_policy = allocation_policy
    job.labels = {"env": "testing", "type": "script"}

    create_request = batch_v1.CreateJobRequest()
    create_request.job = job
    create_request.job_id = job_name
    # The job's parent is the region in which the job will run
    create_request.parent = f"projects/{project_id}/locations/{region}"

    return client.create_job(create_request)

¿Qué sigue?