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 é
5985para HTTP e5986para 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_pathdeve 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 quickconfigpara HTTP ouwinrm quickconfig -transport:httpspara 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_commandouwin_shellpara 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