【问题标题】:Ansible copy ssh key from one host to anotherAnsible 将 ssh 密钥从一台主机复制到另一台主机
【发布时间】:2014-09-02 18:27:59
【问题描述】:

我的系统中有 2 个应用服务器,它们前面有一个负载平衡器,还有 1 个数据库服务器。我正在使用 Ansible 配置它们。应用程序服务器具有 Nginx + Passenger 并为 Rails 应用程序运行。将使用 capistrano 进行部署,但我有一个关于 ssh 密钥的问题。我的 git repo 在另一台服务器上,我必须在 appservers 上生成 ssh 公钥并将它们添加到 Git 服务器(到 authorized_keys 文件)。我怎样才能在 ansible playbook 中做到这一点?

PS:我可能有超过 2 个应用服务器。

【问题讨论】:

  • 您能否详细说明您如何在 Git 服务器上管理密钥?这是一个 gitlab 实例吗?你只需要在authorized_keys文件中添加密钥吗?
  • 我只需要将密钥添加到授权密钥文件

标签: ssh ansible capistrano3 ansible-playbook


【解决方案1】:

这对我有用,它收集节点上的公共 ssh 密钥并将其分发到所有节点。这样他们就可以相互交流了。

- hosts: controllers
  gather_facts: false
  remote_user: root
  tasks:
    - name: fetch all public ssh keys
      shell: cat ~/.ssh/id_rsa.pub
      register: ssh_keys
      tags:
        - ssh

    - name: check keys
      debug: msg="{{ ssh_keys.stdout }}"
      tags:
        - ssh

    - name: deploy keys on all servers
      authorized_key: user=root key="{{ item[0] }}"
      delegate_to: "{{ item[1] }}"
      with_nested:
        - "{{ ssh_keys.stdout }}"
        - "{{groups['controllers']}}"
      tags:
        - ssh

信息:这是给用户root

【讨论】:

  • 我采用了这个想法,但使用了 local_action: ssh-agent -L 并在博客上写了这篇文章:dannyman.toldme.com/2016/07/01/… 所以谢谢!!
  • 很好,这行得通,但我不明白你为什么用shell: user=root key... 而不是authorized_key: user=root key...。我试过这个 sn-p 但不能让它与 shell 一起工作,authorized_key 就像魅力一样。
  • @Thomas8:可能是我搞错了,很好的发现!
  • @dannyman 您可能是指您的博文中的ssh-add(而不是ssh-agent)。
【解决方案2】:

查看authorized_key module 获取有关如何管理您的公钥的信息。

我能想到的最直接的解决方案是为您的应用程序生成一个新的密钥对,以便在您的所有应用程序实例之间共享。 这可能会带来安全隐患(您确实在所有实例之间共享密钥!),但它会大大简化配置过程。

您还需要在每台应用计算机上部署一个用户,以便稍后在部署过程中使用。您需要在每个部署用户的 authorized_keys 上使用您的公钥(或 jenkins 公钥)。

素描剧本:

---
- name: ensure app/deploy public key is present on git server
  hosts: gitserver
  tasks:
    - name: ensure app public key
      authorized_key: 
        user: "{{ git_user }}" 
        key: app_keys/id_dsa.pub 
        state: present

- name: provision app servers
  hosts: appservers
  tasks:
    - name: ensure app/deploy user is present
      user: 
        name: "{{ deploy_user }}"
        state: present

    - name: ensure you'll be able to deploy later on
      authorized_key:
        user: "{{ deploy_user }}" 
        key: "{{ path_to_your_public_key }}" 
        state: present

    - name: ensure private key and public one are present
      copy: 
        src: keys/myapp.private 
        dest: "/home/{{ deploy_user }}/.ssh/{{ item }}" 
        mode: 0600
      with_items:
        - app_keys/id_dsa.pub
        - app_keys/id_dsa

