Partilhar via


Proteger um serviço agenciado

Os serviços agenciados têm como padrão estar disponível apenas para o usuário local e para os processos envolvidos na sessão do Visual Studio que o ativou. Sob esses padrões, as considerações de segurança para serviços agenciados não são diferentes de outros códigos em execução nesses processos, que incluem:

  • De uma perspectiva de modelo de ameaça, as extensões executadas no processo do Visual Studio são consideradas totalmente confiáveis. As extensões que ficam fora do processo devem tratar as chamadas de serviço do Visual Studio como cruzando um limite de confiança.
  • Seu código deve validar argumentos em pontos de entrada para confirmar que eles se enquadram em padrões/intervalos esperados.
  • Ao ler dados do disco, considere que os dados podem ter sido adulterados.
  • Ao receber dados de uma rede ou da Internet, seja cauteloso ao analisar ou desserializar os dados para evitar vulnerabilidades comuns.

Várias considerações críticas de segurança adicionais se aplicam quando o serviço é registrado com o ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients sinalizador definido. O restante deste artigo concentra-se nessas considerações.

Verificações de autorização para operações confidenciais

Adquirindo o serviço de autorização

Seu serviço agenciado deve ter um construtor que usa um AuthorizationServiceClient como parâmetro. O argumento deve ser armazenado em um campo e descartado no método do Dispose() serviço.

class Calculator : ICalculator, IDisposable
{
    private readonly AuthorizationServiceClient authorizationService;

    internal Calculator(AuthorizationServiceClient authorizationService)
    {
        this.authorizationService = authorizationService;
    }

    public void Dispose()
    {
        this.authorizationService.Dispose();
    }
}

A fábrica de serviços que você oferece muda ligeiramente para oferecer suporte a esse novo parâmetro. Em vez de fornecer um para o IBrokeredServiceContainer.Proffer método, forneça um BrokeredServiceFactoryAuthorizingBrokeredServiceFactory delegado. Este delegado recebe o que você precisará passar para o AuthorizationServiceClient seu serviço intermediado.

Essa alteração no seu código proffer pode ter a seguinte aparência:

 container.Proffer(
     CalculatorService,
-    (moniker, options, serviceBroker, cancellationToken) => new ValueTask<object?>(new CalculatorService()));
+    (moniker, options, serviceBroker, authorizationService, cancellationToken) => new ValueTask<object?>(new CalculatorService(authorizationService)));

Usando o serviço de autorização

Qualquer operação que possa divulgar informações confidenciais ou alterar o estado do usuário deve ser verificada com o serviço de autorização usando AuthorizationServiceClient.AuthorizeOrThrowAsynco .

Para afirmar que o chamador é o proprietário do código (a mesma identidade que o operador do host Live Share), esse código pode ser usado:

private static readonly ProtectedOperation ClientIsOwner = WellKnownProtectedOperations.CreateClientIsOwner();

public ValueTask ResetOperationCounterAsync(CancellationToken cancellationToken)
{
    // Resetting the counter should only be allowed if the user is the owner.
    await this.authorizationService.AuthorizeOrThrowAsync(ClientIsOwner, cancellationToken);

    // Proceed with the operation.
    this.operationCounter = 0;
}

Vários outros níveis de WellKnownProtectedOperations autorização são definidos na classe.

Todas as verificações de autorização são sempre aprovadas quando o cliente de serviço está sendo executado na mesma máquina e conta de usuário. Todos eles também são aprovados para um convidado do Live Share que esteja operando na mesma conta da Microsoft que o host.

Quando a operação solicitada não for autorizada, AuthorizeOrThrowAsync lançará um UnauthorizedAccessExceptionarquivo . O host Live Share pode notificar o proprietário da tentativa com falha, dando ao host a chance de conceder a permissão necessária para concluir a operação se a ProtectedOperation for reconhecida para que uma tentativa subsequente no cliente possa ser bem-sucedida.

O AuthorizationServiceClient armazena em cache todas as verificações de autorização localmente para que as verificações de autorização repetidas sejam rápidas. Caso o conjunto de permissões de um usuário seja alterado (por exemplo, o host do Live Share altera as permissões para o convidado), o cache local é liberado automaticamente.

Consumindo outros serviços intermediados

Quando um serviço agenciado em si requer acesso a outro serviço agenciado, ele deve usar o IServiceBroker que é fornecido à sua fábrica de serviços. Ele não deve usar o agente de serviço global, pois ele não está ciente do contexto dessa instância de serviço agenciada específica e da autorização que seu cliente tem para ativar e invocar outro comportamento.

