Partilhar via


Usando a Instrumentação de Gerenciamento do Windows para Diagnóstico

O Windows Communication Foundation (WCF) expõe dados de inspeção de um serviço em tempo de execução por meio de um provedor WMI (Instrumentação de Gerenciamento do Windows) do WCF.

Habilitando o WMI

WMI é a implementação da Microsoft do padrão Web-Based Enterprise Management (WBEM). Para obter mais informações sobre o SDK do WMI, consulte Instrumentação de gerenciamento do Windows. O WBEM é um padrão do setor para como os aplicativos expõem a instrumentação de gerenciamento a ferramentas de gerenciamento externas.

Um provedor WMI é um componente que expõe a instrumentação em tempo de execução por meio de uma interface compatível com WBEM. Ele consiste em um conjunto de objetos WMI que têm pares atributo/valor. Os pares podem ser de vários tipos simples. As ferramentas de gerenciamento podem se conectar aos serviços através da interface em tempo de execução. O WCF expõe atributos de serviços como endereços, associações, comportamentos e ouvintes.

O provedor WMI interno pode ser ativado no arquivo de configuração do aplicativo. Isso é feito por meio wmiProviderEnabled do atributo do diagnóstico> na seção system.serviceModel>, conforme mostrado na< configuração de <exemplo a seguir.

<system.serviceModel>  
    …  
    <diagnostics wmiProviderEnabled="true" />  
    …  
</system.serviceModel>  

Esta entrada de configuração expõe uma interface WMI. As aplicações de gestão podem agora ligar-se através desta interface e aceder à instrumentação de gestão da aplicação.

Acessando dados WMI

Os dados WMI podem ser acessados de muitas maneiras diferentes. A Microsoft fornece APIs WMI para scripts, aplicativos Visual Basic, aplicativos C++ e o .NET Framework. Para obter mais informações, consulte Usando WMI.

Atenção

Se você usar os métodos fornecidos pelo .NET Framework para acessar programaticamente dados WMI, você deve estar ciente de que esses métodos podem gerar exceções quando a conexão é estabelecida. A conexão não é estabelecida durante a ManagementObject construção da instância, mas no primeiro pedido envolvendo a troca de dados real. Portanto, você deve usar um try..catch bloco para capturar as possíveis exceções.

Você pode alterar o nível de rastreamento e log de mensagens, bem como as opções de log de mensagens para a fonte de System.ServiceModel rastreamento no WMI. Isso pode ser feito acessando a instância AppDomainInfo, que expõe essas propriedades booleanas: LogMessagesAtServiceLevel, , LogMessagesAtTransportLevelLogMalformedMessagese TraceLevel. Portanto, se você configurar um ouvinte de rastreamento para log de mensagens, mas definir essas opções como false em configuração, poderá alterá-las posteriormente para true quando o aplicativo estiver em execução. Isso permitirá efetivamente o registro de mensagens em tempo de execução. Da mesma forma, se você habilitar o log de mensagens em seu arquivo de configuração, poderá desativá-lo em tempo de execução usando WMI.

Você deve estar ciente de que, se nenhum ouvinte de rastreamento de log de mensagens para registro de mensagens ou nenhum System.ServiceModel ouvinte de rastreamento para rastreamento for especificado no arquivo de configuração, nenhuma de suas alterações entrará em vigor, mesmo que as alterações sejam aceitas pelo WMI. Para obter mais informações sobre como configurar corretamente os respetivos ouvintes, consulte Configurando o log de mensagens e Configurando o rastreamento. O nível de rastreamento de todas as outras fontes de rastreamento especificadas pela configuração é efetivo quando o aplicativo é iniciado e não pode ser alterado.

WCF expõe um GetOperationCounterInstanceName método para scripting. Esse método retorna um nome de instância do contador de desempenho se você fornecer a ele um nome de operação. No entanto, não valida a sua entrada. Portanto, se você fornecer um nome de operação incorreto, um nome de contador incorreto será retornado.

A OutgoingChannel propriedade da instância não conta canais abertos por um serviço para se conectar a outro serviço, se o cliente WCF para o serviço de Service destino não for criado dentro do Service método.

