From 02016ed6d0cc6e63396ad5d40dab547fc3be99d7 Mon Sep 17 00:00:00 2001 From: iquzart Date: Tue, 27 Oct 2020 14:20:30 +0400 Subject: [PATCH] local project --- .travis.yml | 29 ++ README.md | 39 ++ defaults/main.yml | 160 +++++++ handlers/main.yml | 16 + meta/main.yml | 15 + tasks/main.yml | 37 ++ tasks/section_1.yml | 884 +++++++++++++++++++++++++++++++++++ tasks/section_2.yml | 339 ++++++++++++++ templates/etc/chrony.conf.j2 | 93 ++++ templates/etc/issue.j2 | 1 + templates/etc/issue.net.j2 | 1 + templates/etc/motd.j2 | 1 + templates/tmp.mount.j2 | 25 + tests/inventory | 2 + tests/test.yml | 5 + vars/main.yml | 2 + 16 files changed, 1649 insertions(+) create mode 100644 .travis.yml create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/main.yml create mode 100644 tasks/section_1.yml create mode 100644 tasks/section_2.yml create mode 100644 templates/etc/chrony.conf.j2 create mode 100644 templates/etc/issue.j2 create mode 100644 templates/etc/issue.net.j2 create mode 100644 templates/etc/motd.j2 create mode 100644 templates/tmp.mount.j2 create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 vars/main.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..84470a1 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +CIS - CentOs +========= + +Asible role to apply CIS Benchmark on RHEL 8 based systems (Under Development) + + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..ea96791 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,160 @@ +--- +# defaults file for cis-centos + +# +section_1: true +section_2: true +section_3: true +section_4: true +section_5: true +section_6: true + +# Section 1 rules +rule_1_1_1_1: true # Ensure mounting of cramfs filesystems is disabled +rule_1_1_1_2: true # Ensure mounting of vFAT filesystems is disabled +rule_1_1_1_3: true # Ensure mounting of squashfs filesystems is disabled +rule_1_1_1_4: true # Ensure mounting of udf filesystems is disabled +rule_1_1_2: true # Ensure separate partition exists for /tmp | enable and start/restart tmp.mount +rule_1_1_3: true # Ensure nodev option set on /tmp partition +rule_1_1_4: true # Ensure nosuid option set on /tmp partition +rule_1_1_5: true # Ensure noexec option set on /tmp partition +rule_1_1_6: true # Ensure separate partition exists for /var +rule_1_1_7: true # Ensure separate partition exists for /var/tmp +rule_1_1_8: true # Ensure nodev option set on /var/tmp partition +rule_1_1_9: true # Ensure nosuid option set on /var/tmp partition +rule_1_1_10: true # Ensure noexec option set on /var/tmp partition +rule_1_1_11: true # Ensure separate partition exists for /var/log +rule_1_1_12: true # Ensure separate partition exists for /var/log/audit +rule_1_1_13: true # Ensure separate partition exists for /home +rule_1_1_14: true # Ensure nodev option set on /home +rule_1_1_15: true # Ensure nodev option set on /dev/shm partition +rule_1_1_16: true # Ensure nosuid option set on /dev/shm partition +rule_1_1_17: true # Ensure noexec option set on /dev/shm partition +rule_1_1_18: true # Ensure nodev option set on removable media partitions +rule_1_1_19: true # Ensure nosuid option set on removable media partitions +rule_1_1_20: true # Ensure noexec option set on removable media partitions +rule_1_1_21: true # Ensure sticky bit is set on all world-writable directories +rule_1_1_22: true # Diable automounting +rule_1_1_23: false # Disable USB Storage +rule_1_2_1: true # Ensure Red Hat Subscription Manager connection is configured +rule_1_2_2: true # Disable the RHNSD daemon +rule_1_2_3: true # Ensure gpg keys are configured +rule_1_2_4: true # Ensure gpgcheck is globally activated +rule_1_2_5: true # Ensure package manager repositories are configured +rule_1_3_1: true # Ensure sudo is installed +rule_1_3_2: true # Ensure sudo commands user pty +rule_1_3_3: true # Ensure sudo log file exists +rule_1_4_1: true # Ensure aide is installed +rule_1_4_2: true # Ensure filesystem integrity is regularly checked +rule_1_5_1: true # Ensure permissions on bootloader config are configured +rule_1_5_2: true # Ensure bootloader password is set --> not idempotent +rule_1_5_3: true # Ensure authentication required for single user mode +rule_1_6_1: true # Ensure core dumps are restricted +rule_1_6_2: true # Ensure address space layout randomization (ASLR) is enabled +rule_1_7_1_1: true # Ensure selinux is installed +rule_1_7_1_2: true # Ensure selinux is not disabled in bootloader configuration +rule_1_7_1_3: true # Ensure selinux policy is configured +rule_1_7_1_4: true # Ensure the selinux state is enforcing +rule_1_7_1_5: true # Ensure no unconfined services exist +rule_1_7_1_6: true # Ensure SETroubleshoot is not installed +rule_1_7_1_7: true # Ensure the MCS Translation Service (mcstrans) is not installed +rule_1_8_1_1: true # Ensure message of the day is configured properly +rule_1_8_1_2: true # Ensure local login warning banner is configured properly +rule_1_8_1_3: true # Ensure remote login warning banner is configured properly +rule_1_8_1_4: true # Ensure permissions on /etc/motd are configured +rule_1_8_1_5: true # Ensure permissions on /etc/issue are configured +rule_1_8_1_6: true # Ensure permissions on /etc/issue.net are configured +rule_1_8_2: true # Ensure GDM login banner is configured +rule_1_9: false # Ensure updates, patches, and additional security software are installed +rule_1_10: true # Ensure system-wide crypto policy is not legacy +rule_1_11: true # Ensure system-wide crypto policy is is FUTURE or FIPS --> not idempotent + +# Section 2 rules +rule_2_1_1: true # Ensure xinetd is not installed +rule_2_2_1_1: true # Ensure time synchronization is in use +rule_2_2_1_2: true # Ensure chrony is configured +rule_2_2_2: true # Ensure X Window System is not installed +rule_2_2_3: true # Ensure rsync service is not enabled +rule_2_2_4: true # Ensure Avahi Server is not enabled +rule_2_2_5: true # Ensure SNMP Server is not enabled" +rule_2_2_6: true # Ensure HTTP Proxy Server is not enabled +rule_2_2_7: true # Ensure Samba is not enabled +rule_2_2_8: true # Ensure IMAP and POP3 server is not enabled +rule_2_2_9: true # Ensure HTTP server is not enabled +rule_2_2_10: true # Ensure FTP server is not enabled +rule_2_2_11: true # Ensure DNS Server is not enabled +rule_2_2_12: true # Ensure NFS is not enabled +rule_2_2_13: true # Ensure RPC is not enabled +rule_2_2_14: true # Ensure LDAP service is not enabled +rule_2_2_15: true # Ensure DHCP is not enabled +rule_2_2_16: true # Ensure CUPS is not enabled +rule_2_2_17: true # Ensure NIS Server is not enabled +rule_2_2_18: true # Ensure mail transfer agent is configured for local-only mode +rule_2_3_1: true # Ensure NIS Client is not installed +rule_2_3_2: true # Ensure telnet client is not installed +rule_2_3_3: true # Ensure LDAP client is not installed + +##################################################################### +# 1.4.2 Bootloader password +bootloader_password: random +set_boot_pass: true + +# AIDE +config_aide: true +# AIDE cron settings +aide_cron: + cron_user: root + cron_file: /etc/crontab + aide_job: '/usr/sbin/aide --check' + aide_minute: 0 + aide_hour: 5 + aide_day: '*' + aide_month: '*' + aide_weekday: '*' + +crypto_policy: FIPS #FUTURE + +# SELinux policy +selinux_state: enforcing +selinux_policy: targeted + +# Set to 'true' if X Windows is needed in your environment +xwindows_required: false + +# Time Synchronization +time_synchronization: chrony +time_synchronization_servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 2.pool.ntp.org + - 3.pool.ntp.org + + +# Warning Banner Content (motd) +warning_banner_motd: | + Authorized uses only. All activity may be monitored and reported. +# End Banner + +# Warning Banner Content (issue, issue.net) +warning_banner_issue: | + WARNING: This system is for use of authorized users only. + Individuals using this computer system without authority, or in + excess of their authority, are subject to having all of their + activities on this system monitored and recorded by system personnel. + + In the course of Monitoring individuals improperly using this system, + or in the course of system maintenance, the activity of authorized + users may also be monitored. + Anyone using this system expressly consents to such monitoring and is + adviced that if such monitoring reveals possible evidence of criminal + activity, system personnel may provide the evidence of such monitoring + to law enforcement officials. +# End Banner + +vartmp: + source: /tmp + fstype: none + opts: "defaults,nodev,nosuid,noexec,bind" + enabled: no + + diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..8125801 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,16 @@ +--- +# handlers file for cis-centos + +- name: systemd restart tmp.mount + become: yes + systemd: + name: tmp.mount + daemon_reload: yes + enabled: yes + masked: no + state: reloaded + +- name: generate new grub config + become: yes + command: grub2-mkconfig -o "{{ grub_cfg.stat.lnk_source }}" + diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..93438d0 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,15 @@ +galaxy_info: + role_name: cis-centos + author: iquzart + description: CIS Benchmark for RHEL 8 Based Systems + license: MIT + min_ansible_version: 2.9 + platforms: + - name: EL + versions: + - 8 + galaxy_tags: + - docker + - compose + - containers +dependencies: [] \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..73db05d --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,37 @@ +--- +# tasks file for cis-centos + +- name: Check OS version and family + fail: + msg: "This role can only be run agaist CentOS or RHEL. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported." + when: + - not ansible_os_family == "RedHat" + - not ansible_distribution_major_version == "8" + tags: + - always + +- name: Check ansible version + fail: + msg: You must use ansible 2.9 or greater! + when: not ansible_version.full is version_compare('2.9', '>=') + tags: + - always + +- name: "Set package facts" + package_facts: + manager: "auto" + +- name: "Set service facts" + service_facts: + +- include: section_1.yml + become: true + when: section_1 + tags: + - section_1 + +- include: section_2.yml + become: true + when: section_2 + tags: + - section_2 diff --git a/tasks/section_1.yml b/tasks/section_1.yml new file mode 100644 index 0000000..271b675 --- /dev/null +++ b/tasks/section_1.yml @@ -0,0 +1,884 @@ +--- +- name: "1.1.1.1 | Ensure mounting of cramfs filesystems is disabled (Scored)" + lineinfile: + dest: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install cramfs(\\s|$)" + line: "install cramfs /bin/true" + create: yes + when: + - rule_1_1_1_1|bool + tags: + - section_1 + - scored + - cramfs + +- name: "1.1.1.1 | Remove cramfs module" + modprobe: + name: cramfs + state: absent + when: + - rule_1_1_1_1|bool + - ansible_connection != 'docker' + tags: + - section_1 + - scored + - cramfs + +- name: "1.1.1.2 | Ensure mounting of vFAT filesystems is limited (Not Scored)" + lineinfile: + dest: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install vfat(\\s|$)" + line: "install vfat /bin/true" + create: yes + when: + - rule_1_1_1_2|bool + tags: + - section_1 + - not_scored + - vfat + +- name: "1.1.1.2 | Remove FAT module" + modprobe: + name: vfat + state: absent + when: + - rule_1_1_1_2|bool + - ansible_connection != 'docker' + tags: + - section_1 + - not_scored + - vfat + +- name: "1.1.1.3 | Ensure mounting of squashfs filesystems is disabled (Scored)" + lineinfile: + dest: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install squashfs(\\s|$)" + line: "install squashfs /bin/true" + create: yes + when: + - rule_1_1_1_3|bool + tags: + - section_1 + - scored + - squashfs + +- name: "1.1.1.3 | Remove squashfs module" + modprobe: + name: squashfs + state: absent + when: + - rule_1_1_1_3|bool + - ansible_connection != 'docker' + tags: + - section_1 + - scored + - squashfs + + +- name: "1.1.1.4 | Ensure mounting of udf filesystems is disabled (Scored)" + lineinfile: + dest: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install udf(\\s|$)" + line: "install udf /bin/true" + create: yes + when: + - rule_1_1_1_4|bool + tags: + - section_1 + - scored + - udf + +- name: "1.1.1.4 | Remove udf module" + modprobe: + name: udf + state: absent + when: + - rule_1_1_1_4|bool + - ansible_connection != 'docker' + tags: + - section_1 + - scored + - udf + + +- name: "1.1.2 | Ensure separate partition exists for /tmp | enable and start/restart tmp.mount" + systemd: + name: tmp.mount + daemon_reload: yes + enabled: yes + masked: no + state: started + when: + - rule_1_1_2|bool + tags: + - section_1 + - scored + - rule_1.1.2 + +- name: "1.1.3 | 1.1.4 | 1.1.5 | Ensure nodev,nosuid,noexec options set on /tmp partition" + template: + src: tmp.mount.j2 + dest: /etc/systemd/system/tmp.mount + owner: root + group: root + mode: 0644 + notify: systemd restart tmp.mount + when: rule_1_1_3|bool or + rule_1_1_4|bool or + rule_1_1_5|bool + tags: + - section_1 + - scored + - rule_1.1.3 + - rule_1.1.4 + - rule_1.1.5 + +- name: "1.1.6 | Ensure separate partition exists for /var (Scored)" + shell: mount | grep "on /var " + args: + warn: false + register: var_mounted + changed_when: no + failed_when: no + when: + - rule_1_1_6 + tags: + - level2 + - scored + - section_1 + - rule_1.1.6 + - skip_ansible_lint + +- name: "1.1.7 | Ensure separate partition exists for /var/tmp (Scored)" + shell: mount | grep "on /var/tmp " + args: + warn: false + register: var_tmp_mounted + changed_when: no + failed_when: no + when: + - rule_1_1_7 + tags: + - level2 + - scored + - section_1 + - rule_1.1.7 + - skip_ansible_lint + +- name: "1.1.8 | Ensure nodev option set on /var/tmp partition (Scored)\n + 1.1.9 | Ensure nosuid option set on /var/tmp partition (Scored)\n + 1.1.10 | Ensure noexec option set on /var/tmp partition (Scored)" + mount: + name: /var/tmp + src: "{{ vartmp['source'] }}" + state: present + fstype: "{{ vartmp['fstype'] }}" + opts: "{{ vartmp['opts'] }}" + when: + - rule_1_1_8|bool + - rule_1_1_9|bool + - rule_1_1_10|bool + tags: + - level1 + - scored + - patch + - rule_1.1.8 + - rule_1.1.9 + - rule_1.1.10 + +- name: "1.1.11 | Ensure separate partition exists for /var/log (Scored)" + shell: mount | grep "on /var/log " + args: + warn: false + register: var_log_mounted + changed_when: no + failed_when: no + when: + - rule_1_1_11 + tags: + - level2 + - scored + - section_1 + - rule_1.1.11 + - skip_ansible_lint + +- name: "1.1.12 | Ensure separate partition exists for /var/log/audit (Scored)" + shell: mount | grep "on /var/log/audit " + args: + warn: false + register: var_log_audit_mounted + changed_when: no + failed_when: no + when: + - rule_1_1_12 + tags: + - level2 + - scored + - section_1 + - rule_1.1.12 + - skip_ansible_lint + +- name: "1.1.13 | Ensure separate partition exists for /home (Scored)" + shell: mount | grep "on /home" + args: + warn: false + register: home_mounted + changed_when: no + failed_when: no + when: + - rule_1_1_13|bool + tags: + - level2 + - scored + - patch + - rule_1.1.13 + - skip_ansible_lint + +- name: "1.1.14 | Ensure nodev option set on /home partition (Scored)" + mount: + name: "/home" + src: "{{ item.device }}" + state: mounted + fstype: "{{ item.fstype }}" + opts: "nodev" + when: + - rule_1_1_14|bool + - item.mount == "/home" + with_items: "{{ ansible_mounts }}" + tags: + - level1 + - level2 + - patch + - rule_1.1.14 + +- name: "1.1.15 | Ensure nodev option set on /dev/shm partition (Scored)\n + 1.1.16 | Ensure nosuid option set on /dev/shm partition (Scored)\n + 1.1.17 | Ensure noexec option set on /dev/shm partition (Scored)" + mount: + name: /dev/shm + src: tmpfs + state: mounted + fstype: tmpfs + opts: "defaults,nodev,nosuid,noexec" + when: + - rule_1_1_15 + - rule_1_1_16 + - rule_1_1_17 + tags: + - level1 + - scored + - section_1 + - rule_1.1.15 + - rule_1.1.16 + - rule_1.1.17 + +- name: "1.1.18 | Ensure nodev option set on removable media partitions (Not Scored)" + debug: + msg: "--> Not relevant" + changed_when: no + when: + - rule_1_1_18 + tags: + - level1 + - notscored + - section_1 + - rule_1.1.18 + +- name: "1.1.19 | Ensure nosuid option set on removable media partitions (Not Scored)" + debug: + msg: "--> Not relevant" + changed_when: no + when: + - rule_1_1_19 + tags: + - level1 + - notscored + - section_1 + - rule_1.1.19 + +- name: "1.1.20 | Ensure noexec option set on removable media partitions (Not Scored)" + debug: + msg: "--> Not relevant" + changed_when: no + when: + - rule_1_1_20 + tags: + - level1 + - notscored + - section_1 + - rule_1.1.20 + +- name: "1.1.21 | Ensure sticky bit is set on all world-writable directories (Scored)" + shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t + changed_when: no + failed_when: no + #when: sticky_bit_on_worldwritable_dirs_audit.rc == '0' + when: + - rule_1_1_21 + tags: + - level1 + - level2 + - section_1 + - rule_1.1.21 + +- name: "1.1.22 | Disable Automounting (Scored)" + service: + name: autofs + enabled: no + when: + - "'autofs.service' in ansible_facts.services" + - rule_1_1_22|bool + tags: + - level1 + - patch + - rule_1.1.22 + +- name: "1.1.23 | Disable USB Storage (Scored)" + command: rmmod usb-storage + ignore_errors: yes + when: + - rule_1_1_23|bool + tags: + - level1 + - scored + - patch + - rule_1.1.23 + - usb + +- name: "1.2.1 | Ensure Red Hat Subscription Manager connection is configured (Not Scored)" + command: subscription-manager identity + register: subscription_configured + changed_when: no + failed_when: no + when: + - ansible_distribution == "redhat" + - rule_1_2_1 + tags: + - level1 + - notscored + - section_1 + - rule_1.2.1 + - skip_ansible_lint + +- name: "1.2.2 | Disable the rhnsd Daemon (Not Scored)" + systemd: + name: rhnsd + state: stopped + enabled: no + when: + - ansible_distribution == "redhat" + - "'rhnsd' in ansible_facts.packages" + - rule_1_2_2 + tags: + - level2 + - notscored + - section_1 + - rule_1.2.2 + +- name: "1.2.3 | Ensure GPG keys are configured (Not Scored)" + command: gpg --quiet --with-fingerprint /etc/pki/rpm-gpg/rpm-gpg-key-{{ ansible_distribution|lower }}-release + when: + - rule_1_2_3 + - ansible_distribution == "redhat" + tags: + - level1 + - notscored + - section_1 + - rule_1.2.3 + +- name: "1.2.4 | Ensure gpgcheck is globally activated (Scored)" + block: + - name: "1.2.4 | Ensure gpgcheck is globally activated (Scored)" + replace: + name: /etc/yum.conf + regexp: "^gpgcheck=0" + replace: "gpgcheck=1" + + - name: "1.2.4 | Ensure gpgcheck is globally activated (Scored)" + find: + paths: /etc/yum.repos.d + patterns: "/*.repo" + register: yum_repos + changed_when: no + + - name: "1.2.4 | Ensure gpgcheck is globally activated (Scored)" + replace: + name: "{{ item.path }}" + regexp: "^gpgcheck=0" + replace: "gpgcheck=1" + with_items: + - "{{ yum_repos.files }}" + when: + - rule_1_2_4 + tags: + - level1 + - scored + - section_1 + - rule_1.2.4 + +- name: "1.3.1 | Ensure sudo is installed (Scored)" + dnf: + name: sudo + state: present + when: + - rule_1_3_1 + tags: + - level1 + - scored + - section_1 + - aide + - rule_1.3.1 + +- name: "1.3.2 | Ensure sudo commands use pty (Scored)" + lineinfile: + dest: /etc/sudoers + regexp: '^\s*Defaults\s+use_pty' + line: 'Defaults use_pty' + create: yes + when: + - rule_1_3_2 + tags: + - level1 + - scored + - section_1 + - aide + - rule_1.3.2 + +- name: "1.3.3 | Ensure sudo log file exists (Scored)" + lineinfile: + dest: /etc/sudoers + regexp: '^\s*Defaults\s+([^#]+,\s*)?logfile="\/var\/log\/sudo\.log"' + line: 'Defaults logfile="/var/log/sudo.log"' + create: yes + when: + - rule_1_3_3 + tags: + - level1 + - scored + - section_1 + - aide + - rule_1.3.3 + +- name: "1.4.1 | Ensure AIDE is installed (Scored)" + package: + name: aide + state: present + when: + - rule_1_4_1|bool + tags: + - level1 + - scored + - aide + - patch + - rule_1.4.1 + +- name: "1.4.1 | Ensure AIDE is installed (Scored)" + command: /usr/sbin/aide --init -B 'database_out=file:/var/lib/aide/aide.db.gz' + args: + creates: /var/lib/aide/aide.db.gz + changed_when: no + failed_when: no + async: 45 + poll: 0 + when: + - config_aide|bool + - rule_1_4_1|bool + tags: + - level1 + - scored + - aide + - patch + - rule_1.4.1 + +- name: "1.4.2 | Ensure filesystem integrity is regularly checked (Scored)" + cron: + name: Run AIDE integrity check + cron_file: "{{ aide_cron['cron_file'] }}" + user: "{{ aide_cron['cron_user'] }}" + minute: "{{ aide_cron['aide_minute'] | default('0') }}" + hour: "{{ aide_cron['aide_hour'] | default('5') }}" + day: "{{ aide_cron['aide_day'] | default('*') }}" + month: "{{ aide_cron['aide_month'] | default('*') }}" + weekday: "{{ aide_cron['aide_weekday'] | default('*') }}" + job: "{{ aide_cron['aide_job'] }}" + when: + - rule_1_4_2|bool + tags: + - level1 + - scored + - aide + - file_integrity + - patch + - rule_1.4.2 + +- name: "1.5.1 | Ensure permissions on bootloader config are configured (Scored)" + stat: + path: /etc/grub2.cfg + register: grub_cfg + when: + - rule_1_5_1|bool + tags: + - level1 + - scored + - grub + - patch + - rule_1.5.1 + +- name: "1.5.1 | Ensure permissions on bootloader config are configured (Scored)" + file: + path: "{{ grub_cfg.stat.lnk_source }}" + owner: root + group: root + mode: 0600 + when: + - grub_cfg.stat.exists and grub_cfg.stat.islnk + - rule_1_5_1|bool + tags: + - level1 + - scored + - grub + - patch + - rule_1.5.1 + +- name: "1.5.2 | Ensure bootloader password is set (Scored)" + block: + - name: "1.5.2 | Ensure bootloader password is set (Scored) | Install Python Expect" + dnf: + name: python3-pexpect + state: latest + + - name: "1.5.2 | Ensure bootloader password is set (Scored) | Configure" + expect: + command: grub2-setpassword + responses: + (?i)password: "{{ bootloader_password }}" + notify: generate new grub config + when: + - rule_1_5_2 + tags: + - level1 + - scored + - section_1 + - grub + - rule_1.5.2 + +- name: "NOT1.5.3 | Ensure authentication required for single user mode (Scored)" + block: + - name: "NOT1.5.3 | Ensure authentication required for single user mode (Scored) - emergency" + lineinfile: + dest: /usr/lib/systemd/system/emergency.service + regexp: '/sbin/sulogin' + line: 'execstart=-/usr/lib/systemd/systemd-sulogin-shell rescue' + + - name: "NOT1.5.3 | Ensure authentication required for single user mode (Scored) - rescue" + lineinfile: + dest: /usr/lib/systemd/system/rescue.service + regexp: '/sbin/sulogin' + line: 'execstart=-/usr/lib/systemd/systemd-sulogin-shell rescue' + when: + - rule_1_5_3 + - ansible_distribution_major_version == 8 + tags: + - level1 + - level2 + - section_1 + - rule_1.5.3 + +- name: "1.6.1 | Ensure core dumps are restricted (Scored)" + lineinfile: + state: present + dest: /etc/security/limits.conf + regexp: '^#?\\*.*core' + line: '* hard core 0' + insertbefore: '^# End of file' + when: + - rule_1_6_1|bool + tags: + - level1 + - scored + - limits + - patch + - rule_1.6.1 + +- name: "1.6.1 | Ensure core dumps are restricted (Scored)" + sysctl: + name: fs.suid_dumpable + value: '0' + state: present + reload: yes + sysctl_set: yes + ignoreerrors: yes + when: + - rule_1_6_1|bool + tags: + - level1 + - scored + - sysctl + - patch + - rule_1.6.1 + +- name: "1.6.2 | Ensure address space layout randomization (ASLR) is enabled (Scored)" + sysctl: + name: kernel.randomize_va_space + value: '2' + state: present + reload: yes + sysctl_set: yes + ignoreerrors: yes + when: + - rule_1_6_2|bool + tags: + - level1 + - scored + - patch + - rule_1.6.2 + +- name: "1.7.1.2 | Ensure SELinux is not disabled in bootloader configuration (Scored)" + replace: + dest: /etc/default/grub + regexp: '(selinux|enforcing)\s*=\s*0\s*' + follow: yes + register: selinux_grub_patch + ignore_errors: yes + notify: generate new grub config + when: + - selinux_state == "enforcing" + - rule_1_7_1_2|bool + tags: + - level2 + - scored + - patch + - rule_1.7.1.2 + +############################################### +#- name: "1.7.1.3 | Ensure SELinux policy is configured (Scored)" +# selinux: +# conf: /etc/selinux/config +# policy: "{{ selinux_policy }}" +# state: "{{ selinux_state }}" +# debug: +# msg: "--> Not relevant" +# changed_when: no +# when: +# - rule_1_7_1_3|bool +# tags: +# - level2 +# - scored +# - selinux +# - patch +# - rule_1.7.1.3 +################################################ +- name: "1.7.1.4 | Ensure the SELinux state is enforcing (Scored)" + selinux: + conf: /etc/selinux/config + policy: "{{ selinux_policy }}" + state: "{{ selinux_state }}" + when: + - rule_1_7_1_4|bool + tags: + - level2 + - scored + - selinux + - patch + - rule_1.7.1.4 + + +- name: "1.7.1.5 | Ensure no unconfined services exist (Scored)" + shell: ps -eZ | grep unconfined_service_t + changed_when: no + failed_when: no + when: + - rule_1_7_1_5|bool + tags: + - level2 + - scored + - patch + - rule_1.7.1.5 + +- name: "1.7.1.6 | Ensure SETroubleshoot is not installed (Scored)" + dnf: + name: setroubleshoot + state: absent + when: + - rule_1_7_1_6|bool + tags: + - level2 + - scored + - selinux + - patch + - rule_1.7.1.6 + +- name: "1.7.1.7 | Ensure the MCS Translation Service (mcstrans) is not installed (Scored)" + dnf: + name: mcstrans + state: absent + when: + - rule_1_7_1_7|bool + tags: + - level2 + - scored + - patch + - rule_1.7.1.7 + +- name: "1.7.1.1 | Ensure SELinux is installed" + package: + name: libselinux + state: present + when: + - rule_1_7_1_1|bool + tags: + - level2 + - scored + - patch + - rule_1.7.1.1 + +- name: "1.8.1.1 | Ensure message of the day is configured properly (Scored)" + template: + src: etc/motd.j2 + dest: /etc/motd + when: + - rule_1_8_1_1|bool + tags: + - level1 + - banner + - patch + - rule_1.8.1.1 + +- name: "1.8.1.2 | Ensure local login warning banner is configured properly (Scored)" + template: + src: etc/issue.j2 + dest: /etc/issue + when: + - rule_1_8_1_2|bool + tags: + - level1 + - patch + - rule_1.8.1.2 + +- name: "1.8.1.3 | Ensure remote login warning banner is configured properly (Scored)" + template: + src: etc/issue.net.j2 + dest: /etc/issue.net + when: + - rule_1_8_1_3|bool + tags: + - level1 + - banner + - patch + - rule_1.8.1.3 + +- name: "1.8.1.4 | Ensure permissions on /etc/motd are configured (Scored)" + file: + dest: /etc/motd + state: file + owner: root + group: root + mode: 0644 + when: + - rule_1_8_1_4|bool + tags: + - level1 + - perms + - patch + - rule_1.8.1.4 + +- name: "1.8.1.5 | Ensure permissions on /etc/issue are configured (Scored)" + file: + dest: /etc/issue + state: file + owner: root + group: root + mode: 0644 + when: + - rule_1_8_1_5|bool + tags: + - level1 + - perms + - patch + - rule_1.8.1.5 + +- name: "1.8.1.6 | Ensure permissions on /etc/issue.net are configured (Scored)" + file: + dest: /etc/issue.net + state: file + owner: root + group: root + mode: 0644 + when: + - rule_1_8_1_6|bool + tags: + - level1 + - perms + - patch + - rule_1.8.1.6 + +- name: "1.8.2 | Ensure GDM login banner is configured (Scored)" + lineinfile: + dest: "{{ item.file }}" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + state: present + create: yes + owner: root + group: root + mode: 0644 + with_items: + - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } + - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } + - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } + - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } + - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-enable', line: 'banner-message-enable=true' } + - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-text', line: "banner-message-text='{{ warning_banner }}' " } + when: + - gui|bool + - rule_1_8_2|bool + tags: + - level1 + - level2 + - patch + - rule_1.8.2 + +- name: "1.9 | Ensure updates, patches, and additional security software are installed (Scored)" + dnf: + name: "*" + state: latest + when: + - rule_1_9 + tags: + - level1 + - level2 + - section_1 + - rule_1.9 + +- name: "1.10 | Ensure system-wide crypto policy is not legacy (Scored)" + block: + - name: 1.10 | Ensure system-wide crypto policy is not legacy (Scored) | Check Current Crypto Policy + slurp: + src: /etc/crypto-policies/config + register: cryptopolicies + + - name: 1.10 | Ensure system-wide crypto policy is not legacy (Scored) | Update if not to DEFAULT + command: update-crypto-policies --set DEFAULT + when: + - '"LEGACY" in cryptopolicies.content|b64decode' + when: + - rule_1_10 + tags: + - level1 + - level2 + - section_1 + - rule_1.10 + - crypto + +- name: "1.11 | Ensure system-wide crypto policy is FUTURE or FIPS (Scored)" + shell: | + update-crypto-policies --set {{ crypto_policy }} + update-crypto-policies + when: + - rule_1_11|bool + tags: + - level1 + - level2 + - patch + - rule_1.11 + - crypto \ No newline at end of file diff --git a/tasks/section_2.yml b/tasks/section_2.yml new file mode 100644 index 0000000..43d43fd --- /dev/null +++ b/tasks/section_2.yml @@ -0,0 +1,339 @@ +--- +- name: "2.1.1 | Ensure xinetd is not installed" + dnf: + name: xinetd + state: absent + when: + - rule_2_1_1 + tags: + - section_2 + - level1 + - scored + - rule_2.1.1 + +- name: "2.2.1.1 | Ensure time synchronization is in use" + dnf: + name: chrony + state: present + tags: + - section_2 + - level1 + - rule_2.2.1.1 + +- name: "2.2.1.2 | Ensure chrony is configured" + template: + src: etc/chrony.conf.j2 + dest: /etc/chrony.conf + owner: root + group: root + mode: 0644 + when: + - rule_2_2_1_2 + tags: + - section_2 + - level1 + - rule_2.2.1.2 + +- name: "2.2.2 | Ensure X Window System is not installed" + package: + state: absent + name: + - "xorg-x11*" + when: + - not xwindows_required | bool + - "'xorg-x11' in ansible_facts.packages" + - rule_2_2_2 + tags: + - section_2 + - level1 + - scored + - xwindows + - rule_2.2.2 + +- name: "Update facts" + block: + - name: "Update package facts" + package_facts: + manager: "auto" + + - name: "Update service facts" + service_facts: + when: + - not xwindows_required | bool + - "'xorg-x11' in ansible_facts.packages" + - rule_2_2_2 + tags: + - section_2 + - level1 + - scored + - xwindows + - rule_2.2.2 + + +- name: "2.2.3 | Ensure rsync service is not enabled " + systemd: + name: rsyncd + state: stopped + enabled: no + when: + - "'rsyncd.service' in ansible_facts.services" + - rule_2_2_3 + tags: + - section_2 + - level1 + - rule_2.2.3 + +- name: "2.2.4 | Ensure Avahi Server is not enabled" + systemd: + name: avahi-daemon + state: stopped + enabled: no + when: + - "'avahi-daemon' in ansible_facts.services" + - rule_2_2_4 + tags: + - section_2 + - level1 + - scored + - avahi + - services + - rule_2.2.4 + +- name: "2.2.5 | Ensure SNMP Server is not enabled" + systemd: + name: snmpd + state: stopped + enabled: no + when: + - "'snmpd.service' in ansible_facts.services" + - rule_2_2_5 + tags: + - section_2 + - level1 + - rule_2.2.5 + +- name: "2.2.6 | Ensure HTTP Proxy Server is not enabled" + systemd: + name: squid + state: stopped + enabled: no + when: + - "'squid.service' in ansible_facts.services" + - rule_2_2_6 + tags: + - section_2 + - level1 + - rule_2.2.6 + +- name: "2.2.7 | Ensure Samba is not enabled" + systemd: + name: smb + state: stopped + enabled: no + when: + - "'smb.service' in ansible_facts.services" + - rule_2_2_7 + tags: + - section_2 + - level1 + - rule_2.2.7 + +- name: "2.2.8 | Ensure IMAP and POP3 server is not enabled" + systemd: + name: dovecot + state: stopped + enabled: no + when: + - "'dovecot.service' in ansible_facts.services" + - rule_2_2_8 + tags: + - section_2 + - level1 + - scored + - rule_2.2.8 + +- name: "2.2.9 | Ensure HTTP server is not enabled (Scored)" + systemd: + name: httpd + state: stopped + enabled: no + when: + - "'httpd.service' in ansible_facts.services" + - rule_2_2_9 + tags: + - section_2 + - level1 + - scored + - rule_2.2.9 + +- name: "2.2.10 | Ensure FTP Server is not enabled (Scored)" + systemd: + name: vsftpd + state: stopped + enabled: no + when: + - "'vsftpd.service' in ansible_facts.services" + - rule_2_2_10 + tags: + - section_2 + - level1 + - scored + - rule_2.2.10 + +- name: "2.2.11 | Ensure DNS Server is not enabled" + systemd: + name: named + state: stopped + enabled: no + when: + - "'named.service' in ansible_facts.services" + - rule_2_2_11 + tags: + - section_2 + - level1 + - rule_2.2.11 + +- name: "2.2.12 | Ensure NFS is not enabled" + systemd: + name: nfs + state: stopped + enabled: no + when: + - "'nfs.service' in ansible_facts.services" + - rule_2_2_12 + tags: + - section_2 + - level1 + - scored + - nfs + - rpc + - services + - rule_2.2.12 + +- name: "2.2.13 | Ensure RPC is not enabled" + systemd: + name: rpcbind + state: stopped + enabled: no + when: + - "'rpcbind.service' in ansible_facts.services" + - rule_2_2_13 + tags: + - section_2 + - level1 + - scored + - nfs + - rpc + - services + - rule_2.2.13 + +- name: "2.2.14 | Ensure LDAP server is not enabled" + service: + name: slapd + state: stopped + enabled: no + when: + - "'slapd.service' in ansible_facts.services" + - rule_2_2_14 + tags: + - section_2 + - level1 + - scored + - ldap + - services + - rule_2.2.14 + +- name: "2.2.15 | Ensure DHCP Server is not enabled" + systemd: + name: dhcpd + state: stopped + enabled: no + when: + - "'dhcpd.service' in ansible_facts.services" + - rule_2_2_14 + tags: + - section_2 + - level1 + - scored + - dhcp + - services + - rule_2.2.14 + +- name: "2.2.16 | Ensure CUPS is not enabled" + systemd: + name: cups + state: stopped + enabled: no + when: + - "'cups.service' in ansible_facts.services" + - rule_2_2_16 + tags: + - section_2 + - level1 + - scored + - cups + - services + - rule_2.2.16 + +- name: "2.2.17 | Ensure NIS Server is not enabled" + systemd: + name: ypserv + state: stopped + enabled: no + when: + - "'ypserv.service' in ansible_facts.services" + - rule_2_2_17 + tags: + - section_2 + - level1 + - rule_2.2.17 + +- name: "2.2.18 | Ensure mail transfer agent is configured for local-only mode" + lineinfile: + dest: /etc/postfix/main.cf + regexp: "^(#)?inet_interfaces" + line: "inet_interfaces = loopback-only" + when: + - "'postfix' in ansible_facts.packages" + - rule_2_2_18 + tags: + - section_2 + - level1 + - rule_2.2.18 + +- name: "2.3.1 | Ensure NIS Client is not installed" + dnf: + name: ypbind + state: absent + when: + - "'ypbind' in ansible_facts.packages" + - rule_2_3_1 + tags: + - section_2 + - level1 + - rule_2.3.1 + +- name: "2.3.2 | Ensure telnet client is not installed" + dnf: + name: telnet + state: absent + when: + - "'telnet' in ansible_facts.packages" + - rule_2_3_2 + tags: + - section_2 + - level1 + - rule_2.3.2 + +- name: "2.3.3 | Ensure LDAP client is not installed" + dnf: + name: openldap-clients + state: absent + when: + - "'openldap-clients' in ansible_facts.packages" + - rule_2_3_3 + tags: + - section_2 + - level1 + - rule_2.3.3 + diff --git a/templates/etc/chrony.conf.j2 b/templates/etc/chrony.conf.j2 new file mode 100644 index 0000000..4b039aa --- /dev/null +++ b/templates/etc/chrony.conf.j2 @@ -0,0 +1,93 @@ +# This the default chrony.conf file for the Debian chrony package. After +# editing this file use the command 'invoke-rc.d chrony restart' to make +# your changes take effect. John Hasler 1998-2008 + +# See www.pool.ntp.org for an explanation of these servers. Please +# consider joining the project if possible. If you can't or don't want to +# use these servers I suggest that you try your ISP's nameservers. We mark +# the servers 'offline' so that chronyd won't try to connect when the link +# is down. Scripts in /etc/ppp/ip-up.d and /etc/ppp/ip-down.d use chronyc +# commands to switch it on when a dialup link comes up and off when it goes +# down. Code in /etc/init.d/chrony attempts to determine whether or not +# the link is up at boot time and set the online status accordingly. If +# you have an always-on connection such as cable omit the 'offline' +# directive and chronyd will default to online. +# +# Note that if Chrony tries to go "online" and dns lookup of the servers +# fails they will be discarded. Thus under some circumstances it is +# better to use IP numbers than host names. + +{% for server in time_synchronization_servers -%} +server {{ server }} minpoll 8 +{% endfor %} + +# Look here for the admin password needed for chronyc. The initial +# password is generated by a random process at install time. You may +# change it if you wish. + +keyfile /etc/chrony/chrony.keys + +# Set runtime command key. Note that if you change the key (not the +# password) to anything other than 1 you will need to edit +# /etc/ppp/ip-up.d/chrony, /etc/ppp/ip-down.d/chrony, /etc/init.d/chrony +# and /etc/cron.weekly/chrony as these scripts use it to get the password. + +commandkey 1 + +# I moved the driftfile to /var/lib/chrony to comply with the Debian +# filesystem standard. + +driftfile /var/lib/chrony/chrony.drift + +# Comment this line out to turn off logging. + +log tracking measurements statistics +logdir /var/log/chrony + +# Stop bad estimates upsetting machine clock. + +maxupdateskew 100.0 + +# Dump measurements when daemon exits. + +dumponexit + +# Specify directory for dumping measurements. + +dumpdir /var/lib/chrony + +# Let computer be a server when it is unsynchronised. + +local stratum 10 + +# Allow computers on the unrouted nets to use the server. + +#allow 10/8 +#allow 192.168/16 +#allow 172.16/12 + +# This directive forces `chronyd' to send a message to syslog if it +# makes a system clock adjustment larger than a threshold value in seconds. + +logchange 0.5 + +# This directive defines an email address to which mail should be sent +# if chronyd applies a correction exceeding a particular threshold to the +# system clock. + +# mailonchange root@localhost 0.5 + +# This directive tells chrony to regulate the real-time clock and tells it +# Where to store related data. It may not work on some newer motherboards +# that use the HPET real-time clock. It requires enhanced real-time +# support in the kernel. I've commented it out because with certain +# combinations of motherboard and kernel it is reported to cause lockups. + +# rtcfile /var/lib/chrony/chrony.rtc + +# If the last line of this file reads 'rtconutc' chrony will assume that +# the CMOS clock is on UTC (GMT). If it reads '# rtconutc' or is absent +# chrony will assume local time. The line (if any) was written by the +# chrony postinst based on what it found in /etc/default/rcS. You may +# change it if necessary. +rtconutc \ No newline at end of file diff --git a/templates/etc/issue.j2 b/templates/etc/issue.j2 new file mode 100644 index 0000000..b21bb89 --- /dev/null +++ b/templates/etc/issue.j2 @@ -0,0 +1 @@ +{{ warning_banner_issue }} \ No newline at end of file diff --git a/templates/etc/issue.net.j2 b/templates/etc/issue.net.j2 new file mode 100644 index 0000000..b21bb89 --- /dev/null +++ b/templates/etc/issue.net.j2 @@ -0,0 +1 @@ +{{ warning_banner_issue }} \ No newline at end of file diff --git a/templates/etc/motd.j2 b/templates/etc/motd.j2 new file mode 100644 index 0000000..b2c1cf4 --- /dev/null +++ b/templates/etc/motd.j2 @@ -0,0 +1 @@ +{{ warning_banner_motd }} \ No newline at end of file diff --git a/templates/tmp.mount.j2 b/templates/tmp.mount.j2 new file mode 100644 index 0000000..c21bfeb --- /dev/null +++ b/templates/tmp.mount.j2 @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Temporary Directory +Documentation=man:hier(7) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems +ConditionPathIsSymbolicLink=!/tmp +DefaultDependencies=no +Conflicts=umount.target +Before=local-fs.target umount.target + +[Mount] +What=tmpfs +Where=/tmp +Type=tmpfs +Options=mode=1777,strictatime{% if rule_1_1_3 %},noexec{%endif%}{% if rule_1_1_4 %},nodev{%endif%}{% if rule_1_1_5 %},nosuid{%endif%} + +# Make 'systemctl enable tmp.mount' work: +[Install] +WantedBy=local-fs.target \ No newline at end of file diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..3cbc194 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - cis-centos \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..6d55809 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for cis-centos \ No newline at end of file