31

I've set up a box with a user david who has sudo privileges. I can ssh into the box and perform sudo operations like apt-get install. When I try to do the same thing using Ansible's "become privilege escalation", I get a permission denied error. So a simple playbook might look like this:

simple_playbook.yml:

---
- name: Testing...
  hosts: all
  become: true
  become_user: david
  become_method: sudo

  tasks:
    - name: Just want to install sqlite3 for example...
      apt: name=sqlite3 state=present

I run this playbook with the following command:

ansible-playbook -i inventory simple_playbook.yml --ask-become-pass

This gives me a prompt for a password, which I give, and I get the following error (abbreviated):

fatal: [123.45.67.89]: FAILED! => {...
failed: E: Could not open lock file /var/lib/dpkg/lock - open (13: 
Permission denied)\nE: Unable to lock the administration directory
(/var/lib/dpkg/), are you root?\n", ...}

Why am I getting permission denied?

Additional information

I'm running Ansible 2.1.1.0 and am targeting a Ubuntu 16.04 box. If I use remote_user and sudo options as per Ansible < v1.9, it works fine, like this: remote_user: david sudo: yes

Update

The local and remote usernames are the same. To get this working, I just needed to specify become: yes (see @techraf's answer):

DavB
  • 1,676
  • 2
  • 14
  • 16
  • What is the user name, the remote user that you using to perform the first ssh connection? – Raul Hugo Dec 06 '16 at 03:46
  • I think the become user is root, change root instead david, and it will works. – Raul Hugo Dec 06 '16 at 03:53
  • @helloV - I've also tried adding 'become true' to the task and the result is the same. – DavB Dec 06 '16 at 06:21
  • @Raul Hugo - the username is 'david' on both the remote and the local machine. If I remove 'become_user' it works and that is because it defaults to root (as per the docs). However I want to run it as 'david',, not as'root'. – DavB Dec 06 '16 at 06:21
  • @DavB see my updated answer. – helloV Dec 06 '16 at 06:35
  • "*However I want to run it as 'david',, not as'root'.*" - you cannot. Ansible uses APT package manager and it requires root permissions. – techraf Dec 06 '16 at 06:39
  • @techraf - the user 'david' on the remote box has sudo privileges. So, if I use `remote_user: david` and `sudo: yes` as per ansible <1.9, it works fine (with deprecation warnings). I've updated the question with this info. I thought it should work the same with with `become_user` and `become_method`. – DavB Dec 06 '16 at 06:42
  • Because `remote_user: david` has no effect. You already said "the username is 'david' on [ ] the remote machine". And `sudo` is an alias to `become`. You have wrong impression that something changed. The only problem in your playbook is `become_user: david`. – techraf Dec 06 '16 at 06:47
  • Well the problem was not ansible You need to understand better how sudo works xD – Raul Hugo Dec 06 '16 at 15:03

3 Answers3

42

Why am I getting permission denied?

Because APT requires root permissions (see the error: are you root?) and you are running the tasks as david.

Per these settings:

become: true
become_user: david
become_method: sudo

Ansible becomes david using sudo method. It basically runs its Python script with sudo david in front.


the user 'david' on the remote box has sudo privileges.

It means david can execute commands (some or all) using sudo-executable to change the effective user for the child process (the command). If no username is given, this process runs as the root account.

Compare the results of these two commands:

$ sudo whoami
root
$ sudo david whoami
david

Back to the APT problem, you (from CLI) as well as Ansible (connecting with SSH using your account) need to run:

sudo apt-get install sqlite3

not:

sudo david apt-get install sqlite3

which will fail with the very exact message Ansible displayed.


The following playbook will escalate by default to the root user:

---
- name: Testing...   
  hosts: all
  become: true

  tasks:
    - name: Just want to install sqlite3 for example...
      apt: name=sqlite3 state=present
techraf
  • 64,883
  • 27
  • 193
  • 198
  • Thanks @techraf for the explanation. If I use `remote_user: david` with `become: true`, it seems to works fine. Are these settings correct in this situation? – DavB Dec 06 '16 at 07:20
  • @DavB `remote_user` has no direct relation to the parameters starting with `become`. It is the `` you use in the command the `ssh @`. In one of your comments you said you use the same user `david` both on the client and the server, hence you connect with `ssh `. In this situation `remote_user: david` has **no effect**. You can include it, you can remove it. Nothing will change. The problem was with `become_user: david`. Only. – techraf Dec 06 '16 at 07:34
  • 1
    You would need `remote_user: david` **if** you were running Ansible on your (client) machine using an account named `davb` (or any other than `david`). – techraf Dec 06 '16 at 07:42
  • 1
    @DavB I already answered this in the first sentence and in bold font. If you run APT package manager using different user than root, you get an error message. This is how APT was written. Don't use it if you don't like it. You can install software without APT, though you will have to handle everything manually. – techraf Dec 06 '16 at 08:39
  • the user `david` has root privileges. – DavB Dec 06 '16 at 10:02
  • 2
    Have you read the answer which you are commenting? There is no such thing as "root privileges" in Unix. Either a process is running as root or as a different user. – techraf Dec 06 '16 at 10:06
  • sorry, finally the penny has dropped. Thanks a lot for your help (and patience)! – DavB Dec 06 '16 at 10:13
  • This is very unintuitive coming from normal userland, where `sudo` is for prefixing all management commants and `sudo su` or `su root` is for switching to root. Thanks for the explanation, I spent hours trying to find a reason for this, as ansible documentation doesn't mention it. – Megakoresh Apr 01 '18 at 06:29
6

remote_user is david. Call the script with --ask-pass and give password for david. If david doesn't have passwordless sudo, then you should also call it with --ask-become-pass.

- name: Testing...
  hosts: all
  remote_user: david
  become: true
  become_method: sudo

  tasks:
    - name: Just want to install sqlite3 for example...
      apt: name=sqlite3 state=present
helloV
  • 50,176
  • 7
  • 137
  • 145
  • thanks, but I don't understand what you mean. I already have `become: true` specified (and `become_method: sudo`). Could you clarify? – DavB Dec 05 '16 at 23:26
  • @helloV I also have similar question on ansible [here](https://stackoverflow.com/questions/48724920/copy-files-to-remote-servers-but-in-a-directory-which-belongs-to-some-other-user) where I am not sure what wrong I am doing with either `become` or `become_user`. Wanted to see if you can help out? – user1950349 Feb 11 '18 at 04:31
1

I have the same issue.

The issue is solved by using root and --ask-become-pass --ask-pass command together.

- name: Testing...
  hosts: all
  remote_user: root
  become: true
  become_method: sudo

  tasks:
    - name: Just want to install sqlite3 for example...
      apt: name=sqlite3 state=present
ansible-playbook playbook.yml --ask-become-pass --ask-pass
Metin Bulak
  • 537
  • 4
  • 8
  • 30