* linting

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* more linting

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* change line length issues

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* replace yes with true in tasks

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* use manual line-wrapping because ansible-lint does not support it correctly.

see https://github.com/ansible/ansible-lint/issues/2522

* use manual line-wrapping because ansible-lint does not support it correctly.

see https://github.com/ansible/ansible-lint/issues/2522

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* use manual line-wrapping because ansible-lint does not support it correctly.

see https://github.com/ansible/ansible-lint/issues/2522

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* add exception for task

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* remove trailing whitespace

* add back deleted params

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* add back deleted params

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>

* add back tasks

Signed-off-by: Sebastian Gumprich <sebastian.gumprich@t-systems.com>
This commit is contained in:
Sebastian Gumprich 2023-01-24 12:40:27 +01:00 committed by GitHub
parent a94168c84f
commit bb588bd777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 1095 additions and 1029 deletions

View file

@ -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

View file

@ -1,13 +1,14 @@
---
namespace: devsec namespace: devsec
name: hardening name: hardening
version: 8.4.0 version: 8.4.0
readme: README.md readme: README.md
authors: authors:
- dev-sec <hello@dev-sec.io> - dev-sec <hello@dev-sec.io>
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: license:
- Apache-2.0 - Apache-2.0
license_file: '' license_file: ""
tags: tags:
- devsec - devsec
- hardening - hardening
@ -23,13 +24,13 @@ tags:
- os_hardening - os_hardening
- ssh_hardening - ssh_hardening
dependencies: dependencies:
ansible.posix: '>=1.0.0' ansible.posix: ">=1.0.0"
community.crypto: '>=1.0.0' community.crypto: ">=1.0.0"
community.general: '>=1.0.0' community.general: ">=1.0.0"
community.mysql: '>=1.3.0' community.mysql: ">=1.3.0"
repository: 'https://github.com/dev-sec/ansible-collection-hardening/' repository: https://github.com/dev-sec/ansible-collection-hardening/
homepage: 'https://dev-sec.io/' homepage: https://dev-sec.io/
issues: 'https://github.com/dev-sec/ansible-collection-hardening/issues' issues: https://github.com/dev-sec/ansible-collection-hardening/issues
build_ignore: build_ignore:
- codecov.yml - codecov.yml
- .github - .github

View file

@ -1,2 +1,2 @@
--- ---
requires_ansible: '>=2.9.10' requires_ansible: ">=2.9.10"

View file

@ -7,9 +7,9 @@ mysql_daemon_enabled: true
mysql_hardening_restart_mysql: true mysql_hardening_restart_mysql: true
# general configuration # 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 # 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 # There .my.cnf with mysql root credentials will be installed
mysql_user_home: "{{ ansible_env.HOME }}" mysql_user_home: "{{ ansible_env.HOME }}"
@ -48,6 +48,6 @@ mysql_hardening_options:
automatic-sp-privileges: 0 automatic-sp-privileges: 0
# @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option-mysqld-secure-file-priv # @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 # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_user
user: '{{ mysql_hardening_user }}' user: "{{ mysql_hardening_user }}"

View file

@ -1,7 +1,6 @@
--- ---
- name: Restart mysql - name: Restart mysql
service: ansible.builtin.service:
name: '{{ mysql_daemon }}' name: "{{ mysql_daemon }}"
state: restarted state: restarted
when: mysql_hardening_restart_mysql | bool when: mysql_hardening_restart_mysql | bool

View file

@ -1,10 +1,10 @@
--- ---
galaxy_info: galaxy_info:
author: "Sebastian Gumprich" author: Sebastian Gumprich
description: 'This Ansible playbook provides security configuration for mysql.' description: This Ansible playbook provides security configuration for mysql.
company: Hardening Framework Team company: Hardening Framework Team
license: Apache License 2.0 license: Apache License 2.0
min_ansible_version: '2.9.10' min_ansible_version: 2.9.10
platforms: platforms:
- name: EL - name: EL
versions: versions:

View file

@ -1,64 +1,64 @@
--- ---
- name: Protect my.cnf - name: Protect my.cnf
file: ansible.builtin.file:
path: '{{ mysql_hardening_mysql_conf_file }}' path: "{{ mysql_hardening_mysql_conf_file }}"
mode: '0640' mode: "0640"
owner: '{{ mysql_cnf_owner }}' owner: "{{ mysql_cnf_owner }}"
group: '{{ mysql_cnf_group }}' group: "{{ mysql_cnf_group }}"
follow: true follow: true
state: file state: file
- name: Ensure permissions on mysql-datadir are correct - name: Ensure permissions on mysql-datadir are correct
file: ansible.builtin.file:
path: '{{ item }}' path: "{{ item }}"
state: directory state: directory
owner: '{{ mysql_hardening_user }}' owner: "{{ mysql_hardening_user }}"
group: '{{ mysql_hardening_user }}' group: "{{ mysql_hardening_user }}"
mode: '0750' mode: "0750"
when: item is defined and item != "" when: item is defined and item != ""
loop: loop:
- '{{ mysql_settings.settings.datadir }}' - "{{ mysql_settings.settings.datadir }}"
- '{{ mysql_datadir | default("") }}' - '{{ mysql_datadir | default("") }}'
- name: Ensure permissions on mysql-logfile are correct - name: Ensure permissions on mysql-logfile are correct
file: ansible.builtin.file:
path: '{{ item }}' path: "{{ item }}"
state: file state: file
owner: '{{ mysql_hardening_user }}' owner: "{{ mysql_hardening_user }}"
group: '{{ mysql_hardening_group }}' group: "{{ mysql_hardening_group }}"
mode: '0640' mode: "0640"
when: item is defined and item != "" when: item is defined and item != ""
loop: loop:
- '{{ mysql_settings.settings.log_error }}' - "{{ mysql_settings.settings.log_error }}"
- '{{ mysql_hardening_log_file | default("") }}' - '{{ mysql_hardening_log_file | default("") }}'
- name: Check mysql configuration-directory exists and has right permissions - name: Check mysql configuration-directory exists and has right permissions
file: ansible.builtin.file:
path: '{{ mysql_hardening_mysql_confd_dir }}' path: "{{ mysql_hardening_mysql_confd_dir }}"
state: directory state: directory
owner: '{{ mysql_hardening_user }}' owner: "{{ mysql_hardening_user }}"
group: '{{ mysql_hardening_group }}' group: "{{ mysql_hardening_group }}"
mode: '0750' mode: "0750"
- name: Check include-dir directive is present in my.cnf - name: Check include-dir directive is present in my.cnf
lineinfile: ansible.builtin.lineinfile:
dest: '{{ mysql_hardening_mysql_conf_file }}' dest: "{{ mysql_hardening_mysql_conf_file }}"
line: '!includedir {{ mysql_hardening_mysql_confd_dir }}' line: "!includedir {{ mysql_hardening_mysql_confd_dir }}"
insertafter: 'EOF' insertafter: EOF
state: present state: present
backup: true backup: true
notify: Restart mysql notify: Restart mysql
- name: Apply hardening configuration - name: Apply hardening configuration
template: ansible.builtin.template:
src: 'hardening.cnf.j2' src: hardening.cnf.j2
dest: '{{ mysql_hardening_mysql_hardening_conf_file }}' dest: "{{ mysql_hardening_mysql_hardening_conf_file }}"
owner: '{{ mysql_cnf_owner }}' owner: "{{ mysql_cnf_owner }}"
group: '{{ mysql_cnf_group }}' group: "{{ mysql_cnf_group }}"
mode: '0640' mode: "0640"
notify: Restart mysql notify: Restart mysql
- name: Enable mysql - name: Enable mysql
service: ansible.builtin.service:
name: '{{ mysql_daemon }}' name: "{{ mysql_daemon }}"
enabled: '{{ mysql_daemon_enabled }}' enabled: "{{ mysql_daemon_enabled }}"

View file

@ -1,14 +1,14 @@
--- ---
- name: Fetch OS dependent variables - name: Fetch OS dependent variables
include_vars: ansible.builtin.include_vars:
file: '{{ item }}' file: "{{ item }}"
name: 'os_vars' name: os_vars
with_first_found: with_first_found:
- files: - files:
- '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml' - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml"
- '{{ ansible_facts.distribution }}.yml' - "{{ ansible_facts.distribution }}.yml"
- '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml' - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml"
- '{{ ansible_facts.os_family }}.yml' - "{{ ansible_facts.os_family }}.yml"
skip: true skip: true
tags: always tags: always
@ -16,16 +16,16 @@
# by default the lookup functions finds all varnames containing the string, therefore # 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. # 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 - name: Set OS dependent variables, if not already defined by user # noqa var-naming
set_fact: ansible.builtin.set_fact:
'{{ item.key }}': '{{ item.value }}' "{{ item.key }}": "{{ item.value }}"
when: "not lookup('varnames', '^' + item.key + '$')" when: not lookup('varnames', '^' + item.key + '$')
with_dict: '{{ os_vars }}' with_dict: "{{ os_vars }}"
tags: always tags: always
- name: Check that the variable mysql_distribution is set correctly - name: Check that the variable mysql_distribution is set correctly
ansible.builtin.assert: ansible.builtin.assert:
that: mysql_distribution == 'mysql' or mysql_distribution == 'mariadb' 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 when: mysql_distribution is defined
- name: Gather package facts to check for mysql/mariadb version - name: Gather package facts to check for mysql/mariadb version
@ -34,7 +34,7 @@
when: not mysql_distribution is defined when: not mysql_distribution is defined
- name: Check if MySQL or MariaDB is used - 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') }}" mysql_distribution: "{{ ansible_facts.packages['mysql-server'] is defined | ternary('mysql', 'mariadb') }}"
when: not mysql_distribution is defined when: not mysql_distribution is defined
@ -53,20 +53,20 @@
# see https://stackoverflow.com/a/59451077/2953919 for the # see https://stackoverflow.com/a/59451077/2953919 for the
# dict2items and vice versa magic # dict2items and vice versa magic
- name: Drop the secure-auth parameter on MySQL >=8.0.3 (not mariadb) - 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 }}" mysql_hardening_options: "{{ mysql_hardening_options | dict2items | rejectattr('key', 'search', 'secure-auth') | list | items2dict }}"
when: when:
- mysql_version.version.full is version('8.0.3', '>=') - mysql_version.version.full is version('8.0.3', '>=')
- mysql_distribution == "mysql" - mysql_distribution == "mysql"
- name: Include tasks for configuration - name: Include tasks for configuration
import_tasks: configure.yml ansible.builtin.import_tasks: configure.yml
when: mysql_hardening_enabled | bool when: mysql_hardening_enabled | bool
tags: tags:
- mysql_hardening - mysql_hardening
- name: Include tasks to secure mysql installation - 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 when: mysql_hardening_enabled | bool
tags: tags:
- mysql_hardening - mysql_hardening

View file

@ -1,22 +1,22 @@
--- ---
- name: Fail the role if the mysql root password was not set - name: Fail the role if the mysql root password was not set
fail: ansible.builtin.fail:
msg: 'ERROR - you have to change default mysql_root_password' msg: ERROR - you have to change default mysql_root_password
when: mysql_root_password == '-----====>SetR00tPa$$wordH3r3!!!<====-----' when: mysql_root_password == '-----====>SetR00tPa$$wordH3r3!!!<====-----'
- name: Ensure that the root password is present - name: Ensure that the root password is present
community.mysql.mysql_user: community.mysql.mysql_user:
name: 'root' name: root
host_all: true host_all: true
password: '{{ mysql_root_password | mandatory }}' password: "{{ mysql_root_password | mandatory }}"
state: present state: present
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
- name: Install .my.cnf with credentials - name: Install .my.cnf with credentials
template: ansible.builtin.template:
src: 'my.cnf.j2' src: my.cnf.j2
dest: '{{ mysql_user_home }}/.my.cnf' dest: "{{ mysql_user_home }}/.my.cnf"
mode: '0400' mode: "0400"
tags: my_cnf tags: my_cnf
- name: Ensure that the test database is absent - name: Ensure that the test database is absent
@ -28,7 +28,7 @@
- name: Ensure that anonymous users are absent - name: Ensure that anonymous users are absent
community.mysql.mysql_user: community.mysql.mysql_user:
name: '' name: ""
state: absent state: absent
host_all: true host_all: true
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
@ -36,36 +36,38 @@
- name: Ensure that root can only login from localhost - name: Ensure that root can only login from localhost
community.mysql.mysql_query: community.mysql.mysql_query:
query: query: >
- DELETE DELETE
FROM mysql.user FROM mysql.user
WHERE USER='root' WHERE USER='root'
AND HOST NOT IN ('localhost', AND HOST NOT IN ('localhost',
'127.0.0.1', '127.0.0.1',
'::1') '::1');
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
when: mysql_remove_remote_root 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 - 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: community.mysql.mysql_query:
query: query: >
- SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users
FROM mysql.user FROM mysql.user
WHERE (length(authentication_string)=0 WHERE (length(authentication_string)=0
OR authentication_string="") OR authentication_string="")
AND USER NOT IN ('mysql.sys', AND USER NOT IN ('mysql.sys',
'mysqlxsys', 'mysqlxsys',
'mariadb.sys'); 'mariadb.sys');
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
register: mysql_users_wo_passwords_or_auth_string register: mysql_users_wo_passwords_or_auth_string
when: when: >
- (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '>=')) or (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', '>=')) (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 - 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: community.mysql.mysql_query:
query: query: >
- SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users SELECT GROUP_CONCAT(QUOTE(USER), '@', QUOTE(HOST) SEPARATOR ', ') AS users
FROM mysql.user FROM mysql.user
WHERE (length(password)=0 WHERE (length(password)=0
OR password="") OR password="")
@ -76,19 +78,20 @@
'mariadb.sys'); 'mariadb.sys');
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
register: mysql_users_wo_passwords register: mysql_users_wo_passwords
when: when: >
- (mysql_distribution == "mysql" and mysql_version.version.full is version('5.7.6', '<')) or (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', '<')) (mysql_distribution == "mariadb" and mysql_version.version.full is
version('10.4.0', '<'))
- name: Create a fact for users without password or authentication_string - 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') }}" users_wo_auth: "{{ mysql_users_wo_passwords_or_auth_string.query_result.0.0 | community.general.json_query('users') }}"
when: when:
- mysql_users_wo_passwords_or_auth_string.query_result is defined - 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 - 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') }}" users_wo_auth: "{{ mysql_users_wo_passwords.query_result.0.0 | community.general.json_query('users') }}"
when: when:
- mysql_users_wo_passwords.query_result is defined - mysql_users_wo_passwords.query_result is defined
@ -97,7 +100,7 @@
- name: Ensure that there are no users without password or authentication_string - name: Ensure that there are no users without password or authentication_string
community.mysql.mysql_query: community.mysql.mysql_query:
query: query:
- "DROP USER {{ users_wo_auth }}" - DROP USER {{ users_wo_auth }}
login_unix_socket: "{{ login_unix_socket | default(omit) }}" login_unix_socket: "{{ login_unix_socket | default(omit) }}"
when: when:
- users_wo_auth is defined - users_wo_auth is defined

