diff --git a/defaults/main.yml b/defaults/main.yml index c13fabc..9c139ca 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -7,6 +7,8 @@ provision_management_user_is_system: false provision_management_user_home: /home/{{ provision_management_user_name }} provision_management_user_shell: /bin/bash provision_management_user_sudoer: false +provision_management_user_disable_root_login: false +provision_management_user_disable_root_password_auth: false provision_management_user_add_ssh_key: false provision_management_user_ssh_key: provision_management_user_ssh_key_options: "" diff --git a/handlers/main.yml b/handlers/main.yml index 4f72979..7afcc90 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,2 +1,7 @@ --- # handlers file for provision_management_user +- name: "Restart sshd service" + ansible.builtin.service: + name: sshd + state: restarted + listen: "systemctl-restart-sshd" diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py index 0cff669..6920d95 100644 --- a/molecule/default/tests/test_default.py +++ b/molecule/default/tests/test_default.py @@ -3,8 +3,26 @@ def test_hosts_file(host): """Validate /etc/hosts file.""" - f = host.file("/etc/hosts") + etc_hosts = host.file("/etc/hosts") + assert etc_hosts.exists + assert etc_hosts.user == "root" + assert etc_hosts.group == "root" - assert f.exists - assert f.user == "root" - assert f.group == "root" +def test_ubuntu_user_group(host): + """Validate ubuntu user and group.""" + ubuntu_group = host.group("ubuntu") + ubuntu_user = host.user("ubuntu") + assert ubuntu_group.exists + assert ubuntu_user.exists + assert ubuntu_user.group == "ubuntu" + assert ubuntu_user.shell == "/bin/bash" + +def test_ubuntu_sudoer(host): + """Validate that ubuntu user is not sudoer""" + etc_sudoers_d_ubuntu = host.file("/etc/sudoers.d/ubuntu") + assert not etc_sudoers_d_ubuntu.exists + +def test_ubuntu_no_ssh(host): + """Validate that ubuntu user has no authorized_keys""" + opt_ubuntu_authorized_keys = host.file("/home/ubuntu/.ssh/authorized_keys") + assert not opt_ubuntu_authorized_keys.exists diff --git a/molecule/with_ssh_keys/converge.yml b/molecule/with_ssh_keys/converge.yml new file mode 100644 index 0000000..6bfdef7 --- /dev/null +++ b/molecule/with_ssh_keys/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: all + tasks: + - name: "Include ednxzu.provision_management_user" + ansible.builtin.include_role: + name: "ednxzu.provision_management_user" diff --git a/molecule/with_ssh_keys/group_vars/all.yml b/molecule/with_ssh_keys/group_vars/all.yml new file mode 100644 index 0000000..2d59393 --- /dev/null +++ b/molecule/with_ssh_keys/group_vars/all.yml @@ -0,0 +1,14 @@ +--- +provision_management_user_name: ubuntu +provision_management_user_group: ubuntu +provision_management_user_password: "*" +provision_management_user_is_system: true +provision_management_user_home: /home/{{ provision_management_user_name }} +provision_management_user_shell: /bin/bash +provision_management_user_sudoer: true +provision_management_user_disable_root_login: false +provision_management_user_disable_root_password_auth: false +provision_management_user_add_ssh_key: true +provision_management_user_ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIClfmTk73wNNL2jwvhRUmUuy80JRrz3P7cEgXUqlc5O9" +provision_management_user_ssh_key_options: "" +provision_management_user_ssh_key_exclusive: true diff --git a/molecule/with_ssh_keys/molecule.yml b/molecule/with_ssh_keys/molecule.yml new file mode 100644 index 0000000..758cfbb --- /dev/null +++ b/molecule/with_ssh_keys/molecule.yml @@ -0,0 +1,37 @@ +--- +dependency: + name: galaxy + options: + requirements-file: ./requirements.yml +driver: + name: docker +platforms: + - name: instance + image: geerlingguy/docker-${MOLECULE_TEST_OS}-ansible + command: "" + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + cgroupns_mode: host + privileged: true + pre_build_image: true +provisioner: + name: ansible + config_options: + defaults: + remote_tmp: /tmp/.ansible +verifier: + name: testinfra +scenario: + name: with_ssh_keys + test_sequence: + - dependency + - cleanup + - destroy + - syntax + - create + - prepare + - converge + - idempotence + - verify + - cleanup + - destroy diff --git a/molecule/with_ssh_keys/requirements.yml b/molecule/with_ssh_keys/requirements.yml new file mode 100644 index 0000000..e9320f9 --- /dev/null +++ b/molecule/with_ssh_keys/requirements.yml @@ -0,0 +1,3 @@ +--- +# requirements file for molecule +roles: [] diff --git a/molecule/with_ssh_keys/tests/conftest.py b/molecule/with_ssh_keys/tests/conftest.py new file mode 100644 index 0000000..f7ddb3f --- /dev/null +++ b/molecule/with_ssh_keys/tests/conftest.py @@ -0,0 +1,22 @@ +"""PyTest Fixtures.""" +from __future__ import absolute_import + +import os + +import pytest + + +def pytest_runtest_setup(item): + """Run tests only when under molecule with testinfra installed.""" + try: + import testinfra + except ImportError: + pytest.skip("Test requires testinfra", allow_module_level=True) + if "MOLECULE_INVENTORY_FILE" in os.environ: + pytest.testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ["MOLECULE_INVENTORY_FILE"] + ).get_hosts("all") + else: + pytest.skip( + "Test should run only from inside molecule.", allow_module_level=True + ) diff --git a/molecule/with_ssh_keys/tests/test_default.py b/molecule/with_ssh_keys/tests/test_default.py new file mode 100644 index 0000000..cc50c0d --- /dev/null +++ b/molecule/with_ssh_keys/tests/test_default.py @@ -0,0 +1,36 @@ +"""Role testing files using testinfra.""" + + +def test_hosts_file(host): + """Validate /etc/hosts file.""" + etc_hosts = host.file("/etc/hosts") + assert etc_hosts.exists + assert etc_hosts.user == "root" + assert etc_hosts.group == "root" + +def test_ubuntu_user_group(host): + """Validate ubuntu user and group.""" + ubuntu_group = host.group("ubuntu") + ubuntu_user = host.user("ubuntu") + assert ubuntu_group.exists + assert ubuntu_user.exists + assert ubuntu_user.group == "ubuntu" + assert ubuntu_user.shell == "/bin/bash" + +def test_ubuntu_sudoer(host): + """Validate that ubuntu user is sudoer""" + etc_sudoers_d_ubuntu = host.file("/etc/sudoers.d/ubuntu") + assert etc_sudoers_d_ubuntu.exists + assert etc_sudoers_d_ubuntu.user == "root" + assert etc_sudoers_d_ubuntu.group == "root" + assert etc_sudoers_d_ubuntu.mode == 0o640 + assert etc_sudoers_d_ubuntu.contains("ubuntu ALL=(ALL) NOPASSWD: ALL") + +def test_ubuntu_ssh_authorized_keys(host): + """Validate that ubuntu user has authorized_keys""" + opt_ubuntu_authorized_keys = host.file("/home/ubuntu/.ssh/authorized_keys") + assert opt_ubuntu_authorized_keys.exists + assert opt_ubuntu_authorized_keys.user == "ubuntu" + assert opt_ubuntu_authorized_keys.group == "ubuntu" + assert opt_ubuntu_authorized_keys.mode == 0o600 + assert opt_ubuntu_authorized_keys.contains("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIClfmTk73wNNL2jwvhRUmUuy80JRrz3P7cEgXUqlc5O9 ubuntu@instance") diff --git a/tasks/configure_host.yml b/tasks/configure_host.yml new file mode 100644 index 0000000..0fb2e58 --- /dev/null +++ b/tasks/configure_host.yml @@ -0,0 +1,23 @@ +--- +# task/configure_host file for provision_management_user +- name: "Lock root password authentication" + ansible.builtin.lineinfile: + dest=/etc/ssh/sshd_config + regexp='^PasswordAuthentication' + line="PasswordAuthentication no" + state=present + backup=yes + notify: + - systemctl-restart-sshd + when: provision_management_user_disable_root_password_auth + +- name: "Lock root authentication" + ansible.builtin.lineinfile: + dest=/etc/ssh/sshd_config + regexp='^PermitRootLogin' + line="PermitRootLogin no" + state=present + backup=yes + notify: + - systemctl-restart-sshd + when: provision_management_user_disable_root_login diff --git a/tasks/create_user.yml b/tasks/create_user.yml index 0e38793..41fda0e 100644 --- a/tasks/create_user.yml +++ b/tasks/create_user.yml @@ -9,7 +9,7 @@ - name: "Create user {{ provision_management_user_name }}" ansible.builtin.user: name: "{{ provision_management_user_name }}" - comment: "Ansible service user" + comment: "Management user" password: "{{ provision_management_user_password }}" group: "{{ provision_management_user_group }}" home: "{{ provision_management_user_home }}"