Início > Windows PowerShell > PoSh – Verificando a data e hora em um host remoto

PoSh – Verificando a data e hora em um host remoto

março 4, 2016

Olá pessoALL,

Neste post eu vou falar sobre uma tarefa comum e anual: a verificação de horário em servidores. Mas por que esta tarefa é comum e anual? Como todos nós sabemos, temos anualmente o inicio e termino do horário de versão no Brasil e em outros países ao redor do mundo.

Embora esta situação seja automática e garantida com a aplicação de um KB da Microsoft, ter uma forma de validar que o horário de um ou mais servidores foi alterado realmente é sempre importante para evitar surpresas desagradáveis durante o dia produtivo.

Introdução

Com a chegada e partida do horário de verão todos os anos, ter certeza que sistemas sensíveis a este tipo de evento estejam com sua data e hora atualizadas é uma tarefa imprescindível para garantir que seu ambiente está operando corretamente.

Partindo da premissa de que um ambiente com um número grande de servidores exista neste caso, fazer uma verificação deste nível levaria um tempo consideravelmente grande se feita manualmente, sem contar o tamanho da mão de obra empregada para realizar tal tarefa.

Efetuar o logon em cada servidor para verificar a data e hora pós inicio/término do horário de versão não é uma solução viável dependendo do tamanho do ambiente. Há soluções mais robustas e que permitem um nível de interação com o sistema operacional mínimo, reduzindo o tempo gasto com esta ação.

Com Windows PowerShell é possível conectar a um host remoto para obter a informação de data e hora atual do sistema operacional. Vejamos então como é possível esta ação usando PoSh!.

O cenário

Você foi contratado recentemente para administrar o ambiente de uma grande empresa que possui diversos sistemas críticos sobre vários servidores executando uma versão do Windows Server e recebe o comunicado de que o horário de versão será iniciado/encerrado.

Você é informado que alguns destes sistemas críticos são extremamente sensíveis a alteração de data e hora e que um minuto de atraso na emissão de uma informação pode gerar uma multa para a empresa.

Como o horário produtivo da empresa é de segunda a sexta feira, você tem uma janela no dia de domingo pós inicio/término do horário de verão para fazer uma verificação em sua infraestrutura e garantir que o horário foi alterado corretamente e caso existam servidores onde isso não ocorreu, tomar uma ação corretiva.

No entanto, há uma centena de servidores onde esta verificação precisa ser feita e não há mão de obra suficiente para tal operação no domingo. Você precisa garantir que na segunda feira todos os sistemas críticos tenham a data e hora correta para evitar multas para a empresa.

Como você pode resolver esta demanda de forma rápida, robusta e sem demandar mão de obra desnecessária com ações manuais?

A solução

Primeiramente você precisa entender qual informação você deve obter e como você pode obtê-la. Para obtermos a data e hora em um sistema operacional, seja local ou remotamente, nós podemos contar com o nosso velho amigo WMI e suas classes.

Antes de prosseguirmos, lembre-se que é preciso permitir a conexão via Windows Management Instrumentation através de seu firewall para que as consultas ocorram com sucesso.

Sabendo que o que nós precisamos é WMI, vamos agora falar sobre a sua classe Win32_OperatingSystem. Esta classe possui diversas propriedades relacionadas ao sistema operacional como pode ser visualizado no link anterior, mas em nosso caso, vamos focar em uma propriedade específica: LocalDateTime.

A propriedade LocalDateTime permite consultar a data e hora em um sistema operacional local ou remoto. Como podemos ver na imagem abaixo, a consulta WMI via command let Get-WMIObject retornou o valor da data e hora local do servidor remoto chamado W11001PNOD1:

CheckDateTimeOnRemoteComputer-0001

No entanto, a valor retornado pela propriedade LocalDateTime não é tão amigável quanto uma data e hora formatada por exemplo como 23/02/2016 11:24:00. Pensando em melhorar a visualização desta informação, nós vamos usar um método que está presente em várias classes WMI chamado ConvertoToDateTime.

O método ConvertToDateTime permite que o valor retornado pela propriedade LocalDateTime seja convertido em um formato mais amigável para quem está lendo a informação. Vamos ver então como é possível fazer esta conversão:

CheckDateTimeOnRemoteComputer-0002

Como podemos ver na imagem anterior, após a conversão do valor da propriedade LocalDateTime com o método ConvertToDateTime a leitura da informação se tornou muito mais simples e aproveitando, eu também tornei a saída da consulta mais amigável criando as colunas com nomes de minha escolha, populando-as com as informações que eu desejo.

Continuando nossa abordagem, com o último código na imagem anterior nós já temos como obter a data e hora em um computador remoto, agora, vamos melhorar o código para que a busca pelos nomes dos servidores se torne mais simples.

Para chegarmos a este objetivo eu vou utilizar um command let chamado Get-ADComputer presente no Windows PowerShell Module for Active Directory. Presumindo que você tenha uma estrutura de unidades organizacionais (OU) bem definida, obter o nome dos servidores é algo relativamente simples:

CheckDateTimeOnRemoteComputer-0003

Com uma pesquisa simples através do Active Directory Module for Windows PowerShell é possível retornar a lista de controladores de domínio e sua descrição, por exemplo. No código acima a única coisa que precisa ser alterada para atender a sua estrutura é o DN informado em -SearchBase que neste exemplo é a OU Domain Controllers.

Já temos o que precisamos para obtermos uma lista de servidores no domínio e em seguida verificar a data e hora destes servidores, mas ainda falta consolidar estas soluções para que o resultado seja o que nós precisamos. Então vamos ver como ficará a solução final com a união de ambos os códigos.

CheckDateTimeOnRemoteComputer-0004

