ANSIBLE SERIES: Final … (WinRM + Chocolatey) A Windows Friend
De longe, a maior série do BLOG até agora. Se pegarmos a quantidade de posts somada a data do primeiro artigo, essa foi sim a mais longa (e completa) que já fiz. Mas antes de abordar esse assunto pela última vez … Você sabia que dá pra gerenciar estações Windows via Ansible? Sim, pois é. O nosso carinha é tão de boa, tão gente fina, que é amigável à todos os sistemas operacionais, incluindo a “janela” do Tio Gattes. E por falar em última(o), caso tenha prestado atenção ao título, essa não será a primeira nem a “última” (haha) vez que o Chocolatey aparece por aqui. Não, não. Já o vimos com o Terraform lembram?
Voltando ao foco da conversa. Para entendermos melhor a interação entre esses dois (ANSIBLE-WINDOWS), iremos compará-los com o Linux. Então, sem mais delongas: Let’s bora!!!
SSH e Python no Windows? Como pode?
Bem, na verdade não. Quero dizer, sim! Tenho plena ciência de que a Microsoft já disponibilizou o OpenSSH nativamente a partir do Windows 10 e Server 2016. Não é novidade pra ninguém! Mas o que acontece é que somente agora os desenvolvedores do Ansible começaram a dar suporte ao SSH no Windows, e ainda por cima de forma experimental. Palavras retiradas da própria documentação oficial, e você pode conferir aqui. Sendo assim, por ora o que temos é:
- O protocolo chamado Windows Remote Management (ou WinRM¹) desempenhando o papel de SSH para o Ansible.
- A linguagem de script proprietária da Microsoft, transformando os playbooks que chegam em Python para sintaxe do PowerShell².
¹ WinRM
A primeira diferença é na forma de conexão entre o controlador e o host. É utilizado o Windows Remote Management (WinRM), que é a implementação da Microsoft do Web Services Management (WS-Man), um padrão aberto do Distributed Management Task Force (DMTF), em que se utiliza um web service baseado em SOAP para gerência remota de diversos dispositivos.
² PowerShell
A segunda diferença é o uso de scripts PowerShell no lugar do Python na execução das tasks nos hosts. Ao gerenciar servidores Linux, o Ansible converte as playbooks em scripts Python que são transferidos via SSH para os hosts e executados remotamente.
No caso do Windows, são gerados scripts PowerShell que são transferidos via WinRM (utilizando a biblioteca pywinrm), para então serem executados nos hosts.
Pré-requisitos:
- Windows 8.1 e Windows 10
- Windows Server 2012, 2012 R2, 2016, 2019 e 2022
- PowerShell 3.0 ou maior
- .NET 4.0 ou maior
Atualizando o PowerShell e .NET Framework
O Ansible requer o PowerShell versão 3.0 e .NET Framework 4.0, ou mais recente, para funcionar em sistemas operacionais mais antigos, como Server 2008 e Windows 7. A imagem base não atende a esse requisito. Você pode usar o script Upgrade-PowerShell.ps1
para atualizá-los.
Este é o exemplo extraído do site oficial e você pode executá-lo tranquilamente no Windows:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Upgrade-PowerShell.ps1" $file = "$env:temp\Upgrade-PowerShell.ps1" $username = "Administrator" $password = "Password" (New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file) Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force # Version can be 3.0, 4.0 or 5.1 &$file -Version 5.1 -Username $username -Password $password -Verbose

Uma vez concluído, você precisará remover o logon automático e definir a política de execução de volta ao padrão (Restricted
para clientes Windows ou RemoteSigned
para servidores Windows). Você pode fazer isso com os seguintes comandos do PowerShell:
# This isn't needed but is a good security practice to complete Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force $reg_winlogon_path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" Set-ItemProperty -Path $reg_winlogon_path -Name AutoAdminLogon -Value 0 Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultUserName -ErrorAction SilentlyContinue Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultPassword -ErrorAction SilentlyContinue

O script funciona verificando quais programas precisam ser instalados (como .NET Framework 4.5.2) e qual versão do PowerShell é necessária. Se uma reinicialização for necessária e os parâmetros de nome de usuário e senha estiverem definidos, o script será reinicializado e conectado automaticamente quando voltar da reinicialização. O script continuará até que não sejam necessárias mais ações e a versão do PowerShell corresponda à versão de destino. Se os parâmetros de nome de usuário e senha não estiverem definidos, o script solicitará que o usuário reinicialize manualmente e faça logon quando necessário. Quando o usuário fizer login novamente, o script continuará de onde parou e o processo continuará até que não sejam necessárias mais ações.
Configurando o WinRM
Depois que o Powershell for atualizado para o mínimo (versão 3.0+), a etapa final é configurar o serviço WinRM para que o Ansible possa se conectar a ele. Existem dois componentes principais do serviço WinRM que ditam como o Ansible pode interagir com o Windows: o listener
e o próprio service
WinRM Listener
Os serviços WinRM escutam solicitações em uma ou mais portas. Cada uma dessas portas deve ter um listener criado e configurado. Para visualizar os ouvintes atuais em execução no serviço WinRM, execute o seguinte comando:
winrm enumerate winrm/config/Listener
A saída será algo mais ou menos assim:

