Initial commit of the go_audit role

Only Ubuntu 18.04 64 bit is supported.
go-audit can not run on FreeBSD.

The audit rules are based on the CIS benchmark for Ubuntu 18.04 v1.0.0
https://www.cisecurity.org/benchmark/ubuntu_linux/

Audit logs are written to syslog until it has been decided how to notify
users. syslog was chosen because these logs are already being rotated.

Testing

    $ cd roles/go_audit/tests
    $ vagrant up
    $ vagrant snapshot save init
    $ ansible-playbook -i inventory test.yml
    $ vagrant snapshot restore init
    $ ansible-playbook -i inventory test.yml -e 'go_audit_build=true'
This commit is contained in:
Tim H 2017-12-01 12:11:25 -05:00
parent 43ed5b2aaa
commit 1bd21ca90b
14 changed files with 392 additions and 0 deletions

View file

@ -0,0 +1,20 @@
---
# Directory in which to store the go-audit binary.
go_audit_bindir: /usr/local/bin
# true: Build go-audit from source on the target host.
# false: Use the pre-built binaries located in the role's files/ directory.
go_audit_build: false
# Directory to use when building go-audit. All source code and other temporary
# files will be stored here. The directory is *not* explicitly removed.
go_audit_build_dir: /tmp/go-audit-build
# Golang environment used for building go-audit from source.
go_audit_go_env:
GOROOT: "{{ go_audit_build_dir }}/go"
GOPATH: "{{ go_audit_build_dir }}/go-work"
PATH:
"{{ go_audit_build_dir }}/go/bin:\
{{ go_audit_build_dir }}/go-work/bin:\
{{ ansible_env.PATH }}"

BIN
roles/go_audit/files/go-audit Executable file

Binary file not shown.

View file

@ -0,0 +1,11 @@
---
- name: audit configuration changed
debug:
msg: >
The audit configuration changed.
For the settings to be applied a system reboot may be required.
- name: Update grub2 configuration
command: update-grub
register: go_audit_update_grub_result
failed_when: "'error' in go_audit_update_grub_result.stderr"

View file

@ -0,0 +1,58 @@
---
- name: Ensure that the build dependencies are installed
package:
name: "{{ item }}"
state: present
with_items:
- git
- make
- name: Ensure that the required build directories exist
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ go_audit_build_dir }}"
- "{{ go_audit_go_env.GOROOT }}"
- "{{ go_audit_go_env.GOPATH }}/src/github.com/slackhq/go-audit"
- name: "Download the Go distribution (version: {{ go_audit_go_version }})"
get_url:
url: "{{ go_audit_go_download_url }}"
dest: "{{ go_audit_build_dir }}/{{ go_audit_go_filename }}"
checksum: "sha256:{{ go_audit_go_checksum }}"
- name: "Download go-audit (commit: {{ go_audit_commit }})"
get_url:
url: "{{ go_audit_download_url }}"
dest: "{{ go_audit_build_dir }}/{{ go_audit_filename }}"
checksum: "sha256:{{ go_audit_checksum }}"
- name: Extract the Go distribution
unarchive:
src: "{{ go_audit_build_dir }}/{{ go_audit_go_filename }}"
dest: "{{ go_audit_go_env.GOROOT }}"
extra_opts: "--strip-components=1"
remote_src: true
creates: "{{ go_audit_go_env.GOROOT }}/LICENSE"
- name: Extract go-audit
unarchive:
src: "{{ go_audit_build_dir }}/{{ go_audit_filename }}"
dest: "{{ go_audit_go_env.GOPATH }}/src/github.com/slackhq/go-audit"
extra_opts: "--strip-components=1"
remote_src: true
creates: "{{ go_audit_go_env.GOPATH }}/src/github.com/slackhq/go-audit/LICENSE"
- name: Install govendor
command: go get -u github.com/kardianos/govendor
args:
creates: "{{ go_audit_go_env.GOPATH }}/bin/govendor"
environment: "{{ go_audit_go_env }}"
- name: Build go-audit
command: make
args:
chdir: "{{ go_audit_go_env.GOPATH }}/src/github.com/slackhq/go-audit"
creates: "go-audit"
environment: "{{ go_audit_go_env }}"

View file