View file

@ -1,10 +1,10 @@
--- ---
mysql_daemon: mariadb mysql_daemon: mariadb
mysql_hardening_mysql_conf_file: '/etc/mysql/my.cnf' mysql_hardening_mysql_conf_file: /etc/mysql/my.cnf
mysql_hardening_mysql_confd_dir: '/etc/mysql/conf.d' 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_owner: root # owner of /etc/mysql/*.cnf files
mysql_cnf_group: 'mysql' # owner of /etc/mysql/*.cnf files mysql_cnf_group: mysql # owner of /etc/mysql/*.cnf files

View file

@ -1,4 +1,4 @@
--- ---
mysql_daemon: mysqld mysql_daemon: mysqld
mysql_hardening_mysql_conf_file: '/etc/my.cnf' mysql_hardening_mysql_conf_file: /etc/my.cnf
mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' mysql_hardening_mysql_confd_dir: /etc/my.cnf.d

View file

@ -1,10 +1,10 @@
--- ---
mysql_daemon: mysql-server mysql_daemon: mysql-server
mysql_hardening_mysql_conf_file: '/usr/local/etc/mysql/my.cnf' 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_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_owner: root # owner of /usr/local/etc/mysql/*.cnf files
mysql_cnf_group: 'mysql' # owner of /usr/local/etc/mysql/*.cnf files mysql_cnf_group: mysql # owner of /usr/local/etc/mysql/*.cnf files

View file

@ -1,7 +1,7 @@
--- ---
mysql_daemon: mysqld mysql_daemon: mysqld
mysql_hardening_mysql_conf_file: '/etc/my.cnf' mysql_hardening_mysql_conf_file: /etc/my.cnf
mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' mysql_hardening_mysql_confd_dir: /etc/my.cnf.d
mysql_hardening_group: 'adm' mysql_hardening_group: adm

View file

@ -1,9 +1,9 @@
--- ---
mysql_daemon: mariadb mysql_daemon: mariadb
mysql_hardening_mysql_conf_file: '/etc/my.cnf' mysql_hardening_mysql_conf_file: /etc/my.cnf
mysql_hardening_mysql_confd_dir: '/etc/my.cnf.d' mysql_hardening_mysql_confd_dir: /etc/my.cnf.d
mysql_cnf_owner: 'root' # 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_cnf_group: mysql # owner of /etc/mysql/*.cnf files
mysql_hardening_group: 'mysql' mysql_hardening_group: mysql

View file

@ -1,10 +1,10 @@
--- ---
mysql_daemon: mysql mysql_daemon: mysql
mysql_hardening_mysql_conf_file: '/etc/mysql/my.cnf' mysql_hardening_mysql_conf_file: /etc/mysql/my.cnf
mysql_hardening_mysql_confd_dir: '/etc/mysql/conf.d' mysql_hardening_mysql_confd_dir: /etc/mysql/conf.d
mysql_cnf_owner: 'root' # 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_cnf_group: mysql # owner of /etc/mysql/*.cnf files
mysql_hardening_group: 'adm' mysql_hardening_group: adm

View file

@ -1,3 +1,2 @@
--- ---
mysql_hardening_user: mysql # owner of data
mysql_hardening_user: 'mysql' # owner of data

View file

@ -1,20 +1,20 @@
--- ---
nginx_client_body_buffer_size: '1k' nginx_client_body_buffer_size: 1k
nginx_remove_default_site: true nginx_remove_default_site: true
nginx_client_max_body_size: '1k' nginx_client_max_body_size: 1k
nginx_keepalive_timeout: '5 5' nginx_keepalive_timeout: 5 5
nginx_server_tokens: 'off' nginx_server_tokens: "off"
nginx_client_header_buffer_size: "1k" nginx_client_header_buffer_size: 1k
nginx_large_client_header_buffers: "2 1k" nginx_large_client_header_buffers: 2 1k
nginx_client_body_timeout: "10" nginx_client_body_timeout: "10"
nginx_client_header_timeout: "10" nginx_client_header_timeout: "10"
nginx_send_timeout: "10" nginx_send_timeout: "10"
nginx_limit_conn_zone: "$binary_remote_addr zone=default:10m" nginx_limit_conn_zone: $binary_remote_addr zone=default:10m
nginx_limit_conn: "default 5" nginx_limit_conn: default 5
nginx_configuration_dir: "/etc/nginx" nginx_configuration_dir: /etc/nginx
nginx_configuration_hardening_dir: "/etc/nginx" nginx_configuration_hardening_dir: /etc/nginx
nginx_owner_user: "root" nginx_owner_user: root
nginx_owner_group: "root" nginx_owner_group: root
nginx_add_header: nginx_add_header:
# avoid clickjacking # avoid clickjacking
- X-Frame-Options SAMEORIGIN - X-Frame-Options SAMEORIGIN
@ -27,7 +27,8 @@ nginx_add_header:
nginx_set_cookie_flag: "* HttpOnly secure" nginx_set_cookie_flag: "* HttpOnly secure"
nginx_ssl_prefer_server_ciphers: "on" nginx_ssl_prefer_server_ciphers: "on"
nginx_ssl_protocols: "TLSv1.2 TLSv1.3" 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" # 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_ssl_session_tickets: "off"
nginx_dh_size: "4096" nginx_dh_size: "4096"

View file

@ -1,5 +1,5 @@
--- ---
- name: Restart nginx - name: Restart nginx
service: ansible.builtin.service:
name: "nginx" name: nginx
state: restarted state: restarted

View file

@ -1,10 +1,10 @@
--- ---
galaxy_info: galaxy_info:
author: "Sebastian Gumprich" author: Sebastian Gumprich
description: 'This Ansible role provides secure nginx configurations. http://dev-sec.io/' description: This Ansible role provides secure nginx configurations. http://dev-sec.io/
company: Hardening Framework Team company: Hardening Framework Team
license: Apache License 2.0 license: Apache License 2.0
min_ansible_version: '2.9.10' min_ansible_version: 2.9.10
platforms: platforms:
- name: EL - name: EL
versions: versions:

View file