Algumas das principais opções que são úteis para entender são:
- Transport: Independentemente de o ouvinte ser executado em HTTP ou HTTPS, é recomendável usar um ouvinte em HTTPS, pois os dados são criptografados sem a necessidade de outras alterações.
- Port: A porta em que o listener é executado, por padrão é
5985
para HTTP e5986
para HTTPS. Esta porta pode ser alterada para o que for necessário e corresponde ao host varansible_port
. - URLPrefix: O prefixo da URL para atender, por padrão é
wsman
. Se isso for alterado, o host varansible_winrm_path
deve ser definido com o mesmo valor. - CertificateThumbprint: Se estiver executando em um ouvinte HTTPS, esta é a impressão digital do certificado no Windows Certificate Store usado na conexão.
Setup Listener
Existem três maneiras de configurar um ouvinte WinRM:
- Usando
winrm quickconfig
para HTTP ouwinrm quickconfig -transport:https
para HTTPS. Essa é a opção mais fácil de usar ao executar fora de um ambiente de domínio e é necessário um ouvinte simples. Ao contrário das outras opções, esse processo também tem o benefício adicional de abrir o Firewall para as portas necessárias e iniciar o serviço WinRM. - Usando Objetos de Diretiva de Grupo. Esta é a melhor maneira de criar um listener quando o host é membro de um domínio porque a configuração é feita automaticamente sem nenhuma entrada do usuário. Para obter mais informações sobre objetos de política de grupo, consulte a documentação de objetos de política de grupo.
- Usando o PowerShell para criar o ouvinte com uma configuração específica. Isso pode ser feito executando os seguintes comandos do PowerShell:
$selector_set = @{ Address = "*" Transport = "HTTPS" } $value_set = @{ CertificateThumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE" } New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
WinRM Service
Há várias opções que podem ser definidas para controlar o comportamento do componente de serviço WinRM, incluindo opções de autenticação e configurações de memória. Para obter uma saída das opções de configuração de serviço atuais, execute o seguinte comando:
winrm get winrm/config/Service winrm get winrm/config/Winrs

Embora muitas dessas opções raramente devam ser alteradas, algumas podem afetar facilmente as operações no WinRM e são úteis para entender. Algumas das opções importantes são:
- Service\AllowUnencrypted: Esta opção define se o WinRM permitirá o tráfego executado em HTTP sem criptografia de mensagem. A criptografia em nível de mensagem só é possível quando ansible_winrm_transport for ntlm, kerberos ou credssp. Por padrão, isso é falso e só deve ser definido como verdadeiro ao depurar mensagens do WinRM.
- Service\Auth*: Esses sinalizadores definem quais opções de autenticação são permitidas com o serviço WinRM. Por padrão, Negociar (NTLM) e Kerberos estão habilitados.
- Service\Auth\CbtHardeningLevel: especifica se os tokens de associação de canal não são verificados (Nenhum), verificados, mas não obrigatórios (Relaxado) ou verificados e obrigatórios (Estritos). O CBT é usado apenas ao se conectar com NTLM ou Kerberos por HTTPS.
- Service\CertificateThumbprint: Esta é a impressão digital do certificado usado para criptografar o canal TLS usado com a autenticação CredSSP. Por padrão, isso está vazio; um certificado autoassinado é gerado quando o serviço WinRM é iniciado e usado no processo TLS.
- Winrs\MaxShellRunTime: Este é o tempo máximo, em milissegundos, que um comando remoto pode executar.
- Winrs\MaxMemoryPerShellMB: Esta é a quantidade máxima de memória alocada por shell, incluindo os processos filho do shell.
Autenticando no WinRM
Ao contrário dos hosts Linux/Unix, que usam SSH por padrão, os hosts Windows são configurados com WinRM. WinRM é um protocolo de gerenciamento usado pelo Windows para se comunicar remotamente com outro servidor. É um protocolo baseado em SOAP que se comunica por HTTP/HTTPS e está incluído em todos os sistemas operacionais Windows recentes. Desde o Windows Server 2012, o WinRM foi habilitado por padrão, mas na maioria dos casos é necessária uma configuração extra para usar o WinRM com o Ansible.
O Ansible usa o pacote pywinrm
para se comunicar com servidores Windows pelo WinRM. Ele não é instalado por padrão com o pacote Ansible, mas pode ser instalado executando o seguinte:
pip install "pywinrm>=0.3.0"
Ao se conectar a um host Windows, existem várias opções diferentes que podem ser usadas ao autenticar com uma conta. O tipo de autenticação pode ser definido em hosts ou grupos de inventário com a variável ansible_winrm_transport
.
A tabela a seguir é uma visão geral das opções:

Cobriremos aqui somente as três principais que são: básica, kerberos e NTLM
Basic
A autenticação básica é uma das opções mais simples de usar, mas também é a mais insegura. Isso ocorre porque o nome de usuário e a senha são simplesmente codificados em base64 e, se um canal seguro não estiver em uso (por exemplo, HTTPS), ele poderá ser decodificado por qualquer pessoa. A autenticação básica só pode ser usada para contas locais (não contas de domínio).
O exemplo a seguir mostra vars de host configuradas para autenticação básica:
ansible_user: LocalUsername ansible_password: Password ansible_connection: winrm ansible_winrm_transport: basic
A autenticação básica não é habilitada por padrão em um host Windows, mas pode ser habilitada executando o seguinte no PowerShell:
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
Kerberos
Kerberos é a opção de autenticação recomendada para usar ao executar em um ambiente de domínio. O Kerberos oferece suporte a recursos como delegação de credenciais e criptografia de mensagens por HTTP e é uma das opções mais seguras disponíveis por meio do WinRM.
O Kerberos requer algum trabalho de configuração adicional no host Ansible antes de poder ser usado corretamente.
O exemplo a seguir mostra vars de host configuradas para autenticação Kerberos:
ansible_user: [email protected] ansible_password: Password ansible_connection: winrm ansible_port: 5985 ansible_winrm_transport: kerberos
Existem algumas dependências de pacote que devem ser instaladas antes de usar o Kerberos. Observe abaixo a lista de dependências baseada na sua distro favorita (em uso):
# Via Yum (RHEL/Centos/Fedora for the older version) yum -y install gcc python-devel krb5-devel krb5-libs krb5-workstation # Via DNF (RHEL/Centos/Fedora for the newer version) dnf -y install gcc python3-devel krb5-devel krb5-libs krb5-workstation # Via Apt (Ubuntu) sudo apt-get install python-dev libkrb5-dev krb5-user # Via Portage (Gentoo) emerge -av app-crypt/mit-krb5 emerge -av dev-python/setuptools # Via Pkg (FreeBSD) sudo pkg install security/krb5 # Via OpenCSW (Solaris) pkgadd -d http://get.opencsw.org/now /opt/csw/bin/pkgutil -U /opt/csw/bin/pkgutil -y -i libkrb5_3 # Via Pacman (Arch Linux) pacman -S krb5
Uma vez que as dependências foram instaladas, o wrapper python-kerberos
pode ser instalado usando pip
:
pip install pywinrm[kerberos]
NTLM
O NTLM é um mecanismo de autenticação mais antigo usado pela Microsoft que pode oferecer suporte a contas locais e de domínio. O NTLM é habilitado por padrão no serviço WinRM, portanto, nenhuma configuração é necessária antes de usá-lo.
O NTLM é o protocolo de autenticação mais fácil de usar e é mais seguro que a autenticação básica. Se estiver executando em um ambiente de domínio, o Kerberos deve ser usado em vez do NTLM.
O Kerberos tem várias vantagens sobre o uso do NTLM:
- O NTLM é um protocolo mais antigo e não oferece suporte a protocolos de criptografia mais recentes.
- O NTLM é mais lento para autenticar porque requer mais viagens de ida e volta ao host no estágio de autenticação.
- Ao contrário do Kerberos, o NTLM não permite delegação de credenciais.
Este exemplo mostra as variáveis de host configuradas para usar a autenticação NTLM:
ansible_user: LocalUsername ansible_password: Password ansible_connection: winrm ansible_winrm_transport: ntlm
Executando o Ansible para Windows
Ao usar o Ansible para gerenciar o Windows, muitas das sintaxes e regras que se aplicam aos hosts Unix/Linux também se aplicam ao Windows. Todavia, ainda há algumas diferenças quando se trata de certos componentes, como por exemplo, separadores de caminho e tarefas específicas do sistema operacional.
Instalando software
Existem três maneiras principais de usar o Ansible para instalar software:
- Usando o módulo
win_chocolatey
. Isso origina os dados do programa do repositório público padrão do Chocolatey. Repositórios internos podem ser usados definindo a opção de origem. - Usando o módulo
win_package
. Isso instala o software usando um instalador MSI ou .exe de um caminho ou URL local/de rede. - Usando o módulo
win_command
ouwin_shell
para executar um instalador manualmente.
O módulo win_chocolatey
é recomendado, pois possui a lógica mais completa para verificar se um pacote já foi instalado e está atualizado.
Abaixo estão alguns exemplos de uso das três opções para instalar o 7-Zip:
# Install/uninstall with chocolatey - name: Ensure 7-Zip is installed via Chocolatey win_chocolatey: name: 7zip state: present - name: Ensure 7-Zip is not installed via Chocolatey win_chocolatey: name: 7zip state: absent # Install/uninstall with win_package - name: Download the 7-Zip package win_get_url: url: https://www.7-zip.org/a/7z1701-x64.msi dest: C:\temp\7z.msi - name: Ensure 7-Zip is installed via win_package win_package: path: C:\temp\7z.msi state: present - name: Ensure 7-Zip is not installed via win_package win_package: path: C:\temp\7z.msi state: absent # Install/uninstall with win_command - name: Download the 7-Zip package win_get_url: url: https://www.7-zip.org/a/7z1701-x64.msi dest: C:\temp\7z.msi - name: Check if 7-Zip is already installed win_reg_stat: name: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2702-1701-000001000000} register: 7zip_installed - name: Ensure 7-Zip is installed via win_command win_command: C:\Windows\System32\msiexec.exe /i C:\temp\7z.msi /qn /norestart when: 7zip_installed.exists == false - name: Ensure 7-Zip is uninstalled via win_command win_command: C:\Windows\System32\msiexec.exe /x {23170F69-40C1-2702-1701-000001000000} /qn /norestart when: 7zip_installed.exists == true



Criando usuários e grupos
O Ansible pode ser usado para adicionar usuários e grupos ao Windows, de forma local e/ou em um domínio do Active Directory.
Os módulos win_user
, win_group
e win_group_membership
gerenciam usuários, grupos e associações de grupos do Windows localmente. Veja a seguir um exemplo de criação de contas e grupos locais que podem acessar uma pasta no mesmo host:
- name: Create local group to contain new users win_group: name: LocalGroup description: Allow access to C:\Development folder - name: Create local user win_user: name: '{{ item.name }}' password: '{{ item.password }}' groups: LocalGroup update_password: no password_never_expires: yes loop: - name: User1 password: Password1 - name: User2 password: Password2 - name: Create Development folder win_file: path: C:\Development state: directory - name: Set ACL of Development folder win_acl: path: C:\Development rights: FullControl state: present type: allow user: LocalGroup - name: Remove parent inheritance of Development folder win_acl_inheritance: path: C:\Development reorganize: yes state: absent



Os módulos win_domain_user
e win_domain_group
gerenciam usuários e grupos em um domínio. Veja abaixo um exemplo de como garantir que um lote de usuários de domínio seja criado:
- name: Ensure each account is created win_domain_user: name: '{{ item.name }}' upn: '{{ item.name }}@MY.DOMAIN.COM' password: '{{ item.password }}' password_never_expires: no groups: - Test User - Application company: Ansible update_password: on_create loop: - name: Test User password: Password - name: Admin User password: SuperSecretPass01 - name: Dev User password: '@fvr3IbFBujSRh!3hBg%wgFucD8^x8W5'
Rodando tarefas agendadas
O WinRM possui algumas restrições que causam erros ao executar determinados comandos. Uma maneira de contornar essas restrições é executar um comando por meio de uma tarefa agendada. Uma tarefa agendada é um componente do Windows que oferece a capacidade de executar um executável em uma agenda e/ou em uma conta diferente.
O Ansible versão 2.5 adicionou módulos que facilitam o trabalho com tarefas agendadas no Windows. Veja a seguir um exemplo de execução de um script como uma tarefa agendada que se exclui após a execução:
- name: Create scheduled task to run a process win_scheduled_task: name: adhoc-task username: SYSTEM actions: - path: PowerShell.exe arguments: | Start-Sleep -Seconds 30 # This isn't required, just here as a demonstration New-Item -Path C:\temp\test -ItemType Directory # Remove this action if the task shouldn't be deleted on completion - path: cmd.exe arguments: /c schtasks.exe /Delete /TN "adhoc-task" /F triggers: - type: registration - name: Wait for the scheduled task to complete win_scheduled_task_stat: name: adhoc-task register: task_stat until: (task_stat.state is defined and task_stat.state.status != "TASK_STATE_RUNNING") or (task_stat.task_exists == False) retries: 12 delay: 10


É isso aí pessoal \o/\o/\o/ Missão cumprida!
Até breve …
( CURTA, COMPARTILHE, COMENTE )
REFERÊNCIAS:
https://www.ansible.com/for/windows
https://docs.ansible.com/ansible/latest/user_guide/windows.html
https://www.redhat.com/pt-br/technologies/management/ansible/automate-microsoft-windows-with-ansible