@ -0,0 +1,54 @@
---
- name: Install the auditd package (provides auditctl)
package:
name: auditd
state: present
- name: "Ensure that the {{ go_audit_bindir }} directory exists"
file:
path: "{{ go_audit_bindir }}"
state: directory
- name: Install the go-audit binary
copy:
src: "{{ go_audit_go_env.GOPATH }}/src/github.com/slackhq/go-audit/go-audit"
dest: "{{ go_audit_bindir }}/go-audit"
owner: root
group: "{{ root_group|default('root') }}"
mode: 0755
remote_src: true
when:
- go_audit_build|bool
- name: Install the pre-built go-audit binary
copy:
src: "go-audit"
dest: "{{ go_audit_bindir }}/go-audit"
owner: root
group: "{{ root_group|default('root') }}"
mode: 0755
remote_src: false
when:
- not go_audit_build|bool
- name: Calculate the checksum of the go-audit binary
stat:
path: "{{ go_audit_bindir }}/go-audit"
checksum_algorithm: sha256
register: go_audit_binary_st
- name: Verify the checksum of the go-audit binary
assert:
that:
- go_audit_binary_st.stat.checksum is defined
- go_audit_binary_st.stat.checksum == go_audit_binary_checksum
- name: Generate the go-audit configuration file
template:
src: go-audit.yaml.j2
dest: "{{ config_prefix|default('/') }}etc/go-audit.yaml"
owner: root
group: "{{ root_group|default('root') }}"
mode: 0644
notify:
- audit configuration changed

View file

@ -0,0 +1,27 @@
---
- name: Check distribution and version
fail:
msg: >
{{ ansible_distribution }} version {{ ansible_distribution_version }}
({{ ansible_machine }}) is not supported.
when:
- ansible_system != "Linux" or
ansible_machine not in ['amd64', 'x86_64'] or
ansible_distribution != "Ubuntu"
- block:
- name: Build go-audit
include_tasks: build.yml
when: go_audit_build|bool
- import_tasks: install.yml
- name: Include tasks for Ubuntu
include_tasks: ubuntu.yml
when: ansible_distribution == 'Ubuntu'
rescue:
- debug: var=fail_hint
tags: always
- name: Fail
fail:
tags: always

View file

@ -0,0 +1,42 @@
---
# Adding a grub command-line argument via Ansible in a generic, idempotent
# manner is non-trivial. The regex below assumes that a line of the format
# GRUB_CMDLINE_LINUX=".*" exists and inserts audit=1 right before the closing
# quote. The regex fails if no GRUB_CMDLINE_LINUX key exists, the value is not
# enclosed in double quotes, or the value contains escaped double quotes.
- name: Ubuntu | Enable auditing for processes that start prior to go-audit
lineinfile:
dest: /etc/default/grub
regexp: '^(GRUB_CMDLINE_LINUX=(?!.*audit=1)".*)(".*)'
line: '\1 audit=1\2'
backrefs: true
state: present
notify:
- Update grub2 configuration
- audit configuration changed
- name: Ubuntu | Generate the systemd unit configuration file
template:
src: systemd.go-audit.service.j2
dest: /etc/systemd/system/go-audit.service
owner: root
group: "{{ root_group|default('root') }}"
mode: 0644
- name: Ubuntu | Stop and disable the auditd service
systemd:
name: auditd.service
state: stopped
enabled: false
- name: Ubuntu | Start and enable the go-audit service
systemd:
name: go-audit.service
state: started
enabled: yes
- name: Ubuntu | Prevent duplicate audit entries in syslog
systemd:
name: systemd-journald-audit.socket
state: stopped
masked: true

View file

