diff --git a/.config/ansible-lint.yml b/.config/ansible-lint.yml index a126d0c4..f6c1df41 100644 --- a/.config/ansible-lint.yml +++ b/.config/ansible-lint.yml @@ -4,7 +4,7 @@ # and not relative to the CWD of execution. CLI arguments passed to the --exclude # option will be parsed relative to the CWD of execution. exclude_paths: - - .cache/ # implicit unless exclude_paths is defined in config + - .cache/ # implicit unless exclude_paths is defined in config - .yamllint - ../molecule/ - ../.github/ diff --git a/.yamllint b/.yamllint deleted file mode 100644 index 372338d4..00000000 --- a/.yamllint +++ /dev/null @@ -1,26 +0,0 @@ ---- -# Based on ansible-lint config -extends: default - -rules: - braces: - max-spaces-inside: 1 - level: error - brackets: - max-spaces-inside: 1 - level: error - colons: - max-spaces-after: -1 - level: error - commas: - max-spaces-after: -1 - level: error - empty-lines: - max: 3 - level: error - hyphens: - level: error - key-duplicates: enable - line-length: disable - new-lines: - type: unix diff --git a/galaxy.yml b/galaxy.yml index 034009e8..3f811c8b 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,13 +1,14 @@ +--- namespace: devsec name: hardening version: 8.4.0 readme: README.md authors: - dev-sec -description: 'This collection provides battle tested hardening for Linux, SSH, nginx, MySQL' +description: This collection provides battle tested hardening for Linux, SSH, nginx, MySQL license: - Apache-2.0 -license_file: '' +license_file: "" tags: - devsec - hardening @@ -23,13 +24,13 @@ tags: - os_hardening - ssh_hardening dependencies: - ansible.posix: '>=1.0.0' - community.crypto: '>=1.0.0' - community.general: '>=1.0.0' - community.mysql: '>=1.3.0' -repository: 'https://github.com/dev-sec/ansible-collection-hardening/' -homepage: 'https://dev-sec.io/' -issues: 'https://github.com/dev-sec/ansible-collection-hardening/issues' + ansible.posix: ">=1.0.0" + community.crypto: ">=1.0.0" + community.general: ">=1.0.0" + community.mysql: ">=1.3.0" +repository: https://github.com/dev-sec/ansible-collection-hardening/ +homepage: https://dev-sec.io/ +issues: https://github.com/dev-sec/ansible-collection-hardening/issues build_ignore: - codecov.yml - .github diff --git a/meta/runtime.yml b/meta/runtime.yml index 2ee3c9fa..460bbaf8 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,2 +1,2 @@ --- -requires_ansible: '>=2.9.10' +requires_ansible: ">=2.9.10" diff --git a/roles/mysql_hardening/defaults/main.yml b/roles/mysql_hardening/defaults/main.yml index 37111fa3..c56e479c 100644 --- a/roles/mysql_hardening/defaults/main.yml +++ b/roles/mysql_hardening/defaults/main.yml @@ -7,9 +7,9 @@ mysql_daemon_enabled: true mysql_hardening_restart_mysql: true # general configuration -mysql_hardening_mysql_hardening_conf_file: '{{ mysql_hardening_mysql_confd_dir }}/hardening.cnf' +mysql_hardening_mysql_hardening_conf_file: "{{ mysql_hardening_mysql_confd_dir }}/hardening.cnf" # You have to change this to your own strong enough mysql root password -mysql_root_password: '-----====>SetR00tPa$$wordH3r3!!!<====-----' +mysql_root_password: "-----====>SetR00tPa$$wordH3r3!!!<====-----" # There .my.cnf with mysql root credentials will be installed mysql_user_home: "{{ ansible_env.HOME }}" @@ -48,6 +48,6 @@ mysql_hardening_options: automatic-sp-privileges: 0 # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option-mysqld-secure-file-priv - secure-file-priv: '/tmp' + secure-file-priv: /tmp # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_user - user: '{{ mysql_hardening_user }}' + user: "{{ mysql_hardening_user }}" diff --git a/roles/mysql_hardening/handlers/main.yml b/roles/mysql_hardening/handlers/main.yml index bb0d1d3c..1f35d6db 100644 --- a/roles/mysql_hardening/handlers/main.yml +++ b/roles/mysql_hardening/handlers/main.yml @@ -1,7 +1,6 @@ --- - - name: Restart mysql - service: - name: '{{ mysql_daemon }}' + ansible.builtin.service: + name: "{{ mysql_daemon }}" state: restarted when: mysql_hardening_restart_mysql | bool diff --git a/roles/mysql_hardening/meta/main.yml b/roles/mysql_hardening/meta/main.yml index df33c621..2a1df16e 100644 --- a/roles/mysql_hardening/meta/main.yml +++ b/roles/mysql_hardening/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: - author: "Sebastian Gumprich" - description: 'This Ansible playbook provides security configuration for mysql.' + author: Sebastian Gumprich + description: This Ansible playbook provides security configuration for mysql. company: Hardening Framework Team license: Apache License 2.0 - min_ansible_version: '2.9.10' + min_ansible_version: 2.9.10 platforms: - name: EL versions: diff --git a/roles/mysql_hardening/tasks/configure.yml b/roles/mysql_hardening/tasks/configure.yml index e0bc61e6..a1611529 100644 --- a/roles/mysql_hardening/tasks/configure.yml +++ b/roles/mysql_hardening/tasks/configure.yml @@ -1,64 +1,64 @@ --- - name: Protect my.cnf - file: - path: '{{ mysql_hardening_mysql_conf_file }}' - mode: '0640' - owner: '{{ mysql_cnf_owner }}' - group: '{{ mysql_cnf_group }}' + ansible.builtin.file: + path: "{{ mysql_hardening_mysql_conf_file }}" + mode: "0640" + owner: "{{ mysql_cnf_owner }}" + group: "{{ mysql_cnf_group }}" follow: true state: file - name: Ensure permissions on mysql-datadir are correct - file: - path: '{{ item }}' + ansible.builtin.file: + path: "{{ item }}" state: directory - owner: '{{ mysql_hardening_user }}' - group: '{{ mysql_hardening_user }}' - mode: '0750' + owner: "{{ mysql_hardening_user }}" + group: "{{ mysql_hardening_user }}" + mode: "0750" when: item is defined and item != "" loop: - - '{{ mysql_settings.settings.datadir }}' + - "{{ mysql_settings.settings.datadir }}" - '{{ mysql_datadir | default("") }}' - name: Ensure permissions on mysql-logfile are correct - file: - path: '{{ item }}' + ansible.builtin.file: + path: "{{ item }}" state: file - owner: '{{ mysql_hardening_user }}' - group: '{{ mysql_hardening_group }}' - mode: '0640' + owner: "{{ mysql_hardening_user }}" + group: "{{ mysql_hardening_group }}" + mode: "0640" when: item is defined and item != "" loop: - - '{{ mysql_settings.settings.log_error }}' + - "{{ mysql_settings.settings.log_error }}" - '{{ mysql_hardening_log_file | default("") }}' - name: Check mysql configuration-directory exists and has right permissions - file: - path: '{{ mysql_hardening_mysql_confd_dir }}' + ansible.builtin.file: + path: "{{ mysql_hardening_mysql_confd_dir }}" state: directory - owner: '{{ mysql_hardening_user }}' - group: '{{ mysql_hardening_group }}' - mode: '0750' + owner: "{{ mysql_hardening_user }}" + group: "{{ mysql_hardening_group }}" + mode: "0750" - name: Check include-dir directive is present in my.cnf - lineinfile: - dest: '{{ mysql_hardening_mysql_conf_file }}' - line: '!includedir {{ mysql_hardening_mysql_confd_dir }}' - insertafter: 'EOF' + ansible.builtin.lineinfile: + dest: "{{ mysql_hardening_mysql_conf_file }}" + line: "!includedir {{ mysql_hardening_mysql_confd_dir }}" + insertafter: EOF state: present backup: true notify: Restart mysql - name: Apply hardening configuration - template: - src: 'hardening.cnf.j2' - dest: '{{ mysql_hardening_mysql_hardening_conf_file }}' - owner: '{{ mysql_cnf_owner }}' - group: '{{ mysql_cnf_group }}' - mode: '0640' + ansible.builtin.template: + src: hardening.cnf.j2 + dest: "{{ mysql_hardening_mysql_hardening_conf_file }}" + owner: "{{ mysql_cnf_owner }}" + group: "{{ mysql_cnf_group }}" + mode: "0640" notify: Restart mysql - name: Enable mysql - service: - name: '{{ mysql_daemon }}' - enabled: '{{ mysql_daemon_enabled }}' + ansible.builtin.service: + name: "{{ mysql_daemon }}" + enabled: "{{ mysql_daemon_enabled }}" diff --git a/roles/mysql_hardening/tasks/main.yml b/roles/mysql_hardening/tasks/main.yml index 54a64797..bc74008b 100644 --- a/roles/mysql_hardening/tasks/main.yml +++ b/roles/mysql_hardening/tasks/main.yml @@ -1,31 +1,31 @@ --- - name: Fetch OS dependent variables - include_vars: - file: '{{ item }}' - name: 'os_vars' + ansible.builtin.include_vars: + file: "{{ item }}" + name: os_vars with_first_found: - files: - - '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml' - - '{{ ansible_facts.distribution }}.yml' - - '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml' - - '{{ ansible_facts.os_family }}.yml' + - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml" + - "{{ ansible_facts.distribution }}.yml" + - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml" + - "{{ ansible_facts.os_family }}.yml" skip: true tags: always # we only override variables with our default if they have not been specified already. # by default the lookup functions finds all varnames containing the string, therefore # we add ^ and $ to denote start and end of string, so this returns only exact maches. -- name: Set OS dependent variables, if not already defined by user # noqa var-naming - set_fact: - '{{ item.key }}': '{{ item.value }}' - when: "not lookup('varnames', '^' + item.key + '$')" - with_dict: '{{ os_vars }}' +- name: Set OS dependent variables, if not already defined by user # noqa var-naming + ansible.builtin.set_fact: + "{{ item.key }}": "{{ item.value }}" + when: not lookup('varnames', '^' + item.key + '$') + with_dict: "{{ os_vars }}" tags: always - name: Check that the variable mysql_distribution is set correctly ansible.builtin.assert: that: mysql_distribution == 'mysql' or mysql_distribution == 'mariadb' - fail_msg: 'mysql_distribution must be set to either mysql or mariadb!' + fail_msg: mysql_distribution must be set to either mysql or mariadb! when: mysql_distribution is defined - name: Gather package facts to check for mysql/mariadb version @@ -34,7 +34,7 @@ when: not mysql_distribution is defined - name: Check if MySQL or MariaDB is used - set_fact: + ansible.builtin.set_fact: mysql_distribution: "{{ ansible_facts.packages['mysql-server'] is defined | ternary('mysql', 'mariadb') }}" when: not mysql_distribution is defined @@ -53,20 +53,20 @@ # see https://stackoverflow.com/a/59451077/2953919 for the # dict2items and vice versa magic - name: Drop the secure-auth parameter on MySQL >=8.0.3 (not mariadb) - set_fact: + ansible.builtin.set_fact: mysql_hardening_options: "{{ mysql_hardening_options | dict2items | rejectattr('key', 'search', 'secure-auth') | list | items2dict }}" when: - mysql_version.version.full is version('8.0.3', '>=') - mysql_distribution == "mysql" - name: Include tasks for configuration - import_tasks: configure.yml + ansible.builtin.import_tasks: configure.yml when: mysql_hardening_enabled | bool tags: - mysql_hardening - name: Include tasks to secure mysql installation - import_tasks: mysql_secure_installation.yml + ansible.builtin.import_tasks: mysql_secure_installation.yml when: mysql_hardening_enabled | bool tags: - mysql_hardening diff --git a/roles/mysql_hardening/tasks/mysql_secure_installation.yml b/roles/mysql_hardening/tasks/mysql_secure_installation.yml index 9aa3a8eb..493b274d 100644 --- a/roles/mysql_hardening/tasks/mysql_secure_installation.yml +++ b/roles/mysql_hardening/tasks/mysql_secure_installation.yml @@ -1,22 +1,22 @@ --- - name: Fail the role if the mysql root password was not set - fail: - msg: 'ERROR - you have to change default mysql_root_password' + ansible.builtin.fail: + msg: ERROR - you have to change default mysql_root_password when: mysql_root_password == '-----====>SetR00tPa$$wordH3r3!!!<====-----' - name: Ensure that the root password is present community.mysql.mysql_user: - name: 'root' + name: root host_all: true - password: '{{ mysql_root_password | mandatory }}' + password: "{{ mysql_root_password | mandatory }}" state: present login_unix_socket: "{{ login_unix_socket | default(omit) }}" - name: Install .my.cnf with credentials - template: - src: 'my.cnf.j2' - dest: '{{ mysql_user_home }}/.my.cnf' - mode: '0400' + ansible.builtin.template: + src: my.cnf.j2 + dest: "{{ mysql_user_home }}/.my.cnf" + mode: "0400" tags: my_cnf - name: Ensure that the test database is absent @@ -28,7 +28,7 @@ - name: Ensure that anonymous users are absent community.mysql.mysql_user: - name: '' + name: "" state: absent host_all: true login_unix_socket: "{{ login_unix_socket | default(omit) }}" @@ -36,69 +36,72 @@ - name: Ensure that root can only login from localhost community.mysql.mysql_query: - query: - - DELETE - FROM mysql.user - WHERE USER='root' - AND HOST NOT IN ('localhost', - '127.0.0.1', - '::1') + query: > + DELETE + FROM mysql.user + WHERE USER='root' + AND HOST NOT IN ('localhost', + '127.0.0.1', + '::1'); login_unix_socket: "{{ login_unix_socket | default(omit) }}" when: mysql_remove_remote_root - name: Get all users that have no authentication_string on MySQL version >= 5.7.6 or Mariadb version >= 10.4.0 community.mysql.mysql_query: - query: - - SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users - FROM mysql.user - WHERE (length(authentication_string)=0 - OR authentication_string="") - AND USER NOT IN ('mysql.sys', - 'mysqlxsys', - 'mariadb.sys'); + query: > + SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users + FROM mysql.user + WHERE (length(authentication_string)=0 + OR authentication_string="") + AND USER NOT IN ('mysql.sys', + 'mysqlxsys', + 'mariadb.sys'); + login_unix_socket: "{{ login_unix_socket | default(omit) }}" register: mysql_users_wo_passwords_or_auth_string - when: - - (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '>=')) or - (mysql_distribution == "mariadb" and mysql_version.version.full is version('10.4.0', '>=')) + when: > + (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '>=')) or + (mysql_distribution == "mariadb" and mysql_version.version.full + is version('10.4.0', '>=')) - name: Get all users that have no password or authentication_string on MySQL version < 5.7.6 or Mariadb version < 10.4.0 community.mysql.mysql_query: - query: - - SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users - FROM mysql.user - WHERE (length(password)=0 - OR password="") - AND (length(authentication_string)=0 - OR authentication_string="") - AND USER NOT IN ('mysql.sys', - 'mysqlxsys', - 'mariadb.sys'); + query: > + SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users + FROM mysql.user + WHERE (length(password)=0 + OR password="") + AND (length(authentication_string)=0 + OR authentication_string="") + AND USER NOT IN ('mysql.sys', + 'mysqlxsys', + 'mariadb.sys'); login_unix_socket: "{{ login_unix_socket | default(omit) }}" register: mysql_users_wo_passwords - when: - - (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '<')) or - (mysql_distribution == "mariadb" and mysql_version.version.full is version('10.4.0', '<')) + when: > + (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '<')) or + (mysql_distribution == "mariadb" and mysql_version.version.full is + version('10.4.0', '<')) - name: Create a fact for users without password or authentication_string - set_fact: + ansible.builtin.set_fact: users_wo_auth: "{{ mysql_users_wo_passwords_or_auth_string.query_result.0.0 | community.general.json_query('users') }}" when: - mysql_users_wo_passwords_or_auth_string.query_result is defined - - mysql_users_wo_passwords_or_auth_string.query_result != "" # noqa empty-string-compare + - mysql_users_wo_passwords_or_auth_string.query_result != "" # noqa empty-string-compare - name: Create a fact for users without password - set_fact: + ansible.builtin.set_fact: users_wo_auth: "{{ mysql_users_wo_passwords.query_result.0.0 | community.general.json_query('users') }}" when: - mysql_users_wo_passwords.query_result is defined - - mysql_users_wo_passwords.query_result != "" # noqa empty-string-compare + - mysql_users_wo_passwords.query_result != "" # noqa empty-string-compare - name: Ensure that there are no users without password or authentication_string community.mysql.mysql_query: query: - - "DROP USER {{ users_wo_auth }}" + - DROP USER {{ users_wo_auth }} login_unix_socket: "{{ login_unix_socket | default(omit) }}" when: - users_wo_auth is defined - - users_wo_auth != "" # noqa empty-string-compare + - users_wo_auth != "" # noqa empty-string-compare diff --git a/roles/mysql_hardening/vars/Debian.yml b/roles/mysql_hardening/vars/Debian.yml index bb9d9ea4..20cbaf6b 100644 --- a/roles/mysql_hardening/vars/Debian.yml +++ b/roles/mysql_hardening/vars/Debian.yml @@ -1,10 +1,10 @@ --- mysql_daemon: mariadb -mysql_hardening_mysql_conf_file: '/etc/mysql/my.cnf' -mysql_hardening_mysql_confd_dir: '/etc/mysql/conf.d' +mysql_hardening_mysql_conf_file: /etc/mysql/my.cnf +mysql_hardening_mysql_confd_dir: /etc/mysql/conf.d -mysql_hardening_group: 'adm' +mysql_hardening_group: adm -mysql_cnf_owner: 'root' # owner of /etc/mysql/*.cnf files -mysql_cnf_group: 'mysql' # owner of /etc/mysql/*.cnf files +mysql_cnf_owner: root # owner of /etc/mysql/*.cnf files +mysql_cnf_group: mysql # owner of /etc/mysql/*.cnf files diff --git a/roles/mysql_hardening/vars/Fedora.yml b/roles/mysql_hardening/vars/Fedora.yml index 1d18da6a..545aaf6a 100644 --- a/roles/mysql_hardening/vars/Fedora.yml +++ b/roles/mysql_hardening/vars/Fedora.yml @@ -1,4 +1,4 @@ --- mysql_daemon: mysqld -mysql_hardening_mysql_conf_file: '/etc/my.cnf' -mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' +mysql_hardening_mysql_conf_file: /etc/my.cnf +mysql_hardening_mysql_confd_dir: /etc/my.cnf.d diff --git a/roles/mysql_hardening/vars/FreeBSD.yml b/roles/mysql_hardening/vars/FreeBSD.yml index 4c2bffd7..9e942065 100644 --- a/roles/mysql_hardening/vars/FreeBSD.yml +++ b/roles/mysql_hardening/vars/FreeBSD.yml @@ -1,10 +1,10 @@ --- mysql_daemon: mysql-server -mysql_hardening_mysql_conf_file: '/usr/local/etc/mysql/my.cnf' -mysql_hardening_mysql_confd_dir: '/usr/local/etc/mysql/conf.d' +mysql_hardening_mysql_conf_file: /usr/local/etc/mysql/my.cnf +mysql_hardening_mysql_confd_dir: /usr/local/etc/mysql/conf.d -mysql_hardening_group: 'mysql' +mysql_hardening_group: mysql -mysql_cnf_owner: 'root' # owner of /usr/local/etc/mysql/*.cnf files -mysql_cnf_group: 'mysql' # owner of /usr/local/etc/mysql/*.cnf files +mysql_cnf_owner: root # owner of /usr/local/etc/mysql/*.cnf files +mysql_cnf_group: mysql # owner of /usr/local/etc/mysql/*.cnf files diff --git a/roles/mysql_hardening/vars/Oracle Linux.yml b/roles/mysql_hardening/vars/Oracle Linux.yml index d009ee0a..ff1fc513 100644 --- a/roles/mysql_hardening/vars/Oracle Linux.yml +++ b/roles/mysql_hardening/vars/Oracle Linux.yml @@ -1,7 +1,7 @@ --- mysql_daemon: mysqld -mysql_hardening_mysql_conf_file: '/etc/my.cnf' -mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' +mysql_hardening_mysql_conf_file: /etc/my.cnf +mysql_hardening_mysql_confd_dir: /etc/my.cnf.d -mysql_hardening_group: 'adm' +mysql_hardening_group: adm diff --git a/roles/mysql_hardening/vars/RedHat.yml b/roles/mysql_hardening/vars/RedHat.yml index 7edaadd9..342167c6 100644 --- a/roles/mysql_hardening/vars/RedHat.yml +++ b/roles/mysql_hardening/vars/RedHat.yml @@ -1,9 +1,9 @@ --- mysql_daemon: mariadb -mysql_hardening_mysql_conf_file: '/etc/my.cnf' -mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' +mysql_hardening_mysql_conf_file: /etc/my.cnf +mysql_hardening_mysql_confd_dir: /etc/my.cnf.d -mysql_cnf_owner: 'root' # owner of /etc/mysql/*.cnf files -mysql_cnf_group: 'mysql' # owner of /etc/mysql/*.cnf files +mysql_cnf_owner: root # owner of /etc/mysql/*.cnf files +mysql_cnf_group: mysql # owner of /etc/mysql/*.cnf files -mysql_hardening_group: 'mysql' +mysql_hardening_group: mysql diff --git a/roles/mysql_hardening/vars/Ubuntu.yml b/roles/mysql_hardening/vars/Ubuntu.yml index ce0ebe36..f2d090d2 100644 --- a/roles/mysql_hardening/vars/Ubuntu.yml +++ b/roles/mysql_hardening/vars/Ubuntu.yml @@ -1,10 +1,10 @@ --- mysql_daemon: mysql -mysql_hardening_mysql_conf_file: '/etc/mysql/my.cnf' -mysql_hardening_mysql_confd_dir: '/etc/mysql/conf.d' +mysql_hardening_mysql_conf_file: /etc/mysql/my.cnf +mysql_hardening_mysql_confd_dir: /etc/mysql/conf.d -mysql_cnf_owner: 'root' # owner of /etc/mysql/*.cnf files -mysql_cnf_group: 'mysql' # owner of /etc/mysql/*.cnf files +mysql_cnf_owner: root # owner of /etc/mysql/*.cnf files +mysql_cnf_group: mysql # owner of /etc/mysql/*.cnf files -mysql_hardening_group: 'adm' +mysql_hardening_group: adm diff --git a/roles/mysql_hardening/vars/main.yml b/roles/mysql_hardening/vars/main.yml index c8e099be..8a0fc9dc 100644 --- a/roles/mysql_hardening/vars/main.yml +++ b/roles/mysql_hardening/vars/main.yml @@ -1,3 +1,2 @@ --- - -mysql_hardening_user: 'mysql' # owner of data +mysql_hardening_user: mysql # owner of data diff --git a/roles/nginx_hardening/defaults/main.yml b/roles/nginx_hardening/defaults/main.yml index 39043e51..73913eb7 100644 --- a/roles/nginx_hardening/defaults/main.yml +++ b/roles/nginx_hardening/defaults/main.yml @@ -1,20 +1,20 @@ --- -nginx_client_body_buffer_size: '1k' +nginx_client_body_buffer_size: 1k nginx_remove_default_site: true -nginx_client_max_body_size: '1k' -nginx_keepalive_timeout: '5 5' -nginx_server_tokens: 'off' -nginx_client_header_buffer_size: "1k" -nginx_large_client_header_buffers: "2 1k" +nginx_client_max_body_size: 1k +nginx_keepalive_timeout: 5 5 +nginx_server_tokens: "off" +nginx_client_header_buffer_size: 1k +nginx_large_client_header_buffers: 2 1k nginx_client_body_timeout: "10" nginx_client_header_timeout: "10" nginx_send_timeout: "10" -nginx_limit_conn_zone: "$binary_remote_addr zone=default:10m" -nginx_limit_conn: "default 5" -nginx_configuration_dir: "/etc/nginx" -nginx_configuration_hardening_dir: "/etc/nginx" -nginx_owner_user: "root" -nginx_owner_group: "root" +nginx_limit_conn_zone: $binary_remote_addr zone=default:10m +nginx_limit_conn: default 5 +nginx_configuration_dir: /etc/nginx +nginx_configuration_hardening_dir: /etc/nginx +nginx_owner_user: root +nginx_owner_group: root nginx_add_header: # avoid clickjacking - X-Frame-Options SAMEORIGIN @@ -27,7 +27,8 @@ nginx_add_header: nginx_set_cookie_flag: "* HttpOnly secure" nginx_ssl_prefer_server_ciphers: "on" -nginx_ssl_protocols: "TLSv1.2 TLSv1.3" -nginx_ssl_ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" +nginx_ssl_protocols: TLSv1.2 TLSv1.3 +# yamllint disable-line rule:line-length +nginx_ssl_ciphers: ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 nginx_ssl_session_tickets: "off" nginx_dh_size: "4096" diff --git a/roles/nginx_hardening/handlers/main.yml b/roles/nginx_hardening/handlers/main.yml index 22955aba..3ba7687f 100644 --- a/roles/nginx_hardening/handlers/main.yml +++ b/roles/nginx_hardening/handlers/main.yml @@ -1,5 +1,5 @@ --- - name: Restart nginx - service: - name: "nginx" + ansible.builtin.service: + name: nginx state: restarted diff --git a/roles/nginx_hardening/meta/main.yml b/roles/nginx_hardening/meta/main.yml index 932f9be5..b87eb942 100644 --- a/roles/nginx_hardening/meta/main.yml +++ b/roles/nginx_hardening/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: - author: "Sebastian Gumprich" - description: 'This Ansible role provides secure nginx configurations. http://dev-sec.io/' + author: Sebastian Gumprich + description: This Ansible role provides secure nginx configurations. http://dev-sec.io/ company: Hardening Framework Team license: Apache License 2.0 - min_ansible_version: '2.9.10' + min_ansible_version: 2.9.10 platforms: - name: EL versions: diff --git a/roles/nginx_hardening/tasks/main.yml b/roles/nginx_hardening/tasks/main.yml index 6e77e596..de85d377 100644 --- a/roles/nginx_hardening/tasks/main.yml +++ b/roles/nginx_hardening/tasks/main.yml @@ -1,81 +1,81 @@ --- - name: Create additional configuration - template: - src: "hardening.conf.j2" + ansible.builtin.template: + src: hardening.conf.j2 dest: "{{ nginx_configuration_dir }}/conf.d/90.hardening.conf" - mode: '0600' + mode: "0600" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change configuration in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*server_tokens' + regexp: ^\s*server_tokens line: " server_tokens {{ nginx_server_tokens }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change ssl_protocols in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*ssl_protocols' + regexp: ^\s*ssl_protocols line: " ssl_protocols {{ nginx_ssl_protocols }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change ssl_prefer_server_ciphers in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*ssl_prefer_server_ciphers' + regexp: ^\s*ssl_prefer_server_ciphers line: " ssl_prefer_server_ciphers {{ nginx_ssl_prefer_server_ciphers }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change client_max_body_size in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*client_max_body_size' + regexp: ^\s*client_max_body_size line: " client_max_body_size {{ nginx_client_max_body_size }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change client_body_buffer_size in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*client_body_buffer_size' + regexp: ^\s*client_body_buffer_size line: " client_body_buffer_size {{ nginx_client_body_buffer_size }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Change keepalive_timeout in main nginx.conf - lineinfile: + ansible.builtin.lineinfile: dest: "{{ nginx_configuration_dir }}/nginx.conf" - regexp: '^\s*keepalive_timeout' + regexp: ^\s*keepalive_timeout line: " keepalive_timeout {{ nginx_keepalive_timeout }};" - insertafter: "http {" - mode: '0640' + insertafter: http { + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx - name: Remove default.conf - file: + ansible.builtin.file: path: "{{ item }}" state: absent when: nginx_remove_default_site @@ -85,10 +85,10 @@ - "{{ nginx_configuration_dir }}/sites-enabled/default" - name: Generate dh group - openssl_dhparam: + community.crypto.openssl_dhparam: path: "{{ nginx_configuration_dir }}/dh{{ nginx_dh_size }}.pem" size: "{{ nginx_dh_size }}" - mode: '0640' + mode: "0640" owner: "{{ nginx_owner_user }}" group: "{{ nginx_owner_group }}" notify: Restart nginx diff --git a/roles/os_hardening/defaults/main.yml b/roles/os_hardening/defaults/main.yml index 27fd4514..dc06e58e 100644 --- a/roles/os_hardening/defaults/main.yml +++ b/roles/os_hardening/defaults/main.yml @@ -2,18 +2,17 @@ os_desktop_enable: false os_env_extra_user_paths: [] os_auth_pw_max_age: 60 -os_auth_pw_min_age: 7 # Discourage password cycling -os_auth_pw_remember: 5 # Specify how many used passwords are record +os_auth_pw_min_age: 7 # Discourage password cycling +os_auth_pw_remember: 5 # Specify how many used passwords are record os_auth_retries: 5 -os_auth_lockout_time: 600 # Seconds (600 = 10min) +os_auth_lockout_time: 600 # Seconds (600 = 10min) os_auth_timeout: 60 os_auth_allow_homeless: false os_auth_pam_passwdqc_enable: true -os_auth_pam_passwdqc_options: 'min=disabled,disabled,16,12,8' # Used in Debian -os_auth_pam_pwquality_options: 'try_first_pass retry=3 authtok_type=' # Used in RHEL7 and RHEL8 +os_auth_pam_passwdqc_options: min=disabled,disabled,16,12,8 # Used in Debian +os_auth_pam_pwquality_options: try_first_pass retry=3 authtok_type= # Used in RHEL7 and RHEL8 os_auth_root_ttys: [console, tty1, tty2, tty3, tty4, tty5, tty6] - -os_chfn_restrict: '' +os_chfn_restrict: "" # Set to false to disable chmod userhome folders to 700 os_chmod_rootuser_home_folder: true @@ -22,8 +21,7 @@ os_chmod_home_folders: true # May contain: change_user os_security_users_allow: [] # Specify user home folders in /home that shouldn't be chmodded to 700 -os_ignore_home_folder_users: ['lost+found'] - +os_ignore_home_folder_users: [lost+found] # Set to false to disable password age enforcement on existing users os_rootuser_pw_ageing: false @@ -37,7 +35,7 @@ os_user_pw_ageing: true os_users_without_password_ageing: [] # Specify system accounts whose login should not be disabled and password not changed -os_ignore_users: ['vagrant', 'kitchen'] +os_ignore_users: [vagrant, kitchen] os_security_kernel_enable_module_loading: true os_security_kernel_enable_core_dump: false os_security_suid_sgid_enforce: true @@ -49,8 +47,7 @@ os_security_suid_sgid_remove_from_unknown: false # Remove packages with known security issues os_security_packages_clean: true -os_security_packages_list: ['xinetd', 'inetd', 'ypserv', 'telnet-server', 'rsh-server', 'prelink'] - +os_security_packages_list: [xinetd, inetd, ypserv, telnet-server, rsh-server, prelink] # Allow interactive startup (rhel, centos) os_security_init_prompt: true # Require root password for single user mode. (rhel, centos) @@ -63,15 +60,15 @@ ufw_manage_defaults: true # By default in Ubuntu it is set to: /etc/ufw/sysctl.conf # CAUTION! # If you enable it - it overwrites /etc/sysctl.conf file, managed by hardening framework -ufw_ipt_sysctl: '' +ufw_ipt_sysctl: "" # Default ufw variables -ufw_default_input_policy: 'DROP' -ufw_default_output_policy: 'ACCEPT' -ufw_default_forward_policy: 'DROP' -ufw_default_application_policy: 'SKIP' -ufw_manage_builtins: 'no' -ufw_ipt_modules: 'nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns' +ufw_default_input_policy: DROP +ufw_default_output_policy: ACCEPT +ufw_default_forward_policy: DROP +ufw_default_application_policy: SKIP +ufw_manage_builtins: "no" +ufw_ipt_modules: nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns # Set to true to apply rules to support IPv6 (no means only IPv6 on loopback # accepted). @@ -307,27 +304,25 @@ sysctl_config: # Do not delete the following line or otherwise the playbook will fail # at task 'create a combined sysctl-dict if overwrites are defined' sysctl_overwrite: - # Disable unused filesystems os_unused_filesystems: - - "cramfs" - - "freevxfs" - - "jffs2" - - "hfs" - - "hfsplus" - - "squashfs" - - "udf" - - "vfat" + - cramfs + - freevxfs + - jffs2 + - hfs + - hfsplus + - squashfs + - udf + - vfat # Obsolete network protocols that should be disabled # per CIS Oracle Linux 6 Benchmark (2016) - - "dccp" # CIS 3.5.1 - - "rds" # CIS 3.5.3 - - "sctp" # CIS 3.5.2 - - "tipc" # CIS 3.5.4 + - dccp # CIS 3.5.1 + - rds # CIS 3.5.3 + - sctp # CIS 3.5.2 + - tipc # CIS 3.5.4 # Whitelist for used filesystems os_filesystem_whitelist: [] - # Set to false to turn the role into a no-op. Useful when using # the Ansible role dependency mechanism. os_hardening_enabled: true @@ -353,7 +348,7 @@ os_selinux_state: enforcing os_selinux_policy: targeted # Mount options for proc in /etc/fstab. -proc_mnt_options: 'rw,nosuid,nodev,noexec,relatime,hidepid={{ hidepid_option }}' +proc_mnt_options: rw,nosuid,nodev,noexec,relatime,hidepid={{ hidepid_option }} # Set to false to disable installing and configuring cron. os_cron_enabled: true @@ -399,7 +394,6 @@ os_yum_enabled: true # List of yum repository files under /etc/yum.repos.d/ which should not be altered. os_yum_repo_file_whitelist: [] - # Set to false to disable installing and configuring apt. os_apt_enabled: true @@ -412,72 +406,82 @@ os_selinux_enabled: true os_sha_crypt_min_rounds: "640000" os_sha_crypt_max_rounds: "640000" +os_mnt_boot_dir_mode: "0700" os_mnt_boot_enabled: false os_mnt_boot_src: "" -os_mnt_boot_options: 'rw,nosuid,nodev,noexec' +os_mnt_boot_options: rw,nosuid,nodev,noexec os_mnt_boot_filesystem: "" os_mnt_boot_dump: "" os_mnt_boot_passno: "" +os_mnt_dev_dir_mode: "0755" os_mnt_dev_enabled: true -os_mnt_dev_src: "devtmpfs" -os_mnt_dev_options: 'rw,nosuid,noexec' -os_mnt_dev_filesystem: "devtmpfs" +os_mnt_dev_src: devtmpfs +os_mnt_dev_options: rw,nosuid,noexec +os_mnt_dev_filesystem: devtmpfs os_mnt_dev_dump: "" os_mnt_dev_passno: "" +os_mnt_dev_shm_dir_mode: "1777" os_mnt_dev_shm_enabled: true -os_mnt_dev_shm_src: "tmpfs" -os_mnt_dev_shm_options: 'rw,nosuid,nodev,noexec' -os_mnt_dev_shm_filesystem: "tmpfs" +os_mnt_dev_shm_src: tmpfs +os_mnt_dev_shm_options: rw,nosuid,nodev,noexec +os_mnt_dev_shm_filesystem: tmpfs os_mnt_dev_shm_dump: "" os_mnt_dev_shm_passno: "" +os_mnt_home_dir_mode: "0755" os_mnt_home_enabled: false os_mnt_home_src: "" -os_mnt_home_options: 'rw,nosuid,nodev' +os_mnt_home_options: rw,nosuid,nodev os_mnt_home_filesystem: "" os_mnt_home_dump: "" os_mnt_home_passno: "" +os_mnt_run_dir_mode: "0755" os_mnt_run_enabled: true -os_mnt_run_src: "tmpfs" -os_mnt_run_options: 'rw,nosuid,nodev' -os_mnt_run_filesystem: "tmpfs" +os_mnt_run_src: tmpfs +os_mnt_run_options: rw,nosuid,nodev +os_mnt_run_filesystem: tmpfs os_mnt_run_dump: "" os_mnt_run_passno: "" +os_mnt_tmp_dir_mode: "1777" os_mnt_tmp_enabled: false os_mnt_tmp_src: "" -os_mnt_tmp_options: 'rw,nosuid,nodev,noexec' +os_mnt_tmp_options: rw,nosuid,nodev,noexec os_mnt_tmp_filesystem: "" os_mnt_tmp_dump: "" os_mnt_tmp_passno: "" +os_mnt_var_dir_mode: "0755" os_mnt_var_enabled: false os_mnt_var_src: "" -os_mnt_var_options: 'rw,nosuid,nodev' +os_mnt_var_options: rw,nosuid,nodev os_mnt_var_filesystem: "" os_mnt_var_dump: "" os_mnt_var_passno: "" +os_mnt_var_log_dir_mode: "0755" os_mnt_var_log_enabled: false os_mnt_var_log_src: "" -os_mnt_var_log_options: 'rw,nosuid,nodev,noexec' +os_mnt_var_log_options: rw,nosuid,nodev,noexec os_mnt_var_log_filesystem: "" os_mnt_var_log_dump: "" os_mnt_var_log_passno: "" +os_mnt_var_log_audit_dir_mode: "0700" os_mnt_var_log_audit_enabled: false os_mnt_var_log_audit_src: "" -os_mnt_var_log_audit_options: 'rw,nosuid,nodev,noexec' +os_mnt_var_log_audit_options: rw,nosuid,nodev,noexec os_mnt_var_log_audit_filesystem: "" os_mnt_var_log_audit_dump: "" os_mnt_var_log_audit_passno: "" +os_mnt_var_tmp_dir_mode: "1777" os_mnt_var_tmp_enabled: false os_mnt_var_tmp_src: "" -os_mnt_var_tmp_options: 'rw,nosuid,nodev,noexec' +os_mnt_var_tmp_options: rw,nosuid,nodev,noexec os_mnt_var_tmp_filesystem: "" os_mnt_var_tmp_dump: "" os_mnt_var_tmp_passno: "" diff --git a/roles/os_hardening/handlers/main.yml b/roles/os_hardening/handlers/main.yml index 3d6ccba9..17ee7e90 100644 --- a/roles/os_hardening/handlers/main.yml +++ b/roles/os_hardening/handlers/main.yml @@ -1,11 +1,11 @@ --- - name: Update-initramfs - ansible.builtin.command: 'update-initramfs -u' + ansible.builtin.command: update-initramfs -u -- name: Restart auditd +- name: Restart auditd # noqa command-instead-of-module ansible.builtin.command: - cmd: 'service auditd restart' # rhel: see: https://access.redhat.com/solutions/2664811 - when: molecule_yml is not defined # restarting auditd in a container does not work + cmd: service auditd restart # rhel: see: https://access.redhat.com/solutions/2664811 + when: molecule_yml is not defined # restarting auditd in a container does not work - name: Reload systemd ansible.builtin.systemd: diff --git a/roles/os_hardening/meta/main.yml b/roles/os_hardening/meta/main.yml index 590897ab..308450c8 100644 --- a/roles/os_hardening/meta/main.yml +++ b/roles/os_hardening/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: - author: "Sebastian Gumprich" - description: 'This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.' + author: Sebastian Gumprich + description: This Ansible role provides numerous security-related ssh configurations, providing all-round base protection. company: Hardening Framework Team license: Apache License 2.0 - min_ansible_version: '2.9.10' + min_ansible_version: 2.9.10 platforms: - name: EL versions: diff --git a/roles/os_hardening/tasks/apt.yml b/roles/os_hardening/tasks/apt.yml index a34c9ab3..a1c85831 100644 --- a/roles/os_hardening/tasks/apt.yml +++ b/roles/os_hardening/tasks/apt.yml @@ -1,7 +1,7 @@ --- - name: Remove deprecated or insecure packages | package-01 - package-09 - apt: - name: '{{ os_security_packages_list }}' - state: 'absent' - purge: 'yes' + ansible.builtin.apt: + name: "{{ os_security_packages_list }}" + state: absent + purge: true when: os_security_packages_clean | bool diff --git a/roles/os_hardening/tasks/auditd.yml b/roles/os_hardening/tasks/auditd.yml index b35bc092..d24a694b 100644 --- a/roles/os_hardening/tasks/auditd.yml +++ b/roles/os_hardening/tasks/auditd.yml @@ -1,16 +1,16 @@ --- - name: Install auditd package | package-08 - package: - name: '{{ auditd_package }}' - state: 'present' + ansible.builtin.package: + name: "{{ auditd_package }}" + state: present tags: auditd - name: Configure auditd | package-08 - template: - src: 'etc/audit/auditd.conf.j2' - dest: '/etc/audit/auditd.conf' - owner: 'root' - group: 'root' - mode: '0640' + ansible.builtin.template: + src: etc/audit/auditd.conf.j2 + dest: /etc/audit/auditd.conf + owner: root + group: root + mode: "0640" notify: Restart auditd tags: auditd diff --git a/roles/os_hardening/tasks/cron.yml b/roles/os_hardening/tasks/cron.yml index 390d3f66..6e97c233 100644 --- a/roles/os_hardening/tasks/cron.yml +++ b/roles/os_hardening/tasks/cron.yml @@ -6,7 +6,7 @@ # CIS 5.1.2 - CIS 5.1.7 # - name: Find cron files and directories - find: + ansible.builtin.find: paths: - /etc patterns: diff --git a/roles/os_hardening/tasks/ctrlaltdel.yml b/roles/os_hardening/tasks/ctrlaltdel.yml index 7daaf8c6..dae46ad6 100644 --- a/roles/os_hardening/tasks/ctrlaltdel.yml +++ b/roles/os_hardening/tasks/ctrlaltdel.yml @@ -1,6 +1,6 @@ --- - name: Disable CTRL-ALT-DEL - systemd: + ansible.builtin.systemd: name: ctrl-alt-del.target masked: true daemon_reload: true diff --git a/roles/os_hardening/tasks/hardening.yml b/roles/os_hardening/tasks/hardening.yml index ec77a7f2..a76b74c0 100644 --- a/roles/os_hardening/tasks/hardening.yml +++ b/roles/os_hardening/tasks/hardening.yml @@ -1,118 +1,118 @@ --- - name: Fetch OS dependent variables - include_vars: - file: '{{ item }}' - name: 'os_vars' + ansible.builtin.include_vars: + file: "{{ item }}" + name: os_vars with_first_found: - files: - - '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml' - - '{{ ansible_facts.distribution }}.yml' - - '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml' - - '{{ ansible_facts.os_family }}.yml' + - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml" + - "{{ ansible_facts.distribution }}.yml" + - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml" + - "{{ ansible_facts.os_family }}.yml" skip: true tags: always # we only override variables with our default, if they have not been specified already # by default the lookup functions finds all varnames containing the string, therefore # we add ^ and $ to denote start and end of string, so this returns only exact matches -- name: Set OS dependent variables, if not already defined by user # noqa var-naming - set_fact: - '{{ item.key }}': '{{ item.value }}' - when: "not lookup('varnames', '^' + item.key + '$')" - with_dict: '{{ os_vars }}' +- name: Set OS dependent variables, if not already defined by user # noqa var-naming + ansible.builtin.set_fact: + "{{ item.key }}": "{{ item.value }}" + when: not lookup('varnames', '^' + item.key + '$') + with_dict: "{{ os_vars }}" tags: always - name: Import tasks for auditd - import_tasks: auditd.yml + ansible.builtin.import_tasks: auditd.yml tags: auditd when: os_auditd_enabled | bool - name: Import tasks for cron - import_tasks: cron.yml + ansible.builtin.import_tasks: cron.yml tags: cron when: os_cron_enabled | bool - name: Import tasks to configure ctrl+alt+del - import_tasks: ctrlaltdel.yml + ansible.builtin.import_tasks: ctrlaltdel.yml tags: ctrlaltdel when: os_ctrlaltdel_disabled | bool - name: Import tasks to configure limits - import_tasks: limits.yml + ansible.builtin.import_tasks: limits.yml tags: limits when: os_limits_enabled | bool - name: Import tasks to configure login_defs - import_tasks: login_defs.yml + ansible.builtin.import_tasks: login_defs.yml tags: login_defs when: os_login_defs_enabled | bool - name: Import tasks to minimize access permissions - import_tasks: minimize_access.yml + ansible.builtin.import_tasks: minimize_access.yml tags: minimize_access when: os_minimize_access_enabled | bool - name: Import tasks to configure PAM - import_tasks: pam.yml + ansible.builtin.import_tasks: pam.yml tags: pam when: os_pam_enabled | bool - name: Import tasks to configure modules - import_tasks: modprobe.yml + ansible.builtin.import_tasks: modprobe.yml tags: modprobe when: os_modprobe_enabled | bool - name: Import tasks to configure profile - import_tasks: profile.yml + ansible.builtin.import_tasks: profile.yml tags: profile when: os_profile_enabled | bool - name: Import tasks to configure securetty - import_tasks: securetty.yml + ansible.builtin.import_tasks: securetty.yml tags: securetty when: os_securetty_enabled | bool - name: Import tasks to set suid and sgid - import_tasks: suid_sgid.yml + ansible.builtin.import_tasks: suid_sgid.yml when: os_security_suid_sgid_enforce | bool tags: suid_sgid - name: Import tasks to configure sysctl - import_tasks: sysctl.yml + ansible.builtin.import_tasks: sysctl.yml tags: sysctl when: os_sysctl_enabled | bool - name: Import tasks to harden user accounts - import_tasks: user_accounts.yml + ansible.builtin.import_tasks: user_accounts.yml tags: user_accounts when: os_user_accounts_enabled | bool - name: Import tasks to configure rhosts - import_tasks: rhosts.yml + ansible.builtin.import_tasks: rhosts.yml tags: rhosts when: os_rhosts_enabled | bool - name: Import tasks to configure netrc - import_tasks: netrc.yml + ansible.builtin.import_tasks: netrc.yml tags: netrc when: os_netrc_enabled | bool - name: Import tasks to configure yum - import_tasks: yum.yml + ansible.builtin.import_tasks: yum.yml tags: yum when: - ansible_facts.os_family == 'RedHat' - os_yum_enabled | bool - name: Import tasks to configure apt - import_tasks: apt.yml + ansible.builtin.import_tasks: apt.yml tags: apt when: - ansible_facts.os_family == 'Debian' - os_apt_enabled | bool - name: Import tasks to configure selinux - import_tasks: selinux.yml + ansible.builtin.import_tasks: selinux.yml tags: selinux when: - ansible_facts.selinux.status == 'enabled' diff --git a/roles/os_hardening/tasks/limits.yml b/roles/os_hardening/tasks/limits.yml index 5b0ddaec..6a6d5c61 100644 --- a/roles/os_hardening/tasks/limits.yml +++ b/roles/os_hardening/tasks/limits.yml @@ -2,63 +2,63 @@ - name: Disable coredumps when: not os_security_kernel_enable_core_dump | bool block: - - name: Create limits.d-directory if it does not exist | sysctl-31a, sysctl-31b - file: - path: '/etc/security/limits.d' - owner: 'root' - group: 'root' - mode: '0755' - state: 'directory' + - name: Create limits.d-directory if it does not exist | sysctl-31a, sysctl-31b + ansible.builtin.file: + path: /etc/security/limits.d + owner: root + group: root + mode: "0755" + state: directory - - name: Create additional limits config file -> 10.hardcore.conf | sysctl-31a, sysctl-31b - pam_limits: - dest: '/etc/security/limits.d/10.hardcore.conf' - domain: '*' - limit_type: hard - limit_item: core - value: '0' - comment: Prevent core dumps for all users. These are usually not needed and may contain sensitive information + - name: Create additional limits config file -> 10.hardcore.conf | sysctl-31a, sysctl-31b + community.general.pam_limits: + dest: /etc/security/limits.d/10.hardcore.conf + domain: "*" + limit_type: hard + limit_item: core + value: "0" + comment: Prevent core dumps for all users. These are usually not needed and may contain sensitive information - - name: Set 10.hardcore.conf perms to 0400 and root ownership - file: - path: /etc/security/limits.d/10.hardcore.conf - owner: 'root' - group: 'root' - mode: '0440' - state: touch - modification_time: preserve - access_time: preserve + - name: Set 10.hardcore.conf perms to 0400 and root ownership + ansible.builtin.file: + path: /etc/security/limits.d/10.hardcore.conf + owner: root + group: root + mode: "0440" + state: touch + modification_time: preserve + access_time: preserve - - name: Create coredump.conf.d-directory if it does not exist - file: - path: '/etc/systemd/coredump.conf.d' - owner: root - group: root - mode: 0755 - state: directory - when: ansible_service_mgr == "systemd" + - name: Create coredump.conf.d-directory if it does not exist + ansible.builtin.file: + path: /etc/systemd/coredump.conf.d + owner: root + group: root + mode: 0755 + state: directory + when: ansible_service_mgr == "systemd" - - name: Create custom.conf for disabling coredumps - template: - src: 'etc/systemd/coredump.conf.d/coredumps.conf.j2' - dest: '/etc/systemd/coredump.conf.d/custom.conf' - owner: root - group: root - mode: 0644 - when: ansible_service_mgr == "systemd" - notify: Reload systemd + - name: Create custom.conf for disabling coredumps + ansible.builtin.template: + src: etc/systemd/coredump.conf.d/coredumps.conf.j2 + dest: /etc/systemd/coredump.conf.d/custom.conf + owner: root + group: root + mode: 0644 + when: ansible_service_mgr == "systemd" + notify: Reload systemd - name: Enable coredumps when: os_security_kernel_enable_core_dump | bool block: - name: Remove coredump.conf.d directory with files - file: + ansible.builtin.file: path: /etc/systemd/coredump.conf.d state: absent when: ansible_service_mgr == "systemd" notify: Reload systemd - name: Remove 10.hardcore.conf config file - file: + ansible.builtin.file: path: /etc/security/limits.d/10.hardcore.conf state: absent diff --git a/roles/os_hardening/tasks/login_defs.yml b/roles/os_hardening/tasks/login_defs.yml index a1f092f6..a84e2ba9 100644 --- a/roles/os_hardening/tasks/login_defs.yml +++ b/roles/os_hardening/tasks/login_defs.yml @@ -1,8 +1,8 @@ --- - name: Create login.defs | os-05, os-05b - template: - src: 'etc/login.defs.j2' - dest: '/etc/login.defs' - owner: 'root' - group: 'root' - mode: '0444' + ansible.builtin.template: + src: etc/login.defs.j2 + dest: /etc/login.defs + owner: root + group: root + mode: "0444" diff --git a/roles/os_hardening/tasks/main.yml b/roles/os_hardening/tasks/main.yml index f032907b..6f7fe824 100644 --- a/roles/os_hardening/tasks/main.yml +++ b/roles/os_hardening/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Include hardening tasks - include_tasks: hardening.yml + ansible.builtin.include_tasks: hardening.yml when: os_hardening_enabled | bool tags: - always diff --git a/roles/os_hardening/tasks/minimize_access.yml b/roles/os_hardening/tasks/minimize_access.yml index af1834e6..da99781b 100644 --- a/roles/os_hardening/tasks/minimize_access.yml +++ b/roles/os_hardening/tasks/minimize_access.yml @@ -4,103 +4,193 @@ # still getting found and the permissions minimized in the next task. # This is also the reason why there's ignore_errors: true on the task. # also see: https://github.com/dev-sec/ansible-os-hardening/issues/219 -- name: Find files with write-permissions for group - shell: "find -L {{ item }} -perm /go+w -type f" # noqa command-instead-of-shell +- name: Find files with write-permissions for group # noqa command-instead-of-shell + ansible.builtin.shell: find -L {{ item }} -perm /go+w -type f with_community.general.flattened: - - '/usr/local/sbin' - - '/usr/local/bin' - - '/usr/sbin' - - '/usr/bin' - - '/sbin' - - '/bin' - - "{{ os_env_extra_user_paths }}" # noqa deprecated-bare-vars + - /usr/local/sbin + - /usr/local/bin + - /usr/sbin + - /usr/bin + - /sbin + - /bin + - "{{ os_env_extra_user_paths }}" register: minimize_access_directories ignore_errors: true changed_when: false - name: Minimize access on found files - file: - path: '{{ item.1 }}' - mode: 'go-w' + ansible.builtin.file: + path: "{{ item.1 }}" + mode: go-w state: file with_subelements: - "{{ minimize_access_directories.results }}" - stdout_lines - name: Find shadow files - stat: + ansible.builtin.stat: path: "{{ item }}" loop: - - '/etc/shadow' - - '/etc/gshadow' - - '/etc/shadow-' - - '/etc/gshadow-' + - /etc/shadow + - /etc/gshadow + - /etc/shadow- + - /etc/gshadow- register: minimize_access_shadow_files - name: Change shadow ownership to root and mode to 0600 | os-02 - file: + ansible.builtin.file: dest: "{{ item.item }}" - owner: '{{ os_shadow_perms.owner }}' - group: '{{ os_shadow_perms.group }}' - mode: '{{ os_shadow_perms.mode }}' + owner: "{{ os_shadow_perms.owner }}" + group: "{{ os_shadow_perms.group }}" + mode: "{{ os_shadow_perms.mode }}" when: item.stat.exists loop: "{{ minimize_access_shadow_files.results }}" - name: Find passwd files - stat: + ansible.builtin.stat: path: "{{ item }}" loop: - - '/etc/passwd' - - '/etc/group' - - '/etc/passwd-' - - '/etc/group-' + - /etc/passwd + - /etc/group + - /etc/passwd- + - /etc/group- register: minimize_access_passwd_files - name: Change passwd ownership to root and mode to 0644 | os-03 - file: + ansible.builtin.file: dest: "{{ item.item }}" - owner: '{{ os_passwd_perms.owner }}' - group: '{{ os_passwd_perms.group }}' - mode: '{{ os_passwd_perms.mode }}' + owner: "{{ os_passwd_perms.owner }}" + group: "{{ os_passwd_perms.group }}" + mode: "{{ os_passwd_perms.mode }}" when: item.stat.exists loop: "{{ minimize_access_passwd_files.results }}" - name: Change su-binary to only be accessible to user and group root - file: - dest: '/bin/su' - owner: 'root' - group: 'root' - mode: '0750' + ansible.builtin.file: + dest: /bin/su + owner: root + group: root + mode: "0750" when: '"change_user" not in os_security_users_allow' - name: Set option hidepid for proc filesystem - mount: + ansible.posix.mount: path: /proc src: proc fstype: proc - opts: '{{ proc_mnt_options }}' + opts: "{{ proc_mnt_options }}" state: mounted - name: Generate list of current available mounted filesystems on the system - set_fact: + ansible.builtin.set_fact: mountpoints_list: "{{ ansible_mounts | map(attribute='mount') | list }}" - name: Append special devices list to valid mountpoint list - set_fact: + ansible.builtin.set_fact: mountpoints_list: "{{ mountpoints_list + ['/dev', '/dev/shm', '/run'] }}" - name: Minimize access for filesystems - include_tasks: minimize_access_fs.yml - loop: - - { path: '/boot', src: '{{ os_mnt_boot_src }}', fstype: '{{ os_mnt_boot_filesystem }}', opts: '{{ os_mnt_boot_options }}', enabled: "{{ os_mnt_boot_enabled }}", mode: "{{ os_mnt_boot_dir_mode }}", group: "{{ os_mnt_boot_group }}", owner: "{{ os_mnt_boot_owner }}", dump: "{{ os_mnt_boot_dump }}", passno: "{{ os_mnt_boot_passno }}" } - - { path: '/dev', src: '{{ os_mnt_dev_src }}', fstype: '{{ os_mnt_dev_filesystem }}', opts: '{{ os_mnt_dev_options }}', enabled: "{{ os_mnt_dev_enabled }}", mode: "{{ os_mnt_dev_dir_mode }}", group: "{{ os_mnt_dev_group }}", owner: "{{ os_mnt_dev_owner }}", dump: "{{ os_mnt_dev_dump }}", passno: "{{ os_mnt_dev_passno }}" } - - { path: '/dev/shm', src: '{{ os_mnt_dev_shm_src }}', fstype: '{{ os_mnt_dev_shm_filesystem }}', opts: '{{ os_mnt_dev_shm_options }}', enabled: "{{ os_mnt_dev_shm_enabled }}", mode: "{{ os_mnt_dev_shm_dir_mode }}", group: "{{ os_mnt_dev_shm_group }}", owner: "{{ os_mnt_dev_shm_owner }}", dump: "{{ os_mnt_dev_shm_dump }}", passno: "{{ os_mnt_dev_shm_passno }}" } - - { path: '/home', src: '{{ os_mnt_home_src }}', fstype: '{{ os_mnt_home_filesystem }}', opts: '{{ os_mnt_home_options }}', enabled: "{{ os_mnt_home_enabled }}", mode: "{{ os_mnt_home_dir_mode }}", group: "{{ os_mnt_home_group }}", owner: "{{ os_mnt_home_owner }}", dump: "{{ os_mnt_home_dump }}", passno: "{{ os_mnt_home_passno }}" } - - { path: '/run', src: '{{ os_mnt_run_src }}', fstype: '{{ os_mnt_run_filesystem }}', opts: '{{ os_mnt_run_options }}', enabled: "{{ os_mnt_run_enabled }}", mode: "{{ os_mnt_run_dir_mode }}", group: "{{ os_mnt_run_group }}", owner: "{{ os_mnt_run_owner }}", dump: "{{ os_mnt_run_dump }}", passno: "{{ os_mnt_run_passno }}" } - - { path: '/tmp', src: '{{ os_mnt_tmp_src }}', fstype: '{{ os_mnt_tmp_filesystem }}', opts: '{{ os_mnt_tmp_options }}', enabled: "{{ os_mnt_tmp_enabled }}", mode: "{{ os_mnt_tmp_dir_mode }}", group: "{{ os_mnt_tmp_group }}", owner: "{{ os_mnt_tmp_owner }}", dump: "{{ os_mnt_tmp_dump }}", passno: "{{ os_mnt_tmp_passno }}" } - - { path: '/var', src: '{{ os_mnt_var_src }}', fstype: '{{ os_mnt_var_filesystem }}', opts: '{{ os_mnt_var_options }}', enabled: "{{ os_mnt_var_enabled }}", mode: "{{ os_mnt_var_dir_mode }}", group: "{{ os_mnt_var_group }}", owner: "{{ os_mnt_var_owner }}", dump: "{{ os_mnt_var_dump }}", passno: "{{ os_mnt_var_passno }}" } - - { path: '/var/log', src: '{{ os_mnt_var_log_src }}', fstype: '{{ os_mnt_var_log_filesystem }}', opts: '{{ os_mnt_var_log_options }}', enabled: "{{ os_mnt_var_log_enabled }}", mode: "{{ os_mnt_var_log_dir_mode }}", group: "{{ os_mnt_var_log_group }}", owner: "{{ os_mnt_var_log_owner }}", dump: "{{ os_mnt_var_log_dump }}", passno: "{{ os_mnt_var_log_passno }}" } - - { path: '/var/log/audit', src: '{{ os_mnt_var_log_audit_src }}', fstype: '{{ os_mnt_var_log_audit_filesystem }}', opts: '{{ os_mnt_var_log_audit_options }}', enabled: "{{ os_mnt_var_log_audit_enabled }}", mode: "{{ os_mnt_var_log_audit_dir_mode }}", group: "{{ os_mnt_var_log_audit_group }}", owner: "{{ os_mnt_var_log_audit_owner }}", dump: "{{ os_mnt_var_log_audit_dump }}", passno: "{{ os_mnt_var_log_audit_passno }}" } - - { path: '/var/tmp', src: '{{ os_mnt_var_tmp_src }}', fstype: '{{ os_mnt_var_tmp_filesystem }}', opts: '{{ os_mnt_var_tmp_options }}', enabled: "{{ os_mnt_var_tmp_enabled }}", mode: "{{ os_mnt_var_tmp_dir_mode }}", group: "{{ os_mnt_var_tmp_group }}", owner: "{{ os_mnt_var_tmp_owner }}", dump: "{{ os_mnt_var_tmp_dump }}", passno: "{{ os_mnt_var_tmp_passno }}" } + ansible.builtin.include_tasks: minimize_access_fs.yml loop_control: loop_var: mount + loop: + - path: /boot + src: "{{ os_mnt_boot_src }}" + fstype: "{{ os_mnt_boot_filesystem }}" + opts: "{{ os_mnt_boot_options }}" + enabled: "{{ os_mnt_boot_enabled }}" + mode: "{{ os_mnt_boot_dir_mode }}" + group: "{{ os_mnt_boot_group }}" + owner: "{{ os_mnt_boot_owner }}" + dump: "{{ os_mnt_boot_dump }}" + passno: "{{ os_mnt_boot_passno }}" + - path: /dev + src: "{{ os_mnt_dev_src }}" + fstype: "{{ os_mnt_dev_filesystem }}" + opts: "{{ os_mnt_dev_options }}" + enabled: "{{ os_mnt_dev_enabled }}" + mode: "{{ os_mnt_dev_dir_mode }}" + group: "{{ os_mnt_dev_group }}" + owner: "{{ os_mnt_dev_owner }}" + dump: "{{ os_mnt_dev_dump }}" + passno: "{{ os_mnt_dev_passno }}" + - path: /dev/shm + src: "{{ os_mnt_dev_shm_src }}" + fstype: "{{ os_mnt_dev_shm_filesystem }}" + opts: "{{ os_mnt_dev_shm_options }}" + enabled: "{{ os_mnt_dev_shm_enabled }}" + mode: "{{ os_mnt_dev_shm_dir_mode }}" + group: "{{ os_mnt_dev_shm_group }}" + owner: "{{ os_mnt_dev_shm_owner }}" + dump: "{{ os_mnt_dev_shm_dump }}" + passno: "{{ os_mnt_dev_shm_passno }}" + - path: /home + src: "{{ os_mnt_home_src }}" + fstype: "{{ os_mnt_home_filesystem }}" + opts: "{{ os_mnt_home_options }}" + enabled: "{{ os_mnt_home_enabled }}" + mode: "{{ os_mnt_home_dir_mode }}" + group: "{{ os_mnt_home_group }}" + owner: "{{ os_mnt_home_owner }}" + dump: "{{ os_mnt_home_dump }}" + passno: "{{ os_mnt_home_passno }}" + - path: /run + src: "{{ os_mnt_run_src }}" + fstype: "{{ os_mnt_run_filesystem }}" + opts: "{{ os_mnt_run_options }}" + enabled: "{{ os_mnt_run_enabled }}" + mode: "{{ os_mnt_run_dir_mode }}" + group: "{{ os_mnt_run_group }}" + owner: "{{ os_mnt_run_owner }}" + dump: "{{ os_mnt_run_dump }}" + passno: "{{ os_mnt_run_passno }}" + - path: /tmp + src: "{{ os_mnt_tmp_src }}" + fstype: "{{ os_mnt_tmp_filesystem }}" + opts: "{{ os_mnt_tmp_options }}" + enabled: "{{ os_mnt_tmp_enabled }}" + mode: "{{ os_mnt_tmp_dir_mode }}" + group: "{{ os_mnt_tmp_group }}" + owner: "{{ os_mnt_tmp_owner }}" + dump: "{{ os_mnt_tmp_dump }}" + passno: "{{ os_mnt_tmp_passno }}" + - path: /var + src: "{{ os_mnt_var_src }}" + fstype: "{{ os_mnt_var_filesystem }}" + opts: "{{ os_mnt_var_options }}" + enabled: "{{ os_mnt_var_enabled }}" + mode: "{{ os_mnt_var_dir_mode }}" + group: "{{ os_mnt_var_group }}" + owner: "{{ os_mnt_var_owner }}" + dump: "{{ os_mnt_var_dump }}" + passno: "{{ os_mnt_var_passno }}" + - path: /var/log + src: "{{ os_mnt_var_log_src }}" + fstype: "{{ os_mnt_var_log_filesystem }}" + opts: "{{ os_mnt_var_log_options }}" + enabled: "{{ os_mnt_var_log_enabled }}" + mode: "{{ os_mnt_var_log_dir_mode }}" + group: "{{ os_mnt_var_log_group }}" + owner: "{{ os_mnt_var_log_owner }}" + dump: "{{ os_mnt_var_log_dump }}" + passno: "{{ os_mnt_var_log_passno }}" + - path: /var/log/audit + src: "{{ os_mnt_var_log_audit_src }}" + fstype: "{{ os_mnt_var_log_audit_filesystem }}" + opts: "{{ os_mnt_var_log_audit_options }}" + enabled: "{{ os_mnt_var_log_audit_enabled }}" + mode: "{{ os_mnt_var_log_audit_dir_mode }}" + group: "{{ os_mnt_var_log_audit_group }}" + owner: "{{ os_mnt_var_log_audit_owner }}" + dump: "{{ os_mnt_var_log_audit_dump }}" + passno: "{{ os_mnt_var_log_audit_passno }}" + - path: /var/tmp + src: "{{ os_mnt_var_tmp_src }}" + fstype: "{{ os_mnt_var_tmp_filesystem }}" + opts: "{{ os_mnt_var_tmp_options }}" + enabled: "{{ os_mnt_var_tmp_enabled }}" + mode: "{{ os_mnt_var_tmp_dir_mode }}" + group: "{{ os_mnt_var_tmp_group }}" + owner: "{{ os_mnt_var_tmp_owner }}" + dump: "{{ os_mnt_var_tmp_dump }}" + passno: "{{ os_mnt_var_tmp_passno }}" diff --git a/roles/os_hardening/tasks/modprobe.yml b/roles/os_hardening/tasks/modprobe.yml index 2c22aa0d..23aad5dc 100644 --- a/roles/os_hardening/tasks/modprobe.yml +++ b/roles/os_hardening/tasks/modprobe.yml @@ -1,29 +1,29 @@ --- - name: Install modprobe to disable filesystems | os-10 - package: - name: '{{ modprobe_package }}' - state: 'present' + ansible.builtin.package: + name: "{{ modprobe_package }}" + state: present - name: Check if efi is installed - stat: - path: "/sys/firmware/efi" + ansible.builtin.stat: + path: /sys/firmware/efi register: efi_installed - name: Remove vfat from fs-list if efi is used - set_fact: + ansible.builtin.set_fact: os_unused_filesystems: "{{ os_unused_filesystems | difference('vfat') }}" when: - efi_installed.stat.isdir is defined - efi_installed.stat.isdir - name: Remove used filesystems from fs-list - set_fact: + ansible.builtin.set_fact: os_unused_filesystems: "{{ os_unused_filesystems | difference(ansible_mounts | map(attribute='fstype') | list) }}" - name: Disable unused filesystems | os-10 - template: - src: 'etc/modprobe.d/modprobe.j2' - dest: '/etc/modprobe.d/dev-sec.conf' - owner: 'root' - group: 'root' - mode: '0644' + ansible.builtin.template: + src: etc/modprobe.d/modprobe.j2 + dest: /etc/modprobe.d/dev-sec.conf + owner: root + group: root + mode: "0644" diff --git a/roles/os_hardening/tasks/netrc.yml b/roles/os_hardening/tasks/netrc.yml index 46722190..df3782a3 100644 --- a/roles/os_hardening/tasks/netrc.yml +++ b/roles/os_hardening/tasks/netrc.yml @@ -1,13 +1,13 @@ --- - name: Get user accounts | os-09 - command: "awk -F: '{print $1}' /etc/passwd" + ansible.builtin.command: "awk -F: '{print $1}' /etc/passwd" changed_when: false check_mode: false register: users_accounts - name: Delete .netrc-files from system | os-09 - file: - dest: '~{{ item }}/.netrc' - state: 'absent' - loop: '{{ users_accounts.stdout_lines | flatten | default([]) }}' + ansible.builtin.file: + dest: ~{{ item }}/.netrc + state: absent + loop: "{{ users_accounts.stdout_lines | flatten | default([]) }}" when: item not in os_netrc_whitelist_user diff --git a/roles/os_hardening/tasks/pam.yml b/roles/os_hardening/tasks/pam.yml index 689e937c..d83a7c21 100644 --- a/roles/os_hardening/tasks/pam.yml +++ b/roles/os_hardening/tasks/pam.yml @@ -1,6 +1,6 @@ --- - name: Gather package facts - package_facts: + ansible.builtin.package_facts: manager: auto when: - ansible_facts.os_family != 'Suse' @@ -11,29 +11,29 @@ # normally caching credentials shouldn't be necessary for most machines. # removing it provides some more security while not removing usability. - name: Remove pam ccreds to disable password caching - package: - name: '{{ os_packages_pam_ccreds }}' - state: 'absent' + ansible.builtin.package: + name: "{{ os_packages_pam_ccreds }}" + state: absent when: - ansible_facts.os_family != 'Archlinux' - name: Import tasks for Debian PAM - import_tasks: pam_debian.yml + ansible.builtin.import_tasks: pam_debian.yml when: - ansible_facts.os_family == 'Debian' - name: Import tasks for RedHat PAM - import_tasks: pam_rhel.yml + ansible.builtin.import_tasks: pam_rhel.yml when: - ansible_facts.os_family == 'RedHat' - name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512 - template: - src: 'etc/libuser.conf.j2' - dest: '/etc/libuser.conf' - mode: '0640' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: etc/libuser.conf.j2 + dest: /etc/libuser.conf + mode: "0640" + owner: root + group: root when: - ansible_facts.os_family != 'Suse' - ansible_facts.os_family != 'Archlinux' diff --git a/roles/os_hardening/tasks/pam_debian.yml b/roles/os_hardening/tasks/pam_debian.yml index 57d3d870..f49de474 100644 --- a/roles/os_hardening/tasks/pam_debian.yml +++ b/roles/os_hardening/tasks/pam_debian.yml @@ -1,120 +1,120 @@ --- - name: Install the package for strong password checking - apt: - name: 'libpam-passwdqc' - state: 'present' - update_cache: 'yes' + ansible.builtin.apt: + name: libpam-passwdqc + state: present + update_cache: true when: - os_auth_pam_passwdqc_enable - name: Configure passwdqc - template: - src: 'usr/share/pam-configs/pam_passwdqc.j2' - dest: '{{ passwdqc_path }}' - mode: '0644' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: usr/share/pam-configs/pam_passwdqc.j2 + dest: "{{ passwdqc_path }}" + mode: "0644" + owner: root + group: root when: - os_auth_pam_passwdqc_enable - name: Install tally2 - apt: - name: 'libpam-modules' - state: 'present' + ansible.builtin.apt: + name: libpam-modules + state: present when: - os_auth_retries|int > 0 - name: Manage tally on Debian stable when: - "'libpam-modules' in ansible_facts.packages" - - "ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '<')" + - ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '<') block: - name: Configure tally2 - template: - src: 'usr/share/pam-configs/pam_tally2.j2' - dest: '{{ tally2_path }}' - mode: '0644' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: usr/share/pam-configs/pam_tally2.j2 + dest: "{{ tally2_path }}" + mode: "0644" + owner: root + group: root when: - os_auth_retries|int > 0 - name: Delete tally2 when retries is 0 - file: - path: '{{ tally2_path }}' - state: 'absent' + ansible.builtin.file: + path: "{{ tally2_path }}" + state: absent when: - os_auth_retries|int == 0 - name: Manage tally/faillock on Debian unstable when: - "'libpam-modules' in ansible_facts.packages" - - "ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '>=')" + - ansible_facts.packages['libpam-modules'][0].version is version('1.4.0', '>=') block: - name: Delete tally2 - file: - path: '{{ tally2_path }}' - state: 'absent' + ansible.builtin.file: + path: "{{ tally2_path }}" + state: absent - name: Create tally directory - file: - path: '/var/run/faillock' - state: 'directory' - mode: '0755' - owner: 'root' - group: 'root' + ansible.builtin.file: + path: /var/run/faillock + state: directory + mode: "0755" + owner: root + group: root - name: Configure faillock - template: - src: 'etc/security/faillock.conf.j2' - dest: '/etc/security/faillock.conf' - mode: '0644' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: etc/security/faillock.conf.j2 + dest: /etc/security/faillock.conf + mode: "0644" + owner: root + group: root - name: Configure faillock pam - template: - src: 'usr/share/pam-configs/pam_faillock.j2' - dest: '/usr/share/pam-configs/faillock' - mode: '0644' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: usr/share/pam-configs/pam_faillock.j2 + dest: /usr/share/pam-configs/faillock + mode: "0644" + owner: root + group: root when: - os_auth_retries|int > 0 - name: Configure faillock pam authfail - template: - src: 'usr/share/pam-configs/pam_faillock_authfail.j2' - dest: '/usr/share/pam-configs/faillock_authfail' - mode: '0644' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: usr/share/pam-configs/pam_faillock_authfail.j2 + dest: /usr/share/pam-configs/faillock_authfail + mode: "0644" + owner: root + group: root when: - os_auth_retries|int > 0 - name: Delete faillock when retries is 0 - file: - path: '/usr/share/pam-configs/faillock' - state: 'absent' + ansible.builtin.file: + path: /usr/share/pam-configs/faillock + state: absent when: - os_auth_retries|int == 0 - name: Delete faillock authfail when retries is 0 - file: - path: '/usr/share/pam-configs/faillock_authfail' - state: 'absent' + ansible.builtin.file: + path: /usr/share/pam-configs/faillock_authfail + state: absent when: - os_auth_retries|int == 0 - name: Update pam on Debian systems - command: 'pam-auth-update --package' + ansible.builtin.command: pam-auth-update --package environment: DEBIAN_FRONTEND: noninteractive changed_when: false - name: Remove passwdqc - apt: - name: 'libpam-passwdqc' - state: 'absent' + ansible.builtin.apt: + name: libpam-passwdqc + state: absent when: - not os_auth_pam_passwdqc_enable diff --git a/roles/os_hardening/tasks/pam_rhel.yml b/roles/os_hardening/tasks/pam_rhel.yml index 8548dc82..8468b01c 100644 --- a/roles/os_hardening/tasks/pam_rhel.yml +++ b/roles/os_hardening/tasks/pam_rhel.yml @@ -1,43 +1,43 @@ --- - name: Install sssd-clients - yum: + ansible.builtin.yum: name: sssd-client - state: 'present' + state: present when: - os_auth_pam_sssd_enable | bool - name: Configure passwdqc and faillock via central system-auth config - template: - src: 'etc/pam.d/rhel_auth.j2' - dest: '/etc/pam.d/system-auth-local' - mode: '0640' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: etc/pam.d/rhel_auth.j2 + dest: /etc/pam.d/system-auth-local + mode: "0640" + owner: root + group: root - name: Enable our config for system-auth - file: + ansible.builtin.file: src: /etc/pam.d/system-auth-local dest: /etc/pam.d/system-auth - mode: '0640' - owner: 'root' - group: 'root' + mode: "0640" + owner: root + group: root state: link force: true - name: Configure passwdqc and faillock via central password-auth config - template: - src: 'etc/pam.d/rhel_auth.j2' - dest: '/etc/pam.d/password-auth-local' - mode: '0640' - owner: 'root' - group: 'root' + ansible.builtin.template: + src: etc/pam.d/rhel_auth.j2 + dest: /etc/pam.d/password-auth-local + mode: "0640" + owner: root + group: root - name: Enable our config for password-auth - file: + ansible.builtin.file: src: /etc/pam.d/password-auth-local dest: /etc/pam.d/password-auth - mode: '0640' - owner: 'root' - group: 'root' + mode: "0640" + owner: root + group: root state: link force: true diff --git a/roles/os_hardening/tasks/profile.yml b/roles/os_hardening/tasks/profile.yml index 14eac390..9bff0557 100644 --- a/roles/os_hardening/tasks/profile.yml +++ b/roles/os_hardening/tasks/profile.yml @@ -1,23 +1,23 @@ --- - name: Add pinerolo_profile.sh to profile.d - template: - src: 'etc/profile.d/profile.conf.j2' - dest: '/etc/profile.d/pinerolo_profile.sh' - owner: 'root' - group: 'root' - mode: '0750' + ansible.builtin.template: + src: etc/profile.d/profile.conf.j2 + dest: /etc/profile.d/pinerolo_profile.sh + owner: root + group: root + mode: "0750" when: not os_security_kernel_enable_core_dump | bool - name: Remove pinerolo_profile.sh from profile.d - file: + ansible.builtin.file: path: /etc/profile.d/pinerolo_profile.sh state: absent when: os_security_kernel_enable_core_dump | bool - name: Add autologout to profile env - template: - src: 'etc/profile.d/tmout.sh.j2' - dest: '/etc/profile.d/tmout.sh' - owner: 'root' - group: 'root' - mode: '0644' + ansible.builtin.template: + src: etc/profile.d/tmout.sh.j2 + dest: /etc/profile.d/tmout.sh + owner: root + group: root + mode: "0644" diff --git a/roles/os_hardening/tasks/rhosts.yml b/roles/os_hardening/tasks/rhosts.yml index 8af93884..05211308 100644 --- a/roles/os_hardening/tasks/rhosts.yml +++ b/roles/os_hardening/tasks/rhosts.yml @@ -1,17 +1,17 @@ --- - name: Get user accounts | os-09 - command: "awk -F: '{print $1}' /etc/passwd" + ansible.builtin.command: "awk -F: '{print $1}' /etc/passwd" changed_when: false check_mode: false register: users_accounts - name: Delete rhosts-files from system | os-09 - file: - dest: '~{{ item }}/.rhosts' - state: 'absent' - loop: '{{ users_accounts.stdout_lines | flatten | default([]) }}' + ansible.builtin.file: + dest: ~{{ item }}/.rhosts + state: absent + loop: "{{ users_accounts.stdout_lines | flatten | default([]) }}" - name: Delete hosts.equiv from system | os-01 - file: - dest: '/etc/hosts.equiv' - state: 'absent' + ansible.builtin.file: + dest: /etc/hosts.equiv + state: absent diff --git a/roles/os_hardening/tasks/securetty.yml b/roles/os_hardening/tasks/securetty.yml index 71508619..dafd960d 100644 --- a/roles/os_hardening/tasks/securetty.yml +++ b/roles/os_hardening/tasks/securetty.yml @@ -1,8 +1,8 @@ --- - name: Create securetty - template: - src: 'etc/securetty.j2' - dest: '/etc/securetty' - owner: 'root' - group: 'root' - mode: '0400' + ansible.builtin.template: + src: etc/securetty.j2 + dest: /etc/securetty + owner: root + group: root + mode: "0400" diff --git a/roles/os_hardening/tasks/selinux.yml b/roles/os_hardening/tasks/selinux.yml index b1539d04..fdb66bac 100644 --- a/roles/os_hardening/tasks/selinux.yml +++ b/roles/os_hardening/tasks/selinux.yml @@ -1,5 +1,5 @@ --- - name: Configure selinux | selinux-01 - selinux: + ansible.posix.selinux: policy: "{{ os_selinux_policy }}" - state: "{{ os_selinux_state }}" + state: "{{ os_selinux_state }}" # noqa args - see https://github.com/ansible/ansible-lint/issues/2930 diff --git a/roles/os_hardening/tasks/suid_sgid.yml b/roles/os_hardening/tasks/suid_sgid.yml index 10ef8ab3..b9bbfc86 100644 --- a/roles/os_hardening/tasks/suid_sgid.yml +++ b/roles/os_hardening/tasks/suid_sgid.yml @@ -1,32 +1,32 @@ --- - name: Remove suid/sgid bit from binaries in blacklist | os-06 - file: - path: '{{ item }}' - mode: 'a-s' - state: 'file' - follow: 'yes' + ansible.builtin.file: + path: "{{ item }}" + mode: a-s + state: file + follow: true failed_when: false with_community.general.flattened: - - '{{ os_security_suid_sgid_system_blacklist }}' - - '{{ os_security_suid_sgid_blacklist }}' + - "{{ os_security_suid_sgid_system_blacklist }}" + - "{{ os_security_suid_sgid_blacklist }}" - name: Find binaries with suid/sgid set | os-06 - shell: find / -xdev \( -perm -4000 -o -perm -2000 \) -type f ! -path '/proc/*' -print 2>/dev/null + ansible.builtin.shell: find / -xdev \( -perm -4000 -o -perm -2000 \) -type f ! -path '/proc/*' -print 2>/dev/null register: sbit_binaries when: os_security_suid_sgid_remove_from_unknown | bool changed_when: false - name: Gather files from which to remove suids/sgids and remove system white-listed files | os-06 - set_fact: - suid: '{{ sbit_binaries.stdout_lines | difference(os_security_suid_sgid_system_whitelist) }}' + ansible.builtin.set_fact: + suid: "{{ sbit_binaries.stdout_lines | difference(os_security_suid_sgid_system_whitelist) }}" when: os_security_suid_sgid_remove_from_unknown | bool - name: Remove suid/sgid bit from all binaries except in system and user whitelist | os-06 - file: - path: '{{ item }}' - mode: 'a-s' - state: 'file' - follow: 'yes' + ansible.builtin.file: + path: "{{ item }}" + mode: a-s + state: file + follow: true with_community.general.flattened: - - '{{ suid | default([]) | difference(os_security_suid_sgid_whitelist) }}' + - "{{ suid | default([]) | difference(os_security_suid_sgid_whitelist) }}" when: os_security_suid_sgid_remove_from_unknown | bool diff --git a/roles/os_hardening/tasks/sysctl.yml b/roles/os_hardening/tasks/sysctl.yml index 3b32dc54..d6ad9c1c 100644 --- a/roles/os_hardening/tasks/sysctl.yml +++ b/roles/os_hardening/tasks/sysctl.yml @@ -1,39 +1,39 @@ --- - name: Protect sysctl.conf - file: - path: '/etc/sysctl.conf' - owner: 'root' - group: 'root' - mode: '0440' + ansible.builtin.file: + path: /etc/sysctl.conf + owner: root + group: root + mode: "0440" state: touch modification_time: preserve access_time: preserve - name: Set Daemon umask, do config for rhel-family | NSA 2.2.4.1 - template: - src: 'etc/sysconfig/rhel_sysconfig_init.j2' - dest: '/etc/sysconfig/init' - owner: 'root' - group: 'root' - mode: '0544' + ansible.builtin.template: + src: etc/sysconfig/rhel_sysconfig_init.j2 + dest: /etc/sysconfig/init + owner: root + group: root + mode: "0544" when: ansible_facts.os_family == 'RedHat' - name: Install initramfs-tools - apt: - name: 'initramfs-tools' - state: 'present' + ansible.builtin.apt: + name: initramfs-tools + state: present update_cache: true when: - ansible_facts.os_family == 'Debian' - os_security_kernel_enable_module_loading - name: Rebuild initramfs with starting pack of modules, if module loading at runtime is disabled - template: - src: 'etc/initramfs-tools/modules.j2' - dest: '/etc/initramfs-tools/modules' - owner: 'root' - group: 'root' - mode: '0440' + ansible.builtin.template: + src: etc/initramfs-tools/modules.j2 + dest: /etc/initramfs-tools/modules + owner: root + group: root + mode: "0440" notify: - Update-initramfs when: @@ -45,37 +45,37 @@ when: ansible_virtualization_type not in ['docker', 'lxc', 'openvz'] block: - name: Create a combined sysctl-dict if os-dependent sysctls are defined - set_fact: - sysctl_config: '{{ sysctl_config | combine(sysctl_custom_config) }}' + ansible.builtin.set_fact: + sysctl_config: "{{ sysctl_config | combine(sysctl_custom_config) }}" when: sysctl_custom_config | default() # sysctl_rhel_config is kept for backwards-compatibility. use sysctl_custom_config instead - name: Create a combined sysctl-dict if os-dependent sysctls are defined - set_fact: - sysctl_config: '{{ sysctl_config | combine(sysctl_rhel_config) }}' + ansible.builtin.set_fact: + sysctl_config: "{{ sysctl_config | combine(sysctl_rhel_config) }}" when: sysctl_rhel_config | default() - name: Create a combined sysctl-dict if overwrites are defined - set_fact: - sysctl_config: '{{ sysctl_config | combine(sysctl_overwrite) }}' + ansible.builtin.set_fact: + sysctl_config: "{{ sysctl_config | combine(sysctl_overwrite) }}" when: sysctl_overwrite | default() - name: Change various sysctl-settings, look at the sysctl-vars file for documentation - sysctl: - name: '{{ item.key }}' - value: '{{ item.value }}' + ansible.posix.sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" sysctl_set: true state: present reload: true ignoreerrors: true - with_dict: '{{ sysctl_config }}' + with_dict: "{{ sysctl_config }}" when: item.key not in sysctl_unsupported_entries | default() - name: Apply ufw defaults - template: - src: 'etc/default/ufw.j2' - dest: '/etc/default/ufw' - mode: '0644' + ansible.builtin.template: + src: etc/default/ufw.j2 + dest: /etc/default/ufw + mode: "0644" when: - ufw_manage_defaults - ansible_facts.os_family == 'Debian' diff --git a/roles/os_hardening/tasks/user_accounts.yml b/roles/os_hardening/tasks/user_accounts.yml index 3cdb5ed7..1ea2a717 100644 --- a/roles/os_hardening/tasks/user_accounts.yml +++ b/roles/os_hardening/tasks/user_accounts.yml @@ -1,12 +1,12 @@ --- - name: Read local linux user database - getent: + ansible.builtin.getent: database: passwd # creates a dict for each user containing UID/HOMEDIR etc... when: getent_passwd is undefined # skip this task if "getent" has run before - name: Read local linux shadow database - getent: + ansible.builtin.getent: database: shadow - name: Extract regular (non-system, non-root) accounts from local user database @@ -14,8 +14,8 @@ when: - getent_passwd[item][1]|int >= os_auth_uid_min|int - getent_passwd[item][1]|int <= os_auth_uid_max|int - - item is not in os_always_ignore_users # skip users from "os_always_ignore_users" list (taken from role "vars") - - item is not in os_ignore_users # skip users from "os_ignore_users" list (taken from role "defaults") + - item is not in os_always_ignore_users # skip users from "os_always_ignore_users" list (taken from role "vars") + - item is not in os_ignore_users # skip users from "os_ignore_users" list (taken from role "defaults") set_fact: regular_users: "{{ regular_users | default([]) + [item] }}" @@ -36,11 +36,11 @@ loop: "{{ getent_passwd.keys() | list }}" when: - getent_passwd[item][1]|int == 0 - set_fact: + ansible.builtin.set_fact: root_users: "{{ root_users | default([]) + [item] }}" - name: Set ownership of root user home directory(s) to 0700 - file: + ansible.builtin.file: mode: 0700 owner: "{{ item }}" path: "{{ getent_passwd[item][4] }}" @@ -50,18 +50,18 @@ - os_chmod_rootuser_home_folder | bool - name: Set password ageing for root user(s) - user: + ansible.builtin.user: name: "{{ item }}" password_expire_min: "{{ os_auth_pw_min_age }}" password_expire_max: "{{ os_auth_pw_max_age }}" loop: "{{ root_users }}" - when: + when: - os_rootuser_pw_ageing | bool - getent_shadow[item][0] is not match("\*") # password hashes containing illegal characters like "*" are unusable (locked) and don't need to age - getent_shadow[item][0] is not match("\!") # password hashes containing illegal characters like "!" are unusable (locked) and don't need to age - name: Remove additional users with UID=0 ("root" user is not touched) - user: + ansible.builtin.user: name: "{{ item }}" state: absent loop: "{{ root_users }}" @@ -71,7 +71,7 @@ - item != "root" - name: Get UID_MIN from login.defs - shell: awk '/^\s*UID_MIN\s*([0-9]*).*?$/ {print $2}' /etc/login.defs + ansible.builtin.shell: awk '/^\s*UID_MIN\s*([0-9]*).*?$/ {print $2}' /etc/login.defs args: removes: /etc/login.defs register: uid_min @@ -79,24 +79,24 @@ changed_when: false - name: Calculate UID_MAX from UID_MIN by substracting 1 - set_fact: - uid_max: '{{ uid_min.stdout | int - 1 }}' + ansible.builtin.set_fact: + uid_max: "{{ uid_min.stdout | int - 1 }}" when: uid_min.stdout|int > 0 - name: Set UID_MAX on Debian-systems if no login.defs exist - set_fact: - uid_max: '999' + ansible.builtin.set_fact: + uid_max: "999" when: - ansible_facts.os_family == 'Debian' - uid_max is not defined - name: Set UID_MAX on other systems if no login.defs exist - set_fact: - uid_max: '499' + ansible.builtin.set_fact: + uid_max: "499" when: uid_max is not defined - name: Get all system accounts - command: awk -F'':'' '{ if ( $3 <= {{ uid_max | quote }} ) print $1}' /etc/passwd + ansible.builtin.command: awk -F'':'' '{ if ( $3 <= {{ uid_max | quote }} ) print $1}' /etc/passwd args: removes: /etc/passwd changed_when: false @@ -104,21 +104,21 @@ register: sys_accs - name: Remove always ignored system accounts from list - set_fact: - sys_accs_cond: '{{ sys_accs.stdout_lines | difference(os_always_ignore_users) }}' + ansible.builtin.set_fact: + sys_accs_cond: "{{ sys_accs.stdout_lines | difference(os_always_ignore_users) }}" check_mode: false - name: Change system accounts not on the user provided ignore-list - user: - name: '{{ item }}' - shell: '{{ os_nologin_shell_path }}' - password: '*' + ansible.builtin.user: + name: "{{ item }}" + shell: "{{ os_nologin_shell_path }}" + password: "*" createhome: false with_community.general.flattened: - - '{{ sys_accs_cond | default([]) | difference(os_ignore_users) | list }}' + - "{{ sys_accs_cond | default([]) | difference(os_ignore_users) | list }}" - name: Get all home directories in /home, but skip ignored users - find: + ansible.builtin.find: paths: /home/ recurse: false file_type: directory @@ -127,7 +127,7 @@ when: os_chmod_home_folders | bool - name: Set ownership of /home directories to 0700 - file: + ansible.builtin.file: mode: 0700 path: "{{ item.path }}" state: directory diff --git a/roles/os_hardening/tasks/yum.yml b/roles/os_hardening/tasks/yum.yml index d4f69c0b..14692753 100644 --- a/roles/os_hardening/tasks/yum.yml +++ b/roles/os_hardening/tasks/yum.yml @@ -1,50 +1,51 @@ --- - name: Remove unused repositories - file: - name: '/etc/yum.repos.d/{{ item }}.repo' - state: 'absent' + ansible.builtin.file: + name: /etc/yum.repos.d/{{ item }}.repo + state: absent loop: - - 'CentOS-Debuginfo' - - 'CentOS-Media' - - 'CentOS-Vault' + - CentOS-Debuginfo + - CentOS-Media + - CentOS-Vault when: os_security_packages_clean | bool - name: Get yum repository files - find: - paths: '/etc/yum.repos.d' - patterns: '*.repo' + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" register: yum_repos # for the 'default([])' see here: # https://github.com/dev-sec/ansible-os-hardening/issues/99 and # https://stackoverflow.com/questions/37067827/ansible-deprecation-warning-for-undefined-variable-despite-when-clause - name: Activate gpg-check for yum repository files - replace: - path: '{{ item }}' - regexp: '^\s*gpgcheck.*' - replace: 'gpgcheck=1' - mode: '0644' + ansible.builtin.replace: + path: "{{ item }}" + regexp: ^\s*gpgcheck.* + replace: gpgcheck=1 + mode: "0644" with_items: + # yamllint disable-line rule:line-length - "{{ yum_repos.files | default([]) | map(attribute='path') | difference(os_yum_repo_file_whitelist | map('regex_replace', '^', '/etc/yum.repos.d/') | list) }}" # failed_when is needed because by default replace module will fail if the file doesn't exists. # status.rc is only defined if an error accrued and only error code (rc) 257 will be ignored. # All other errors will still be raised. - name: Activate gpg-check for config files - replace: - path: '{{ item }}' - regexp: '^\s*gpgcheck\W.*' - replace: 'gpgcheck=1' - mode: '0644' + ansible.builtin.replace: + path: "{{ item }}" + regexp: ^\s*gpgcheck\W.* + replace: gpgcheck=1 + mode: "0644" register: status failed_when: status.rc is defined and status.rc not in (257, 0) loop: - - '/etc/yum.conf' - - '/etc/dnf/dnf.conf' - - '/etc/yum/pluginconf.d/rhnplugin.conf' + - /etc/yum.conf + - /etc/dnf/dnf.conf + - /etc/yum/pluginconf.d/rhnplugin.conf - name: Remove deprecated or insecure packages | package-01 - package-09 - yum: - name: '{{ os_security_packages_list }}' - state: 'absent' + ansible.builtin.yum: + name: "{{ os_security_packages_list }}" + state: absent when: os_security_packages_clean | bool diff --git a/roles/os_hardening/vars/Amazon.yml b/roles/os_hardening/vars/Amazon.yml index 6a21a380..1a87de61 100644 --- a/roles/os_hardening/vars/Amazon.yml +++ b/roles/os_hardening/vars/Amazon.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'pam_ccreds' -os_nologin_shell_path: '/sbin/nologin' +os_packages_pam_ccreds: pam_ccreds +os_nologin_shell_path: /sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/sbin/nologin' os_shadow_perms: owner: root group: root - mode: '0000' + mode: "0000" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '077' +os_env_umask: "077" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -79,10 +78,9 @@ os_mnt_var_tmp_owner: 'root' os_useradd_mail_dir: /var/spool/mail os_useradd_create_home: true -modprobe_package: 'module-init-tools' -auditd_package: 'audit' +modprobe_package: module-init-tools +auditd_package: audit # system accounts that do not get their login disabled and pasword changed -os_always_ignore_users: ['root', 'sync', 'shutdown', 'halt', 'ec2-user'] - -hidepid_option: '2' # allowed values: 0, 1, 2 +os_always_ignore_users: [root, sync, shutdown, halt, ec2-user] +hidepid_option: "2" # allowed values: 0, 1, 2 diff --git a/roles/os_hardening/vars/Archlinux.yml b/roles/os_hardening/vars/Archlinux.yml index bc559006..45fbe452 100644 --- a/roles/os_hardening/vars/Archlinux.yml +++ b/roles/os_hardening/vars/Archlinux.yml @@ -1,18 +1,17 @@ --- - -os_nologin_shell_path: '/sbin/nologin' +os_nologin_shell_path: /sbin/nologin os_shadow_perms: owner: root group: root - mode: '0600' + mode: "0600" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '027' +os_env_umask: "027" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -69,10 +68,10 @@ os_mnt_var_tmp_dir_mode: '1777' os_mnt_var_tmp_group: 'root' os_mnt_var_tmp_owner: 'root' -modprobe_package: 'kmod' -auditd_package: 'audit' +modprobe_package: kmod +auditd_package: audit -hidepid_option: '2' # allowed values: 0, 1, 2 +hidepid_option: "2" # allowed values: 0, 1, 2 sysctl_custom_config: # Mitigation of vulnerability CVE-2021-33909 diff --git a/roles/os_hardening/vars/Debian.yml b/roles/os_hardening/vars/Debian.yml index dc0e09a1..d67cb794 100644 --- a/roles/os_hardening/vars/Debian.yml +++ b/roles/os_hardening/vars/Debian.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'libpam-ccreds' -os_nologin_shell_path: '/usr/sbin/nologin' +os_packages_pam_ccreds: libpam-ccreds +os_nologin_shell_path: /usr/sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/usr/sbin/nologin' os_shadow_perms: owner: root group: shadow - mode: '0640' + mode: "0640" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '027' +os_env_umask: "027" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -76,13 +75,13 @@ os_mnt_var_tmp_owner: 'root' # defaults for useradd os_useradd_mail_dir: /var/mail -modprobe_package: 'kmod' -auditd_package: 'auditd' +modprobe_package: kmod +auditd_package: auditd -tally2_path: '/usr/share/pam-configs/tally2' -passwdqc_path: '/usr/share/pam-configs/passwdqc' +tally2_path: /usr/share/pam-configs/tally2 +passwdqc_path: /usr/share/pam-configs/passwdqc -hidepid_option: '2' # allowed values: 0, 1, 2 +hidepid_option: "2" # allowed values: 0, 1, 2 sysctl_custom_config: # Mitigation of vulnerability CVE-2021-33909 diff --git a/roles/os_hardening/vars/Fedora.yml b/roles/os_hardening/vars/Fedora.yml index 5110bda2..7bc33082 100644 --- a/roles/os_hardening/vars/Fedora.yml +++ b/roles/os_hardening/vars/Fedora.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'pam_ccreds' -os_nologin_shell_path: '/sbin/nologin' +os_packages_pam_ccreds: pam_ccreds +os_nologin_shell_path: /sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/sbin/nologin' os_shadow_perms: owner: root group: root - mode: '0000' + mode: "0000" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '027' +os_env_umask: "027" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -79,7 +78,7 @@ os_mnt_var_tmp_owner: 'root' os_useradd_mail_dir: /var/spool/mail os_useradd_create_home: true -modprobe_package: 'module-init-tools' -auditd_package: 'audit' +modprobe_package: module-init-tools +auditd_package: audit -hidepid_option: '2' # allowed values: 0, 1, 2 +hidepid_option: "2" # allowed values: 0, 1, 2 diff --git a/roles/os_hardening/vars/RedHat.yml b/roles/os_hardening/vars/RedHat.yml index 0f422d4f..1dfa56ef 100644 --- a/roles/os_hardening/vars/RedHat.yml +++ b/roles/os_hardening/vars/RedHat.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'pam_ccreds' -os_nologin_shell_path: '/sbin/nologin' +os_packages_pam_ccreds: pam_ccreds +os_nologin_shell_path: /sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/sbin/nologin' os_shadow_perms: owner: root group: root - mode: '0000' + mode: "0000" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '077' +os_env_umask: "077" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -79,7 +78,7 @@ os_mnt_var_tmp_owner: 'root' os_useradd_mail_dir: /var/spool/mail os_useradd_create_home: true -modprobe_package: 'module-init-tools' -auditd_package: 'audit' +modprobe_package: module-init-tools +auditd_package: audit -hidepid_option: '2' # allowed values: 0, 1, 2 +hidepid_option: "2" # allowed values: 0, 1, 2 diff --git a/roles/os_hardening/vars/RedHat_7.yml b/roles/os_hardening/vars/RedHat_7.yml index 343c46e4..c2402016 100644 --- a/roles/os_hardening/vars/RedHat_7.yml +++ b/roles/os_hardening/vars/RedHat_7.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'pam_ccreds' -os_nologin_shell_path: '/sbin/nologin' +os_packages_pam_ccreds: pam_ccreds +os_nologin_shell_path: /sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/sbin/nologin' os_shadow_perms: owner: root group: root - mode: '0000' + mode: "0000" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '077' +os_env_umask: "077" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -79,11 +78,11 @@ os_mnt_var_tmp_owner: 'root' os_useradd_mail_dir: /var/spool/mail os_useradd_create_home: true -modprobe_package: 'module-init-tools' -auditd_package: 'audit' +modprobe_package: module-init-tools +auditd_package: audit -hidepid_option: '0' # allowed values: 0, 1, 2 +hidepid_option: "0" # allowed values: 0, 1, 2 sysctl_unsupported_entries: - - 'fs.protected_fifos' - - 'fs.protected_regular' + - fs.protected_fifos + - fs.protected_regular diff --git a/roles/os_hardening/vars/Suse.yml b/roles/os_hardening/vars/Suse.yml index 41b57298..10e50f75 100644 --- a/roles/os_hardening/vars/Suse.yml +++ b/roles/os_hardening/vars/Suse.yml @@ -1,7 +1,6 @@ --- - -os_packages_pam_ccreds: 'pam_ccreds' -os_nologin_shell_path: '/sbin/nologin' +os_packages_pam_ccreds: pam_ccreds +os_nologin_shell_path: /sbin/nologin # Different distros use different standards for /etc/shadow perms, e.g. # RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. @@ -9,14 +8,14 @@ os_nologin_shell_path: '/sbin/nologin' os_shadow_perms: owner: root group: shadow - mode: '0640' + mode: "0640" os_passwd_perms: owner: root group: root - mode: '0644' + mode: "0644" -os_env_umask: '027' +os_env_umask: "027" os_auth_uid_min: 1000 os_auth_uid_max: 60000 @@ -76,7 +75,7 @@ os_mnt_var_tmp_owner: 'root' # defaults for useradd os_useradd_create_home: false -modprobe_package: 'kmod-compat' -auditd_package: 'audit' +modprobe_package: kmod-compat +auditd_package: audit -hidepid_option: '2' # allowed values: 0, 1, 2 +hidepid_option: "2" # allowed values: 0, 1, 2 diff --git a/roles/os_hardening/vars/main.yml b/roles/os_hardening/vars/main.yml index beeaba14..3aa29725 100644 --- a/roles/os_hardening/vars/main.yml +++ b/roles/os_hardening/vars/main.yml @@ -11,102 +11,102 @@ # list of suid/sgid entries that must be removed os_security_suid_sgid_system_blacklist: # blacklist as provided by NSA - - '/usr/bin/rcp' - - '/usr/bin/rlogin' - - '/usr/bin/rsh' + - /usr/bin/rcp + - /usr/bin/rlogin + - /usr/bin/rsh # sshd must not use host-based authentication (see ssh cookbook) - - '/usr/libexec/openssh/ssh-keysign' - - '/usr/lib/openssh/ssh-keysign' + - /usr/libexec/openssh/ssh-keysign + - /usr/lib/openssh/ssh-keysign # misc others - - '/sbin/netreport' # not normally required for user - - '/usr/sbin/usernetctl' # modify interfaces via functional accounts + - /sbin/netreport # not normally required for user + - /usr/sbin/usernetctl # modify interfaces via functional accounts # connecting to ... - - '/usr/sbin/userisdnctl' # no isdn... - - '/usr/sbin/pppd' # no ppp / dsl ... + - /usr/sbin/userisdnctl # no isdn... + - /usr/sbin/pppd # no ppp / dsl ... # lockfile - - '/usr/bin/lockfile' - - '/usr/bin/mail-lock' - - '/usr/bin/mail-unlock' - - '/usr/bin/mail-touchlock' - - '/usr/bin/dotlockfile' + - /usr/bin/lockfile + - /usr/bin/mail-lock + - /usr/bin/mail-unlock + - /usr/bin/mail-touchlock + - /usr/bin/dotlockfile # need more investigation blacklist for now - - '/usr/bin/arping' - - '/usr/sbin/uuidd' - - '/usr/bin/mtr' # investigate current state... - - '/usr/lib/evolution/camel-lock-helper-1.2' # investigate current state... - - '/usr/lib/pt_chown' # pseudo-tty needed? - - '/usr/lib/eject/dmcrypt-get-device' - - '/usr/lib/mc/cons.saver' # midnight commander screensaver + - /usr/bin/arping + - /usr/sbin/uuidd + - /usr/bin/mtr # investigate current state... + - /usr/lib/evolution/camel-lock-helper-1.2 # investigate current state... + - /usr/lib/pt_chown # pseudo-tty needed? + - /usr/lib/eject/dmcrypt-get-device + - /usr/lib/mc/cons.saver # midnight commander screensaver # list of suid/sgid entries that can remain untouched os_security_suid_sgid_system_whitelist: # whitelist as provided by NSA - - '/bin/mount' - - '/bin/ping' - - '/bin/su' - - '/usr/bin/su' - - '/bin/umount' - - '/sbin/pam_timestamp_check' - - '/sbin/unix_chkpwd' - - '/usr/bin/at' - - '/usr/bin/gpasswd' - - '/usr/bin/locate' - - '/usr/bin/newgrp' - - '/usr/bin/passwd' - - '/usr/bin/ssh-agent' - - '/usr/libexec/utempter/utempter' - - '/usr/sbin/lockdev' - - '/usr/sbin/sendmail.sendmail' - - '/usr/bin/expiry' + - /bin/mount + - /bin/ping + - /bin/su + - /usr/bin/su + - /bin/umount + - /sbin/pam_timestamp_check + - /sbin/unix_chkpwd + - /usr/bin/at + - /usr/bin/gpasswd + - /usr/bin/locate + - /usr/bin/newgrp + - /usr/bin/passwd + - /usr/bin/ssh-agent + - /usr/libexec/utempter/utempter + - /usr/sbin/lockdev + - /usr/sbin/sendmail.sendmail + - /usr/bin/expiry # whitelist ipv6 - - '/bin/ping6' - - '/usr/bin/traceroute6.iputils' + - /bin/ping6 + - /usr/bin/traceroute6.iputils # whitelist nfs - - '/sbin/mount.nfs' - - '/sbin/umount.nfs' + - /sbin/mount.nfs + - /sbin/umount.nfs # whitelist nfs4 - - '/sbin/mount.nfs4' - - '/sbin/umount.nfs4' + - /sbin/mount.nfs4 + - /sbin/umount.nfs4 # whitelist cron - - '/usr/bin/crontab' + - /usr/bin/crontab # whitelist consolemssaging - - '/usr/bin/wall' - - '/usr/bin/write' + - /usr/bin/wall + - /usr/bin/write # whitelist: only SGID with utmp group for multi-session access # impact is limited; installation/usage has some remaining risk - - '/usr/bin/screen' + - /usr/bin/screen # whitelist locate - - '/usr/bin/mlocate' + - /usr/bin/mlocate # whitelist usermanagement - - '/usr/bin/chage' - - '/usr/bin/chfn' - - '/usr/bin/chsh' + - /usr/bin/chage + - /usr/bin/chfn + - /usr/bin/chsh # whitelist fuse - - '/bin/fusermount' + - /bin/fusermount # whitelist pkexec - - '/usr/bin/pkexec' + - /usr/bin/pkexec # whitelist sudo - - '/usr/bin/sudo' - - '/usr/bin/sudoedit' + - /usr/bin/sudo + - /usr/bin/sudoedit # whitelist postfix - - '/usr/sbin/postdrop' - - '/usr/sbin/postqueue' + - /usr/sbin/postdrop + - /usr/sbin/postqueue # whitelist apache - - '/usr/sbin/suexec' + - /usr/sbin/suexec # whitelist squid - - '/usr/lib/squid/ncsa_auth' - - '/usr/lib/squid/pam_auth' + - /usr/lib/squid/ncsa_auth + - /usr/lib/squid/pam_auth # whitelist kerberos - - '/usr/kerberos/bin/ksu' + - /usr/kerberos/bin/ksu # whitelist pam_caching - - '/usr/sbin/ccreds_validate' + - /usr/sbin/ccreds_validate # whitelist Xorg - - '/usr/bin/Xorg' # xorg - - '/usr/bin/X' # xorg - - '/usr/lib/dbus-1.0/dbus-daemon-launch-helper' # freedesktop ipc - - '/usr/lib/vte/gnome-pty-helper' # gnome - - '/usr/lib/libvte9/gnome-pty-helper' # gnome - - '/usr/lib/libvte-2.90-9/gnome-pty-helper' # gnome + - /usr/bin/Xorg # xorg + - /usr/bin/X # xorg + - /usr/lib/dbus-1.0/dbus-daemon-launch-helper # freedesktop ipc + - /usr/lib/vte/gnome-pty-helper # gnome + - /usr/lib/libvte9/gnome-pty-helper # gnome + - /usr/lib/libvte-2.90-9/gnome-pty-helper # gnome # system accounts that do not get their login disabled and pasword changed -os_always_ignore_users: ['root', 'sync', 'shutdown', 'halt'] +os_always_ignore_users: [root, sync, shutdown, halt] diff --git a/roles/ssh_hardening/defaults/main.yml b/roles/ssh_hardening/defaults/main.yml index 0676ef15..8870628d 100644 --- a/roles/ssh_hardening/defaults/main.yml +++ b/roles/ssh_hardening/defaults/main.yml @@ -1,64 +1,68 @@ --- # true if IPv6 is needed -network_ipv6_enable: true # sshd + ssh +network_ipv6_enable: true # sshd + ssh # Paths of the config files -ssh_client_config_file: /etc/ssh/ssh_config # ssh -ssh_server_config_file: /etc/ssh/sshd_config # sshd +ssh_client_config_file: /etc/ssh/ssh_config # ssh +ssh_server_config_file: /etc/ssh/sshd_config # sshd # true if sshd should be started and enabled -ssh_server_enabled: true # sshd +ssh_server_enabled: true # sshd -# true if DNS resolutions are needed, look up the remote host name, defaults to false from 6.8, see: http://www.openssh.com/txt/release-6.8 -ssh_use_dns: false # sshd +# true if DNS resolutions are needed, look up the remote host name, +# defaults to false from 6.8, see: http://www.openssh.com/txt/release-6.8 +ssh_use_dns: false # sshd # true or value if compression is needed -ssh_client_compression: false # ssh -ssh_compression: false # sshd +ssh_client_compression: false # ssh +ssh_compression: false # sshd -# For which components (client and server) to generate the configuration for. Can be useful when running against a client without an SSH server. -ssh_client_hardening: true # ssh -ssh_server_hardening: true # sshd +# For which components (client and server) to generate the configuration for. +# Can be useful when running against a client without an SSH server. +ssh_client_hardening: true # ssh +ssh_server_hardening: true # sshd # If true, password login is allowed -ssh_client_password_login: false # ssh -ssh_server_password_login: false # sshd +ssh_client_password_login: false # ssh +ssh_server_password_login: false # sshd # ports on which ssh-server should listen -ssh_server_ports: ['22'] # sshd +ssh_server_ports: ["22"] # sshd # port to which ssh-client should connect -ssh_client_port: '22' # ssh +ssh_client_port: "22" # ssh -# one or more ip addresses, to which ssh-server should listen to. Default is empty, but should be configured for security reasons! -ssh_listen_to: ['0.0.0.0'] # sshd +# one or more ip addresses, to which ssh-server should listen to. +# Default is empty, but should be configured for security reasons! +ssh_listen_to: [0.0.0.0] # sshd # Host keys to look for when starting sshd. -ssh_host_key_files: [] # sshd +ssh_host_key_files: [] # sshd # Host RSA key size in bits -ssh_host_rsa_key_size: 4096 # sshd +ssh_host_rsa_key_size: 4096 # sshd # Host certificates to look for when starting sshd. -ssh_host_certificates: [] # sshd +ssh_host_certificates: [] # sshd # Specifies the host key algorithms that the server offers -ssh_host_key_algorithms: [] # sshd +ssh_host_key_algorithms: [] # sshd # Specifies the host key algorithms order the client will try -ssh_client_host_key_algorithms: [] # ssh +ssh_client_host_key_algorithms: [] # ssh # specifies the time allowed for successful authentication to the SSH server ssh_login_grace_time: 30s -# Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. +# Specifies the maximum number of authentication attempts permitted per connection. +# Once the number of failures reaches half this value, additional failures are logged. ssh_max_auth_retries: 2 # Specifies the maximum number of open sessions permitted from a given connection ssh_max_sessions: 10 -ssh_client_alive_interval: 300 # sshd -ssh_client_alive_count: 3 # sshd +ssh_client_alive_interval: 300 # sshd +ssh_client_alive_count: 3 # sshd # Allow SSH Tunnels ssh_permit_tunnel: false @@ -71,28 +75,29 @@ ssh_permit_tunnel: false # - names: ['example3.com'] # options: ['StrictHostKeyChecking no'] ssh_remote_hosts: [] - # Set this to "without-password" or "yes" to allow root to login -ssh_permit_root_login: 'no' # sshd +ssh_permit_root_login: "no" # sshd -# false to disable TCP Forwarding. Set to 'yes', 'no', 'local', 'all' or 'remote' to allow TCP Forwarding. -ssh_allow_tcp_forwarding: 'no' # sshd +# false to disable TCP Forwarding. Set to 'yes', 'no', 'local', 'all' or 'remote' +# to allow TCP Forwarding. +ssh_allow_tcp_forwarding: "no" # sshd -# false to disable binding forwarded ports to non-loopback addresses. Set to true to force binding on wildcard address. +# false to disable binding forwarded ports to non-loopback addresses. +# Set to true to force binding on wildcard address. # Set to 'clientspecified' to allow the client to specify which address to bind to. -ssh_gateway_ports: false # sshd +ssh_gateway_ports: false # sshd # false to disable Agent Forwarding. Set to true to allow Agent Forwarding. -ssh_allow_agent_forwarding: false # sshd +ssh_allow_agent_forwarding: false # sshd # false to disable X11 Forwarding. Set to true to allow X11 Forwarding. -ssh_x11_forwarding: false # sshd +ssh_x11_forwarding: false # sshd # false to disable pam authentication. -ssh_use_pam: true # sshd +ssh_use_pam: true # sshd # specify AuthenticationMethods -sshd_authenticationmethods: 'publickey' +sshd_authenticationmethods: publickey # Set to true to enable GSSAPI authentication (both client and server) ssh_gssapi_support: false @@ -101,29 +106,29 @@ ssh_gssapi_support: false ssh_gssapi_delegation: false # if specified, login is disallowed for user names that match one of the patterns. -ssh_deny_users: '' # sshd +ssh_deny_users: "" # sshd # if specified, login is allowed only for user names that match one of the patterns. -ssh_allow_users: '' # sshd +ssh_allow_users: "" # sshd # if specified, login is disallowed for users whose primary group or supplementary group list matches one of the patterns. -ssh_deny_groups: '' # sshd +ssh_deny_groups: "" # sshd # if specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. -ssh_allow_groups: '' # sshd +ssh_allow_groups: "" # sshd # change default file that contains the public keys that can be used for user authentication. -ssh_authorized_keys_file: '' # sshd +ssh_authorized_keys_file: "" # sshd # specifies the file containing trusted certificate authorities public keys used to sign user certificates. -ssh_trusted_user_ca_keys_file: '' # sshd +ssh_trusted_user_ca_keys_file: "" # sshd # set the trusted certificate authorities public keys used to sign user certificates. # Example: # ssh_trusted_user_ca_keys: # - 'ssh-rsa ... comment1' # - 'ssh-rsa ... comment2' -ssh_trusted_user_ca_keys: [] # sshd +ssh_trusted_user_ca_keys: [] # sshd # specifies the file containing principals that are allowed. Only used if ssh_trusted_user_ca_keys_file is set. # Example: @@ -133,30 +138,31 @@ ssh_trusted_user_ca_keys: [] # sshd # replaced by the username of that user. After expansion, the path is taken to be # an absolute path or one relative to the user's home directory. # -ssh_authorized_principals_file: '' # sshd +ssh_authorized_principals_file: "" # sshd # list of hashes containing file paths and authorized principals. Only used if ssh_authorized_principals_file is set. # Example: # ssh_authorized_principals: -# - { path: '/etc/ssh/auth_principals/root', principals: [ 'root' ], owner: "{{ ssh_owner }}", group: "{{ ssh_group }}", directoryowner: "{{ ssh_owner }}", directorygroup: "{{ ssh_group}}" } +# - { path: '/etc/ssh/auth_principals/root', principals: [ 'root' ], owner: "{{ ssh_owner }}", +# group: "{{ ssh_group }}", directoryowner: "{{ ssh_owner }}", directorygroup: "{{ ssh_group}}" } # - { path: '/etc/ssh/auth_principals/myuser', principals: [ 'masteradmin', 'webserver' ] } -ssh_authorized_principals: [] # sshd +ssh_authorized_principals: [] # sshd # false to disable printing of the MOTD -ssh_print_motd: false # sshd -ssh_print_pam_motd: false # sshd +ssh_print_motd: false # sshd +ssh_print_pam_motd: false # sshd # false to disable display of last login information -ssh_print_last_log: false # sshd +ssh_print_last_log: false # sshd # false to disable serving ssh warning banner before authentication is allowed -ssh_banner: false # sshd +ssh_banner: false # sshd # path to file with ssh warning banner -ssh_banner_path: '/etc/ssh/banner.txt' +ssh_banner_path: /etc/ssh/banner.txt # false to disable distribution version leakage during initial protocol handshake -ssh_print_debian_banner: false # sshd (Debian OS family only) +ssh_print_debian_banner: false # sshd (Debian OS family only) # false to disable sftp configuration sftp_enabled: true @@ -165,7 +171,7 @@ sftp_enabled: true sftp_chroot: true # sftp default umask -sftp_umask: '0027' +sftp_umask: "0027" # change default sftp chroot location sftp_chroot_dir: /home/%u @@ -174,31 +180,30 @@ sftp_chroot_dir: /home/%u ssh_client_roaming: false # list of hashes (containing user and rules) to generate Match User blocks for -ssh_server_match_user: false # sshd +ssh_server_match_user: false # sshd # list of hashes (containing group and rules) to generate Match Group blocks for -ssh_server_match_group: false # sshd +ssh_server_match_group: false # sshd # list of hashes (containing addresses/subnets and rules) to generate Match Address blocks for -ssh_server_match_address: false # sshd +ssh_server_match_address: false # sshd # list of hashes (containing port and rules) to generate Match LocalPort blocks for -ssh_server_match_local_port: false # sshd +ssh_server_match_local_port: false # sshd -ssh_server_permit_environment_vars: 'no' -ssh_server_accept_env_vars: '' +ssh_server_permit_environment_vars: "no" +ssh_server_accept_env_vars: "" # maximum number of concurrent unauthenticated connections to the SSH daemon -ssh_max_startups: '10:30:60' # sshd +ssh_max_startups: 10:30:60 # sshd -ssh_ps59: 'sandbox' +ssh_ps59: sandbox ssh_macs: [] ssh_ciphers: [] ssh_kex: [] - # directory where to store ssh_password policy -ssh_custom_selinux_dir: '/etc/selinux/local-policies' +ssh_custom_selinux_dir: /etc/selinux/local-policies sshd_moduli_minimum: 2048 @@ -207,19 +212,16 @@ ssh_challengeresponseauthentication: false # a list of public keys that are never accepted by the ssh server ssh_server_revoked_keys: [] - # Set to false to turn the role into a no-op. Useful when using # the Ansible role dependency mechanism. ssh_hardening_enabled: true # Custom options for SSH client configuration file ssh_custom_options: [] - # Custom options for SSH daemon configuration file sshd_custom_options: [] - # Logging -sshd_syslog_facility: 'AUTH' -sshd_log_level: 'VERBOSE' +sshd_syslog_facility: AUTH +sshd_log_level: VERBOSE sshd_strict_modes: true diff --git a/roles/ssh_hardening/handlers/main.yml b/roles/ssh_hardening/handlers/main.yml index 43b7b4ba..4a2976e6 100644 --- a/roles/ssh_hardening/handlers/main.yml +++ b/roles/ssh_hardening/handlers/main.yml @@ -1,7 +1,7 @@ --- - name: Restart sshd - service: - name: '{{ sshd_service_name }}' + ansible.builtin.service: + name: "{{ sshd_service_name }}" state: restarted when: ssh_server_enabled | bool become: true diff --git a/roles/ssh_hardening/meta/main.yml b/roles/ssh_hardening/meta/main.yml index 590897ab..308450c8 100644 --- a/roles/ssh_hardening/meta/main.yml +++ b/roles/ssh_hardening/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: - author: "Sebastian Gumprich" - description: 'This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.' + author: Sebastian Gumprich + description: This Ansible role provides numerous security-related ssh configurations, providing all-round base protection. company: Hardening Framework Team license: Apache License 2.0 - min_ansible_version: '2.9.10' + min_ansible_version: 2.9.10 platforms: - name: EL versions: diff --git a/roles/ssh_hardening/tasks/ca_keys_and_principals.yml b/roles/ssh_hardening/tasks/ca_keys_and_principals.yml index a3c45192..e4822cb5 100644 --- a/roles/ssh_hardening/tasks/ca_keys_and_principals.yml +++ b/roles/ssh_hardening/tasks/ca_keys_and_principals.yml @@ -1,27 +1,27 @@ --- - name: Set ssh CA pub keys - template: - src: 'trusted_user_ca_keys.j2' - dest: '{{ ssh_trusted_user_ca_keys_file }}' - mode: '0644' - owner: '{{ ssh_owner }}' - group: '{{ ssh_group }}' + ansible.builtin.template: + src: trusted_user_ca_keys.j2 + dest: "{{ ssh_trusted_user_ca_keys_file }}" + mode: "0644" + owner: "{{ ssh_owner }}" + group: "{{ ssh_group }}" notify: Restart sshd - name: Create ssh authorized principals directories - file: - path: '{{ item.path | dirname }}' + ansible.builtin.file: + path: "{{ item.path | dirname }}" mode: '{{ item.directorymode | default("700") }}' - owner: '{{ item.directoryowner | default(ssh_owner) }}' - group: '{{ item.directorygroup | default(ssh_group) }}' + owner: "{{ item.directoryowner | default(ssh_owner) }}" + group: "{{ item.directorygroup | default(ssh_group) }}" state: directory - loop: '{{ ssh_authorized_principals }}' + loop: "{{ ssh_authorized_principals }}" - name: Set ssh authorized principals - template: - src: 'authorized_principals.j2' - dest: '{{ item.path }}' + ansible.builtin.template: + src: authorized_principals.j2 + dest: "{{ item.path }}" mode: '{{ item.filemode | default("600") }}' - owner: '{{ item.owner | default(ssh_owner) }}' - group: '{{ item.group | default(ssh_group) }}' - loop: '{{ ssh_authorized_principals }}' + owner: "{{ item.owner | default(ssh_owner) }}" + group: "{{ item.group | default(ssh_group) }}" + loop: "{{ ssh_authorized_principals }}" diff --git a/roles/ssh_hardening/tasks/crypto_ciphers.yml b/roles/ssh_hardening/tasks/crypto_ciphers.yml index 1d674d3d..baa6d9df 100644 --- a/roles/ssh_hardening/tasks/crypto_ciphers.yml +++ b/roles/ssh_hardening/tasks/crypto_ciphers.yml @@ -1,10 +1,10 @@ --- - name: Set ciphers according to openssh-version if openssh >= 5.3 - set_fact: - ssh_ciphers: '{{ ssh_ciphers_53_default }}' + ansible.builtin.set_fact: + ssh_ciphers: "{{ ssh_ciphers_53_default }}" when: sshd_version is version('5.3', '>=') - name: Set ciphers according to openssh-version if openssh >= 6.6 - set_fact: - ssh_ciphers: '{{ ssh_ciphers_66_default }}' + ansible.builtin.set_fact: + ssh_ciphers: "{{ ssh_ciphers_66_default }}" when: sshd_version is version('6.6', '>=') diff --git a/roles/ssh_hardening/tasks/crypto_hostkeys.yml b/roles/ssh_hardening/tasks/crypto_hostkeys.yml index 4d7b4d56..8b242782 100644 --- a/roles/ssh_hardening/tasks/crypto_hostkeys.yml +++ b/roles/ssh_hardening/tasks/crypto_hostkeys.yml @@ -11,28 +11,28 @@ # In RHEL and Fedora, the 'ssh_keys' group is the group owner of the host private SSH keys. # Since the openssh_keypair module needs to read the key to provide idempotency, we need to set ownership and group based on specific OS vars. - name: Change host private key ownership, group and permissions - file: + ansible.builtin.file: path: "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" owner: "{{ ssh_host_keys_owner }}" group: "{{ ssh_host_keys_group }}" mode: "0640" - when: "ansible_facts.os_family == 'RedHat'" + when: ansible_facts.os_family == 'RedHat' - name: Set hostkeys according to openssh-version if openssh >= 5.3 - set_fact: + ansible.builtin.set_fact: ssh_host_key_files: - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" when: sshd_version is version('5.3', '>=') - name: Set hostkeys according to openssh-version if openssh >= 6.0 - set_fact: + ansible.builtin.set_fact: ssh_host_key_files: - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key" when: sshd_version is version('6.0', '>=') - name: Set hostkeys according to openssh-version if openssh >= 6.3 - set_fact: + ansible.builtin.set_fact: ssh_host_key_files: - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key" diff --git a/roles/ssh_hardening/tasks/crypto_kex.yml b/roles/ssh_hardening/tasks/crypto_kex.yml index 1161d611..a37efd85 100644 --- a/roles/ssh_hardening/tasks/crypto_kex.yml +++ b/roles/ssh_hardening/tasks/crypto_kex.yml @@ -1,20 +1,20 @@ --- - name: Set kex according to openssh-version if openssh >= 5.9 - set_fact: - ssh_kex: '{{ ssh_kex_59_default }}' + ansible.builtin.set_fact: + ssh_kex: "{{ ssh_kex_59_default }}" when: sshd_version is version('5.9', '>=') - name: Set kex according to openssh-version if openssh >= 6.6 - set_fact: - ssh_kex: '{{ ssh_kex_66_default }}' + ansible.builtin.set_fact: + ssh_kex: "{{ ssh_kex_66_default }}" when: sshd_version is version('6.6', '>=') - name: Set kex according to openssh-version if openssh >= 8.0 - set_fact: - ssh_kex: '{{ ssh_kex_80_default }}' + ansible.builtin.set_fact: + ssh_kex: "{{ ssh_kex_80_default }}" when: sshd_version is version('8.0', '>=') - name: Set kex according to openssh-version if openssh >= 8.5 - set_fact: - ssh_kex: '{{ ssh_kex_85_default }}' + ansible.builtin.set_fact: + ssh_kex: "{{ ssh_kex_85_default }}" when: sshd_version is version('8.5', '>=') diff --git a/roles/ssh_hardening/tasks/crypto_macs.yml b/roles/ssh_hardening/tasks/crypto_macs.yml index 31330ce0..9bfaf11a 100644 --- a/roles/ssh_hardening/tasks/crypto_macs.yml +++ b/roles/ssh_hardening/tasks/crypto_macs.yml @@ -1,20 +1,20 @@ --- - name: Set macs according to openssh-version if openssh >= 5.3 - set_fact: - ssh_macs: '{{ ssh_macs_53_default }}' + ansible.builtin.set_fact: + ssh_macs: "{{ ssh_macs_53_default }}" when: sshd_version is version('5.3', '>=') - name: Set macs according to openssh-version if openssh >= 5.9 - set_fact: - ssh_macs: '{{ ssh_macs_59_default }}' + ansible.builtin.set_fact: + ssh_macs: "{{ ssh_macs_59_default }}" when: sshd_version is version('5.9', '>=') - name: Set macs according to openssh-version if openssh >= 6.6 - set_fact: - ssh_macs: '{{ ssh_macs_66_default }}' + ansible.builtin.set_fact: + ssh_macs: "{{ ssh_macs_66_default }}" when: sshd_version is version('6.6', '>=') - name: Set macs according to openssh-version if openssh >= 7.6 - set_fact: - ssh_macs: '{{ ssh_macs_76_default }}' + ansible.builtin.set_fact: + ssh_macs: "{{ ssh_macs_76_default }}" when: sshd_version is version('7.6', '>=') diff --git a/roles/ssh_hardening/tasks/hardening.yml b/roles/ssh_hardening/tasks/hardening.yml index 75164698..4fa4d6af 100644 --- a/roles/ssh_hardening/tasks/hardening.yml +++ b/roles/ssh_hardening/tasks/hardening.yml @@ -1,78 +1,78 @@ --- - name: Fetch OS dependent variables - include_vars: - file: '{{ item }}' - name: 'os_vars' + ansible.builtin.include_vars: + file: "{{ item }}" + name: os_vars with_first_found: - files: - - '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version | default() }}.yml' - - '{{ ansible_facts.distribution }}.yml' - - '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version | default() }}.yml' - - '{{ ansible_facts.os_family }}.yml' + - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version | default() }}.yml" + - "{{ ansible_facts.distribution }}.yml" + - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version | default() }}.yml" + - "{{ ansible_facts.os_family }}.yml" skip: true tags: always # we only override variables with our default, if they have not been specified already # by default the lookup functions finds all varnames containing the string, therefore # we add ^ and $ to denote start and end of string, so this returns only exact matches -- name: Set OS dependent variables, if not already defined by user # noqa var-naming - set_fact: - '{{ item.key }}': '{{ item.value }}' - when: "not lookup('varnames', '^' + item.key + '$')" - with_dict: '{{ os_vars }}' +- name: Set OS dependent variables, if not already defined by user # noqa var-naming + ansible.builtin.set_fact: + "{{ item.key }}": "{{ item.value }}" + when: not lookup('varnames', '^' + item.key + '$') + with_dict: "{{ os_vars }}" tags: always - name: Get openssh-version - command: ssh -V + ansible.builtin.command: ssh -V register: sshd_version_raw changed_when: false check_mode: false - name: Parse openssh-version - set_fact: + ansible.builtin.set_fact: sshd_version: "{{ sshd_version_raw.stderr | regex_replace('.*_([0-9]*.[0-9]).*', '\\1') }}" - name: Set default for ssh_host_key_files if not supplied - include_tasks: crypto_hostkeys.yml + ansible.builtin.include_tasks: crypto_hostkeys.yml when: - ssh_server_hardening | bool - not ssh_host_key_files - name: Set default for ssh_macs if not supplied - include_tasks: crypto_macs.yml + ansible.builtin.include_tasks: crypto_macs.yml when: not ssh_macs - name: Set default for ssh_ciphers if not supplied - include_tasks: crypto_ciphers.yml + ansible.builtin.include_tasks: crypto_ciphers.yml when: not ssh_ciphers - name: Set default for ssh_kex if not supplied - include_tasks: crypto_kex.yml + ansible.builtin.include_tasks: crypto_kex.yml when: not ssh_kex - name: Create revoked_keys and set permissions to root/600 - template: - src: 'revoked_keys.j2' - dest: '/etc/ssh/revoked_keys' - mode: '0600' - owner: '{{ ssh_owner }}' - group: '{{ ssh_group }}' + ansible.builtin.template: + src: revoked_keys.j2 + dest: /etc/ssh/revoked_keys + mode: "0600" + owner: "{{ ssh_owner }}" + group: "{{ ssh_group }}" notify: Restart sshd when: ssh_server_hardening | bool - name: Create sshd_config and set permissions to root/600 - template: - src: 'opensshd.conf.j2' + ansible.builtin.template: + src: opensshd.conf.j2 dest: "{{ ssh_server_config_file }}" - mode: '0600' - owner: '{{ ssh_owner }}' - group: '{{ ssh_group }}' - validate: '{{ sshd_path }} -T -C user=root -C host=localhost -C addr=localhost -C lport=22 -f %s' + mode: "0600" + owner: "{{ ssh_owner }}" + group: "{{ ssh_group }}" + validate: "{{ sshd_path }} -T -C user=root -C host=localhost -C addr=localhost -C lport=22 -f %s" notify: Restart sshd when: ssh_server_hardening | bool - name: Disable dynamic MOTD - pamd: + community.general.pamd: name: sshd type: session control: optional @@ -85,52 +85,53 @@ - not (ssh_print_pam_motd | bool) - name: Create ssh_config and set permissions to root/644 - template: - src: 'openssh.conf.j2' + ansible.builtin.template: + src: openssh.conf.j2 dest: "{{ ssh_client_config_file }}" - mode: '0644' - owner: '{{ ssh_owner }}' - group: '{{ ssh_group }}' + mode: "0644" + owner: "{{ ssh_owner }}" + group: "{{ ssh_group }}" when: ssh_client_hardening | bool - name: Check if {{ sshd_moduli_file }} contains weak DH parameters - shell: awk '$5 < {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} + ansible.builtin.shell: awk '$5 < {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} register: sshd_register_moduli changed_when: false check_mode: false when: ssh_server_hardening | bool - name: Remove all small primes - shell: awk '$5 >= {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} > {{ sshd_moduli_file }}.new ; - [ -r {{ sshd_moduli_file }}.new -a -s {{ sshd_moduli_file }}.new ] && mv {{ sshd_moduli_file }}.new {{ sshd_moduli_file }} || true + ansible.builtin.shell: > + awk '$5 >= {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} > {{ sshd_moduli_file }}.new ; [ -r {{ sshd_moduli_file }}.new + -a -s {{ sshd_moduli_file }}.new ] && mv {{ sshd_moduli_file }}.new {{ sshd_moduli_file }} || true notify: Restart sshd when: - ssh_server_hardening | bool - sshd_register_moduli.stdout - name: Include tasks to setup ca keys and principals - include_tasks: ca_keys_and_principals.yml + ansible.builtin.include_tasks: ca_keys_and_principals.yml when: - ssh_trusted_user_ca_keys_file | length > 0 - ssh_trusted_user_ca_keys | length > 0 - name: Include selinux specific tasks - include_tasks: selinux.yml + ansible.builtin.include_tasks: selinux.yml when: ansible_facts.selinux and ansible_facts.selinux.status == "enabled" - name: Gather package facts - package_facts: + ansible.builtin.package_facts: check_mode: false when: - sshd_disable_crypto_policy | bool - name: Disable SSH server CRYPTO_POLICY - copy: + ansible.builtin.copy: src: sshd dest: /etc/sysconfig/sshd - owner: 'root' - group: 'root' - mode: '0640' + owner: root + group: root + mode: "0640" when: - sshd_disable_crypto_policy | bool - ('crypto-policies' in ansible_facts.packages) diff --git a/roles/ssh_hardening/tasks/main.yml b/roles/ssh_hardening/tasks/main.yml index 5a9530f9..360f0679 100644 --- a/roles/ssh_hardening/tasks/main.yml +++ b/roles/ssh_hardening/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Include hardening tasks - include_tasks: hardening.yml + ansible.builtin.include_tasks: hardening.yml args: apply: become: true diff --git a/roles/ssh_hardening/tasks/selinux.yml b/roles/ssh_hardening/tasks/selinux.yml index 8fcf1074..ad051090 100644 --- a/roles/ssh_hardening/tasks/selinux.yml +++ b/roles/ssh_hardening/tasks/selinux.yml @@ -1,19 +1,19 @@ --- - name: Install selinux dependencies when selinux is installed - package: - name: '{{ ssh_selinux_packages }}' + ansible.builtin.package: + name: "{{ ssh_selinux_packages }}" state: present - name: Authorize {{ ssh_server_ports }} ports for selinux - seport: - ports: '{{ item }}' + community.general.seport: + ports: "{{ item }}" proto: tcp setype: ssh_port_t state: present - loop: '{{ ssh_server_ports }}' + loop: "{{ ssh_server_ports }}" - name: Check if ssh_password module is already installed - shell: 'set -o pipefail && semodule -l | grep ssh_password' + ansible.builtin.shell: set -o pipefail && semodule -l | grep ssh_password args: executable: /bin/bash register: ssh_password_module @@ -30,36 +30,35 @@ - ('ssh_password' not in ssh_password_module.stdout) block: - name: Create selinux custom policy drop folder - file: - path: '{{ ssh_custom_selinux_dir }}' - state: 'directory' - owner: 'root' - group: 'root' - mode: '0750' + ansible.builtin.file: + path: "{{ ssh_custom_selinux_dir }}" + state: directory + owner: root + group: root + mode: "0750" - name: Distributing custom selinux policies - copy: - src: 'ssh_password' - dest: '{{ ssh_custom_selinux_dir }}' - owner: 'root' - group: 'root' - mode: '0600' + ansible.builtin.copy: + src: ssh_password + dest: "{{ ssh_custom_selinux_dir }}" + owner: root + group: root + mode: "0600" - - name: Check and compile policy # noqa no-changed-when - command: checkmodule -M -m -o {{ ssh_custom_selinux_dir }}/ssh_password.mod {{ ssh_custom_selinux_dir }}/ssh_password + - name: Check and compile policy # noqa no-changed-when + ansible.builtin.command: checkmodule -M -m -o {{ ssh_custom_selinux_dir }}/ssh_password.mod {{ ssh_custom_selinux_dir }}/ssh_password - - name: Create selinux policy module package # noqa no-changed-when - command: semodule_package -o {{ ssh_custom_selinux_dir }}/ssh_password.pp -m {{ ssh_custom_selinux_dir }}/ssh_password.mod - - - name: Install selinux policy # noqa no-changed-when - command: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp + - name: Create selinux policy module package # noqa no-changed-when + ansible.builtin.command: semodule_package -o {{ ssh_custom_selinux_dir }}/ssh_password.pp -m {{ ssh_custom_selinux_dir }}/ssh_password.mod + - name: Install selinux policy # noqa no-changed-when + ansible.builtin.command: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp # The following tasks only get executed when selinux is installed, UsePam is # 'yes' and the ssh_password module is installed. See # http://danwalsh.livejournal.com/12333.html for more info - name: Remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk - command: semodule -r ssh_password + ansible.builtin.command: semodule -r ssh_password when: - ssh_use_pam | bool - ('ssh_password' in ssh_password_module.stdout) diff --git a/roles/ssh_hardening/vars/Archlinux.yml b/roles/ssh_hardening/vars/Archlinux.yml index 25796938..9ccbe38f 100644 --- a/roles/ssh_hardening/vars/Archlinux.yml +++ b/roles/ssh_hardening/vars/Archlinux.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root # true if SSH support Kerberos ssh_kerberos_support: true @@ -13,7 +13,7 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli # CRYPTO_POLICY is not supported on Archlinux # and the package check only works in Ansible >2.10 diff --git a/roles/ssh_hardening/vars/Debian.yml b/roles/ssh_hardening/vars/Debian.yml index d112d0f1..9cbc1d97 100644 --- a/roles/ssh_hardening/vars/Debian.yml +++ b/roles/ssh_hardening/vars/Debian.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: ssh ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root ssh_selinux_packages: - policycoreutils-python - checkpolicy @@ -16,6 +16,6 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli sshd_disable_crypto_policy: false diff --git a/roles/ssh_hardening/vars/Fedora.yml b/roles/ssh_hardening/vars/Fedora.yml index 31dadb10..2b157dbe 100644 --- a/roles/ssh_hardening/vars/Fedora.yml +++ b/roles/ssh_hardening/vars/Fedora.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'ssh_keys' +ssh_host_keys_owner: root +ssh_host_keys_group: ssh_keys ssh_selinux_packages: - python3-policycoreutils - checkpolicy @@ -16,7 +16,7 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli # disable CRYPTO_POLICY to take settings from sshd configuration # see: https://access.redhat.com/solutions/4410591 diff --git a/roles/ssh_hardening/vars/FreeBSD.yml b/roles/ssh_hardening/vars/FreeBSD.yml index 688184d2..036d3f35 100644 --- a/roles/ssh_hardening/vars/FreeBSD.yml +++ b/roles/ssh_hardening/vars/FreeBSD.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: wheel -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root # true if SSH support Kerberos ssh_kerberos_support: true @@ -13,6 +13,6 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli sshd_disable_crypto_policy: false diff --git a/roles/ssh_hardening/vars/OpenBSD.yml b/roles/ssh_hardening/vars/OpenBSD.yml index 75df8149..24174711 100644 --- a/roles/ssh_hardening/vars/OpenBSD.yml +++ b/roles/ssh_hardening/vars/OpenBSD.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: wheel -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root # true if SSH support Kerberos ssh_kerberos_support: false @@ -13,6 +13,6 @@ ssh_kerberos_support: false # true if SSH has PAM support ssh_pam_support: false -sshd_moduli_file: '/etc/moduli' +sshd_moduli_file: /etc/moduli sshd_disable_crypto_policy: false diff --git a/roles/ssh_hardening/vars/RedHat.yml b/roles/ssh_hardening/vars/RedHat.yml index 6bafe8c7..dcb8e63d 100644 --- a/roles/ssh_hardening/vars/RedHat.yml +++ b/roles/ssh_hardening/vars/RedHat.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'ssh_keys' +ssh_host_keys_owner: root +ssh_host_keys_group: ssh_keys ssh_selinux_packages: - policycoreutils-python-utils - checkpolicy @@ -16,7 +16,7 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli # disable CRYPTO_POLICY to take settings from sshd configuration # see: https://access.redhat.com/solutions/4410591 diff --git a/roles/ssh_hardening/vars/RedHat_7.yml b/roles/ssh_hardening/vars/RedHat_7.yml index 4c97cd6a..d871dd52 100644 --- a/roles/ssh_hardening/vars/RedHat_7.yml +++ b/roles/ssh_hardening/vars/RedHat_7.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'ssh_keys' +ssh_host_keys_owner: root +ssh_host_keys_group: ssh_keys ssh_selinux_packages: - policycoreutils-python - checkpolicy @@ -16,7 +16,7 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli # disable CRYPTO_POLICY to take settings from sshd configuration # see: https://access.redhat.com/solutions/4410591 diff --git a/roles/ssh_hardening/vars/SmartOS.yml b/roles/ssh_hardening/vars/SmartOS.yml index f22f5bf0..9a6e7a15 100644 --- a/roles/ssh_hardening/vars/SmartOS.yml +++ b/roles/ssh_hardening/vars/SmartOS.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/lib/ssh/sshd -ssh_host_keys_dir: '/var/ssh' +ssh_host_keys_dir: /var/ssh sshd_service_name: ssh ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root # true if SSH support Kerberos ssh_kerberos_support: true @@ -13,6 +13,6 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: false -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli sshd_disable_crypto_policy: false diff --git a/roles/ssh_hardening/vars/Suse.yml b/roles/ssh_hardening/vars/Suse.yml index 066dfe58..833e7484 100644 --- a/roles/ssh_hardening/vars/Suse.yml +++ b/roles/ssh_hardening/vars/Suse.yml @@ -1,11 +1,11 @@ --- sshd_path: /usr/sbin/sshd -ssh_host_keys_dir: '/etc/ssh' +ssh_host_keys_dir: /etc/ssh sshd_service_name: sshd ssh_owner: root ssh_group: root -ssh_host_keys_owner: 'root' -ssh_host_keys_group: 'root' +ssh_host_keys_owner: root +ssh_host_keys_group: root # true if SSH support Kerberos ssh_kerberos_support: true @@ -13,6 +13,6 @@ ssh_kerberos_support: true # true if SSH has PAM support ssh_pam_support: true -sshd_moduli_file: '/etc/ssh/moduli' +sshd_moduli_file: /etc/ssh/moduli sshd_disable_crypto_policy: false