Problem:
Basic Auth not working as expected. When running a playbook locally using an ini it works as expected. Running via job I get:
fatal: [win-iot-1.int.m-box.de]: UNREACHABLE! => {"changed": false, "msg": "basic: auth method basic requires a password", "unreachable": true}
Expected outcome:
Foreman and Proxy versions:
3.14
Foreman and Proxy plugin versions:
Distribution and version:
Rocky Linux 9.5
Other relevant data:
The following params are set on the host group:
ansible_connection=winrm
ansible_become=false
ansible_user=ansible
ansible_password=******
ansible_winrm_transport=basic
ansible_winrm_scheme=http
ansible_port=5985
ansible_winrm_server_cert_validation=ignore
Ansible
ansible [core 2.16.14]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/usr/share/foreman-proxy/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.12/site-packages/ansible
ansible collection location = /usr/share/foreman-proxy/.ansible/collections:/usr/share/ansible/collections
executable location = /bin/ansible
python version = 3.12.5 (main, Apr 2 2025, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-5)] (/usr/bin/python3.12)
jinja version = 3.1.5
libyaml = True
Does anybody have an idea? Shoud I open an issue?
When looking at the inventory, ansible_password is not included indeed:
Even I have a same issue, are you able to figure out any solution ?
@amgokak - no, not really - ansible_password is still filtered.
I moved away from basic auth winrm; this is the right choice I guess (only wanted to give it a quick test).
My windows hosts now use cert based authenticaton and integrate mostly with ansible_winrm_ host vars. Below the snippet I use at deploy time from foreman; it adds a cert I generated for foreman_proxy user. In the end the config more or less equals SSH. Because it is Windows after all, the setup is involed. I tested this with Windows 10/11 Pro and thier IoT LTSC equivalents.
# WAIK-Ansible-setup.ps1
# Create ansible user account
$ansibleUser = "<%= host_param('ansible_user') ? host_param('ansible_user') : 'ansible' %>"
$ansiblePassword = <% if host_param('ansiblecert_pem_string') or !host_param("ansible_password") %>"$(-join ((48..57) + (97..122) | Get-Random -Count 14 | % {[char]$_}))"<% else %>'<%= host_param("ansible_password") %>'<%end%>
$winRmPort = <%= host_param('ansible_port') ? host_param('ansible_port') : '5986' %>
$createUserParams = @{
Name = $ansibleUser
Description = "Ansible User"
Password = ConvertTo-SecureString -AsPlainText -Force -String $ansiblePassword
PasswordNeverExpires = $true
UserMayNotChangePassword = $true
}
Remove-LocalUser -Name $ansibleUser -ErrorAction SilentlyContinue
New-LocalUser @createUserParams | Add-LocalGroupMember -Group Administrators
# Allows local user accounts to be used with WinRM
# This can be ignored if using domain accounts
$tokenFilterParams = @{
Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
Name = 'LocalAccountTokenFilterPolicy'
Value = 1
PropertyType = 'DWORD'
Force = $true
}
New-ItemProperty @tokenFilterParams
# Firewall settings
Get-NetConnectionProfile | foreach{Set-NetConnectionProfile -InterfaceIndex $_.InterfaceIndex -NetworkCategory Private -Confirm:$false -PassThru}
New-NetFirewallRule -DisplayName 'Allow WinRM HTTPS' -Direction Inbound -LocalPort $winRmPort -Protocol TCP -Action Allow
$winrmcert = New-SelfSignedCertificate -DnsName ([System.Net.Dns]::GetHostByName($env:computerName)).Hostname -CertStoreLocation "cert:LocalMachine\My" -FriendlyName $ansibleUser
$listenerParams = @{
ResourceURI = "winrm/config/Listener"
SelectorSet = @{
address = "*"
transport = "https"
}
ValueSet = @{
Hostname = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname
CertificateThumbprint = $winrmcert.Thumbprint
Enabled = $true
Port = $winRmPort
}
}
# Setup WinRM instance
Remove-Item -Path "WSMan:\localhost\Listener\*" -Recurse -Force -ErrorAction SilentlyContinue
Set-WSManQuickConfig -Force
New-WSManInstance @listenerParams
# Remove HTTP listener from Quick Config
Get-ChildItem -Path WSMan:\localhost\Listener |
Where-Object Keys -contains "Transport=HTTP" |
Remove-Item -Recurse -Force
<% authTransport = (host_param('ansible_psrp_auth') || host_param("ansible_winrm_transport")) || 'basic' -%>
# Using Auth: <%= authTransport %>
<% case authTransport -%>
<% when 'certificate' -%>
$cert_file = 'cert.pem'
[IO.File]::WriteAllLines($cert_file, '<%= host_param("ansiblecert_pem_string") %>')
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($cert_file)
$store = Get-Item -LiteralPath Cert:\LocalMachine\TrustedPeople
$store.Open('ReadWrite')
$store.Add($cert)
$store.Dispose()
$store = Get-Item -LiteralPath Cert:\LocalMachine\Root
$store.Open('ReadWrite')
$store.Add($cert)
$store.Dispose()
$certChain = [System.Security.Cryptography.X509Certificates.X509Chain]::new()
[void]$certChain.Build($cert)
$caThumbprint = $certChain.ChainElements.Certificate[-1].Thumbprint
$certMapping = @{
Path = 'WSMan:\localhost\ClientCertificate'
Subject = $cert.GetNameInfo('UpnName', $false)
Issuer = $caThumbprint
Credential = [PSCredential]::new($ansibleUser, (ConvertTo-SecureString -AsPlainText -Force -String $ansiblePassword))
Force = $true
}
New-Item @certMapping
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
Remove-Item -Path $cert_file -Force
<% when 'basic' -%>
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
<% end %>
# Default config for reliability
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
winrm enumerate "winrm/config/Listener"
These are my hostgroup vars; they shoud get you started. Keep in mind:
ansiblecert_pem_string is the content of ansible_winrm_cert_pem
- The forman_proxy user can read both cert files
- If you have any suggestions - reply back here!
Cheers, Helge