Se nosso serviço de calculadora tivesse necessidade de outros serviços intermediados para implementar seu comportamento, modificaríamos o construtor para aceitar um IServiceBroker:

internal class Calculator : ICalculator
{
    private readonly IServiceBroker serviceBroker;
    private readonly AuthorizationServiceClient authorizationService;

    internal class Calculator(IServiceBroker serviceBroker, AuthorizationServiceClient authorizationService)
    {
        this.serviceBroker = serviceBroker;
        this.authorizationService = authorizationService;
    }
}

Esse parâmetro adicional afetará o código de oferta do service factory:

 container.Proffer(
     CalculatorService,
     (moniker, options, serviceBroker, authorizationService, cancellationToken)
-        => new ValueTask<object?>(new CalculatorService(authorizationService)));
+        => new ValueTask<object?>(new CalculatorService(serviceBroker, authorizationService)));

Disponibilidade limitada do serviço agenciado

Quando o cliente do seu serviço intermediado é um convidado do Live Share (em uma conta diferente do proprietário do Host), seu agente de serviço contextual só ativará outros serviços intermediados que também definiram o AllowTransitiveGuestClients sinalizador como uma precaução de segurança. As tentativas de ativar um serviço intermediado não qualificado lançarão um UnauthorizedAccessExceptionarquivo .

Se o seu serviço agenciado requer outro serviço agenciado que não possui o sinalizador, você pode usar o agente de serviço global para obtê-lo, mas deve considerar que os serviços intermediados obtidos a partir dele não têm ideia de que um convidado não confiável é o AllowTransitiveGuestClients cliente final. Você deve seguir todas as mesmas precauções dadas na próxima seção sobre como chamar outros serviços VS ou outras APIs.

Leia mais sobre o consumo de serviços intermediados.

Consumindo outros serviços VS ou outras APIs

Chamar serviços padrão do Visual Studio, bibliotecas de terceiros 3 ou APIs padrão do .NET é permitido em serviços agenciados que são expostos a convidados do Live Share, mas essas chamadas devem ser cuidadosamente escritas e todas as entradas validadas primeiro.

Os caminhos de arquivo ou URLs devem ser cuidadosamente verificados para garantir que sejam válidos e estejam dentro dos subcaminhos esperados que o convidado tem autorização para acessar. Por exemplo, se o serviço agenciado permitir a leitura ou gravação em arquivos com base em um caminho, o caminho deverá ser verificado para se enquadrar na solução aberta e se o convidado realmente tem permissões de gravação, se aplicável. Validar caminhos de arquivo corretamente pode ser difícil considerando .. e outros meios para fazer parecer que um caminho começa com o prefixo certo, mas depois escapa do diretório de solução permitido.

Faça uso do AuthorizationServiceClient descrito na seção acima, conforme apropriado, para afirmar que o cliente tem permissão antes de chamar qualquer API que não tenha suas próprias verificações de permissão internas. Somente os serviços agenciados internos do Visual Studio devem conter suas próprias verificações de autorização, e isso depende da aquisição desses serviços agenciados usando o agente de serviços contextual, conforme descrito na seção acima.

Todas as outras APIs, incluindo serviços do Visual Studio não agenciados ou serviços agenciados obtidos com o agente de serviços global, podem ser executadas à medida que você as direciona sem levar em conta o nível de permissão do convidado do Live Share, tornando sua própria verificação de autorização crítica para proteger a segurança do host do Live Share.

Evite expor a funcionalidade do serviço agenciado que outro serviço agenciado do Visual Studio já expõe à medida que aumenta a superfície de ataque.

Estado de compartilhamento entre instâncias de serviço agenciadas

Quando o serviço agenciado requer o estado de compartilhamento entre várias instâncias do serviço, esses dados ficam potencialmente expostos a vários usuários com diversos conjuntos de permissões. Torna-se fundamental para o serviço intermediado proteger esses dados entre esses usuários. Use o modelo STRIDE para ajudar a identificar, classificar e, finalmente, mitigar ameaças.

Você pode decidir tratar seu estado compartilhado como confiável e, portanto, conceder a ele permissão para fazer o que for necessário internamente (por exemplo, acessar serviços VS ou usar o agente de serviços global). Nesse caso, torna-se responsabilidade de uma instância de serviço intermediada individual proteger as chamadas feitas em seu estado compartilhado para garantir que todas as entradas sejam apropriadas, dadas as permissões de seu próprio usuário usando o serviço de autorização.

A Microsoft Threat Modeling Tool pode ser uma ferramenta útil para proteger seu estado compartilhado e seus usuários.