So I have been doing some rsa-key based to factor authentication work recently, but have hit a stumbling block with Ansible. Has anyone ever done key based privilege escalation? Apparently just use the ssh connection option ForwardAgent=true is not quite the same as “ssh -A” when doing escalation.
Before I get advice to just use passwordless sudo, that is something I am looking for a way to avoid as it generates a massive amount of paperwork in the federal FISMA high and med spaces that require MFA and expected MFA elevated privilege access.
Manually I am very successful with the RSA key
[user@localhost vagrant-kube]$ ssh -A 10.0.0.18
1 device has a firmware upgrade available.
Run fwupdmgr get-upgrades for more information.
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Wed Aug 16 14:07:25 2023 from 10.0.0.10
[user@kube ~]$ sudo whoami
root
[user@kube ~]$ exit
logout
However Ansible is not making the same connections:
I have tried several options, and assume it is going to end up being something in the SSH connection options to get this working beyond using “ForwardAgent=Yes”
I haven’t tested this myself, but this article mentions that you’d need to set ansible_become_pass var somewhere with a potential dummy value. Give it a try !
You can control what arguments Ansible uses to invoke the ssh binary with. See ssh_extra_args [1] for ways to set extra arguments. You can run Ansible with -vvv and it will show you the full ssh command being run on each connection.
Using ssh_extra_args does not solve the issue. There is already 2 other methods of ensuring the ssh side of the house work. The core issue turns out to be something of a known bug in ansible
, ansible wants a password if you are not using passwordless sudo. The article linked by Pierre discovered ot.
This was easy to confirm by simple adding the “ansible_become_pass” with a garbage setting and it works, remove variable and it fails. Not sure if the ansible team is planning to address this or not.
ansible wants a password if you are not using passwordless sudo. The article linked by Pierre discovered ot.
Ansible only wants a password if it gets prompted by sudo for one, if there is no prompt there is no mandatory password. You can definitely use become sudo without a password normally and not have a password set.
Not true. If you dint give it a password and use rsa sudo it still.asks for password. Follow the article Pierre linked and you can reproduce the issue, i am using ansible 2.14. The only change between working and not working is setting a dummy password. I started with using the ssh args which did not work.
What I’m trying to say is that sudo is still writing the password is required message which then causes Ansible to say the password is required. If sudo doesn’t write this line then Ansible won’t say it needs a password ansible_become_pass.
So ultimately the reason why you are seeing this error is because sudo is writing one of those 2 responses to the stdout/stderr of the ssh process and the become plugin is flagging that as the password needs to be set. What should be investigated is why the sudo invocations done without the password is causing sudo to display this error vs why it accepts a dummy password. Also knowing why it’s working for an interactive command outside of Ansible vs the non-interactive command being run by Ansible when there is no password.
If you run with ‘-vvv’ you can see the exact commands Ansible is running for each task which will show both the ssh arguments as well as the sudo arguments being run on the ssh target. When you run with a set sudo password the ‘-p “[sudo via ansible, key=random] password:”’ argument is going to be added to the sudo prompt but I cannot see any other changes. Playing around with these commands can give you a way to try and replicate how Ansible runs things outside of Ansible itself giving you more things to try yourself.
The Ansible engine does not really handle this directly, this is
mostly up to the sudo become plugin.
While the connection plugins are the ones listening to output, they
have hooks for the become plugins to match, in this case the output
from sudo (prompting for a password) is matched by the sudo become
plugin. Which when prompted, if it has a password, it passes it as
input, if not .. then raises an error that requires a password.
The default options we pass to sudo are -H -S -n (only the last 2
matter for this issue), while -S handles where sudo sends
output/expects input (stdin) the -n tells it not to prompt .. EXCEPT
if sudo itself determines the command needs a password. How does sudo
determine this? by using `NOPASSWORD` on the command, it then prompts
the user and sends the info to PAM for it to authenticate .. but PAM
in this case does not require the password, as it finds the ssh key to
be sufficient (but sudo has no idea about this) and that is how we get
to the current behavior.
So if you have this setup you have a few workarounds:
- Configure sudo to not attemp using passwords (passwd_tries = 0),
this might be an issue if this user tries to do any manual escalation
w/o sshing in.
- The already mentioned junk become password
- Modify/create a custom sudo become plugin to take a new option
(ignore_password_prompt=false|true) to avoid raising the error.