Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible: insert a single word on an existing line in a file

Tags:

ansible

sshd

I have to use Ansible modules in order to edit the /etc/ssh/sshd_config file - every time I create a new user I want to append it at these two lines:

AllowUsers root osadmin <new_user>
AllowGroups root staff <new_group>

At this moment I'm using the shell module to execute a sed command but would like to use lineinfile, if possible

- shell: "sed -i '/^Allow/ s/$/ {{ user_name }}/' /etc/ssh/sshd_config"

Any suggestions would be sincerely appreciated.

like image 813
Alexandra Ivan Avatar asked Jul 15 '15 13:07

Alexandra Ivan


1 Answers

The selected answer assumes that the complete list of users is available at runtime, while the most popular answer can fail when there is a dash in the username, because \b interprets it as a word boundary. The following solution assumes that the playbook cannot regenerate the complete list of usernames from scratch, and tries and handle the corner case of dashes:

name: add a user to the list of AllowUsers if not present
lineinfile:
  path: /etc/ssh/sshd_config
  backrefs: yes
  backup: yes
  regexp: "^AllowUsers((?:(?:\s+\S+(?!\S))(?<!\s{{ username }}))+\s*?)(\n?)$"
  line: "AllowUsers\1 {{ username }}\2"
  validate: /usr/sbin/sshd -t -f %s

As a bonus, I threw in sshd_config backup and verification.

How the (interesting part of the) regular expression works:

--------------------------+----------------------------------------------------
(                         |
--------------------------+----------------------------------------------------
  (?:                     | This group is not captured
--------------------------+----------------------------------------------------
    (?:\s+\S+(?!\S))      | Matches any sequence of whitespace characters fol-
                          | lowed by any sequence of non-whitespace characters,
                          | that is to say a leading space and a username. The
                          | negative look-ahead at the end prevents a "catast-
                          | rophic backtracking". Also, this group is not cap-
                          | tured.
--------------------------+----------------------------------------------------
    (?<!\s{{ username }}) | Applies a negative look-behind on the username, so
                          | that if the username found by the previous expres-
                          | sion matches, the regular expression fails. The
                          | match on a leading whitespace character ensures
                          | that the comparison is made on the complete string.
--------------------------+----------------------------------------------------
  )+                      | Groups the detection of a username and its negative
                          | look-behind together. The "+" quantifier is used
                          | here on the assumption that the file already cont-
                          | ains at least one username, but "*" could be used
                          | for a more relaxed matching.
--------------------------+----------------------------------------------------
  \s*?                    | Matches any trailing whitespace. The match is lazy
                          | in order to detect the newline character later on.
--------------------------+----------------------------------------------------
)                         | Captures the whole text after "AllowUsers" (this
                          | will be \1).
--------------------------+----------------------------------------------------
(\n?)                     | Captures either a newline character or an empty
                          | string (this will be \2).
--------------------------+----------------------------------------------------

If the regular expression matches, it means that the line exists and that it does not contain {{ username }}, so we append it.

If the regular expression does not match, it means that either the line does not exist or that it contains {{ username }}, and we do nothing.

like image 107
To마SE Avatar answered Sep 23 '22 14:09

To마SE