我无法通过 AD 对来自我的 ansible 主机的 windows 机器进行身份验证。 'Server not found in Kerberos Database' 于 Ubuntu 16.10

I'm having trouble authenticating over AD to windows machines from my ansible host. 'Server not found in Kerberos Database' on Ubuntu 16.10

我无法通过 AD 对来自我的 ansible 主机的 windows 机器进行身份验证。我有一张有效的 kerberos 票 -

klist
Credentials cache: FILE:/tmp/krb5cc_1000
        Principal: ansible@SOMEDOMAIN.LOCAL

  Issued                Expires               Principal
Mar 10 09:15:27 2017  Mar 10 19:15:24 2017  krbtgt/SOMEDOMAIN.LOCAL@SOMEDOMAIN.LOCAL

我的 kerberos 配置看起来不错 -

cat /etc/krb5.conf
[libdefaults]
        default_realm = SOMEDOMAIN.LOCAL
#       dns_lookup_realm = true
#       dns_lookup_kdc = true
#       ticket_lifetime = 24h
#       renew_lifetime = 7d
#       forwardable = true

# The following krb5.conf variables are only for MIT Kerberos.
#       kdc_timesync = 1
#       forwardable = true
#       proxiable = true

# The following encryption type specification will be used by MIT Kerberos
# if uncommented.  In general, the defaults in the MIT Kerberos code are
# correct and overriding these specifications only serves to disable new
# encryption types as they are added, creating interoperability problems.
#
# Thie only time when you might need to uncomment these lines and change
# the enctypes is if you have local software that will break on ticket
# caches containing ticket encryption types it doesn't know about (such as
# old versions of Sun Java).

#       default_tgs_enctypes = des3-hmac-sha1
#       default_tkt_enctypes = des3-hmac-sha1
#       permitted_enctypes = des3-hmac-sha1

# The following libdefaults parameters are only for Heimdal Kerberos.
#       v4_instance_resolve = false
#       v4_name_convert = {
#               host = {
#                       rcmd = host
#                       ftp = ftp
#               }
#               plain = {
#                       something = something-else
#               }
#       }
#       fcc-mit-ticketflags = true

[realms]
        SOMEDOMAIN.LOCAL = {
                kdc = prosperitydc1.somedomain.local
                kdc = prosperitydc2.somedomain.local
                default_domain = somedomain.local
                admin_server = somedomain.local
        }
[domain_realm]
        .somedomain.local = SOMEDOMAIN.LOCAL
        somedomain.local = SOMEDOMAIN.LOCAL

当 运行 一个测试命令 - ansible windows -m win_ping -vvvvv 我得到

'Server not found in Kerberos database'.
     ansible windows -m win_ping -vvvvv
    Using /etc/ansible/ansible.cfg as config file
    Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
    Using module file /usr/lib/python2.7/dist-packages/ansible/modules/core/windows/win_ping.ps1
    <kerberostest.somedomain.local> ESTABLISH WINRM CONNECTION FOR USER: ansible@SOMEDOMAIN.LOCAL on PORT 5986 TO kerberostest.somedomain.local
    <kerberostest.somedomain.local> WINRM CONNECT: transport=kerberos endpoint=https://kerberostest.somedomain.local:5986/wsman
    <kerberostest.somedomain.local> WINRM CONNECTION ERROR: authGSSClientStep() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))
    Traceback (most recent call last):
      File "/usr/lib/python2.7/dist-packages/ansible/plugins/connection/winrm.py", line 154, in _winrm_connect
        self.shell_id = protocol.open_shell(codepage=65001)  # UTF-8
      File "/home/prosperity/.local/lib/python2.7/site-packages/winrm/protocol.py", line 132, in open_shell
        res = self.send_message(xmltodict.unparse(req))
      File "/home/prosperity/.local/lib/python2.7/site-packages/winrm/protocol.py", line 207, in send_message
        return self.transport.send_message(message)
      File "/home/prosperity/.local/lib/python2.7/site-packages/winrm/transport.py", line 181, in send_message
        prepared_request = self.session.prepare_request(request)
      File "/home/prosperity/.local/lib/python2.7/site-packages/requests/sessions.py", line 407, in prepare_request
        hooks=merge_hooks(request.hooks, self.hooks),
      File "/home/prosperity/.local/lib/python2.7/site-packages/requests/models.py", line 306, in prepare
        self.prepare_auth(auth, url)
      File "/home/prosperity/.local/lib/python2.7/site-packages/requests/models.py", line 543, in prepare_auth
        r = auth(self)
      File "/home/prosperity/.local/lib/python2.7/site-packages/requests_kerberos/kerberos_.py", line 308, in __call__
        auth_header = self.generate_request_header(None, host, is_preemptive=True)
      File "/home/prosperity/.local/lib/python2.7/site-packages/requests_kerberos/kerberos_.py", line 148, in generate_request_header
        raise KerberosExchangeError("%s failed: %s" % (kerb_stage, str(error.args)))
    KerberosExchangeError: authGSSClientStep() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))

    kerberostest.somedomain.local | UNREACHABLE! => {
        "changed": false,
        "msg": "kerberos: authGSSClientStep() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))",
        "unreachable": true
    }

我可以通过 ssh 连接到目标机器

 ssh -v1 kerberostest.somedomain.local -p 5986
