Change remote_user within main.yml in role - ansible

I am new to ansible.
i am trying to create a role where i start the playbook as root and then in the next play i switch to a different user and continue. The following files are within the role itself.
---
# tasks file for /etc/ansible/roles/dashmn
#
- name: create users logged in as root
remote_user: root
import_tasks: whoami.yml
import_tasks: create_users.yml
import_tasks: set_sudoer.yml
- name: log in as dashadmin
remote_user: dashadmin
become: true
import_tasks: whoami.yml
import_tasks: disable_rootlogin.yml
import_tasks: update_install_reqs.yml
import_tasks: configure_firewall.yml
import_tasks: add_swap.yml
i added a sudoer task that adds users to /etc/sudoer.d
---
- name: set passwordless sudo
lineinfile:
path: /etc/sudoers
state: present
regexp: '^%sudo'
line: '%sudo ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
I created a deploy.yml that uses the role i created as follows.
---
- hosts: test-mn
roles:
- dashmn
when i syntax-check the deploy.yml
[DEPRECATION WARNING]: The TRANSFORM_INVALID_GROUP_CHARS settings is set to allow bad characters in group names
by default, this will change, but still be user configurable on deprecation. This feature will be removed in
version 2.10. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
[WARNING]: While constructing a mapping from /etc/ansible/roles/dashmn/tasks/main.yml, line 4, column 3, found
a duplicate dict key (import_tasks). Using last defined value only.
[WARNING]: While constructing a mapping from /etc/ansible/roles/dashmn/tasks/main.yml, line 10, column 3, found
a duplicate dict key (import_tasks). Using last defined value only.
Any help on how to organize this to make it better would be appreciated.
Now, my problem is that if in the tasks file i remove the plays themselves and just leave the import_tasks everything works but its not using the user dashadmin, its using root.
i would like to create the users and then only ever login as dashadmin and work as dashadmin.
I also get an error
FAILED! => {"msg": "Missing sudo password"}
something is clearly wrong, just not sure where ive gone wrong.
Here is /etc/sudoers file
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL) NOPASSWD: ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d

First of all, the way you defined import_tasks will basically executes the last import_tasks only as the warning says.
Secondly, remote_user is used for logging in to defined host(s) but if you want to login as a user then execute tasks using a different user then you need to define become_user. By default, become_user is set to root.
So probably below is how you can change the role's import_tasks:
/etc/ansible/roles/dashmn/tasks/main.yml
- name: create users logged in as root
block:
- import_tasks: whoami.yml
- import_tasks: create_users.yml
- import_tasks: set_sudoer.yml
remote_user: root
- name: log in as dashadmin
block:
- import_tasks: whoami.yml
- import_tasks: disable_rootlogin.yml
- import_tasks: update_install_reqs.yml
- import_tasks: configure_firewall.yml
- import_tasks: add_swap.yml
remote_user: dashadmin
become: yes
Refer privilege escalation for more details.

Q: "Change remote_user within main.yml in a role"
Short answer: See the example in "Play 3" on how to change remote_user for each task.
Details: Keyword remote_user can be used in all playbook's objects: play, role, block, task. See Playbook Keywords.
The best practice is to connect to the remote host as an unprivileged user and escalate the privilege. For example,
- name: Play 1
hosts: test_01
remote_user: user1
become: true
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
gives
ok: [test_01] =>
result.stdout: root
Without the escalation of priviledge the tasks will be executed by the remote_user at the remote host. For example,
- name: Play 2
hosts: test_01
remote_user: user1
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
gives
ok: [test_01] =>
result.stdout: user1
It's possible to declare the remote_user for each task. For example
- name: Play 3
hosts: test_01
remote_user: user1
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
- command: whoami
remote_user: user2
register: result
- debug:
var: result.stdout
gives
ok: [test_01] =>
result.stdout: user1
ok: [test_01] =>
result.stdout: user2
All plays can be put into one playbook.
Example of sudoers file
root.test_01# cat /usr/local/etc/sudoers
...
#includedir /usr/local/etc/sudoers.d
admin ALL=(ALL) NOPASSWD: ALL
user1 ALL=(ALL) NOPASSWD: ALL
user2 ALL=(ALL) NOPASSWD: ALL

Related

set ansible_user for specific task in role

I am stumbling over setting the ansible_user (or remote_user) for a specific task in a role.
What works fine is to set the ansible_user in host or group vars and the role and tasks are using this user for ssh into the server.
What I want to achieve is to set an remote user for a specific task in a role.
So I have a main.yml where different tasks are included.
For one if them I want to set the ansible_user: user2
But I tried different variants, every time I execute the play with this role the ansible_user, defined in group or host vars will be used:
- name: "include user_create.yml"
include_tasks:
file: "user_create.yml"
apply:
become: yes
remote_user: user2
vars:
- become: yes
- remote_user: user2
- ansible_user: user2
tags:
- user_create
I tried almost all variants of the above settings but no luck.
Does anyone has an idea?
UPDATE:
This should work according to Zeitounator but did not work for me either:
- name: "include user_create.yml"
include_tasks:
file: "user_create.yml"
apply:
ansible_user: user2
tags:
- user_create
UPDATE2:
So i was able to set a different user to a task like this:
- name: "include user_create.yml"
include_tasks:
file: "user_create.yml"
#apply:
# become: yes
vars:
ansible_user: user2
tags:
- user_create
but only if there is no ansibl_user defined in all.yml.
So from my understanding a block or task var should overwrite a group var (all.yml is a group var from my understanding).
remote_user is a play level stanza. The variable to use elsewhere is ansible_user. I suspect what you want exactly is:
- name: "include user_create.yml"
include_tasks:
file: "user_create.yml"
apply:
become: yes
ansible_user: user2
tags:
- user_create
tags:
- always