Cuidado WMI suporta apenas um TimeSpan valor de até 3 pontos decimais. Por exemplo, se o serviço definir uma de suas propriedades como MaxValue, seu valor será truncado após 3 casas decimais quando visualizado por meio do WMI.

Segurança

Como o provedor WMI do WCF permite a descoberta de serviços em um ambiente, você deve ter extrema cautela ao conceder acesso a ele. Se você relaxar o acesso padrão somente de administrador, poderá permitir que partes menos confiáveis acessem dados confidenciais em seu ambiente. Especificamente, se você afrouxar as permissões no acesso WMI remoto, ataques de inundação podem ocorrer. Se um processo for inundado por solicitações WMI excessivas, seu desempenho poderá ser degradado.

Além disso, se você relaxar as permissões de acesso para o arquivo MOF, as partes menos confiáveis poderão manipular o comportamento do WMI e alterar os objetos carregados no esquema WMI. Por exemplo, os campos podem ser removidos de forma que os dados críticos sejam ocultados do administrador ou que os campos que não preenchem ou causam exceções sejam adicionados ao arquivo.

Por padrão, o provedor WMI do WCF concede permissão de "método de execução", "gravação de provedor" e "habilitar conta" para Administrador e permissão de "habilitar conta" para ASP.NET, Serviço Local e Serviço de Rede. Em particular, em plataformas que não sejam do Windows Vista, a conta ASP.NET tem acesso de leitura ao namespace ServiceModel do WMI. Se não quiser conceder esses privilégios a um grupo de usuários específico, desative o provedor WMI (ele está desabilitado por padrão) ou desabilite o acesso para o grupo de usuários específico.

Além disso, quando você tenta habilitar o WMI por meio da configuração, o WMI pode não ser habilitado devido ao privilégio de usuário insuficiente. No entanto, nenhum evento é gravado no log de eventos para registrar essa falha.

Para modificar os níveis de privilégio do usuário, use as etapas a seguir.

  1. Clique em Iniciar e, em seguida, em Executar e digite compmgmt.msc.

  2. Clique com o botão direito do mouse em Serviços e Controles WMI/Aplicativo/para selecionar Propriedades.

  3. Selecione a guia Segurança e navegue até o namespace Root/ServiceModel . Clique no botão Segurança .

  4. Selecione o grupo ou usuário específico que você deseja controlar o acesso e use a caixa de seleção Permitir ou Negar para configurar permissões.

Concedendo permissões de registro WMI do WCF a usuários adicionais

O WCF expõe dados de gerenciamento ao WMI. Ele faz isso hospedando um provedor WMI em processo, às vezes chamado de "provedor dissociado". Para que os dados de gerenciamento sejam expostos, a conta que registra esse provedor deve ter as permissões apropriadas. No Windows, apenas um pequeno conjunto de contas privilegiadas pode registrar provedores dissociados por padrão. Isso é um problema porque os usuários geralmente desejam expor dados WMI de um serviço WCF em execução em uma conta que não está no conjunto padrão.

Para fornecer esse acesso, um administrador deve conceder as seguintes permissões à conta adicional na seguinte ordem:

  1. Permissão para acessar o namespace WMI do WCF.

  2. Permissão para registrar o provedor WMI desacoplado do WCF.

Para conceder permissão de acesso ao namespace WMI

  1. Execute o seguinte script do PowerShell.

    write-host ""  
    write-host "Granting Access to root/servicemodel WMI namespace to built in users group"  
    write-host ""  
    
    # Create the binary representation of the permissions to grant in SDDL  
    $newPermissions = "O:BAG:BAD:P(A;CI;CCDCLCSWRPWPRCWD;;;BA)(A;CI;CC;;;NS)(A;CI;CC;;;LS)(A;CI;CC;;;BU)"  
    $converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper  
    $binarySD = $converter.SDDLToBinarySD($newPermissions)  
    $convertedPermissions = ,$binarySD.BinarySD  
    
    # Get the object used to set the permissions  
    $security = gwmi -namespace root/servicemodel -class __SystemSecurity  
    
    # Get and output the current settings  
    $binarySD = @($null)  
    $result = $security.PsBase.InvokeMethod("GetSD",$binarySD)  
    
    $outsddl = $converter.BinarySDToSDDL($binarySD[0])  
    write-host "Previous ACL: "$outsddl.SDDL  
    
    # Change the Access Control List (ACL) using SDDL  
    $result = $security.PsBase.InvokeMethod("SetSD",$convertedPermissions)
    
    # Get and output the current settings  
    $binarySD = @($null)  
    $result = $security.PsBase.InvokeMethod("GetSD",$binarySD)  
    
    $outsddl = $converter.BinarySDToSDDL($binarySD[0])  
    write-host "New ACL:      "$outsddl.SDDL  
    write-host ""  
    

    Esse script do PowerShell usa SDDL (Security Descriptor Definition Language) para conceder ao grupo Usuários Internos acesso ao namespace WMI "root/servicemodel". Especifica as seguintes ACLs:

    • Built-In Administrator (BA) - Já tinha acesso.

    • Serviço de rede (NS) - já tinha acesso.

    • Sistema Local (LS) - já tinha acesso.

    • Usuários internos - O grupo ao qual conceder acesso.