@ -1,81 +1,81 @@
--- ---
- name: Create additional configuration - name: Create additional configuration
template: ansible.builtin.template:
src: "hardening.conf.j2" src: hardening.conf.j2
dest: "{{ nginx_configuration_dir }}/conf.d/90.hardening.conf" dest: "{{ nginx_configuration_dir }}/conf.d/90.hardening.conf"
mode: '0600' mode: "0600"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change configuration in main nginx.conf - name: Change configuration in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" dest: "{{ nginx_configuration_dir }}/nginx.conf"
regexp: '^\s*server_tokens' regexp: ^\s*server_tokens
line: " server_tokens {{ nginx_server_tokens }};" line: " server_tokens {{ nginx_server_tokens }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change ssl_protocols in main nginx.conf - name: Change ssl_protocols in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" dest: "{{ nginx_configuration_dir }}/nginx.conf"
regexp: '^\s*ssl_protocols' regexp: ^\s*ssl_protocols
line: " ssl_protocols {{ nginx_ssl_protocols }};" line: " ssl_protocols {{ nginx_ssl_protocols }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change ssl_prefer_server_ciphers in main nginx.conf - name: Change ssl_prefer_server_ciphers in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" 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 }};" line: " ssl_prefer_server_ciphers {{ nginx_ssl_prefer_server_ciphers }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change client_max_body_size in main nginx.conf - name: Change client_max_body_size in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" 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 }};" line: " client_max_body_size {{ nginx_client_max_body_size }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change client_body_buffer_size in main nginx.conf - name: Change client_body_buffer_size in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" 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 }};" line: " client_body_buffer_size {{ nginx_client_body_buffer_size }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Change keepalive_timeout in main nginx.conf - name: Change keepalive_timeout in main nginx.conf
lineinfile: ansible.builtin.lineinfile:
dest: "{{ nginx_configuration_dir }}/nginx.conf" dest: "{{ nginx_configuration_dir }}/nginx.conf"
regexp: '^\s*keepalive_timeout' regexp: ^\s*keepalive_timeout
line: " keepalive_timeout {{ nginx_keepalive_timeout }};" line: " keepalive_timeout {{ nginx_keepalive_timeout }};"
insertafter: "http {" insertafter: http {
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx
- name: Remove default.conf - name: Remove default.conf
file: ansible.builtin.file:
path: "{{ item }}" path: "{{ item }}"
state: absent state: absent
when: nginx_remove_default_site when: nginx_remove_default_site
@ -85,10 +85,10 @@
- "{{ nginx_configuration_dir }}/sites-enabled/default" - "{{ nginx_configuration_dir }}/sites-enabled/default"
- name: Generate dh group - name: Generate dh group
openssl_dhparam: community.crypto.openssl_dhparam:
path: "{{ nginx_configuration_dir }}/dh{{ nginx_dh_size }}.pem" path: "{{ nginx_configuration_dir }}/dh{{ nginx_dh_size }}.pem"
size: "{{ nginx_dh_size }}" size: "{{ nginx_dh_size }}"
mode: '0640' mode: "0640"
owner: "{{ nginx_owner_user }}" owner: "{{ nginx_owner_user }}"
group: "{{ nginx_owner_group }}" group: "{{ nginx_owner_group }}"
notify: Restart nginx notify: Restart nginx

View file

@ -9,11 +9,10 @@ os_auth_lockout_time: 600 # Seconds (600 = 10min)
os_auth_timeout: 60 os_auth_timeout: 60
os_auth_allow_homeless: false os_auth_allow_homeless: false
os_auth_pam_passwdqc_enable: true os_auth_pam_passwdqc_enable: true
os_auth_pam_passwdqc_options: 'min=disabled,disabled,16,12,8' # Used in Debian 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_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_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 # Set to false to disable chmod userhome folders to 700
os_chmod_rootuser_home_folder: true os_chmod_rootuser_home_folder: true
@ -22,8 +21,7 @@ os_chmod_home_folders: true
# May contain: change_user # May contain: change_user
os_security_users_allow: [] os_security_users_allow: []
# Specify user home folders in /home that shouldn't be chmodded to 700 # 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 # Set to false to disable password age enforcement on existing users
os_rootuser_pw_ageing: false os_rootuser_pw_ageing: false
@ -37,7 +35,7 @@ os_user_pw_ageing: true
os_users_without_password_ageing: [] os_users_without_password_ageing: []
# Specify system accounts whose login should not be disabled and password not changed # 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_module_loading: true
os_security_kernel_enable_core_dump: false os_security_kernel_enable_core_dump: false
os_security_suid_sgid_enforce: true os_security_suid_sgid_enforce: true
@ -49,8 +47,7 @@ os_security_suid_sgid_remove_from_unknown: false
# Remove packages with known security issues # Remove packages with known security issues
os_security_packages_clean: true 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) # Allow interactive startup (rhel, centos)
os_security_init_prompt: true os_security_init_prompt: true
# Require root password for single user mode. (rhel, centos) # 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 # By default in Ubuntu it is set to: /etc/ufw/sysctl.conf
# CAUTION! # CAUTION!
# If you enable it - it overwrites /etc/sysctl.conf file, managed by hardening framework # If you enable it - it overwrites /etc/sysctl.conf file, managed by hardening framework
ufw_ipt_sysctl: '' ufw_ipt_sysctl: ""
# Default ufw variables # Default ufw variables
ufw_default_input_policy: 'DROP' ufw_default_input_policy: DROP
ufw_default_output_policy: 'ACCEPT' ufw_default_output_policy: ACCEPT
ufw_default_forward_policy: 'DROP' ufw_default_forward_policy: DROP
ufw_default_application_policy: 'SKIP' ufw_default_application_policy: SKIP
ufw_manage_builtins: 'no' ufw_manage_builtins: "no"
ufw_ipt_modules: 'nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns' 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 # Set to true to apply rules to support IPv6 (no means only IPv6 on loopback
# accepted). # accepted).
@ -307,27 +304,25 @@ sysctl_config:
# Do not delete the following line or otherwise the playbook will fail # Do not delete the following line or otherwise the playbook will fail
# at task 'create a combined sysctl-dict if overwrites are defined' # at task 'create a combined sysctl-dict if overwrites are defined'
sysctl_overwrite: sysctl_overwrite:
# Disable unused filesystems # Disable unused filesystems
os_unused_filesystems: os_unused_filesystems:
- "cramfs" - cramfs
- "freevxfs" - freevxfs
- "jffs2" - jffs2
- "hfs" - hfs
- "hfsplus" - hfsplus
- "squashfs" - squashfs
- "udf" - udf
- "vfat" - vfat
# Obsolete network protocols that should be disabled # Obsolete network protocols that should be disabled
# per CIS Oracle Linux 6 Benchmark (2016) # per CIS Oracle Linux 6 Benchmark (2016)
- "dccp" # CIS 3.5.1 - dccp # CIS 3.5.1
- "rds" # CIS 3.5.3 - rds # CIS 3.5.3
- "sctp" # CIS 3.5.2 - sctp # CIS 3.5.2
- "tipc" # CIS 3.5.4 - tipc # CIS 3.5.4
# Whitelist for used filesystems # Whitelist for used filesystems
os_filesystem_whitelist: [] os_filesystem_whitelist: []
# Set to false to turn the role into a no-op. Useful when using # Set to false to turn the role into a no-op. Useful when using
# the Ansible role dependency mechanism. # the Ansible role dependency mechanism.
os_hardening_enabled: true os_hardening_enabled: true
@ -353,7 +348,7 @@ os_selinux_state: enforcing
os_selinux_policy: targeted os_selinux_policy: targeted
# Mount options for proc in /etc/fstab. # 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. # Set to false to disable installing and configuring cron.
os_cron_enabled: true 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. # List of yum repository files under /etc/yum.repos.d/ which should not be altered.
os_yum_repo_file_whitelist: [] os_yum_repo_file_whitelist: []
# Set to false to disable installing and configuring apt. # Set to false to disable installing and configuring apt.
os_apt_enabled: true os_apt_enabled: true
@ -412,72 +406,82 @@ os_selinux_enabled: true
os_sha_crypt_min_rounds: "640000" os_sha_crypt_min_rounds: "640000"
os_sha_crypt_max_rounds: "640000" os_sha_crypt_max_rounds: "640000"
os_mnt_boot_dir_mode: "0700"
os_mnt_boot_enabled: false os_mnt_boot_enabled: false
os_mnt_boot_src: "" 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_filesystem: ""
os_mnt_boot_dump: "" os_mnt_boot_dump: ""
os_mnt_boot_passno: "" os_mnt_boot_passno: ""
os_mnt_dev_dir_mode: "0755"
os_mnt_dev_enabled: true os_mnt_dev_enabled: true
os_mnt_dev_src: "devtmpfs" os_mnt_dev_src: devtmpfs
os_mnt_dev_options: 'rw,nosuid,noexec' os_mnt_dev_options: rw,nosuid,noexec
os_mnt_dev_filesystem: "devtmpfs" os_mnt_dev_filesystem: devtmpfs
os_mnt_dev_dump: "" os_mnt_dev_dump: ""
os_mnt_dev_passno: "" os_mnt_dev_passno: ""
os_mnt_dev_shm_dir_mode: "1777"
os_mnt_dev_shm_enabled: true os_mnt_dev_shm_enabled: true
os_mnt_dev_shm_src: "tmpfs" os_mnt_dev_shm_src: tmpfs
os_mnt_dev_shm_options: 'rw,nosuid,nodev,noexec' os_mnt_dev_shm_options: rw,nosuid,nodev,noexec
os_mnt_dev_shm_filesystem: "tmpfs" os_mnt_dev_shm_filesystem: tmpfs
os_mnt_dev_shm_dump: "" os_mnt_dev_shm_dump: ""
os_mnt_dev_shm_passno: "" os_mnt_dev_shm_passno: ""
os_mnt_home_dir_mode: "0755"
os_mnt_home_enabled: false os_mnt_home_enabled: false
os_mnt_home_src: "" 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_filesystem: ""
os_mnt_home_dump: "" os_mnt_home_dump: ""
os_mnt_home_passno: "" os_mnt_home_passno: ""
os_mnt_run_dir_mode: "0755"
os_mnt_run_enabled: true os_mnt_run_enabled: true
os_mnt_run_src: "tmpfs" os_mnt_run_src: tmpfs
os_mnt_run_options: 'rw,nosuid,nodev' os_mnt_run_options: rw,nosuid,nodev
os_mnt_run_filesystem: "tmpfs" os_mnt_run_filesystem: tmpfs
os_mnt_run_dump: "" os_mnt_run_dump: ""
os_mnt_run_passno: "" os_mnt_run_passno: ""
os_mnt_tmp_dir_mode: "1777"
os_mnt_tmp_enabled: false os_mnt_tmp_enabled: false
os_mnt_tmp_src: "" 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_filesystem: ""
os_mnt_tmp_dump: "" os_mnt_tmp_dump: ""
os_mnt_tmp_passno: "" os_mnt_tmp_passno: ""
os_mnt_var_dir_mode: "0755"
os_mnt_var_enabled: false os_mnt_var_enabled: false
os_mnt_var_src: "" 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_filesystem: ""
os_mnt_var_dump: "" os_mnt_var_dump: ""
os_mnt_var_passno: "" os_mnt_var_passno: ""
os_mnt_var_log_dir_mode: "0755"
os_mnt_var_log_enabled: false os_mnt_var_log_enabled: false
os_mnt_var_log_src: "" 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_filesystem: ""
os_mnt_var_log_dump: "" os_mnt_var_log_dump: ""
os_mnt_var_log_passno: "" 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_enabled: false
os_mnt_var_log_audit_src: "" 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_filesystem: ""
os_mnt_var_log_audit_dump: "" os_mnt_var_log_audit_dump: ""
os_mnt_var_log_audit_passno: "" os_mnt_var_log_audit_passno: ""
os_mnt_var_tmp_dir_mode: "1777"
os_mnt_var_tmp_enabled: false os_mnt_var_tmp_enabled: false
os_mnt_var_tmp_src: "" 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_filesystem: ""
os_mnt_var_tmp_dump: "" os_mnt_var_tmp_dump: ""
os_mnt_var_tmp_passno: "" os_mnt_var_tmp_passno: ""

View file

@ -1,10 +1,10 @@
--- ---
- name: Update-initramfs - 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: ansible.builtin.command:
cmd: 'service auditd restart' # rhel: see: https://access.redhat.com/solutions/2664811 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 when: molecule_yml is not defined # restarting auditd in a container does not work
- name: Reload systemd - name: Reload systemd

View file

@ -1,10 +1,10 @@
--- ---
galaxy_info: galaxy_info:
author: "Sebastian Gumprich" author: Sebastian Gumprich
description: 'This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.' description: This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.
company: Hardening Framework Team company: Hardening Framework Team
license: Apache License 2.0 license: Apache License 2.0
min_ansible_version: '2.9.10' min_ansible_version: 2.9.10
platforms: platforms:
- name: EL - name: EL
versions: versions:

View file

@ -1,7 +1,7 @@
--- ---
- name: Remove deprecated or insecure packages | package-01 - package-09 - name: Remove deprecated or insecure packages | package-01 - package-09
apt: ansible.builtin.apt:
name: '{{ os_security_packages_list }}' name: "{{ os_security_packages_list }}"
state: 'absent' state: absent
purge: 'yes' purge: true
when: os_security_packages_clean | bool when: os_security_packages_clean | bool

View file

@ -1,16 +1,16 @@
--- ---
- name: Install auditd package | package-08 - name: Install auditd package | package-08
package: ansible.builtin.package:
name: '{{ auditd_package }}' name: "{{ auditd_package }}"
state: 'present' state: present
tags: auditd tags: auditd
- name: Configure auditd | package-08 - name: Configure auditd | package-08
template: ansible.builtin.template:
src: 'etc/audit/auditd.conf.j2' src: etc/audit/auditd.conf.j2
dest: '/etc/audit/auditd.conf' dest: /etc/audit/auditd.conf
owner: 'root' owner: root
group: 'root' group: root
mode: '0640' mode: "0640"
notify: Restart auditd notify: Restart auditd
tags: auditd tags: auditd

View file

@ -6,7 +6,7 @@
# CIS 5.1.2 - CIS 5.1.7 # CIS 5.1.2 - CIS 5.1.7
# #
- name: Find cron files and directories - name: Find cron files and directories
find: ansible.builtin.find:
paths: paths:
- /etc - /etc
patterns: patterns:

View file

@ -1,6 +1,6 @@
--- ---
- name: Disable CTRL-ALT-DEL - name: Disable CTRL-ALT-DEL
systemd: ansible.builtin.systemd:
name: ctrl-alt-del.target name: ctrl-alt-del.target
masked: true masked: true
daemon_reload: true daemon_reload: true

View file

@ -1,14 +1,14 @@
--- ---
- name: Fetch OS dependent variables - name: Fetch OS dependent variables
include_vars: ansible.builtin.include_vars:
file: '{{ item }}' file: "{{ item }}"
name: 'os_vars' name: os_vars
with_first_found: with_first_found:
- files: - files:
- '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml' - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version }}.yml"
- '{{ ansible_facts.distribution }}.yml' - "{{ ansible_facts.distribution }}.yml"
- '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml' - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version }}.yml"
- '{{ ansible_facts.os_family }}.yml' - "{{ ansible_facts.os_family }}.yml"
skip: true skip: true
tags: always tags: always
@ -16,103 +16,103 @@
# by default the lookup functions finds all varnames containing the string, therefore # 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 # 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 - name: Set OS dependent variables, if not already defined by user # noqa var-naming
set_fact: ansible.builtin.set_fact:
'{{ item.key }}': '{{ item.value }}' "{{ item.key }}": "{{ item.value }}"
when: "not lookup('varnames', '^' + item.key + '$')" when: not lookup('varnames', '^' + item.key + '$')
with_dict: '{{ os_vars }}' with_dict: "{{ os_vars }}"
tags: always tags: always
- name: Import tasks for auditd - name: Import tasks for auditd
import_tasks: auditd.yml ansible.builtin.import_tasks: auditd.yml
tags: auditd tags: auditd
when: os_auditd_enabled | bool when: os_auditd_enabled | bool
- name: Import tasks for cron - name: Import tasks for cron
import_tasks: cron.yml ansible.builtin.import_tasks: cron.yml
tags: cron tags: cron
when: os_cron_enabled | bool when: os_cron_enabled | bool
- name: Import tasks to configure ctrl+alt+del - name: Import tasks to configure ctrl+alt+del
import_tasks: ctrlaltdel.yml ansible.builtin.import_tasks: ctrlaltdel.yml
tags: ctrlaltdel tags: ctrlaltdel
when: os_ctrlaltdel_disabled | bool when: os_ctrlaltdel_disabled | bool
- name: Import tasks to configure limits - name: Import tasks to configure limits
import_tasks: limits.yml ansible.builtin.import_tasks: limits.yml
tags: limits tags: limits
when: os_limits_enabled | bool when: os_limits_enabled | bool
- name: Import tasks to configure login_defs - name: Import tasks to configure login_defs
import_tasks: login_defs.yml ansible.builtin.import_tasks: login_defs.yml
tags: login_defs tags: login_defs
when: os_login_defs_enabled | bool when: os_login_defs_enabled | bool
- name: Import tasks to minimize access permissions - name: Import tasks to minimize access permissions
import_tasks: minimize_access.yml ansible.builtin.import_tasks: minimize_access.yml
tags: minimize_access tags: minimize_access
when: os_minimize_access_enabled | bool when: os_minimize_access_enabled | bool
- name: Import tasks to configure PAM - name: Import tasks to configure PAM
import_tasks: pam.yml ansible.builtin.import_tasks: pam.yml
tags: pam tags: pam
when: os_pam_enabled | bool when: os_pam_enabled | bool
- name: Import tasks to configure modules - name: Import tasks to configure modules
import_tasks: modprobe.yml ansible.builtin.import_tasks: modprobe.yml
tags: modprobe tags: modprobe
when: os_modprobe_enabled | bool when: os_modprobe_enabled | bool
- name: Import tasks to configure profile - name: Import tasks to configure profile
import_tasks: profile.yml ansible.builtin.import_tasks: profile.yml
tags: profile tags: profile
when: os_profile_enabled | bool when: os_profile_enabled | bool
- name: Import tasks to configure securetty - name: Import tasks to configure securetty
import_tasks: securetty.yml ansible.builtin.import_tasks: securetty.yml
tags: securetty tags: securetty
when: os_securetty_enabled | bool when: os_securetty_enabled | bool
- name: Import tasks to set suid and sgid - 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 when: os_security_suid_sgid_enforce | bool
tags: suid_sgid tags: suid_sgid
- name: Import tasks to configure sysctl - name: Import tasks to configure sysctl
import_tasks: sysctl.yml ansible.builtin.import_tasks: sysctl.yml
tags: sysctl tags: sysctl
when: os_sysctl_enabled | bool when: os_sysctl_enabled | bool
- name: Import tasks to harden user accounts - name: Import tasks to harden user accounts
import_tasks: user_accounts.yml ansible.builtin.import_tasks: user_accounts.yml
tags: user_accounts tags: user_accounts
when: os_user_accounts_enabled | bool when: os_user_accounts_enabled | bool
- name: Import tasks to configure rhosts - name: Import tasks to configure rhosts
import_tasks: rhosts.yml ansible.builtin.import_tasks: rhosts.yml
tags: rhosts tags: rhosts
when: os_rhosts_enabled | bool when: os_rhosts_enabled | bool
- name: Import tasks to configure netrc - name: Import tasks to configure netrc
import_tasks: netrc.yml ansible.builtin.import_tasks: netrc.yml
tags: netrc tags: netrc
when: os_netrc_enabled | bool when: os_netrc_enabled | bool
- name: Import tasks to configure yum - name: Import tasks to configure yum
import_tasks: yum.yml ansible.builtin.import_tasks: yum.yml
tags: yum tags: yum
when: when:
- ansible_facts.os_family == 'RedHat' - ansible_facts.os_family == 'RedHat'
- os_yum_enabled | bool - os_yum_enabled | bool
- name: Import tasks to configure apt - name: Import tasks to configure apt
import_tasks: apt.yml ansible.builtin.import_tasks: apt.yml
tags: apt tags: apt
when: when:
- ansible_facts.os_family == 'Debian' - ansible_facts.os_family == 'Debian'
- os_apt_enabled | bool - os_apt_enabled | bool
- name: Import tasks to configure selinux - name: Import tasks to configure selinux
import_tasks: selinux.yml ansible.builtin.import_tasks: selinux.yml
tags: selinux tags: selinux
when: when:
- ansible_facts.selinux.status == 'enabled' - ansible_facts.selinux.status == 'enabled'

View file

@ -3,35 +3,35 @@
when: not os_security_kernel_enable_core_dump | bool when: not os_security_kernel_enable_core_dump | bool
block: block:
- name: Create limits.d-directory if it does not exist | sysctl-31a, sysctl-31b - name: Create limits.d-directory if it does not exist | sysctl-31a, sysctl-31b
file: ansible.builtin.file:
path: '/etc/security/limits.d' path: /etc/security/limits.d
owner: 'root' owner: root
group: 'root' group: root
mode: '0755' mode: "0755"
state: 'directory' state: directory
- name: Create additional limits config file -> 10.hardcore.conf | sysctl-31a, sysctl-31b - name: Create additional limits config file -> 10.hardcore.conf | sysctl-31a, sysctl-31b
pam_limits: community.general.pam_limits:
dest: '/etc/security/limits.d/10.hardcore.conf' dest: /etc/security/limits.d/10.hardcore.conf
domain: '*' domain: "*"
limit_type: hard limit_type: hard
limit_item: core limit_item: core
value: '0' value: "0"
comment: Prevent core dumps for all users. These are usually not needed and may contain sensitive information 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 - name: Set 10.hardcore.conf perms to 0400 and root ownership
file: ansible.builtin.file:
path: /etc/security/limits.d/10.hardcore.conf path: /etc/security/limits.d/10.hardcore.conf
owner: 'root' owner: root
group: 'root' group: root
mode: '0440' mode: "0440"
state: touch state: touch
modification_time: preserve modification_time: preserve
access_time: preserve access_time: preserve
- name: Create coredump.conf.d-directory if it does not exist - name: Create coredump.conf.d-directory if it does not exist
file: ansible.builtin.file:
path: '/etc/systemd/coredump.conf.d' path: /etc/systemd/coredump.conf.d
owner: root owner: root
group: root group: root
mode: 0755 mode: 0755
@ -39,9 +39,9 @@
when: ansible_service_mgr == "systemd" when: ansible_service_mgr == "systemd"
- name: Create custom.conf for disabling coredumps - name: Create custom.conf for disabling coredumps
template: ansible.builtin.template:
src: 'etc/systemd/coredump.conf.d/coredumps.conf.j2' src: etc/systemd/coredump.conf.d/coredumps.conf.j2
dest: '/etc/systemd/coredump.conf.d/custom.conf' dest: /etc/systemd/coredump.conf.d/custom.conf
owner: root owner: root
group: root group: root
mode: 0644 mode: 0644
@ -52,13 +52,13 @@
when: os_security_kernel_enable_core_dump | bool when: os_security_kernel_enable_core_dump | bool
block: block:
- name: Remove coredump.conf.d directory with files - name: Remove coredump.conf.d directory with files
file: ansible.builtin.file:
path: /etc/systemd/coredump.conf.d path: /etc/systemd/coredump.conf.d
state: absent state: absent
when: ansible_service_mgr == "systemd" when: ansible_service_mgr == "systemd"
notify: Reload systemd notify: Reload systemd
- name: Remove 10.hardcore.conf config file - name: Remove 10.hardcore.conf config file
file: ansible.builtin.file:
path: /etc/security/limits.d/10.hardcore.conf path: /etc/security/limits.d/10.hardcore.conf
state: absent state: absent