`remote_user` is ignored in playbooks and roles

I have defined the following in my ansible.cfg
# default user to use for playbooks if user is not specified
# (/usr/bin/ansible will use current user as default)
remote_user = ansible
However I have a playbook bootstrap.yaml where I connect with root rather than ansible
---
- hosts: "{{ target }}"
become: no
gather_facts: false
remote_user: root
vars:
os_family: "{{ osfamily }}}"
roles:
- role: papanito.bootstrap
However it seems that remote_user: root is ignored as I always get a connection error, because it uses the user ansible instead of root for the ssh connection
fatal: [node001]: UNREACHABLE! => {"changed": false,
"msg": "Failed to connect to the host via ssh:
ansible#node001: Permission denied (publickey,password).",
"unreachable": true}
The only workaround for this I could find is calling the playbook with -e ansible_user=root. But this is not convenient as I want to call multiple playbooks with the site.yaml, where the first playbook has to run with ansible_user root, whereas the others have to run with ansible
- import_playbook: playbooks/bootstrap.yml
- import_playbook: playbooks/networking.yml
- import_playbook: playbooks/monitoring.yml
Any suggestions what I am missing or how to fix it?
Q: "remote_user: root is ignored"
A: The playbook works as expected
- hosts: test_01
gather_facts: false
become: no
remote_user: root
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
gives
"result.stdout": "root"
But, the variable can be overridden in the inventory. For example with the inventory
$ cat hosts
all:
hosts:
test_01:
vars:
ansible_connection: ssh
ansible_user: admin
the result is
"result.stdout": "admin"
Double-check the inventory with the command
$ ansible-inventory --list
Notes
It might be also necessary to double-check the role - role: papanito.bootstrap
See Controlling how Ansible behaves: precedence rules
I faced a similar issue, where ec2 instance required different username to ssh with. You could try with below example
- import_playbook: playbooks/bootstrap.yml
vars:
ansible_ssh_user: root
Try this
Instead of “remote_user: root”use “remote_user: ansible” and additional “become: yes” ,”become_user: root”,”become_method: sudo or su”

Ansible systemctl --user for another user

I'm logging into another computer as the unprivileged user ansible and I'd like to have ansible enable a systemd user service for the user bob.
Without ansible, the solution would be ssh bob#machine followed by systemctl --user enable service
However, with ansible, there are two problems:
Newer versions of ansible will refuse to become the unprivileged user bob if already logged in as another unprivileged user (ansible).
Even if this worked, dbus would not be started and systemctl would not be able to talk to systemd (if I understood this correctly).
A horribly ugly workaround would be to execute the shell command, have the remote host ssh into itself as bob and run the systemctl raw command there.
Is there a nicer way to get this done?
Both options are feasible.
remote_user: bob
- hosts: test_01
become: no
remote_user: admin
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
- command: whoami
remote_user: bob
register: result
- debug:
var: result.stdout
gives (abridged)
result.stdout: admin
result.stdout: bob
pipelining = true quoting from Becoming an Unprivileged User
Use pipelining. When pipelining is enabled, Ansible doesn’t save the module to a temporary file on the client. Instead, it pipes the module to the remote python interpreter’s stdin. Pipelining does not work for python modules involving file transfer (for example: copy, fetch, template), or for non-python modules.
- hosts: test_01
become: no
remote_user: admin
tasks:
- command: whoami
register: result
- debug:
var: result.stdout
- command: whoami
become_user: bob
become_method: sudo
become: yes
register: result
- debug:
var: result.stdout
gives (abridged) the same result
result.stdout: admin
result.stdout: bob
with
shell> grep pipe ansible.cfg
pipelining = true

Ansible vars_prompt for roles

