Ansible login user logged in [duplicate] - ansible

A recurring theme that's in my ansible playbooks is that I often must execute a command with sudo privileges (sudo: yes) because I'd like to do it for a certain user. Ideally I'd much rather use sudo to switch to that user and execute the commands normally. Because then I won't have to do my usual post commands clean up such as chowning directories. Here's a snippet from one of my playbooks:
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
sudo: yes
- name: change perms
file: dest={{ dst }} state=directory mode=0755 owner=some_user
sudo: yes
Ideally I could run commands or sets of commands as a different user even if it requires sudo to su to that user.

With Ansible 1.9 or later
Ansible uses the become, become_user, and become_method directives to achieve privilege escalation. You can apply them to an entire play or playbook, set them in an included playbook, or set them for a particular task.
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
become: yes
become_user: some_user
You can use become_with to specify how the privilege escalation is achieved, the default being sudo.
The directive is in effect for the scope of the block in which it is used (examples).
See Hosts and Users for some additional examples and Become (Privilege Escalation) for more detailed documentation.
In addition to the task-scoped become and become_user directives, Ansible 1.9 added some new variables and command line options to set these values for the duration of a play in the absence of explicit directives:
Command line options for the equivalent become/become_user directives.
Connection specific variables which can be set per host or group.
As of Ansible 2.0.2.0, the older sudo/sudo_user syntax described below still works, but the deprecation notice states, "This feature will be removed in a future release."
Previous syntax, deprecated as of Ansible 1.9 and scheduled for removal:
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
sudo: yes
sudo_user: some_user

In Ansible 2.x, you can use the block for group of tasks:
- block:
- name: checkout repo
git:
repo: https://github.com/some/repo.git
version: master
dest: "{{ dst }}"
- name: change perms
file:
dest: "{{ dst }}"
state: directory
mode: 0755
owner: some_user
become: yes
become_user: some user

In Ansible >1.4 you can actually specify a remote user at the task level which should allow you to login as that user and execute that command without resorting to sudo. If you can't login as that user then the sudo_user solution will work too.
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
See http://docs.ansible.com/playbooks_intro.html#hosts-and-users

