Ansible também trabalha com Windows Server

project

Em algumas ocasiões, temos a necessidade em atender requisitos de projetos que temos necessidade de realizar instalações e configurações em servidores Windows Server.

Com isso, o Ansible, recentemente comprado pela Red Hat, realiza seu papel muito bem dentro do cinturão de ferramentas da cultura DevOps.

Suponhamos que o Terraform já construiu todo seu planejamento de rede e deixou disponível e operante um servidor Windows Server 2016 na cloud de preferência.

Disponibilizando o Windows Remote Management

Sabemos que o Ansible executa suas instruções se comunicando com protocolo SSH em servidores Linux, porém em Windows Server a Microsoft pensou e projetou seu próprio gerenciador de servidores como descrevem em sua documentação oficial como WinRM, tendo como abreviatura para Windows Remote Management.

Premissa que temos para essa arquitetura de provisionamento IaC a ser executada com sucesso, é execução de um script powershell e algumas instruções com comandos que realiza a instalação e as devidas configurações do WinRM.

A sequência de comandos dentro de um shell no servidor com powershell, para a instalação é o seguinte:

                    
                        

winrm quickconfig

project

                    
                        

winrm enumerate winrm/config/Listener

project

O WinRM faz uso das portas 5985 para o transporte em HTTP e 5986 para HTTPS, onde realiza comunicação e instrumentação das instruções que o Ansible executa no servidor do Windows 2016. Recomendação de segurança é que essas duas portas disponíveis sejam somente abertas para o IP Addresses do destino, o qual será o servidor Windows 2016 em questão, isso evitará que o WinRM esteja totalmente exposto e sofra algum ataque consequentemente, como por exemplo:

https://securethelogs.com/2019/08/30/hacking-windows-remote-management-winrm/

Execute em um shell do powershell o seguinte comando:

PS C:\>

                    
                        

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol= [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-ObjectSystem.Net.WebClient).DownloadString('https://raw.githubusercontent.com/andrebassi/winrm-ansible/main/ConfigureRemotingForAnsible.ps1'))

O script realiza as devidas instalações, tal como inicialização do serviço WinRM e suas configurações locais de firewall e permissões, que foi desenvolvido pela própria Microsoft para rodar em Powershell versão 3.

Recomendamos que esse script seja executado junto ao Terraform, logo após a disponibilização da mesma e também as liberações de firewall para as respectivas portas do WinRM.

Explorando WinRM com Golang

A linguagem go foi criada pelo Google, pensando na produtividade e na programação concorrente, com isso apresentando uma performance muito boa nas ferramentas DevOps, o qual podemos citar o Kubernetes, o qual foi desenvolvido com golang.

Há um tempo atrás, antes do Ansible ter seu surgimento em 2012, houve a necessidade de executar comandos para o Windows Server.

Dessa forma podemos executar comandos de forma remota para o servidor, como por exemplo

                    
                        

./winrm -hostname 89.145.161.169 -username "administrator" -password "secret" "ipconfig /all"

Ao executar o comando acima, e caso retorne o erro:

http response error: 401 - invalid content type

WinRM aguarda autenticação básica para contas locais, portanto devemos executar no servidor Windows Server em Powershell, a sequência de comandos:

                    
                        

winrm set winrm/config/service/Auth '@{Basic="true"}'

winrm set winrm/config/service '@{AllowUnencrypted="true"}'

winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'

Agora, se tentarmos novamente:

                    
                        

./winrm -hostname 89.145.161.169 -username 'administrator' -password secret 'systeminfo | findstr /C:"OS"'

Obteremos com sucesso a resposta e o retorno do comando systeminfo, filtrando somente as informações do SO do Windows Server em questão:

project

Para maiores detalhes do comando em golang do winrm, acesse o github:

https://github.com/andrebassi/winrm-cli

Automatizando real cenário com ansible

Imaginamos no cenário como requisito, onde temos necessidade de instalar um servidor Windows 2016 com IIS (Internet Information Server), que executa uma aplicação em .NET Framework 4.6.1 como por exemplo.

Temos premissa que já tenha ansible e python instalado, onde agora precisamos instalar o módulo win_chocolatey através do seguinte comando:

                    
                        

ansible-galaxy collection install chocolatey.chocolatey

Após o ansible estar com o módulo, vamos definir nosso arquivo hosts como:

project

Simples assim, testamos comunicação com servidor através do WinRM da seguinte forma:

                    
                        

ansible windows -i hosts -m win_ping

Caso ocorrer o erro conhecido do Ansible:

+[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called.

Para mitigar esse problema, é muito simples, basta setar a variável de ambiente

                    
                        

OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

Por exemplo:

                    
                        

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

Porém, estando correto as configurações acima, o ansible executando o comando, o mesmo responderá um pong, condizente que está comunicando sucesso, através do WinRM no seu servidor Windows Server.

project

Agora criamos um arquivo denominado iis.yaml, e definimo ele dessa forma:

project

E então, para a instalação e configuração do IIS, executamos esse playbook ansible da seguinte maneira:

                    
                        

ansible-playbook iis.yaml -i hosts -vvv

Ao executar o playbook, o Ansible instrumenta suas instruções, transformando em comandos no formato de winrs para transportar até o WinRM no servidor, por exemplo alguns trechos do log de sua execução:

Using module file /Users/andrebassi/.ansible/collections/ansible_collections/ansible/windows/plugins/modules/win_feature.ps1 Pipelining is enabled.
ESTABLISH WINRM CONNECTION FOR USER: administrator on PORT 5986 TO 89.145.161.169

Assim que a instalação finalizar com sucesso, podemos checar e validar no servidor usando o comando powershell:

                    
                        

Get-WindowsFeature "web-server"

project

Para a instalação do .NET Framework utilizaremos o módulo instalado anteriormente do win_chocolatey, criando um arquivo denominado dotnet-framework.yaml e inserindo as seguinte instruções:

project

Então executamos o playbook ansible:

                    
                        

ansible-playbook dotnet-framework.yaml -i hosts -v

Ao finalizar com sucesso o Ansible instalará primeiramente o cliente do Chocolatey e então fará a instalação do framework do .NET em questão tendo como retorno de sucesso:

project

Ao finalizar podemos checar no servidor se houve a instalação com o comando choco da seguinte forma:

                    
                        

choco version all

Ou então executar remotamente pelo winrm-cli:

                    
                        

./winrm -hostname 89.145.161.169 -username 'administrator' -password 'gD6iaatffdacnww' 'choco version all"'

Teremos o seguinte retorno com o .NET Framework 4.6 instalado com sucesso:

project

Um verdadeiro orquestrador de apps Windows

Se formos analisar e pensar em uma arquitetura, o Ansible e a execução remota de comandos possibilita a projetar um orquestrador para distribuir seus binários dos aplicativos em diversos servidores e versões diferentes no ambientes produtivos.

Exemplo são os hosts do Ansible, que podemos executar dessa forma seu playbook:

project

Isso faz com que 4 servidores recebam uma determinada versão do seu aplicativo de forma remota e orquestrada através do WinRM.

Conclusão

Com isso temos provisionado nosso exemplo, o IIS com .NET Framework 4.6 conforme requisito de forma automatizada, tomando uso do módulo do ansible win_chocolatey através do gerenciamento remoto do WinRM, e então, podendo ser executado em uma esteira de CI/CD para criação de ambiente Windows Server de forma rápida e segura

Resume

O Linux comunica com protocolo SSH e Windows Server a Microsoft pensou e projetou seu próprio gerenciador para se comunicar usando o WinRM, sendo assim facilitando a automação IaC com Ansible.

Technology