I have a set of Ansible playbooks and the main yml file is like this
- hosts: all
roles:
- common
- install_nginx
I want to add the confirm message when I trigger the playbook. I tried this and did not work
- hosts: all
vars_prompt:
- name: CONFIRM
prompt: Just to confirm you will install stuff
tasks:
- fail: no deployment this time
when: CONFIRM != 'yes'
roles:
- common
- install_nginx
How can I use vars_prompt in this case without modify every role?
If you look at the output from running your playbook with the vars_prompt you'll see that the fail task runs after the other roles. This is also mentioned in the Ansible docs for playbooks and roles:
If the play still has a ‘tasks’ section, those tasks are executed
after roles are applied.
As the above docs also mention if you want to force a task to run before any roles then you can use pre_tasks.
So to have your confirmation style prompt you could simply do this:
- hosts: all
vars_prompt:
- name: CONFIRM
prompt: Just to confirm you will install stuff
pre_tasks:
- fail: no deployment this time
when: CONFIRM != 'yes'
roles:
- common
- install_nginx
I am not very sure, but the way this works is :
- hosts: all
vars_prompt:
- name: "confirm"
prompt: Just to confirm you will install stuff
private: no
default: "no"
tasks:
- name: Install Nginx
apt: name=nginx
sudo: true
when: confirm == "yes"
Now if we need to call each role based on a condition , i suppose we shoud be using tags.
How to use Ansible vars_prompt for roles
i got the solution to use vars_prompts in ansible role section
i have directly included vars_prompt in my main.yml playbook as like before
- hosts: "{{HOSTS}}"
gather_facts: yes
become: yes
roles:
- syslog
- splunk
- nmon
- trendmicro
- user-creation
- extened-history
vars_prompt:
- name: "user_password"
prompt: "Enter User Password"
private: yes
confirm: yes
==========================================================
Below is the ansible command to execute the playbook
# ansible-playbook ort-linux.yml -e "HOSTS=TESTSERVER"
Enter User Password:
confirm Enter User Password:
========================================================
Below is my roles playbook for user id creation
---
- name: "Task-1 create Linux Team user"
user:
name: "{{item}}"
comment: LINUX_UNIX_TEAM
group: LINUX_UNIX_TEAM
shell: /bin/bash
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
createhome: yes
password: "{{user_password|password_hash('sha512')}}"
loop:
- sam
- jack
- kumar
- ravi
tags: linuxuser

Set remote_user for set of tasks in Ansible playbook without repeating it per task

I am creating a playbook which first creates a new username. I then want to run "moretasks.yml" as that new user that I just created. Currently, I'm setting remote_user for every task. Is there a way I can set it for the entire set of tasks once? I couldn't seem to find examples of this, nor did any of my attempts to move remote_user around help.
Below is main.yml:
---
- name: Configure Instance(s)
hosts: all
remote_user: root
gather_facts: true
tags:
- config
- configure
tasks:
- include: createuser.yml new_user=username
- include: moretasks.yml new_user=username
- include: roottasks.yml #some tasks unrelated to username.
moretasks.yml:
---
- name: Task1
copy:
src: /vagrant/FILE
dest: ~/FILE
remote_user: "{{newuser}}"
- name: Task2
copy:
src: /vagrant/FILE
dest: ~/FILE
remote_user: "{{newuser}}"
First of all you surely want to use sudo_user (remote user is the one that logs in, sudo_user is the one who executes the task).
In your case you want to execute the task as another user (the one previously created) just set:
- include: moretasks.yml
sudo: yes
sudo_user: "{{ newuser }}"
and those tasks will be executed as {{ newuser }} (Don't forget the quotes)
Remark: In most cases you should consider remote_user as a host parameter. It is the user that is allowed to login on the machine and that has sufficient rights to do things. For operational stuff you should use sudo / sudo_user
You could split this up into to separate plays? (playbooks can contain multiple plays)
---
- name: PLAY 1
hosts: all
remote_user: root
gather_facts: true
tasks:
- include: createuser.yml new_user=username
- include: roottasks.yml #some tasks unrelated to username.
- name: PLAY 2
hosts: all
remote_user: username
gather_facts: false
tasks:
- include: moretasks.yml new_user=username
There is a gotcha using separate plays: you can't use variables set with register: or set_fact: in the first play to do things in the second play (this statement is not entirely true, the variables are available in hostvars, but I recommend not using variables between roles). Defined variables like in group_vars and host_vars work just fine.
Another tip I'd like to give is to look into using roles http://docs.ansible.com/playbooks_roles.html. While it might seem more complicated at first, it's much easier to re-use them (as you seem to be doing with the "createuser.yml"). Looking at the type of things you are trying to achieve, the 'include all the things' path won't last much longer.
Kind of inline with your issue. Hope it helps. While updating my playbooks for Ansible 2.5 support for Cisco IOS network_cli connection
Credential file created with ansible-vault: auth/secrets.yml
---
creds:
username: 'ansible'
password: 'user_password'
Playbook:
---
- hosts: ios
gather_facts: yes
connection: network_cli
become: yes
become_method: enable
ignore_errors: yes
tasks:
- name: obtain login credentials
include_vars: auth/secrets.yml
- name: Set Username/ Password
set_fact:
remote_user: "{{ creds['username'] }}"
ansible_ssh_pass: "{{ creds['password'] }}"
- name: Find info for "{{ inventory_hostname }}" via ios_facts
ios_facts:
gather_subset: all
register: hardware_fact
Running playbook without auth/secrets.yml creds:
ansible-playbook -u ansible -k playbook.yml -l inventory_hostname

Resources