Ansible для Windows: настройка WinRM HTTPS

У меня есть несколько сценариев Ansible, которые я хочу запустить на некоторых хостах Windows. Я следил за различными руководствами по Ansible по настройке WinRM, и они работали нормально, но настройки по умолчанию очень небезопасны, и я хочу, чтобы что-то было готово к производству. Однако инструкций, как это сделать, невероятно мало. Пока что я сделал следующее:

В моем окне Windows:

  1. Включил WinRM с помощью прилагаемого скрипта ConfigureRemotingForAnsible.ps1
  2. Настроена целевая машина для использования действительного сертификата на HTTPS / 5986, а не самозаверяющего сертификата, сгенерированного приведенным выше сценарием.
  3. Включены методы аутентификации Kerberos и CredSSP на целевой машине в WinRM. Некоторые из этапов моей роли требуют, чтобы CredSSP работал надежно.

Пока все хорошо, сторона Windows вроде работает нормально. Однако заставить Ansible подключиться - это кошмар. Я не могу понять, как заставить Ansible доверять сертификату HTTPS на цели, несмотря на его добавление. На моем «push box» Centos 7 я сделал следующее:

  1. Установите Ansible и pip с модулями pywinrm, requests_kerberos и requests_credssp
  2. Добавлен мой сертификат CA в / etc / pki / tls / certs и / etc / pki / ca-cert
  3. Установите в моем инвентаре следующее:

[email protected]

ansible_password = Пароль1

ansible_port = 5986

ansible_connection = Winrm

ansible_winrm_scheme = https

/ # ansible_winrm_server_cert_validation = игнорировать

ansible_winrm_transport = credssp

При включенной проверке сертификата соединение не устанавливается со следующей ошибкой:

fatal: [host.domain.com]: 
UNREACHABLE! => {
"changed": false, 
"msg": "credssp: HTTPSConnectionPool(host='host.domain.com', port=5986): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(\"bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)\",),))", 
"unreachable": true}

С отключенной проверкой сертификата он работает нормально.

Итак, мой вопрос: как заставить Ansible доверять моему сертификату CA?


person Matt    schedule 24.11.2017    source источник
comment
NTLM неприемлем, это небезопасно. Он должен быть правильно проверен HTTPS, иначе просто игнорировать проверку сертификата было бы нормально. Честно говоря, мне кажется странным, что подобных вещей нет в стандартной документации.   -  person Matt    schedule 24.11.2017
comment
Чтобы уточнить, SSL (https) использует сертификаты, а Kerberos - нет. Если вы используете SSL, сертификат должен быть установлен на удаленном компьютере Windows, а не на управляющем узле. Вот что я сделал, чтобы Ansible работал на моих ящиках с Windows.   -  person skinnedKnuckles    schedule 06.01.2018


Ответы (3)


Это непросто. Проблема в том, что есть 3 разные группы, которые на самом деле не хотят играть:

  1. Ansible: не хочет нести ответственность за детали OpenSSL или Windows
  2. OpenSSL: не хочет использоваться в качестве центра сертификации
  3. Microsoft: не хочет, чтобы вы использовали ничего, кроме инструментов Windows

Во-первых, вам понадобятся 3 набора сертификатов / ключей OpenSSL: самозаверяющий центр сертификации (CA), сервер WinRM HTTPS и целевой пользователь.

В сертификате / ключе CA нет ничего волшебного; его можно сгенерировать с помощью следующего:

openssl req -new -out caroot.req -keyout caroot.key -days 730 ...
openssl x509 -req -in caroot.req -extensions v3_ca -signkey caroot.key -out cacert.pem -days 730

Есть множество других опций для этих команд OpenSSL, которые могут (или нет) работать в вашей конкретной среде. Это один из тех случаев, когда вы не хотите нести ответственность за OpenSSL.

Во-вторых, вам понадобится сертификат / ключ WinRM HTTPS. Во-первых, вам нужно сгенерировать сертификат сервера. Ключевой деталью создания сертификата является то, что атрибут «общее имя» в сертификате ДОЛЖЕН соответствовать имени целевого хоста, как и любой сертификат HTTPS.

openssl req -new -out server.req -keyout server.key -days 730 -nodes ...

А теперь самое сложное. Вы не можете просто подписать ключ как есть; процесс подписания должен добавить к сертификату пару дополнительных атрибутов, иначе это не сработает. Создайте текстовый файл, который я назову "attributes.txt", со следующими двумя строками:

subjectAltName=DNS:hostname.mycompany.com,DNS:hostname
extendedKeyUsage=serverAuth

Первая строка, «subjectAltName», является обязательной, иначе клиент Python / OpenSSL отклонит ключ. Вам необходимо подставить правильные значения для имени целевого хоста. Вторая строка требуется Windows, иначе Windows не будет использовать ее как для HTTPS-сервера.

Теперь подпишите ключ с помощью сгенерированного ранее CA:

openssl x509 -req -in server.req -out server.pem -days 730 -CA caroot.pem -CAkey caroot.key -extfile attributes.txt

Еще одна небольшая загвоздка: Windows не будет импортировать ключ сервера, если вы не объедините ключ и сертификат в файл PKCS # 12. Это можно сделать с помощью следующей команды, которая создает файл PKCS # 12 без пароля:

openssl pkcs12 -export -password pass: -inkey server.key -in server.pem -out windows.pfx

Это сгенерирует файл windows.pfx, который нам понадобится позже.

Еще не скучно?

Далее нам понадобится еще один ключ / сертификат для входа пользователя. Предполагается, что мы будем использовать локального пользователя в системе, а не пользователя домена. (Вы сами по себе.) Генерация ключа почти такая же, как и для ключа сервера, за исключением того, что атрибут 'commom name' (CN) ДОЛЖЕН соответствовать целевому имени пользователя. (В дальнейшем я буду называть нашего пользователя доступным).