A solution is to use the include statement with remote_user var (describe there : http://docs.ansible.com/playbooks_roles.html) but it has to be done at playbook instead of task level.

You can specify become_method to override the default method set in ansible.cfg (if any), and which can be set to one of sudo, su, pbrun, pfexec, doas, dzdo, ksu.
- name: I am confused
command: 'whoami'
become: true
become_method: su
become_user: some_user
register: myidentity
- name: my secret identity
debug:
msg: '{{ myidentity.stdout }}'
Should display
TASK [my-task : my secret identity] ************************************************************
ok: [my_ansible_server] => {
"msg": "some_user"
}

Related

Ansible Failed to set permissions on the temporary files

I'd like to make a playbook that shows me the user currently in use.
this is my ansible cfg:
[defaults]
inventory=inventory
remote_user=adminek
[privilege_escalation]
become=true
[ssh_connection]
allow_world_readable_tmpfiles = True
ssh_args = -o ControlMaster=no -o ControlPath=none -o ControlPersist=no
pipelining = false
and this is my playbook
---
- name: show currenty users
hosts: server_a
tasks:
- name: test user - root
shell: "whoami"
register: myvar_root
- name: test user - user2
become: true
become_user: user2
shell: "whoami"
register: myvar_user2
- name: print myvar root
debug:
var: myvar_root.stdout_lines
- name: print myvar user2
debug:
var: myvar_user2.stdout
taks "test user - root" work fine and give me output
ok: [172.22.0.134] => {
"myvar_root.stdout_lines": [
"root"
]
}
taks "test user - user2" give me output
fatal: [172.22.0.134]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: changing ownership `/var/tmp/ansible-tmp-1621340458.2-11599-141854654478770/': Operation permited\nchown: changing ownership `/var/tmp/ansible-tmp-1621340458.2-11599-141854654478770/AnsiballZ_command.py': Operation permited\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"}
Explanation:
adminek- sudoer user
User2 - non sudoers users
OS - Scientific Linux release 6.9
Additionaly I hgad similar problem on ubuntu 18.04 but when i installed acl begun works
Someone know what is wrong?
Thanks for help!
One of the following options should fix your issue:
Ensure sudo is installed on the remote host
Ensure acl is installed on the remote host
Uncomment the following lines in /etc/ansible/ansible.cfg:
allow_world_readable_tmpfiles = True
pipelining = True
#F1ko thanks for reply.
I did what you wont and I installed acl on my host, but steal was wrong.
I added to visudo.
Defaults:user2 !requiretty
Defaults:adminek !requiretty
I dont know it's ok and secure but work.
for me it worked installing the acl package in host
- name: Install required packaged
yum:
name: "{{ item }}"
state: present
with_items:
- acl
- python3-pip
in my case I used centos/07, if you use ubuntu, change yum to apt.

Ansible pre-check before run playbook

Is it possible to add a condition before to run a playbook which check if there is a title, a description, the environment and the versions on the playbook ?
For example my test.yml playbook:
---
#Apache servers
#Linux
#Ubuntu
#version 2.1.1
#Testing for secure the webserver
task:
xxxxxx
xxxxxx
And I would like to check if all the comment before are present before to run this task !
I tried to test this solution :
name: run Apachetest playbook
include: test.yml
when: "{{ lookup('file', 'test.yml').split('\n')[1] == '#Apache servers' }}"
But still not working...
BS
Comments are, well, comments. They do not impact the execution and are just ignored. So there is no way, and actually no real reason, to check if comments are present or not. You would need to implement that yourself.
To check playbooks, roles, etc. there is ansible-lint which will verify the syntax and some best practices (e.g. if you use a command or shell for something there is a module for) but this does not verify comments (again, checking for comments does not make sense from a execution perspective, as they are ignored).
You want some information to be present in your playbook, that is what I understand. If I was you, I would either create a git hook, that verifies if the information is present before letting you push that code to your repository or establish a proper review-process, where the reviewer only accepts a merge/pull request, if the information is present.
Otherwise, here is the code, that will do what you are trying to do:
---
#Apache server
- hosts: all
tasks:
- name: set fact
set_fact:
pb: "{{ lookup('file', 'test.yml').split('\n')[1] }}"
- name: check if we found it
debug:
msg: 'found'
when: "'#Apache server' in pb"
You could use the apache role for apache installed like that
---
- hosts: apache
sudo: yes
tasks:
- name: install apache2
apt: name=apache2 update_cache=yes state=latest
have a look here how-to-install-apache-on-ansible

How to make Ansible display the host name before asking for the sudo password?

I have an Ansible playbook to update my Debian based servers. For simplicity and security reasons, I don't want to use a vault for the passwords and I also don't want to store them in a publically accessible config file. So I ask for the password for every client with
become: yes
become_method: sudo
Now, when the playbook runs, it seems the first thing Ansible does is ask for the sudo password, but I don't know for which server (the passwords are different). Is there a way to get Ansible to print the current host name before it asks for the password?
The update playbook is similar to this:
---
- hosts:
all
gather_facts: no
vars:
verbose: false
log_dir: "log/dist-upgrade/{{ inventory_hostname }}"
pre_tasks:
- block:
- setup:
rescue:
- name: "Install required python-minimal package"
raw: "apt-get update && apt-get install -y --force-yes python-apt python-minimal"
- setup:
tasks:
- name: Update packages
apt:
update_cache: yes
upgrade: dist
autoremove: yes
register: output
- name: Check changes
set_fact:
updated: true
when: not output.stdout | search("0 upgraded, 0 newly installed")
- name: Display changes
debug:
msg: "{{ output.stdout_lines }}"
when: verbose or updated is defined
- block:
- name: "Create log directory"
file:
path: "{{ log_dir }}"
state: directory
changed_when: false
- name: "Write changes to logfile"
copy:
content: "{{ output.stdout }}"
dest: "{{ log_dir }}/dist-upgrade_{{ ansible_date_time.iso8601 }}.log"
changed_when: false
when: updated is defined
connection: local
(source: http://www.panticz.de/Debian-Ubuntu-mass-dist-upgrade-with-Ansible)
Your above become configuration does not make ansible ask you for a become password: it just advises it to use become with the sudo method (which will work without any password if your have the correct keys configured for example).
If you are asked for a become password, it's because (it's a guess but I'm rather confident...) you used the --ask-become-pass option when running ansible-playbook.
In this case, you are prompted only once at the beginning of the playbook operations and this default become password will be used on all servers you connect to except if you defined an other one in your inventory for a specific host/group.
If you have different become passwords depending on your machines, you don't really have an other option: you need to declare those passwords in your inventory (and it is strongly advised to use ansible-vault encryption) or use some other mechanisms to get them out of an external application (hashicorp vault, dynamic inventory, cyberark...)

Ansible role with shared python virtual environment

I have ansible role which have task delegated to localhost:
- name: Test role
hosts: my_hosts
gather_facts: no
tasks:
- name: Register remote hosts
include_role: name=register_remote_hosts
delegate_to: localhost
The Role register_remote_systems must work for every host in my_hosts, but must be ran from the box where Ansible is invoked, that is why there is delegate_to.
The role register_remote_hosts checks for a specific application on localhost and if one is not installed it creates virtual environment and then installs it:
- name: Check if my_app is installed system-wide
shell: |
my_app --version >/dev/null 2>&1
register: my_app_cmd
failed_when: my_app_cmd.rc not in [0, 127]
- name: Install My App
block:
- name: Create temporary directory for my_app
tempfile:
state: directory
suffix: my_app
register: my_app_temp
- name: Create virtual environment
command: virtualenv "{{ my_app_temp.path }}"
- name: Install my_app
pip:
name: my_app
state: latest
virtualenv: "{{ my_app_temp.path }}"
virtualenv_site_packages: yes
- name: Set Virtual Environment variable
set_fact:
venv_activate: "source {{ my_app_temp.path }}/bin/activate"
when: my_app_cmd.rc != 0
- name: Use my_app
shell: |
{{ venv_activate | default('echo "Using my_app from system path"') }}
my_app --version
Everything works great, but if there are many hosts in my_hosts then a lot of venvs are being created.
What would be the best approach to create role which is reusing same venv with my_app installed. Note that role is included in many different playbooks and I do not want to write additional role included in every playbook where "Register remote hosts" included role is used. There is of course concurrency problem of creating venv prior to using that in other playbooks.
Above solution works and I can live with it, but maybe there are nicer design patterns for such problems in Ansible.
Solution is to put run_once (thanks #ssbarnea):
when: my_app_cmd.rc != 0
run_once: yes

how to define login user and become root in playbook

my loginuser is user1 and i want to execute the playbook with root. how can i do this. if i use in cmdline it does not work like this
ansible-playbook main.yaml -i hosts --user=git -k --become-user=root --ask-become-pass --become-method=su
Please tell me how to implement this.
name: Install and Configure IEM
hosts: rhel
ansible_become: yes
ansible_become_method: su
ansible_become_user: root
ansible_become_pass: passw0rd
tasks:
- name: Creating masthead file path
file: path=/etc/opt/BESClient state=directory
- name: Creating install directory
I use :
deploy.yml
- name: Todo something
hosts: all
become: yes
become_user: root
become_method: su
When you execute the playbook pass the password as an extra var.
--extra-vars='ansible_become_pass=password'
From Ansible docs:
you can set those in the playbook as #Raul-Hugo, with become_user and become_user;
alternatively, it can also be done in the inventory, which allows setting per host or group. But then the variables get "ansible_" prefix: ansible_become_user, ansible_become_user, etc. That's why the playbook you gave in your question did not work: it used variable names that are used in the inventory.
You can become root like below and install the packages
tasks:
- name: install apache package
become: yes
become_user: root
yum:
name: httpd
state: present
- name: ensure apache is running
become: yes
become_user: root
service:
name: httpd
state: started
All the above answers caused Ansible to try to login as root from the beginning. but in this case, the user you request is git so the below example worked for me:
- name: Install and Configure IEM
hosts: rhel
tasks:
- name: Creating masthead file path
file: path=/etc/opt/BESClient state=directory
remote_user: git
become: yes # when not specifying `become_user` it's "root"
This will cause it to login as git and after the login - switch to root

Resources