View file

@ -1,8 +1,8 @@
--- ---
- name: Create login.defs | os-05, os-05b - name: Create login.defs | os-05, os-05b
template: ansible.builtin.template:
src: 'etc/login.defs.j2' src: etc/login.defs.j2
dest: '/etc/login.defs' dest: /etc/login.defs
owner: 'root' owner: root
group: 'root' group: root
mode: '0444' mode: "0444"

View file

@ -1,6 +1,6 @@
--- ---
- name: Include hardening tasks - name: Include hardening tasks
include_tasks: hardening.yml ansible.builtin.include_tasks: hardening.yml
when: os_hardening_enabled | bool when: os_hardening_enabled | bool
tags: tags:
- always - always

View file

@ -4,103 +4,193 @@
# still getting found and the permissions minimized in the next task. # 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. # 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 # also see: https://github.com/dev-sec/ansible-os-hardening/issues/219
- name: Find files with write-permissions for group - name: Find files with write-permissions for group # noqa command-instead-of-shell
shell: "find -L {{ item }} -perm /go+w -type f" # noqa command-instead-of-shell ansible.builtin.shell: find -L {{ item }} -perm /go+w -type f
with_community.general.flattened: with_community.general.flattened:
- '/usr/local/sbin' - /usr/local/sbin
- '/usr/local/bin' - /usr/local/bin
- '/usr/sbin' - /usr/sbin
- '/usr/bin' - /usr/bin
- '/sbin' - /sbin
- '/bin' - /bin
- "{{ os_env_extra_user_paths }}" # noqa deprecated-bare-vars - "{{ os_env_extra_user_paths }}"
register: minimize_access_directories register: minimize_access_directories
ignore_errors: true ignore_errors: true
changed_when: false changed_when: false
- name: Minimize access on found files - name: Minimize access on found files
file: ansible.builtin.file:
path: '{{ item.1 }}' path: "{{ item.1 }}"
mode: 'go-w' mode: go-w
state: file state: file
with_subelements: with_subelements:
- "{{ minimize_access_directories.results }}" - "{{ minimize_access_directories.results }}"
- stdout_lines - stdout_lines
- name: Find shadow files - name: Find shadow files
stat: ansible.builtin.stat:
path: "{{ item }}" path: "{{ item }}"
loop: loop:
- '/etc/shadow' - /etc/shadow
- '/etc/gshadow' - /etc/gshadow
- '/etc/shadow-' - /etc/shadow-
- '/etc/gshadow-' - /etc/gshadow-
register: minimize_access_shadow_files register: minimize_access_shadow_files
- name: Change shadow ownership to root and mode to 0600 | os-02 - name: Change shadow ownership to root and mode to 0600 | os-02
file: ansible.builtin.file:
dest: "{{ item.item }}" dest: "{{ item.item }}"
owner: '{{ os_shadow_perms.owner }}' owner: "{{ os_shadow_perms.owner }}"
group: '{{ os_shadow_perms.group }}' group: "{{ os_shadow_perms.group }}"
mode: '{{ os_shadow_perms.mode }}' mode: "{{ os_shadow_perms.mode }}"
when: item.stat.exists when: item.stat.exists
loop: "{{ minimize_access_shadow_files.results }}" loop: "{{ minimize_access_shadow_files.results }}"
- name: Find passwd files - name: Find passwd files
stat: ansible.builtin.stat:
path: "{{ item }}" path: "{{ item }}"
loop: loop:
- '/etc/passwd' - /etc/passwd
- '/etc/group' - /etc/group
- '/etc/passwd-' - /etc/passwd-
- '/etc/group-' - /etc/group-
register: minimize_access_passwd_files register: minimize_access_passwd_files
- name: Change passwd ownership to root and mode to 0644 | os-03 - name: Change passwd ownership to root and mode to 0644 | os-03
file: ansible.builtin.file:
dest: "{{ item.item }}" dest: "{{ item.item }}"
owner: '{{ os_passwd_perms.owner }}' owner: "{{ os_passwd_perms.owner }}"
group: '{{ os_passwd_perms.group }}' group: "{{ os_passwd_perms.group }}"
mode: '{{ os_passwd_perms.mode }}' mode: "{{ os_passwd_perms.mode }}"
when: item.stat.exists when: item.stat.exists
loop: "{{ minimize_access_passwd_files.results }}" loop: "{{ minimize_access_passwd_files.results }}"
- name: Change su-binary to only be accessible to user and group root - name: Change su-binary to only be accessible to user and group root
file: ansible.builtin.file:
dest: '/bin/su' dest: /bin/su
owner: 'root' owner: root
group: 'root' group: root
mode: '0750' mode: "0750"
when: '"change_user" not in os_security_users_allow' when: '"change_user" not in os_security_users_allow'
- name: Set option hidepid for proc filesystem - name: Set option hidepid for proc filesystem
mount: ansible.posix.mount:
path: /proc path: /proc
src: proc src: proc
fstype: proc fstype: proc
opts: '{{ proc_mnt_options }}' opts: "{{ proc_mnt_options }}"
state: mounted state: mounted
- name: Generate list of current available mounted filesystems on the system - 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 }}" mountpoints_list: "{{ ansible_mounts | map(attribute='mount') | list }}"
- name: Append special devices list to valid mountpoint list - name: Append special devices list to valid mountpoint list
set_fact: ansible.builtin.set_fact:
mountpoints_list: "{{ mountpoints_list + ['/dev', '/dev/shm', '/run'] }}" mountpoints_list: "{{ mountpoints_list + ['/dev', '/dev/shm', '/run'] }}"
- name: Minimize access for filesystems - name: Minimize access for filesystems
include_tasks: minimize_access_fs.yml ansible.builtin.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 }}" }
loop_control: loop_control:
loop_var: mount 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 }}"

View file

@ -1,29 +1,29 @@
--- ---
- name: Install modprobe to disable filesystems | os-10 - name: Install modprobe to disable filesystems | os-10
package: ansible.builtin.package:
name: '{{ modprobe_package }}' name: "{{ modprobe_package }}"
state: 'present' state: present
- name: Check if efi is installed - name: Check if efi is installed
stat: ansible.builtin.stat:
path: "/sys/firmware/efi" path: /sys/firmware/efi
register: efi_installed register: efi_installed
- name: Remove vfat from fs-list if efi is used - name: Remove vfat from fs-list if efi is used
set_fact: ansible.builtin.set_fact:
os_unused_filesystems: "{{ os_unused_filesystems | difference('vfat') }}" os_unused_filesystems: "{{ os_unused_filesystems | difference('vfat') }}"
when: when:
- efi_installed.stat.isdir is defined - efi_installed.stat.isdir is defined
- efi_installed.stat.isdir - efi_installed.stat.isdir
- name: Remove used filesystems from fs-list - 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) }}" os_unused_filesystems: "{{ os_unused_filesystems | difference(ansible_mounts | map(attribute='fstype') | list) }}"
- name: Disable unused filesystems | os-10 - name: Disable unused filesystems | os-10
template: ansible.builtin.template:
src: 'etc/modprobe.d/modprobe.j2' src: etc/modprobe.d/modprobe.j2
dest: '/etc/modprobe.d/dev-sec.conf' dest: /etc/modprobe.d/dev-sec.conf
owner: 'root' owner: root
group: 'root' group: root
mode: '0644' mode: "0644"

View file

@ -1,13 +1,13 @@
--- ---
- name: Get user accounts | os-09 - 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 changed_when: false
check_mode: false check_mode: false
register: users_accounts register: users_accounts
- name: Delete .netrc-files from system | os-09 - name: Delete .netrc-files from system | os-09
file: ansible.builtin.file:
dest: '~{{ item }}/.netrc' dest: ~{{ item }}/.netrc
state: 'absent' state: absent
loop: '{{ users_accounts.stdout_lines | flatten | default([]) }}' loop: "{{ users_accounts.stdout_lines | flatten | default([]) }}"
when: item not in os_netrc_whitelist_user when: item not in os_netrc_whitelist_user

View file

@ -1,6 +1,6 @@
--- ---
- name: Gather package facts - name: Gather package facts
package_facts: ansible.builtin.package_facts:
manager: auto manager: auto
when: when:
- ansible_facts.os_family != 'Suse' - ansible_facts.os_family != 'Suse'
@ -11,29 +11,29 @@
# normally caching credentials shouldn't be necessary for most machines. # normally caching credentials shouldn't be necessary for most machines.
# removing it provides some more security while not removing usability. # removing it provides some more security while not removing usability.
- name: Remove pam ccreds to disable password caching - name: Remove pam ccreds to disable password caching
package: ansible.builtin.package:
name: '{{ os_packages_pam_ccreds }}' name: "{{ os_packages_pam_ccreds }}"
state: 'absent' state: absent
when: when:
- ansible_facts.os_family != 'Archlinux' - ansible_facts.os_family != 'Archlinux'
- name: Import tasks for Debian PAM - name: Import tasks for Debian PAM
import_tasks: pam_debian.yml ansible.builtin.import_tasks: pam_debian.yml
when: when:
- ansible_facts.os_family == 'Debian' - ansible_facts.os_family == 'Debian'
- name: Import tasks for RedHat PAM - name: Import tasks for RedHat PAM
import_tasks: pam_rhel.yml ansible.builtin.import_tasks: pam_rhel.yml
when: when:
- ansible_facts.os_family == 'RedHat' - ansible_facts.os_family == 'RedHat'
- name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512 - name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512
template: ansible.builtin.template:
src: 'etc/libuser.conf.j2' src: etc/libuser.conf.j2
dest: '/etc/libuser.conf' dest: /etc/libuser.conf
mode: '0640' mode: "0640"
owner: 'root' owner: root
group: 'root' group: root
when: when:
- ansible_facts.os_family != 'Suse' - ansible_facts.os_family != 'Suse'
- ansible_facts.os_family != 'Archlinux' - ansible_facts.os_family != 'Archlinux'

View file

@ -1,120 +1,120 @@
--- ---
- name: Install the package for strong password checking - name: Install the package for strong password checking
apt: ansible.builtin.apt:
name: 'libpam-passwdqc' name: libpam-passwdqc
state: 'present' state: present
update_cache: 'yes' update_cache: true
when: when:
- os_auth_pam_passwdqc_enable - os_auth_pam_passwdqc_enable
- name: Configure passwdqc - name: Configure passwdqc
template: ansible.builtin.template:
src: 'usr/share/pam-configs/pam_passwdqc.j2' src: usr/share/pam-configs/pam_passwdqc.j2
dest: '{{ passwdqc_path }}' dest: "{{ passwdqc_path }}"
mode: '0644' mode: "0644"
owner: 'root' owner: root
group: 'root' group: root
when: when:
- os_auth_pam_passwdqc_enable - os_auth_pam_passwdqc_enable
- name: Install tally2 - name: Install tally2
apt: ansible.builtin.apt:
name: 'libpam-modules' name: libpam-modules
state: 'present' state: present
when: when:
- os_auth_retries|int > 0 - os_auth_retries|int > 0
- name: Manage tally on Debian stable - name: Manage tally on Debian stable
when: when:
- "'libpam-modules' in ansible_facts.packages" - "'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: block:
- name: Configure tally2 - name: Configure tally2
template: ansible.builtin.template:
src: 'usr/share/pam-configs/pam_tally2.j2' src: usr/share/pam-configs/pam_tally2.j2
dest: '{{ tally2_path }}' dest: "{{ tally2_path }}"
mode: '0644' mode: "0644"
owner: 'root' owner: root
group: 'root' group: root
when: when:
- os_auth_retries|int > 0 - os_auth_retries|int > 0
- name: Delete tally2 when retries is 0 - name: Delete tally2 when retries is 0
file: ansible.builtin.file:
path: '{{ tally2_path }}' path: "{{ tally2_path }}"
state: 'absent' state: absent
when: when:
- os_auth_retries|int == 0 - os_auth_retries|int == 0
- name: Manage tally/faillock on Debian unstable - name: Manage tally/faillock on Debian unstable
when: when:
- "'libpam-modules' in ansible_facts.packages" - "'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: block:
- name: Delete tally2 - name: Delete tally2
file: ansible.builtin.file:
path: '{{ tally2_path }}' path: "{{ tally2_path }}"
state: 'absent' state: absent
- name: Create tally directory - name: Create tally directory
file: ansible.builtin.file:
path: '/var/run/faillock' path: /var/run/faillock
state: 'directory' state: directory
mode: '0755' mode: "0755"
owner: 'root' owner: root
group: 'root' group: root
- name: Configure faillock - name: Configure faillock
template: ansible.builtin.template:
src: 'etc/security/faillock.conf.j2' src: etc/security/faillock.conf.j2
dest: '/etc/security/faillock.conf' dest: /etc/security/faillock.conf
mode: '0644' mode: "0644"
owner: 'root' owner: root
group: 'root' group: root
- name: Configure faillock pam - name: Configure faillock pam
template: ansible.builtin.template:
src: 'usr/share/pam-configs/pam_faillock.j2' src: usr/share/pam-configs/pam_faillock.j2
dest: '/usr/share/pam-configs/faillock' dest: /usr/share/pam-configs/faillock
mode: '0644' mode: "0644"
owner: 'root' owner: root
group: 'root' group: root
when: when:
- os_auth_retries|int > 0 - os_auth_retries|int > 0
- name: Configure faillock pam authfail - name: Configure faillock pam authfail
template: ansible.builtin.template:
src: 'usr/share/pam-configs/pam_faillock_authfail.j2' src: usr/share/pam-configs/pam_faillock_authfail.j2
dest: '/usr/share/pam-configs/faillock_authfail' dest: /usr/share/pam-configs/faillock_authfail
mode: '0644' mode: "0644"
owner: 'root' owner: root
group: 'root' group: root
when: when:
- os_auth_retries|int > 0 - os_auth_retries|int > 0
- name: Delete faillock when retries is 0 - name: Delete faillock when retries is 0
file: ansible.builtin.file:
path: '/usr/share/pam-configs/faillock' path: /usr/share/pam-configs/faillock
state: 'absent' state: absent
when: when:
- os_auth_retries|int == 0 - os_auth_retries|int == 0
- name: Delete faillock authfail when retries is 0 - name: Delete faillock authfail when retries is 0
file: ansible.builtin.file:
path: '/usr/share/pam-configs/faillock_authfail' path: /usr/share/pam-configs/faillock_authfail
state: 'absent' state: absent
when: when:
- os_auth_retries|int == 0 - os_auth_retries|int == 0
- name: Update pam on Debian systems - name: Update pam on Debian systems
command: 'pam-auth-update --package' ansible.builtin.command: pam-auth-update --package
environment: environment:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
changed_when: false changed_when: false
- name: Remove passwdqc - name: Remove passwdqc
apt: ansible.builtin.apt:
name: 'libpam-passwdqc' name: libpam-passwdqc
state: 'absent' state: absent
when: when:
- not os_auth_pam_passwdqc_enable - not os_auth_pam_passwdqc_enable

