Executar tarefas em contas de utilizador no Batch

Nota

As contas de utilizador abordadas neste artigo são diferentes das contas de utilizador utilizadas para o Protocolo RDP (Remote Desktop Protocol) ou Secure Shell (SSH), por motivos de segurança.

Para ligar a um nó com a configuração da máquina virtual do Linux através de SSH, veja Instalar e configurar xrdp para utilizar o Ambiente de Trabalho Remoto com o Ubuntu. Para ligar a nós com o Windows através de RDP, veja Como ligar e iniciar sessão numa máquina virtual do Azure com o Windows.

Para ligar a um nó que executa o através de RDP, veja Ativar a Ligação ao Ambiente de Trabalho Remoto para uma Função no Azure Serviços Cloud.

Uma tarefa no Azure Batch é sempre executada numa conta de utilizador. Por predefinição, as tarefas são executadas em contas de utilizador padrão, sem permissões de administrador. Para determinados cenários, poderá querer configurar a conta de utilizador na qual pretende executar uma tarefa. Este artigo aborda os tipos de contas de utilizador e como configurá-las para o seu cenário.

Tipos de contas de utilizador

Azure Batch fornece dois tipos de contas de utilizador para executar tarefas:

  • Contas de utilizador automático. As contas de utilizador automático são contas de utilizador incorporadas que são criadas automaticamente pelo serviço Batch. Por predefinição, as tarefas são executadas numa conta de utilizador automático. Pode configurar a especificação do utilizador automático para uma tarefa para indicar em que conta de utilizador automático uma tarefa deve ser executada. A especificação do utilizador automático permite-lhe especificar o nível de elevação e o âmbito da conta de utilizador automático que irá executar a tarefa.

  • Uma conta de utilizador com nome. Pode especificar uma ou mais contas de utilizador nomeadas para um conjunto quando criar o conjunto. Cada conta de utilizador é criada em cada nó do conjunto. Além do nome da conta, especifique a palavra-passe da conta de utilizador, o nível de elevação e, para conjuntos linux, a chave privada SSH. Quando adiciona uma tarefa, pode especificar a conta de utilizador com nome na qual essa tarefa deve ser executada.

Importante

A versão do serviço Batch 2017-01-01.4.0 introduziu uma alteração interruptória que requer que atualize o código para chamar essa versão ou posterior. Consulte Atualizar o código para a biblioteca de cliente do Batch mais recente para obter diretrizes rápidas para atualizar o código do Batch a partir de uma versão mais antiga.

Acesso da conta de utilizador a ficheiros e diretórios

Tanto uma conta de utilizador automático como uma conta de utilizador com nome têm acesso de leitura/escrita ao diretório de trabalho da tarefa, diretório partilhado e diretório de tarefas de várias instâncias. Ambos os tipos de contas têm acesso de leitura aos diretórios de preparação de tarefas e de arranque.

Se uma tarefa for executada na mesma conta que foi utilizada para executar uma tarefa inicial, a tarefa tem acesso de leitura-escrita ao diretório de tarefas de início. Da mesma forma, se uma tarefa for executada na mesma conta que foi utilizada para executar uma tarefa de preparação de tarefas, a tarefa tem acesso de leitura-escrita ao diretório de tarefas de preparação de tarefas. Se uma tarefa for executada numa conta diferente da tarefa inicial ou da tarefa de preparação de tarefas, a tarefa só tem acesso de leitura ao respetivo diretório.

Para obter mais informações sobre como aceder a ficheiros e diretórios a partir de uma tarefa, consulte Ficheiros e diretórios.

Acesso elevado para tarefas

O nível de elevação da conta de utilizador indica se uma tarefa é executada com acesso elevado. Tanto uma conta de utilizador automático como uma conta de utilizador com nome podem ser executadas com acesso elevado. As duas opções para o nível de elevação são:

  • NonAdmin: A tarefa é executada como um utilizador padrão sem acesso elevado. O nível de elevação predefinido para uma conta de utilizador do Batch é sempre NonAdmin.
  • Administração: a tarefa é executada como um utilizador com acesso elevado e funciona com permissões de Administrador completas.

Contas de utilizador automático

Por predefinição, as tarefas são executadas no Batch numa conta de utilizador automático, como um utilizador padrão sem acesso elevado e com o âmbito do conjunto. O âmbito do conjunto significa que a tarefa é executada numa conta de utilizador automático que está disponível para qualquer tarefa no conjunto. Para obter mais informações sobre o âmbito do conjunto, veja Executar uma tarefa como um utilizador automático com o âmbito do conjunto.

A alternativa ao âmbito do conjunto é o âmbito da tarefa. Quando a especificação do utilizador automático está configurada para o âmbito da tarefa, o serviço Batch cria uma conta de utilizador automático apenas para essa tarefa.

