0
votes

Ansible version 2.7.9

I'm writing an ansible playbook to deploy an piece of software to a linux environment. SSH access to these systems is protected by a CPM (Cyberark), used as an ssh key manager.

I've got most of the logic figured out, save for one piece. The playbook needs to loop through hosts in an inventory group, lookup the ssh private key in Cyberark for each host and then use each key to ssh into each host in the inventory group to install the software. I'm struggling with how to make that work in ansible.

I've read through the add_host and cyberarkpassword documentation, as well about 4 hours worth of searching stackoverflow and blogs, and couldn't find a single example even close to what I'm trying to do.

As far as how I think it should work:

  • Using the cyberarkpassword lookup module, loop through hosts in inventory group specified by {{ env }}. Value for this will be passed in through --extra-args.
  • Retrieve the ssh private key for each host.
  • Register the output from the lookup, and copy to disk, again looping through each host, and naming the file with {{ inventory_hostname }}.pem
  • Finally, to consume it in the next play, set a variable ansible_ssh_common_args: "-o StrictHostKeyChecking=no -i {{ deploy_temp_dir}}/keys/{{ inventory_hostname }}.pem"

But I can't figure out how to put the loop-lookup-write to disk piece together.

Sample inventory file

[local]
localhost

[local:vars]
ansible_connection=local

[corp:children]
corp-onprem-dev
corp-onprem-stage
corp-onprem-prod
corp-cloud-dev
corp-cloud-stage
corp-cloud-dev

[corp-onprem-dev]
host1
host2
host3

[corp-onprem-stage]
host1
host2
host3
[corp-onprem-prod]
host1
host2
host3
[corp-cloud-dev]

[corp-cloud-stage]

[corp-cloud-prod]

deploy.yml -- this code does not work, just my attempt at figuring it out.

- name: retrieve ssh keys for hosts in the specified group, and write them to disk
  hosts: local
  gather_facts: no
  tasks:
    - name: lookup ssh private key for each host
      debug: msg={{ lookup("cyberarkpassword", cyquery)}}
      vars:
        cyquery:
          appid: 'myapp'
          query: 'Safe=mysafe;Folder=Root;Object={{ env[0] }}'
          output: 'Password'
      loop: groups['{{ env }}']
      register: sshkeys
    - name: Copy ssh key to disk
      copy:
        content: "{{ sshkeys }}"
        dest: "{{ deploy_temp_dir }}/keys/{{ env[0] }}.pem"
        mode: 0600
      loop: groups['{{ env }}']
1
Shouldn't the hosts retrieve their ssh private keys from Cyberark?Vladimir Botka

1 Answers

0
votes

It is not clear how to "use each (private) key to ssh into each host".

To loop through hosts in an inventory group, lookup the ssh private key in Cyberark for each host and then use each key to ssh into each host in the inventory group.

Let's assume localhost (controller) is able to connect the hosts.

Take a look at the content of the variable sshkeys

- debug:
    var: sshkeys

Among the lists, you'll probably see the 2 items that you're looking for. (Fit the code to what you get.)

sshkeys.results[].item  ...... inventory_hostname
sshkeys.results[].password ... ssh private key

Use template to store the keys in the files. Because the play is running at the localhost delegate_to shall be used to store the files at hosts.

- template:
    src: hostname.pem.j2
    dest: "{{ deploy_temp_dir }}/keys/{{ item.item }}.pem"
  loop: "{{ sshkeys.results }}"
  delegate_to: "{{ item.item }}"

.

$ cat hostname.pem.j2
{{ item.password }}

(Not tested. I don't have CyberArk. Storing passwords in disk files may violate security standards.)