Add the ability to install sudoers file

Change-Id: Ie4edfa60ca0defd9074f84f7ce6bf71b93d95959
diff --git a/README.md b/README.md
index fb909ff..429b7dd 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 --!>
 # users
 
-Adds local users to a host, from a list of users.  This is primariliy for
+Adds local users to a host, from a list of users.  This is primarily for
 interactive (human) users - user accounts created for a specific program or
 installation should be done within that role.
 
@@ -23,9 +23,9 @@
 > **NOTE**: When this role is run, the password and all SSH keys for all users
 > specified are replaced with the ones defined in the role.
 
-The dictionary has the following keys:
+Each item in the `userlist` dictionary has the following keys:
 
-- `username`: The lowercase unix username for the user, which should be
+- `username`: The lowercase Unix username for the user, which should be
   lowercase and lacking in spaces. There may be other OS-specific requirements.
 
 - `fullname`: The full human name, or "comment" for the user.
@@ -60,6 +60,14 @@
 [authorized_key](https://docs.ansible.com/ansible/latest/modules/authorized_key_module.html)
 modules.
 
+Additionally, this role can be given a list of lines in the `users_sudoers`
+file to add to an `/etc/sudoers.d/users_sudoers` file.  Each line should be
+formatted per the [sudoers file
+format](https://www.sudo.ws/man/1.9.3/sudoers.man.html#SUDOERS_FILE_FORMAT).
+The file is verified with the [visudo
+command](https://www.sudo.ws/man/1.9.3/visudo.man.html) prior to being written,
+but no other validation, security, or correctness checks are made.
+
 Related topics:
 
 Passlib has a nice comparison of [password hash
diff --git a/defaults/main.yml b/defaults/main.yml
index a330267..a79f112 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -4,5 +4,6 @@
 # SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
 # SPDX-License-Identifier: Apache-2.0
 
-example_default1: example_value1
-example_default2: example_value2
+userlist: []
+
+users_sudoers: []
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
index 8a12536..d20d847 100644
--- a/molecule/default/converge.yml
+++ b/molecule/default/converge.yml
@@ -24,6 +24,8 @@
         sha512crypt: >-
           $6$rounds=656000$w0/M3W/p4fHA./tW$rHUMUTjI7UK68reJzWorpAidPLSuFoPkLqyWkwWiuhIg7Hkxw10AKMZuvFKzth5Uuotya8DzJZj6TiXy7U3wg1
         sudoer: true
+    users_sudoers:
+      - "%users ALL=(ghopper) NOPASSWD: ALL"
   tasks:
     - name: "Include users"
       include_role:
diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml
index 3525b8d..58ed917 100644
--- a/molecule/default/verify.yml
+++ b/molecule/default/verify.yml
@@ -7,6 +7,15 @@
 - name: Verify
   hosts: all
   tasks:
-  - name: example assertion
-    assert:
-      that: true
+
+    # testing that sudo works, so warning about "consider using become" is not
+    # applicable
+    - name: Make sure that sudoers is functional
+      become: true
+      become_user: "aturing"
+      command:
+        cmd: "sudo -u ghopper whoami"
+      register: sudo_out
+      failed_when: "'ghopper' not in sudo_out.stdout"
+      tags:
+        - skip_ansible_lint
diff --git a/tasks/main.yml b/tasks/main.yml
index 92f7ca2..c0b2b39 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -42,3 +42,13 @@
     key: "{{ lookup('file', item.username ~ '.pub') }}"
     exclusive: true
   with_items: "{{ userlist }}"
+
+- name: Add users_sudoers file (if specified)
+  when: "users_sudoers | length > 0"
+  template:
+    src: "users_sudoers.j2"
+    dest: "/etc/sudoers.d/users_sudoers"
+    owner: "root"
+    group: "root"
+    mode: 0440
+    validate: "visudo -c -s -f %s"
diff --git a/templates/users_sudoers.j2 b/templates/users_sudoers.j2
new file mode 100644
index 0000000..3a285b1
--- /dev/null
+++ b/templates/users_sudoers.j2
@@ -0,0 +1,8 @@
+{#
+SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
+SPDX-License-Identifier: Apache-2.0
+#}
+# users templates/users_sudoers.j2 - {{ ansible_managed }}
+{% for item in users_sudoers %}
+{{ item }}
+{% endfor %}