Existem quatro configurações possíveis para a especificação do utilizador automático, cada uma das quais corresponde a uma conta de utilizador automático exclusiva:

  • Acesso não administrador com âmbito de tarefa
  • Administração acesso (elevado) com o âmbito da tarefa
  • Acesso não administrador com âmbito do conjunto
  • Administração acesso com o âmbito do conjunto

Importante

As tarefas em execução no âmbito da tarefa não têm acesso de facto a outras tarefas num nó. No entanto, um utilizador malicioso com acesso à conta pode contornar esta restrição ao submeter uma tarefa executada com privilégios de administrador e aceder a outros diretórios de tarefas. Um utilizador malicioso também pode utilizar RDP ou SSH para ligar a um nó. É importante proteger o acesso às chaves de conta do Batch para impedir esse cenário. Se suspeitar que a sua conta pode ter sido comprometida, certifique-se de que regenera as chaves.

Executar uma tarefa como um utilizador automático com acesso elevado

Pode configurar a especificação do utilizador automático para privilégios de administrador quando precisar de executar uma tarefa com acesso elevado. Por exemplo, uma tarefa de início pode precisar de acesso elevado para instalar software no nó.

Nota

Utilize o acesso elevado apenas quando necessário. As melhores práticas recomendam a concessão do privilégio mínimo necessário para alcançar o resultado pretendido. Por exemplo, se uma tarefa inicial instalar software para o utilizador atual, em vez de para todos os utilizadores, poderá evitar conceder acesso elevado às tarefas. Pode configurar a especificação do utilizador automático para o âmbito do conjunto e o acesso não administrador para todas as tarefas que precisam de ser executadas na mesma conta, incluindo a tarefa de início.

Os fragmentos de código seguintes mostram como configurar a especificação do utilizador automático. Os exemplos definem o nível de elevação como Admin e o âmbito como Task.

.NET do Batch

task.UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.Admin, scope: AutoUserScope.Task));

Batch Java

taskToAdd.withId(taskId)
        .withUserIdentity(new UserIdentity()
            .withAutoUser(new AutoUserSpecification()
                .withElevationLevel(ElevationLevel.ADMIN))
                .withScope(AutoUserScope.TASK));
        .withCommandLine("cmd /c echo hello");

Batch Python

user = batchmodels.UserIdentity(
    auto_user=batchmodels.AutoUserSpecification(
        elevation_level=batchmodels.ElevationLevel.admin,
        scope=batchmodels.AutoUserScope.task))
task = batchmodels.TaskAddParameter(
    id='task_1',
    command_line='cmd /c "echo hello world"',
    user_identity=user)
batch_client.task.add(job_id=jobid, task=task)

Executar uma tarefa como um utilizador automático com o âmbito do conjunto

Quando um nó é aprovisionado, são criadas duas contas de utilizador automático em todo o conjunto em cada nó do conjunto, uma com acesso elevado e outra sem acesso elevado. Definir o âmbito do utilizador automático para o âmbito do conjunto de uma determinada tarefa executa a tarefa numa destas duas contas de utilizador automático em todo o conjunto.

Quando especifica o âmbito do conjunto para o utilizador automático, todas as tarefas executadas com acesso de administrador são executadas na mesma conta de utilizador automático em todo o conjunto. Da mesma forma, as tarefas executadas sem permissões de administrador também são executadas numa única conta de utilizador automático em todo o conjunto.

Nota

As duas contas de utilizador automático em todo o conjunto são contas separadas. As tarefas em execução na conta administrativa em todo o conjunto não podem partilhar dados com tarefas em execução na conta padrão e vice-versa.

A vantagem de ser executada na mesma conta de utilizador automático é que as tarefas podem partilhar dados com outras tarefas em execução no mesmo nó.

A partilha de segredos entre tarefas é um cenário em que a execução de tarefas numa das duas contas de utilizador automático em todo o conjunto é útil. Por exemplo, suponha que uma tarefa de início precisa de aprovisionar um segredo no nó que outras tarefas podem utilizar. Pode utilizar a API de Proteção de Dados do Windows (DPAPI), mas requer privilégios de administrador. Em vez disso, pode proteger o segredo ao nível do utilizador. As tarefas em execução na mesma conta de utilizador podem aceder ao segredo sem acesso elevado.

Outro cenário em que poderá querer executar tarefas numa conta de utilizador automático com o âmbito do conjunto é uma partilha de ficheiros da Interface de Passagem de Mensagens (MPI). Uma partilha de ficheiros MPI é útil quando os nós na tarefa MPI precisam de trabalhar nos mesmos dados de ficheiro. O nó principal cria uma partilha de ficheiros à qual os nós subordinados podem aceder se estiverem em execução na mesma conta de utilizador automático.

