diff --git a/README.md b/README.md new file mode 100644 index 0000000..21326e0 --- /dev/null +++ b/README.md @@ -0,0 +1,203 @@ +ansible-role-auditd +=================== + +Manage the auditd system, create rules and define its behaviour. +For an extensive guide on how to setup system auditing please refer to the +official [Red Hat System Auditing Guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/chap-system_auditing). + +A Short Auditd Rule Documentation +--------------------------------- + +The linux auditing daemon supports a wide variety of different rules. These can be grouped into the following rule classes. + +## Control Rules + +These rules allow to modify the audit system's behavior and some of its configs. + +### Options + +```bash +# set the max amount of audit buffer in the kernel +$ auditctl -b 8192 +# set the action that is performed when an error is detected. 2=kernelpanic +$ auditctl -f 2 +# enable/disable the audit system or lock the configuration. 2=lock +$ auditctl -e 2 +# set the rate of generated messages per second. 0=nolimit +$ auditctl -r 0 +# report the status of the audit system +$ auditctl -s +# list all currently loaded audit rules +$ auditctl -l +# delete all rules currently loaded by the audit system +$ auditctl -D +``` + +## System Call Rules + +These rules allow the logging of system calls that any specified program generates. + +### Options + +```bash +$ auditctl -a action,filter -s system_call -F field=value -k comment +``` + +* `action` and `filter` specify when a certain event is logged. + * `action` can be either `always` or `never` + * `filter` can be one of the following: `task`, `exit`, `user`, `exclude` +* `system_call` specifies the system call by its name + * see `/usr/include/asm/unistd_64.h` for a list of all possible syscalls. +* `field=value` specifies additional options that further modify the rule to match events based on a specified architecture, group, id, pid. + * see `man 8 auditctl` for a complete list +* `comment` is an optional string that helps identify which rule or set of rules generated a particular log entry. + +### Examples + +```bash +$ auditctl -a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change +``` + +- Create a log entry each time `adjtimex` or `settimeofday` sys calls are used by a program, on a 64bit architecture. + + +```bash +$ auditctl -a always,exit -S unlink -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete +``` + +- Defines a rule that creates a log entry every time a file is deleted or renamed by a user whose id is 1000 or larger. +- The option `-F auid!=4294967295` is used to exclude users whose login uid is not set. + +## File System Rules + +Also known as file watches, these rules allow the auditing of accesses to a file or directory from any program. + +### Options + +```bash +$ auditctl -w path_to_file -p permissions -k comment +``` + +* `path_to_file` is the file or directory that is audited +* `permissions` are the permissions that are logged + * `r` - read acces to a file or directory + * `w` - write acces to a file or directory + * `x` - execute access to a file or directory + * `a` - change in the file or directories attributes + +### Example + +```bash +$ auditctl -w /etc/passwd -p wa -k passwd_changes +``` + +- Create a rule that logs each write access or attribute change of /etc/passwd + +## Executable File Rules + +These rules allow the logging of executables. + +### Options + +```bash +$ auditctl -a always,exit -F exe=path_to_exe -k comment +``` + +* `action` and `filter` see above. +* `system_call` see above. +* `comment` see above. +* `path_to_exe` is the absolute path to the executable file. + +### Example + +```bash +$ auditctl -a always,exit -F exe=/bin/id -F arch=b64 -S execve -k execute_bin_id +``` + +- Create a rule that logs all executions of the /bin/id program. + + +Requirements +------------ + +None. + +Role Variables +-------------- + +To define different types of system auditing rules use the following variable/syntax. + +```yaml +auditd_custom_rules: + # define a file system rule + - type: filesystem + file: /etc/passwd + permissions: wa + comment: passwd_changes + # define a system call rule + - type: syscall + action: always,exit + filters: + - arch=b64 + syscalls: + - adjtimex + - settimeofday + comment: time_change + # define an executable rule + - type: executable + action: always,exit + filters: + - arch=b64 + executable: /bin/id + comment: execution_bin_id +``` + +All the configurations for the audit daemon are configurable as variables. See `defaults/main.yaml` for more details. + +Dependencies +------------ + +None. + +Example Playbook +---------------- + +```yaml +--- + +- name: auditd test play + hosts: all + become: true + vars: + auditd_custom_rules: + - type: filesystem + file: /etc/passwd + permissions: wa + comment: passwd_changes + - type: syscall + action: always,exit + filters: + - arch=b64 + syscalls: + - adjtimex + - settimeofday + comment: time_change + - type: executable + action: always,exit + filters: + - arch=b64 + executable: /bin/id + comment: execution_bin_id + roles: + - auditd +``` + +License +------- + +GPLv3 + +Author Information +------------------ + +Aaron Schmocker (aaron@0x29a.ch) diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..cc6bd42 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,105 @@ +--- + +## +# main config +## + +auditd_config_dir: /etc/audit +auditd_config_file: auditd.conf +auditd_custom_rules_dir: /etc/audit/rules.d +auditd_local_events: "yes" +auditd_write_logs: "yes" + +## +# log files +## + +auditd_log_file: /var/log/audit/audit.log +# Log format. Options: RAW and NOLOG +auditd_log_format: RAW +# Log file owner group. +auditd_log_group: root +# Number of logfiles to keep. +auditd_num_logs: 5 +# Maximum log file size in megabytes. +auditd_max_log_file_size: 8 +# What happens if max log file size is reached. +# Options: ignore, syslog, suspend, rotate, keep_logs +auditd_max_log_file_action: rotate +# Number of megabytes of free space left when space_left_action gets performed. +auditd_space_left: 75 +# Options: ignore, syslog, email, exec, suspend, single, halt +auditd_space_left_action: syslog +# Number of megabytes of free space left when admin_space_left_action gets performed. +auditd_admin_space_left: 50 +# Options: ignore, syslog, email, exec, suspend, single, halt +auditd_admin_space_left_action: suspend +# Action to be taken on disk full +auditd_disk_full_action: suspend +# Action to be taken on disk error +auditd_disk_error_action: suspend + + +## +# misc configs +## + +# priority boost for the audit daemon, default: 4 +auditd_priority_boost: 4 +# How to flush auditd records to disk. +# Options: none, incremental, data, sync +auditd_flush_strategy: INCREMENTAL_ASYNC +# How many records to write before issuing an explicit flush. +# only used if flush_strategy is set to incremental. +auditd_flush_freq: 50 +# Blocking/lossless or non-blocking/lossy communication between the audit +# daemon and the dispatcher queue. The buffer size is 128k, so lossy should do fine. +auditd_disp_qos: lossy +# Auditd dispatcher software, defaults to audispd. See man audispd. +auditd_dispatcher: /sbin/audispd +# How computer node names are insertet into the audit event stream. +# Options: none, hostname, fqd, numeric (means ip), user +auditd_name_format: NUMERIC +# Wheter to use kerberos5 +auditd_enable_krb5: "no" +# Krb5 principal for this server. Default = auditd +auditd_krb5_principal: auditd + +## +# connections +## + +# Controls how many pending connections are allowed. Default = 5 +auditd_tcp_listen_queue: 5 +# Controls how many concurrent connections from one ip adress are allowed. +auditd_tcp_max_per_addr: 1 +# Wheter or not to use tcp_wrappers. +auditd_use_libwrap: "yes" +# Number of seconds a client is allowed to idle. +auditd_tcp_client_max_idle: 0 +# Distribute network originating events to the dispatcher +auditd_distribute_network: "no" + +## +# alerting +## + +# Whom to notify. If not root, sendmail has to be configured +auditd_action_mail_acct: root + + +## +# custom rules +## + +# Kernel buffer size for custom rules +auditd_custom_buffer_size: 32768 +# Enable flag +# Options: 0=disable, 1=enable, 2=locked, requires reboot to unlock +auditd_custom_enable_flag: 1 +# What happens in case of a failure. +# Options: 0=silent, 1=printk, 2=panic +auditd_custom_on_failure: 1 +# Maximum amount of messages per second per rule before the failure flag gets executed +# Default = 0, (=none) +auditd_custom_max_msg_per_sec: 100 diff --git a/handlers/main.yaml b/handlers/main.yaml new file mode 100644 index 0000000..01b406f --- /dev/null +++ b/handlers/main.yaml @@ -0,0 +1,11 @@ +--- + +- name: restart auditd + service: + name: auditd + state: restarted + use: service + +- name: load custom rules + command: augenrules --load + diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/tasks/configuration.yaml b/tasks/configuration.yaml new file mode 100644 index 0000000..e2a088f --- /dev/null +++ b/tasks/configuration.yaml @@ -0,0 +1,23 @@ +--- + +- name: push auditd configuration + template: + src: auditd.conf.j2 + dest: '{{ auditd_config_dir }}/{{ auditd_config_file }}' + mode: '0640' + notify: + - restart auditd + +- name: push custom rules + template: + src: custom.rules.j2 + dest: '{{ auditd_custom_rules_dir }}/custom.rules' + mode: '0666' + notify: + - load custom rules + +- name: start and enable auditd + service: + name: auditd + state: started + enabled: true diff --git a/tasks/installation.yaml b/tasks/installation.yaml new file mode 100644 index 0000000..d3e925d --- /dev/null +++ b/tasks/installation.yaml @@ -0,0 +1,12 @@ +--- + +- name: install packages + package: + name: '{{ auditd_packages }}' + state: present + +- name: ensure rules.d directory exists + file: + path: '{{ auditd_custom_rules_dir }}' + state: directory + mode: '0750' diff --git a/tasks/main.yaml b/tasks/main.yaml new file mode 100644 index 0000000..962c8fa --- /dev/null +++ b/tasks/main.yaml @@ -0,0 +1,19 @@ +--- + +- name: load variables based on distribution type + include_vars: '{{ item }}' + with_first_found: + - '{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yaml' + - '{{ ansible_os_family }}.yaml' + tags: + - 'auditd_vars' + +- name: install auditd and its components + import_tasks: installation.yaml + tags: + - 'auditd_installation' + +- name: push auditd config + import_tasks: configuration.yaml + tags: + - 'auditd_configuration' diff --git a/templates/auditd.conf.j2 b/templates/auditd.conf.j2 new file mode 100644 index 0000000..4d873d8 --- /dev/null +++ b/templates/auditd.conf.j2 @@ -0,0 +1,28 @@ +local_events = {{ auditd_local_events }} +write_logs = {{ auditd_write_logs }} +log_file = {{ auditd_log_file }} +log_format = {{ auditd_log_format }} +log_group = {{ auditd_log_group }} +priority_boost = {{ auditd_priority_boost }} +flush = {{ auditd_flush_strategy }} +freq = {{ auditd_flush_freq }} +num_logs = {{ auditd_num_logs }} +disp_qos = {{ auditd_disp_qos }} +dispatcher = {{ auditd_dispatcher }} +name_format = {{ auditd_name_format }} +max_log_file = {{ auditd_max_log_file_size }} +max_log_file_action {{ auditd_max_log_file_action }} +action_mail_acct = {{ auditd_action_mail_acct }} +space_left = {{ auditd_space_left }} +space_left_action = {{ auditd_space_left_action }} +admin_space_left = {{ auditd_admin_space_left }} +admin_space_left_action = {{ auditd_admin_space_left_action }} +disk_full_action = {{ auditd_disk_full_action }} +disk_error_action = {{ auditd_disk_error_action }} +tcp_listen_queue = {{ auditd_tcp_listen_queue }} +tcp_max_per_addr = {{ auditd_tcp_max_per_addr }} +use_libwrap = {{ auditd_use_libwrap }} +tcp_client_max_idle = {{ auditd_tcp_client_max_idle }} +enable_krb5 = {{ auditd_enable_krb5 }} +krb5_principal = {{ auditd_krb5_principal }} +distribute_network = {{ auditd_distribute_network }} diff --git a/templates/custom.rules.j2 b/templates/custom.rules.j2 new file mode 100644 index 0000000..c668c2c --- /dev/null +++ b/templates/custom.rules.j2 @@ -0,0 +1,25 @@ +# Delete all previous rules +-D +# Set buffer size +-b {{ auditd_custom_buffer_size }} +# Define enable flag +-e {{ auditd_custom_enable_flag }} +# Define what happens in case of a failure +-f {{ auditd_custom_on_failure }} +# Max amount of messages per second +-r {{ auditd_custom_max_msg_per_sec }} + +# ansible generated custom rules +{% if auditd_custom_rules is defined %} +{% for rule in auditd_custom_rules %} +{% if rule.type == 'filesystem' %} +-w {{ rule.file }} -p {{ rule.permissions }} -k {{ rule.comment }} +{% endif %} +{% if rule.type == 'syscall' %} +-a {{ rule.action }}{% if rule.filters is defined %}{% for filter in rule.filters %} -F {{ filter }}{% endfor %}{% endif %}{% if rule.syscalls is defined %}{% for syscall in rule.syscalls %} -S {{ syscall }}{% endfor %}{% endif %} -k {{ rule.comment }} +{% endif %} +{% if rule.type == 'executable' %} +-a {{ rule.action }} -F exe={{ rule.executable }}{% if rule.filters is defined %}{% for filter in rule.filters %} -F {{ filter }}{% endfor %}{% endif %} -S execve -k {{ rule.comment }} +{% endif %} +{% endfor %} +{% endif %} 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..8b369ad --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - ansible-role-auditd diff --git a/vars/RedHat_7.yaml b/vars/RedHat_7.yaml new file mode 100644 index 0000000..f96d603 --- /dev/null +++ b/vars/RedHat_7.yaml @@ -0,0 +1,4 @@ +--- + +auditd_packages: audit +auditd_dependencies: diff --git a/vars/RedHat_8.yaml b/vars/RedHat_8.yaml new file mode 100644 index 0000000..f96d603 --- /dev/null +++ b/vars/RedHat_8.yaml @@ -0,0 +1,4 @@ +--- + +auditd_packages: audit +auditd_dependencies: