playbook to add ssh-key having passphrase and reuse SSH_AUTH_SOCK, SSH_AGENT_PID

huangapple go评论77阅读模式
英文:

playbook to add ssh-key having passphrase and reuse SSH_AUTH_SOCK, SSH_AGENT_PID

问题

Sure, here is the translated content:

我想要实现什么?使用单个 Ansible playbook,

1. 如果尚未运行,请启动 ssh-agent(在本地主机上)。
2. 添加带有密码保护的 ssh 密钥。
3. 连接到远程机器运行任务

---
- name: 设置 ssh-agent
  hosts: localhost
  gather_facts: false
  vars_files:
    - ../vars.yml
  vars:
    ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
    ansible_ssh_pass: "{{sshpassphrs}}"
  tasks:
    - name: 启动 ssh-agent 并获取 SSH_AUTH_SOCK 和 SSH_AGENT_PID 环境变量
      shell: |
          eval $(ssh-agent -s) > /dev/null
          echo '{"SSH_AUTH_SOCK":"'${SSH_AUTH_SOCK}'","SSH_AGENT_PID":"'${SSH_AGENT_PID}'"}'
      register: env_vars_stdout
    - name: 保存到 env_vars
      set_fact:
        env_vars: "{{ env_vars_stdout.stdout }}"
    - name: 添加 {{ansible_ssh_private_key_file}} 到 ssh-agent
      environment: "{{ env_vars }}"
      expect:
        command: ssh-add {{ ansible_ssh_private_key_file }}
        responses:
          passphrase: "{{ ansible_ssh_pass }}"
- name: 主要任务
  hosts: all
  gather_facts: false
  environment: "{{ hostvars['localhost']['env_vars'] }}"
  vars_files:
    - ../vars.yml
  vars:
    ansible_user: "{{username}}"
  tasks:
    - name: 进行 ping 测试
      shell: ping -c 20 -w 50 fb.me

请注意,翻译的内容只包括 Ansible playbook 的部分,不包括问题的回答部分。

英文:

What do I want to achieve? Using a single Ansible playbook,

  1. start ssh-agent if not running (on localhost).
  2. add ssh-key (that is passphrase protected).
  3. connect to remote machines to run tasks
    ---
    - name: setup ssh-agent
      hosts: localhost
      gather_facts: false
      vars_files:
        - ../vars.yml
      vars:
        ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
        ansible_ssh_pass: "{{sshpassphrs}}"
      tasks:
        - name: Start ssh-agent and Retrieve the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables
          shell: |
              eval $(ssh-agent -s) > /dev/null
              echo '{"SSH_AUTH_SOCK":"'$SSH_AUTH_SOCK'","SSH_AGENT_PID":"'$SSH_AGENT_PID'"}'
          register: env_vars_stdout
        - name: save to env_vars
          set_fact:
            env_vars: "{{ env_vars_stdout.stdout }}"
        - name: add {{ansible_ssh_private_key_file}} to ssh-agent
          environment: "{{ env_vars }}"
          expect:
            command: ssh-add {{ ansible_ssh_private_key_file }}
            responses:
              passphrase: "{{ ansible_ssh_pass }}"
    - name: main jobs
      hosts: all
      gather_facts: false
      environment: "{{ hostvars['localhost']['env_vars'] }}"
      vars_files:
        - ../vars.yml
      vars:
        ansible_user: "{{username}}"
      tasks:
        - name: Do a ping test
          shell: ping -c 20 -w 50 fb.me

It throws an error for the ping test, as destination hosts are unreachable with msg "Failed to connect to the host via ssh".

I know this is quite a hacky way, adding the key through ssh-agent in the terminal session would have been straightforward. But anyway to achieve this?

答案1

得分: 1

以下是您提供的内容的翻译:

我认为这里的问题在于,根据文档,enviroment关键字有助于设置远程环境。也就是说,到那时应该已经建立了到远程主机的SSH连接。

为了更改用于连接到remote_host的参数,我们需要使用ansible_ssh_common_args变量。您可以在ssh_config中使用IdentityAgent选项来指定SSH代理套接字。

我已经向您的解决方案添加了一些语句。

 ---
    - name: 设置ssh-agent
      hosts: localhost
      gather_facts: false
      vars_files:
        - ../vars.yml
      vars:
        ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
        ansible_ssh_pass: "{{sshpassphrs}}"
      tasks:
        - name: 启动ssh-agent并检索SSH_AUTH_SOCK和SSH_AGENT_PID环境变量
          shell: |
              eval $(ssh-agent -s) > /dev/null
              echo '{"SSH_AUTH_SOCK":"'$SSH_AUTH_SOCK'","SSH_AGENT_PID":"'$SSH_AGENT_PID'"}'              
          register: env_vars_stdout
        - name: 保存到env_vars
          set_fact:
            env_vars: "{{ env_vars_stdout.stdout }}"
            ssh_auth_sock: "{{ env_vars_stdout.stdout | from_json | json_query('SSH_AUTH_SOCK') }}" # 安装jmespath如果尚未安装
        - name: 将{{ansible_ssh_private_key_file}}添加到ssh-agent
          environment: "{{ env_vars }}"
          expect:
            command: ssh-add {{ ansible_ssh_private_key_file }}
            responses:
              passphrase: "{{ ansible_ssh_pass }}"
    - name: 主要工作
      hosts: all
      gather_facts: false
      environment: "{{ hostvars['localhost']['env_vars'] }}"
      vars_files:
        - ../vars.yml
      vars:
        ansible_user: "{{username}}"
        ansible_ssh_common_args: "-o 'IdentityAgent={{ hostvars['localhost']['ssh_auth_sock'] }}'"
      tasks:
        - name: 进行ping测试
          shell: ping -c 20 -w 50 fb.me

当您运行作业时,我们可以传递-vvv选项,以查看我们的代理是否确实在与remote_host建立连接时使用。

我在输出中看到了类似以下内容:

<remote.host> SSH: EXEC ssh -C -o IdentityAgent=/var/folders/1s/rwv4vb6n01ld3sxfzqp5svtm0000gn/T//ssh-KGeKsXlC8bGO/agent.14769 -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PasswordAuthentication=no -o 'User="phanirajgoutham"' -o ConnectTimeout=10 remote.host

您可以看到在与remote_host建立连接时传递了IdentityAgent选项以及其他选项。

如果这对您有帮助,请告诉我。 1: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_environment.html 2: https://man7.org/linux/man-pages/man5/ssh_config.5.html

英文:

I think the issue here is that, the enviroment keyword, as per the doc, helps in setting the remote environment. i.e. by then the SSH connection to the remote host should have been made.

In order to change the arguments, which are used to connect to the remote_host, we need to use the ansible_ssh_common_args variable. You can use the IdentityAgent option, in the ssh_config, to specify the SSH Agent socket.

I have added a couple of statements to your solution.

 ---
    - name: setup ssh-agent
      hosts: localhost
      gather_facts: false
      vars_files:
        - ../vars.yml
      vars:
        ansible_ssh_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/{{sshkeyname}}"
        ansible_ssh_pass: "{{sshpassphrs}}"
      tasks:
        - name: Start ssh-agent and Retrieve the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables
          shell: |
              eval $(ssh-agent -s) > /dev/null
              echo '{"SSH_AUTH_SOCK":"'$SSH_AUTH_SOCK'","SSH_AGENT_PID":"'$SSH_AGENT_PID'"}'
          register: env_vars_stdout
        - name: save to env_vars
          set_fact:
            env_vars: "{{ env_vars_stdout.stdout }}"
            ssh_auth_sock: "{{ env_vars_stdout.stdout | from_json | json_query('SSH_AUTH_SOCK') }}" # install jmespath if not already present
        - name: add {{ansible_ssh_private_key_file}} to ssh-agent
          environment: "{{ env_vars }}"
          expect:
            command: ssh-add {{ ansible_ssh_private_key_file }}
            responses:
              passphrase: "{{ ansible_ssh_pass }}"
    - name: main jobs
      hosts: all
      gather_facts: false
      environment: "{{ hostvars['localhost']['env_vars'] }}"
      vars_files:
        - ../vars.yml
      vars:
        ansible_user: "{{username}}"
        ansible_ssh_common_args: "-o 'IdentityAgent={{ hostvars['localhost']['ssh_auth_sock'] }}'"
      tasks:
        - name: Do a ping test
          shell: ping -c 20 -w 50 fb.me

When you run the job, we can pass the -vvv option to, see that, our agent is actually being used when making a connection to the remote_host

I saw something like below, in the output

<remote.host> SSH: EXEC ssh -C -o IdentityAgent=/var/folders/1s/rwv4vb6n01ld3sxfzqp5svtm0000gn/T//ssh-KGeKsXlC8bGO/agent.14769 -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PasswordAuthentication=no -o 'User="phanirajgoutham"' -o ConnectTimeout=10 remote.host

You could see the IdentityAgent option being passed along with the other options, when making a connection to the remote_host.

Please let me know if this does not work for you.

huangapple
  • 本文由 发表于 2023年5月8日 00:03:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194954.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定