O fragmento de código seguinte define o âmbito do utilizador automático para o âmbito do conjunto de uma tarefa no Batch .NET. O nível de elevação é omitido, pelo que a tarefa é executada na conta de utilizador automático padrão em todo o conjunto.

task.UserIdentity = new UserIdentity(new AutoUserSpecification(scope: AutoUserScope.Pool));

Contas de utilizador nomeadas

Pode definir contas de utilizador com nome quando cria um conjunto. Uma conta de utilizador com nome tem um nome e uma palavra-passe que fornece. Pode especificar o nível de elevação de uma conta de utilizador com nome. Para nós linux, também pode fornecer uma chave privada SSH.

Existe uma conta de utilizador com nome em todos os nós no conjunto e está disponível para todas as tarefas em execução nesses nós. Pode definir qualquer número de utilizadores nomeados para um conjunto. Quando adiciona uma tarefa ou coleção de tarefas, pode especificar que a tarefa é executada numa das contas de utilizador nomeadas definidas no conjunto.

Uma conta de utilizador com nome é útil quando pretende executar todas as tarefas numa tarefa na mesma conta de utilizador, mas isolá-las de tarefas em execução noutros trabalhos ao mesmo tempo. Por exemplo, pode criar um utilizador com nome para cada tarefa e executar as tarefas de cada tarefa nessa conta de utilizador com o nome. Em seguida, cada tarefa pode partilhar um segredo com as suas próprias tarefas, mas não com tarefas em execução noutros trabalhos.

Também pode utilizar uma conta de utilizador com nome para executar uma tarefa que define permissões em recursos externos, como partilhas de ficheiros. Com uma conta de utilizador nomeada, controla a identidade do utilizador e pode utilizar essa identidade de utilizador para definir permissões.

As contas de utilizador com nome ativam o SSH sem palavra-passe entre os nós do Linux. Pode utilizar uma conta de utilizador com nome com nós do Linux que precisam de executar tarefas de várias instâncias. Cada nó no conjunto pode executar tarefas numa conta de utilizador definida em todo o conjunto. Para obter mais informações sobre tarefas de várias instâncias, veja Utilizar tarefas de várias instâncias para executar aplicações MPI.

Criar contas de utilizador nomeadas

Para criar contas de utilizador nomeadas no Batch, adicione uma coleção de contas de utilizador ao conjunto. Os fragmentos de código seguintes mostram como criar contas de utilizador com nome em .NET, Java e Python. Estes fragmentos de código mostram como criar contas nomeadas de administrador e não administrador num conjunto.

Exemplo de .NET do Batch (Windows)

CloudPool pool = null;
Console.WriteLine("Creating pool [{0}]...", poolId);

// Create a pool using Virtual Machine Configuration.
pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: 3,
    virtualMachineSize: "standard_d1_v2",
    VirtualMachineConfiguration: new VirtualMachineConfiguration(
    imageReference: new ImageReference(
                        publisher: "MicrosoftWindowsServer",
                        offer: "WindowsServer",
                        sku: "2019-datacenter-core",
                        version: "latest"),
    nodeAgentSkuId: "batch.node.windows amd64");

// Add named user accounts.
pool.UserAccounts = new List<UserAccount>
{
    new UserAccount("adminUser", "xyz123", ElevationLevel.Admin),
    new UserAccount("nonAdminUser", "123xyz", ElevationLevel.NonAdmin),
};

// Commit the pool.
await pool.CommitAsync();

Exemplo de .NET do Batch (Linux)

CloudPool pool = null;

// Obtain a collection of all available node agent SKUs.
List<NodeAgentSku> nodeAgentSkus =
    batchClient.PoolOperations.ListNodeAgentSkus().ToList();

// Define a delegate specifying properties of the VM image to use.
Func<ImageReference, bool> isUbuntu1804 = imageRef =>
    imageRef.Publisher == "Canonical" &&
    imageRef.Offer == "UbuntuServer" &&
    imageRef.Sku.Contains("20.04-LTS");

// Obtain the first node agent SKU in the collection that matches
// Ubuntu Server 20.04.
NodeAgentSku ubuntuAgentSku = nodeAgentSkus.First(sku =>
    sku.VerifiedImageReferences.Any(isUbuntu2004));

// Select an ImageReference from those available for node agent.
ImageReference imageReference =
    ubuntuAgentSku.VerifiedImageReferences.First(isUbuntu2004);

// Create the virtual machine configuration to use to create the pool.
VirtualMachineConfiguration virtualMachineConfiguration =
    new VirtualMachineConfiguration(imageReference, ubuntuAgentSku.Id);

Console.WriteLine("Creating pool [{0}]...", poolId);

