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

后端 未结 5 1725
天命终不由人
天命终不由人 2021-01-11 15:34

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:

AllowUs         


        
相关标签:
5条回答
  • 2021-01-11 16:16

    I had the same problem. I needed add user to sudoers group, let's say 'testuser' to line:

    User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3
    

    This worked well for me:

    - name: add testuser to end of line
          lineinfile:
            dest: /etc/sudoers.d/somegroup
            state: present
            regexp: '^(User_Alias(.*)$)'
            backrefs: yes
            line: '\1, testuser'
    

    The point is that if I had '^User_Alias(..)$'* in regexp and not '^(User_Alias(..)$)'* it didn't work and whole line was replaced. With () arround searched text the result was OK:

    User_Alias SOMEADMIN = smoeuser1, someuser2, someuser3, testuser
    

    So then anything can work in line:, included ansible variables like "{{ usernames | join(', ') }}"

    0 讨论(0)
  • 2021-01-11 16:18

    You could do it in a single play with a newline, but I think it's cleaner to use two lineinfile plays for this.

    - hosts: '127.0.0.1'
      vars:
        usernames:
           - larry
           - curly
           - moe
        usergroups:
           - stooges
           - admins
      tasks:
        - lineinfile:
            dest: /etc/ssh/sshd_config
            regexp: '^AllowUsers'
            line: "AllowUsers {{usernames | join(' ')}}"
        - lineinfile:
            dest: /etc/ssh/sshd_config
            regexp: '^AllowGroups'
            line: "AllowGroups {{usergroups | join(' ')}}"
    

    Note that groups is a reserved word so don't use that as a variable name.

    0 讨论(0)
  • 2021-01-11 16:26

    This worked for me

     - name: Add Group to AllowGroups
       lineinfile: 
         dest=/etc/ssh/sshd_config
         backup=True
         backrefs=True
         state=present
         regexp='^(AllowGroups(?!.*\b{{ groupname }}\b).*)$'
         line='\1 {{ groupname }}'
    
    0 讨论(0)
  • 2021-01-11 16:28

    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.

    0 讨论(0)
  • 2021-01-11 16:29

    The replace module will replace all instances of a regular expression pattern within a file. Write a task to match the AllowUsers line and replace it with the original line appended with the user name. To ensure the task is idempotent, a negative lookahead assertion in the regular expression checks if the user name already appears in the line. For example:

    - name: Add user to AllowUsers
      replace:
        backup: yes
        dest: /etc/ssh/sshd_config
        regexp: '^(AllowUsers(?!.*\b{{ user_name }}\b).*)$'
        replace: '\1 {{ user_name }}'
    
    0 讨论(0)
提交回复
热议问题