0

I have several clouds, where each has a different user that we need to login to in order to become root (for installing services).

Now, the first time that we receive a new server, we login as root, define our service account, then all playbooks from this point are logging in with the service account to run tasks.

The issue is: the first part of "login as root". Basically every set of servers are using something different, for example:

  1. One of servers cloud are using directly root@myserver to login
  2. Other servers cloud are using an admin@myserver to login then we need to say become: yes

Our inventory in the above case is something like:

[myserver_cloud1]
# server that requires an admin user and from there to become root
x.x.x.x ansible_user=admin ansible_become=yes

[myserver_cloud2]
# root is by default in the playbook i just say become: yes
z.z.z.z

The playbook then, has an issue: ansible_user will always override any remote_user: {{service_account}} used inside the playbooks.

So I thought of doing something different, inventory will always say ansible_user=my_service_account but, then, how can I differentiate in the playbook "how" to login as root ( directly, or via admin user then sudo ) based on the cloud type?

So I'm not sure what's the right way to configure inventory/playbooks to be able to:

  1. Sometimes run the playbook as root
  2. By default run the playbook as my service account

Edit - Adding an example to reproduce

See the following playbook

---
- name: Testing clouds
  hosts: "{{ ansible_limit | default(all) }}"
  gather_facts: false  
  roles:
    - defaults
    - webserver

  tasks:
    - name: Testing something
      shell: "whoami"

no matter what I try: become:yes or whatever, one set fails, and the other set works:

x.x.x.x   : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0
z.z.z.z   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Any ideas? I want to avoid from saying -u in the command line.

Ricky Levi
  • 7,298
  • 1
  • 57
  • 65
  • 2
    Just set the correct service account for each target (either a "real" service account, or admin or root) and set `become: true` for any play/task that actually needs it. root can become root without any problem, and a service account can switch to root as long as you gave the appropriate escalation authorizations. – Zeitounator May 14 '23 at 11:30
  • 2
    _The playbook then, has an issue - `ansible_user` will always override any `remote_user: {{service_account}}` used inside the playbooks._ > I kind of feel a misconception in here. `remote_user` and `ansible_user` are indeed [the same](https://stackoverflow.com/questions/36668756/ansible-remote-user-vs-ansible-user), but why would you use any of those in your playbook? You should use `become_user` and `become` in a playbook rather (as already pointed by @Zeitounator). – β.εηοιτ.βε May 14 '23 at 11:32
  • @β.εηοιτ.βε Because the default of Ansible ( when i don't set anything in the inventory ) - is `root`, so I set inside the playbooks at the top `remote_user: service_account` - this way, i know all tasks at this file - run with the same user no matter which cloud I choose. – Ricky Levi May 14 '23 at 11:35
  • @Zeitounator but I can't just say `become: true` because my service_account in some clouds can be root - and in some - cannot. so I need to login as `admin@server` and then become root ( the way towards being "root" is different in each cloud ) and my issue here - how can I configure it in such way - that it will alway work no matter which cloud i'm working on – Ricky Levi May 14 '23 at 11:37
  • Well, then don't give that information in the playbook and migrate this setting in your inventory. Yes indeed a variable defined in a playbook is going to win over an inventory / group variable, as it has higher precedence, see the table at https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#understanding-variable-precedence – β.εηοιτ.βε May 14 '23 at 11:37
  • @β.εηοιτ.βε then i'm confused ... `remote_user: service_account` in the playbook doesn't do anything, and keep using the `ansible_user` in the inventory – Ricky Levi May 14 '23 at 11:50
  • The thing being, you question ends up being _I want to avoid using `-u` in the command line._; which is yours to answer, ultimately. Is there something you can gather for the node(s) or from somewhere else that would avoid you having to specify it? Because, yes, it can be done differently, but how is, for example, specifying another host target be different than specifying `-u root`? – β.εηοιτ.βε May 14 '23 at 11:52
  • `I can't just say become: true because my service_account in some clouds can be root ` <= Read my above comment `root can become root without any problem` – Zeitounator May 14 '23 at 11:53
  • @β.εηοιτ.βε it's different because we define the cloud once in our inventory, while `-u` people need now to remember which user belong to which cloud on every ansible run – Ricky Levi May 14 '23 at 11:55
  • @Zeitounator yes, root can become root - but I cannot login as root@server to some clouds, I've edited my question to include a small snippet. – Ricky Levi May 14 '23 at 11:58
  • @RickyLevi still your inventory is not cast in stone, as you have to use a different way of connecting for the same node based on X,Y,Z conditions. If you can identify what they are and write them in a code logic, then you can write that in an inventory / group variable or in a playbook task. But still that question is **yours** to answer. – β.εηοιτ.βε May 14 '23 at 12:00
  • 1
    --- and that is why you set an account user and `become: true` when you need (even if that account user is already root). And as suggested by @β.εηοιτ.βε your can even `become_user: whatever, become:true` if you need to act as any user on the machine. – Zeitounator May 14 '23 at 12:01
  • @Zeitounator oh you right, `remote_user: service_account` doesn't work on all clouds, but `become_user: service_account` + `become: yes` does work ! ... do you think this is the way I should handle it ? ( asking about structure ) or there's a better way ? what would you do ? – Ricky Levi May 14 '23 at 12:06
  • Maybe one way we can put it that would make it clearer for you: Ansible does (in a really simplified way) `ssh {{ ansible_user }}@some_node` then `sudo -u {{ become_user }} ./my_task`. Run the playbook in verbose mode with the option `-vvv` if you want to understand the mechanics better. – β.εηοιτ.βε May 14 '23 at 12:07
  • @β.εηοιτ.βε that i understand, this is how I configured it at first, what confused me is in the playbook, `remote_user` vs `become & become_user` I thought that it was better to use `remote_user` to make it `remote_user@server` vs login as root - then switch to the user ... – Ricky Levi May 14 '23 at 12:13
  • 2
    That all depends on what you are doing (in terms of tasks), but you might want to read about the limitation of logging and/or becoming a non privileged user there: https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_privilege_escalation.html#risks-of-becoming-an-unprivileged-user and on this page in general – β.εηοιτ.βε May 14 '23 at 12:17
  • 1
    A dummy example might help: https://gist.github.com/zeitounator/0e7a0320fbd157b47ea51b1d3397453e – Zeitounator May 14 '23 at 12:20

1 Answers1

0

I've come across similar pain points. If you're using a username/password for authentication, instead of ssh keys for example this should work for you too.

I create vaulted credential files (using ansible-vault), in my case named matching the AD domain. Then import them using include_vars and the when keyword as needed.

These files set the ansible_user and ansible_password special variables, which makes those values the new username and password for connections. You can also include the become keywords here as well.

P.S. if you need to do any pre-handing before deciding which cred to use you can delegate those tasks to localhost.