【讨论】:

    【解决方案3】:

    我创建了一个参数化角色,以确保在源远程主机中的源用户中生成 ssh 密钥对,并将其公钥复制到目标远程主机中的目标用户。

    您可以在源和目标主机列表的嵌套循环中调用该角色,如下所示:

    ---
    #****h* ansible/ansible_roles_ssh_authorize_user
    # NAME
    #   ansible_roles_ssh_authorize_user - Authorizes user via ssh keys
    #
    # FUNCTION
    #
    #   Copies user's SSH public key from a source user in a source host
    #   to a target user in a target host
    #
    # INPUTS
    #
    #   * ssh_authorize_user_source_user
    #   * ssh_authorize_user_source_host
    #   * ssh_authorize_user_target_user
    #   * ssh_authorize_user_target_host
    #****
    #****h* ansible_roles_ssh_authorize_user/main.yml
    # NAME
    #   main.yml - Main playbook for role ssh_authorize_user
    # HISTORY
    #   $Id: $
    #****
    
    - assert:
        that:
          - ssh_authorize_user_source_user != ''
          - ssh_authorize_user_source_host != ''
          - ssh_authorize_user_target_user != ''
          - ssh_authorize_user_target_host != ''
      tags:
        - check_vars
    - name: Generate SSH Keypair in Source
      user:
        name: "{{ ssh_authorize_user_source_user }}"
        state: present
        ssh_key_comment: "ansible-generated for {{ ssh_authorize_user_source_user }}@{{ ssh_authorize_user_source_host }}"
        generate_ssh_key: yes
      delegate_to: "{{ ssh_authorize_user_source_host }}"
      register: source_user
    - name: Install SSH Public Key in Target
      authorized_key:
        user: "{{ ssh_authorize_user_target_user }}"
        key: "{{ source_user.ssh_public_key }}"
      delegate_to: "{{ ssh_authorize_user_target_host }}"
    - debug:
        msg: "{{ ssh_authorize_user_source_user }}@{{ ssh_authorize_user_source_host }} authorized to log in to {{ ssh_authorize_user_target_user }}@{{ ssh_authorize_user_target_host }}"
    

    循环调用角色:

    - name: Authorize User
      include_role:
        name: ssh_authorize_user
      vars:
        ssh_authorize_user_source_user: "{{ git_user }}"
        ssh_authorize_user_source_host: "{{ item[0] }}"
        ssh_authorize_user_target_user: "{{ git_user }}"
        ssh_authorize_user_target_host: "{{ item[1] }}"
      with_nested:
        - "{{ app_server_list }}"
        - "{{ git_server_list }}"
    

    【讨论】:

      【解决方案4】:

      我将创建一个部署用户,该用户被限制为拉取对您的存储库的访问权限。您可以通过 http 或 there are a few options to do it over ssh 允许此操作。

      如果您不关心将用户限制为对您的存储库的只读访问权限,那么您可以创建一个普通的 ssh 用户。创建用户后,您可以使用 Ansible 将用户的公钥添加到 git 服务器上的授权密钥文件中,您可以使用 authorized key module

      设置完成后,您有两个选择:

      1. 如果您使用 ssh,请使用 ssh 密钥转发,以便用于运行 Ansible 任务的用户将其公钥发送到开发服务器。

      2. 暂时转移密钥,使用ssh_optsgit module option使用部署用户的公钥。

      【讨论】:

        【解决方案5】:

        使用 openssh_keypair 和 authorized_key 模块同时创建和部署密钥,无需将其保存到您的 ansible 主机中。

        - openssh_keypair:
            group: root
            owner: root
            path: /some/path/in/your/server
            register: ssh_key
        
        - name: Store public key into origin
          delegate_to: central_server_name
          authorized_key:
             key: "{{ssh_key.public_key}}"
             comment: "{{ansible_hostname}}"
             user: any_user_on_central
        

        将创建和/或确保您服务器上的 ssh 密钥将启用与 central_server_name 的 ssh 连接。

        【讨论】:

          【解决方案6】:

          我想通过删除 shell 模块并使用 slurp 来贡献这段代码。非常感谢 Jonas Libbrecht 提供的代码。挺好用的。

          - name: Get ssh keys
            slurp:
              src: /home/nsbl/.ssh/id_ed25519.pub
            register: ssh_keys
            tags:
              - ssh
          
          - name: Check keys
            debug: msg="{{ ssh_keys['content'] | b64decode }}"
            tags:
              - ssh
          
          - name: deploy keys on nodes 1
            authorized_key: 
              user: root 
              key: "{{ item[1]  }}"
            delegate_to: "{{ item[0] }}"
            with_nested:
              - "{{ groups['cluster'] }}"
              - "{{ ssh_keys['content'] | b64decode }}"
            tags:
              - ssh
          
          

          感谢社区。​​p>

          【讨论】:

          • 谢谢。我已经删除了与问题无关的部分。该代码通过减少 Ansible playbook 中 shell 命令的使用,提出了对问题解决方案的改进。
          • 感谢您建设性地接受批评。玩得开心。