View file

@ -1,43 +1,43 @@
--- ---
- name: Install sssd-clients - name: Install sssd-clients
yum: ansible.builtin.yum:
name: sssd-client name: sssd-client
state: 'present' state: present
when: when:
- os_auth_pam_sssd_enable | bool - os_auth_pam_sssd_enable | bool
- name: Configure passwdqc and faillock via central system-auth config - name: Configure passwdqc and faillock via central system-auth config
template: ansible.builtin.template:
src: 'etc/pam.d/rhel_auth.j2' src: etc/pam.d/rhel_auth.j2
dest: '/etc/pam.d/system-auth-local' dest: /etc/pam.d/system-auth-local
mode: '0640' mode: "0640"
owner: 'root' owner: root
group: 'root' group: root
- name: Enable our config for system-auth - name: Enable our config for system-auth
file: ansible.builtin.file:
src: /etc/pam.d/system-auth-local src: /etc/pam.d/system-auth-local
dest: /etc/pam.d/system-auth dest: /etc/pam.d/system-auth
mode: '0640' mode: "0640"
owner: 'root' owner: root
group: 'root' group: root
state: link state: link
force: true force: true
- name: Configure passwdqc and faillock via central password-auth config - name: Configure passwdqc and faillock via central password-auth config
template: ansible.builtin.template:
src: 'etc/pam.d/rhel_auth.j2' src: etc/pam.d/rhel_auth.j2
dest: '/etc/pam.d/password-auth-local' dest: /etc/pam.d/password-auth-local
mode: '0640' mode: "0640"
owner: 'root' owner: root
group: 'root' group: root
- name: Enable our config for password-auth - name: Enable our config for password-auth
file: ansible.builtin.file:
src: /etc/pam.d/password-auth-local src: /etc/pam.d/password-auth-local
dest: /etc/pam.d/password-auth dest: /etc/pam.d/password-auth
mode: '0640' mode: "0640"
owner: 'root' owner: root
group: 'root' group: root
state: link state: link
force: true force: true

View file

@ -1,23 +1,23 @@
--- ---
- name: Add pinerolo_profile.sh to profile.d - name: Add pinerolo_profile.sh to profile.d
template: ansible.builtin.template:
src: 'etc/profile.d/profile.conf.j2' src: etc/profile.d/profile.conf.j2
dest: '/etc/profile.d/pinerolo_profile.sh' dest: /etc/profile.d/pinerolo_profile.sh
owner: 'root' owner: root
group: 'root' group: root
mode: '0750' mode: "0750"
when: not os_security_kernel_enable_core_dump | bool when: not os_security_kernel_enable_core_dump | bool
- name: Remove pinerolo_profile.sh from profile.d - name: Remove pinerolo_profile.sh from profile.d
file: ansible.builtin.file:
path: /etc/profile.d/pinerolo_profile.sh path: /etc/profile.d/pinerolo_profile.sh
state: absent state: absent
when: os_security_kernel_enable_core_dump | bool when: os_security_kernel_enable_core_dump | bool
- name: Add autologout to profile env - name: Add autologout to profile env
template: ansible.builtin.template:
src: 'etc/profile.d/tmout.sh.j2' src: etc/profile.d/tmout.sh.j2
dest: '/etc/profile.d/tmout.sh' dest: /etc/profile.d/tmout.sh
owner: 'root' owner: root
group: 'root' group: root
mode: '0644' mode: "0644"

View file

@ -1,17 +1,17 @@
--- ---
- name: Get user accounts | os-09 - 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 changed_when: false
check_mode: false check_mode: false
register: users_accounts register: users_accounts
- name: Delete rhosts-files from system | os-09 - name: Delete rhosts-files from system | os-09
file: ansible.builtin.file:
dest: '~{{ item }}/.rhosts' dest: ~{{ item }}/.rhosts
state: 'absent' state: absent
loop: '{{ users_accounts.stdout_lines | flatten | default([]) }}' loop: "{{ users_accounts.stdout_lines | flatten | default([]) }}"
- name: Delete hosts.equiv from system | os-01 - name: Delete hosts.equiv from system | os-01
file: ansible.builtin.file:
dest: '/etc/hosts.equiv' dest: /etc/hosts.equiv
state: 'absent' state: absent

View file

@ -1,8 +1,8 @@
--- ---
- name: Create securetty - name: Create securetty
template: ansible.builtin.template:
src: 'etc/securetty.j2' src: etc/securetty.j2
dest: '/etc/securetty' dest: /etc/securetty
owner: 'root' owner: root
group: 'root' group: root
mode: '0400' mode: "0400"

View file

@ -1,5 +1,5 @@
--- ---
- name: Configure selinux | selinux-01 - name: Configure selinux | selinux-01
selinux: ansible.posix.selinux:
policy: "{{ os_selinux_policy }}" policy: "{{ os_selinux_policy }}"
state: "{{ os_selinux_state }}" state: "{{ os_selinux_state }}" # noqa args - see https://github.com/ansible/ansible-lint/issues/2930

View file

@ -1,32 +1,32 @@
--- ---
- name: Remove suid/sgid bit from binaries in blacklist | os-06 - name: Remove suid/sgid bit from binaries in blacklist | os-06
file: ansible.builtin.file:
path: '{{ item }}' path: "{{ item }}"
mode: 'a-s' mode: a-s
state: 'file' state: file
follow: 'yes' follow: true
failed_when: false failed_when: false
with_community.general.flattened: with_community.general.flattened:
- '{{ os_security_suid_sgid_system_blacklist }}' - "{{ os_security_suid_sgid_system_blacklist }}"
- '{{ os_security_suid_sgid_blacklist }}' - "{{ os_security_suid_sgid_blacklist }}"
- name: Find binaries with suid/sgid set | os-06 - 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 register: sbit_binaries
when: os_security_suid_sgid_remove_from_unknown | bool when: os_security_suid_sgid_remove_from_unknown | bool
changed_when: false changed_when: false
- name: Gather files from which to remove suids/sgids and remove system white-listed files | os-06 - name: Gather files from which to remove suids/sgids and remove system white-listed files | os-06
set_fact: ansible.builtin.set_fact:
suid: '{{ sbit_binaries.stdout_lines | difference(os_security_suid_sgid_system_whitelist) }}' suid: "{{ sbit_binaries.stdout_lines | difference(os_security_suid_sgid_system_whitelist) }}"
when: os_security_suid_sgid_remove_from_unknown | bool 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 - name: Remove suid/sgid bit from all binaries except in system and user whitelist | os-06
file: ansible.builtin.file:
path: '{{ item }}' path: "{{ item }}"
mode: 'a-s' mode: a-s
state: 'file' state: file
follow: 'yes' follow: true
with_community.general.flattened: 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 when: os_security_suid_sgid_remove_from_unknown | bool

View file

@ -1,39 +1,39 @@
--- ---
- name: Protect sysctl.conf - name: Protect sysctl.conf
file: ansible.builtin.file:
path: '/etc/sysctl.conf' path: /etc/sysctl.conf
owner: 'root' owner: root
group: 'root' group: root
mode: '0440' mode: "0440"
state: touch state: touch
modification_time: preserve modification_time: preserve
access_time: preserve access_time: preserve
- name: Set Daemon umask, do config for rhel-family | NSA 2.2.4.1 - name: Set Daemon umask, do config for rhel-family | NSA 2.2.4.1
template: ansible.builtin.template:
src: 'etc/sysconfig/rhel_sysconfig_init.j2' src: etc/sysconfig/rhel_sysconfig_init.j2
dest: '/etc/sysconfig/init' dest: /etc/sysconfig/init
owner: 'root' owner: root
group: 'root' group: root
mode: '0544' mode: "0544"
when: ansible_facts.os_family == 'RedHat' when: ansible_facts.os_family == 'RedHat'
- name: Install initramfs-tools - name: Install initramfs-tools
apt: ansible.builtin.apt:
name: 'initramfs-tools' name: initramfs-tools
state: 'present' state: present
update_cache: true update_cache: true
when: when:
- ansible_facts.os_family == 'Debian' - ansible_facts.os_family == 'Debian'
- os_security_kernel_enable_module_loading - os_security_kernel_enable_module_loading
- name: Rebuild initramfs with starting pack of modules, if module loading at runtime is disabled - name: Rebuild initramfs with starting pack of modules, if module loading at runtime is disabled
template: ansible.builtin.template:
src: 'etc/initramfs-tools/modules.j2' src: etc/initramfs-tools/modules.j2
dest: '/etc/initramfs-tools/modules' dest: /etc/initramfs-tools/modules
owner: 'root' owner: root
group: 'root' group: root
mode: '0440' mode: "0440"
notify: notify:
- Update-initramfs - Update-initramfs
when: when:
@ -45,37 +45,37 @@
when: ansible_virtualization_type not in ['docker', 'lxc', 'openvz'] when: ansible_virtualization_type not in ['docker', 'lxc', 'openvz']
block: block:
- name: Create a combined sysctl-dict if os-dependent sysctls are defined - name: Create a combined sysctl-dict if os-dependent sysctls are defined
set_fact: ansible.builtin.set_fact:
sysctl_config: '{{ sysctl_config | combine(sysctl_custom_config) }}' sysctl_config: "{{ sysctl_config | combine(sysctl_custom_config) }}"
when: sysctl_custom_config | default() when: sysctl_custom_config | default()
# sysctl_rhel_config is kept for backwards-compatibility. use sysctl_custom_config instead # 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 - name: Create a combined sysctl-dict if os-dependent sysctls are defined
set_fact: ansible.builtin.set_fact:
sysctl_config: '{{ sysctl_config | combine(sysctl_rhel_config) }}' sysctl_config: "{{ sysctl_config | combine(sysctl_rhel_config) }}"
when: sysctl_rhel_config | default() when: sysctl_rhel_config | default()
- name: Create a combined sysctl-dict if overwrites are defined - name: Create a combined sysctl-dict if overwrites are defined
set_fact: ansible.builtin.set_fact:
sysctl_config: '{{ sysctl_config | combine(sysctl_overwrite) }}' sysctl_config: "{{ sysctl_config | combine(sysctl_overwrite) }}"
when: sysctl_overwrite | default() when: sysctl_overwrite | default()
- name: Change various sysctl-settings, look at the sysctl-vars file for documentation - name: Change various sysctl-settings, look at the sysctl-vars file for documentation
sysctl: ansible.posix.sysctl:
name: '{{ item.key }}' name: "{{ item.key }}"
value: '{{ item.value }}' value: "{{ item.value }}"
sysctl_set: true sysctl_set: true
state: present state: present
reload: true reload: true
ignoreerrors: true ignoreerrors: true
with_dict: '{{ sysctl_config }}' with_dict: "{{ sysctl_config }}"
when: item.key not in sysctl_unsupported_entries | default() when: item.key not in sysctl_unsupported_entries | default()
- name: Apply ufw defaults - name: Apply ufw defaults
template: ansible.builtin.template:
src: 'etc/default/ufw.j2' src: etc/default/ufw.j2
dest: '/etc/default/ufw' dest: /etc/default/ufw
mode: '0644' mode: "0644"
when: when:
- ufw_manage_defaults - ufw_manage_defaults
- ansible_facts.os_family == 'Debian' - ansible_facts.os_family == 'Debian'

View file

@ -1,12 +1,12 @@
--- ---
- name: Read local linux user database - name: Read local linux user database
getent: ansible.builtin.getent:
database: passwd database: passwd
# creates a dict for each user containing UID/HOMEDIR etc... # creates a dict for each user containing UID/HOMEDIR etc...
when: getent_passwd is undefined # skip this task if "getent" has run before when: getent_passwd is undefined # skip this task if "getent" has run before
- name: Read local linux shadow database - name: Read local linux shadow database
getent: ansible.builtin.getent:
database: shadow database: shadow
- name: Extract regular (non-system, non-root) accounts from local user database - name: Extract regular (non-system, non-root) accounts from local user database
@ -36,11 +36,11 @@
loop: "{{ getent_passwd.keys() | list }}" loop: "{{ getent_passwd.keys() | list }}"
when: when:
- getent_passwd[item][1]|int == 0 - getent_passwd[item][1]|int == 0
set_fact: ansible.builtin.set_fact:
root_users: "{{ root_users | default([]) + [item] }}" root_users: "{{ root_users | default([]) + [item] }}"
- name: Set ownership of root user home directory(s) to 0700 - name: Set ownership of root user home directory(s) to 0700
file: ansible.builtin.file:
mode: 0700 mode: 0700
owner: "{{ item }}" owner: "{{ item }}"
path: "{{ getent_passwd[item][4] }}" path: "{{ getent_passwd[item][4] }}"
@ -50,7 +50,7 @@
- os_chmod_rootuser_home_folder | bool - os_chmod_rootuser_home_folder | bool
- name: Set password ageing for root user(s) - name: Set password ageing for root user(s)
user: ansible.builtin.user:
name: "{{ item }}" name: "{{ item }}"
password_expire_min: "{{ os_auth_pw_min_age }}" password_expire_min: "{{ os_auth_pw_min_age }}"
password_expire_max: "{{ os_auth_pw_max_age }}" password_expire_max: "{{ os_auth_pw_max_age }}"
@ -61,7 +61,7 @@
- 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) - name: Remove additional users with UID=0 ("root" user is not touched)
user: ansible.builtin.user:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
loop: "{{ root_users }}" loop: "{{ root_users }}"
@ -71,7 +71,7 @@
- item != "root" - item != "root"
- name: Get UID_MIN from login.defs - 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: args:
removes: /etc/login.defs removes: /etc/login.defs
register: uid_min register: uid_min
@ -79,24 +79,24 @@
changed_when: false changed_when: false
- name: Calculate UID_MAX from UID_MIN by substracting 1 - name: Calculate UID_MAX from UID_MIN by substracting 1
set_fact: ansible.builtin.set_fact:
uid_max: '{{ uid_min.stdout | int - 1 }}' uid_max: "{{ uid_min.stdout | int - 1 }}"
when: uid_min.stdout|int > 0 when: uid_min.stdout|int > 0
- name: Set UID_MAX on Debian-systems if no login.defs exist - name: Set UID_MAX on Debian-systems if no login.defs exist
set_fact: ansible.builtin.set_fact:
uid_max: '999' uid_max: "999"
when: when:
- ansible_facts.os_family == 'Debian' - ansible_facts.os_family == 'Debian'
- uid_max is not defined - uid_max is not defined
- name: Set UID_MAX on other systems if no login.defs exist - name: Set UID_MAX on other systems if no login.defs exist
set_fact: ansible.builtin.set_fact:
uid_max: '499' uid_max: "499"
when: uid_max is not defined when: uid_max is not defined
- name: Get all system accounts - 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: args:
removes: /etc/passwd removes: /etc/passwd
changed_when: false changed_when: false
@ -104,21 +104,21 @@
register: sys_accs register: sys_accs
- name: Remove always ignored system accounts from list - name: Remove always ignored system accounts from list
set_fact: ansible.builtin.set_fact:
sys_accs_cond: '{{ sys_accs.stdout_lines | difference(os_always_ignore_users) }}' sys_accs_cond: "{{ sys_accs.stdout_lines | difference(os_always_ignore_users) }}"
check_mode: false check_mode: false
- name: Change system accounts not on the user provided ignore-list - name: Change system accounts not on the user provided ignore-list
user: ansible.builtin.user:
name: '{{ item }}' name: "{{ item }}"
shell: '{{ os_nologin_shell_path }}' shell: "{{ os_nologin_shell_path }}"
password: '*' password: "*"
createhome: false createhome: false
with_community.general.flattened: 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 - name: Get all home directories in /home, but skip ignored users
find: ansible.builtin.find:
paths: /home/ paths: /home/
recurse: false recurse: false
file_type: directory file_type: directory
@ -127,7 +127,7 @@
when: os_chmod_home_folders | bool when: os_chmod_home_folders | bool
- name: Set ownership of /home directories to 0700 - name: Set ownership of /home directories to 0700
file: ansible.builtin.file:
mode: 0700 mode: 0700
path: "{{ item.path }}" path: "{{ item.path }}"
state: directory state: directory

