Search code examples
authenticationdynamicansibleansible-inventory

How to incorporate password along with passwordless login in ansible dynamic inventory


I give the end user to either provide username i.e dest_user for which ssh-keys is already setup on Linux for all destination hosts i.e dest_host.

Below is how I setup dynamic inventory for passwordless user

- add_host:
    name: "{{ item }}"
    groups: dest_nodes
    ansible_user: "{{ dest_user }}"
  with_items: "{{ dest_host.split() }}"
  when: dest_user != ""

All good. The second scenario is when the user does not provide any dest_user then his SSO username (I get this from their Jenkins login) and password i.e., dest_pass which he enters manually should be used for all hosts in the dynamic inventory.

How can I construct dest_nodes group to accommodate both username for passwordless login and both username-password for SSO login?


Solution

  • You can conditionally prompt for a variable using the pause module, and use the special variable omit to make the ansible_password optional in your add_host task.

    Note: as you seems to have a pretty good idea on the way to get the user from Jenkins, I assumed it in a variable dest_user_from_jenkins, here.

    Here would be the two tasks to do so:

    - pause:
        prompt: Please enter your password
        echo: no
      register: dest_pass
      when: dest_user | default('') == ''
    
    - add_host:
        name: "{{ item }}"
        groups: dest_nodes
        ansible_user: "{{ dest_user | default(dest_user_from_jenkins) }}"
        ansible_password: "{{ dest_pass.user_input | default(omit) }}"
      loop: "{{ dest_host.split() }}"
    

    Given the playbook:

    - hosts: localhost
      gather_facts: no
      vars:
        dest_host: foo bar
        dest_user_from_jenkins: dest_user_not_set
    
      tasks:
        - pause:
            prompt: Please enter your password
            echo: no
          register: dest_pass
          when: dest_user | default('') == ''
    
        - add_host:
            name: "{{ item }}"
            groups: dest_nodes
            ansible_user: "{{ dest_user | default(dest_user_from_jenkins) }}"
            ansible_password: "{{ dest_pass.user_input | default(omit) }}"
          loop: "{{ dest_host.split() }}"
    
        - debug:
            msg: |
              user: {{ hostvars[item].ansible_user }}
              password: {{ 
                hostvars[item].ansible_password 
                  | default('password has not been set!') 
              }}
          loop: "{{ groups['dest_nodes'] }}"
    

    We end up having two possible paths:

    • When run without any extra parameter, this yields:
      TASK [pause] ***********************************************************
      [pause]
      Please enter your password (output is hidden):
      ok: [localhost]
      
      TASK [add_host] ********************************************************
      ok: [localhost] => (item=foo)
      ok: [localhost] => (item=bar)
      
      TASK [debug] ***********************************************************
      ok: [localhost] => (item=foo) => 
        msg: |-
          user: dest_user_not_set
          password: password
      ok: [localhost] => (item=bar) => 
        msg: |-
          user: dest_user_not_set
          password: password
      
    • When run with --extra-vars "dest_user=dest_user_set", this yields:
      TASK [pause] ***********************************************************
      skipping: [localhost]
      
      TASK [add_host] ********************************************************
      ok: [localhost] => (item=foo)
      ok: [localhost] => (item=bar)
      
      TASK [debug] ***********************************************************
      ok: [localhost] => (item=foo) => 
        msg: |-
          user: dest_user_set
          password: password has not been set!
      ok: [localhost] => (item=bar) => 
        msg: |-
          user: dest_user_set
          password: password has not been set!