@ -0,0 +1,121 @@
# go-audit configuration file
#
# For general documentation and specifications related to the Linux Audit
# project see https://github.com/linux-audit/audit-documentation/wiki
# The wiki contains definitions of all audit fields, messages, and ranges.
output:
syslog:
enabled: true
tag: "go-audit"
# Configure the type of socket this should be, default is unixgram
# This maps to `network` in golangs net.Dial: https://golang.org/pkg/net/#Dial
network: unixgram
# Set the remote address to connect to, this can be a path or an ip address
# This maps to `address` in golangs net.Dial: https://golang.org/pkg/net/#Dial
address: /dev/log
# Sets the facility and severity for all events. See the table below for help
# The default is 132 which maps to local0 | warn
priority: 129 # local0 | emerg
# Based on CIS_Ubuntu_Linux_18.04_LTS_Benchmark_v1.0.0.pdf
# https://www.cisecurity.org/benchmark/ubuntu_linux/
rules:
# Ensure events that modify date and time information are collected
- -a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
- -a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change
- -a always,exit -F arch=b64 -S clock_settime -k time-change
- -a always,exit -F arch=b32 -S clock_settime -k time-change
- -w /etc/localtime -p wa -k time-change
# Ensure events that modify user/group information are collected
- -w /etc/group -p wa -k identity
- -w /etc/passwd -p wa -k identity
- -w /etc/gshadow -p wa -k identity
- -w /etc/shadow -p wa -k identity
- -w /etc/security/opasswd -p wa -k identity
# Ensure events that modify the system's network environment are collected
- -a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale
- -a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale
- -w /etc/issue -p wa -k system-locale
- -w /etc/issue.net -p wa -k system-locale
- -w /etc/hosts -p wa -k system-locale
- -w /etc/network -p wa -k system-locale
# Ensure events that modify the system's Mandatory Access Controls are collected
- -w /etc/apparmor/ -p wa -k MAC-policy
- -w /etc/apparmor.d/ -p wa -k MAC-policy
# Ensure login and logout events are collected
- -w /var/log/faillog -p wa -k logins
- -w /var/log/lastlog -p wa -k logins
- -w /var/log/tallylog -p wa -k logins
# Ensure session initiation information is collected
- -w /var/run/utmp -p wa -k session
- -w /var/log/wtmp -p wa -k logins
- -w /var/log/btmp -p wa -k logins
# Ensure discretionary access control permission modification events are collected
- -a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod
- -a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod
- -a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod
- -a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod
- -a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod
- -a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod
# Ensure unsuccessful unauthorized file access attempts are collected
- -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access
- -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access
- -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access
- -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access
# Ensure use of privileged commands is collected
# XXX Incomplete list. Chose some potentially relevant commands. Thoughts?
# For a full list run `find <partition> -xdev \( -perm -4000 -o -perm -2000 \) -type f`
- -a always,exit -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/newgidmap -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/chage -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/newuidmap -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/chfn -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/at -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/pkexec -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/expiry -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/bin/mount -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/bin/fusermount -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/bin/umount -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
- -a always,exit -F path=/bin/su -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
# Ensure successful file system mounts are collected
- -a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts
- -a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts
# Ensure file deletion events by users are collected
- -a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
- -a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
# Ensure changes to system administration scope (sudoers) is collected
- -w /etc/sudoers -p wa -k scope
- -w /etc/sudoers.d/ -p wa -k scope
# Ensure system administrator actions (sudolog) are collected
- -w /var/log/sudo.log -p wa -k actions
# Ensure kernel module loading and unloading is collected
- -w /sbin/insmod -p x -k modules
- -w /sbin/rmmod -p x -k modules
- -w /sbin/modprobe -p x -k modules
- -a always,exit -F arch=b64 -S init_module -S delete_module -k modules
# Ensure the audit configuration is immutable
- -e 2

View file

@ -0,0 +1,11 @@
[Unit]
Description = go-audit
After=network.target auditd.service
Conflicts = auditd.service
[Service]
Type = simple
ExecStart = {{ go_audit_bindir }}/go-audit -config {{ config_prefix|default('/') }}etc/go-audit.yaml
[Install]
WantedBy = multi-user.target

17
roles/go_audit/tests/Vagrantfile vendored Normal file
View file

@ -0,0 +1,17 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "ubuntu18.04-amd64", primary: true do |ubuntu|
ubuntu.vm.box = "ubuntu/bionic64"
ubuntu.vm.network "private_network", ip: "192.168.144.64"
ubuntu.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y --no-install-recommends python
SHELL
end
config.vm.synced_folder ".", "/vagrant", disabled: true
end

View file

@ -0,0 +1,7 @@
all:
hosts:
ubuntu18.04-amd64:
ansible_host: 192.168.144.64
ansible_user: vagrant
ansible_ssh_private_key_file:
.vagrant/machines/ubuntu18.04-amd64/virtualbox/private_key

View file

@ -0,0 +1 @@
../../

View file

@ -0,0 +1,5 @@
---
- hosts: all
become: yes
roles:
- go_audit

View file

@ -0,0 +1,18 @@
---
go_audit_go_version: 1.11.5
go_audit_go_filename: "go{{ go_audit_go_version }}.linux-amd64.tar.gz"
go_audit_go_download_url: "https://storage.googleapis.com/golang/{{ go_audit_go_filename }}"
# SHA256 checksums copied from https://golang.org/dl/
go_audit_go_checksum: ff54aafedff961eb94792487e827515da683d61a5f9482f668008832631e5d25
# go-audit is not versioned, therefore a commit hash is used instead.
go_audit_commit: daf7385d7bea16bb1b51fbceeba07e7f3ad78f24
go_audit_filename: "{{ go_audit_commit }}.tar.gz"
go_audit_download_url: "https://github.com/slackhq/go-audit/archive/{{ go_audit_filename }}"
# SHA256 checksum manually computed from
# https://github.com/slackhq/go-audit/archive/{{ go_audit_commit }}.tar.gz
go_audit_checksum: 7327796309fbd08086e28f69b4091b7d2f977c4d1384becfe3bc256ccc6c053b
# SHA256 checksums manually computed from the binaries located in this role's
# files/ directory. The binaries were build via this role (go_audit_build: yes).
go_audit_binary_checksum: 223c904f06dcb2f7205ec8b4e5509d88bd9987bc1d64adb7e59ea7fc7232bbae