View file

@ -1,50 +1,51 @@
--- ---
- name: Remove unused repositories - name: Remove unused repositories
file: ansible.builtin.file:
name: '/etc/yum.repos.d/{{ item }}.repo' name: /etc/yum.repos.d/{{ item }}.repo
state: 'absent' state: absent
loop: loop:
- 'CentOS-Debuginfo' - CentOS-Debuginfo
- 'CentOS-Media' - CentOS-Media
- 'CentOS-Vault' - CentOS-Vault
when: os_security_packages_clean | bool when: os_security_packages_clean | bool
- name: Get yum repository files - name: Get yum repository files
find: ansible.builtin.find:
paths: '/etc/yum.repos.d' paths: /etc/yum.repos.d
patterns: '*.repo' patterns: "*.repo"
register: yum_repos register: yum_repos
# for the 'default([])' see here: # for the 'default([])' see here:
# https://github.com/dev-sec/ansible-os-hardening/issues/99 and # 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 # https://stackoverflow.com/questions/37067827/ansible-deprecation-warning-for-undefined-variable-despite-when-clause
- name: Activate gpg-check for yum repository files - name: Activate gpg-check for yum repository files
replace: ansible.builtin.replace:
path: '{{ item }}' path: "{{ item }}"
regexp: '^\s*gpgcheck.*' regexp: ^\s*gpgcheck.*
replace: 'gpgcheck=1' replace: gpgcheck=1
mode: '0644' mode: "0644"
with_items: 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) }}" - "{{ 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. # 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. # 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. # All other errors will still be raised.
- name: Activate gpg-check for config files - name: Activate gpg-check for config files
replace: ansible.builtin.replace:
path: '{{ item }}' path: "{{ item }}"
regexp: '^\s*gpgcheck\W.*' regexp: ^\s*gpgcheck\W.*
replace: 'gpgcheck=1' replace: gpgcheck=1
mode: '0644' mode: "0644"
register: status register: status
failed_when: status.rc is defined and status.rc not in (257, 0) failed_when: status.rc is defined and status.rc not in (257, 0)
loop: loop:
- '/etc/yum.conf' - /etc/yum.conf
- '/etc/dnf/dnf.conf' - /etc/dnf/dnf.conf
- '/etc/yum/pluginconf.d/rhnplugin.conf' - /etc/yum/pluginconf.d/rhnplugin.conf
- name: Remove deprecated or insecure packages | package-01 - package-09 - name: Remove deprecated or insecure packages | package-01 - package-09
yum: ansible.builtin.yum:
name: '{{ os_security_packages_list }}' name: "{{ os_security_packages_list }}"
state: 'absent' state: absent
when: os_security_packages_clean | bool when: os_security_packages_clean | bool

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: pam_ccreds
os_packages_pam_ccreds: 'pam_ccreds' os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: root group: root
mode: '0000' mode: "0000"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '077' os_env_umask: "077"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -79,10 +78,9 @@ os_mnt_var_tmp_owner: 'root'
os_useradd_mail_dir: /var/spool/mail os_useradd_mail_dir: /var/spool/mail
os_useradd_create_home: true os_useradd_create_home: true
modprobe_package: 'module-init-tools' modprobe_package: module-init-tools
auditd_package: 'audit' auditd_package: audit
# system accounts that do not get their login disabled and pasword changed # system accounts that do not get their login disabled and pasword changed
os_always_ignore_users: ['root', 'sync', 'shutdown', 'halt', 'ec2-user'] os_always_ignore_users: [root, sync, shutdown, halt, ec2-user]
hidepid_option: "2" # allowed values: 0, 1, 2
hidepid_option: '2' # allowed values: 0, 1, 2

View file

@ -1,18 +1,17 @@
--- ---
os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
os_shadow_perms: os_shadow_perms:
owner: root owner: root
group: root group: root
mode: '0600' mode: "0600"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '027' os_env_umask: "027"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 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_group: 'root'
os_mnt_var_tmp_owner: 'root' os_mnt_var_tmp_owner: 'root'
modprobe_package: 'kmod' modprobe_package: kmod
auditd_package: 'audit' auditd_package: audit
hidepid_option: '2' # allowed values: 0, 1, 2 hidepid_option: "2" # allowed values: 0, 1, 2
sysctl_custom_config: sysctl_custom_config:
# Mitigation of vulnerability CVE-2021-33909 # Mitigation of vulnerability CVE-2021-33909

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: libpam-ccreds
os_packages_pam_ccreds: 'libpam-ccreds' os_nologin_shell_path: /usr/sbin/nologin
os_nologin_shell_path: '/usr/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: shadow group: shadow
mode: '0640' mode: "0640"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '027' os_env_umask: "027"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -76,13 +75,13 @@ os_mnt_var_tmp_owner: 'root'
# defaults for useradd # defaults for useradd
os_useradd_mail_dir: /var/mail os_useradd_mail_dir: /var/mail
modprobe_package: 'kmod' modprobe_package: kmod
auditd_package: 'auditd' auditd_package: auditd
tally2_path: '/usr/share/pam-configs/tally2' tally2_path: /usr/share/pam-configs/tally2
passwdqc_path: '/usr/share/pam-configs/passwdqc' 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: sysctl_custom_config:
# Mitigation of vulnerability CVE-2021-33909 # Mitigation of vulnerability CVE-2021-33909

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: pam_ccreds
os_packages_pam_ccreds: 'pam_ccreds' os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: root group: root
mode: '0000' mode: "0000"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '027' os_env_umask: "027"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -79,7 +78,7 @@ os_mnt_var_tmp_owner: 'root'
os_useradd_mail_dir: /var/spool/mail os_useradd_mail_dir: /var/spool/mail
os_useradd_create_home: true os_useradd_create_home: true
modprobe_package: 'module-init-tools' modprobe_package: module-init-tools
auditd_package: 'audit' auditd_package: audit
hidepid_option: '2' # allowed values: 0, 1, 2 hidepid_option: "2" # allowed values: 0, 1, 2

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: pam_ccreds
os_packages_pam_ccreds: 'pam_ccreds' os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: root group: root
mode: '0000' mode: "0000"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '077' os_env_umask: "077"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -79,7 +78,7 @@ os_mnt_var_tmp_owner: 'root'
os_useradd_mail_dir: /var/spool/mail os_useradd_mail_dir: /var/spool/mail
os_useradd_create_home: true os_useradd_create_home: true
modprobe_package: 'module-init-tools' modprobe_package: module-init-tools
auditd_package: 'audit' auditd_package: audit
hidepid_option: '2' # allowed values: 0, 1, 2 hidepid_option: "2" # allowed values: 0, 1, 2

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: pam_ccreds
os_packages_pam_ccreds: 'pam_ccreds' os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: root group: root
mode: '0000' mode: "0000"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '077' os_env_umask: "077"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -79,11 +78,11 @@ os_mnt_var_tmp_owner: 'root'
os_useradd_mail_dir: /var/spool/mail os_useradd_mail_dir: /var/spool/mail
os_useradd_create_home: true os_useradd_create_home: true
modprobe_package: 'module-init-tools' modprobe_package: module-init-tools
auditd_package: 'audit' auditd_package: audit
hidepid_option: '0' # allowed values: 0, 1, 2 hidepid_option: "0" # allowed values: 0, 1, 2
sysctl_unsupported_entries: sysctl_unsupported_entries:
- 'fs.protected_fifos' - fs.protected_fifos
- 'fs.protected_regular' - fs.protected_regular

View file

@ -1,7 +1,6 @@
--- ---
os_packages_pam_ccreds: pam_ccreds
os_packages_pam_ccreds: 'pam_ccreds' os_nologin_shell_path: /sbin/nologin
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g. # Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640. # 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: os_shadow_perms:
owner: root owner: root
group: shadow group: shadow
mode: '0640' mode: "0640"
os_passwd_perms: os_passwd_perms:
owner: root owner: root
group: root group: root
mode: '0644' mode: "0644"
os_env_umask: '027' os_env_umask: "027"
os_auth_uid_min: 1000 os_auth_uid_min: 1000
os_auth_uid_max: 60000 os_auth_uid_max: 60000
@ -76,7 +75,7 @@ os_mnt_var_tmp_owner: 'root'
# defaults for useradd # defaults for useradd
os_useradd_create_home: false os_useradd_create_home: false
modprobe_package: 'kmod-compat' modprobe_package: kmod-compat
auditd_package: 'audit' auditd_package: audit
hidepid_option: '2' # allowed values: 0, 1, 2 hidepid_option: "2" # allowed values: 0, 1, 2

View file

@ -11,102 +11,102 @@
# list of suid/sgid entries that must be removed # list of suid/sgid entries that must be removed
os_security_suid_sgid_system_blacklist: os_security_suid_sgid_system_blacklist:
# blacklist as provided by NSA # blacklist as provided by NSA
- '/usr/bin/rcp' - /usr/bin/rcp
- '/usr/bin/rlogin' - /usr/bin/rlogin
- '/usr/bin/rsh' - /usr/bin/rsh
# sshd must not use host-based authentication (see ssh cookbook) # sshd must not use host-based authentication (see ssh cookbook)
- '/usr/libexec/openssh/ssh-keysign' - /usr/libexec/openssh/ssh-keysign
- '/usr/lib/openssh/ssh-keysign' - /usr/lib/openssh/ssh-keysign
# misc others # misc others
- '/sbin/netreport' # not normally required for user - /sbin/netreport # not normally required for user
- '/usr/sbin/usernetctl' # modify interfaces via functional accounts - /usr/sbin/usernetctl # modify interfaces via functional accounts
# connecting to ... # connecting to ...
- '/usr/sbin/userisdnctl' # no isdn... - /usr/sbin/userisdnctl # no isdn...
- '/usr/sbin/pppd' # no ppp / dsl ... - /usr/sbin/pppd # no ppp / dsl ...
# lockfile # lockfile
- '/usr/bin/lockfile' - /usr/bin/lockfile
- '/usr/bin/mail-lock' - /usr/bin/mail-lock
- '/usr/bin/mail-unlock' - /usr/bin/mail-unlock
- '/usr/bin/mail-touchlock' - /usr/bin/mail-touchlock
- '/usr/bin/dotlockfile' - /usr/bin/dotlockfile
# need more investigation blacklist for now # need more investigation blacklist for now
- '/usr/bin/arping' - /usr/bin/arping
- '/usr/sbin/uuidd' - /usr/sbin/uuidd
- '/usr/bin/mtr' # investigate current state... - /usr/bin/mtr # investigate current state...
- '/usr/lib/evolution/camel-lock-helper-1.2' # investigate current state... - /usr/lib/evolution/camel-lock-helper-1.2 # investigate current state...
- '/usr/lib/pt_chown' # pseudo-tty needed? - /usr/lib/pt_chown # pseudo-tty needed?
- '/usr/lib/eject/dmcrypt-get-device' - /usr/lib/eject/dmcrypt-get-device
- '/usr/lib/mc/cons.saver' # midnight commander screensaver - /usr/lib/mc/cons.saver # midnight commander screensaver
# list of suid/sgid entries that can remain untouched # list of suid/sgid entries that can remain untouched
os_security_suid_sgid_system_whitelist: os_security_suid_sgid_system_whitelist:
# whitelist as provided by NSA # whitelist as provided by NSA
- '/bin/mount' - /bin/mount
- '/bin/ping' - /bin/ping
- '/bin/su' - /bin/su
- '/usr/bin/su' - /usr/bin/su
- '/bin/umount' - /bin/umount
- '/sbin/pam_timestamp_check' - /sbin/pam_timestamp_check
- '/sbin/unix_chkpwd' - /sbin/unix_chkpwd
- '/usr/bin/at' - /usr/bin/at
- '/usr/bin/gpasswd' - /usr/bin/gpasswd
- '/usr/bin/locate' - /usr/bin/locate
- '/usr/bin/newgrp' - /usr/bin/newgrp
- '/usr/bin/passwd' - /usr/bin/passwd
- '/usr/bin/ssh-agent' - /usr/bin/ssh-agent
- '/usr/libexec/utempter/utempter' - /usr/libexec/utempter/utempter
- '/usr/sbin/lockdev' - /usr/sbin/lockdev
- '/usr/sbin/sendmail.sendmail' - /usr/sbin/sendmail.sendmail
- '/usr/bin/expiry' - /usr/bin/expiry
# whitelist ipv6 # whitelist ipv6
- '/bin/ping6' - /bin/ping6
- '/usr/bin/traceroute6.iputils' - /usr/bin/traceroute6.iputils
# whitelist nfs # whitelist nfs
- '/sbin/mount.nfs' - /sbin/mount.nfs
- '/sbin/umount.nfs' - /sbin/umount.nfs
# whitelist nfs4 # whitelist nfs4
- '/sbin/mount.nfs4' - /sbin/mount.nfs4
- '/sbin/umount.nfs4' - /sbin/umount.nfs4
# whitelist cron # whitelist cron
- '/usr/bin/crontab' - /usr/bin/crontab
# whitelist consolemssaging # whitelist consolemssaging
- '/usr/bin/wall' - /usr/bin/wall
- '/usr/bin/write' - /usr/bin/write
# whitelist: only SGID with utmp group for multi-session access # whitelist: only SGID with utmp group for multi-session access
# impact is limited; installation/usage has some remaining risk # impact is limited; installation/usage has some remaining risk
- '/usr/bin/screen' - /usr/bin/screen
# whitelist locate # whitelist locate
- '/usr/bin/mlocate' - /usr/bin/mlocate
# whitelist usermanagement # whitelist usermanagement
- '/usr/bin/chage' - /usr/bin/chage
- '/usr/bin/chfn' - /usr/bin/chfn
- '/usr/bin/chsh' - /usr/bin/chsh
# whitelist fuse # whitelist fuse
- '/bin/fusermount' - /bin/fusermount
# whitelist pkexec # whitelist pkexec
- '/usr/bin/pkexec' - /usr/bin/pkexec
# whitelist sudo # whitelist sudo
- '/usr/bin/sudo' - /usr/bin/sudo
- '/usr/bin/sudoedit' - /usr/bin/sudoedit
# whitelist postfix # whitelist postfix
- '/usr/sbin/postdrop' - /usr/sbin/postdrop
- '/usr/sbin/postqueue' - /usr/sbin/postqueue
# whitelist apache # whitelist apache
- '/usr/sbin/suexec' - /usr/sbin/suexec
# whitelist squid # whitelist squid
- '/usr/lib/squid/ncsa_auth' - /usr/lib/squid/ncsa_auth
- '/usr/lib/squid/pam_auth' - /usr/lib/squid/pam_auth
# whitelist kerberos # whitelist kerberos
- '/usr/kerberos/bin/ksu' - /usr/kerberos/bin/ksu
# whitelist pam_caching # whitelist pam_caching
- '/usr/sbin/ccreds_validate' - /usr/sbin/ccreds_validate
# whitelist Xorg # whitelist Xorg
- '/usr/bin/Xorg' # xorg - /usr/bin/Xorg # xorg
- '/usr/bin/X' # xorg - /usr/bin/X # xorg
- '/usr/lib/dbus-1.0/dbus-daemon-launch-helper' # freedesktop ipc - /usr/lib/dbus-1.0/dbus-daemon-launch-helper # freedesktop ipc
- '/usr/lib/vte/gnome-pty-helper' # gnome - /usr/lib/vte/gnome-pty-helper # gnome
- '/usr/lib/libvte9/gnome-pty-helper' # gnome - /usr/lib/libvte9/gnome-pty-helper # gnome
- '/usr/lib/libvte-2.90-9/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 # 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]

View file

@ -9,14 +9,16 @@ ssh_server_config_file: /etc/ssh/sshd_config # sshd
# true if sshd should be started and enabled # 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 # 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 ssh_use_dns: false # sshd
# true or value if compression is needed # true or value if compression is needed
ssh_client_compression: false # ssh ssh_client_compression: false # ssh
ssh_compression: false # sshd 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. # 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_client_hardening: true # ssh
ssh_server_hardening: true # sshd ssh_server_hardening: true # sshd
@ -25,13 +27,14 @@ ssh_client_password_login: false # ssh
ssh_server_password_login: false # sshd ssh_server_password_login: false # sshd
# ports on which ssh-server should listen # ports on which ssh-server should listen
ssh_server_ports: ['22'] # sshd ssh_server_ports: ["22"] # sshd
# port to which ssh-client should connect # 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! # one or more ip addresses, to which ssh-server should listen to.
ssh_listen_to: ['0.0.0.0'] # sshd # 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. # Host keys to look for when starting sshd.
ssh_host_key_files: [] # sshd ssh_host_key_files: [] # sshd
@ -51,7 +54,8 @@ ssh_client_host_key_algorithms: [] # ssh
# specifies the time allowed for successful authentication to the SSH server # specifies the time allowed for successful authentication to the SSH server
ssh_login_grace_time: 30s 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 ssh_max_auth_retries: 2
# Specifies the maximum number of open sessions permitted from a given connection # Specifies the maximum number of open sessions permitted from a given connection
@ -71,14 +75,15 @@ ssh_permit_tunnel: false
# - names: ['example3.com'] # - names: ['example3.com']
# options: ['StrictHostKeyChecking no'] # options: ['StrictHostKeyChecking no']
ssh_remote_hosts: [] ssh_remote_hosts: []
# Set this to "without-password" or "yes" to allow root to login # 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. # false to disable TCP Forwarding. Set to 'yes', 'no', 'local', 'all' or 'remote'
ssh_allow_tcp_forwarding: 'no' # sshd # 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. # Set to 'clientspecified' to allow the client to specify which address to bind to.
ssh_gateway_ports: false # sshd ssh_gateway_ports: false # sshd
@ -92,7 +97,7 @@ ssh_x11_forwarding: false # sshd
ssh_use_pam: true # sshd ssh_use_pam: true # sshd
# specify AuthenticationMethods # specify AuthenticationMethods
sshd_authenticationmethods: 'publickey' sshd_authenticationmethods: publickey
# Set to true to enable GSSAPI authentication (both client and server) # Set to true to enable GSSAPI authentication (both client and server)
ssh_gssapi_support: false ssh_gssapi_support: false
@ -101,22 +106,22 @@ ssh_gssapi_support: false
ssh_gssapi_delegation: false ssh_gssapi_delegation: false
# if specified, login is disallowed for user names that match one of the patterns. # 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. # 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. # 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. # 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. # 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. # 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. # set the trusted certificate authorities public keys used to sign user certificates.
# Example: # Example:
@ -133,12 +138,13 @@ ssh_trusted_user_ca_keys: [] # sshd
# replaced by the username of that user. After expansion, the path is taken to be # 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. # 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. # list of hashes containing file paths and authorized principals. Only used if ssh_authorized_principals_file is set.
# Example: # Example:
# ssh_authorized_principals: # 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' ] } # - { path: '/etc/ssh/auth_principals/myuser', principals: [ 'masteradmin', 'webserver' ] }
ssh_authorized_principals: [] # sshd ssh_authorized_principals: [] # sshd
@ -153,7 +159,7 @@ ssh_print_last_log: false # sshd
ssh_banner: false # sshd ssh_banner: false # sshd
# path to file with ssh warning banner # 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 # 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)
@ -165,7 +171,7 @@ sftp_enabled: true
sftp_chroot: true sftp_chroot: true
# sftp default umask # sftp default umask
sftp_umask: '0027' sftp_umask: "0027"
# change default sftp chroot location # change default sftp chroot location
sftp_chroot_dir: /home/%u sftp_chroot_dir: /home/%u
@ -185,20 +191,19 @@ ssh_server_match_address: false # sshd
# list of hashes (containing port and rules) to generate Match LocalPort blocks for # 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_permit_environment_vars: "no"
ssh_server_accept_env_vars: '' ssh_server_accept_env_vars: ""
# maximum number of concurrent unauthenticated connections to the SSH daemon # 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_macs: []
ssh_ciphers: [] ssh_ciphers: []
ssh_kex: [] ssh_kex: []
# directory where to store ssh_password policy # 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 sshd_moduli_minimum: 2048
@ -207,19 +212,16 @@ ssh_challengeresponseauthentication: false
# a list of public keys that are never accepted by the ssh server # a list of public keys that are never accepted by the ssh server
ssh_server_revoked_keys: [] ssh_server_revoked_keys: []
# Set to false to turn the role into a no-op. Useful when using # Set to false to turn the role into a no-op. Useful when using
# the Ansible role dependency mechanism. # the Ansible role dependency mechanism.
ssh_hardening_enabled: true ssh_hardening_enabled: true
# Custom options for SSH client configuration file # Custom options for SSH client configuration file
ssh_custom_options: [] ssh_custom_options: []
# Custom options for SSH daemon configuration file # Custom options for SSH daemon configuration file
sshd_custom_options: [] sshd_custom_options: []
# Logging # Logging
sshd_syslog_facility: 'AUTH' sshd_syslog_facility: AUTH
sshd_log_level: 'VERBOSE' sshd_log_level: VERBOSE
sshd_strict_modes: true sshd_strict_modes: true

View file

@ -1,7 +1,7 @@
--- ---
- name: Restart sshd - name: Restart sshd
service: ansible.builtin.service:
name: '{{ sshd_service_name }}' name: "{{ sshd_service_name }}"
state: restarted state: restarted
when: ssh_server_enabled | bool when: ssh_server_enabled | bool
become: true become: true

View file

@ -1,10 +1,10 @@
--- ---
galaxy_info: galaxy_info:
author: "Sebastian Gumprich" author: Sebastian Gumprich
description: 'This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.' description: This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.
company: Hardening Framework Team company: Hardening Framework Team
license: Apache License 2.0 license: Apache License 2.0
min_ansible_version: '2.9.10' min_ansible_version: 2.9.10
platforms: platforms:
- name: EL - name: EL
versions: versions:

View file

@ -1,27 +1,27 @@
--- ---
- name: Set ssh CA pub keys - name: Set ssh CA pub keys
template: ansible.builtin.template:
src: 'trusted_user_ca_keys.j2' src: trusted_user_ca_keys.j2
dest: '{{ ssh_trusted_user_ca_keys_file }}' dest: "{{ ssh_trusted_user_ca_keys_file }}"
mode: '0644' mode: "0644"
owner: '{{ ssh_owner }}' owner: "{{ ssh_owner }}"
group: '{{ ssh_group }}' group: "{{ ssh_group }}"
notify: Restart sshd notify: Restart sshd
- name: Create ssh authorized principals directories - name: Create ssh authorized principals directories
file: ansible.builtin.file:
path: '{{ item.path | dirname }}' path: "{{ item.path | dirname }}"
mode: '{{ item.directorymode | default("700") }}' mode: '{{ item.directorymode | default("700") }}'
owner: '{{ item.directoryowner | default(ssh_owner) }}' owner: "{{ item.directoryowner | default(ssh_owner) }}"
group: '{{ item.directorygroup | default(ssh_group) }}' group: "{{ item.directorygroup | default(ssh_group) }}"
state: directory state: directory
loop: '{{ ssh_authorized_principals }}' loop: "{{ ssh_authorized_principals }}"
- name: Set ssh authorized principals - name: Set ssh authorized principals
template: ansible.builtin.template:
src: 'authorized_principals.j2' src: authorized_principals.j2
dest: '{{ item.path }}' dest: "{{ item.path }}"
mode: '{{ item.filemode | default("600") }}' mode: '{{ item.filemode | default("600") }}'
owner: '{{ item.owner | default(ssh_owner) }}' owner: "{{ item.owner | default(ssh_owner) }}"
group: '{{ item.group | default(ssh_group) }}' group: "{{ item.group | default(ssh_group) }}"
loop: '{{ ssh_authorized_principals }}' loop: "{{ ssh_authorized_principals }}"

View file

@ -1,10 +1,10 @@
--- ---
- name: Set ciphers according to openssh-version if openssh >= 5.3 - name: Set ciphers according to openssh-version if openssh >= 5.3
set_fact: ansible.builtin.set_fact:
ssh_ciphers: '{{ ssh_ciphers_53_default }}' ssh_ciphers: "{{ ssh_ciphers_53_default }}"
when: sshd_version is version('5.3', '>=') when: sshd_version is version('5.3', '>=')
- name: Set ciphers according to openssh-version if openssh >= 6.6 - name: Set ciphers according to openssh-version if openssh >= 6.6
set_fact: ansible.builtin.set_fact:
ssh_ciphers: '{{ ssh_ciphers_66_default }}' ssh_ciphers: "{{ ssh_ciphers_66_default }}"
when: sshd_version is version('6.6', '>=') when: sshd_version is version('6.6', '>=')

View file

@ -11,28 +11,28 @@
# In RHEL and Fedora, the 'ssh_keys' group is the group owner of the host private SSH keys. # 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. # 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 - name: Change host private key ownership, group and permissions
file: ansible.builtin.file:
path: "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" path: "{{ ssh_host_keys_dir }}/ssh_host_rsa_key"
owner: "{{ ssh_host_keys_owner }}" owner: "{{ ssh_host_keys_owner }}"
group: "{{ ssh_host_keys_group }}" group: "{{ ssh_host_keys_group }}"
mode: "0640" 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 - name: Set hostkeys according to openssh-version if openssh >= 5.3
set_fact: ansible.builtin.set_fact:
ssh_host_key_files: ssh_host_key_files:
- "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key"
when: sshd_version is version('5.3', '>=') when: sshd_version is version('5.3', '>=')
- name: Set hostkeys according to openssh-version if openssh >= 6.0 - name: Set hostkeys according to openssh-version if openssh >= 6.0
set_fact: ansible.builtin.set_fact:
ssh_host_key_files: ssh_host_key_files:
- "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key"
- "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key"
when: sshd_version is version('6.0', '>=') when: sshd_version is version('6.0', '>=')
- name: Set hostkeys according to openssh-version if openssh >= 6.3 - name: Set hostkeys according to openssh-version if openssh >= 6.3
set_fact: ansible.builtin.set_fact:
ssh_host_key_files: ssh_host_key_files:
- "{{ ssh_host_keys_dir }}/ssh_host_rsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_rsa_key"
- "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key" - "{{ ssh_host_keys_dir }}/ssh_host_ecdsa_key"

View file

@ -1,20 +1,20 @@
--- ---
- name: Set kex according to openssh-version if openssh >= 5.9 - name: Set kex according to openssh-version if openssh >= 5.9
set_fact: ansible.builtin.set_fact:
ssh_kex: '{{ ssh_kex_59_default }}' ssh_kex: "{{ ssh_kex_59_default }}"
when: sshd_version is version('5.9', '>=') when: sshd_version is version('5.9', '>=')
- name: Set kex according to openssh-version if openssh >= 6.6 - name: Set kex according to openssh-version if openssh >= 6.6
set_fact: ansible.builtin.set_fact:
ssh_kex: '{{ ssh_kex_66_default }}' ssh_kex: "{{ ssh_kex_66_default }}"
when: sshd_version is version('6.6', '>=') when: sshd_version is version('6.6', '>=')
- name: Set kex according to openssh-version if openssh >= 8.0 - name: Set kex according to openssh-version if openssh >= 8.0
set_fact: ansible.builtin.set_fact:
ssh_kex: '{{ ssh_kex_80_default }}' ssh_kex: "{{ ssh_kex_80_default }}"
when: sshd_version is version('8.0', '>=') when: sshd_version is version('8.0', '>=')
- name: Set kex according to openssh-version if openssh >= 8.5 - name: Set kex according to openssh-version if openssh >= 8.5
set_fact: ansible.builtin.set_fact:
ssh_kex: '{{ ssh_kex_85_default }}' ssh_kex: "{{ ssh_kex_85_default }}"
when: sshd_version is version('8.5', '>=') when: sshd_version is version('8.5', '>=')

View file

@ -1,20 +1,20 @@
--- ---
- name: Set macs according to openssh-version if openssh >= 5.3 - name: Set macs according to openssh-version if openssh >= 5.3
set_fact: ansible.builtin.set_fact:
ssh_macs: '{{ ssh_macs_53_default }}' ssh_macs: "{{ ssh_macs_53_default }}"
when: sshd_version is version('5.3', '>=') when: sshd_version is version('5.3', '>=')
- name: Set macs according to openssh-version if openssh >= 5.9 - name: Set macs according to openssh-version if openssh >= 5.9
set_fact: ansible.builtin.set_fact:
ssh_macs: '{{ ssh_macs_59_default }}' ssh_macs: "{{ ssh_macs_59_default }}"
when: sshd_version is version('5.9', '>=') when: sshd_version is version('5.9', '>=')
- name: Set macs according to openssh-version if openssh >= 6.6 - name: Set macs according to openssh-version if openssh >= 6.6
set_fact: ansible.builtin.set_fact:
ssh_macs: '{{ ssh_macs_66_default }}' ssh_macs: "{{ ssh_macs_66_default }}"
when: sshd_version is version('6.6', '>=') when: sshd_version is version('6.6', '>=')
- name: Set macs according to openssh-version if openssh >= 7.6 - name: Set macs according to openssh-version if openssh >= 7.6
set_fact: ansible.builtin.set_fact:
ssh_macs: '{{ ssh_macs_76_default }}' ssh_macs: "{{ ssh_macs_76_default }}"
when: sshd_version is version('7.6', '>=') when: sshd_version is version('7.6', '>=')

View file

@ -1,14 +1,14 @@
--- ---
- name: Fetch OS dependent variables - name: Fetch OS dependent variables
include_vars: ansible.builtin.include_vars:
file: '{{ item }}' file: "{{ item }}"
name: 'os_vars' name: os_vars
with_first_found: with_first_found:
- files: - files:
- '{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version | default() }}.yml' - "{{ ansible_facts.distribution }}_{{ ansible_facts.distribution_major_version | default() }}.yml"
- '{{ ansible_facts.distribution }}.yml' - "{{ ansible_facts.distribution }}.yml"
- '{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version | default() }}.yml' - "{{ ansible_facts.os_family }}_{{ ansible_facts.distribution_major_version | default() }}.yml"
- '{{ ansible_facts.os_family }}.yml' - "{{ ansible_facts.os_family }}.yml"
skip: true skip: true
tags: always tags: always
@ -16,63 +16,63 @@
# by default the lookup functions finds all varnames containing the string, therefore # 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 # 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 - name: Set OS dependent variables, if not already defined by user # noqa var-naming
set_fact: ansible.builtin.set_fact:
'{{ item.key }}': '{{ item.value }}' "{{ item.key }}": "{{ item.value }}"
when: "not lookup('varnames', '^' + item.key + '$')" when: not lookup('varnames', '^' + item.key + '$')
with_dict: '{{ os_vars }}' with_dict: "{{ os_vars }}"
tags: always tags: always
- name: Get openssh-version - name: Get openssh-version
command: ssh -V ansible.builtin.command: ssh -V
register: sshd_version_raw register: sshd_version_raw
changed_when: false changed_when: false
check_mode: false check_mode: false
- name: Parse openssh-version - name: Parse openssh-version
set_fact: ansible.builtin.set_fact:
sshd_version: "{{ sshd_version_raw.stderr | regex_replace('.*_([0-9]*.[0-9]).*', '\\1') }}" sshd_version: "{{ sshd_version_raw.stderr | regex_replace('.*_([0-9]*.[0-9]).*', '\\1') }}"
- name: Set default for ssh_host_key_files if not supplied - name: Set default for ssh_host_key_files if not supplied
include_tasks: crypto_hostkeys.yml ansible.builtin.include_tasks: crypto_hostkeys.yml
when: when:
- ssh_server_hardening | bool - ssh_server_hardening | bool
- not ssh_host_key_files - not ssh_host_key_files
- name: Set default for ssh_macs if not supplied - 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 when: not ssh_macs
- name: Set default for ssh_ciphers if not supplied - 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 when: not ssh_ciphers
- name: Set default for ssh_kex if not supplied - 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 when: not ssh_kex
- name: Create revoked_keys and set permissions to root/600 - name: Create revoked_keys and set permissions to root/600
template: ansible.builtin.template:
src: 'revoked_keys.j2' src: revoked_keys.j2
dest: '/etc/ssh/revoked_keys' dest: /etc/ssh/revoked_keys
mode: '0600' mode: "0600"
owner: '{{ ssh_owner }}' owner: "{{ ssh_owner }}"
group: '{{ ssh_group }}' group: "{{ ssh_group }}"
notify: Restart sshd notify: Restart sshd
when: ssh_server_hardening | bool when: ssh_server_hardening | bool
- name: Create sshd_config and set permissions to root/600 - name: Create sshd_config and set permissions to root/600
template: ansible.builtin.template:
src: 'opensshd.conf.j2' src: opensshd.conf.j2
dest: "{{ ssh_server_config_file }}" dest: "{{ ssh_server_config_file }}"
mode: '0600' mode: "0600"
owner: '{{ ssh_owner }}' owner: "{{ ssh_owner }}"
group: '{{ ssh_group }}' group: "{{ ssh_group }}"
validate: '{{ sshd_path }} -T -C user=root -C host=localhost -C addr=localhost -C lport=22 -f %s' validate: "{{ sshd_path }} -T -C user=root -C host=localhost -C addr=localhost -C lport=22 -f %s"
notify: Restart sshd notify: Restart sshd
when: ssh_server_hardening | bool when: ssh_server_hardening | bool
- name: Disable dynamic MOTD - name: Disable dynamic MOTD
pamd: community.general.pamd:
name: sshd name: sshd
type: session type: session
control: optional control: optional
@ -85,52 +85,53 @@
- not (ssh_print_pam_motd | bool) - not (ssh_print_pam_motd | bool)
- name: Create ssh_config and set permissions to root/644 - name: Create ssh_config and set permissions to root/644
template: ansible.builtin.template:
src: 'openssh.conf.j2' src: openssh.conf.j2
dest: "{{ ssh_client_config_file }}" dest: "{{ ssh_client_config_file }}"
mode: '0644' mode: "0644"
owner: '{{ ssh_owner }}' owner: "{{ ssh_owner }}"
group: '{{ ssh_group }}' group: "{{ ssh_group }}"
when: ssh_client_hardening | bool when: ssh_client_hardening | bool
- name: Check if {{ sshd_moduli_file }} contains weak DH parameters - 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 register: sshd_register_moduli
changed_when: false changed_when: false
check_mode: false check_mode: false
when: ssh_server_hardening | bool when: ssh_server_hardening | bool
- name: Remove all small primes - name: Remove all small primes
shell: awk '$5 >= {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} > {{ sshd_moduli_file }}.new ; ansible.builtin.shell: >
[ -r {{ sshd_moduli_file }}.new -a -s {{ sshd_moduli_file }}.new ] && mv {{ sshd_moduli_file }}.new {{ sshd_moduli_file }} || true 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 notify: Restart sshd
when: when:
- ssh_server_hardening | bool - ssh_server_hardening | bool
- sshd_register_moduli.stdout - sshd_register_moduli.stdout
- name: Include tasks to setup ca keys and principals - 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: when:
- ssh_trusted_user_ca_keys_file | length > 0 - ssh_trusted_user_ca_keys_file | length > 0
- ssh_trusted_user_ca_keys | length > 0 - ssh_trusted_user_ca_keys | length > 0
- name: Include selinux specific tasks - 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" when: ansible_facts.selinux and ansible_facts.selinux.status == "enabled"
- name: Gather package facts - name: Gather package facts
package_facts: ansible.builtin.package_facts:
check_mode: false check_mode: false
when: when:
- sshd_disable_crypto_policy | bool - sshd_disable_crypto_policy | bool
- name: Disable SSH server CRYPTO_POLICY - name: Disable SSH server CRYPTO_POLICY
copy: ansible.builtin.copy:
src: sshd src: sshd
dest: /etc/sysconfig/sshd dest: /etc/sysconfig/sshd
owner: 'root' owner: root
group: 'root' group: root
mode: '0640' mode: "0640"
when: when:
- sshd_disable_crypto_policy | bool - sshd_disable_crypto_policy | bool
- ('crypto-policies' in ansible_facts.packages) - ('crypto-policies' in ansible_facts.packages)

View file

@ -1,6 +1,6 @@
--- ---
- name: Include hardening tasks - name: Include hardening tasks
include_tasks: hardening.yml ansible.builtin.include_tasks: hardening.yml
args: args:
apply: apply:
become: true become: true

View file

@ -1,19 +1,19 @@
--- ---
- name: Install selinux dependencies when selinux is installed - name: Install selinux dependencies when selinux is installed
package: ansible.builtin.package:
name: '{{ ssh_selinux_packages }}' name: "{{ ssh_selinux_packages }}"
state: present state: present
- name: Authorize {{ ssh_server_ports }} ports for selinux - name: Authorize {{ ssh_server_ports }} ports for selinux
seport: community.general.seport:
ports: '{{ item }}' ports: "{{ item }}"
proto: tcp proto: tcp
setype: ssh_port_t setype: ssh_port_t
state: present state: present
loop: '{{ ssh_server_ports }}' loop: "{{ ssh_server_ports }}"
- name: Check if ssh_password module is already installed - 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: args:
executable: /bin/bash executable: /bin/bash
register: ssh_password_module register: ssh_password_module
@ -30,36 +30,35 @@
- ('ssh_password' not in ssh_password_module.stdout) - ('ssh_password' not in ssh_password_module.stdout)
block: block:
- name: Create selinux custom policy drop folder - name: Create selinux custom policy drop folder
file: ansible.builtin.file:
path: '{{ ssh_custom_selinux_dir }}' path: "{{ ssh_custom_selinux_dir }}"
state: 'directory' state: directory
owner: 'root' owner: root
group: 'root' group: root
mode: '0750' mode: "0750"
- name: Distributing custom selinux policies - name: Distributing custom selinux policies
copy: ansible.builtin.copy:
src: 'ssh_password' src: ssh_password
dest: '{{ ssh_custom_selinux_dir }}' dest: "{{ ssh_custom_selinux_dir }}"
owner: 'root' owner: root
group: 'root' group: root
mode: '0600' mode: "0600"
- name: Check and compile policy # noqa no-changed-when - 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 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 - 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 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 - name: Install selinux policy # noqa no-changed-when
command: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp ansible.builtin.command: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp
# The following tasks only get executed when selinux is installed, UsePam is # The following tasks only get executed when selinux is installed, UsePam is
# 'yes' and the ssh_password module is installed. See # 'yes' and the ssh_password module is installed. See
# http://danwalsh.livejournal.com/12333.html for more info # 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 - 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: when:
- ssh_use_pam | bool - ssh_use_pam | bool
- ('ssh_password' in ssh_password_module.stdout) - ('ssh_password' in ssh_password_module.stdout)

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
# true if SSH support Kerberos # true if SSH support Kerberos
ssh_kerberos_support: true ssh_kerberos_support: true
@ -13,7 +13,7 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true ssh_pam_support: true
sshd_moduli_file: '/etc/ssh/moduli' sshd_moduli_file: /etc/ssh/moduli
# CRYPTO_POLICY is not supported on Archlinux # CRYPTO_POLICY is not supported on Archlinux
# and the package check only works in Ansible >2.10 # and the package check only works in Ansible >2.10

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: ssh sshd_service_name: ssh
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
ssh_selinux_packages: ssh_selinux_packages:
- policycoreutils-python - policycoreutils-python
- checkpolicy - checkpolicy
@ -16,6 +16,6 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true ssh_pam_support: true
sshd_moduli_file: '/etc/ssh/moduli' sshd_moduli_file: /etc/ssh/moduli
sshd_disable_crypto_policy: false sshd_disable_crypto_policy: false

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'ssh_keys' ssh_host_keys_group: ssh_keys
ssh_selinux_packages: ssh_selinux_packages:
- python3-policycoreutils - python3-policycoreutils
- checkpolicy - checkpolicy
@ -16,7 +16,7 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true 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 # disable CRYPTO_POLICY to take settings from sshd configuration
# see: https://access.redhat.com/solutions/4410591 # see: https://access.redhat.com/solutions/4410591

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: wheel ssh_group: wheel
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
# true if SSH support Kerberos # true if SSH support Kerberos
ssh_kerberos_support: true ssh_kerberos_support: true
@ -13,6 +13,6 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true ssh_pam_support: true
sshd_moduli_file: '/etc/ssh/moduli' sshd_moduli_file: /etc/ssh/moduli
sshd_disable_crypto_policy: false sshd_disable_crypto_policy: false

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: wheel ssh_group: wheel
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
# true if SSH support Kerberos # true if SSH support Kerberos
ssh_kerberos_support: false ssh_kerberos_support: false
@ -13,6 +13,6 @@ ssh_kerberos_support: false
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: false ssh_pam_support: false
sshd_moduli_file: '/etc/moduli' sshd_moduli_file: /etc/moduli
sshd_disable_crypto_policy: false sshd_disable_crypto_policy: false

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'ssh_keys' ssh_host_keys_group: ssh_keys
ssh_selinux_packages: ssh_selinux_packages:
- policycoreutils-python-utils - policycoreutils-python-utils
- checkpolicy - checkpolicy
@ -16,7 +16,7 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true 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 # disable CRYPTO_POLICY to take settings from sshd configuration
# see: https://access.redhat.com/solutions/4410591 # see: https://access.redhat.com/solutions/4410591

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'ssh_keys' ssh_host_keys_group: ssh_keys
ssh_selinux_packages: ssh_selinux_packages:
- policycoreutils-python - policycoreutils-python
- checkpolicy - checkpolicy
@ -16,7 +16,7 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true 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 # disable CRYPTO_POLICY to take settings from sshd configuration
# see: https://access.redhat.com/solutions/4410591 # see: https://access.redhat.com/solutions/4410591

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/lib/ssh/sshd sshd_path: /usr/lib/ssh/sshd
ssh_host_keys_dir: '/var/ssh' ssh_host_keys_dir: /var/ssh
sshd_service_name: ssh sshd_service_name: ssh
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
# true if SSH support Kerberos # true if SSH support Kerberos
ssh_kerberos_support: true ssh_kerberos_support: true
@ -13,6 +13,6 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: false ssh_pam_support: false
sshd_moduli_file: '/etc/ssh/moduli' sshd_moduli_file: /etc/ssh/moduli
sshd_disable_crypto_policy: false sshd_disable_crypto_policy: false

View file

@ -1,11 +1,11 @@
--- ---
sshd_path: /usr/sbin/sshd sshd_path: /usr/sbin/sshd
ssh_host_keys_dir: '/etc/ssh' ssh_host_keys_dir: /etc/ssh
sshd_service_name: sshd sshd_service_name: sshd
ssh_owner: root ssh_owner: root
ssh_group: root ssh_group: root
ssh_host_keys_owner: 'root' ssh_host_keys_owner: root
ssh_host_keys_group: 'root' ssh_host_keys_group: root
# true if SSH support Kerberos # true if SSH support Kerberos
ssh_kerberos_support: true ssh_kerberos_support: true
@ -13,6 +13,6 @@ ssh_kerberos_support: true
# true if SSH has PAM support # true if SSH has PAM support
ssh_pam_support: true ssh_pam_support: true
sshd_moduli_file: '/etc/ssh/moduli' sshd_moduli_file: /etc/ssh/moduli
sshd_disable_crypto_policy: false sshd_disable_crypto_policy: false