Ansible: how to run a play with hosts with different passwords?

16,545

Solution 1

Normally you would want to pass the sudo password on the command line after Ansible's password prompt after using either the --ask-sudo-password or its short alias -K when running with a user that doesn't have passwordless sudo. This has the benefit of then not being recorded in your Ansible code base anywhere and then not ending up in source control.

However, this is a single prompt and will be applied to all hosts so doesn't really fit your use case.

The ansibe_sudo_pass variable can instead be used to provide the sudo password for the user for any specific host. This should only be used when a sudo password is needed so if you provide this variable to a host with passwordless sudo then it should be ignored.

As your user/password combination seems to be split entirely by group rather than by each and every host then it makes logical sense to put the credentials in group vars.

As pointed out by nikobelia you may want to consider encrypting this sensitive data using something like Ansible's Vault, credstash or something else.

Solution 2

Okay, you kind of have two questions here:

How to connect to different hosts with different SSH keys?

Create a different group_vars file for each set of hosts, and set the credentials in there.

# group_vars/legacy
---
ansible_ssh_user: myuser
ansible_ssh_key: ~/.ssh/legacy_key.pem

Then Ansible will apply a different key based on which group each host is in, simple as that.

How to use different credentials per host for privilege escalation?

Once more, stick them in different group_vars files for each set of hosts:

# group_vars/legacy
---
ansible_become_user: root
ansible_become_pass: "{{ vaulted_legacy_password }}"

Then you can use the keyword become: yes to escalate privileges, and Ansible will apply the right credentials for each group. If you're already root, the become keyword just won't have any effect.

And then... see that {{ vaulted_legacy_password }} variable up there?

Best practice, and the only sensible thing to do if you are ever sharing this code, is to make an Ansible Vault file and keep your passwords in there. Ansible Vault password protects your sensitive variables and lets you decrypt them at the time of running.

You can either make your whole group_vars/legacy file vaulted (if the credentials are the only information in it), or make a group_vars/legacy folder, with one plaintext file and one encrypted file in it. All files in a subdirectory of group_vars will be sourced and applied to the group with the name of the folder.

Share:
16,545
risa_risa
Author by

risa_risa

Updated on June 14, 2022

Comments

  • risa_risa
    risa_risa almost 2 years

    I'm currently learning how to use Ansible. Right now, I've got a bunch of servers, both new and legacy, that have different logins or passwords or both. All have key access to run the plays.

    Here's what I started with. Example hosts file:

    # legacy and new have different logins (like root and deploy)
    [legacy]
    serv1
    serv2
    
    [new]
    serv3
    serv4
    
    # different has a different login and password altogether
    [different]
    serv5
    

    So to keep things simple, I originally had a playbook run the equivalent of sudo apt-get update && sudo apt-get upgrade on all the machines, but because of the different login/passwd, I had created multiple playbooks for each host. But now I want to DRY it out and am looking at Roles, per their docs.

    Right now I have something like this. The test/roles/common/tasks/main.yml file:

    ---
    - name: run apt-get update
      apt: update_cache=yes
    - name: run apt-get upgrade
      apt: upgrade=yes
    

    The site.yml file:

    - name: apply common configuration to all nodes
      hosts: all
    
      roles:
      - common
    

    I understand that I can actually define the different logins with ansible_ssh_user=root or ...=deploy in my hosts file. Or put them in group vars. But what do I do about the different sudo passwords? [legacy] is root so I don't need sudo, but [new] and [different] need it, and have different passwords. How do I do this? Group vars? Do I create these: test/group_vars/new/some_file_with_a_passwd.yml and test/group_vars/different/some_other_passwd.yml (ignoring security issues)?

    How does the site.yml recognize that there are hosts with different passwords or some hosts with no passwords?

    Edit for clarity's sake: I have SSH access, so doing the 'pre-tasks' step during the play always work (I connect via key access and never via a password). I'm not worried about security as that's the next step. For now, I want to get the group_vars thing right....It's the sudo escalation I have issues with. E.g. serv1 sudo might be root/password1, serv3 sudo: deploy/password2, serv5: anotherdeploy/password3

  • risa_risa
    risa_risa over 8 years
    Ok, so if I'm understanding you correctly (and ansible's variables), in test/group_vars/new/some_file_with_a_passwd.yml, I'd put the following? ansible_sudo_pass=whateverThePasswordis and that's it? (again, security aside.)
  • nikobelia
    nikobelia over 8 years
    If you are using any kind of source control, or sharing the code with anyone, encrypt those credentials with Ansible Vault.
  • nikobelia
    nikobelia over 8 years
    It's true that you don't need Ansible to solve this issue, but solving it in your own SSH config makes your Ansible code non-portable. Bad for any code maintained by a group, and bad if you ever want to run that playbook from another sever.
  • pmoksuz
    pmoksuz over 8 years
    hi @nikobelia your answer was wrong when i wrote this. ?! Why did you stole my answer ? its not ethic.
  • pmoksuz
    pmoksuz over 8 years
    BTW in your case you need pem keys your all local severs there is nothing change. I think we can write a task to change local ssh config for once.. It depends what your needs.
  • nikobelia
    nikobelia over 8 years
    No, dude, look at timestamps - you answered this before me. I did see your answer about SSH access and realise the OP was asking for that information too, so I edited my post to talk about the Ansible way to manage SSH keys.
  • risa_risa
    risa_risa over 8 years
    Right, I am going to be using Vault, regardless. I've got a .gitignore on any group_vars at the moment while I'm testing things out. However, when I directly put in ansible_become_user: deploy and ansible_become_pass: passw0rd1 into my group_vars and run my play, it doesn't work. I instead get either this error: msg: Failed to lock apt for exclusive operation or this: failed: [testserv1] => {"failed": true, "parsed": false} BECOME-SUCCESS-zddkeemojwrlxnblahblahhalbikigqgpwd
  • nikobelia
    nikobelia over 8 years
    From the BECOME-SUCCESS message in your output, it looks like the become command works (it manages to switch the user running tasks from the one you ssh'd in as to the deploy user), but still doesn't have rights to do that task. If you log on as deploy and try using apt manually, does it work?
  • risa_risa
    risa_risa over 8 years
    Yeah. The ansible_ssh_user and ansible_become_user are both deploy. Deploy has sudo access, and yes it does manually work.