Como podemos ver no código acima, eu direcionei a saída da consulta feita no Active Directory para uma variável e através de um laço ForEach, percorri o conteúdo desta variável para executar a consulta WMI da classe Win32_OperatingSystem e retornar uma tabela formatada com as informações que eu desejo.

Em seu estado atual, já podemos obter as informações dos servidores remotamente, mas ainda é possível melhorar as informações que serão entregues após a execução. No que diz respeito a melhorar as informações disponíveis, digamos que eu queira comparar a data atual do servidor remoto com o horário de um computador de referência.

Digamos que este computador de referência seja um Domain Controller ou até mesmo uma estação de trabalho onde o script pode ser executado, desde que as ferramentas administrativas do AD DS e principalmente o Active Directory Modelu for Windows PowerShell que fazem parte do RSAT.

Para chegarmos a este tipo de informação é preciso criar uma condição a ser retornada no momento de construirmos a tabela que já temos. Vejamos como podemos inserir uma condição para substituir a informação retornada pela variável $_.LocalDateTime.

CheckDateTimeOnRemoteComputer-0005

Para criarmos a condição, eu acrescentei uma nova coluna chamada DateNTimeStatus e a esta coluna uma condição que verifica se a data e hora do servidor remoto é inferior a 360 segundos ou 5 minutos. O motivo de verificarmos esta diferença de 5 minutos é um velho conhecido de quem trabalha com AD DS.

Quem trabalha com AD DS sabe muito bem que um horário diferente em um servidor é um detalhe que pode causar muitos problema de autenticação. O motivo da condição verificar se o horário do servidor é inferior a 5 minutos não é para o horário de verão e sim para alertar que você tem um possível problema com este servidor.

Por padrão, a tolerância de diferença de horário para o Kerberos é de 5 minutos, ou seja, qualquer autenticação via Kerberos que tenha o timestamp inferior a 5 minutos se comparado com o horário do Domain Controller não será aceita, pois está ação poderia ser uma tentativa de submeter novamente um ticket interceptado para ganho acesso.

A título de conhecimento, a política de segurança que controla este espaço de tempo permitido entre um membro e o DC tem o nome de Maximum Tolerance for Computer Clock Synchronization e está localizada em Computer Configuration\Windows Settings\Security Settings\Account Policies\Kerberos Policy.

Em resumo, criamos uma condição para auditar se o horário do host está dentro do esperado para que ele funcione corretamente dentro de sua infraestrutura do AD DS.

A solução até aqui apresentada presume que você tenha objetos literalmente ativos em seu domínio, ou seja, não leva em consideração que existam objetos inativos devido a não remoção no momento de decomissionar um servidor. Pensando neste detalhe, vamos inserir uma condição para verificar se o servidor está online ou não.

CheckDateTimeOnRemoteComputer-0006

Na imagem anterior há uma condição que usa o command let Test-Connection para verificar a resposta ao protocolo ICMP do servidor de destino é verdadeiro ou falso. Se for verdadeiro, ele irá fazer a consulta do horário, caso falso, ele prossegue para o próximo servidor.

Ainda pensando em melhorar o código, é importante saber quais servidores não estavam online no momento da verificação para que uma ação posterior seja tomada, então, vamos acrescentar uma forma de obter esta informação inserindo a informação em um arquivo de log.

CheckDateTimeOnRemoteComputer-0007

Na imagem anterior eu inseri uma nova propriedade a ser obtida na consulta no domínio, o DN para termos a localização do objeto no AD DS visto que podem existir diversas OU abaixo da OU base da consulta. Foi usado também o command let Test-Path para verificar se o diretório C:\TEMP existe.

Como o diretório C:\TEMP foi utilizado neste exemplo como local da saída do arquivo de log, é preciso verificar se o mesmo existe antes de criarmos o log. Caso ele não exista, ele será criado. Por fim, usamos uma variável chamada $LogInfo para inserirmos nossa mensagem de erro e o command let Add-Content para criar o arquivo e popularmos com a informação.

No inicio do código existe uma variável que irá receber a data e hora atual formata como dd-MM-yyyy_hh-mm-ss no momento da execução do script para compor o nome do arquivo de log.

Pensando ainda em melhorias, vamos supor que eu não queira que a saída seja feita na janela do Windows PowerShell e que o meu desejo é ter um arquivo CSV que me permita fazer a importação no Microsoft Excel. Isso facilitaria e muito no momento de filtrar as informações que desejamos.

Então vamos tornar isso possível!

CheckDateTimeOnRemoteComputer-0009

E aqui estamos nós! Após criarmos um variável chamada CSVExportData e direcionarmos a saída da consulta WMI para esta variável, ao final nós podemos direcionar seu conteúdo para um arquivo CSV usando o command let Export-CSV permitindo assim que as informações sejam importadas para o Microsoft Excel.

CheckDateTimeOnRemoteComputer-0010

Conclusão

Neste post nós aprendemos como verificar a data e hora em um host remoto comparando esta informação com a data e hora de um host de referência que está com a informação correta. Aprendemos que há questões de segurança relacionadas a diferença entre a data e hora de um host e um Domain Controller que pode interferir na autenticação.

Aprendemos também como melhorar gradualmente nosso script para que ele faça determinadas ações de forma mais amigável e deixo a tarefa de fazer mais melhorias ao cargo de vocês, pois há muito mais para ser feito e tornar o script ainda mais robusto.

Por fim, como caso de uso este tópico permite que após o inicio e término do horário de verão você seja capaz de validar a data e hora em seus servidores evitando surpresas durante seu horário produtivo ao saber que um ou mais sistemas estão retornando a data e hora erradas.

É isso ai pessoal, até o próximo post…

%d blogueiros gostam disto: