ansible ssh提示known_hosts问题

Aru*_*gal 38 ssh command-prompt hosts-file ansible ansible-playbook

我正在运行Ansible playbook,它在一台机器上工作正常.

在我第一次尝试的新机器上,我收到以下错误.

17:04:34 PLAY [appservers] ************************************************************* 
17:04:34 
17:04:34 GATHERING FACTS *************************************************************** 
17:04:34 fatal: [server02.cit.product-ref.dev] => {'msg': "FAILED: (22, 'Invalid argument')", 'failed': True}
17:04:34 fatal: [server01.cit.product-ref.dev] => {'msg': "FAILED: (22, 'Invalid argument')", 'failed': True}
17:04:34 
17:04:34 TASK: [common | remove old ansible-tmp-*] ************************************* 
17:04:34 FATAL: no hosts matched or all hosts have already failed -- aborting
17:04:34 
17:04:34 
17:04:34 PLAY RECAP ******************************************************************** 
17:04:34            to retry, use: --limit @/var/lib/jenkins/site.retry
17:04:34 
17:04:34 server01.cit.product-ref.dev      : ok=0    changed=0    unreachable=1    failed=0   
17:04:34 server02.cit.product-ref.dev      : ok=0    changed=0    unreachable=1    failed=0   
17:04:34 
17:04:34 Build step 'Execute shell' marked build as failure
17:04:34 Finished: FAILURE
Run Code Online (Sandbox Code Playgroud)

如果我首先转到源计算机(从我运行ansible playbook)并手动ssh到目标计算机(作为给定用户)并输入"yes"表示known_hosts文件条目,则可以解决此错误.

现在,如果我第二次运行相同的ansible playbook,它的工作没有错误.

因此,如何为第一次为给定用户(〜/ .ssh文件夹,文件known_hosts)创建ssh known_hosts条目时,如何禁止SSH提供的提示?

如果我在〜/ .ssh/config文件中使用以下配置条目,我发现我可以这样做.

的〜/ .ssh /配置

# For vapp virtual machines
Host *
  StrictHostKeyChecking no
  UserKnownHostsFile=/dev/null
  User kobaloki
  LogLevel ERROR
Run Code Online (Sandbox Code Playgroud)

即如果我将上述代码放在用户的远程机器的〜/ .ssh/config文件中并首次尝试Ansible playbook,我将不会被提示"是",并且playbook将成功运行(不需要用户手动创建从源计算机到目标/远程计算机的known_hosts文件条目.

我的问题:1.如果我去〜/ .ssh/config方式,我应该注意哪些安全问题2.如何在命令行中将设置(配置文件中的内容)作为参数/选项传递给ansible,以便它将在新机器上第一次运行(不提示/取决于源机器上目标机器的known_hosts文件条目?

Ben*_*ley 40

ansible文档有一节关于此.引用:

Ansible 1.2.1及更高版本默认启用主机密钥检查.

如果重新安装主机并且在'known_hosts'中具有不同的密钥,则会在纠正之前产生错误消息.如果主机最初不在'known_hosts'中,这将导致提示确认密钥,如果使用Ansible,例如cron,则会产生交互式体验.你可能不想要这个.

如果您了解其含义并希望禁用此行为,则可以通过编辑/etc/ansible/ansible.cfg或〜/ .ansible.cfg来执行此操作:

[defaults]
host_key_checking = False
Run Code Online (Sandbox Code Playgroud)

或者,这可以通过环境变量设置:

$ export ANSIBLE_HOST_KEY_CHECKING=False
Run Code Online (Sandbox Code Playgroud)

另请注意,paramiko模式下的主机密钥检查速度相当慢,因此在使用此功能时也建议切换到"ssh".

  • 仅作为记录,请参阅我的答案(如下)http://stackoverflow.com/a/39083724/3114959,它为您提供了一种更新本地“known_hosts”文件的方法。 (2认同)

Ste*_*vra 33

为了更新本地known_hosts文件,我最终使用ssh-keyscan(dig用于解析主机名到IP地址)和ansible模块的组合known_hosts,如下所示:(filename ssh-known_hosts.yml)

- name: Store known hosts of 'all' the hosts in the inventory file
  hosts: localhost
  connection: local

  vars:
    ssh_known_hosts_command: "ssh-keyscan -T 10"
    ssh_known_hosts_file: "{{ lookup('env','HOME') + '/.ssh/known_hosts' }}"
    ssh_known_hosts: "{{ groups['all'] }}"

  tasks:

  - name: For each host, scan for its ssh public key
    shell: "ssh-keyscan {{ item }},`dig +short {{ item }}`"
    with_items: "{{ ssh_known_hosts }}"
    register: ssh_known_host_results
    ignore_errors: yes

  - name: Add/update the public key in the '{{ ssh_known_hosts_file }}'
    known_hosts:
      name: "{{ item.item }}"
      key: "{{ item.stdout }}"
      path: "{{ ssh_known_hosts_file }}"
    with_items: "{{ ssh_known_host_results.results }}"
Run Code Online (Sandbox Code Playgroud)

要执行这样的yml,请执行

ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook path/to/the/yml/above/ssh-known_hosts.yml
Run Code Online (Sandbox Code Playgroud)

因此,对于清单中的每个主机,将known_hosts主机名,ipaddress对记录下的文件中添加/更新所有支持的算法; 如

atlanta1.my.com,10.0.5.2 ecdsa-sha2-nistp256 AAAAEjZHN ... NobYTIGgtbdv3K+w=
atlanta1.my.com,10.0.5.2 ssh-rsa AAAAB3NaC1y ... JTyWisGpFeRB+VTKQ7
atlanta1.my.com,10.0.5.2 ssh-ed25519 AAAAC3NaCZD ... UteryYr
denver8.my.com,10.2.13.3 ssh-rsa AAAAB3NFC2 ... 3tGDQDSfJD
...
Run Code Online (Sandbox Code Playgroud)

(如果库存文件如下所示:

[master]
atlanta1.my.com
atlanta2.my.com

[slave]
denver1.my.com
denver8.my.com
Run Code Online (Sandbox Code Playgroud)

)

与Xiong的答案相反,这将正确处理known_hosts文件的内容.

如果使用目标主机重新映像的虚拟化环境(因此ssh pub键被更改),此播放特别有用.

  • 您可以将 ssh 端口添加到 `ssh-keyscan` 中,该端口类似于 `{{ hostvars[item]['ansible_port'] }}` (3认同)

Xio*_*iov 17

从安全角度来看,完全禁用主机密钥检查是一个坏主意,因为它会让您受到中间人攻击.

如果你可以假设当前网络没有受到损害(也就是说,当你第一次ssh到机器并且出现一个密钥时,那个密钥实际上是机器而不是攻击者),那么你可以使用ssh-keyscanshell模块将新服务器的密钥添加到已知的hosts文件中(编辑:Stepan的答案这样做更好):

- name: accept new ssh fingerprints
  shell: ssh-keyscan -H {{ item.public_ip }} >> ~/.ssh/known_hosts
  with_items: ec2.instances
Run Code Online (Sandbox Code Playgroud)

(在ec2配置后你会发现在这里展示.)

  • 绝对更好,更安全的方式.还有一个模块可以做到这一点http://docs.ansible.com/ansible/known_hosts_module.html (4认同)
  • 这不是幂等的 (3认同)

use*_*074 8

关注@Stepan Vavra的正确答案.较短的版本是:

- known_hosts:
    name: "{{ item }}"
    key: "{{ lookup('pipe', 'ssh-keyscan {{ item }},`dig +short {{ item }}`') }}"
  with_items:
   - google.com
   - github.com
Run Code Online (Sandbox Code Playgroud)


小智 6

不会为启动known_hosts文件执行以下工作:

ANSIBLE_HOST_KEY_CHECKING=false ansible all -m ping
Run Code Online (Sandbox Code Playgroud)

这应该连接到清单中的每个主机,为每个主机更新known_hosts文件,而不必为每个提示输入“是”,然后在每个主机上运行“ ping”模块吗?

快速测试(删除我的known_hosts文件,然后在Ubuntu 16.04实例上执行上述操作)似乎用当前指纹填充了known_hosts文件。

@Stepan Vavra的解决方案对我不起作用,因为我使用的是别名主机(正在连接到没有可用DNS的内部IP,因此我希望使用更具描述性的名称来引用清单中的每个主机,并使用ansible_host变量指向每个的实际IP)。运行上面的命令要简单得多,并且可以在不禁用ansible或ssh的主机密钥检查的情况下启动我的known_hosts文件。