I know my question is what become is designed to solve. And I do use it. However, my command seems to still be run as the ssh user. I'm trying to execute a which psql command to get the executable path. Running which psql as ssh user gives a different output than running the same command as my become user which is the output I want.
EDIT The problem is the $PATH variable ansible is using as suggested in comments. It is not using the correct $PATH variable. How can I direct ansible to use postgres users $PATH variable? Using environment module didn't work for me as suggested here https://serverfault.com/questions/734560/ansible-become-user-not-picking-up-path-correctly
EDIT2 So a solution is to use the environment module and set the path to the path I know has the psql executable but this seems hacky. Ideally, I'd like to just be able to use the become users path and not have to explicitly set it. Here's the hacky solution:
- name: Check if new or existing host
command: which psql
environment:
PATH: "/usr/pgsql-13/bin/:{{ansible_env.PATH}}"
become: yes
become_user: postgres
Playbook
---
- name: Playbook Control
hosts: all
become: yes
become_user: postgres
tasks:
- name: Check if new or existing host
shell: whoami && which psql
register: output
Relevant Output (the same as if I were to run the task command as my_user on myhost.net)
"stdout_lines": [
"postgres",
"/usr/bin/psql"
]
Expected Output (the output if I were to run the task command as postgres user on myhost.net)
"stdout_lines": [
"postgres",
"/usr/pgsql-13/bin/psql"
]
Inventory
myhost.net
[all:vars]
ansible_connection=ssh
ansible_user=my_user
Command
ansible-playbook --ask-vault-pass -vvv -i temp_hosts playbook.yml
In vault I only have the ssh pass of my_user.
Running the playbook with -vvv flag shows me that escalation was successful and that the output of this task is the output of running the command as ssh user, not become user. Any ideas?
Ansible by default uses sudo as the default become method.
Depending on how your linux system is configured (check /etc/sudoers), it could be that your $PATH variable is preserved for sudo commands.
You can either change this, or force ansible to use a different become method such as su:
https://docs.ansible.com/ansible/latest/user_guide/become.html#become-directives
Related
When trying to add a user using Ansible, I set ansible_become_user in my inventory to an account on the server that is a sudoer, but adding a user still fails with this error:
usermod: cannot open /etc/passwd usermod: failed to unlock /etc/passwd
I tested on the server running the command like this from my normal ssh account:
sudo -u <sudo_user> useradd test
useradd: cannot open /etc/passwd
useradd: failed to unlock /etc/passwd
If I su to my sudo account and run sudo useradd test, it works just fine.
I can also get it to work from my base SSH account by running su <sudo_user> -c "sudo useradd test".
The variable to set on your playbook/task is become_user not ansible_become_user. ansible_become_user is used when you set the value for a specific host/group in your inventory. See the privilege escalation doc
Moreover, you also have to set become: true for the above option to have any effect.
A quick example (does not become anything with debug, just to put you on track)
---
- hosts: all
become: true
become_user: someone
tasks:
- name: dummy task with play's defaults
debug:
msg: I would run with play's become_user
- name: dummy task with overriden user
become_user: some_other
debug:
msg: I would run with the overriden become_user
You can try another option, that is execute it like other user, for example root, and try it again.
For do it, edit /etc/sysconfig/jenkins
Then search for:
JENKINS_USER="jenkins"
And change it for
JENKINS_USER="root"
This should resolve the issue.
Another way is to add jenkins to visudo
How to show a process list using ansible ad-hoc command?
Ansible Ad-hoc Syntax:
ansible <"hosts"> [-m <"module_name">] -a <"arguments"> -u [--become]
Ex:
ansible <"hosts"> -m shell -a 'ps -ef'
Hosts: It can be any entry in the inventory file. For specifying all hosts in inventory, use all or '*'. Wild card patterns are also accepted.
module_name: It's an optional parameter. There are hundreds of modules available in Ansible. By default it is a command. For example, shell, copy, yum, apt, file.
Arguments: We should pass values that are required by the module. It may change according to the module used.
Username: It specifies the user account in which Ansible can execute commands. User account, SSH.
Become: It's an optional parameter specified when we want to execute operations that need sudo privilege. By default become is false.
PS: If you put a -c option, then Ansible will do a dry run of the command. It will not actually be applied on the nodes.
I'm trying yo push my dot files and some personal configuration files to a server (I'm not root or sudoer). Ansible connects as my user in order to edit files in my home folder.
I'd like to set my default shell to usr/bin/fish.
I am not allowed to edit /etc/passwd so
user:
name: shaka
shell: /usr/bin/fish
won't run.
I also checked the chsh command but the executable prompt for my password.
How could I change my shell on such machines ? (Debian 8, Ubuntu 16, Opensuse)
I know this is old, but I wanted to post this in case anyone else comes back here looking for advise like I did:
If you're running local playbooks, you might not be specifying the user and expecting to change the shell of user you're running the playbook as.
The problem is that you can't change the shell without elevating the privileges (become: yes), but when you do - you're running things as root. Which just changes the shell of the root user. You can double check that this is the case by looking at /etc/passwd and seeing what the root shell is.
Here's my recipe for changing the shell of the user running the playbook:
- name: set up zsh for user
hosts: localhost
become: no
vars:
the_user: "{{ ansible_user_id }}"
tasks:
- name: change user shell to zsh
become: yes
user:
name: "{{ the_user }}"
shell: /bin/zsh
This will set the variable the_user to the current running user, but will change the shell of that user using root.
I ended up using two ansible modules :
ansible expect
ansible prompt
First I record my password with a prompt :
vars_prompt:
- name: "my_password"
prompt: "Enter password"
private: yes
And then I use the module expect to send the password to the chsh command :
tasks:
- name: Case insensitve password string match
expect:
command: "chsh -s /usr/bin/fish"
responses:
(?i)password: "{{ my_password }}"
creates: ".shell_is_fish"
The creates sets a lock file avoiding this task to be triggered again. This may be dangerous because the shell could be changed after and ansible will not update it (because of the lock still present). You may want to avoid this behaviour.
Here is how I do it:
- name: Set login shell of user {{ ansible_env.USER }} to `/bin/zsh` with `usermod`
ansible.builtin.command: usermod --shell /bin/zsh {{ ansible_env.USER }}
become: true
changed_when: false
Ubuntu 16
add first line in ~/.bashrc
/usr/bin/fish && exit
I try configure ansible for become other user:
My ansible.cfg entries
sudo_flags=
ssh_args = -t -t
sudo_exe = sudo /bin/su
I can escalate privilege on remote host only one way (and this works in ssh session):
sudo /bin/su anyuser -
Example playbook:
---
- hosts: anyhosts
become: true
become_user: anyuser
tasks:
- name: check becoming anyuser
command: "ls -ltha"
When i run my simple playbook, in verbose log output i see -u option:
'"'"'sudo /bin/su -u anyuser -
How i can disable/remove this -u option in playbook or ansible.cfg?
You have told Ansible that sudo is sudo /bin/su, but as far as Ansible knows it's still using sudo, which supports -u argument. If you want to use some other command for privilege escalation, consider setting become_method.
However, it's not clear why you're not just using sudo, since you appear to have sudo privileges. Possibly setting sudo_exe = sudo sudo would actually solve the problem, since the first sudo would get you root access (which appears to work just fine, based on your question), and then root would be able to run sudo -u ..., which should work just fine.
I am trying to overcome some limitations in our environment to write up an authorized SSH file for passwordless ssh keys.
I am requiring to perform an ssh as a to a target system, and then run a "sudo su - , and then update the service account authorized_keys with a key"
This eventually has to go onto my ansible scripts.
I am using "ssh -t user#target "sudo su - service-user" - which actually successfully gets me into a shell for service-user. But I am not able to figure out a way to pass along the file modify commands with the above.
Any tips or alternative options?
Note: I need to use "ssh -t" option as the requiretty is not set on target systems.
Cheers!
Depending on what transport you're using you can use ssh_args.
OpenSSH is the default connection type for Ansible on OSes that are new enough to support ControlPersist. (This means basically all operating systems except Enterprise Linux 6 or earlier).
Then you can do something like this in your ansible.cfg:
ssh_args = -t -t
Which will force ansible to connect the same way you do manually.
Then in your playbook or together with the task where you need it specify become and become_user
- name: Some task
debug: msg="this is a test"
become: true
become_user: someuser
su has an option, -c, that allows you to pass along a command to execute instead of launching a new shell.
-c, --command=COMMAND
pass a single COMMAND to the shell with -c
However, you're authenticating with sudo, which already does this by default; you can just cut su out of the command entirely:
ssh -t user#target "sudo -u service-user <your-command>"
To go one step further, you note that you're planning on putting this into an Ansible playbook. If so, you probably shouldn't be spending too much time trying to do this manually - Ansible will handle running commands remotely (that's one of its primary features, after all), and has a module for modifying the authorized_keys file.