// Create the unbound pool.
pool = batchClient.PoolOperations.CreatePool(
    poolId: poolId,
    targetDedicatedComputeNodes: 3,
    virtualMachineSize: "Standard_A1",
    virtualMachineConfiguration: virtualMachineConfiguration);
// Add named user accounts.
pool.UserAccounts = new List<UserAccount>
{
    new UserAccount(
        name: "adminUser",
        password: "xyz123",
        elevationLevel: ElevationLevel.Admin,
        linuxUserConfiguration: new LinuxUserConfiguration(
            uid: 12345,
            gid: 98765,
            sshPrivateKey: new Guid().ToString()
            )),
    new UserAccount(
        name: "nonAdminUser",
        password: "123xyz",
        elevationLevel: ElevationLevel.NonAdmin,
        linuxUserConfiguration: new LinuxUserConfiguration(
            uid: 45678,
            gid: 98765,
            sshPrivateKey: new Guid().ToString()
            )),
};

// Commit the pool.
await pool.CommitAsync();

Exemplo de Java do Batch

List<UserAccount> userList = new ArrayList<>();
userList.add(new UserAccount().withName(adminUserAccountName).withPassword(adminPassword).withElevationLevel(ElevationLevel.ADMIN));
userList.add(new UserAccount().withName(nonAdminUserAccountName).withPassword(nonAdminPassword).withElevationLevel(ElevationLevel.NONADMIN));
PoolAddParameter addParameter = new PoolAddParameter()
        .withId(poolId)
        .withTargetDedicatedNodes(POOL_VM_COUNT)
        .withVmSize(POOL_VM_SIZE)
        .withVirtualMachineConfiguration(configuration)
        .withUserAccounts(userList);
batchClient.poolOperations().createPool(addParameter);

Exemplo do Batch Python

users = [
    batchmodels.UserAccount(
        name='pool-admin',
        password='******',
        elevation_level=batchmodels.ElevationLevel.admin)
    batchmodels.UserAccount(
        name='pool-nonadmin',
        password='******',
        elevation_level=batchmodels.ElevationLevel.non_admin)
]
pool = batchmodels.PoolAddParameter(
    id=pool_id,
    user_accounts=users,
    virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
        image_reference=image_ref_to_use,
        node_agent_sku_id=sku_to_use),
    vm_size=vm_size,
    target_dedicated=vm_count)
batch_client.pool.add(pool)

Executar uma tarefa numa conta de utilizador com nome com acesso elevado

Para executar uma tarefa como um utilizador elevado, defina a propriedade UserIdentity da tarefa para uma conta de utilizador nomeada que foi criada com a respetiva propriedade ElevationLevel definida como Admin.

Este fragmento de código especifica que a tarefa deve ser executada numa conta de utilizador com nome. Esta conta de utilizador com o nome foi definida no conjunto quando o conjunto foi criado. Neste caso, a conta de utilizador nomeada foi criada com permissões de administrador:

CloudTask task = new CloudTask("1", "cmd.exe /c echo 1");
task.UserIdentity = new UserIdentity(AdminUserAccountName);

Atualizar o código para a biblioteca de cliente do Batch mais recente

A versão do serviço Batch 2017-01-01.4.0 introduziu uma alteração interruptiva, substituindo a propriedade runElevated disponível em versões anteriores pela propriedade userIdentity . As tabelas seguintes fornecem um mapeamento simples que pode utilizar para atualizar o código a partir de versões anteriores das bibliotecas de cliente.

.NET do Batch

Se o seu código utilizar... Atualize-o para...
CloudTask.RunElevated = true; CloudTask.UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.Admin));
CloudTask.RunElevated = false; CloudTask.UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.NonAdmin));
CloudTask.RunElevated não especificado Não é necessária nenhuma atualização

Batch Java

Se o seu código utilizar... Atualize-o para...
CloudTask.withRunElevated(true); CloudTask.withUserIdentity(new UserIdentity().withAutoUser(new AutoUserSpecification().withElevationLevel(ElevationLevel.ADMIN));
CloudTask.withRunElevated(false); CloudTask.withUserIdentity(new UserIdentity().withAutoUser(new AutoUserSpecification().withElevationLevel(ElevationLevel.NONADMIN));
CloudTask.withRunElevated não especificado Não é necessária nenhuma atualização

Batch Python

Se o seu código utilizar... Atualize-o para...
run_elevated=True user_identity=user, em que
user = batchmodels.UserIdentity(
     auto_user=batchmodels.AutoUserSpecification(
          elevation_level=batchmodels.ElevationLevel.admin))
run_elevated=False user_identity=user, em que
user = batchmodels.UserIdentity(
     auto_user=batchmodels.AutoUserSpecification(
          elevation_level=batchmodels.ElevationLevel.non_admin))
run_elevated não especificado Não é necessária nenhuma atualização

Passos seguintes