openssl req -new -out winlogin.req -keyout winlogin.key -days 730

Этот закрытый ключ будет ключом входа в систему, аналогично закрытому ключу SSH. Далее мы должны подписать запрос. Как и в случае с серверным ключом, нам нужно добавить некоторые расширенные атрибуты, иначе это не сработает. Наш файл attributes.txt должен содержать следующие строки:

subjectAltName=otherName:1.3.6.1.4.1.311.20.2.3;UTF8:ansible@localhost
extendedKeyUsage=clientAuth

Необычный идентификатор в «altNames» - это некая проприетарная штука Microsoft, которая должна содержать «имя пользователя @localhost». Как я уже упоминал ранее, я использую «ansible» локального пользователя. Атрибут extendedKeyUsage является обязательным, иначе Windows не позволит использовать ключ для аутентификации пользователя. Наконец, подписываем сертификат:

openssl x509 -req -in winlogin.req -out winlogin.pem -days 730 -CA caroot.pem -CAkey caroot.key -extfile attributes.txt

Просто чтобы вы знали, я начинаю действовать здесь себе на нервы. Мы почти там. Наконец, скопируйте сертификат CA (caroot.pem), сертификат / ключ PKCS # 12 сервера (windows.pfx) и сертификат пользователя (winlogin.pem) куда-нибудь в целевую систему Windows. Запустите следующий сценарий PowerShell из того же каталога. Он создаст локального доступного пользователя и импортирует все артефакты SSL в их надлежащие целевые местоположения. Извините, если это не коммерческий код. Здесь также есть жестко запрограммированный пароль для доступного пользователя, но он не имеет значения и может быть свободно изменен. Если это действительно работает успешно и вы переживете шок, файловые артефакты (файлы PFX и PEM) можно удалить с сервера Windows.

Также обратите внимание, что этот сценарий добавляет в конце правило брандмауэра. Это, конечно, нужно будет соответствующим образом изменить для вашей среды.

# master script to enable winRM via HTTPS and allow certificate-based 
# authentication

# add the local 'ansible' user
$username = "ansible"
$password = ConvertTo-SecureString -string "Ans!b123" -AsPlainText -Force
New-LocalUser -Name $username -AccountNeverExpires -Description "Ansible Remote Management" -Password $password
Add-LocalGroupMember -Member "ansible" -Group "Administrators"
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password

# import the Ansible root CA; certlm should show this in the 
# 'Trusted Root Certification Authorities' folder
$caroot = Import-Certificate -FilePath ".\caroot.pem" -CertStoreLocation "Cert:\LocalMachine\Root"

# import the user cert; certlm should show this in the 'Trusted People' folder
$userkey = Import-Certificate -FilePath ".\winlogin.pem" -CertStoreLocation "Cert:\LocalMachine\TrustedPeople"
New-Item -Path WSMan:\localhost\ClientCertificate -subject "ansible@localhost" -URI "*" -Issuer $caroot.Thumbprint -Credential $credential -Force

# import the server certs - should appear in 'Personal' folder. The PFX file
# must contain both the cert and private key
$srvcert = Get-ChildItem -Path ".\windows.pfx" | Import-PFXCertificate -CertStoreLocation "Cert:\LocalMachine\MY" -Exportable

# Now create the winRM instance
$selector_set = @{Address= "*" Transport = "HTTPS" }

$value_set =  @{CertificateThumbprint = $srvcert.Thumbprint}

New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -value $true

# add a firewall rule
New-NetFirewallRule -DisplayName "Ansible WinRM" -Direction Inbound -Protocol "TCP" -LocalPort "5986" -Action Allow -RemoteAddress @("192.16.2.3")

Хорошо, теперь, когда Windows готова, мы должны быть готовы к Ansible. В вашем инвентаре вам понадобятся следующие переменные для применения к системам Windows:

ansible_port: 5986
ansible_connection: winrm
ansible_winrm_ca_trust_path: /path/to/caroot.pem
ansible_winrm_transport: certficate
ansible_winrm_cert_pem: /path/to/winlogin.pem
ansible_winrm_cert_key_pem: /path/to/winlogin.key

На этом этапе Ansible должен подключиться к серверу Windows, используя HTTPS и проверку подлинности сертификата. Надеюсь, я выполнил все шаги, это было довольно давно.

person CrankyElderGod    schedule 16.12.2020

Запустите это на доступном управляющем хосте:

python -c "import ssl; print(ssl.get_default_verify_paths())"

таким образом вы увидите, где python ожидает найти сертификат

Убедитесь, что сертификат доверия CA имеет кодировку pem.

person Jordi Molina    schedule 24.11.2017
comment
Эта команда говорит, что сертификат CA должен быть добавлен в / etc / pki / tls / certs, поэтому я сделал это. Сертификат был экспортирован как base64, поскольку это то, что Windows называла PEM-кодировкой. Он по-прежнему не работает, сертификат не доверяет. - person Matt; 30.11.2017

Это сработало для меня ..

https://dodgydudes.se/validate-ca-certificate-in-ansible-connecting-with-winrm/

ansible_winrm_ca_trust_path: / etc / ssl / certs #TLS 1.2

ansible_winrm_transport: ntlm

person kinect1things    schedule 21.01.2020
comment
Пожалуйста, подумайте о добавлении некоторых пояснений и деталей к своему ответу. Хотя это может ответить на вопрос, простое добавление некоторых ссылок не поможет OP или будущим членам сообщества понять проблему или решение. - person hongsy; 21.01.2020