1

I have a collection of playbooks and roles that build a fairly complex application platform: several playbooks, several roles, and multiple inventory files define specific variants of the platform. During the build I need to enter usernames / passwords for: database accounts, to access git to pull code down, etc.

I want to prompt for all credentials, for all playbooks, right after the ansible-playbook command is issued (e.g. in the first playbook). Collecting them in multiple playbooks as and when they are required would mean pausing the build at various points several minutes apart, so I'd rather get all credentials in one go right at the beginning.

I also want the ability to have default values for the credentials for when I'm developing the Ansible playbooks or building a simple test environment, and don't need to cut-and-paste real credentials from a password manager. Defaults mean I can hit return several times to accept pre-defined defaults and quickly get on to the playbooks and roles that actually build something.

Ansible Vault is an option, but seems excessive for my simple requirement, and password managers are the normal solution for my organisation in this situation so I'd be duplicating credentials if I introduced Vault.

I've looked at vars_prompts, but that is unsuitable for several reasons including that: the scope of the variables is just the current playbook so I can't use them later on; and that group_vars are not available to the vars_prompt section so I can't control which variables are asked for, based upon the variables defined in the inventory file.

I've looked at the pause module, which can access group_vars, together with when clauses, and set_facts to make vars available later on. Some example, working, code is below, but it is quite verbose, requiring a pause task and two set_facts for each piece of data collected.

But the first question is really, is there a better and standard solution to this problem in Ansible? Collecting all credentials at the start of playbook execution seems such an obvious requirement, yet I can't seem to find a standard solution to this issue anywhere.

Working Example, but is there a better way to do this?

  pre_tasks:
  - name: "get username"
    pause:
      prompt: "Enter username [defaultusername]"
    register: username
    run_once: yes
  - name: username after pause command is
    debug:
      msg: "{{username}}"

  - name: set_fact for default username
    set_fact:
      username_fact: "defaultusername"
    when: username.user_input == ""

  - name: set_fact for non-default username
    set_fact:
      username_fact: "{{username.user_input}}"
    when: username.user_input != ""

  - name: username_fact
    debug:
      msg: "username_fact is {{username_fact}} "
P Burke
  • 163
  • 1
  • 10
  • Have you considered writing an inventory plugin that can pull passwords out of your password manager? – Michael Hampton Sep 19 '19 at 19:45
  • I hadn't considered that. A good idea. Although probably no better than ansible vault in my case, due to the way password files are managed; I would still have to duplicate the password file onto the Ansible control node, because at the moment it sits on a jump server to which the Ansible control node has no access. – P Burke Sep 20 '19 at 09:07

1 Answers1

0

IMHO you're not automating things correctly when you desire to develop solutions that will always depend on manual user input. Doing so will also make it difficult if not impossible to run playbook automatically (from Ansible Tower / AWX)

Ansible vault is the defacto standard to securely provide your playbooks with secrets, but when you use Ansible-Tower you have other options and can pull in secrets from external systems as well: Seee the docs

I would simply store the credentials/secrets your playbooks will use in a variable file.

Keep those variable files in clear text (with default values) for your development when you find Ansible vault to be too cumbersome to use there.

In production use a different variables file and either use the vault to encrypt those files in their entirety or use the option of vault to encrypt only the values of specific variables, resulting securely stored secrets in files that are still readable like this:

notsecret: myvalue
mysecret: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236336462626566653063336164663966303231363934653561363964363833313662
          6431626536303530376336343832656537303632313433360a626438346336353331386135323734
          62656361653630373231613662633962316233633936396165386439616533353965373339616234
          3430613539666330390a313736323265656432366236633330313963326365653937323833366536
          34623731376664623134383463316265643436343438623266623965636363326136
other_plain_text: othervalue

See https://docs.ansible.com/ansible/2.4/playbooks_vault.html#single-encrypted-variable

HBruijn
  • 72,524
  • 21
  • 127
  • 192
  • 1
    The lookup plugins that power Tower / AWX's credential store are also available for Ansible Engine without AWX. Vault your variables, or define them with lookup in a Jinja expression. – John Mahowald Sep 19 '19 at 14:15
  • OK, I guess Vault it is then. Just makes it messy in the short term as I need to keep the credentials in two places: Ansible Vault and in the password manager where the support teams will retrieve them from. Guess I need to advocate a secrets solution that supports multiple client types: Ansible, humans, etc. – P Burke Sep 19 '19 at 14:48
  • Update: took about 30 minutes to implement ansible-vault. Far easier than expected, and does exactly what I want. – P Burke Sep 23 '19 at 07:48