Para conceder acesso ao registro do provedor

  1. Execute o seguinte script do PowerShell.

    write-host ""  
    write-host "Granting WCF provider registration access to built in users group"  
    write-host ""  
    # Set security on ServiceModel provider  
    $provider = get-WmiObject -namespace "root\servicemodel" __Win32Provider  
    
    write-host "Previous ACL: "$provider.SecurityDescriptor  
    $result = $provider.SecurityDescriptor = "O:BUG:BUD:(A;;0x1;;;BA)(A;;0x1;;;NS)(A;;0x1;;;LS)(A;;0x1;;;BU)"  
    
    # Commit the changes and display it to the console  
    $result = $provider.Put()  
    write-host "New ACL:      "$provider.SecurityDescriptor  
    write-host ""  
    

Concedendo acesso a usuários ou grupos arbitrários

O exemplo nesta seção concede privilégios de registro do Provedor WMI a todos os usuários locais. Se você quiser conceder acesso a um usuário ou grupo que não esteja incorporado, deverá obter o SID (Identificador de Segurança) desse usuário ou grupo. Não há uma maneira simples de obter o SID para um usuário arbitrário. Um método é fazer logon como o usuário desejado e, em seguida, emitir o seguinte comando shell.

Whoami /user  

Para obter mais informações, consulte SIDs bem conhecidos.

Acessando instâncias de objeto WMI remotas

Se você precisar acessar instâncias WMI do WCF em uma máquina remota, deverá habilitar a privacidade de pacotes nas ferramentas usadas para acesso. A seção a seguir descreve como conseguir isso usando o WMI CIM Studio, o Windows Management Instrumentation Tester, bem como o .NET SDK 2.0.

WMI CIM Estúdio

Se você tiver instalado as Ferramentas Administrativas WMI, poderá usar o WMI CIM Studio para acessar instâncias WMI. As ferramentas estão na seguinte pasta:

%windir%\Arquivos de Programas\Ferramentas WMI\

  1. Na janela Conectar ao namespace:, digite root\ServiceModel e clique em OK.

  2. Na janela WMI CIM Studio Login, clique no botão Opções >> para expandir a janela. Selecione Privacidade de pacotes para Nível de autenticação e clique em OK.

Testador de Instrumentação de Gerenciamento do Windows

Esta ferramenta é instalada pelo Windows. Para executá-lo, inicie um console de comando digitando cmd.exe na caixa de diálogo Iniciar/Executar e clique em OK. Em seguida, digite wbemtest.exe na janela de comando. A ferramenta Testador de Instrumentação de Gerenciamento do Windows é então iniciada.

  1. Clique no botão Conectar no canto superior direito da janela.

  2. Na nova janela, digite root\ServiceModel para o campo Namespace e selecione Privacidade de pacotes para Nível de autenticação. Clique em Ligar.

Usando código gerenciado

Você também pode acessar instâncias WMI remotas programaticamente usando classes fornecidas pelo System.Management namespace. O exemplo de código a seguir demonstra como fazer isso.

String wcfNamespace = $@"\\{this.serviceMachineName}\Root\ServiceModel");
  
ConnectionOptions connection = new ConnectionOptions();  
connection.Authentication = AuthenticationLevel.PacketPrivacy;  
ManagementScope scope = new ManagementScope(this.wcfNamespace, connection);