diff --git a/README.md b/README.md index 232e28c..b991fbe 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,18 @@ Otherwise puppet will drop an error (duplicate resource)! `true` if you want to remove SUID/SGID bits from any file, that is not explicitly configured in a `blacklist`. This will make every Puppet run search through the mounted filesystems looking for SUID/SGID bits that are not configured in the default and user blacklist. If it finds an SUID/SGID bit, it will be removed, unless this file is in your `whitelist`. * `dry_run_on_unknown = false` like `remove_from_unknown` above, only that SUID/SGID bits aren't removed. It will still search the filesystems to look for SUID/SGID bits but it will only print them in your log. This option is only ever recommended, when you first configure `remove_from_unknown` for SUID/SGID bits, so that you can see the files that are being changed and make adjustments to your `whitelist` and `blacklist`. +* `enable_auditd = false` + when auditd should be managed by this module, set this to true, **after deploying this, a reboot is required to affectuate it!** +* `auditd_max_log_file = 8` + when auditd handling by the module is enabled, this will make sure that at most 8MB of log files are on disk, when the action `rotate` is chosen for `auditd_max_log_files_action` +* `auditd_max_log_file_action = 'rotate'` + this option controls how auditd should handle old log files, valid options are `rotate`, `ignore`, `syslog`, `suspend` and `keep_logs`, if full CIS DIL Benchmark compliance is required, this needs to be set to `keep_logs` and another system of rotation needs to be set up (after the logs have been sent to a remote server) +* `apparmor_in_use = false` + this needs to be set to true if apparmor is in use, to make sure the profiles are monitored for changes +* `selinux_in_use = false` + this needs to be set to true if selinux is in use, to make sure the profiles are monitored for changes +* `privileged_binaries = []` + add all your privileged binaries to this array to monitor usage of them, get a list with `find -xdev \( -perm -4000 -o -perm -2000 \) -type f` and replace with a partitions that can be used to execute binaries * `unwanted_packages = []` packages that should be removed from the system * `wanted_packages = []` diff --git a/manifests/auditd.pp b/manifests/auditd.pp new file mode 100644 index 0000000..d265e06 --- /dev/null +++ b/manifests/auditd.pp @@ -0,0 +1,415 @@ +# === Copyright +# +# Copyright 2018, Kumina B.V., Tim Stoop +# Licensed under the Apache License, Version 2.0 (the "License"); +# http://www.apache.org/licenses/LICENSE-2.0 +# + +# == Class: os_hardening::auditd +# +# Configures Auditd according to the CIS DIL Benchmark +# +class os_hardening::auditd ( + Boolean $enable = false, + Integer $max_log_file = 8, + Enum['rotate', 'ignore', 'syslog', 'suspend', 'keep_logs'] $max_log_file_action = 'rotate', + Integer $num_logs = 5, + Boolean $selinux_in_use = false, + Boolean $apparmor_in_use = false, + Array $privileged_binaries = [], +) { + + case $::operatingsystem { + debian, ubuntu: { + $audit_rules = '/etc/audit/rules.d/cis.rules' + $audit_rules_last = '/etc/audit/rules.d/zzz_last.rules' + $network_file = '/etc/network' + $non_system_users_from = 1000 + } + default: { + $audit_rules = '/etc/audit/audit.rules' + $audit_rules_last = $audit_rules + $network_file = '/etc/sysconfig/network' + $non_system_users_from = 500 + } + } + + if $enable { + $package_action = 'installed' + } else { + $package_action = 'purged' + } + + package { 'auditd': + ensure => $package_action, + } + + if $enable { + service { 'auditd': + ensure => running, + enable => true, + } + + file { $audit_rules: + ensure => file, + owner => 'root', + group => 'root', + mode => '0640', + } + + if $audit_rules_last != $audit_rules { + file { $audit_rules_last: + ensure => file, + owner => 'root', + group => 'root', + mode => '0640', + } + } + + file_line { 'CIS DIL Benchmark 4.1.1.1 - Ensure audit log storage size is configured': + path => '/etc/audit/auditd.conf', + match => '^max_log_file =.*', + line => "max_log_file = ${max_log_file}", + notify => Service['auditd'], + } + + file_line { + 'CIS DIL Benchmark 4.1.1.2 - Ensure system is disabled when audit logs are full, space_left_action': + path => '/etc/audit/auditd.conf', + match => '^space_left_action =.*', + notify => Service['auditd'], + line => 'space_left_action = email'; + 'CIS DIL Benchmark 4.1.1.2 - Ensure system is disabled when audit logs are full, action_mail_acct': + path => '/etc/audit/auditd.conf', + match => '^action_mail_acct =.*', + notify => Service['auditd'], + line => 'action_mail_acct = root'; + 'CIS DIL Benchmark 4.1.1.2 - Ensure system is disabled when audit logs are full, admin_space_left_action': + path => '/etc/audit/auditd.conf', + match => '^admin_space_left_action =.*', + notify => Service['auditd'], + line => 'admin_space_left_action = halt'; + } + + file_line { 'CIS DIL Benchmark 4.1.1.3 - Ensure audit logs are not automatically deleted': + path => '/etc/audit/auditd.conf', + match => '^max_log_file_action =.*', + line => "max_log_file_action = ${max_log_file_action}", + notify => Service['auditd'], + } + + if $max_log_file_action == 'rotate' { + file_line { 'CIS DIL Benchmark 4.1.1.3 not implemented, number of logs to keep': + path => '/etc/audit/auditd.conf', + match => '^num_logs =.*', + line => "num_logs = ${num_logs}", + notify => Service['auditd'], + } + } + + # CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled + exec { 'CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled': + command => "/bin/sed -i -e 's/GRUB_CMDLINE_LINUX_DEFAULT=\"\\(.*\\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\\1 audit=1\"/g' /etc/default/grub;", + unless => "/bin/grep GRUB_CMDLINE_LINUX /etc/default/grub | /bin/grep -q 'audit=1'", + notify => Exec['CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled - update grub'], + } + + file_line { + 'CIS DIL Benchmark 4.1.4 - Ensure events that modify date and time information are collected - line 1, 32 bit': + path => $audit_rules, + line => '-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.4 - Ensure events that modify date and time information are collected - line 2, 32 bit': + path => $audit_rules, + line => '-a always,exit -F arch=b32 -S clock_settime -k time-change', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.4 - Ensure events that modify date and time information are collected - line 3': + path => $audit_rules, + line => '-w /etc/localtime -p wa -k time-change', + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { + 'CIS DIL Benchmark 4.1.4 - Ensure events that modify date and time information are collected - line 1, 64 bit': + path => $audit_rules, + line => '-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.4 - Ensure events that modify date and time information are collected - line 2, 64 bit': + path => $audit_rules, + line => '-a always,exit -F arch=b64 -S clock_settime -k time-change', + notify => Service['auditd']; + } + } + + file_line { + 'CIS DIL Benchmark 4.1.5 - Ensure events that modify user/group information are collected - line 1': + path => $audit_rules, + line => '-w /etc/group -p wa -k identity', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.5 - Ensure events that modify user/group information are collected - line 2': + path => $audit_rules, + line => '-w /etc/passwd -p wa -k identity', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.5 - Ensure events that modify user/group information are collected - line 3': + path => $audit_rules, + line => '-w /etc/gshadow -p wa -k identity', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.5 - Ensure events that modify user/group information are collected - line 4': + path => $audit_rules, + line => '-w /etc/shadow -p wa -k identity', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.5 - Ensure events that modify user/group information are collected - line 5': + path => $audit_rules, + line => '-w /etc/security/opasswd -p wa -k identity', + notify => Service['auditd']; + } + + file_line { + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 1, 32bit': + path => $audit_rules, + line => '-a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 2': + path => $audit_rules, + line => '-w /etc/issue -p wa -k system-locale', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 3': + path => $audit_rules, + line => '-w /etc/issue.net -p wa -k system-locale', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 4': + path => $audit_rules, + line => '-w /etc/hosts -p wa -k system-locale', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 5': + path => $audit_rules, + line => "-w ${network_file} -p wa -k system-locale", + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { + 'CIS DIL Benchmark 4.1.6 - Ensure events that modify the system\'s network environment are collected - line 1, 64bit': + path => $audit_rules, + line => '-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale', + notify => Service['auditd']; + } + } + + if $selinux_in_use { + file_line { + 'CIS DIL Benchmark 4.1.7 - Ensure events that modify the system\'s Mandatory Access Controls are collected - line 1, selinux': + path => $audit_rules, + line => '-w /etc/selinux/ -p wa -k MAC-policy', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.7 - Ensure events that modify the system\'s Mandatory Access Controls are collected - line 2, selinux': + path => $audit_rules, + line => '-w /usr/share/selinux/ -p wa -k MAC-policy', + notify => Service['auditd']; + } + } + + if $apparmor_in_use { + file_line { + 'CIS DIL Benchmark 4.1.7 - Ensure events that modify the system\'s Mandatory Access Controls are collected - line 1, apparmor': + path => $audit_rules, + line => '-w /etc/apparmor/ -p wa -k MAC-policy', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.7 - Ensure events that modify the system\'s Mandatory Access Controls are collected - line 2, apparmor': + path => $audit_rules, + line => '-w /etc/apparmor.d/ -p wa -k MAC-policy', + notify => Service['auditd']; + } + } + + file_line { + 'CIS DIL Benchmark 4.1.8 - Ensure login and logout events are collected - line 1': + path => $audit_rules, + line => '-w /var/log/faillog -p wa -k logins', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.8 - Ensure login and logout events are collected - line 2': + path => $audit_rules, + line => '-w /var/log/lastlog -p wa -k logins', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.8 - Ensure login and logout events are collected - line 3': + path => $audit_rules, + line => '-w /var/log/tallylog -p wa -k logins', + notify => Service['auditd']; + } + + file_line { + 'CIS DIL Benchmark 4.1.9 - Ensure session initiation information is collected - line 1': + path => $audit_rules, + line => '-w /var/run/utmp -p wa -k session', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.9 - Ensure session initiation information is collected - line 2': + path => $audit_rules, + line => '-w /var/log/wtmp -p wa -k logins', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.9 - Ensure session initiation information is collected - line 3': + path => $audit_rules, + line => '-w /var/log/btmp -p wa -k logins', + notify => Service['auditd']; + } + + file_line { + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 1, 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 2, 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 3, 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 1, 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 2, 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.10 - Ensure discretionary access control permission modification events are collected - line 3, 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=${non_system_users_from} -F auid!=4294967295 -k perm_mod", + notify => Service['auditd']; + } + } + + file_line { + 'CIS DIL Benchmark 4.1.11 - Ensure unsuccessful unauthorized file access attempts are collected - line 1, 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=${non_system_users_from} -F auid!=4294967295 -k access", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.11 - Ensure unsuccessful unauthorized file access attempts are collected - line 2, 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=${non_system_users_from} -F auid!=4294967295 -k access", + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { + 'CIS DIL Benchmark 4.1.11 - Ensure unsuccessful unauthorized file access attempts are collected - line 1, 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=${non_system_users_from} -F auid!=4294967295 -k access", + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.11 - Ensure unsuccessful unauthorized file access attempts are collected - line 2, 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=${non_system_users_from} -F auid!=4294967295 -k access", + notify => Service['auditd']; + } + } + + $privileged_binaries.each |String $binary| { + # TODO We should sanitise $binary. + file_line { "CIS DIL Benchmark 4.1.12 - Ensure use of privileged commands is collected - $binary": + path => $audit_rules, + line => "-a always,exit -F path=${binary} -F perm=x -F auid>=${non_system_users_from} -F auid!=4294967295 -k privileged", + notify => Service['auditd']; + } + } + + file_line { 'CIS DIL Benchmark 4.1.13 - Ensure successful file system mounts are collected - 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S mount -F auid>=${non_system_users_from} -F auid!=4294967295 -k mounts", + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { 'CIS DIL Benchmark 4.1.13 - Ensure successful file system mounts are collected - 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S mount -F auid>=${non_system_users_from} -F auid!=4294967295 -k mounts", + notify => Service['auditd']; + } + } + + file_line { 'CIS DIL Benchmark 4.1.14 - Ensure file deletion events by users are collected - 32bit': + path => $audit_rules, + line => "-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=${non_system_users_from} -F auid!=4294967295 -k delete", + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { 'CIS DIL Benchmark 4.1.14 - Ensure file deletion events by users are collected - 64bit': + path => $audit_rules, + line => "-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=${non_system_users_from} -F auid!=4294967295 -k delete", + notify => Service['auditd']; + } + } + + file_line { + 'CIS DIL Benchmark 4.1.15 - Ensure changes to system administration scope (sudoers) is collected - line 1': + path => $audit_rules, + line => '-w /etc/sudoers -p wa -k scope', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.15 - Ensure changes to system administration scope (sudoers) is collected - line 2': + path => $audit_rules, + line => '-w /etc/sudoers.d/ -p wa -k scope', + notify => Service['auditd']; + } + + file_line { 'CIS DIL Benchmark 4.1.16 - Ensure system administrator actions (sudolog) are collected': + path => $audit_rules, + line => '-w /var/log/sudo.log -p wa -k actions', + notify => Service['auditd']; + } + + file_line { + 'CIS DIL Benchmark 4.1.17 - Ensure kernel module loading and unloading is collected - line 1': + path => $audit_rules, + line => '-w /sbin/insmod -p x -k modules', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.17 - Ensure kernel module loading and unloading is collected - line 2': + path => $audit_rules, + line => '-w /sbin/rmmod -p x -k modules', + notify => Service['auditd']; + 'CIS DIL Benchmark 4.1.17 - Ensure kernel module loading and unloading is collected - line 3': + path => $audit_rules, + line => '-w /sbin/modprobe -p x -k modules', + notify => Service['auditd']; + } + + if $::architecture == 'amd64' { + file_line { 'CIS DIL Benchmark 4.1.17 - Ensure kernel module loading and unloading is collected - line 4 64bit': + path => $audit_rules, + line => '-a always,exit -F arch=b64 -S init_module -S delete_module -k modules', + notify => Service['auditd']; + } + } + + if $::architecture == 'i386' { + file_line { 'CIS DIL Benchmark 4.1.17 - Ensure kernel module loading and unloading is collected - line 4 32bit': + path => $audit_rules, + line => '-a always,exit -F arch=b32 -S init_module -S delete_module -k modules', + notify => Service['auditd']; + } + } + + exec { 'CIS DIL Benchmark 4.1.18 - Ensure the audit configuration is immutable': + command => "/bin/echo '-e 2' >> ${audit_rules_last}", + unless => "/bin/grep '^\s*[^#]' ${audit_rules_last} | /usr/bin/tail -1 | /bin/grep -q -e '^-e 2$'", + notify => Service['auditd']; + } + } else { + exec { 'CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled - disable': + command => "/bin/sed -i -e 's/GRUB_CMDLINE_LINUX_DEFAULT=\"\\(.*\\)audit=1\\(.*\\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\\1\\2\"/g' /etc/default/grub;", + onlyif => "/bin/grep GRUB_CMDLINE_LINUX /etc/default/grub | /bin/grep -q 'audit=1'", + notify => Exec['CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled - update grub'], + } + } + + exec { 'CIS DIL Benchmark 4.1.3 - Ensure auditing for processes that start prior to auditd is enabled - update grub': + command => '/usr/sbin/update-grub', + refreshonly => true, + } + +} diff --git a/manifests/init.pp b/manifests/init.pp index 92a3865..85781be 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -68,6 +68,15 @@ Boolean $enable_rpfilter = true, Boolean $enable_log_martians = true, + Boolean $enable_auditd = false, + Integer $auditd_max_log_file = 8, + Enum['rotate', 'ignore', 'syslog', 'suspend', 'keep_logs'] + $auditd_max_log_file_action = 'rotate', + Integer $auditd_num_logs = 5, + Boolean $apparmor_in_use = false, + Boolean $selinux_in_use = false, + Array $privileged_binaries = [], + Array $unwanted_packages = [], Array $wanted_packages = [], Array $disabled_services = [], @@ -202,6 +211,16 @@ } } + class { 'os_hardening::auditd': + enable => $enable_auditd, + max_log_file => $auditd_max_log_file, + max_log_file_action => $auditd_max_log_file_action, + num_logs => $auditd_num_logs, + selinux_in_use => $selinux_in_use, + apparmor_in_use => $apparmor_in_use, + privileged_binaries => $privileged_binaries, + } + class { 'os_hardening::services': unwanted_packages => $unwanted_packages, wanted_packages => $wanted_packages,