Avoid Ansible writing several times the same line in /etc/sudoers

Written by - 0 comments

Published on April 25th 2016 - Listed in Linux


When I ran an Ansible playbook which added an entry in /etc/sudoers for a user "developer" I came across something rather ugly: The line was written every time the playbook ran - resulting in an /etc/sudoers full of the same entries of the developer user.

The relevant task of the playbook looked like this:

  - name: DEVS - Add sudoers entry for developer
    lineinfile: "dest=/etc/sudoers
                regexp='^developer ALL=(www-data)'
                insertafter='^# User privilege specification'
                line='developer ALL=(www-data) NOPASSWD: /bin/bash'
                state=present"

So what I want to achieve with this is the following:

In /etc/sudoers search for a line starting with "developer ALL=(www-data)".
If this line is not found, write the line "developer ALL=(www-data) NOPASSWD: /bin/bash" into /etc/sudoers, right after the line starting with "# User privilege specification".

To my big surprise, whenever I ran the playbook, it executed the task and set it to "changed". Meaning, the entry was added. So at the end /etc/sudoers contained several lines of "developer ALL=(www-data) NOPASSWD: /bin/bash". That's not what I wanted to achieve.

After some troubleshooting it turned out that the regular expression "developer ALL=(www-data)" didn't work because of the brackets ( ). As ansible is using python in the background, I checked out the python regular expression documentation and searched for an escape character. No big surprise here, the escape character is a backslash (\) as it is in Perl's regular expression, too.

I adapted the playbook to escape the brackets:

  - name: DEVS - Add sudoers entry for developer
    lineinfile: "dest=/etc/sudoers
                regexp='^developer ALL=\(www-data\)'
                insertafter='^# User privilege specification'
                line='developer ALL=(www-data) NOPASSWD: /bin/bash'
                state=present"

But now I ran into a YAML syntax error:

ERROR! Syntax Error while loading YAML.

The error appears to have been in 'myplaybook.yaml': line 57, column 36, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

    lineinfile: "dest=/etc/sudoers
                regexp='^developer ALL=\(www-data\)'
                                   ^ here

So the escape character didn't work because YAML didn't like it. Finally I came across the answer: Wrap the character I want to escape in a separate character class and this is how it's done:

  - name: DEVS - Add sudoers entry for developer
    lineinfile: "dest=/etc/sudoers
                regexp='^developer ALL=[(]www-data[)]'
                insertafter='^# User privilege specification'
                line='developer ALL=(www-data) NOPASSWD: /bin/bash'
                state=present"

The playbook now runs through and the sudoers entry only exists once.


Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.