Lynis
- 🐧 Linux Command Line
Ansible Playbook
Core
Install Lynis
dfn install -y lynis
Audit System
lynis audit system
# lynis audit system --nocolors > audit.txt
Custom Scripts
mkdir -p /usr/local/lynis
/usr/local/lynis/run_lynis.sh
#!/bin/bash
REPORT_DIR="/var/log/lynis/reports"
EVENT_DIR="/var/log/lynis/events"
mkdir -p "$REPORT_DIR"
mkdir -p "$EVENT_DIR"
DATE=$(date +%Y%m%d_%H%M%S)
REPORT_NAME="${DATE}.dat"
EVENT_NAME="${DATE}.log"
echo "Running Lynis Audit..."
lynis audit system --nocolors > "$EVENT_DIR/$EVENT_NAME"
DEFAULT_REPORT="/var/log/lynis-report.dat"
if [ -f "$DEFAULT_REPORT" ]; then
cp "$DEFAULT_REPORT" "$REPORT_DIR/$REPORT_NAME"
echo "Report saved to: $REPORT_DIR/$REPORT_NAME"
echo "Event saved to: $EVENT_DIR/$EVENT_NAME"
else
echo "Lynis report not found at $DEFAULT_REPORT."
fi
/usr/local/lynis/compare_lynis.sh
#!/bin/bash
# Define the directory where Lynis reports are stored
REPORT_DIR="/var/log/lynis/reports"
# Get the 5 most recent files, sorted by modification time
FILES=($(ls -t "$REPORT_DIR"/*.dat | head -n 5))
# Check if there are at least 2 files
if [[ ${#FILES[@]} -lt 2 ]]; then
echo -e "\033[31mError: Not enough report files in $REPORT_DIR. At least 2 are needed.\033[0m"
exit 1
fi
# List the files with indices
echo -e "\033[36mAvailable reports (sorted by last modified):\033[0m"
for i in "${!FILES[@]}"; do
echo "$((i + 1)). $(basename "${FILES[i]}")"
done
# Prompt the user to select files by index
read -p "Select the OLD report by number (1-${#FILES[@]}): " OLD_INDEX
read -p "Select the NEW report by number (1-${#FILES[@]}): " NEW_INDEX
# Validate user input
if ! [[ "$OLD_INDEX" =~ ^[1-5]$ ]] || ! [[ "$NEW_INDEX" =~ ^[1-5]$ ]]; then
echo -e "\033[31mError: Invalid selection. Please enter a number between 1 and 5.\033[0m"
exit 1
fi
# Get the paths of the selected files
OLD_REPORT="${FILES[$((OLD_INDEX - 1))]}"
NEW_REPORT="${FILES[$((NEW_INDEX - 1))]}"
# Ensure the selected files are not the same
if [[ "$OLD_REPORT" == "$NEW_REPORT" ]]; then
echo -e "\033[31mError: You selected the same file for both OLD and NEW reports.\033[0m"
exit 1
fi
# Extract warnings and suggestions using awk
OLD_WARNINGS=$(awk -F'=\\[|\\]' '/^warning\[\]/ {print $2}' "$OLD_REPORT")
NEW_WARNINGS=$(awk -F'=\\[|\\]' '/^warning\[\]/ {print $2}' "$NEW_REPORT")
OLD_SUGGESTIONS=$(awk -F'=\\[|\\]' '/^suggestion\[\]/ {print $2}' "$OLD_REPORT")
NEW_SUGGESTIONS=$(awk -F'=\\[|\\]' '/^suggestion\[\]/ {print $2}' "$NEW_REPORT")
# Compare warnings and suggestions
echo -e "\033[33mComparing warnings and suggestions between $(basename "$OLD_REPORT") and $(basename "$NEW_REPORT")...\033[0m"
# Compare warnings
echo -e "\033[35m=== Warnings ===\033[0m"
comm -23 <(echo "$OLD_WARNINGS" | sort) <(echo "$NEW_WARNINGS" | sort) | sed 's/^/Removed: /'
comm -13 <(echo "$OLD_WARNINGS" | sort) <(echo "$NEW_WARNINGS" | sort) | sed 's/^/Added: /'
# Compare suggestions
echo -e "\033[34m=== Suggestions ===\033[0m"
comm -23 <(echo "$OLD_SUGGESTIONS" | sort) <(echo "$NEW_SUGGESTIONS" | sort) | sed 's/^/Removed: /'
comm -13 <(echo "$OLD_SUGGESTIONS" | sort) <(echo "$NEW_SUGGESTIONS" | sort) | sed 's/^/Added: /'
/usr/local/lynis/edit_latest_log.sh
#!/bin/bash
# Define the directory where log files are stored
LOG_DIR="/var/log/lynis/events"
# Check if the directory exists
if [[ ! -d "$LOG_DIR" ]]; then
echo "Error: Directory $LOG_DIR does not exist."
exit 1
fi
# Find the latest file in the directory
LATEST_FILE=$(ls -t "$LOG_DIR"/*.log 2>/dev/null | head -n 1)
# Check if a log file exists
if [[ -z "$LATEST_FILE" ]]; then
echo "Error: No log files found in $LOG_DIR."
exit 1
fi
# Open the latest file with vi
echo "Opening the latest log file: $LATEST_FILE"
less -R "$LATEST_FILE"
Skip Tests Based on Server Requirements
ATTENTION: Skipping tests may lead to security vulnerabilities. Make sure you understand the implications before skipping any tests.
/etc/lynis/custom.prf
skip-test=NETW-3015
skip-test=FILE-6310
skip-test=AUTH-9284
skip-test=AUTH-9286
skip-test=AUTH-9282
skip-test=FILE-6336
skip-test=NAME-4028 # dns config
skip-test=KRNL-6000:kernel.modules_disabled
install-mariadb.yml
- name: Install and Secure MariaDB
hosts: all
remote_user: root
vars:
mariadb_root_password: "root-password"
mariadb_bind_address: "127.0.0.1"
tasks:
- name: Add MariaDB repository
get_url:
url: https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
dest: /tmp/mariadb_repo_setup
mode: "0755"
register: mariadb_repo_setup
- name: Run MariaDB repository setup script
command: /tmp/mariadb_repo_setup
register: mariadb_repo_setup_result
changed_when: mariadb_repo_setup_result.rc != 0
- name: Install MariaDB server and client
dnf:
name:
- MariaDB-server
- MariaDB-client
state: present
- name: Enable and start MariaDB
systemd:
name: mariadb
enabled: true
state: started
- name: Run MariaDB secure installation with expect
expect:
command: mariadb-secure-installation
responses:
"Enter current password for root": ""
"Switch to unix_socket authentication": "n"
"Change the root password": "Y"
"New password": "{{ mariadb_root_password }}"
"enter new password": "{{ mariadb_root_password }}"
"Remove anonymous users": "Y"
"Disallow root login remotely": "Y"
"Remove test database and access to it": "Y"
"Reload privilege tables now": "Y"
timeout: 5
- name: Deploy MariaDB configuration
copy:
dest: "/etc/my.cnf"
owner: "mysql"
group: "mysql"
mode: "0644"
content: |
[mysqld]
log_warnings=1
pid-file=/run/mariadb.pid
socket = /run/mysqld.sock
collation-server=utf8mb4_general_ci
character-set-server=utf8mb4
init_connect=SET NAMES utf8mb4
innodb_buffer_pool_size = 200M
query_cache_size = 8M
max_connections = 200
default_storage_engine = InnoDB
slow_query_log = 1
slow_query_log_file = /var/log/mariadb/slow.log
long_query_time = 2
log_error = /var/log/mariadb/error.log
# skip-networking
bind-address = {{ mariadb_bind_address }}
skip-symbolic-links
local-infile=0
[client]
default-character-set=utf8mb4
socket = /run/mysqld.sock
#
# This group is read both by the client and the server
# use it for options that affect everything
#
[client-server]
#
# include *.cnf from the config directory
#
!includedir /etc/my.cnf.d
- name: Create MariaDB log directory if not exists
file:
path: "/var/log/mariadb"
state: directory
owner: "mysql"
group: "mysql"
mode: "0750"
- name: Create MariaDB log files if not exists
file:
path: "{{ item }}"
state: touch
owner: "mysql"
group: "mysql"
mode: "0644"
loop:
- "/var/log/mariadb/slow.log"
- "/var/log/mariadb/error.log"
- name: Restart MariaDB to apply changes
systemd:
name: mariadb
state: restarted