OpenSSH_7.3p1 Ubuntu-1, OpenSSL 1.0.2g  1 Mar 2016
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to kerberostest.somedomain.local [10.10.20.84] port 5986.
debug1: Connection established.

我还可以使用主机名 ping 所有主机。我不知所措:(

这是ansible主机文件-

sudo cat /etc/ansible/hosts               
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
#   - Comments begin with the '#' character
#   - Blank lines are ignored
#   - Groups of hosts are delimited by [header] elements
#   - You can enter hostnames or ip addresses
#   - A hostname/ip can be a member of multiple groups

# Ex 1: Ungrouped hosts, specify before any group headers.

## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10

# Ex 2: A collection of hosts belonging to the 'webservers' group

## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

# If you have multiple hosts following a pattern you can specify
# them like this:

## www[001:006].example.com

# Ex 3: A collection of database servers in the 'dbservers' group

## [dbservers]
## 
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57

# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com
[monitoring-servers]
#nagios
10.10.20.75 ansible_connection=ssh ansible_user=nagios

[windows]
#fileserver.somedomain.local#this machine isnt joined to the domain yet.
kerberostest.SOMEDOMAIN.LOCAL


[windows:vars]
#the following works for windows local account authentication
#ansible_ssh_user = prosperity
#ansible_ssh_pass = *********
#ansible_connection = winrm
#ansible_ssh_port = 5986
#ansible_winrm_server_cert_validation = ignore

#vars needed to authenticate on the windows domain using kerberos
ansible_user = ansible@SOMEDOMAIN.LOCAL
ansible_connection = winrm
ansible_winrm_scheme = https
ansible_winrm_transport = kerberos
ansible_winrm_server_cert_validation = ignore

我也尝试使用 realmd 成功连接到域,但是 运行ansible 命令产生了相同的结果。

这看起来像是缺少 SPN 的情况。

这是相关的错误片段:

<kerberostest.prosperityerp.local> ESTABLISH WINRM CONNECTION FOR USER: ansible@PROSPERITYERP.LOCAL on PORT 5986 TO kerberostest.prosperityerp.local
    <kerberostest.prosperityerp.local> WINRM CONNECT: transport=kerberos endpoint=https://kerberostest.prosperityerp.local:5986/wsman
    <kerberostest.prosperityerp.local> WINRM CONNECTION ERROR: authGSSClientStep() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), ('Server not found in Kerberos database', -1765328377))

这是基于我在您的 Ansible 配置文件中注意到的内容:

[windows]
#fileserver.prosperityerp.local#this machine isnt joined to the domain yet.
kerberostest.PROSPERITYERP.LOCAL

我认为该文件中的 this machine isnt joined to the domain yet 行很好地表明 SPN HTTP/kerberostest.prosperityerp.local 在 Active 中不存在将导致“server not found”消息的目录。您可以通过 SSH 连接到 kerberostest.prosperityerp.local,可能是因为它存在于 DNS 或客户端计算机的主机文件中,但除非并直到 SPN HTTP/kerberostest.prosperityerp.local 是在 Active Directory 中创建的,您将继续收到该错误消息。此时正确添加该 SPN 将是另一个讨论主题。

  1. 您可以使用这样的命令来测试您是否定义了该 SPN:

    setspn -Q HTTP/kerberostest.prosperityerp.local

SPN 的存在是为了向 Kerberos 客户端表示在哪里可以找到网络上该服务的服务实例。

  1. 还有运行:

nslookup kerberostest.prosperityerp.local

在至少两台客户端计算机上确保 Kerberized 运行ning 的 IP 主机的 FQDN 存在 DNS。 DNS 是 Kerberos 在网络中正确 运行 的要求。

  1. 最后,您可以在客户端使用 Wireshark 进行进一步分析,使用过滤器 kerberos 仅突出显示 kerberos 流量。

在我的例子中,Server not found in Kerberos database 错误是目标 Windows 机器的 DNS 名称未映射到正确领域的结果,正如 this Microsoft Technet Article 这一行中所暗示的:

The error “Server not found in Kerberos database” is common and can be misleading because it often appears when the service principal is not missing. The error can be caused by domain/realm mapping problems or it can be the result of a DNS problem where the service principal name is not being built correctly. Server logs and network traces can be used to determine what service principal is actually being requested.

我有剧本whoami.yaml:

- hosts: windows-machine.mydomain.com
  tasks:
  - name: Run 'whoami' command
    win_command: whoami

主机文件:

[windows]
windows-machine.mydomain.com

[windows:vars]
ansible_connection=winrm
ansible_winrm_transport=kerberos
ansible_user=user@FOO.BAR.MYDOMAIN.COM
ansible_password=<password>
ansible_port=5985

因为 DNS 名称是 windows-machine.mydomain.com,但是 AD 领域 FOO.BAR.MYDOMAIN.COM 我必须在我的 /etc/krb5.conf 文件中修复映射在我的 Ansible 主机上:

不正确

这不适用于我们的案例,因为此映射规则不适用于 windows-machine.mydomain.com:

[domain_realm]
    foo.bar.mydomain.com = FOO.BAR.MYDOMAIN.COM

正确

这会正确地将 windows-machine.mydomain.com 映射到领域 FOO.BAR.MYDOMAIN.COM

[domain_realm]
    .mydomain.com = FOO.BAR.MYDOMAIN.COM