Release 22.05 #155
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -20,6 +20,44 @@ The **patch** part changes is incremented if multiple releases happen the same m
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
## [22.05] 2022-05-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* etc-git: use "ansible-commit" to efficiently commit all available repositories (including /etc inside LXC) from Ansible
|
||||||
|
* minifirewall: compatibility with "legacy" version of minifirewall
|
||||||
|
* minifirewall: configure proxy/backup/sysctl values
|
||||||
|
* munin: Add possibility to install local plugins, and install dhcp_pool plugin
|
||||||
|
* nagios-nrpe: Add a check dhcp_pool
|
||||||
|
* redis: Activate overcommit sysctl
|
||||||
|
* redis: Add log2mail user to redis group
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* dump-server-state: upstream release 22.04.3
|
||||||
|
* evocheck: upstream release 22.04.1
|
||||||
|
* evolinux-base: Add non-free repos & install non-free firmware on dedicated hardware
|
||||||
|
* evolinux-base: rename backup-server-state to dump-server-state
|
||||||
|
* generate-ldif: Add services check for bkctld
|
||||||
|
* minifirewall: restore "force-restart" and fix "restart-if-needed"
|
||||||
|
* minifirewall: tail template follows symlinks
|
||||||
|
* minifirewall: upstream release 22.05
|
||||||
|
* opendkim : add generate opendkim-genkey in sha256 and key 4096
|
||||||
|
* openvpn: use a local copy of files instead of cloning an external git repository
|
||||||
|
* openvpn: use a subnet topology instead of the net30 default topology
|
||||||
|
* tomcat: Tomcat 9 by default with Debian 11
|
||||||
|
* vrrpd: Store sysctl values in specific file
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* etc-git : Remount /usr in rw for git gc in in /usr/share/scripts/
|
||||||
|
* etc-git: Make evocommit fully compatible with OpenBSD
|
||||||
|
* generate-ldif: Correct generated entries for php-fpm in containers
|
||||||
|
* keepalived: repair broken role
|
||||||
|
* minifirewall: fix `failed_when` condition on restart
|
||||||
|
* postfix: Do not send mails through milters a second time after amavis (in packmail)
|
||||||
|
* redis: Remount /usr with RW before adding nagios plugin
|
||||||
|
|
||||||
## [22.03] 2022-03-02
|
## [22.03] 2022-03-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -42,8 +80,6 @@ The **patch** part changes is incremented if multiple releases happen the same m
|
||||||
* lxc: Fail if /var is nosuid
|
* lxc: Fail if /var is nosuid
|
||||||
* openvpn: make it compatible with OpenBSD and add some improvements
|
* openvpn: make it compatible with OpenBSD and add some improvements
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [22.01.3] 2022-01-31
|
## [22.01.3] 2022-01-31
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -8,3 +8,9 @@
|
||||||
service:
|
service:
|
||||||
name: dovecot
|
name: dovecot
|
||||||
state: reloaded
|
state: reloaded
|
||||||
|
|
||||||
|
- name: restart log2mail
|
||||||
|
service:
|
||||||
|
name: log2mail
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
|
|
@ -81,3 +81,25 @@
|
||||||
- include: munin.yml
|
- include: munin.yml
|
||||||
tags:
|
tags:
|
||||||
- dovecot
|
- dovecot
|
||||||
|
|
||||||
|
- name: log2mail is installed
|
||||||
|
apt:
|
||||||
|
name: log2mail
|
||||||
|
state: present
|
||||||
|
tags: dovecot
|
||||||
|
|
||||||
|
- name: dovecot is configured in log2mail
|
||||||
|
blockinfile:
|
||||||
|
path: /etc/log2mail/config/mail.conf
|
||||||
|
create: true
|
||||||
|
owner: log2mail
|
||||||
|
group: adm
|
||||||
|
mode: "0640"
|
||||||
|
block: |
|
||||||
|
file = /var/log/mail.log
|
||||||
|
pattern = "Out of memory"
|
||||||
|
mailto = {{ log2mail_alert_email or general_alert_email | mandatory }}
|
||||||
|
template = /etc/log2mail/mail
|
||||||
|
notify: restart log2mail
|
||||||
|
tags: dovecot
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,4 @@ etc_git_default_commit_message: Ansible run
|
||||||
etc_git_monitor_status: True
|
etc_git_monitor_status: True
|
||||||
etc_git_purge_index_lock_enabled: True
|
etc_git_purge_index_lock_enabled: True
|
||||||
etc_git_purge_index_lock_age: 86400
|
etc_git_purge_index_lock_age: 86400
|
||||||
|
etc_git_config_repositories: True
|
||||||
|
|
187
etc-git/files/ansible-commit
Normal file
187
etc-git/files/ansible-commit
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
VERSION="22.05"
|
||||||
|
|
||||||
|
show_version() {
|
||||||
|
cat <<END
|
||||||
|
ansible-commit version ${VERSION}
|
||||||
|
|
||||||
|
Copyright 2022 Evolix <info@evolix.fr>,
|
||||||
|
Jérémy Lecour <jlecour@evolix.fr>
|
||||||
|
and others.
|
||||||
|
|
||||||
|
ansible-commit comes with ABSOLUTELY NO WARRANTY. This is free software,
|
||||||
|
and you are welcome to redistribute it under certain conditions.
|
||||||
|
See the GNU General Public Licence for details.
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat <<END
|
||||||
|
ansible-commit is a wrapper for evocommit, to be used with Ansible
|
||||||
|
|
||||||
|
END
|
||||||
|
show_usage
|
||||||
|
}
|
||||||
|
show_usage() {
|
||||||
|
cat <<END
|
||||||
|
Usage: ansible-commit --message "add new host"
|
||||||
|
|
||||||
|
Options
|
||||||
|
--message MESSAGE set the commit message
|
||||||
|
--no-lxc disable commit inside LXC containers
|
||||||
|
-V, --version print version number
|
||||||
|
-v, --verbose increase verbosity
|
||||||
|
-n, --dry-run actions are not executed
|
||||||
|
-h, --help print this message and exit
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
is_dry_run() {
|
||||||
|
test "${DRY_RUN}" = "1"
|
||||||
|
}
|
||||||
|
is_verbose() {
|
||||||
|
test "${VERBOSE}" = "1"
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
rc=0
|
||||||
|
common_args="--ansible"
|
||||||
|
if is_verbose; then
|
||||||
|
common_args="${common_args} --verbose"
|
||||||
|
fi
|
||||||
|
if is_dry_run; then
|
||||||
|
common_args="${common_args} --dry-run"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "/etc/.git" ]; then
|
||||||
|
# shellcheck disable=SC2086,SC2090
|
||||||
|
${evocommit_bin} ${common_args} --repository /etc --message "${MESSAGE}"
|
||||||
|
last_rc=$?
|
||||||
|
if [ ${last_rc} -ne 0 ]; then
|
||||||
|
rc=${last_rc}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "/etc/bind/.git" ]; then
|
||||||
|
# shellcheck disable=SC2086,SC2090
|
||||||
|
${evocommit_bin} ${common_args} --repository /etc/bind --message "${MESSAGE}"
|
||||||
|
last_rc=$?
|
||||||
|
if [ ${last_rc} -ne 0 ]; then
|
||||||
|
rc=${last_rc}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "/usr/share/scripts/.git" ]; then
|
||||||
|
# shellcheck disable=SC2086,SC2090
|
||||||
|
${evocommit_bin} ${common_args} --repository /usr/share/scripts --message "${MESSAGE}"
|
||||||
|
last_rc=$?
|
||||||
|
if [ ${last_rc} -ne 0 ]; then
|
||||||
|
rc=${last_rc}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${LXC}" = "1" ] && [ -n "${lxc_ls_bin}" ]; then
|
||||||
|
for container in $(${lxc_ls_bin} -1); do
|
||||||
|
if [ -n "${lxc_config_bin}" ]; then
|
||||||
|
# discovered path
|
||||||
|
etc_path="$(${lxc_config_bin} lxc.lxcpath)/${container}/rootfs/etc"
|
||||||
|
else
|
||||||
|
# fallback to default path
|
||||||
|
etc_path="/var/lib/lxc/${container}/rootfs/etc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "${etc_path}/.git" ]; then
|
||||||
|
# shellcheck disable=SC2086,SC2090
|
||||||
|
${evocommit_bin} ${common_args} --repository "${etc_path}" --message "${MESSAGE}"
|
||||||
|
last_rc=$?
|
||||||
|
if [ ${last_rc} -ne 0 ]; then
|
||||||
|
rc=${last_rc}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit ${rc}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||||
|
while :; do
|
||||||
|
case ${1:-''} in
|
||||||
|
-h|-\?|--help)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-V|--version)
|
||||||
|
show_version
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--message)
|
||||||
|
# message options, with value speparated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
MESSAGE=$2
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
printf 'FAILED: "--message" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--message=?*)
|
||||||
|
# message options, with value speparated by =
|
||||||
|
MESSAGE=${1#*=}
|
||||||
|
;;
|
||||||
|
--message=)
|
||||||
|
# message options, without value
|
||||||
|
printf 'FAILED: "--message" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
--no-lxc)
|
||||||
|
LXC=0
|
||||||
|
;;
|
||||||
|
-n|--dry-run)
|
||||||
|
# disable actual commands
|
||||||
|
DRY_RUN=1
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
# print verbose information
|
||||||
|
VERBOSE=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
# End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*|[[:alnum:]]*)
|
||||||
|
# ignore unknown options
|
||||||
|
printf 'FAILED: Unknown option (ignored): %s\n' "$1" >&2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case: If no more options then break out of the loop.
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "${MESSAGE}" ]; then
|
||||||
|
echo "FAILED: missing message parameter" >&2
|
||||||
|
show_usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
DRY_RUN=${DRY_RUN:-0}
|
||||||
|
VERBOSE=${VERBOSE:-0}
|
||||||
|
LXC=${LXC:-1}
|
||||||
|
|
||||||
|
evocommit_bin=$(command -v evocommit)
|
||||||
|
if [ -z "${evocommit_bin}" ]; then
|
||||||
|
echo "FAILED: evocommit not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
lxc_ls_bin=$(command -v lxc-ls)
|
||||||
|
lxc_config_bin=$(command -v lxc-config)
|
||||||
|
|
||||||
|
main
|
|
@ -6,6 +6,12 @@ repositories="/etc /etc/bind/ /usr/share/scripts"
|
||||||
|
|
||||||
for repository in ${repositories}; do
|
for repository in ${repositories}; do
|
||||||
if [ -d "${repository}/.git" ]; then
|
if [ -d "${repository}/.git" ]; then
|
||||||
|
if [ ${repository} = "/usr/share/scripts" ]; then
|
||||||
|
mount -o remount,rw /usr
|
||||||
|
fi
|
||||||
git --git-dir="${repository}/.git" gc --quiet
|
git --git-dir="${repository}/.git" gc --quiet
|
||||||
|
if [ ${repository} = "/usr/share/scripts" ]; then
|
||||||
|
mount -o remount /usr
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
VERSION="21.10"
|
VERSION="22.04"
|
||||||
|
|
||||||
show_version() {
|
show_version() {
|
||||||
cat <<END
|
cat <<END
|
||||||
evocommit version ${VERSION}
|
evocommit version ${VERSION}
|
||||||
|
|
||||||
Copyright 2021 Evolix <info@evolix.fr>,
|
Copyright 2022 Evolix <info@evolix.fr>,
|
||||||
Jérémy Lecour <jlecour@evolix.fr>
|
Jérémy Lecour <jlecour@evolix.fr>
|
||||||
and others.
|
and others.
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ remount_repository_readwrite() {
|
||||||
if [ "$(get_system)" = "OpenBSD" ]; then
|
if [ "$(get_system)" = "OpenBSD" ]; then
|
||||||
partition=$(stat -f '%Sd' $1)
|
partition=$(stat -f '%Sd' $1)
|
||||||
mount -u -w /dev/${partition} 2>/dev/null
|
mount -u -w /dev/${partition} 2>/dev/null
|
||||||
|
syslog "Re-mount ${mountpoint} as read-write to commit in repository $1"
|
||||||
else
|
else
|
||||||
mountpoint=$(stat -c '%m' $1)
|
mountpoint=$(stat -c '%m' $1)
|
||||||
mount -o remount,rw ${mountpoint}
|
mount -o remount,rw ${mountpoint}
|
||||||
|
@ -73,6 +74,7 @@ remount_repository_readonly() {
|
||||||
if [ "$(get_system)" = "OpenBSD" ]; then
|
if [ "$(get_system)" = "OpenBSD" ]; then
|
||||||
partition=$(stat -f '%Sd' $1)
|
partition=$(stat -f '%Sd' $1)
|
||||||
mount -u -r /dev/${partition} 2>/dev/null
|
mount -u -r /dev/${partition} 2>/dev/null
|
||||||
|
syslog "Re-mount ${mountpoint} as read-only after commit to repository $1"
|
||||||
else
|
else
|
||||||
mountpoint=$(stat -c '%m' $1)
|
mountpoint=$(stat -c '%m' $1)
|
||||||
mount -o remount,ro ${mountpoint} 2>/dev/null
|
mount -o remount,ro ${mountpoint} 2>/dev/null
|
||||||
|
@ -92,8 +94,12 @@ main() {
|
||||||
rc=0
|
rc=0
|
||||||
lock="${GIT_DIR}/index.lock"
|
lock="${GIT_DIR}/index.lock"
|
||||||
if [ -f "${lock}" ]; then
|
if [ -f "${lock}" ]; then
|
||||||
limit=$(date +"%s" -d "now - 1 hour")
|
limit=$(($(date +"%s") - (1 * 60 * 60)))
|
||||||
updated_at=$(stat -c "%Y" "${lock}")
|
if [ "$(get_system)" = "OpenBSD" ]; then
|
||||||
|
updated_at=$(stat -f "%m" "${lock}")
|
||||||
|
else
|
||||||
|
updated_at=$(stat -c "%Y" "${lock}")
|
||||||
|
fi
|
||||||
if [ "$updated_at" -lt "$limit" ]; then
|
if [ "$updated_at" -lt "$limit" ]; then
|
||||||
rm -f "${lock}"
|
rm -f "${lock}"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,52 +1,9 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
# /etc
|
- name: "Execute ansible-commit"
|
||||||
- name: Is /etc a git repository
|
command: "/usr/local/bin/ansible-commit --verbose --message \"{{ commit_message | mandatory }}\""
|
||||||
stat:
|
|
||||||
path: /etc/.git
|
|
||||||
register: _etc_git
|
|
||||||
|
|
||||||
- name: "evocommit /etc"
|
|
||||||
command: "/usr/local/bin/evocommit --ansible --repository /etc --message \"{{ commit_message | mandatory }}\""
|
|
||||||
changed_when:
|
changed_when:
|
||||||
- _etc_git_commit.stdout
|
- _ansible_commit.stdout
|
||||||
- "'CHANGED:' in _etc_git_commit.stdout"
|
- "'CHANGED:' in _ansible_commit.stdout"
|
||||||
ignore_errors: yes
|
ignore_errors: True
|
||||||
register: _etc_git_commit
|
register: _ansible_commit
|
||||||
when:
|
|
||||||
- _etc_git.stat.exists
|
|
||||||
- _etc_git.stat.isdir
|
|
||||||
|
|
||||||
# /etc/bind
|
|
||||||
- name: Is /etc/bind a git repository
|
|
||||||
stat:
|
|
||||||
path: /etc/bind/.git
|
|
||||||
register: _etc_bind_git
|
|
||||||
|
|
||||||
- name: "evocommit /etc/bind"
|
|
||||||
command: "/usr/local/bin/evocommit --ansible --repository /etc/bind --message \"{{ commit_message | mandatory }}\""
|
|
||||||
changed_when:
|
|
||||||
- _etc_bind_git_commit.stdout
|
|
||||||
- "'CHANGED:' in _etc_bind_git_commit.stdout"
|
|
||||||
ignore_errors: yes
|
|
||||||
register: _etc_bind_git_commit
|
|
||||||
when:
|
|
||||||
- _etc_bind_git.stat.exists
|
|
||||||
- _etc_bind_git.stat.isdir
|
|
||||||
|
|
||||||
# /usr/share/scripts
|
|
||||||
- name: Is /usr/share/scripts a git repository
|
|
||||||
stat:
|
|
||||||
path: /usr/share/scripts/.git
|
|
||||||
register: _usr_share_scripts_git
|
|
||||||
|
|
||||||
- name: "evocommit /usr/share/scripts"
|
|
||||||
command: "/usr/local/bin/evocommit --ansible --repository /usr/share/scripts --message \"{{ commit_message | mandatory }}\""
|
|
||||||
changed_when:
|
|
||||||
- _usr_share_scripts_git_commit.stdout
|
|
||||||
- "'CHANGED:' in _usr_share_scripts_git_commit.stdout"
|
|
||||||
ignore_errors: yes
|
|
||||||
register: _usr_share_scripts_git_commit
|
|
||||||
when:
|
|
||||||
- _usr_share_scripts_git.stat.exists
|
|
||||||
- _usr_share_scripts_git.stat.isdir
|
|
35
etc-git/tasks/lxc_commit.yml
Normal file
35
etc-git/tasks/lxc_commit.yml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
- name: "Assert that we have been called with `container` defined"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- container is defined
|
||||||
|
|
||||||
|
- name: "Define path to /etc in {{ container }} container"
|
||||||
|
set_fact:
|
||||||
|
container_etc: "{{ ('/var/lib/lxc', container, 'rootfs/etc') | path_join }}"
|
||||||
|
|
||||||
|
- name: "Check if /etc is a git repository in {{ container }}"
|
||||||
|
stat:
|
||||||
|
path: "{{ (container_etc, '.git') | path_join }}"
|
||||||
|
get_attributes: no
|
||||||
|
get_checksum: no
|
||||||
|
get_mime: no
|
||||||
|
register: "container_etc_git"
|
||||||
|
|
||||||
|
- name: "Evocommit /etc of {{ container }}"
|
||||||
|
command:
|
||||||
|
argv:
|
||||||
|
- /usr/local/bin/evocommit
|
||||||
|
- '--ansible'
|
||||||
|
- '--repository'
|
||||||
|
- "{{ container_etc }}"
|
||||||
|
- '--message'
|
||||||
|
- "{{ commit_message | mandatory }}"
|
||||||
|
changed_when:
|
||||||
|
- "container_etc_git_commit.stdout"
|
||||||
|
- "'CHANGED:' in container_etc_git_commit.stdout"
|
||||||
|
ignore_errors: yes
|
||||||
|
register: "container_etc_git_commit"
|
||||||
|
when:
|
||||||
|
- "container_etc_git.stat.exists"
|
||||||
|
- "container_etc_git.stat.isdir"
|
|
@ -6,109 +6,16 @@
|
||||||
state: present
|
state: present
|
||||||
tags:
|
tags:
|
||||||
- etc-git
|
- etc-git
|
||||||
|
|
||||||
- include_role:
|
|
||||||
name: evolix/remount-usr
|
|
||||||
|
|
||||||
- name: "evocommit script is installed"
|
|
||||||
copy:
|
|
||||||
src: evocommit
|
|
||||||
dest: /usr/local/bin/evocommit
|
|
||||||
mode: "0755"
|
|
||||||
force: yes
|
|
||||||
tags:
|
|
||||||
- etc-git
|
|
||||||
|
|
||||||
- include: repository.yml
|
|
||||||
vars:
|
|
||||||
repository_path: "/etc"
|
|
||||||
gitignore_items:
|
|
||||||
- "aliases.db"
|
|
||||||
- "*.swp"
|
|
||||||
- "postfix/sa-blacklist.access"
|
|
||||||
- "postfix/*.db"
|
|
||||||
- "postfix/spamd.cidr"
|
|
||||||
- "evobackup/.keep-*"
|
|
||||||
- "letsencrypt/.certbot.lock"
|
|
||||||
|
|
||||||
- name: verify /usr/share/scripts presence
|
|
||||||
stat:
|
|
||||||
path: /usr/share/scripts
|
|
||||||
register: _usr_share_scripts
|
|
||||||
|
|
||||||
- include: repository.yml
|
|
||||||
vars:
|
|
||||||
repository_path: "/usr/share/scripts"
|
|
||||||
gitignore_items: []
|
|
||||||
when:
|
when:
|
||||||
- _usr_share_scripts.stat.isdir
|
- ansible_distribution == "Debian"
|
||||||
- ansible_distribution_major_version is version('10', '>=')
|
|
||||||
|
|
||||||
- name: "etc-git-optimize script is installed"
|
- name: Install and configure utilities
|
||||||
copy:
|
include: utils.yml
|
||||||
src: etc-git-optimize
|
|
||||||
dest: /usr/share/scripts/etc-git-optimize
|
|
||||||
mode: "0755"
|
|
||||||
force: yes
|
|
||||||
tags:
|
tags:
|
||||||
- etc-git
|
- etc-git
|
||||||
|
|
||||||
- name: "etc-git-status script is installed"
|
- name: Configure repositories
|
||||||
copy:
|
include: repositories.yml
|
||||||
src: etc-git-status
|
|
||||||
dest: /usr/share/scripts/etc-git-status
|
|
||||||
mode: "0755"
|
|
||||||
force: yes
|
|
||||||
tags:
|
|
||||||
- etc-git
|
|
||||||
|
|
||||||
- name: Check if cron is installed
|
|
||||||
shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'"
|
|
||||||
args:
|
|
||||||
executable: /bin/bash
|
|
||||||
failed_when: False
|
|
||||||
changed_when: False
|
|
||||||
check_mode: no
|
|
||||||
register: is_cron_installed
|
|
||||||
|
|
||||||
- block:
|
|
||||||
- name: Legacy cron jobs for /etc/.git status are absent
|
|
||||||
file:
|
|
||||||
dest: "{{ item }}"
|
|
||||||
state: absent
|
|
||||||
loop:
|
|
||||||
- /etc/cron.monthly/optimize-etc-git
|
|
||||||
- /etc/cron.d/etc-git-status
|
|
||||||
|
|
||||||
- name: Cron job for monthly git optimization
|
|
||||||
cron:
|
|
||||||
name: "Monthly optimization"
|
|
||||||
cron_file: etc-git
|
|
||||||
special_time: "monthly"
|
|
||||||
user: root
|
|
||||||
job: "/usr/share/scripts/etc-git-optimize"
|
|
||||||
|
|
||||||
- name: Cron job for hourly git status
|
|
||||||
cron:
|
|
||||||
name: "Hourly warning for unclean Git repository if nobody is connected"
|
|
||||||
cron_file: etc-git
|
|
||||||
special_time: "hourly"
|
|
||||||
user: root
|
|
||||||
job: "who > /dev/null || /usr/share/scripts/etc-git-status"
|
|
||||||
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
|
|
||||||
|
|
||||||
- name: Cron job for daily git status
|
|
||||||
cron:
|
|
||||||
name: "Daily warning for unclean Git repository"
|
|
||||||
cron_file: etc-git
|
|
||||||
user: root
|
|
||||||
job: "/usr/share/scripts/etc-git-status"
|
|
||||||
minute: "21"
|
|
||||||
hour: "21"
|
|
||||||
weekday: "*"
|
|
||||||
day: "*"
|
|
||||||
month: "*"
|
|
||||||
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
|
|
||||||
when: is_cron_installed.rc == 0
|
|
||||||
tags:
|
tags:
|
||||||
- etc-git
|
- etc-git
|
||||||
|
when: etc_git_config_repositories | bool
|
37
etc-git/tasks/repositories.yml
Normal file
37
etc-git/tasks/repositories.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- include: repository.yml
|
||||||
|
vars:
|
||||||
|
repository_path: "/etc"
|
||||||
|
gitignore_items:
|
||||||
|
- "aliases.db"
|
||||||
|
- "*.swp"
|
||||||
|
- "postfix/sa-blacklist.access"
|
||||||
|
- "postfix/*.db"
|
||||||
|
- "postfix/spamd.cidr"
|
||||||
|
- "evobackup/.keep-*"
|
||||||
|
- "letsencrypt/.certbot.lock"
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: verify /usr/share/scripts presence
|
||||||
|
stat:
|
||||||
|
path: /usr/share/scripts
|
||||||
|
register: _usr_share_scripts
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
when:
|
||||||
|
- _usr_share_scripts.stat.isdir
|
||||||
|
|
||||||
|
- include: repository.yml
|
||||||
|
vars:
|
||||||
|
repository_path: "/usr/share/scripts"
|
||||||
|
gitignore_items: []
|
||||||
|
when:
|
||||||
|
- _usr_share_scripts.stat.isdir
|
||||||
|
- ansible_distribution_major_version is version('10', '>=')
|
||||||
|
tags:
|
||||||
|
- etc-git
|
93
etc-git/tasks/utils.yml
Normal file
93
etc-git/tasks/utils.yml
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: "evocommit script is installed"
|
||||||
|
copy:
|
||||||
|
src: evocommit
|
||||||
|
dest: /usr/local/bin/evocommit
|
||||||
|
mode: "0755"
|
||||||
|
force: yes
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: "ansible-commit script is installed"
|
||||||
|
copy:
|
||||||
|
src: ansible-commit
|
||||||
|
dest: /usr/local/bin/ansible-commit
|
||||||
|
mode: "0755"
|
||||||
|
force: yes
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: "etc-git-optimize script is installed"
|
||||||
|
copy:
|
||||||
|
src: etc-git-optimize
|
||||||
|
dest: /usr/share/scripts/etc-git-optimize
|
||||||
|
mode: "0755"
|
||||||
|
force: yes
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: "etc-git-status script is installed"
|
||||||
|
copy:
|
||||||
|
src: etc-git-status
|
||||||
|
dest: /usr/share/scripts/etc-git-status
|
||||||
|
mode: "0755"
|
||||||
|
force: yes
|
||||||
|
tags:
|
||||||
|
- etc-git
|
||||||
|
|
||||||
|
- name: Check if cron is installed
|
||||||
|
shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
failed_when: False
|
||||||
|
changed_when: False
|
||||||
|
check_mode: no
|
||||||
|
register: is_cron_installed
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Legacy cron jobs for /etc/.git status are absent
|
||||||
|
file:
|
||||||
|
dest: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- /etc/cron.monthly/optimize-etc-git
|
||||||
|
- /etc/cron.d/etc-git-status
|
||||||
|
|
||||||
|
- name: Cron job for monthly git optimization
|
||||||
|
cron:
|
||||||
|
name: "Monthly optimization"
|
||||||
|
cron_file: etc-git
|
||||||
|
special_time: "monthly"
|
||||||
|
user: root
|
||||||
|
job: "/usr/share/scripts/etc-git-optimize"
|
||||||
|
|
||||||
|
- name: Cron job for hourly git status
|
||||||
|
cron:
|
||||||
|
name: "Hourly warning for unclean Git repository if nobody is connected"
|
||||||
|
cron_file: etc-git
|
||||||
|
special_time: "hourly"
|
||||||
|
user: root
|
||||||
|
job: "who > /dev/null || /usr/share/scripts/etc-git-status"
|
||||||
|
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
|
||||||
|
|
||||||
|
- name: Cron job for daily git status
|
||||||
|
cron:
|
||||||
|
name: "Daily warning for unclean Git repository"
|
||||||
|
cron_file: etc-git
|
||||||
|
user: root
|
||||||
|
job: "/usr/share/scripts/etc-git-status"
|
||||||
|
minute: "21"
|
||||||
|
hour: "21"
|
||||||
|
weekday: "*"
|
||||||
|
day: "*"
|
||||||
|
month: "*"
|
||||||
|
state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}"
|
||||||
|
when: is_cron_installed.rc == 0
|
||||||
|
tags:
|
||||||
|
- etc-git
|
|
@ -2,8 +2,9 @@
|
||||||
- name: restart minifirewall
|
- name: restart minifirewall
|
||||||
command: /etc/init.d/minifirewall restart
|
command: /etc/init.d/minifirewall restart
|
||||||
register: minifirewall_init_restart
|
register: minifirewall_init_restart
|
||||||
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
failed_when:
|
||||||
changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout"
|
- "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
||||||
|
- "'minifirewall started' not in minifirewall_init_restart.stdout"
|
||||||
|
|
||||||
- name: 'created new jail'
|
- name: 'created new jail'
|
||||||
command: "bkctld restart {{ evolinux_hostname }}"
|
command: "bkctld restart {{ evolinux_hostname }}"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# Script to verify compliance of a Debian/OpenBSD server
|
# Script to verify compliance of a Debian/OpenBSD server
|
||||||
# powered by Evolix
|
# powered by Evolix
|
||||||
|
|
||||||
VERSION="21.10.4"
|
VERSION="22.04.1"
|
||||||
readonly VERSION
|
readonly VERSION
|
||||||
|
|
||||||
# base functions
|
# base functions
|
||||||
|
@ -13,7 +13,7 @@ show_version() {
|
||||||
cat <<END
|
cat <<END
|
||||||
evocheck version ${VERSION}
|
evocheck version ${VERSION}
|
||||||
|
|
||||||
Copyright 2009-2021 Evolix <info@evolix.fr>,
|
Copyright 2009-2022 Evolix <info@evolix.fr>,
|
||||||
Romain Dessort <rdessort@evolix.fr>,
|
Romain Dessort <rdessort@evolix.fr>,
|
||||||
Benoit Série <bserie@evolix.fr>,
|
Benoit Série <bserie@evolix.fr>,
|
||||||
Gregory Colpart <reg@evolix.fr>,
|
Gregory Colpart <reg@evolix.fr>,
|
||||||
|
@ -142,9 +142,9 @@ failed() {
|
||||||
RC=1
|
RC=1
|
||||||
if [ "${QUIET}" != 1 ]; then
|
if [ "${QUIET}" != 1 ]; then
|
||||||
if [ -n "${check_comments}" ] && [ "${VERBOSE}" = 1 ]; then
|
if [ -n "${check_comments}" ] && [ "${VERBOSE}" = 1 ]; then
|
||||||
printf "%s FAILED! %s\n" "${check_name}" "${check_comments}" 2>&1
|
printf "%s FAILED! %s\n" "${check_name}" "${check_comments}" >> "${main_output_file}"
|
||||||
else
|
else
|
||||||
printf "%s FAILED!\n" "${check_name}" 2>&1
|
printf "%s FAILED!\n" "${check_name}" >> "${main_output_file}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,8 @@ check_syslogconf() {
|
||||||
check_debiansecurity() {
|
check_debiansecurity() {
|
||||||
if is_debian_bullseye; then
|
if is_debian_bullseye; then
|
||||||
# https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.html#security-archive
|
# https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.html#security-archive
|
||||||
pattern="^deb https://deb\.debian\.org/debian-security/? bullseye-security main"
|
# https://www.debian.org/security/
|
||||||
|
pattern="^deb https://(deb|security)\.debian\.org/debian-security/? bullseye-security main"
|
||||||
elif is_debian_buster; then
|
elif is_debian_buster; then
|
||||||
pattern="^deb http://security\.debian\.org/debian-security/? buster/updates main"
|
pattern="^deb http://security\.debian\.org/debian-security/? buster/updates main"
|
||||||
elif is_debian_stretch; then
|
elif is_debian_stretch; then
|
||||||
|
@ -328,8 +329,11 @@ check_tmoutprofile() {
|
||||||
check_alert5boot() {
|
check_alert5boot() {
|
||||||
if is_debian_buster || is_debian_bullseye; then
|
if is_debian_buster || is_debian_bullseye; then
|
||||||
grep -qs "^date" /usr/share/scripts/alert5.sh || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
grep -qs "^date" /usr/share/scripts/alert5.sh || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
||||||
test -f /etc/systemd/system/alert5.service || failed "IS_ALERT5BOOT" "alert5 unit file is missing"
|
if [ -f /etc/systemd/system/alert5.service ]; then
|
||||||
systemctl is-enabled alert5 -q || failed "IS_ALERT5BOOT" "alert5 unit is not enabled"
|
systemctl is-enabled alert5.service -q || failed "IS_ALERT5BOOT" "alert5 unit is not enabled"
|
||||||
|
else
|
||||||
|
failed "IS_ALERT5BOOT" "alert5 unit file is missing"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if [ -n "$(find /etc/rc2.d/ -name 'S*alert5')" ]; then
|
if [ -n "$(find /etc/rc2.d/ -name 'S*alert5')" ]; then
|
||||||
grep -q "^date" /etc/rc2.d/S*alert5 || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
grep -q "^date" /etc/rc2.d/S*alert5 || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script"
|
||||||
|
@ -567,7 +571,7 @@ check_network_interfaces() {
|
||||||
# Verify if all if are in auto
|
# Verify if all if are in auto
|
||||||
check_autoif() {
|
check_autoif() {
|
||||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||||
interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | tr "\n" " ")
|
interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap|vrrp|lxcbr)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | tr "\n" " ")
|
||||||
else
|
else
|
||||||
interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 1 |tr "\n" " ")
|
interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 1 |tr "\n" " ")
|
||||||
fi
|
fi
|
||||||
|
@ -592,18 +596,21 @@ check_evobackup() {
|
||||||
}
|
}
|
||||||
# Vérification de l'exclusion des montages (NFS) dans les sauvegardes
|
# Vérification de l'exclusion des montages (NFS) dans les sauvegardes
|
||||||
check_evobackup_exclude_mount() {
|
check_evobackup_exclude_mount() {
|
||||||
excludes_file=$(mktemp)
|
excludes_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.evobackup_exclude_mount.XXXXX")
|
||||||
# shellcheck disable=SC2064
|
files_to_cleanup="${files_to_cleanup} ${excludes_file}"
|
||||||
trap "rm -f ${excludes_file}" 0
|
|
||||||
# shellcheck disable=SC2044
|
# shellcheck disable=SC2044
|
||||||
for evobackup_file in $(find /etc/cron* -name '*evobackup*' | grep -v -E ".disabled$"); do
|
for evobackup_file in $(find /etc/cron* -name '*evobackup*' | grep -v -E ".disabled$"); do
|
||||||
grep -- "--exclude " "${evobackup_file}" | grep -E -o "\"[^\"]+\"" | tr -d '"' > "${excludes_file}"
|
# If rsync is not limited by "one-file-system"
|
||||||
not_excluded=$(findmnt --type nfs,nfs4,fuse.sshfs, -o target --noheadings | grep -v -f "${excludes_file}")
|
# then we verify that every mount is excluded
|
||||||
for mount in ${not_excluded}; do
|
if ! grep -q -- "^\s*--one-file-system" "${evobackup_file}"; then
|
||||||
failed "IS_EVOBACKUP_EXCLUDE_MOUNT" "${mount} is not excluded from ${evobackup_file} backup script"
|
grep -- "--exclude " "${evobackup_file}" | grep -E -o "\"[^\"]+\"" | tr -d '"' > "${excludes_file}"
|
||||||
done
|
not_excluded=$(findmnt --type nfs,nfs4,fuse.sshfs, -o target --noheadings | grep -v -f "${excludes_file}")
|
||||||
|
for mount in ${not_excluded}; do
|
||||||
|
failed "IS_EVOBACKUP_EXCLUDE_MOUNT" "${mount} is not excluded from ${evobackup_file} backup script"
|
||||||
|
done
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
rm -rf "${excludes_file}"
|
|
||||||
}
|
}
|
||||||
# Verification de la presence du userlogrotate
|
# Verification de la presence du userlogrotate
|
||||||
check_userlogrotate() {
|
check_userlogrotate() {
|
||||||
|
@ -809,8 +816,10 @@ check_tune2fs_m5() {
|
||||||
check_evolinuxsudogroup() {
|
check_evolinuxsudogroup() {
|
||||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||||
if grep -q "^evolinux-sudo:" /etc/group; then
|
if grep -q "^evolinux-sudo:" /etc/group; then
|
||||||
grep -qE '^%evolinux-sudo +ALL ?= ?\(ALL:ALL\) ALL' /etc/sudoers.d/evolinux \
|
if [ -f /etc/sudoers.d/evolinux ]; then
|
||||||
|| failed "IS_EVOLINUXSUDOGROUP" "missing evolinux-sudo directive in sudoers file"
|
grep -qE '^%evolinux-sudo +ALL ?= ?\(ALL:ALL\) ALL' /etc/sudoers.d/evolinux \
|
||||||
|
|| failed "IS_EVOLINUXSUDOGROUP" "missing evolinux-sudo directive in sudoers file"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -827,7 +836,7 @@ check_userinadmgroup() {
|
||||||
}
|
}
|
||||||
check_apache2evolinuxconf() {
|
check_apache2evolinuxconf() {
|
||||||
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
if is_debian_stretch || is_debian_buster || is_debian_bullseye; then
|
||||||
if test -d /etc/apache2; then
|
if is_installed apache2; then
|
||||||
{ test -L /etc/apache2/conf-enabled/z-evolinux-defaults.conf \
|
{ test -L /etc/apache2/conf-enabled/z-evolinux-defaults.conf \
|
||||||
&& test -L /etc/apache2/conf-enabled/zzz-evolinux-custom.conf \
|
&& test -L /etc/apache2/conf-enabled/zzz-evolinux-custom.conf \
|
||||||
&& test -f /etc/apache2/ipaddr_whitelist.conf;
|
&& test -f /etc/apache2/ipaddr_whitelist.conf;
|
||||||
|
@ -1006,6 +1015,8 @@ check_mysqlmunin() {
|
||||||
test "${VERBOSE}" = 1 || break
|
test "${VERBOSE}" = 1 || break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
munin-run mysql_commands 2> /dev/null > /dev/null
|
||||||
|
test $? -eq 0 || failed "IS_MYSQLMUNIN" "Munin plugin mysql_commands returned an error"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -1062,8 +1073,10 @@ check_squidevolinuxconf() {
|
||||||
check_duplicate_fs_label() {
|
check_duplicate_fs_label() {
|
||||||
# Do it only if thereis blkid binary
|
# Do it only if thereis blkid binary
|
||||||
BLKID_BIN=$(command -v blkid)
|
BLKID_BIN=$(command -v blkid)
|
||||||
if [ -x "$BLKID_BIN" ]; then
|
if [ -n "$BLKID_BIN" ]; then
|
||||||
tmpFile=$(mktemp -p /tmp)
|
tmpFile=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.duplicate_fs_label.XXXXX")
|
||||||
|
files_to_cleanup="${files_to_cleanup} ${tmpFile}"
|
||||||
|
|
||||||
parts=$($BLKID_BIN -c /dev/null | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2)
|
parts=$($BLKID_BIN -c /dev/null | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2)
|
||||||
for part in $parts; do
|
for part in $parts; do
|
||||||
echo "$part" >> "$tmpFile"
|
echo "$part" >> "$tmpFile"
|
||||||
|
@ -1076,7 +1089,6 @@ check_duplicate_fs_label() {
|
||||||
labels=$(echo -n $tmpOutput | tr '\n' ' ')
|
labels=$(echo -n $tmpOutput | tr '\n' ' ')
|
||||||
failed "IS_DUPLICATE_FS_LABEL" "Duplicate labels: $labels"
|
failed "IS_DUPLICATE_FS_LABEL" "Duplicate labels: $labels"
|
||||||
fi
|
fi
|
||||||
rm "$tmpFile"
|
|
||||||
else
|
else
|
||||||
failed "IS_DUPLICATE_FS_LABEL" "blkid not found in ${PATH}"
|
failed "IS_DUPLICATE_FS_LABEL" "blkid not found in ${PATH}"
|
||||||
fi
|
fi
|
||||||
|
@ -1367,7 +1379,7 @@ download_versions() {
|
||||||
elif is_openbsd; then
|
elif is_openbsd; then
|
||||||
versions_url="https://upgrades.evolix.org/versions-${OPENBSD_RELEASE}"
|
versions_url="https://upgrades.evolix.org/versions-${OPENBSD_RELEASE}"
|
||||||
else
|
else
|
||||||
failed "IS_VERSIONS_CHECK" "error determining os release"
|
failed "IS_CHECK_VERSIONS" "error determining os release"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# fetch timeout, in seconds
|
# fetch timeout, in seconds
|
||||||
|
@ -1380,9 +1392,9 @@ download_versions() {
|
||||||
elif command -v GET; then
|
elif command -v GET; then
|
||||||
GET -t ${timeout}s "${versions_url}" > "${versions_file}"
|
GET -t ${timeout}s "${versions_url}" > "${versions_file}"
|
||||||
else
|
else
|
||||||
failed "IS_VERSIONS_CHECK" "failed to find curl, wget or GET"
|
failed "IS_CHECK_VERSIONS" "failed to find curl, wget or GET"
|
||||||
fi
|
fi
|
||||||
test "$?" -eq 0 || failed "IS_VERSIONS_CHECK" "failed to download ${versions_url} to ${versions_file}"
|
test "$?" -eq 0 || failed "IS_CHECK_VERSIONS" "failed to download ${versions_url} to ${versions_file}"
|
||||||
}
|
}
|
||||||
get_command() {
|
get_command() {
|
||||||
local program
|
local program
|
||||||
|
@ -1395,6 +1407,7 @@ get_command() {
|
||||||
listupgrade) command -v "evolistupgrade.sh" ;;
|
listupgrade) command -v "evolistupgrade.sh" ;;
|
||||||
old-kernel-autoremoval) command -v "old-kernel-autoremoval.sh" ;;
|
old-kernel-autoremoval) command -v "old-kernel-autoremoval.sh" ;;
|
||||||
mysql-queries-killer) command -v "mysql-queries-killer.sh" ;;
|
mysql-queries-killer) command -v "mysql-queries-killer.sh" ;;
|
||||||
|
minifirewall) echo "/etc/init.d/minifirewall" ;;
|
||||||
|
|
||||||
## General case, where the program name is the same as the command name
|
## General case, where the program name is the same as the command name
|
||||||
*) command -v "${program}" ;;
|
*) command -v "${program}" ;;
|
||||||
|
@ -1415,6 +1428,9 @@ get_version() {
|
||||||
add-vm)
|
add-vm)
|
||||||
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2
|
||||||
;;
|
;;
|
||||||
|
minifirewall)
|
||||||
|
${command} status | head -1 | cut -d ' ' -f 3
|
||||||
|
;;
|
||||||
## Let's try the --version flag before falling back to grep for the constant
|
## Let's try the --version flag before falling back to grep for the constant
|
||||||
kvmstats)
|
kvmstats)
|
||||||
if ${command} --version > /dev/null 2> /dev/null; then
|
if ${command} --version > /dev/null 2> /dev/null; then
|
||||||
|
@ -1440,11 +1456,11 @@ check_version() {
|
||||||
actual_version=$(get_version "${program}" "${command}")
|
actual_version=$(get_version "${program}" "${command}")
|
||||||
# printf "program:%s expected:%s actual:%s\n" "${program}" "${expected_version}" "${actual_version}"
|
# printf "program:%s expected:%s actual:%s\n" "${program}" "${expected_version}" "${actual_version}"
|
||||||
if [ -z "${actual_version}" ]; then
|
if [ -z "${actual_version}" ]; then
|
||||||
failed "IS_VERSIONS_CHECK" "failed to lookup actual version of ${program}"
|
failed "IS_CHECK_VERSIONS" "failed to lookup actual version of ${program}"
|
||||||
elif dpkg --compare-versions "${actual_version}" lt "${expected_version}"; then
|
elif dpkg --compare-versions "${actual_version}" lt "${expected_version}"; then
|
||||||
failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is older than expected version ${expected_version}"
|
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is older than expected version ${expected_version}"
|
||||||
elif dpkg --compare-versions "${actual_version}" gt "${expected_version}"; then
|
elif dpkg --compare-versions "${actual_version}" gt "${expected_version}"; then
|
||||||
failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update tour index."
|
failed "IS_CHECK_VERSIONS" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update your index."
|
||||||
else
|
else
|
||||||
: # Version check OK
|
: # Version check OK
|
||||||
fi
|
fi
|
||||||
|
@ -1457,9 +1473,9 @@ add_to_path() {
|
||||||
echo "$PATH" | grep -qF "${new_path}" || export PATH="${PATH}:${new_path}"
|
echo "$PATH" | grep -qF "${new_path}" || export PATH="${PATH}:${new_path}"
|
||||||
}
|
}
|
||||||
check_versions() {
|
check_versions() {
|
||||||
versions_file=$(mktemp --tmpdir=/tmp "evocheck-versions.XXXXX")
|
versions_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.versions.XXXXX")
|
||||||
# shellcheck disable=SC2064
|
files_to_cleanup="${files_to_cleanup} ${versions_file}"
|
||||||
trap "rm -f ${versions_file}" 0
|
|
||||||
download_versions "${versions_file}"
|
download_versions "${versions_file}"
|
||||||
add_to_path "/usr/share/scripts"
|
add_to_path "/usr/share/scripts"
|
||||||
|
|
||||||
|
@ -1473,12 +1489,10 @@ check_versions() {
|
||||||
if [ -n "${version}" ]; then
|
if [ -n "${version}" ]; then
|
||||||
check_version "${program}" "${version}"
|
check_version "${program}" "${version}"
|
||||||
else
|
else
|
||||||
failed "IS_VERSIONS_CHECK" "failed to lookup expected version for ${program}"
|
failed "IS_CHECK_VERSIONS" "failed to lookup expected version for ${program}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
rm -f "${versions_file}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
@ -1487,6 +1501,9 @@ main() {
|
||||||
# Detect operating system name, version and release
|
# Detect operating system name, version and release
|
||||||
detect_os
|
detect_os
|
||||||
|
|
||||||
|
main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX")
|
||||||
|
files_to_cleanup="${files_to_cleanup} ${main_output_file}"
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
# Tests communs à tous les systèmes
|
# Tests communs à tous les systèmes
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
|
@ -1715,8 +1732,21 @@ main() {
|
||||||
# - NRPEDISK et NRPEPOSTFIX
|
# - NRPEDISK et NRPEPOSTFIX
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -f "${main_output_file}" ]; then
|
||||||
|
lines_found=$(wc -l < "${main_output_file}")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if [ ${lines_found} -gt 0 ]; then
|
||||||
|
|
||||||
|
cat "${main_output_file}" 2>&1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
exit ${RC}
|
exit ${RC}
|
||||||
}
|
}
|
||||||
|
cleanup_temp_files() {
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
rm -f ${files_to_cleanup}
|
||||||
|
}
|
||||||
|
|
||||||
PROGNAME=$(basename "$0")
|
PROGNAME=$(basename "$0")
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
|
@ -1730,6 +1760,10 @@ readonly ARGS
|
||||||
export LANG=C
|
export LANG=C
|
||||||
export LANGUAGE=C
|
export LANGUAGE=C
|
||||||
|
|
||||||
|
files_to_cleanup=""
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap cleanup_temp_files 0
|
||||||
|
|
||||||
# Source configuration file
|
# Source configuration file
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
test -f /etc/evocheck.cf && . /etc/evocheck.cf
|
test -f /etc/evocheck.cf && . /etc/evocheck.cf
|
||||||
|
|
|
@ -1,1019 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PROGNAME="backup-server-state"
|
|
||||||
|
|
||||||
VERSION="22.01.3"
|
|
||||||
readonly VERSION
|
|
||||||
|
|
||||||
backup_dir=
|
|
||||||
rc=0
|
|
||||||
|
|
||||||
# base functions
|
|
||||||
|
|
||||||
show_version() {
|
|
||||||
cat <<END
|
|
||||||
${PROGNAME} version ${VERSION}
|
|
||||||
|
|
||||||
Copyright 2018-2022 Evolix <info@evolix.fr>,
|
|
||||||
Jérémy Lecour <jlecour@evolix.fr>
|
|
||||||
and others.
|
|
||||||
|
|
||||||
${PROGNAME} comes with ABSOLUTELY NO WARRANTY.This is free software,
|
|
||||||
and you are welcome to redistribute it under certain conditions.
|
|
||||||
See the GNU General Public License v3.0 for details.
|
|
||||||
END
|
|
||||||
}
|
|
||||||
show_help() {
|
|
||||||
cat <<END
|
|
||||||
${PROGNAME} is making backup copies of information related to the state of the server.
|
|
||||||
|
|
||||||
Usage: ${PROGNAME} --backup-dir=/path/to/backup/directory [OPTIONS]
|
|
||||||
|
|
||||||
Options
|
|
||||||
-d, --backup-dir path to the directory where the backup will be stored
|
|
||||||
-f, --force keep existing backup directory and its content
|
|
||||||
--etc backup copy of /etc
|
|
||||||
--no-etc no backup copy of /etc (default)
|
|
||||||
--dpkg backup copy of /var/lib/dpkg
|
|
||||||
--no-dpkg no backup copy of /var/lib/dpkg (default)
|
|
||||||
--apt-states backup copy of apt extended states (default)
|
|
||||||
--no-apt-states no backup copy of apt extended states
|
|
||||||
--apt-config backup copy of apt configuration (default)
|
|
||||||
--no-apt-config no backup copy of apt configuration
|
|
||||||
--packages backup copy of dpkg selections (default)
|
|
||||||
--no-packages no backup copy of dpkg selections
|
|
||||||
--processes backup copy of process list (default)
|
|
||||||
--no-processes no backup copy of process list
|
|
||||||
--uptime backup of uptime value (default)
|
|
||||||
--no-uptime no backup of uptime value
|
|
||||||
--netstat backup copy of netstat (default)
|
|
||||||
--no-netstat no backup copy of netstat
|
|
||||||
--netcfg backup copy of network configuration (default)
|
|
||||||
--no-netcfg no backup copy of network configuration
|
|
||||||
--iptables backup copy of iptables (default)
|
|
||||||
--no-iptables no backup copy of iptables
|
|
||||||
--sysctl backup copy of sysctl values (default)
|
|
||||||
--no-sysctl no backup copy of sysctl values
|
|
||||||
--virsh backup copy of virsh list (default)
|
|
||||||
--no-virsh no backup copy of virsh list
|
|
||||||
--lxc backup copy of lxc list (default)
|
|
||||||
--no-lxc no backup copy of lxc list
|
|
||||||
--disks backup copy of MBR and partitions (default)
|
|
||||||
--no-disks no backup copy of MBR and partitions
|
|
||||||
--mount backup copy of mount points (default)
|
|
||||||
--no-mount no backup copy of mount points
|
|
||||||
--df backup copy of disk usage (default)
|
|
||||||
--no-df no backup copy of disk usage
|
|
||||||
--dmesg backup copy of dmesg (default)
|
|
||||||
--no-dmesg no backup copy of dmesg
|
|
||||||
--mysql backup copy of mysql processes (default)
|
|
||||||
--no-mysql no backup copy of mysql processes
|
|
||||||
--services backup copy of services states (default)
|
|
||||||
--no-services no backup copy of services states
|
|
||||||
-v, --verbose print details about backup steps
|
|
||||||
-V, --version print version and exit
|
|
||||||
-h, --help print this message and exit
|
|
||||||
END
|
|
||||||
}
|
|
||||||
debug() {
|
|
||||||
if [ "${VERBOSE}" = "1" ]; then
|
|
||||||
echo "$1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
create_backup_dir() {
|
|
||||||
debug "Create ${backup_dir}"
|
|
||||||
|
|
||||||
last_result=$(mkdir -p "${backup_dir}" && chmod -R 755 "${backup_dir}")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* mkdir/chmod OK"
|
|
||||||
else
|
|
||||||
debug "* mkdir/chmod ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_etc() {
|
|
||||||
debug "Backup /etc"
|
|
||||||
|
|
||||||
rsync_bin=$(command -v rsync)
|
|
||||||
|
|
||||||
if [ -n "${rsync_bin}" ]; then
|
|
||||||
last_result=$(${rsync_bin} -ah --itemize-changes --exclude=.git /etc "${backup_dir}/")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* rsync OK"
|
|
||||||
else
|
|
||||||
debug "* rsync ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* rsync not found"
|
|
||||||
last_result=$(cp -r /etc "${backup_dir}/ && rm -rf ${backup_dir}/etc/.git")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* cp OK"
|
|
||||||
else
|
|
||||||
debug "* cp ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_apt_states() {
|
|
||||||
apt_dir="/"
|
|
||||||
apt_dir_state="var/lib/apt"
|
|
||||||
apt_dir_state_extended_states="extended_states"
|
|
||||||
|
|
||||||
apt_config_bin=$(command -v apt-config)
|
|
||||||
|
|
||||||
if [ -n "${apt_config_bin}" ]; then
|
|
||||||
eval "$(${apt_config_bin} shell apt_dir Dir)"
|
|
||||||
eval "$(${apt_config_bin} shell apt_dir_state Dir::State)"
|
|
||||||
eval "$(${apt_config_bin} shell apt_dir_state_extended_states Dir::State::extended_states)"
|
|
||||||
fi
|
|
||||||
extended_states="${apt_dir}/${apt_dir_state}/${apt_dir_state_extended_states}"
|
|
||||||
|
|
||||||
if [ -f "${extended_states}" ]; then
|
|
||||||
debug "Backup APT states"
|
|
||||||
|
|
||||||
last_result=$(cp -r "${extended_states}" "${backup_dir}/apt-extended-states.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* cp OK"
|
|
||||||
else
|
|
||||||
debug "* cp ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_apt_config() {
|
|
||||||
debug "Backup APT config"
|
|
||||||
|
|
||||||
apt_config_bin=$(command -v apt-config)
|
|
||||||
|
|
||||||
if [ -n "${apt_config_bin}" ]; then
|
|
||||||
last_result=$(${apt_config_bin} dump > "${backup_dir}/apt-config.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* apt-config OK"
|
|
||||||
else
|
|
||||||
debug "* apt-config ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* apt-config is not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_dpkg_full() {
|
|
||||||
debug "Backup DPkg full state"
|
|
||||||
|
|
||||||
dir_state_status="/var/lib/dpkg/status"
|
|
||||||
|
|
||||||
apt_config_bin=$(command -v apt-config)
|
|
||||||
|
|
||||||
if [ -n "${apt_config_bin}" ]; then
|
|
||||||
eval "$(${apt_config_bin} shell dir_state_status Dir::State::status)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
dpkg_dir=$(dirname "${dir_state_status}")
|
|
||||||
|
|
||||||
last_result=$(mkdir -p "${backup_dir}${dpkg_dir}" && chmod -R 755 "${backup_dir}${dpkg_dir}")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* mkdir/chmod OK"
|
|
||||||
else
|
|
||||||
debug "* mkdir/chmod ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
|
|
||||||
rsync_bin=$(command -v rsync)
|
|
||||||
|
|
||||||
if [ -n "${rsync_bin}" ]; then
|
|
||||||
last_result=$(${rsync_bin} -ah --itemize-changes --exclude='*-old' "${dpkg_dir}/" "${backup_dir}${dpkg_dir}/")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* rsync OK"
|
|
||||||
else
|
|
||||||
debug "* rsync ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* rsync not found"
|
|
||||||
|
|
||||||
last_result=$(cp -r "${dpkg_dir}/*" "${backup_dir}${dpkg_dir}/" && rm -rf "${backup_dir}${dpkg_dir}/*-old")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* cp OK"
|
|
||||||
else
|
|
||||||
debug "* cp ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_dpkg_status() {
|
|
||||||
debug "Backup DPkg status"
|
|
||||||
|
|
||||||
dir_state_status="/var/lib/dpkg/status"
|
|
||||||
|
|
||||||
apt_config_bin=$(command -v apt-config)
|
|
||||||
|
|
||||||
if [ -n "${apt_config_bin}" ]; then
|
|
||||||
eval "$(${apt_config_bin} shell dir_state_status Dir::State::status)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
last_result=$(cp "${dir_state_status}" "${backup_dir}/dpkg-status.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* cp OK"
|
|
||||||
else
|
|
||||||
debug "* cp ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_packages() {
|
|
||||||
debug "Backup list of installed package"
|
|
||||||
|
|
||||||
dpkg_bin=$(command -v dpkg)
|
|
||||||
|
|
||||||
if [ -n "${dpkg_bin}" ]; then
|
|
||||||
last_result=$(${dpkg_bin} --get-selections "*" > "${backup_dir}/current_packages.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* dpkg OK"
|
|
||||||
else
|
|
||||||
debug "* dpkg ERROR :"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* dpkg not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_uname() {
|
|
||||||
debug "Backup uname"
|
|
||||||
|
|
||||||
last_result=$(uname -a > "${backup_dir}/uname.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* uname OK"
|
|
||||||
else
|
|
||||||
debug "* uname ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_uptime() {
|
|
||||||
debug "Backup uptime"
|
|
||||||
|
|
||||||
last_result=$(uptime > "${backup_dir}/uptime.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* uptime OK"
|
|
||||||
else
|
|
||||||
debug "* uptime ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_processes() {
|
|
||||||
debug "Backup process list"
|
|
||||||
|
|
||||||
last_result=$(ps fauxw > "${backup_dir}/ps.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* ps OK"
|
|
||||||
else
|
|
||||||
debug "* ps ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
|
|
||||||
pstree_bin=$(command -v pstree)
|
|
||||||
|
|
||||||
if [ -n "${pstree_bin}" ]; then
|
|
||||||
last_result=$(${pstree_bin} -pan > "${backup_dir}/pstree.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* pstree OK"
|
|
||||||
else
|
|
||||||
debug "* pstree ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_netstat() {
|
|
||||||
debug "Backup network status"
|
|
||||||
|
|
||||||
ss_bin=$(command -v ss)
|
|
||||||
|
|
||||||
if [ -n "${ss_bin}" ]; then
|
|
||||||
last_result=$(${ss_bin} -tanpul > "${backup_dir}/netstat-ss.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* ss OK"
|
|
||||||
else
|
|
||||||
debug "* ss ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* ss not found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
netstat_bin=$(command -v netstat)
|
|
||||||
|
|
||||||
if [ -n "${netstat_bin}" ]; then
|
|
||||||
last_result=$(netstat -laputen > "${backup_dir}/netstat-legacy.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* netstat OK"
|
|
||||||
else
|
|
||||||
debug "* netstat ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* netstat not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_netcfg() {
|
|
||||||
debug "Backup network configuration"
|
|
||||||
|
|
||||||
ip_bin=$(command -v ip)
|
|
||||||
|
|
||||||
if [ -n "${ip_bin}" ]; then
|
|
||||||
last_result=$(${ip_bin} address show > "${backup_dir}/ip-address.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* ip address OK"
|
|
||||||
else
|
|
||||||
debug "* ip address ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
|
|
||||||
last_result=$(${ip_bin} route show > "${backup_dir}/ip-route.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* ip route OK"
|
|
||||||
else
|
|
||||||
debug "* ip route ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* ip not found"
|
|
||||||
|
|
||||||
ifconfig_bin=$(command -v ifconfig)
|
|
||||||
|
|
||||||
if [ -n "${ifconfig_bin}" ]; then
|
|
||||||
last_result=$(${ifconfig_bin} > "${backup_dir}/ifconfig.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* ifconfig OK"
|
|
||||||
else
|
|
||||||
debug "* ifconfig ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* ifconfig not found"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_iptables() {
|
|
||||||
debug "Backup iptables"
|
|
||||||
|
|
||||||
iptables_bin=$(command -v iptables)
|
|
||||||
|
|
||||||
if [ -n "${iptables_bin}" ]; then
|
|
||||||
last_result=$({ ${iptables_bin} -L -n -v; ${iptables_bin} -t filter -L -n -v; } > "${backup_dir}/iptables.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* iptables OK"
|
|
||||||
else
|
|
||||||
debug "* iptables ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* iptables not found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
iptables_save_bin=$(command -v iptables-save)
|
|
||||||
|
|
||||||
if [ -n "${iptables_save_bin}" ]; then
|
|
||||||
last_result=$(${iptables_save_bin} > "${backup_dir}/iptables-save.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* iptables-save OK"
|
|
||||||
else
|
|
||||||
debug "* iptables-save ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* iptables-save not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_sysctl() {
|
|
||||||
debug "Backup sysctl values"
|
|
||||||
|
|
||||||
sysctl_bin=$(command -v sysctl)
|
|
||||||
|
|
||||||
if [ -n "${sysctl_bin}" ]; then
|
|
||||||
last_result=$(${sysctl_bin} -a | sort -h > "${backup_dir}/sysctl.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* sysctl OK"
|
|
||||||
else
|
|
||||||
debug "* sysctl ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* sysctl not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_virsh() {
|
|
||||||
debug "Backup virsh list"
|
|
||||||
|
|
||||||
virsh_bin=$(command -v virsh)
|
|
||||||
|
|
||||||
if [ -n "${virsh_bin}" ]; then
|
|
||||||
last_result=$(${virsh_bin} list --all > "${backup_dir}/virsh-list.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* virsh list OK"
|
|
||||||
else
|
|
||||||
debug "* virsh list ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* virsh not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_lxc() {
|
|
||||||
debug "Backup lxc list"
|
|
||||||
|
|
||||||
lxc_ls_bin=$(command -v lxc-ls)
|
|
||||||
|
|
||||||
if [ -n "${lxc_ls_bin}" ]; then
|
|
||||||
last_result=$(${lxc_ls_bin} --fancy > "${backup_dir}/lxc-list.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* lxc list OK"
|
|
||||||
else
|
|
||||||
debug "* lxc list ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* lxc-ls not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_disks() {
|
|
||||||
debug "Backup disks"
|
|
||||||
|
|
||||||
lsblk_bin=$(command -v lsblk)
|
|
||||||
awk_bin=$(command -v awk)
|
|
||||||
|
|
||||||
if [ -n "${lsblk_bin}" ] && [ -n "${awk_bin}" ]; then
|
|
||||||
disks=$(${lsblk_bin} -l | grep disk | grep -v -E '(drbd|fd[0-9]+)' | ${awk_bin} '{print $1}')
|
|
||||||
for disk in ${disks}; do
|
|
||||||
dd_bin=$(command -v dd)
|
|
||||||
if [ -n "${dd_bin}" ]; then
|
|
||||||
last_result=$(${dd_bin} if="/dev/${disk}" of="${backup_dir}/MBR-${disk}" bs=512 count=1 2>&1)
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* dd ${disk} OK"
|
|
||||||
else
|
|
||||||
debug "* dd ${disk} ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* dd not found"
|
|
||||||
fi
|
|
||||||
fdisk_bin=$(command -v fdisk)
|
|
||||||
if [ -n "${fdisk_bin}" ]; then
|
|
||||||
last_result=$(${fdisk_bin} -l "/dev/${disk}" > "${backup_dir}/partitions-${disk}" 2>&1)
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* fdisk ${disk} OK"
|
|
||||||
else
|
|
||||||
debug "* fdisk ${disk} ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* fdisk not found"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
cat "${backup_dir}"/partitions-* > "${backup_dir}/partitions"
|
|
||||||
else
|
|
||||||
if [ -n "${lsblk_bin}" ]; then
|
|
||||||
debug "* lsblk not found"
|
|
||||||
fi
|
|
||||||
if [ -n "${awk_bin}" ]; then
|
|
||||||
debug "* awk not found"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_mount() {
|
|
||||||
debug "Backup mount points"
|
|
||||||
|
|
||||||
findmnt_bin=$(command -v findmnt)
|
|
||||||
|
|
||||||
if [ -n "${findmnt_bin}" ]; then
|
|
||||||
last_result=$(${findmnt_bin} > "${backup_dir}/mount.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* mount points OK"
|
|
||||||
else
|
|
||||||
debug "* mount points ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* findmnt not found"
|
|
||||||
|
|
||||||
mount_bin=$(command -v mount)
|
|
||||||
|
|
||||||
if [ -n "${mount_bin}" ]; then
|
|
||||||
last_result=$(${mount_bin} > "${backup_dir}/mount.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* mount points OK"
|
|
||||||
else
|
|
||||||
debug "* mount points ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* mount not found"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_df() {
|
|
||||||
debug "Backup df"
|
|
||||||
|
|
||||||
df_bin=$(command -v df)
|
|
||||||
|
|
||||||
if [ -n "${df_bin}" ]; then
|
|
||||||
last_result=$(${df_bin} --portability > "${backup_dir}/df.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* df OK"
|
|
||||||
else
|
|
||||||
debug "* df ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* df not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_dmesg() {
|
|
||||||
debug "Backup dmesg"
|
|
||||||
|
|
||||||
dmesg_bin=$(command -v dmesg)
|
|
||||||
|
|
||||||
if [ -n "${dmesg_bin}" ]; then
|
|
||||||
last_result=$(${dmesg_bin} > "${backup_dir}/dmesg.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* dmesg OK"
|
|
||||||
else
|
|
||||||
debug "* dmesg ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* dmesg not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_mysql_processes() {
|
|
||||||
debug "Backup mysql processes"
|
|
||||||
|
|
||||||
mysqladmin_bin=$(command -v mysqladmin)
|
|
||||||
|
|
||||||
if [ -n "${mysqladmin_bin}" ]; then
|
|
||||||
last_result=$(${mysqladmin_bin} --verbose processlist > "${backup_dir}/mysql-processlist.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* mysqladmin OK"
|
|
||||||
else
|
|
||||||
debug "* mysqladmin ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* mysqladmin not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
backup_systemctl() {
|
|
||||||
debug "Backup services"
|
|
||||||
|
|
||||||
systemctl_bin=$(command -v systemctl)
|
|
||||||
|
|
||||||
if [ -n "${systemctl_bin}" ]; then
|
|
||||||
last_result=$(${systemctl_bin} --no-legend --state=failed --type=service > "${backup_dir}/systemctl-failed-services.txt")
|
|
||||||
last_rc=$?
|
|
||||||
|
|
||||||
if [ ${last_rc} -eq 0 ]; then
|
|
||||||
debug "* failed services OK"
|
|
||||||
else
|
|
||||||
debug "* failed services ERROR"
|
|
||||||
debug "${last_result}"
|
|
||||||
rc=10
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
debug "* systemctl not found"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if [ -z "${backup_dir}" ]; then
|
|
||||||
echo "ERROR: You must provide the --backup-dir argument" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "${backup_dir}" ]; then
|
|
||||||
if [ "${FORCE}" != "1" ]; then
|
|
||||||
echo "ERROR: The backup directory ${backup_dir} already exists. Delete it first." >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
create_backup_dir
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${DO_ETC}" -eq 1 ]; then
|
|
||||||
backup_etc
|
|
||||||
fi
|
|
||||||
if [ "${DO_DPKG_FULL}" -eq 1 ]; then
|
|
||||||
backup_dpkg_full
|
|
||||||
fi
|
|
||||||
if [ "${DO_DPKG_STATUS}" -eq 1 ]; then
|
|
||||||
backup_dpkg_status
|
|
||||||
fi
|
|
||||||
if [ "${DO_APT_STATES}" -eq 1 ]; then
|
|
||||||
backup_apt_states
|
|
||||||
fi
|
|
||||||
if [ "${DO_APT_CONFIG}" -eq 1 ]; then
|
|
||||||
backup_apt_config
|
|
||||||
fi
|
|
||||||
if [ "${DO_PACKAGES}" -eq 1 ]; then
|
|
||||||
backup_packages
|
|
||||||
fi
|
|
||||||
if [ "${DO_PROCESSES}" -eq 1 ]; then
|
|
||||||
backup_processes
|
|
||||||
fi
|
|
||||||
if [ "${DO_UPTIME}" -eq 1 ]; then
|
|
||||||
backup_uptime
|
|
||||||
fi
|
|
||||||
if [ "${DO_UNAME}" -eq 1 ]; then
|
|
||||||
backup_uname
|
|
||||||
fi
|
|
||||||
if [ "${DO_NETSTAT}" -eq 1 ]; then
|
|
||||||
backup_netstat
|
|
||||||
fi
|
|
||||||
if [ "${DO_NETCFG}" -eq 1 ]; then
|
|
||||||
backup_netcfg
|
|
||||||
fi
|
|
||||||
if [ "${DO_IPTABLES}" -eq 1 ]; then
|
|
||||||
backup_iptables
|
|
||||||
fi
|
|
||||||
if [ "${DO_SYSCTL}" -eq 1 ]; then
|
|
||||||
backup_sysctl
|
|
||||||
fi
|
|
||||||
if [ "${DO_VIRSH}" -eq 1 ]; then
|
|
||||||
backup_virsh
|
|
||||||
fi
|
|
||||||
if [ "${DO_LXC}" -eq 1 ]; then
|
|
||||||
backup_lxc
|
|
||||||
fi
|
|
||||||
if [ "${DO_DISKS}" -eq 1 ]; then
|
|
||||||
backup_disks
|
|
||||||
fi
|
|
||||||
if [ "${DO_MOUNT}" -eq 1 ]; then
|
|
||||||
backup_mount
|
|
||||||
fi
|
|
||||||
if [ "${DO_DF}" -eq 1 ]; then
|
|
||||||
backup_df
|
|
||||||
fi
|
|
||||||
if [ "${DO_DMESG}" -eq 1 ]; then
|
|
||||||
backup_dmesg
|
|
||||||
fi
|
|
||||||
if [ "${DO_MYSQL_PROCESSES}" -eq 1 ]; then
|
|
||||||
backup_mysql_processes
|
|
||||||
fi
|
|
||||||
if [ "${DO_SYSTEMCTL}" -eq 1 ]; then
|
|
||||||
backup_systemctl
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
debug "=> Your backup is available at ${backup_dir}"
|
|
||||||
exit ${rc}
|
|
||||||
}
|
|
||||||
|
|
||||||
# parse options
|
|
||||||
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
|
||||||
while :; do
|
|
||||||
case $1 in
|
|
||||||
-h|-\?|--help)
|
|
||||||
show_help
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-V|--version)
|
|
||||||
show_version
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-v|--verbose)
|
|
||||||
VERBOSE=1
|
|
||||||
;;
|
|
||||||
|
|
||||||
-f|--force)
|
|
||||||
FORCE=1
|
|
||||||
;;
|
|
||||||
|
|
||||||
-d|--backup-dir)
|
|
||||||
# with value separated by space
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
backup_dir=$2
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
printf 'ERROR: "-d|--backup-dir" requires a non-empty option argument.\n' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--backup-dir=?*)
|
|
||||||
# with value speparated by =
|
|
||||||
backup_dir=${1#*=}
|
|
||||||
;;
|
|
||||||
--backup-dir=)
|
|
||||||
# without value
|
|
||||||
printf 'ERROR: "--backup-dir" requires a non-empty option argument.\n' >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
--etc)
|
|
||||||
DO_ETC=1
|
|
||||||
;;
|
|
||||||
--no-etc)
|
|
||||||
DO_ETC=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--dpkg-full)
|
|
||||||
DO_DPKG_FULL=1
|
|
||||||
;;
|
|
||||||
--no-dpkg-full)
|
|
||||||
DO_DPKG_FULL=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--dpkg-status)
|
|
||||||
DO_DPKG_STATUS=1
|
|
||||||
;;
|
|
||||||
--no-dpkg-status)
|
|
||||||
DO_DPKG_STATUS=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--apt-states)
|
|
||||||
DO_APT_STATES=1
|
|
||||||
;;
|
|
||||||
--no-apt-states)
|
|
||||||
DO_APT_STATES=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--apt-config)
|
|
||||||
DO_APT_CONFIG=1
|
|
||||||
;;
|
|
||||||
--no-apt-config)
|
|
||||||
DO_APT_CONFIG=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--packages)
|
|
||||||
DO_PACKAGES=1
|
|
||||||
;;
|
|
||||||
--no-packages)
|
|
||||||
DO_PACKAGES=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--processes)
|
|
||||||
DO_PROCESSES=1
|
|
||||||
;;
|
|
||||||
--no-processes)
|
|
||||||
DO_PROCESSES=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--uptime)
|
|
||||||
DO_UPTIME=1
|
|
||||||
;;
|
|
||||||
--no-uptime)
|
|
||||||
DO_UPTIME=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--uname)
|
|
||||||
DO_UNAME=1
|
|
||||||
;;
|
|
||||||
--no-uname)
|
|
||||||
DO_UNAME=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--netstat)
|
|
||||||
DO_NETSTAT=1
|
|
||||||
;;
|
|
||||||
--no-netstat)
|
|
||||||
DO_NETSTAT=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--netcfg)
|
|
||||||
DO_NETCFG=1
|
|
||||||
;;
|
|
||||||
--no-netcfg)
|
|
||||||
DO_NETCFG=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--iptables)
|
|
||||||
DO_IPTABLES=1
|
|
||||||
;;
|
|
||||||
--no-iptables)
|
|
||||||
DO_IPTABLES=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--sysctl)
|
|
||||||
DO_SYSCTL=1
|
|
||||||
;;
|
|
||||||
--no-sysctl)
|
|
||||||
DO_SYSCTL=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--virsh)
|
|
||||||
DO_VIRSH=1
|
|
||||||
;;
|
|
||||||
--no-virsh)
|
|
||||||
DO_VIRSH=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--lxc)
|
|
||||||
DO_LXC=1
|
|
||||||
;;
|
|
||||||
--no-lxc)
|
|
||||||
DO_LXC=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--disks)
|
|
||||||
DO_DISKS=1
|
|
||||||
;;
|
|
||||||
--no-disks)
|
|
||||||
DO_DISKS=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--mount)
|
|
||||||
DO_MOUNT=1
|
|
||||||
;;
|
|
||||||
--no-mount)
|
|
||||||
DO_MOUNT=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--df)
|
|
||||||
DO_DF=1
|
|
||||||
;;
|
|
||||||
--no-df)
|
|
||||||
DO_DF=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--dmesg)
|
|
||||||
DO_DMESG=1
|
|
||||||
;;
|
|
||||||
--no-dmesg)
|
|
||||||
DO_DMESG=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--mysql-processes)
|
|
||||||
DO_MYSQL_PROCESSES=1
|
|
||||||
;;
|
|
||||||
--no-mysql-processes)
|
|
||||||
DO_MYSQL_PROCESSES=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--systemctl)
|
|
||||||
DO_SYSTEMCTL=1
|
|
||||||
;;
|
|
||||||
--no-systemctl)
|
|
||||||
DO_SYSTEMCTL=0
|
|
||||||
;;
|
|
||||||
|
|
||||||
--)
|
|
||||||
# End of all options.
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
-?*)
|
|
||||||
# ignore unknown options
|
|
||||||
printf 'WARN: Unknown option : %s\n' "$1" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# Default case: If no more options then break out of the loop.
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
# Default values
|
|
||||||
: "${VERBOSE:=0}"
|
|
||||||
: "${FORCE:=0}"
|
|
||||||
: "${DO_ETC:=0}"
|
|
||||||
: "${DO_DPKG_FULL:=0}"
|
|
||||||
: "${DO_DPKG_STATUS:=1}"
|
|
||||||
: "${DO_APT_STATES:=1}"
|
|
||||||
: "${DO_APT_CONFIG:=1}"
|
|
||||||
: "${DO_PACKAGES:=1}"
|
|
||||||
: "${DO_PROCESSES:=1}"
|
|
||||||
: "${DO_UNAME:=1}"
|
|
||||||
: "${DO_UPTIME:=1}"
|
|
||||||
: "${DO_NETSTAT:=1}"
|
|
||||||
: "${DO_NETCFG:=1}"
|
|
||||||
: "${DO_IPTABLES:=1}"
|
|
||||||
: "${DO_SYSCTL:=1}"
|
|
||||||
: "${DO_VIRSH:=1}"
|
|
||||||
: "${DO_LXC:=1}"
|
|
||||||
: "${DO_DISKS:=1}"
|
|
||||||
: "${DO_MOUNT:=1}"
|
|
||||||
: "${DO_DF:=1}"
|
|
||||||
: "${DO_DMESG:=1}"
|
|
||||||
: "${DO_MYSQL_PROCESSES:=1}"
|
|
||||||
: "${DO_SYSTEMCTL:=1}"
|
|
||||||
|
|
||||||
export LC_ALL=C
|
|
||||||
|
|
||||||
set -u
|
|
||||||
|
|
||||||
main
|
|
1177
evolinux-base/files/dump-server-state.sh
Normal file
1177
evolinux-base/files/dump-server-state.sh
Normal file
|
@ -0,0 +1,1177 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROGNAME="dump-server-state"
|
||||||
|
REPOSITORY="https://gitea.evolix.org/evolix/dump-server-state"
|
||||||
|
|
||||||
|
VERSION="22.04.3"
|
||||||
|
readonly VERSION
|
||||||
|
|
||||||
|
dump_dir=
|
||||||
|
rc=0
|
||||||
|
|
||||||
|
# base functions
|
||||||
|
|
||||||
|
show_version() {
|
||||||
|
cat <<END
|
||||||
|
${PROGNAME} version ${VERSION}
|
||||||
|
|
||||||
|
Copyright 2018-2022 Evolix <info@evolix.fr>,
|
||||||
|
Jérémy Lecour <jlecour@evolix.fr>,
|
||||||
|
Éric Morino <emorino@evolix.fr>,
|
||||||
|
Brice Waegeneire <bwaegeneire@evolix.fr>
|
||||||
|
and others.
|
||||||
|
|
||||||
|
${REPOSITORY}
|
||||||
|
|
||||||
|
${PROGNAME} comes with ABSOLUTELY NO WARRANTY.This is free software,
|
||||||
|
and you are welcome to redistribute it under certain conditions.
|
||||||
|
See the GNU General Public License v3.0 for details.
|
||||||
|
END
|
||||||
|
}
|
||||||
|
show_help() {
|
||||||
|
cat <<END
|
||||||
|
${PROGNAME} is dumping information related to the state of the server.
|
||||||
|
|
||||||
|
Usage: ${PROGNAME} --dump-dir=/path/to/dump/directory [OPTIONS]
|
||||||
|
|
||||||
|
Main options
|
||||||
|
-d, --dump-dir path to the directory where data will be stored
|
||||||
|
--backup-dir legacy option for dump directory
|
||||||
|
-f, --force keep existing dump directory and its content
|
||||||
|
-v, --verbose print details about each task
|
||||||
|
-V, --version print version and exit
|
||||||
|
-h, --help print this message and exit
|
||||||
|
|
||||||
|
Tasks options
|
||||||
|
--all reset options to execute all tasks
|
||||||
|
--none reset options to execute no task
|
||||||
|
--[no-]etc copy of /etc (default: no)
|
||||||
|
--[no-]dpkg-full copy of /var/lib/dpkg (default: no)
|
||||||
|
--[no-]dpkg-status copy of /var/lib/dpkg/status (default: yes)
|
||||||
|
--[no-]apt-states copy of apt extended states (default: yes)
|
||||||
|
--[no-]apt-config copy of apt configuration (default: yes)
|
||||||
|
--[no-]packages copy of dpkg selections (default: yes)
|
||||||
|
--[no-]processes copy of process list (default: yes)
|
||||||
|
--[no-]uname copy of uname value (default: yes)
|
||||||
|
--[no-]uptime copy of uptime value (default: yes)
|
||||||
|
--[no-]netstat copy of netstat (default: yes)
|
||||||
|
--[no-]netcfg copy of network configuration (default: yes)
|
||||||
|
--[no-]iptables copy of iptables (default: yes)
|
||||||
|
--[no-]sysctl copy of sysctl values (default: yes)
|
||||||
|
--[no-]virsh copy of virsh list (default: yes)
|
||||||
|
--[no-]lxc copy of lxc list (default: yes)
|
||||||
|
--[no-]disks copy of MBR and partitions (default: yes)
|
||||||
|
--[no-]mount copy of mount points (default: yes)
|
||||||
|
--[no-]df copy of disk usage (default: yes)
|
||||||
|
--[no-]dmesg copy of dmesg (default: yes)
|
||||||
|
--[no-]mysql copy of mysql processes (default: yes)
|
||||||
|
--[no-]systemctl copy of systemd services states (default: yes)
|
||||||
|
|
||||||
|
Tasks options order matters. They are evaluated from left to right.
|
||||||
|
Examples :
|
||||||
|
* "[…] --none --uname" will do only the uname task
|
||||||
|
* "[…] --all --no-etc" will do everything but the etc task
|
||||||
|
* "[…] --etc --none --mysql" will do only the mysql task
|
||||||
|
END
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ]; then
|
||||||
|
msg="${1:-$(cat /dev/stdin)}"
|
||||||
|
echo "${msg}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
create_dump_dir() {
|
||||||
|
debug "Task: Create ${dump_dir}"
|
||||||
|
|
||||||
|
last_result=$(mkdir -p "${dump_dir}" && chmod -R 755 "${dump_dir}")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* mkdir/chmod OK"
|
||||||
|
else
|
||||||
|
debug "* mkdir/chmod ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_etc() {
|
||||||
|
debug "Task: /etc"
|
||||||
|
|
||||||
|
rsync_bin=$(command -v rsync)
|
||||||
|
|
||||||
|
if [ -n "${rsync_bin}" ]; then
|
||||||
|
last_result=$(${rsync_bin} -ah --itemize-changes --exclude=.git /etc "${dump_dir}/")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* rsync OK"
|
||||||
|
else
|
||||||
|
debug "* rsync ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* rsync not found"
|
||||||
|
last_result=$(cp -r /etc "${dump_dir}/ && rm -rf ${dump_dir}/etc/.git")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* cp OK"
|
||||||
|
else
|
||||||
|
debug "* cp ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_apt_states() {
|
||||||
|
apt_dir="/"
|
||||||
|
apt_dir_state="var/lib/apt"
|
||||||
|
apt_dir_state_extended_states="extended_states"
|
||||||
|
|
||||||
|
apt_config_bin=$(command -v apt-config)
|
||||||
|
|
||||||
|
if [ -n "${apt_config_bin}" ]; then
|
||||||
|
eval "$(${apt_config_bin} shell apt_dir Dir)"
|
||||||
|
eval "$(${apt_config_bin} shell apt_dir_state Dir::State)"
|
||||||
|
eval "$(${apt_config_bin} shell apt_dir_state_extended_states Dir::State::extended_states)"
|
||||||
|
fi
|
||||||
|
extended_states="${apt_dir}/${apt_dir_state}/${apt_dir_state_extended_states}"
|
||||||
|
|
||||||
|
if [ -f "${extended_states}" ]; then
|
||||||
|
debug "Task: APT states"
|
||||||
|
|
||||||
|
last_result=$(cp -r "${extended_states}" "${dump_dir}/apt-extended-states.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* cp OK"
|
||||||
|
else
|
||||||
|
debug "* cp ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_apt_config() {
|
||||||
|
debug "Task: APT config"
|
||||||
|
|
||||||
|
apt_config_bin=$(command -v apt-config)
|
||||||
|
|
||||||
|
if [ -n "${apt_config_bin}" ]; then
|
||||||
|
last_result=$(${apt_config_bin} dump > "${dump_dir}/apt-config.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* apt-config OK"
|
||||||
|
else
|
||||||
|
debug "* apt-config ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* apt-config is not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_dpkg_full() {
|
||||||
|
debug "Task: DPkg full state"
|
||||||
|
|
||||||
|
dir_state_status="/var/lib/dpkg/status"
|
||||||
|
|
||||||
|
apt_config_bin=$(command -v apt-config)
|
||||||
|
|
||||||
|
if [ -n "${apt_config_bin}" ]; then
|
||||||
|
eval "$(${apt_config_bin} shell dir_state_status Dir::State::status)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
dpkg_dir=$(dirname "${dir_state_status}")
|
||||||
|
|
||||||
|
last_result=$(mkdir -p "${dump_dir}${dpkg_dir}" && chmod -R 755 "${dump_dir}${dpkg_dir}")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* mkdir/chmod OK"
|
||||||
|
else
|
||||||
|
debug "* mkdir/chmod ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
rsync_bin=$(command -v rsync)
|
||||||
|
|
||||||
|
if [ -n "${rsync_bin}" ]; then
|
||||||
|
last_result=$(${rsync_bin} -ah --itemize-changes --exclude='*-old' "${dpkg_dir}/" "${dump_dir}${dpkg_dir}/")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* rsync OK"
|
||||||
|
else
|
||||||
|
debug "* rsync ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* rsync not found"
|
||||||
|
|
||||||
|
last_result=$(cp -r "${dpkg_dir}/*" "${dump_dir}${dpkg_dir}/" && rm -rf "${dump_dir}${dpkg_dir}/*-old")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* cp OK"
|
||||||
|
else
|
||||||
|
debug "* cp ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_dpkg_status() {
|
||||||
|
debug "Task: DPkg status"
|
||||||
|
|
||||||
|
dir_state_status="/var/lib/dpkg/status"
|
||||||
|
|
||||||
|
apt_config_bin=$(command -v apt-config)
|
||||||
|
|
||||||
|
if [ -n "${apt_config_bin}" ]; then
|
||||||
|
eval "$(${apt_config_bin} shell dir_state_status Dir::State::status)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
last_result=$(cp "${dir_state_status}" "${dump_dir}/dpkg-status.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* cp OK"
|
||||||
|
else
|
||||||
|
debug "* cp ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_packages() {
|
||||||
|
debug "Task: List of installed package"
|
||||||
|
|
||||||
|
dpkg_bin=$(command -v dpkg)
|
||||||
|
|
||||||
|
if [ -n "${dpkg_bin}" ]; then
|
||||||
|
last_result=$(${dpkg_bin} --get-selections "*" > "${dump_dir}/current_packages.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* dpkg OK"
|
||||||
|
else
|
||||||
|
debug "* dpkg ERROR :"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* dpkg not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_uname() {
|
||||||
|
debug "Task: uname"
|
||||||
|
|
||||||
|
last_result=$(uname -a > "${dump_dir}/uname.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* uname OK"
|
||||||
|
else
|
||||||
|
debug "* uname ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_uptime() {
|
||||||
|
debug "Task: uptime"
|
||||||
|
|
||||||
|
last_result=$(uptime > "${dump_dir}/uptime.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* uptime OK"
|
||||||
|
else
|
||||||
|
debug "* uptime ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_processes() {
|
||||||
|
debug "Task: Process list"
|
||||||
|
|
||||||
|
last_result=$(ps fauxw > "${dump_dir}/ps.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* ps OK"
|
||||||
|
else
|
||||||
|
debug "* ps ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
pstree_bin=$(command -v pstree)
|
||||||
|
|
||||||
|
if [ -n "${pstree_bin}" ]; then
|
||||||
|
last_result=$(${pstree_bin} -pan > "${dump_dir}/pstree.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* pstree OK"
|
||||||
|
else
|
||||||
|
debug "* pstree ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_netstat() {
|
||||||
|
debug "Task: Network status"
|
||||||
|
|
||||||
|
ss_bin=$(command -v ss)
|
||||||
|
|
||||||
|
if [ -n "${ss_bin}" ]; then
|
||||||
|
last_result=$(${ss_bin} -tanpul > "${dump_dir}/netstat-ss.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* ss OK"
|
||||||
|
else
|
||||||
|
debug "* ss ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* ss not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
netstat_bin=$(command -v netstat)
|
||||||
|
|
||||||
|
if [ -n "${netstat_bin}" ]; then
|
||||||
|
last_result=$(netstat -laputen > "${dump_dir}/netstat-legacy.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* netstat OK"
|
||||||
|
else
|
||||||
|
debug "* netstat ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* netstat not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_netcfg() {
|
||||||
|
debug "Task: Network configuration"
|
||||||
|
|
||||||
|
ip_bin=$(command -v ip)
|
||||||
|
|
||||||
|
if [ -n "${ip_bin}" ]; then
|
||||||
|
last_result=$(${ip_bin} address show > "${dump_dir}/ip-address.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* ip address OK"
|
||||||
|
else
|
||||||
|
debug "* ip address ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
last_result=$(${ip_bin} route show > "${dump_dir}/ip-route.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* ip route OK"
|
||||||
|
else
|
||||||
|
debug "* ip route ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* ip not found"
|
||||||
|
|
||||||
|
ifconfig_bin=$(command -v ifconfig)
|
||||||
|
|
||||||
|
if [ -n "${ifconfig_bin}" ]; then
|
||||||
|
last_result=$(${ifconfig_bin} > "${dump_dir}/ifconfig.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* ifconfig OK"
|
||||||
|
else
|
||||||
|
debug "* ifconfig ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* ifconfig not found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_iptables() {
|
||||||
|
debug "Task: iptables"
|
||||||
|
|
||||||
|
iptables_bin=$(command -v iptables)
|
||||||
|
ip6tables_bin=$(command -v ip6tables)
|
||||||
|
|
||||||
|
if [ -n "${iptables_bin}" ]; then
|
||||||
|
last_result=$({
|
||||||
|
printf "#### iptables --list ###############################\n"
|
||||||
|
${iptables_bin} --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n### iptables --table nat --list ####################\n"
|
||||||
|
${iptables_bin} --table nat --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n#### iptables --table mangle --list ################\n"
|
||||||
|
${iptables_bin} --table mangle --list --numeric --verbose --line-numbers
|
||||||
|
if [ -n "${ip6tables_bin}" ]; then
|
||||||
|
printf "\n#### ip6tables --list ##############################\n"
|
||||||
|
${ip6tables_bin} --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n#### ip6tables --table mangle --list ###############\n"
|
||||||
|
${ip6tables_bin} --table mangle --list --numeric --verbose --line-numbers
|
||||||
|
fi
|
||||||
|
} > "${dump_dir}/iptables-v.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* iptables -v OK"
|
||||||
|
else
|
||||||
|
debug "* iptables -v ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
# Ignore errors because we don't know if this is nft related or a real error
|
||||||
|
# rc=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
last_result=$({
|
||||||
|
printf "#### iptables --list ###############################\n"
|
||||||
|
${iptables_bin} --list --numeric
|
||||||
|
printf "\n### iptables --table nat --list ####################\n"
|
||||||
|
${iptables_bin} --table nat --list --numeric
|
||||||
|
printf "\n#### iptables --table mangle --list ################\n"
|
||||||
|
${iptables_bin} --table mangle --list --numeric
|
||||||
|
if [ -n "${ip6tables_bin}" ]; then
|
||||||
|
printf "\n#### ip6tables --list ##############################\n"
|
||||||
|
${ip6tables_bin} --list --numeric
|
||||||
|
printf "\n#### ip6tables --table mangle --list ###############\n"
|
||||||
|
${ip6tables_bin} --table mangle --list --numeric
|
||||||
|
fi
|
||||||
|
} > "${dump_dir}/iptables.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* iptables OK"
|
||||||
|
else
|
||||||
|
debug "* iptables ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
# Ignore errors because we don't know if this is nft related or a real error
|
||||||
|
# rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* iptables not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
iptables_save_bin=$(command -v iptables-save)
|
||||||
|
|
||||||
|
if [ -n "${iptables_save_bin}" ]; then
|
||||||
|
last_result=$(${iptables_save_bin} > "${dump_dir}/iptables-save.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* iptables-save OK"
|
||||||
|
else
|
||||||
|
debug "* iptables-save ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
# Ignore errors because we don't know if this is nft related or a real error
|
||||||
|
# rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* iptables-save not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
nft_bin=$(command -v nft)
|
||||||
|
|
||||||
|
if [ -n "${nft_bin}" ]; then
|
||||||
|
last_result=$(${nft_bin} list ruleset > "${dump_dir}/nft-ruleset.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* nft ruleset OK"
|
||||||
|
else
|
||||||
|
debug "* nft ruleset ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_sysctl() {
|
||||||
|
debug "Task: sysctl values"
|
||||||
|
|
||||||
|
sysctl_bin=$(command -v sysctl)
|
||||||
|
|
||||||
|
if [ -n "${sysctl_bin}" ]; then
|
||||||
|
last_result=$(${sysctl_bin} -a --ignore 2>/dev/null | sort -h > "${dump_dir}/sysctl.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* sysctl OK"
|
||||||
|
else
|
||||||
|
debug "* sysctl ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* sysctl not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_virsh() {
|
||||||
|
debug "Task: virsh list"
|
||||||
|
|
||||||
|
virsh_bin=$(command -v virsh)
|
||||||
|
|
||||||
|
if [ -n "${virsh_bin}" ]; then
|
||||||
|
last_result=$(${virsh_bin} list --all > "${dump_dir}/virsh-list.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* virsh list OK"
|
||||||
|
else
|
||||||
|
debug "* virsh list ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* virsh not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_lxc() {
|
||||||
|
debug "Task: lxc list"
|
||||||
|
|
||||||
|
lxc_ls_bin=$(command -v lxc-ls)
|
||||||
|
|
||||||
|
if [ -n "${lxc_ls_bin}" ]; then
|
||||||
|
last_result=$(${lxc_ls_bin} --fancy > "${dump_dir}/lxc-list.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* lxc list OK"
|
||||||
|
else
|
||||||
|
debug "* lxc list ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* lxc-ls not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_disks() {
|
||||||
|
debug "Task: Disks"
|
||||||
|
|
||||||
|
lsblk_bin=$(command -v lsblk)
|
||||||
|
awk_bin=$(command -v awk)
|
||||||
|
|
||||||
|
if [ -n "${lsblk_bin}" ] && [ -n "${awk_bin}" ]; then
|
||||||
|
disks=$(${lsblk_bin} -l | grep disk | grep -v -E '(drbd|fd[0-9]+)' | ${awk_bin} '{print $1}')
|
||||||
|
for disk in ${disks}; do
|
||||||
|
dd_bin=$(command -v dd)
|
||||||
|
if [ -n "${dd_bin}" ]; then
|
||||||
|
last_result=$(${dd_bin} if="/dev/${disk}" of="${dump_dir}/MBR-${disk}" bs=512 count=1 2>&1)
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* dd ${disk} OK"
|
||||||
|
else
|
||||||
|
debug "* dd ${disk} ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* dd not found"
|
||||||
|
fi
|
||||||
|
fdisk_bin=$(command -v fdisk)
|
||||||
|
if [ -n "${fdisk_bin}" ]; then
|
||||||
|
last_result=$(${fdisk_bin} -l "/dev/${disk}" > "${dump_dir}/partitions-${disk}" 2>&1)
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* fdisk ${disk} OK"
|
||||||
|
else
|
||||||
|
debug "* fdisk ${disk} ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* fdisk not found"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
cat "${dump_dir}"/partitions-* > "${dump_dir}/partitions"
|
||||||
|
else
|
||||||
|
if [ -n "${lsblk_bin}" ]; then
|
||||||
|
debug "* lsblk not found"
|
||||||
|
fi
|
||||||
|
if [ -n "${awk_bin}" ]; then
|
||||||
|
debug "* awk not found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_mount() {
|
||||||
|
debug "Task: Mount points"
|
||||||
|
|
||||||
|
findmnt_bin=$(command -v findmnt)
|
||||||
|
|
||||||
|
if [ -n "${findmnt_bin}" ]; then
|
||||||
|
last_result=$(${findmnt_bin} > "${dump_dir}/mount.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* mount points OK"
|
||||||
|
else
|
||||||
|
debug "* mount points ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* findmnt not found"
|
||||||
|
|
||||||
|
mount_bin=$(command -v mount)
|
||||||
|
|
||||||
|
if [ -n "${mount_bin}" ]; then
|
||||||
|
last_result=$(${mount_bin} > "${dump_dir}/mount.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* mount points OK"
|
||||||
|
else
|
||||||
|
debug "* mount points ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* mount not found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_df() {
|
||||||
|
debug "Task: df"
|
||||||
|
|
||||||
|
df_bin=$(command -v df)
|
||||||
|
|
||||||
|
if [ -n "${df_bin}" ]; then
|
||||||
|
last_result=$(${df_bin} --portability > "${dump_dir}/df.txt" 2>&1)
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* df OK"
|
||||||
|
else
|
||||||
|
debug "* df ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* df not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_dmesg() {
|
||||||
|
debug "Task: dmesg"
|
||||||
|
|
||||||
|
dmesg_bin=$(command -v dmesg)
|
||||||
|
|
||||||
|
if [ -n "${dmesg_bin}" ]; then
|
||||||
|
last_result=$(${dmesg_bin} > "${dump_dir}/dmesg.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* dmesg OK"
|
||||||
|
else
|
||||||
|
debug "* dmesg ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* dmesg not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_mysql_processes() {
|
||||||
|
debug "Task: MySQL processes"
|
||||||
|
|
||||||
|
mysqladmin_bin=$(command -v mysqladmin)
|
||||||
|
|
||||||
|
if [ -n "${mysqladmin_bin}" ]; then
|
||||||
|
# Look for local MySQL or MariaDB process
|
||||||
|
if pgrep mysqld > /dev/null || pgrep mariadbd > /dev/null; then
|
||||||
|
if ${mysqladmin_bin} ping > /dev/null 2>&1; then
|
||||||
|
${mysqladmin_bin} --verbose processlist > "${dump_dir}/mysql-processlist.txt" 2> "${dump_dir}/mysql-processlist.err"
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* mysqladmin OK"
|
||||||
|
else
|
||||||
|
debug "* mysqladmin ERROR"
|
||||||
|
debug < "${dump_dir}/mysql-processlist.err"
|
||||||
|
rm "${dump_dir}/mysql-processlist.err"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* unable to ping with mysqladmin"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* no mysqld or mariadbd process is running"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* mysqladmin not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_systemctl() {
|
||||||
|
debug "Task: Systemd services"
|
||||||
|
|
||||||
|
systemctl_bin=$(command -v systemctl)
|
||||||
|
|
||||||
|
if [ -n "${systemctl_bin}" ]; then
|
||||||
|
last_result=$(${systemctl_bin} --no-legend --state=failed --type=service > "${dump_dir}/systemctl-failed-services.txt")
|
||||||
|
last_rc=$?
|
||||||
|
|
||||||
|
if [ ${last_rc} -eq 0 ]; then
|
||||||
|
debug "* failed services OK"
|
||||||
|
else
|
||||||
|
debug "* failed services ERROR"
|
||||||
|
debug "${last_result}"
|
||||||
|
rc=10
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "* systemctl not found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if [ -z "${dump_dir}" ]; then
|
||||||
|
echo "ERROR: You must provide the --dump-dir argument" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "${dump_dir}" ]; then
|
||||||
|
if [ "${FORCE}" != "1" ]; then
|
||||||
|
echo "ERROR: The dump directory ${dump_dir} already exists. Delete it first." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
create_dump_dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${TASK_ETC}" -eq 1 ]; then
|
||||||
|
task_etc
|
||||||
|
fi
|
||||||
|
if [ "${TASK_DPKG_FULL}" -eq 1 ]; then
|
||||||
|
task_dpkg_full
|
||||||
|
fi
|
||||||
|
if [ "${TASK_DPKG_STATUS}" -eq 1 ]; then
|
||||||
|
task_dpkg_status
|
||||||
|
fi
|
||||||
|
if [ "${TASK_APT_STATES}" -eq 1 ]; then
|
||||||
|
task_apt_states
|
||||||
|
fi
|
||||||
|
if [ "${TASK_APT_CONFIG}" -eq 1 ]; then
|
||||||
|
task_apt_config
|
||||||
|
fi
|
||||||
|
if [ "${TASK_PACKAGES}" -eq 1 ]; then
|
||||||
|
task_packages
|
||||||
|
fi
|
||||||
|
if [ "${TASK_PROCESSES}" -eq 1 ]; then
|
||||||
|
task_processes
|
||||||
|
fi
|
||||||
|
if [ "${TASK_UPTIME}" -eq 1 ]; then
|
||||||
|
task_uptime
|
||||||
|
fi
|
||||||
|
if [ "${TASK_UNAME}" -eq 1 ]; then
|
||||||
|
task_uname
|
||||||
|
fi
|
||||||
|
if [ "${TASK_NETSTAT}" -eq 1 ]; then
|
||||||
|
task_netstat
|
||||||
|
fi
|
||||||
|
if [ "${TASK_NETCFG}" -eq 1 ]; then
|
||||||
|
task_netcfg
|
||||||
|
fi
|
||||||
|
if [ "${TASK_IPTABLES}" -eq 1 ]; then
|
||||||
|
task_iptables
|
||||||
|
fi
|
||||||
|
if [ "${TASK_SYSCTL}" -eq 1 ]; then
|
||||||
|
task_sysctl
|
||||||
|
fi
|
||||||
|
if [ "${TASK_VIRSH}" -eq 1 ]; then
|
||||||
|
task_virsh
|
||||||
|
fi
|
||||||
|
if [ "${TASK_LXC}" -eq 1 ]; then
|
||||||
|
task_lxc
|
||||||
|
fi
|
||||||
|
if [ "${TASK_DISKS}" -eq 1 ]; then
|
||||||
|
task_disks
|
||||||
|
fi
|
||||||
|
if [ "${TASK_MOUNT}" -eq 1 ]; then
|
||||||
|
task_mount
|
||||||
|
fi
|
||||||
|
if [ "${TASK_DF}" -eq 1 ]; then
|
||||||
|
task_df
|
||||||
|
fi
|
||||||
|
if [ "${TASK_DMESG}" -eq 1 ]; then
|
||||||
|
task_dmesg
|
||||||
|
fi
|
||||||
|
if [ "${TASK_MYSQL_PROCESSES}" -eq 1 ]; then
|
||||||
|
task_mysql_processes
|
||||||
|
fi
|
||||||
|
if [ "${TASK_SYSTEMCTL}" -eq 1 ]; then
|
||||||
|
task_systemctl
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
debug "=> Your dump is available at ${dump_dir}"
|
||||||
|
exit ${rc}
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse options
|
||||||
|
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||||
|
while :; do
|
||||||
|
case $1 in
|
||||||
|
-h|-\?|--help)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-V|--version)
|
||||||
|
show_version
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
VERBOSE=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
-f|--force)
|
||||||
|
FORCE=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
-d|--dump-dir)
|
||||||
|
# with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
dump_dir=$2
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
printf 'ERROR: "-d|--dump-dir" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--dump-dir=?*)
|
||||||
|
# with value speparated by =
|
||||||
|
dump_dir=${1#*=}
|
||||||
|
;;
|
||||||
|
--dump-dir=)
|
||||||
|
# without value
|
||||||
|
printf 'ERROR: "--dump-dir" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
--backup-dir)
|
||||||
|
printf 'WARNING: "--backup-dir" is deprecated in favor of "--dump-dir".\n'
|
||||||
|
if [ -n "${dump_dir}" ]; then
|
||||||
|
debug "Dump directory is already set, let's ignore this one."
|
||||||
|
else
|
||||||
|
debug "Dump directory is not set already, let's stay backward compatible."
|
||||||
|
# with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
dump_dir=$2
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
printf 'ERROR: "--backup-dir" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--backup-dir=?*)
|
||||||
|
# with value speparated by =
|
||||||
|
printf 'WARNING: "--backup-dir" is deprecated in favor of "--dump-dir".\n'
|
||||||
|
if [ -n "${dump_dir}" ]; then
|
||||||
|
debug "Dump directory is already set, let's ignore this one."
|
||||||
|
else
|
||||||
|
debug "Dump directory is not set already, let's stay backward compatible."
|
||||||
|
dump_dir=${1#*=}
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--backup-dir=)
|
||||||
|
# without value
|
||||||
|
printf 'WARNING: "--backup-dir" is deprecated in favor of "--dump-dir".\n'
|
||||||
|
if [ -n "${dump_dir}" ]; then
|
||||||
|
debug "Dump directory is already set, let's ignore this one."
|
||||||
|
else
|
||||||
|
printf 'ERROR: "--backup-dir" requires a non-empty option argument.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
--all)
|
||||||
|
for option in \
|
||||||
|
TASK_ETC \
|
||||||
|
TASK_DPKG_FULL \
|
||||||
|
TASK_DPKG_STATUS \
|
||||||
|
TASK_APT_STATES \
|
||||||
|
TASK_APT_CONFIG \
|
||||||
|
TASK_PACKAGES \
|
||||||
|
TASK_PROCESSES \
|
||||||
|
TASK_UNAME \
|
||||||
|
TASK_UPTIME \
|
||||||
|
TASK_NETSTAT \
|
||||||
|
TASK_NETCFG \
|
||||||
|
TASK_IPTABLES \
|
||||||
|
TASK_SYSCTL \
|
||||||
|
TASK_VIRSH \
|
||||||
|
TASK_LXC \
|
||||||
|
TASK_DISKS \
|
||||||
|
TASK_MOUNT \
|
||||||
|
TASK_DF \
|
||||||
|
TASK_DMESG \
|
||||||
|
TASK_MYSQL_PROCESSES \
|
||||||
|
TASK_SYSTEMCTL
|
||||||
|
do
|
||||||
|
eval "${option}=1"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
--none)
|
||||||
|
for option in \
|
||||||
|
TASK_ETC \
|
||||||
|
TASK_DPKG_FULL \
|
||||||
|
TASK_DPKG_STATUS \
|
||||||
|
TASK_APT_STATES \
|
||||||
|
TASK_APT_CONFIG \
|
||||||
|
TASK_PACKAGES \
|
||||||
|
TASK_PROCESSES \
|
||||||
|
TASK_UNAME \
|
||||||
|
TASK_UPTIME \
|
||||||
|
TASK_NETSTAT \
|
||||||
|
TASK_NETCFG \
|
||||||
|
TASK_IPTABLES \
|
||||||
|
TASK_SYSCTL \
|
||||||
|
TASK_VIRSH \
|
||||||
|
TASK_LXC \
|
||||||
|
TASK_DISKS \
|
||||||
|
TASK_MOUNT \
|
||||||
|
TASK_DF \
|
||||||
|
TASK_DMESG \
|
||||||
|
TASK_MYSQL_PROCESSES \
|
||||||
|
TASK_SYSTEMCTL
|
||||||
|
do
|
||||||
|
eval "${option}=0"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
--etc)
|
||||||
|
TASK_ETC=1
|
||||||
|
;;
|
||||||
|
--no-etc)
|
||||||
|
TASK_ETC=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--dpkg-full)
|
||||||
|
TASK_DPKG_FULL=1
|
||||||
|
;;
|
||||||
|
--no-dpkg-full)
|
||||||
|
TASK_DPKG_FULL=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--dpkg-status)
|
||||||
|
TASK_DPKG_STATUS=1
|
||||||
|
;;
|
||||||
|
--no-dpkg-status)
|
||||||
|
TASK_DPKG_STATUS=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--apt-states)
|
||||||
|
TASK_APT_STATES=1
|
||||||
|
;;
|
||||||
|
--no-apt-states)
|
||||||
|
TASK_APT_STATES=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--apt-config)
|
||||||
|
TASK_APT_CONFIG=1
|
||||||
|
;;
|
||||||
|
--no-apt-config)
|
||||||
|
TASK_APT_CONFIG=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--packages)
|
||||||
|
TASK_PACKAGES=1
|
||||||
|
;;
|
||||||
|
--no-packages)
|
||||||
|
TASK_PACKAGES=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--processes)
|
||||||
|
TASK_PROCESSES=1
|
||||||
|
;;
|
||||||
|
--no-processes)
|
||||||
|
TASK_PROCESSES=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--uptime)
|
||||||
|
TASK_UPTIME=1
|
||||||
|
;;
|
||||||
|
--no-uptime)
|
||||||
|
TASK_UPTIME=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--uname)
|
||||||
|
TASK_UNAME=1
|
||||||
|
;;
|
||||||
|
--no-uname)
|
||||||
|
TASK_UNAME=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--netstat)
|
||||||
|
TASK_NETSTAT=1
|
||||||
|
;;
|
||||||
|
--no-netstat)
|
||||||
|
TASK_NETSTAT=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--netcfg)
|
||||||
|
TASK_NETCFG=1
|
||||||
|
;;
|
||||||
|
--no-netcfg)
|
||||||
|
TASK_NETCFG=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--iptables)
|
||||||
|
TASK_IPTABLES=1
|
||||||
|
;;
|
||||||
|
--no-iptables)
|
||||||
|
TASK_IPTABLES=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--sysctl)
|
||||||
|
TASK_SYSCTL=1
|
||||||
|
;;
|
||||||
|
--no-sysctl)
|
||||||
|
TASK_SYSCTL=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--virsh)
|
||||||
|
TASK_VIRSH=1
|
||||||
|
;;
|
||||||
|
--no-virsh)
|
||||||
|
TASK_VIRSH=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--lxc)
|
||||||
|
TASK_LXC=1
|
||||||
|
;;
|
||||||
|
--no-lxc)
|
||||||
|
TASK_LXC=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--disks)
|
||||||
|
TASK_DISKS=1
|
||||||
|
;;
|
||||||
|
--no-disks)
|
||||||
|
TASK_DISKS=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--mount)
|
||||||
|
TASK_MOUNT=1
|
||||||
|
;;
|
||||||
|
--no-mount)
|
||||||
|
TASK_MOUNT=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--df)
|
||||||
|
TASK_DF=1
|
||||||
|
;;
|
||||||
|
--no-df)
|
||||||
|
TASK_DF=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--dmesg)
|
||||||
|
TASK_DMESG=1
|
||||||
|
;;
|
||||||
|
--no-dmesg)
|
||||||
|
TASK_DMESG=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--mysql-processes)
|
||||||
|
TASK_MYSQL_PROCESSES=1
|
||||||
|
;;
|
||||||
|
--no-mysql-processes)
|
||||||
|
TASK_MYSQL_PROCESSES=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--systemctl)
|
||||||
|
TASK_SYSTEMCTL=1
|
||||||
|
;;
|
||||||
|
--no-systemctl)
|
||||||
|
TASK_SYSTEMCTL=0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--)
|
||||||
|
# End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
# ignore unknown options
|
||||||
|
printf 'WARN: Unknown option : %s\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case: If no more options then break out of the loop.
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
: "${VERBOSE:=0}"
|
||||||
|
: "${FORCE:=0}"
|
||||||
|
: "${TASK_ETC:=0}"
|
||||||
|
: "${TASK_DPKG_FULL:=0}"
|
||||||
|
: "${TASK_DPKG_STATUS:=1}"
|
||||||
|
: "${TASK_APT_STATES:=1}"
|
||||||
|
: "${TASK_APT_CONFIG:=1}"
|
||||||
|
: "${TASK_PACKAGES:=1}"
|
||||||
|
: "${TASK_PROCESSES:=1}"
|
||||||
|
: "${TASK_UNAME:=1}"
|
||||||
|
: "${TASK_UPTIME:=1}"
|
||||||
|
: "${TASK_NETSTAT:=1}"
|
||||||
|
: "${TASK_NETCFG:=1}"
|
||||||
|
: "${TASK_IPTABLES:=1}"
|
||||||
|
: "${TASK_SYSCTL:=1}"
|
||||||
|
: "${TASK_VIRSH:=1}"
|
||||||
|
: "${TASK_LXC:=1}"
|
||||||
|
: "${TASK_DISKS:=1}"
|
||||||
|
: "${TASK_MOUNT:=1}"
|
||||||
|
: "${TASK_DF:=1}"
|
||||||
|
: "${TASK_DMESG:=1}"
|
||||||
|
: "${TASK_MYSQL_PROCESSES:=1}"
|
||||||
|
: "${TASK_SYSTEMCTL:=1}"
|
||||||
|
|
||||||
|
export LC_ALL=C
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
main
|
|
@ -1,15 +1,15 @@
|
||||||
top's Config File (Linux processes with windows)
|
top's Config File (Linux processes with windows)
|
||||||
Id:j, Mode_altscr=0, Mode_irixps=1, Delay_time=3.0, Curwin=0
|
Id:j, Mode_altscr=0, Mode_irixps=1, Delay_time=3.0, Curwin=0
|
||||||
Def fieldscur=ķ&')*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
Def fieldscur=¥¨³´»½À¼Ä·º¹Å&')*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
||||||
winflags=193844, sortindx=18, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
winflags=177460, sortindx=18, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
||||||
summclr=1, msgsclr=1, headclr=3, taskclr=1
|
summclr=1, msgsclr=1, headclr=3, taskclr=1
|
||||||
Job fieldscur=(Ļ@<)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
Job fieldscur=¥¦¹·º(³´Ä»½@<§Å)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
||||||
winflags=193844, sortindx=0, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
winflags=193844, sortindx=0, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
||||||
summclr=6, msgsclr=6, headclr=7, taskclr=6
|
summclr=6, msgsclr=6, headclr=7, taskclr=6
|
||||||
Mem fieldscur=<MBND34&'()*+,-./0125689FGHIJKLOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
Mem fieldscur=¥º»<½¾¿ÀÁMBNÃD34·Å&'()*+,-./0125689FGHIJKLOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
||||||
winflags=193844, sortindx=21, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
winflags=193844, sortindx=21, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
||||||
summclr=5, msgsclr=5, headclr=4, taskclr=5
|
summclr=5, msgsclr=5, headclr=4, taskclr=5
|
||||||
Usr fieldscur=)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
Usr fieldscur=¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
|
||||||
winflags=193844, sortindx=3, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
winflags=193844, sortindx=3, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0
|
||||||
summclr=3, msgsclr=3, headclr=2, taskclr=3
|
summclr=3, msgsclr=3, headclr=2, taskclr=3
|
||||||
Fixed_widest=0, Summ_mscale=1, Task_mscale=0, Zero_suppress=0
|
Fixed_widest=0, Summ_mscale=1, Task_mscale=0, Zero_suppress=0
|
||||||
|
|
|
@ -72,3 +72,8 @@
|
||||||
name: postfix
|
name: postfix
|
||||||
state: reloaded
|
state: reloaded
|
||||||
|
|
||||||
|
- name: restart log2mail
|
||||||
|
service:
|
||||||
|
name: log2mail
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,14 @@
|
||||||
|
|
||||||
|
|
||||||
## Dedicated hardware
|
## Dedicated hardware
|
||||||
- name: Install freepmi when it's dedicated hardware
|
- name: Install some additionnals tools when it dedicated hardware
|
||||||
apt:
|
apt:
|
||||||
name:
|
name:
|
||||||
- libipc-run-perl
|
- libipc-run-perl
|
||||||
- freeipmi
|
- freeipmi
|
||||||
|
- ipmitool
|
||||||
|
- firmware-linux-nonfree
|
||||||
|
- intel-microcode
|
||||||
state: present
|
state: present
|
||||||
tags:
|
tags:
|
||||||
- packages
|
- packages
|
||||||
|
|
|
@ -16,3 +16,20 @@
|
||||||
daemon-reload: yes
|
daemon-reload: yes
|
||||||
state: started
|
state: started
|
||||||
enabled: yes
|
enabled: yes
|
||||||
|
|
||||||
|
- name: log2mail config is present
|
||||||
|
blockinfile:
|
||||||
|
dest: /etc/log2mail/config/default
|
||||||
|
owner: log2mail
|
||||||
|
group: adm
|
||||||
|
mode: "0640"
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED RULES FOR DEFAULT INSTANCE"
|
||||||
|
block: |
|
||||||
|
file = /var/log/syslog
|
||||||
|
pattern = "Out of memory: Kill"
|
||||||
|
mailto = {{ log2mail_alert_email or general_alert_email | mandatory }}
|
||||||
|
template = /etc/log2mail/mail
|
||||||
|
notify: restart log2mail
|
||||||
|
tags:
|
||||||
|
- log2mail
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
apt_install_basics: "{{ evolinux_apt_replace_default_sources }}"
|
apt_install_basics: "{{ evolinux_apt_replace_default_sources }}"
|
||||||
apt_install_evolix_public: "{{ evolinux_apt_public_sources }}"
|
apt_install_evolix_public: "{{ evolinux_apt_public_sources }}"
|
||||||
apt_upgrade: "{{ evolinux_apt_upgrade }}"
|
apt_upgrade: "{{ evolinux_apt_upgrade }}"
|
||||||
|
apt_basics_components: "{{ 'main contrib non-free' if ansible_virtualization_role == 'host' else 'main' }}"
|
||||||
when: evolinux_apt_include | bool
|
when: evolinux_apt_include | bool
|
||||||
|
|
||||||
- name: /etc versioning with Git
|
- name: /etc versioning with Git
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
- name: Deploy top configuration file
|
- name: Deploy top configuration file
|
||||||
copy:
|
copy:
|
||||||
# The config format is unredable; ATM it only add the SWAP column
|
# The config format is unredable; ATM it only add the SWAP column
|
||||||
src: htoprc
|
src: topdefaultrc
|
||||||
dest: /etc/topdefaultrc
|
dest: /etc/topdefaultrc
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
|
@ -3,15 +3,22 @@
|
||||||
- include_role:
|
- include_role:
|
||||||
name: evolix/remount-usr
|
name: evolix/remount-usr
|
||||||
|
|
||||||
- name: backup-server-state script is present
|
- name: dump-server-state script is present
|
||||||
copy:
|
copy:
|
||||||
src: "backup-server-state.sh"
|
src: "dump-server-state.sh"
|
||||||
dest: /usr/local/sbin/backup-server-state
|
dest: /usr/local/sbin/dump-server-state
|
||||||
force: True
|
force: True
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
|
|
||||||
|
- name: symlink backup-server-state to dump-server-state
|
||||||
|
file:
|
||||||
|
src: /usr/local/sbin/dump-server-state
|
||||||
|
dest: /usr/local/sbin/backup-server-state
|
||||||
|
state: link
|
||||||
|
force: yes
|
||||||
|
|
||||||
- name: "/sbin/deny script is present"
|
- name: "/sbin/deny script is present"
|
||||||
copy:
|
copy:
|
||||||
src: deny.sh
|
src: deny.sh
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
- name: restart minifirewall
|
- name: restart minifirewall
|
||||||
command: /etc/init.d/minifirewall restart
|
command: /etc/init.d/minifirewall restart
|
||||||
register: minifirewall_init_restart
|
register: minifirewall_init_restart
|
||||||
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
failed_when:
|
||||||
changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout"
|
- "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
||||||
|
- "'minifirewall started' not in minifirewall_init_restart.stdout"
|
||||||
|
|
||||||
- name: restart minifirewall (noop)
|
- name: restart minifirewall (noop)
|
||||||
meta: noop
|
meta: noop
|
||||||
|
|
31
evomaintenance/tasks/install_vendor_other.yml
Normal file
31
evomaintenance/tasks/install_vendor_other.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
tags:
|
||||||
|
- evomaintenance
|
||||||
|
|
||||||
|
- name: /usr/share/scripts exists
|
||||||
|
file:
|
||||||
|
dest: /usr/share/scripts
|
||||||
|
mode: "0700"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
state: directory
|
||||||
|
tags:
|
||||||
|
- evomaintenance
|
||||||
|
|
||||||
|
- name: Evomaintenance script and template are installed
|
||||||
|
copy:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ item.dest }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "{{ item.mode }}"
|
||||||
|
force: yes
|
||||||
|
backup: yes
|
||||||
|
loop:
|
||||||
|
- { src: 'evomaintenance.sh', dest: '/usr/share/scripts/', mode: '0700' }
|
||||||
|
- { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/', mode: '0600' }
|
||||||
|
tags:
|
||||||
|
- evomaintenance
|
|
@ -10,6 +10,12 @@
|
||||||
- evomaintenance_install_vendor | bool
|
- evomaintenance_install_vendor | bool
|
||||||
- ansible_distribution == "Debian"
|
- ansible_distribution == "Debian"
|
||||||
|
|
||||||
|
- include: install_vendor_other.yml
|
||||||
|
when:
|
||||||
|
- evomaintenance_install_vendor | bool
|
||||||
|
- ansible_distribution != "Debian"
|
||||||
|
|
||||||
|
|
||||||
- include: config.yml
|
- include: config.yml
|
||||||
|
|
||||||
- include: minifirewall.yml
|
- include: minifirewall.yml
|
||||||
|
|
|
@ -608,11 +608,11 @@ if is_pkg_installed lxc; then
|
||||||
if lxc-ls | grep -q php56 ; then
|
if lxc-ls | grep -q php56 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm56,${computer_dn}
|
dn: ServiceName=php-fpm56,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm56
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 5.6 (multiphp)
|
ServiceVersion: PHP-FPM 5.6 (multiphp)
|
||||||
|
@ -622,11 +622,11 @@ fi
|
||||||
if lxc-ls | grep -q php70 ; then
|
if lxc-ls | grep -q php70 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm70,${computer_dn}
|
dn: ServiceName=php-fpm70,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm70
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 7.0 (multiphp)
|
ServiceVersion: PHP-FPM 7.0 (multiphp)
|
||||||
|
@ -636,11 +636,11 @@ fi
|
||||||
if lxc-ls | grep -q php73 ; then
|
if lxc-ls | grep -q php73 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm73,${computer_dn}
|
dn: ServiceName=php-fpm73,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm73
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 7.3 (multiphp)
|
ServiceVersion: PHP-FPM 7.3 (multiphp)
|
||||||
|
@ -650,11 +650,11 @@ fi
|
||||||
if lxc-ls | grep -q php74 ; then
|
if lxc-ls | grep -q php74 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm74,${computer_dn}
|
dn: ServiceName=php-fpm74,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm74
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 7.4 (multiphp)
|
ServiceVersion: PHP-FPM 7.4 (multiphp)
|
||||||
|
@ -664,11 +664,11 @@ fi
|
||||||
if lxc-ls | grep -q php80 ; then
|
if lxc-ls | grep -q php80 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm80,${computer_dn}
|
dn: ServiceName=php-fpm80,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm80
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 8.0 (multiphp)
|
ServiceVersion: PHP-FPM 8.0 (multiphp)
|
||||||
|
@ -678,11 +678,11 @@ fi
|
||||||
if lxc-ls | grep -q php81 ; then
|
if lxc-ls | grep -q php81 ; then
|
||||||
cat <<EOT >> "${ldif_file}"
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
dn: ServiceName=ServiceName=php-fpm81,${computer_dn}
|
dn: ServiceName=php-fpm81,${computer_dn}
|
||||||
NagiosEnabled: TRUE
|
NagiosEnabled: TRUE
|
||||||
ipServiceProtocol: tcp
|
ipServiceProtocol: tcp
|
||||||
objectClass: EvoService
|
objectClass: EvoService
|
||||||
ServiceName: PHP-FPM (multiphp)
|
ServiceName: php-fpm81
|
||||||
ipServicePort: 443
|
ipServicePort: 443
|
||||||
ServiceType: web
|
ServiceType: web
|
||||||
ServiceVersion: PHP-FPM 8.1 (multiphp)
|
ServiceVersion: PHP-FPM 8.1 (multiphp)
|
||||||
|
@ -709,6 +709,37 @@ EOT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# bkctld
|
||||||
|
if is_pkg_installed bkctld; then
|
||||||
|
bkctld_version=$(get_pkg_version bkctld)
|
||||||
|
fi
|
||||||
|
if [ -n "${bkctld_version}" ]; then
|
||||||
|
cat <<EOT >> "${ldif_file}"
|
||||||
|
|
||||||
|
dn: ServiceName=bkctld_jails,${computer_dn}
|
||||||
|
NagiosEnabled: TRUE
|
||||||
|
objectClass: EvoService
|
||||||
|
ServiceName: bkctld_jails
|
||||||
|
ServiceType: backup
|
||||||
|
ServiceVersion: bkctld ${bkctld_version}
|
||||||
|
|
||||||
|
dn: ServiceName=bkctld_setup,${computer_dn}
|
||||||
|
NagiosEnabled: TRUE
|
||||||
|
objectClass: EvoService
|
||||||
|
ServiceName: bkctld_setup
|
||||||
|
ServiceType: backup
|
||||||
|
ServiceVersion: bkctld ${bkctld_version}
|
||||||
|
|
||||||
|
dn: ServiceName=disk-worktime,${computer_dn}
|
||||||
|
NagiosEnabled: TRUE
|
||||||
|
objectClass: EvoService
|
||||||
|
ServiceName: disk-worktime
|
||||||
|
ServiceType: disk
|
||||||
|
ServiceVersion: Undefined
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# test if we have a stdout
|
# test if we have a stdout
|
||||||
if [ -t 1 ]; then
|
if [ -t 1 ]; then
|
||||||
echo "Output is in ${ldif_file}"
|
echo "Output is in ${ldif_file}"
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
force: yes
|
force: yes
|
||||||
tags:
|
tags:
|
||||||
- keepalived
|
- keepalived
|
||||||
- nrpe
|
- nrpe
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
state: present
|
state: present
|
||||||
special_time: "hourly"
|
special_time: "hourly"
|
||||||
user: root
|
user: root
|
||||||
job: "rsync -a --delete /etc/libvirt/qemu/*xml {{ hostvars[kvm_pair]['lan.ip'] }}:/root/libvirt-{{ inventory_hostname }}/"
|
job: "if ls /etc/libvirt/qemu/*xml > /dev/null 2> /dev/null; then rsync -a --delete /etc/libvirt/qemu/*xml {{ hostvars[kvm_pair]['lan.ip'] }}:/root/libvirt-{{ inventory_hostname }}/; fi"
|
||||||
when:
|
when:
|
||||||
- kvm_pair is defined
|
- kvm_pair is defined
|
||||||
- kvm_pair is not none
|
- kvm_pair is not none
|
||||||
|
|
|
@ -36,4 +36,6 @@ lxc.start.auto = 1
|
||||||
{% if ansible_distribution_major_version is version('9', '>') %}
|
{% if ansible_distribution_major_version is version('9', '>') %}
|
||||||
# Set LXC container unconfined in AppArmor
|
# Set LXC container unconfined in AppArmor
|
||||||
lxc.apparmor.profile = unconfined
|
lxc.apparmor.profile = unconfined
|
||||||
|
{% else %}
|
||||||
|
lxc.aa_profile = unconfined
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,24 +1,35 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
minifirewall_main_file: /etc/default/minifirewall
|
# possible values: Null (default), modern or legacy
|
||||||
minifirewall_tail_file: /etc/default/minifirewall.tail
|
minifirewall_install_mode: Null
|
||||||
|
|
||||||
|
# BEGIN legacy variables
|
||||||
|
minifirewall_legacy_main_file: /etc/default/minifirewall
|
||||||
|
minifirewall_legacy_tail_file: /etc/default/minifirewall.tail
|
||||||
|
# END legacy variabes
|
||||||
|
|
||||||
|
minifirewall_tail_file: /etc/minifirewall.d/zzz-tail
|
||||||
minifirewall_tail_included: False
|
minifirewall_tail_included: False
|
||||||
minifirewall_tail_force: True
|
minifirewall_tail_force: True
|
||||||
|
|
||||||
|
# Overwrite files completely
|
||||||
minifirewall_force_upgrade_script: False
|
minifirewall_force_upgrade_script: False
|
||||||
minifirewall_force_upgrade_config: False
|
minifirewall_force_upgrade_config: False
|
||||||
|
|
||||||
minifirewall_git_url: "https://forge.evolix.org/minifirewall.git"
|
# Update specific values in configuration
|
||||||
minifirewall_checkout_path: "/tmp/minifirewall"
|
minifirewall_update_config: True
|
||||||
|
|
||||||
minifirewall_int: "{{ ansible_default_ipv4.interface }}"
|
minifirewall_int: "{{ ansible_default_ipv4.interface }}"
|
||||||
minifirewall_ipv6: "on"
|
minifirewall_ipv6: "on"
|
||||||
minifirewall_intlan: "{{ ansible_default_ipv4.address }}/32"
|
minifirewall_intlan: "{{ ansible_default_ipv4.address }}/32"
|
||||||
minifirewall_docker: "off"
|
minifirewall_docker: "off"
|
||||||
|
|
||||||
minifirewall_default_trusted_ips: []
|
minifirewall_default_trusted_ips: []
|
||||||
|
minifirewall_legacy_fallback_trusted_ips: ['0.0.0.0/0']
|
||||||
|
minifirewall_fallback_trusted_ips: ['0.0.0.0/0', '::/0']
|
||||||
minifirewall_additional_trusted_ips: []
|
minifirewall_additional_trusted_ips: []
|
||||||
# and default to ['0.0.0.0/0'] if the result is still empty
|
# and default to ['0.0.0.0/0', '::/0'] if the result is still empty
|
||||||
minifirewall_trusted_ips: "{{ minifirewall_default_trusted_ips | union(minifirewall_additional_trusted_ips) | unique | default(['0.0.0.0/0'], true) }}"
|
minifirewall_trusted_ips: "{{ minifirewall_default_trusted_ips | union(minifirewall_additional_trusted_ips) | unique }}"
|
||||||
minifirewall_privilegied_ips: []
|
minifirewall_privilegied_ips: []
|
||||||
|
|
||||||
minifirewall_protected_ports_tcp: [22]
|
minifirewall_protected_ports_tcp: [22]
|
||||||
|
@ -31,7 +42,7 @@ minifirewall_private_ports_tcp: [5666]
|
||||||
minifirewall_private_ports_udp: []
|
minifirewall_private_ports_udp: []
|
||||||
|
|
||||||
# Keep a null value to leave the setting as is
|
# Keep a null value to leave the setting as is
|
||||||
# otherwise use an Array, eg. "minifirewall_ssh_ok: ['0.0.0.0/0']"
|
# otherwise use an Array, eg. "minifirewall_ssh_ok: ['0.0.0.0/0', '::/0']"
|
||||||
minifirewall_dns_servers: Null
|
minifirewall_dns_servers: Null
|
||||||
minifirewall_http_sites: Null
|
minifirewall_http_sites: Null
|
||||||
minifirewall_https_sites: Null
|
minifirewall_https_sites: Null
|
||||||
|
@ -41,6 +52,22 @@ minifirewall_smtp_ok: Null
|
||||||
minifirewall_smtp_secure_ok: Null
|
minifirewall_smtp_secure_ok: Null
|
||||||
minifirewall_ntp_ok: Null
|
minifirewall_ntp_ok: Null
|
||||||
|
|
||||||
|
minifirewall_proxy: "off"
|
||||||
|
minifirewall_proxyport: 8888
|
||||||
|
minifirewall_proxybypass:
|
||||||
|
- "${INTLAN}"
|
||||||
|
- "127.0.0.0/8"
|
||||||
|
- "::1/128"
|
||||||
|
minifirewall_backupservers: Null
|
||||||
|
|
||||||
|
minifirewall_sysctl_icmp_echo_ignore_broadcasts : Null
|
||||||
|
minifirewall_sysctl_icmp_ignore_bogus_error_responses : Null
|
||||||
|
minifirewall_sysctl_accept_source_route : Null
|
||||||
|
minifirewall_sysctl_tcp_syncookies : Null
|
||||||
|
minifirewall_sysctl_icmp_redirects : Null
|
||||||
|
minifirewall_sysctl_rp_filter : Null
|
||||||
|
minifirewall_sysctl_log_martians : Null
|
||||||
|
|
||||||
minifirewall_autostart: False
|
minifirewall_autostart: False
|
||||||
minifirewall_restart_if_needed: True
|
minifirewall_restart_if_needed: True
|
||||||
minifirewall_restart_force: False
|
minifirewall_restart_force: False
|
||||||
|
|
23
minifirewall/files/blacklist-countries.sh
Normal file
23
minifirewall/files/blacklist-countries.sh
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ripedeny_file=/var/tmp/ripe_deny
|
||||||
|
|
||||||
|
cd /var/tmp
|
||||||
|
|
||||||
|
rm -f $ripedeny_file
|
||||||
|
|
||||||
|
GET http://antispam00.evolix.org/spam/ripe.cidr.md5 > ripe.cidr.md5
|
||||||
|
GET http://antispam00.evolix.org/spam/ripe.cidr > ripe.cidr
|
||||||
|
|
||||||
|
for i in CN KR RU; do
|
||||||
|
|
||||||
|
grep "^$i|" ripe.cidr >> $ripedeny_file
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
/sbin/iptables -F NEEDRESTRICT
|
||||||
|
|
||||||
|
for i in $(cat $ripedeny_file); do
|
||||||
|
BLOCK=$(echo $i | cut -d"|" -f2)
|
||||||
|
/sbin/iptables -I NEEDRESTRICT -s $BLOCK -j DROP
|
||||||
|
done
|
1099
minifirewall/files/minifirewall
Executable file
1099
minifirewall/files/minifirewall
Executable file
|
@ -0,0 +1,1099 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
|
||||||
|
# minifirewall is a shell script for easy firewalling on a standalone server
|
||||||
|
# It uses netfilter/iptables http://netfilter.org/ designed for recent Linux kernel
|
||||||
|
# See https://gitea.evolix.org/evolix/minifirewall
|
||||||
|
|
||||||
|
# Copyright (c) 2007-2022 Evolix
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 3
|
||||||
|
# of the License.
|
||||||
|
|
||||||
|
# Description
|
||||||
|
# script for standalone server
|
||||||
|
|
||||||
|
# Start or stop minifirewall
|
||||||
|
#
|
||||||
|
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: minifirewall
|
||||||
|
# Required-Start:
|
||||||
|
# Required-Stop:
|
||||||
|
# Should-Start: $network $syslog $named
|
||||||
|
# Should-Stop: $syslog
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: start and stop the firewall
|
||||||
|
# Description: Firewall designed for standalone server
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
VERSION="22.05"
|
||||||
|
|
||||||
|
NAME="minifirewall"
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
DESC="Firewall designed for standalone server"
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
# Variables configuration
|
||||||
|
#########################
|
||||||
|
|
||||||
|
config_file="/etc/default/minifirewall"
|
||||||
|
includes_dir="/etc/minifirewall.d"
|
||||||
|
|
||||||
|
# iptables paths
|
||||||
|
IPT=$(command -v iptables)
|
||||||
|
if [ -z "${IPT}" ]; then
|
||||||
|
echo "Unable to find 'iptables\` command in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
IPT6=$(command -v ip6tables)
|
||||||
|
if [ -z "${IPT6}" ]; then
|
||||||
|
echo "Unable to find 'ip6tables\` command in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TCP/IP variables
|
||||||
|
LOOPBACK='127.0.0.0/8'
|
||||||
|
CLASSA='10.0.0.0/8'
|
||||||
|
CLASSB='172.16.0.0/12'
|
||||||
|
CLASSC='192.168.0.0/16'
|
||||||
|
CLASSD='224.0.0.0/4'
|
||||||
|
CLASSE='240.0.0.0/5'
|
||||||
|
ALL='0.0.0.0'
|
||||||
|
BROAD='255.255.255.255'
|
||||||
|
PORTSROOT='0:1023'
|
||||||
|
PORTSUSER='1024:65535'
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
INT=''
|
||||||
|
IPV6=''
|
||||||
|
DOCKER=''
|
||||||
|
INTLAN=''
|
||||||
|
TRUSTEDIPS=''
|
||||||
|
PRIVILEGIEDIPS=''
|
||||||
|
SERVICESTCP1p=''
|
||||||
|
SERVICESUDP1p=''
|
||||||
|
SERVICESTCP1=''
|
||||||
|
SERVICESUDP1=''
|
||||||
|
SERVICESTCP2=''
|
||||||
|
SERVICESUDP2=''
|
||||||
|
SERVICESTCP3=''
|
||||||
|
SERVICESUDP3=''
|
||||||
|
DNSSERVEURS=''
|
||||||
|
HTTPSITES=''
|
||||||
|
HTTPSSITES=''
|
||||||
|
FTPSITES=''
|
||||||
|
SSHOK=''
|
||||||
|
SMTPOK=''
|
||||||
|
SMTPSECUREOK=''
|
||||||
|
NTPOK=''
|
||||||
|
PROXY=''
|
||||||
|
PROXYBYPASS=''
|
||||||
|
PROXYPORT=''
|
||||||
|
BACKUPSERVERS=''
|
||||||
|
|
||||||
|
LEGACY_CONFIG='off'
|
||||||
|
|
||||||
|
STATE_FILE_LATEST='/var/run/minifirewall_state_latest'
|
||||||
|
STATE_FILE_CURRENT='/var/run/minifirewall_state_current'
|
||||||
|
STATE_FILE_PREVIOUS='/var/run/minifirewall_state_previous'
|
||||||
|
STATE_FILE_DIFF='/var/run/minifirewall_state_diff'
|
||||||
|
|
||||||
|
LOGGER_BIN=$(command -v logger)
|
||||||
|
|
||||||
|
# No colors by default
|
||||||
|
RED=''
|
||||||
|
GREEN=''
|
||||||
|
YELLOW=''
|
||||||
|
BLUE=''
|
||||||
|
MAGENTA=''
|
||||||
|
CYAN=''
|
||||||
|
WHITE=''
|
||||||
|
BOLD=''
|
||||||
|
RESET=''
|
||||||
|
# check if stdout is a terminal...
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
|
||||||
|
# see if it supports colors...
|
||||||
|
ncolors=$(tput colors)
|
||||||
|
|
||||||
|
if [ -n "${ncolors}" ] && [ ${ncolors} -ge 8 ]; then
|
||||||
|
RED=$(tput setaf 1)
|
||||||
|
GREEN=$(tput setaf 2)
|
||||||
|
YELLOW=$(tput setaf 3)
|
||||||
|
BLUE=$(tput setaf 4)
|
||||||
|
MAGENTA=$(tput setaf 5)
|
||||||
|
CYAN=$(tput setaf 6)
|
||||||
|
WHITE=$(tput setaf 7)
|
||||||
|
BOLD=$(tput bold)
|
||||||
|
RESET='\e[m'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
## pseudo dry-run :
|
||||||
|
## Uncomment and call these functions instead of the real iptables and ip6tables commands
|
||||||
|
# IPT="fake_iptables"
|
||||||
|
# IPT6="fake_ip6tables"
|
||||||
|
# fake_iptables() {
|
||||||
|
# printf "DRY-RUN iptables %s\n" "$*"
|
||||||
|
# }
|
||||||
|
# fake_ip6tables() {
|
||||||
|
# printf "DRY-RUN ip6tables %s\n" "$*"
|
||||||
|
# }
|
||||||
|
## Beware that commands executed from included files are not modified by this trick.
|
||||||
|
|
||||||
|
syslog_info() {
|
||||||
|
if [ -x "${LOGGER_BIN}" ]; then
|
||||||
|
${LOGGER_BIN} -t "${NAME}" -p daemon.info "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
syslog_error() {
|
||||||
|
if [ -x "${LOGGER_BIN}" ]; then
|
||||||
|
${LOGGER_BIN} -t "${NAME}" -p daemon.error "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
sort_values() {
|
||||||
|
echo "$*" | tr ' ' '\n' | sort -h
|
||||||
|
}
|
||||||
|
is_ipv6_enabled() {
|
||||||
|
test "${IPV6}" != "off"
|
||||||
|
}
|
||||||
|
is_docker_enabled() {
|
||||||
|
test "${DOCKER}" = "on"
|
||||||
|
}
|
||||||
|
is_proxy_enabled() {
|
||||||
|
test "${PROXY}" = "on"
|
||||||
|
}
|
||||||
|
is_ipv6() {
|
||||||
|
echo "$1" | grep -q ':'
|
||||||
|
}
|
||||||
|
is_legacy_config() {
|
||||||
|
test "${LEGACY_CONFIG}" != "off"
|
||||||
|
}
|
||||||
|
chain_exists() {
|
||||||
|
chain_name="$1"
|
||||||
|
if [ $# -ge 2 ]; then
|
||||||
|
intable="--table $2"
|
||||||
|
else
|
||||||
|
intable=""
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
iptables ${intable} -nL "${chain_name}" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
source_file_or_error() {
|
||||||
|
file=$1
|
||||||
|
syslog_info "sourcing \`${file}'"
|
||||||
|
printf "${BLUE}sourcing \`%s'${RESET}\n" "${file}"
|
||||||
|
|
||||||
|
tmpfile=$(mktemp --tmpdir=/tmp minifirewall.XXX)
|
||||||
|
. "${file}" 2>"${tmpfile}" >&2
|
||||||
|
|
||||||
|
if [ -s "${tmpfile}" ]; then
|
||||||
|
syslog_error "Error while sourcing ${file}"
|
||||||
|
printf "${RED}%s returns standard or error output (see below). Stopping.${RESET}\n" ${file} >&2
|
||||||
|
cat "${tmpfile}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm -f "${tmpfile}"
|
||||||
|
}
|
||||||
|
source_configuration() {
|
||||||
|
if ! test -f ${config_file}; then
|
||||||
|
printf "${RED}%s does not exist${RESET}\n" "${config_file}" >&2
|
||||||
|
|
||||||
|
## We still want to deal with this really old configuration file
|
||||||
|
## even if it has been deprecated since Debian 8
|
||||||
|
old_config_file="/etc/firewall.rc"
|
||||||
|
if test -f ${old_config_file}; then
|
||||||
|
printf "${YELLOW}%s is deprecated and ignored. Rename it to %s${RESET}\n" "${old_config_file}" "${config_file}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we find something other than a blank line, a comment or a variable assignment
|
||||||
|
if grep --quiet --extended-regexp --invert-match "^\s*(#|$|\w+=)" "${config_file}"; then
|
||||||
|
# Backward compatible mode
|
||||||
|
###########################
|
||||||
|
|
||||||
|
printf "${YELLOW}legacy config detected${RESET}\n"
|
||||||
|
LEGACY_CONFIG='on'
|
||||||
|
|
||||||
|
# Non-backward compatible mode
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# If we ever want to remove the backward compatible mode
|
||||||
|
# we can remove the two lines above and uncomment the lines below.
|
||||||
|
# They break if any iptables/ip6tables command is found in the configuration file
|
||||||
|
|
||||||
|
# echo "iptables/ip6tables commands found in ${config_file}." >&2
|
||||||
|
# echo "Move them in included files (in ${includes_dir})." >&2
|
||||||
|
# exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_legacy_config; then
|
||||||
|
# In this mode, we extract all variable definitions
|
||||||
|
# to a temporary file that we can source.
|
||||||
|
# It allow iptables/ip6tables commands to remain in the configuration file
|
||||||
|
# and not interfere with the configuration step.
|
||||||
|
|
||||||
|
tmp_config_file=$(mktemp --tmpdir=/tmp minifirewall.XXX)
|
||||||
|
# get only variable assignments
|
||||||
|
grep -E "^\s*\w+=" "${config_file}" > "${tmp_config_file}"
|
||||||
|
|
||||||
|
source_file_or_error "${tmp_config_file}"
|
||||||
|
rm -f "${tmp_config_file}"
|
||||||
|
else
|
||||||
|
source_file_or_error "${config_file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
source_includes() {
|
||||||
|
if [ -d "${includes_dir}" ]; then
|
||||||
|
include_files=$(find ${includes_dir} -type f -readable -not -name '*.*' | sort -h)
|
||||||
|
for include_file in ${include_files}; do
|
||||||
|
source_file_or_error "${include_file}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
check_unpersisted_state() {
|
||||||
|
cmp_bin=$(command -v cmp)
|
||||||
|
diff_bin=$(command -v diff)
|
||||||
|
|
||||||
|
if [ -z "${cmp_bin}" ]; then
|
||||||
|
printf "${YELLOW}skip state comparison (Can't find cmp command)${RESET}\n" >&2
|
||||||
|
elif [ -z "${diff_bin}" ]; then
|
||||||
|
printf "${YELLOW}skip state comparison (Can't find diff command)${RESET}\n" >&2
|
||||||
|
else
|
||||||
|
# store current state
|
||||||
|
mkdir -p "$(dirname "${STATE_FILE_CURRENT}")"
|
||||||
|
status_without_numbers > "${STATE_FILE_CURRENT}"
|
||||||
|
|
||||||
|
# clean previous diff file
|
||||||
|
rm -f "${STATE_FILE_DIFF}"
|
||||||
|
|
||||||
|
if [ -f "${STATE_FILE_LATEST}" ]; then
|
||||||
|
cmp_result=$(cmp "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}")
|
||||||
|
cmp_rc=$?
|
||||||
|
|
||||||
|
if [ ${cmp_rc} -eq 0 ]; then
|
||||||
|
# echo " rules have not changed since latest start"
|
||||||
|
:
|
||||||
|
elif [ ${cmp_rc} -eq 1 ]; then
|
||||||
|
diff -u "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}" > "${STATE_FILE_DIFF}"
|
||||||
|
printf "${YELLOW}WARNING: current state is different than persisted state, check %s${RESET}\n" "${STATE_FILE_DIFF}" >&2
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR comparing rules:${RESET}\n" >&2
|
||||||
|
echo "${cmp_result}" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# cleanup
|
||||||
|
rm -f "${STATE_FILE_CURRENT}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
report_state_changes() {
|
||||||
|
cmp_bin=$(command -v cmp)
|
||||||
|
diff_bin=$(command -v diff)
|
||||||
|
|
||||||
|
if [ -z "${cmp_bin}" ]; then
|
||||||
|
printf "${YELLOW}skip state comparison (Can't find cmp command)${RESET}\n" >&2
|
||||||
|
return
|
||||||
|
elif [ -z "${diff_bin}" ]; then
|
||||||
|
printf "${YELLOW}skip state comparison (Can't find diff command)${RESET}\n" >&2
|
||||||
|
else
|
||||||
|
# If there is a known state
|
||||||
|
# let's compare it with the current state
|
||||||
|
if [ -f "${STATE_FILE_LATEST}" ]; then
|
||||||
|
check_unpersisted_state
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Then reset the known state
|
||||||
|
mkdir -p "$(dirname "${STATE_FILE_LATEST}")"
|
||||||
|
status_without_numbers > "${STATE_FILE_LATEST}"
|
||||||
|
|
||||||
|
# But if there is a previous known state
|
||||||
|
# let's compare with the new known state
|
||||||
|
if [ -f "${STATE_FILE_PREVIOUS}" ]; then
|
||||||
|
cmp_result=$(cmp "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}")
|
||||||
|
cmp_rc=$?
|
||||||
|
|
||||||
|
if [ ${cmp_rc} -eq 0 ]; then
|
||||||
|
# echo "Rules have not changed since previous start"
|
||||||
|
:
|
||||||
|
elif [ ${cmp_rc} -eq 1 ]; then
|
||||||
|
diff -u "${STATE_FILE_PREVIOUS}" "${STATE_FILE_LATEST}" > "${STATE_FILE_DIFF}"
|
||||||
|
printf "${YELLOW}INFO: rules have changed since latest start, check %s${RESET}\n" "${STATE_FILE_DIFF}" >&2
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR comparing rules:${RESET}\n" >&2
|
||||||
|
echo "${cmp_result}" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
syslog_info "starting"
|
||||||
|
printf "${BOLD}${NAME} starting${RESET}\n"
|
||||||
|
|
||||||
|
# Stop and warn if error!
|
||||||
|
set -e
|
||||||
|
trap 'printf "${RED}${NAME} failed : an error occured during startup.${RESET}\n"; syslog_error "failed" ' INT TERM EXIT
|
||||||
|
|
||||||
|
# sysctl network security settings
|
||||||
|
##################################
|
||||||
|
|
||||||
|
# Set 1 to ignore broadcast pings (default)
|
||||||
|
: "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS:=1}"
|
||||||
|
# Set 1 to ignore bogus ICMP responses (default)
|
||||||
|
: "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES:=1}"
|
||||||
|
# Set 0 to disable source routing (default)
|
||||||
|
: "${SYSCTL_ACCEPT_SOURCE_ROUTE:=0}"
|
||||||
|
# Set 1 to enable TCP SYN cookies (default)
|
||||||
|
# cf http://cr.yp.to/syncookies.html
|
||||||
|
: "${SYSCTL_TCP_SYNCOOKIES:=1}"
|
||||||
|
# Set 0 to disable ICMP redirects (default)
|
||||||
|
: "${SYSCTL_ICMP_REDIRECTS:=0}"
|
||||||
|
# Set 1 to enable Reverse Path filtering (default)
|
||||||
|
# Set 0 if VRRP is used
|
||||||
|
: "${SYSCTL_RP_FILTER:=1}"
|
||||||
|
# Set 1 to log packets with inconsistent address (default)
|
||||||
|
: "${SYSCTL_LOG_MARTIANS:=1}"
|
||||||
|
|
||||||
|
if [ "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" = "1" ] || [ "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" = "0" ]; then
|
||||||
|
echo "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS" "${SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" = "1" ] || [ "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" = "0" ]; then
|
||||||
|
echo "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES" "${SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_ACCEPT_SOURCE_ROUTE}" = "1" ] || [ "${SYSCTL_ACCEPT_SOURCE_ROUTE}" = "0" ]; then
|
||||||
|
for proc_sys_file in /proc/sys/net/ipv4/conf/*/accept_source_route; do
|
||||||
|
echo "${SYSCTL_ACCEPT_SOURCE_ROUTE}" > "${proc_sys_file}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ACCEPT_SOURCE_ROUTE" "${SYSCTL_ACCEPT_SOURCE_ROUTE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_TCP_SYNCOOKIES}" = "1" ] || [ "${SYSCTL_TCP_SYNCOOKIES}" = "0" ]; then
|
||||||
|
echo "${SYSCTL_TCP_SYNCOOKIES}" > /proc/sys/net/ipv4/tcp_syncookies
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_TCP_SYNCOOKIES" "${SYSCTL_TCP_SYNCOOKIES}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_ICMP_REDIRECTS}" = "1" ] || [ "${SYSCTL_ICMP_REDIRECTS}" = "0" ]; then
|
||||||
|
for proc_sys_file in /proc/sys/net/ipv4/conf/*/accept_redirects; do
|
||||||
|
echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}"
|
||||||
|
done
|
||||||
|
for proc_sys_file in /proc/sys/net/ipv4/conf/*/send_redirects; do
|
||||||
|
echo "${SYSCTL_ICMP_REDIRECTS}" > "${proc_sys_file}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_ICMP_REDIRECTS" "${SYSCTL_ICMP_REDIRECTS}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_RP_FILTER}" = "1" ] || [ "${SYSCTL_RP_FILTER}" = "0" ]; then
|
||||||
|
for proc_sys_file in /proc/sys/net/ipv4/conf/*/rp_filter; do
|
||||||
|
echo "${SYSCTL_RP_FILTER}" > "${proc_sys_file}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_RP_FILTER" "${SYSCTL_RP_FILTER}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${SYSCTL_LOG_MARTIANS}" = "1" ] || [ "${SYSCTL_LOG_MARTIANS}" = "0" ]; then
|
||||||
|
for proc_sys_file in /proc/sys/net/ipv4/conf/*/log_martians; do
|
||||||
|
echo "${SYSCTL_LOG_MARTIANS}" > "${proc_sys_file}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: invalid %s value '%s', must be '0' or '1'.\n" "SYSCTL_LOG_MARTIANS" "${SYSCTL_LOG_MARTIANS}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# IPTables configuration
|
||||||
|
########################
|
||||||
|
|
||||||
|
${IPT} -N LOG_DROP
|
||||||
|
${IPT} -A LOG_DROP -j LOG --log-prefix '[IPTABLES DROP] : '
|
||||||
|
${IPT} -A LOG_DROP -j DROP
|
||||||
|
${IPT} -N LOG_ACCEPT
|
||||||
|
${IPT} -A LOG_ACCEPT -j LOG --log-prefix '[IPTABLES ACCEPT] : '
|
||||||
|
${IPT} -A LOG_ACCEPT -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -N LOG_DROP
|
||||||
|
${IPT6} -A LOG_DROP -j LOG --log-prefix '[IPTABLES DROP] : '
|
||||||
|
${IPT6} -A LOG_DROP -j DROP
|
||||||
|
${IPT6} -N LOG_ACCEPT
|
||||||
|
${IPT6} -A LOG_ACCEPT -j LOG --log-prefix '[IPTABLES ACCEPT] : '
|
||||||
|
${IPT6} -A LOG_ACCEPT -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Source additional rules and commands
|
||||||
|
# * from legacy configuration file (/etc/default/minifirewall)
|
||||||
|
# * from configuration directory (/etc/minifirewall.d/*)
|
||||||
|
source_includes
|
||||||
|
|
||||||
|
# IP/ports lists are sorted to have consistent ordering
|
||||||
|
# You can disable this feature by simply commenting the following lines
|
||||||
|
LOOPBACK=$(sort_values ${LOOPBACK})
|
||||||
|
INTLAN=$(sort_values ${INTLAN})
|
||||||
|
TRUSTEDIPS=$(sort_values ${TRUSTEDIPS})
|
||||||
|
PRIVILEGIEDIPS=$(sort_values ${PRIVILEGIEDIPS})
|
||||||
|
SERVICESTCP1p=$(sort_values ${SERVICESTCP1p})
|
||||||
|
SERVICESUDP1p=$(sort_values ${SERVICESUDP1p})
|
||||||
|
SERVICESTCP1=$(sort_values ${SERVICESTCP1})
|
||||||
|
SERVICESUDP1=$(sort_values ${SERVICESUDP1})
|
||||||
|
SERVICESTCP2=$(sort_values ${SERVICESTCP2})
|
||||||
|
SERVICESUDP2=$(sort_values ${SERVICESUDP2})
|
||||||
|
SERVICESTCP3=$(sort_values ${SERVICESTCP3})
|
||||||
|
SERVICESUDP3=$(sort_values ${SERVICESUDP3})
|
||||||
|
DNSSERVEURS=$(sort_values ${DNSSERVEURS})
|
||||||
|
HTTPSITES=$(sort_values ${HTTPSITES})
|
||||||
|
HTTPSSITES=$(sort_values ${HTTPSSITES})
|
||||||
|
FTPSITES=$(sort_values ${FTPSITES})
|
||||||
|
SSHOK=$(sort_values ${SSHOK})
|
||||||
|
SMTPOK=$(sort_values ${SMTPOK})
|
||||||
|
SMTPSECUREOK=$(sort_values ${SMTPSECUREOK})
|
||||||
|
NTPOK=$(sort_values ${NTPOK})
|
||||||
|
PROXYBYPASS=$(sort_values ${PROXYBYPASS})
|
||||||
|
BACKUPSERVERS=$(sort_values ${BACKUPSERVERS})
|
||||||
|
|
||||||
|
# Trusted ip addresses
|
||||||
|
${IPT} -N ONLYTRUSTED
|
||||||
|
${IPT} -A ONLYTRUSTED -j LOG_DROP
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -N ONLYTRUSTED
|
||||||
|
${IPT6} -A ONLYTRUSTED -j LOG_DROP
|
||||||
|
fi
|
||||||
|
for ip in ${TRUSTEDIPS}; do
|
||||||
|
if is_ipv6 ${ip}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -I ONLYTRUSTED -s ${ip} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -I ONLYTRUSTED -s ${ip} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Privilegied ip addresses
|
||||||
|
# (trusted ip addresses *are* privilegied)
|
||||||
|
${IPT} -N ONLYPRIVILEGIED
|
||||||
|
${IPT} -A ONLYPRIVILEGIED -j ONLYTRUSTED
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -N ONLYPRIVILEGIED
|
||||||
|
${IPT6} -A ONLYPRIVILEGIED -j ONLYTRUSTED
|
||||||
|
fi
|
||||||
|
for ip in ${PRIVILEGIEDIPS}; do
|
||||||
|
if is_ipv6 ${ip}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -I ONLYPRIVILEGIED -s ${ip} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -I ONLYPRIVILEGIED -s ${ip} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Chain for restrictions (blacklist IPs/ranges)
|
||||||
|
${IPT} -N NEEDRESTRICT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -N NEEDRESTRICT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We allow all on loopback interface
|
||||||
|
${IPT} -A INPUT -i lo -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -i lo -j ACCEPT
|
||||||
|
fi
|
||||||
|
# if OUTPUTDROP
|
||||||
|
${IPT} -A OUTPUT -o lo -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A OUTPUT -o lo -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We avoid "martians" packets, typical when W32/Blaster virus
|
||||||
|
# attacked windowsupdate.com and DNS was changed to 127.0.0.1
|
||||||
|
# ${IPT} -t NAT -I PREROUTING -s ${LOOPBACK} -i ! lo -j DROP
|
||||||
|
for IP in ${LOOPBACK}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -s ${IP} ! -i lo -j DROP
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -s ${IP} ! -i lo -j DROP
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if is_docker_enabled; then
|
||||||
|
# WARN: IPv6 not yet supported for Docker rules
|
||||||
|
${IPT} -N MINIFW-DOCKER-TRUSTED
|
||||||
|
${IPT} -A MINIFW-DOCKER-TRUSTED -j DROP
|
||||||
|
|
||||||
|
${IPT} -N MINIFW-DOCKER-PRIVILEGED
|
||||||
|
${IPT} -A MINIFW-DOCKER-PRIVILEGED -j MINIFW-DOCKER-TRUSTED
|
||||||
|
${IPT} -A MINIFW-DOCKER-PRIVILEGED -j RETURN
|
||||||
|
|
||||||
|
${IPT} -N MINIFW-DOCKER-PUB
|
||||||
|
${IPT} -A MINIFW-DOCKER-PUB -j MINIFW-DOCKER-PRIVILEGED
|
||||||
|
${IPT} -A MINIFW-DOCKER-PUB -j RETURN
|
||||||
|
|
||||||
|
# Flush DOCKER-USER if exist, create it if absent
|
||||||
|
if chain_exists 'DOCKER-USER'; then
|
||||||
|
${IPT} -F DOCKER-USER
|
||||||
|
else
|
||||||
|
${IPT} -N DOCKER-USER
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Pipe new connection through MINIFW-DOCKER-PUB
|
||||||
|
${IPT} -A DOCKER-USER -i ${INT} -m state --state NEW -j MINIFW-DOCKER-PUB
|
||||||
|
${IPT} -A DOCKER-USER -j RETURN
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Local services restrictions
|
||||||
|
#############################
|
||||||
|
|
||||||
|
# Allow services for ${INTLAN} (local server or local network)
|
||||||
|
for IP in ${INTLAN}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Enable protection chain for sensible services
|
||||||
|
for port in ${SERVICESTCP1p}; do
|
||||||
|
${IPT} -A INPUT -p tcp --dport ${port} -j NEEDRESTRICT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp --dport ${port} -j NEEDRESTRICT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for port in ${SERVICESUDP1p}; do
|
||||||
|
${IPT} -A INPUT -p udp --dport ${port} -j NEEDRESTRICT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p udp --dport ${port} -j NEEDRESTRICT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Public service
|
||||||
|
for port in ${SERVICESTCP1}; do
|
||||||
|
${IPT} -A INPUT -p tcp --dport ${port} -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp --dport ${port} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for port in ${SERVICESUDP1}; do
|
||||||
|
${IPT} -A INPUT -p udp --dport ${port} -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p udp --dport ${port} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Privilegied services
|
||||||
|
for port in ${SERVICESTCP2}; do
|
||||||
|
${IPT} -A INPUT -p tcp --dport ${port} -j ONLYPRIVILEGIED
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp --dport ${port} -j ONLYPRIVILEGIED
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for port in ${SERVICESUDP2}; do
|
||||||
|
${IPT} -A INPUT -p udp --dport ${port} -j ONLYPRIVILEGIED
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p udp --dport ${port} -j ONLYPRIVILEGIED
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Private services
|
||||||
|
for port in ${SERVICESTCP3}; do
|
||||||
|
${IPT} -A INPUT -p tcp --dport ${port} -j ONLYTRUSTED
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp --dport ${port} -j ONLYTRUSTED
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for port in ${SERVICESUDP3}; do
|
||||||
|
${IPT} -A INPUT -p udp --dport ${port} -j ONLYTRUSTED
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p udp --dport ${port} -j ONLYTRUSTED
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
if is_docker_enabled; then
|
||||||
|
# WARN: IPv6 not yet supported
|
||||||
|
|
||||||
|
# Public services defined in SERVICESTCP1 & SERVICESUDP1
|
||||||
|
for dstport in ${SERVICESTCP1}; do
|
||||||
|
${IPT} -I MINIFW-DOCKER-PUB -p tcp --dport "${dstport}" -j RETURN
|
||||||
|
done
|
||||||
|
|
||||||
|
for dstport in ${SERVICESUDP1}; do
|
||||||
|
${IPT} -I MINIFW-DOCKER-PUB -p udp --dport "${dstport}" -j RETURN
|
||||||
|
done
|
||||||
|
|
||||||
|
# Privileged services (accessible from privileged & trusted IPs)
|
||||||
|
for dstport in ${SERVICESTCP2}; do
|
||||||
|
for srcip in ${PRIVILEGIEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for srcip in ${TRUSTEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
for dstport in ${SERVICESUDP2}; do
|
||||||
|
for srcip in ${PRIVILEGIEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-PRIVILEGED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for srcip in ${TRUSTEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-PRIVILEGED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Trusted services (accessible from trusted IPs)
|
||||||
|
for dstport in ${SERVICESTCP3}; do
|
||||||
|
for srcip in ${TRUSTEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-TRUSTED -p tcp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
for dstport in ${SERVICESUDP3}; do
|
||||||
|
for srcip in ${TRUSTEDIPS}; do
|
||||||
|
if ! is_ipv6 ${srcip}; then
|
||||||
|
${IPT} -I MINIFW-DOCKER-TRUSTED -p udp -s "${srcip}" --dport "${dstport}" -j RETURN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# External services
|
||||||
|
###################
|
||||||
|
|
||||||
|
# DNS authorizations
|
||||||
|
for IP in ${DNSSERVEURS}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
${IPT6} -A INPUT -p udp --sport 53 --dport ${PORTSUSER} -s ${IP} -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
${IPT6} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 53 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
${IPT} -A INPUT -p udp --sport 53 --dport ${PORTSUSER} -s ${IP} -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 53 --match state --state NEW -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# HTTP (TCP/80) authorizations
|
||||||
|
for IP in ${HTTPSITES}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 80 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 80 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# HTTPS (TCP/443) authorizations
|
||||||
|
for IP in ${HTTPSSITES}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 443 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 443 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# FTP (so complex protocol...) authorizations
|
||||||
|
for IP in ${FTPSITES}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
# requests on Control connection
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 21 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
# FTP port-mode on Data Connection
|
||||||
|
${IPT6} -A INPUT -p tcp --sport 20 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
# FTP passive-mode on Data Connection
|
||||||
|
# WARNING, this allow all connections on TCP ports > 1024
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport ${PORTSUSER} --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# requests on Control connection
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 21 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
# FTP port-mode on Data Connection
|
||||||
|
${IPT} -A INPUT -p tcp --sport 20 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
# FTP passive-mode on Data Connection
|
||||||
|
# WARNING, this allow all connections on TCP ports > 1024
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport ${PORTSUSER} --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# SSH authorizations
|
||||||
|
for IP in ${SSHOK}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 22 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 22 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# SMTP authorizations
|
||||||
|
for IP in ${SMTPOK}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 25 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 25 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# secure SMTP (TCP/465 et TCP/587) authorizations
|
||||||
|
for IP in ${SMTPSECUREOK}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 465 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
${IPT6} -A INPUT -p tcp ! --syn --sport 587 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 465 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
${IPT} -A INPUT -p tcp ! --syn --sport 587 --dport ${PORTSUSER} -s ${IP} -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# NTP authorizations
|
||||||
|
for IP in ${NTPOK}; do
|
||||||
|
if is_ipv6 ${IP}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p udp --sport 123 -s ${IP} -j ACCEPT
|
||||||
|
${IPT6} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 123 --match state --state NEW -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p udp --sport 123 -s ${IP} -j ACCEPT
|
||||||
|
${IPT} -A OUTPUT -o ${INT} -p udp -d ${IP} --dport 123 --match state --state NEW -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Proxy (Squid)
|
||||||
|
if is_proxy_enabled; then
|
||||||
|
# WARN: Squid only listen on IPv4 yet
|
||||||
|
# TODO: verify that the pattern used for IPv4 is relevant with IPv6
|
||||||
|
|
||||||
|
${IPT} -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT
|
||||||
|
for dstip in ${PROXYBYPASS}; do
|
||||||
|
if ! is_ipv6 ${dstip}; then
|
||||||
|
${IPT} -t nat -A OUTPUT -p tcp --dport 80 -d "${dstip}" -j ACCEPT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
${IPT} -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port "${PROXYPORT:-'8888'}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Output for backup servers
|
||||||
|
for server in ${BACKUPSERVERS}; do
|
||||||
|
server_port=$(echo "${server}" | awk -F : '{print $(NF)}')
|
||||||
|
server_ip=$(echo "${server}" | sed -e "s/:${server_port}$//")
|
||||||
|
|
||||||
|
if [ -n "${server_ip}" ] && [ -n "${server_port}" ]; then
|
||||||
|
if is_ipv6 ${server_ip}; then
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
${IPT} -A INPUT -p tcp --sport "${server_port}" --dport 1024:65535 -s "${server_ip}" -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf "${RED}ERROR: unrecognized syntax for BACKUPSERVERS '%s\`. Use space-separated IP:PORT tuples.${RESET}\n" "${server}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Always allow ICMP
|
||||||
|
${IPT} -A INPUT -p icmp -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A INPUT -p icmpv6 -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# source config file for remaining commands
|
||||||
|
if is_legacy_config; then
|
||||||
|
source_file_or_error "${config_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# IPTables policy
|
||||||
|
#################
|
||||||
|
|
||||||
|
# by default DROP INPUT packets
|
||||||
|
${IPT} -P INPUT DROP
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -P INPUT DROP
|
||||||
|
fi
|
||||||
|
|
||||||
|
# by default, no FORWARDING (deprecated for Virtual Machines)
|
||||||
|
#echo 0 > /proc/sys/net/ipv4/ip_forward
|
||||||
|
#${IPT} -P FORWARD DROP
|
||||||
|
#${IPT6} -P FORWARD DROP
|
||||||
|
|
||||||
|
# by default allow OUTPUT packets... but drop UDP packets (see OUTPUTDROP to drop OUTPUT packets)
|
||||||
|
${IPT} -P OUTPUT ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -P OUTPUT ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A OUTPUT -o ${INT} -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A OUTPUT -p udp --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -A OUTPUT -p udp -j DROP
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -A OUTPUT -p udp -j DROP
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Finish
|
||||||
|
########################
|
||||||
|
|
||||||
|
trap - INT TERM EXIT
|
||||||
|
|
||||||
|
syslog_info "started"
|
||||||
|
printf "${GREEN}${BOLD}${NAME} started${RESET}\n"
|
||||||
|
|
||||||
|
# No need to exit on error anymore
|
||||||
|
set +e
|
||||||
|
|
||||||
|
report_state_changes
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
syslog_info "stopping"
|
||||||
|
printf "${BOLD}${NAME} stopping${RESET}\n"
|
||||||
|
|
||||||
|
printf "${BLUE}flushing all rules and accepting everything${RESET}\n"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "${STATE_FILE_PREVIOUS}")"
|
||||||
|
status_without_numbers > "${STATE_FILE_PREVIOUS}"
|
||||||
|
|
||||||
|
# Delete all rules
|
||||||
|
${IPT} -F INPUT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -F INPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -F OUTPUT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -F OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -F LOG_DROP
|
||||||
|
${IPT} -F LOG_ACCEPT
|
||||||
|
${IPT} -F ONLYTRUSTED
|
||||||
|
${IPT} -F ONLYPRIVILEGIED
|
||||||
|
${IPT} -F NEEDRESTRICT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -F LOG_DROP
|
||||||
|
${IPT6} -F LOG_ACCEPT
|
||||||
|
${IPT6} -F ONLYTRUSTED
|
||||||
|
${IPT6} -F ONLYPRIVILEGIED
|
||||||
|
${IPT6} -F NEEDRESTRICT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -t mangle -F
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -t mangle -F
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_docker_enabled; then
|
||||||
|
# WARN: IPv6 not yet supported
|
||||||
|
|
||||||
|
${IPT} -F DOCKER-USER
|
||||||
|
${IPT} -A DOCKER-USER -j RETURN
|
||||||
|
|
||||||
|
${IPT} -F MINIFW-DOCKER-PUB
|
||||||
|
${IPT} -X MINIFW-DOCKER-PUB
|
||||||
|
${IPT} -F MINIFW-DOCKER-PRIVILEGED
|
||||||
|
${IPT} -X MINIFW-DOCKER-PRIVILEGED
|
||||||
|
${IPT} -F MINIFW-DOCKER-TRUSTED
|
||||||
|
${IPT} -X MINIFW-DOCKER-TRUSTED
|
||||||
|
else
|
||||||
|
${IPT} -t nat -F
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Accept all
|
||||||
|
${IPT} -P INPUT ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -P INPUT ACCEPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -P OUTPUT ACCEPT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -P OUTPUT ACCEPT
|
||||||
|
fi
|
||||||
|
#${IPT} -P FORWARD ACCEPT
|
||||||
|
#${IPT} -t nat -P PREROUTING ACCEPT
|
||||||
|
#${IPT} -t nat -P POSTROUTING ACCEPT
|
||||||
|
|
||||||
|
# Delete non-standard chains
|
||||||
|
${IPT} -X LOG_DROP
|
||||||
|
${IPT} -X LOG_ACCEPT
|
||||||
|
${IPT} -X ONLYPRIVILEGIED
|
||||||
|
${IPT} -X ONLYTRUSTED
|
||||||
|
${IPT} -X NEEDRESTRICT
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -X LOG_DROP
|
||||||
|
${IPT6} -X LOG_ACCEPT
|
||||||
|
${IPT6} -X ONLYPRIVILEGIED
|
||||||
|
${IPT6} -X ONLYTRUSTED
|
||||||
|
${IPT6} -X NEEDRESTRICT
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "${STATE_FILE_LATEST}" "${STATE_FILE_CURRENT}"
|
||||||
|
|
||||||
|
syslog_info "stopped"
|
||||||
|
printf "${GREEN}${BOLD}${NAME} stopped${RESET}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
printf "${BLUE}#### iptables --list ###############################${RESET}\n"
|
||||||
|
${IPT} --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n${BLUE}#### iptables --table nat --list ###################${RESET}\n"
|
||||||
|
${IPT} --table nat --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n${BLUE}#### iptables --table mangle --list ################${RESET}\n"
|
||||||
|
${IPT} --table mangle --list --numeric --verbose --line-numbers
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
printf "\n${BLUE}#### ip6tables --list ##############################${RESET}\n"
|
||||||
|
${IPT6} --list --numeric --verbose --line-numbers
|
||||||
|
printf "\n${BLUE}#### ip6tables --table mangle --list ###############${RESET}\n"
|
||||||
|
${IPT6} --table mangle --list --numeric --verbose --line-numbers
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
status_without_numbers() {
|
||||||
|
printf "${BLUE}#### iptables --list ###############################${RESET}\n"
|
||||||
|
${IPT} --list --numeric
|
||||||
|
printf "\n${BLUE}#### iptables --table nat --list ###################${RESET}\n"
|
||||||
|
${IPT} --table nat --list --numeric
|
||||||
|
printf "\n${BLUE}#### iptables --table mangle --list ################${RESET}\n"
|
||||||
|
${IPT} --table mangle --list --numeric
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
printf "\n${BLUE}#### ip6tables --list ##############################${RESET}\n"
|
||||||
|
${IPT6} --list --numeric
|
||||||
|
printf "\n${BLUE}#### ip6tables --table mangle --list ###############${RESET}\n"
|
||||||
|
${IPT6} --table mangle --list --numeric
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
syslog_info "resetting"
|
||||||
|
printf "${BOLD}${NAME} resetting${RESET}\n"
|
||||||
|
|
||||||
|
${IPT} -Z
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -Z
|
||||||
|
fi
|
||||||
|
|
||||||
|
${IPT} -t nat -Z
|
||||||
|
|
||||||
|
${IPT} -t mangle -Z
|
||||||
|
if is_ipv6_enabled; then
|
||||||
|
${IPT6} -t mangle -Z
|
||||||
|
fi
|
||||||
|
|
||||||
|
syslog_info "reset"
|
||||||
|
printf "${GREEN}${BOLD}${NAME} reset${RESET}\n"
|
||||||
|
}
|
||||||
|
show_version() {
|
||||||
|
cat <<END
|
||||||
|
${NAME} version ${VERSION}
|
||||||
|
|
||||||
|
Copyright 2007-2022 Evolix <info@evolix.fr>.
|
||||||
|
|
||||||
|
${NAME} comes with ABSOLUTELY NO WARRANTY.
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 3
|
||||||
|
of the License.
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-''}" in
|
||||||
|
start)
|
||||||
|
source_configuration
|
||||||
|
check_unpersisted_state
|
||||||
|
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
source_configuration
|
||||||
|
check_unpersisted_state
|
||||||
|
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
source_configuration
|
||||||
|
check_unpersisted_state
|
||||||
|
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
|
||||||
|
reset)
|
||||||
|
source_configuration
|
||||||
|
check_unpersisted_state
|
||||||
|
|
||||||
|
reset
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
source_configuration
|
||||||
|
check_unpersisted_state
|
||||||
|
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
version)
|
||||||
|
show_version
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|status|reset|version}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
|
@ -1,31 +1,37 @@
|
||||||
# Configuration for minifirewall : https://gitea.evolix.org/evolix/minifirewall
|
# Configuration for minifirewall : https://gitea.evolix.org/evolix/minifirewall
|
||||||
# Version 20.12 — 2020-12-01 22:55:35
|
# Version 22.03.1 — 2022-03-15
|
||||||
|
# shellcheck shell=sh disable=SC2034
|
||||||
|
|
||||||
# Main interface
|
# Main interface
|
||||||
INT='eth0'
|
INT='eth0'
|
||||||
|
|
||||||
# IPv6
|
# IPv6
|
||||||
IPV6=on
|
IPV6='on'
|
||||||
|
|
||||||
# Docker Mode
|
# Docker Mode
|
||||||
# Changes the behaviour of minifirewall to not break the containers' network
|
# Changes the behaviour of minifirewall to not break the containers' network
|
||||||
# For instance, turning it on will disable nat table purge
|
# For instance, turning it on will disable nat table purge
|
||||||
# Also, we'll add the DOCKER-USER chain, in iptable
|
# Also, we'll add the DOCKER-USER chain, in iptables
|
||||||
|
#
|
||||||
|
# WARNING : If the port mapping is different between the host and the container
|
||||||
|
# (ie: Listen on :8090 on host, but :8080 in container)
|
||||||
|
# then you need to give the port used inside the container
|
||||||
DOCKER='off'
|
DOCKER='off'
|
||||||
|
|
||||||
# Trusted IPv4 local network
|
# Trusted local network
|
||||||
# ...will be often IP/32 if you don't trust anything
|
# ...will be often IPv4/32 or IPv6/128 if you don't trust anything
|
||||||
INTLAN='192.168.0.2/32'
|
INTLAN='192.0.2.1/32 2001:db8::1/128'
|
||||||
|
|
||||||
# Trusted IPv4 addresses for private and semi-public services
|
# Trusted IP addresses for private and semi-public services
|
||||||
TRUSTEDIPS='31.170.9.129 62.212.121.90 31.170.8.4 82.65.34.85 54.37.106.210 51.210.84.146'
|
# TODO: add all our IPv6 adresses
|
||||||
|
TRUSTEDIPS='31.170.9.129 2a01:9500:37:129::/64 62.212.121.90 31.170.8.4 2a01:9500::fada/128 82.65.34.85 54.37.106.210 51.210.84.146'
|
||||||
|
|
||||||
# Privilegied IPv4 addresses for semi-public services
|
# Privilegied IP addresses for semi-public services
|
||||||
# (no need to add again TRUSTEDIPS)
|
# (no need to add again TRUSTEDIPS)
|
||||||
PRIVILEGIEDIPS=''
|
PRIVILEGIEDIPS=''
|
||||||
|
|
||||||
|
|
||||||
# Local services IPv4/IPv6 restrictions
|
# Local services IP restrictions
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
# Protected services
|
# Protected services
|
||||||
|
@ -45,62 +51,86 @@ SERVICESUDP2=''
|
||||||
SERVICESTCP3='5666'
|
SERVICESTCP3='5666'
|
||||||
SERVICESUDP3=''
|
SERVICESUDP3=''
|
||||||
|
|
||||||
# Standard output IPv4 access restrictions
|
|
||||||
|
# Standard output IPv4/IPv6 access restrictions
|
||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
# DNS authorizations
|
# DNS authorizations
|
||||||
# (if you have local DNS server, set 0.0.0.0/0)
|
# (if you have local DNS server, set 0.0.0.0/0)
|
||||||
DNSSERVEURS='0.0.0.0/0'
|
DNSSERVEURS='0.0.0.0/0 ::/0'
|
||||||
|
|
||||||
# HTTP authorizations
|
# HTTP authorizations
|
||||||
# (you can use DNS names but set cron to reload minifirewall regularly)
|
# (you can use DNS names but set cron to reload minifirewall regularly)
|
||||||
# (if you have HTTP proxy, set 0.0.0.0/0)
|
# (if you have HTTP proxy, set 0.0.0.0/0)
|
||||||
# HTTPSITES='security.debian.org pub.evolix.net security-cdn.debian.org mirror.evolix.org backports.debian.org hwraid.le-vert.net antispam00.evolix.org spamassassin.apache.org sa-update.space-pro.be sa-update.secnap.net www.sa-update.pccc.com sa-update.dnswl.org ocsp.int-x3.letsencrypt.org'
|
HTTPSITES='0.0.0.0/0 ::/0'
|
||||||
HTTPSITES='0.0.0.0/0'
|
|
||||||
|
|
||||||
# HTTPS authorizations
|
# HTTPS authorizations
|
||||||
HTTPSSITES='0.0.0.0/0'
|
HTTPSSITES='0.0.0.0/0 ::/0'
|
||||||
|
|
||||||
# FTP authorizations
|
# FTP authorizations
|
||||||
FTPSITES=''
|
FTPSITES=''
|
||||||
|
|
||||||
# SSH authorizations
|
# SSH authorizations
|
||||||
SSHOK='0.0.0.0/0'
|
SSHOK='0.0.0.0/0 ::/0'
|
||||||
|
|
||||||
# SMTP authorizations
|
# SMTP authorizations
|
||||||
SMTPOK='0.0.0.0/0'
|
SMTPOK='0.0.0.0/0 ::/0'
|
||||||
|
|
||||||
# SMTP secure authorizations (ports TCP/465 and TCP/587)
|
# SMTP secure authorizations (ports TCP/465 and TCP/587)
|
||||||
SMTPSECUREOK=''
|
SMTPSECUREOK=''
|
||||||
|
|
||||||
# NTP authorizations
|
# NTP authorizations
|
||||||
NTPOK='0.0.0.0/0'
|
NTPOK='0.0.0.0/0 ::/0'
|
||||||
|
|
||||||
|
# Proxy (Squid)
|
||||||
|
PROXY='off'
|
||||||
|
# (proxy port)
|
||||||
|
PROXYPORT='8888'
|
||||||
|
# (destinations that bypass the proxy)
|
||||||
|
PROXYBYPASS="${INTLAN} 127.0.0.0/8 ::1/128"
|
||||||
|
|
||||||
|
# Backup servers
|
||||||
|
# (add IP:PORT for each one, example: '192.168.10.1:1234 192.168.10.2:5678')
|
||||||
|
BACKUPSERVERS=''
|
||||||
|
|
||||||
|
|
||||||
# IPv6 Specific rules
|
# Includes
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
# Example: allow SSH from Trusted IPv6 addresses
|
# Files in /etc/minifirewall.d/* (without "." in name)
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --dport 22 -s 2a01:9500:37:129::/64 -j ACCEPT
|
# are automatically included in alphanumerical order.
|
||||||
|
#
|
||||||
|
# Within included files, you can use those helper functions :
|
||||||
|
# * is_ipv6_enabled: returns true if IPv6 is enabled, or false
|
||||||
|
# * is_docker_enabled: returns true if Docker mode is eabled, or false
|
||||||
|
# * is_proxy_enabled: returns true if Proxy mode is enabled , or false
|
||||||
|
|
||||||
# Example: allow outgoing SSH/HTTP/HTTPS/SMTP/DNS traffic
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 22 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 80 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 443 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 25 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p udp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
|
||||||
|
|
||||||
# Example: allow output DNS, NTP and traceroute traffic
|
# Custom sysctl values (advanced)
|
||||||
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 53 --match state --state NEW -j ACCEPT
|
#################################
|
||||||
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 123 --match state --state NEW -j ACCEPT
|
|
||||||
#/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
|
||||||
|
|
||||||
# Example: allow DHCPv6
|
# In most cases, the default values set by minifirewall are good.
|
||||||
/sbin/ip6tables -A INPUT -i $INT -p udp --dport 546 -d fe80::/64 -j ACCEPT
|
# If you really know what you are doing,
|
||||||
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 547 -j ACCEPT
|
# you can uncomment some lines and customize the values.
|
||||||
|
|
||||||
# IPv4 Specific rules
|
# Set 1 to ignore broadcast pings (default)
|
||||||
#####################
|
# SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS='1'
|
||||||
|
|
||||||
# /sbin/iptables ...
|
# Set 1 to ignore bogus ICMP responses (default)
|
||||||
|
# SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES='1'
|
||||||
|
|
||||||
|
# Set 0 to disable source routing (default)
|
||||||
|
# SYSCTL_ACCEPT_SOURCE_ROUTE='0'
|
||||||
|
|
||||||
|
# Set 1 to enable TCP SYN cookies (default)
|
||||||
|
# SYSCTL_TCP_SYNCOOKIES='1'
|
||||||
|
|
||||||
|
# Set 0 to disable ICMP redirects (default)
|
||||||
|
# SYSCTL_ICMP_REDIRECTS='0'
|
||||||
|
|
||||||
|
# Set 1 to enable Reverse Path filtering (default)
|
||||||
|
# Set 0 if VRRP is used
|
||||||
|
# SYSCTL_RP_FILTER='1'
|
||||||
|
|
||||||
|
# Set 1 to log packets with inconsistent address (default)
|
||||||
|
# SYSCTL_LOG_MARTIANS='1'
|
11
minifirewall/files/minifirewall.d/zzz-custom
Normal file
11
minifirewall/files/minifirewall.d/zzz-custom
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
### custom minifirewall commands
|
||||||
|
#
|
||||||
|
# You can add any custom command in files like this;
|
||||||
|
# either this one, or others in the same directory.
|
||||||
|
# They are executed as shell scripts.
|
||||||
|
# They are automatically included in alphanumerical order.
|
||||||
|
#
|
||||||
|
# Within included files, you can use those helper functions :
|
||||||
|
# * is_ipv6_enabled: returns true if IPv6 is enabled, or false
|
||||||
|
# * is_docker_enabled: returns true if Docker mode is eabled, or false
|
||||||
|
# * is_proxy_enabled: returns true if Proxy mode is enabled , or false
|
7
minifirewall/files/minifirewall.d/zzzz-ban
Normal file
7
minifirewall/files/minifirewall.d/zzzz-ban
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
### ban rules
|
||||||
|
#
|
||||||
|
# If you have ban rules in /root/ban.iptables
|
||||||
|
# (either manually or with /usr/share/scripts/blacklist-countries.sh)
|
||||||
|
# ou can automatically import them with the following command:
|
||||||
|
#
|
||||||
|
# cat /root/ban.iptables | iptables-restore -n
|
106
minifirewall/files/minifirewall.legacy.conf
Normal file
106
minifirewall/files/minifirewall.legacy.conf
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
# Configuration for minifirewall : https://gitea.evolix.org/evolix/minifirewall
|
||||||
|
# Version 20.12 — 2020-12-01 22:55:35
|
||||||
|
|
||||||
|
# Main interface
|
||||||
|
INT='eth0'
|
||||||
|
|
||||||
|
# IPv6
|
||||||
|
IPV6=on
|
||||||
|
|
||||||
|
# Docker Mode
|
||||||
|
# Changes the behaviour of minifirewall to not break the containers' network
|
||||||
|
# For instance, turning it on will disable nat table purge
|
||||||
|
# Also, we'll add the DOCKER-USER chain, in iptable
|
||||||
|
DOCKER='off'
|
||||||
|
|
||||||
|
# Trusted IPv4 local network
|
||||||
|
# ...will be often IP/32 if you don't trust anything
|
||||||
|
INTLAN='192.168.0.2/32'
|
||||||
|
|
||||||
|
# Trusted IPv4 addresses for private and semi-public services
|
||||||
|
TRUSTEDIPS='31.170.9.129 62.212.121.90 31.170.8.4 82.65.34.85 54.37.106.210 51.210.84.146'
|
||||||
|
|
||||||
|
# Privilegied IPv4 addresses for semi-public services
|
||||||
|
# (no need to add again TRUSTEDIPS)
|
||||||
|
PRIVILEGIEDIPS=''
|
||||||
|
|
||||||
|
|
||||||
|
# Local services IPv4/IPv6 restrictions
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
# Protected services
|
||||||
|
# (add also in Public services if needed)
|
||||||
|
SERVICESTCP1p='22222'
|
||||||
|
SERVICESUDP1p=''
|
||||||
|
|
||||||
|
# Public services (IPv4/IPv6)
|
||||||
|
SERVICESTCP1='22222'
|
||||||
|
SERVICESUDP1=''
|
||||||
|
|
||||||
|
# Semi-public services (IPv4)
|
||||||
|
SERVICESTCP2='22'
|
||||||
|
SERVICESUDP2=''
|
||||||
|
|
||||||
|
# Private services (IPv4)
|
||||||
|
SERVICESTCP3='5666'
|
||||||
|
SERVICESUDP3=''
|
||||||
|
|
||||||
|
# Standard output IPv4 access restrictions
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# DNS authorizations
|
||||||
|
# (if you have local DNS server, set 0.0.0.0/0)
|
||||||
|
DNSSERVEURS='0.0.0.0/0'
|
||||||
|
|
||||||
|
# HTTP authorizations
|
||||||
|
# (you can use DNS names but set cron to reload minifirewall regularly)
|
||||||
|
# (if you have HTTP proxy, set 0.0.0.0/0)
|
||||||
|
# HTTPSITES='security.debian.org pub.evolix.net security-cdn.debian.org mirror.evolix.org backports.debian.org hwraid.le-vert.net antispam00.evolix.org spamassassin.apache.org sa-update.space-pro.be sa-update.secnap.net www.sa-update.pccc.com sa-update.dnswl.org ocsp.int-x3.letsencrypt.org'
|
||||||
|
HTTPSITES='0.0.0.0/0'
|
||||||
|
|
||||||
|
# HTTPS authorizations
|
||||||
|
HTTPSSITES='0.0.0.0/0'
|
||||||
|
|
||||||
|
# FTP authorizations
|
||||||
|
FTPSITES=''
|
||||||
|
|
||||||
|
# SSH authorizations
|
||||||
|
SSHOK='0.0.0.0/0'
|
||||||
|
|
||||||
|
# SMTP authorizations
|
||||||
|
SMTPOK='0.0.0.0/0'
|
||||||
|
|
||||||
|
# SMTP secure authorizations (ports TCP/465 and TCP/587)
|
||||||
|
SMTPSECUREOK=''
|
||||||
|
|
||||||
|
# NTP authorizations
|
||||||
|
NTPOK='0.0.0.0/0'
|
||||||
|
|
||||||
|
|
||||||
|
# IPv6 Specific rules
|
||||||
|
#####################
|
||||||
|
|
||||||
|
# Example: allow SSH from Trusted IPv6 addresses
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --dport 22 -s 2a01:9500:37:129::/64 -j ACCEPT
|
||||||
|
|
||||||
|
# Example: allow outgoing SSH/HTTP/HTTPS/SMTP/DNS traffic
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 22 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 80 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 443 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 25 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p udp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p tcp --sport 53 --match state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
|
||||||
|
# Example: allow output DNS, NTP and traceroute traffic
|
||||||
|
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 53 --match state --state NEW -j ACCEPT
|
||||||
|
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 123 --match state --state NEW -j ACCEPT
|
||||||
|
#/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 33434:33523 --match state --state NEW -j ACCEPT
|
||||||
|
|
||||||
|
# Example: allow DHCPv6
|
||||||
|
/sbin/ip6tables -A INPUT -i $INT -p udp --dport 546 -d fe80::/64 -j ACCEPT
|
||||||
|
/sbin/ip6tables -A OUTPUT -o $INT -p udp --dport 547 -j ACCEPT
|
||||||
|
|
||||||
|
# IPv4 Specific rules
|
||||||
|
#####################
|
||||||
|
|
||||||
|
# /sbin/iptables ...
|
218
minifirewall/tasks/config.legacy.yml
Normal file
218
minifirewall/tasks/config.legacy.yml
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_trusted_ips
|
||||||
|
verbosity: 1
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_privilegied_ips
|
||||||
|
verbosity: 1
|
||||||
|
|
||||||
|
- name: Stat minifirewall config file (before)
|
||||||
|
stat:
|
||||||
|
path: "{{ minifirewall_main_file }}"
|
||||||
|
register: minifirewall_before
|
||||||
|
|
||||||
|
- name: Check if minifirewall is running
|
||||||
|
shell: /sbin/iptables -L -n | grep -E "^(DROP\s+udp|ACCEPT\s+icmp)\s+--\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0\s*$"
|
||||||
|
changed_when: False
|
||||||
|
failed_when: False
|
||||||
|
check_mode: no
|
||||||
|
register: minifirewall_is_running
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_is_running
|
||||||
|
verbosity: 1
|
||||||
|
|
||||||
|
- name: Begin marker for IP addresses
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
|
insertbefore: '^# Main interface'
|
||||||
|
create: no
|
||||||
|
|
||||||
|
- name: End marker for IP addresses
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
create: no
|
||||||
|
line: "# END ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
|
insertafter: '^PRIVILEGIEDIPS='
|
||||||
|
|
||||||
|
- name: Verify that at least 1 trusted IP is provided
|
||||||
|
assert:
|
||||||
|
that: minifirewall_trusted_ips | length > 0
|
||||||
|
msg: You must provide at least 1 trusted IP
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "Warning: minifirewall_trusted_ips='0.0.0.0/0', the firewall is useless!"
|
||||||
|
when: minifirewall_trusted_ips == ["0.0.0.0/0"]
|
||||||
|
|
||||||
|
- name: Configure IP addresses
|
||||||
|
blockinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
|
block: |
|
||||||
|
# Main interface
|
||||||
|
INT='{{ minifirewall_int }}'
|
||||||
|
|
||||||
|
# IPv6
|
||||||
|
IPV6='{{ minifirewall_ipv6 }}'
|
||||||
|
|
||||||
|
# Docker Mode
|
||||||
|
# Changes the behaviour of minifirewall to not break the containers' network
|
||||||
|
# For instance, turning it on will disable nat table purge
|
||||||
|
# Also, we'll add the DOCKER-USER chain, in iptable
|
||||||
|
DOCKER='{{ minifirewall_docker }}'
|
||||||
|
|
||||||
|
# Trusted IPv4 local network
|
||||||
|
# ...will be often IP/32 if you don't trust anything
|
||||||
|
INTLAN='{{ minifirewall_intlan }}'
|
||||||
|
|
||||||
|
# Trusted IPv4 addresses for private and semi-public services
|
||||||
|
TRUSTEDIPS='{{ minifirewall_trusted_ips | join(' ') }}'
|
||||||
|
|
||||||
|
# Privilegied IPv4 addresses for semi-public services
|
||||||
|
# (no need to add again TRUSTEDIPS)
|
||||||
|
PRIVILEGIEDIPS='{{ minifirewall_privilegied_ips | join(' ') }}'
|
||||||
|
create: no
|
||||||
|
register: minifirewall_config_ips
|
||||||
|
|
||||||
|
- name: Begin marker for ports
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
|
insertbefore: '^# Protected services'
|
||||||
|
create: no
|
||||||
|
|
||||||
|
- name: End marker for ports
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "# END ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
|
insertafter: '^SERVICESUDP3='
|
||||||
|
create: no
|
||||||
|
|
||||||
|
- name: Configure ports
|
||||||
|
blockinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
|
block: |
|
||||||
|
# Protected services
|
||||||
|
# (add also in Public services if needed)
|
||||||
|
SERVICESTCP1p='{{ minifirewall_protected_ports_tcp | join(' ') }}'
|
||||||
|
SERVICESUDP1p='{{ minifirewall_protected_ports_udp | join(' ') }}'
|
||||||
|
|
||||||
|
# Public services (IPv4/IPv6)
|
||||||
|
SERVICESTCP1='{{ minifirewall_public_ports_tcp | join(' ') }}'
|
||||||
|
SERVICESUDP1='{{ minifirewall_public_ports_udp | join(' ') }}'
|
||||||
|
|
||||||
|
# Semi-public services (IPv4)
|
||||||
|
SERVICESTCP2='{{ minifirewall_semipublic_ports_tcp | join(' ') }}'
|
||||||
|
SERVICESUDP2='{{ minifirewall_semipublic_ports_udp | join(' ') }}'
|
||||||
|
|
||||||
|
# Private services (IPv4)
|
||||||
|
SERVICESTCP3='{{ minifirewall_private_ports_tcp | join(' ') }}'
|
||||||
|
SERVICESUDP3='{{ minifirewall_private_ports_udp | join(' ') }}'
|
||||||
|
create: no
|
||||||
|
register: minifirewall_config_ports
|
||||||
|
|
||||||
|
- name: Configure DNSSERVEURS
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "DNSSERVEURS='{{ minifirewall_dns_servers | join(' ') }}'"
|
||||||
|
regexp: "DNSSERVEURS='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_dns_servers is not none
|
||||||
|
|
||||||
|
- name: Configure HTTPSITES
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "HTTPSITES='{{ minifirewall_http_sites | join(' ') }}'"
|
||||||
|
regexp: "HTTPSITES='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_http_sites is not none
|
||||||
|
|
||||||
|
- name: Configure HTTPSSITES
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "HTTPSSITES='{{ minifirewall_https_sites | join(' ') }}'"
|
||||||
|
regexp: "HTTPSSITES='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_https_sites is not none
|
||||||
|
|
||||||
|
- name: Configure FTPSITES
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "FTPSITES='{{ minifirewall_ftp_sites | join(' ') }}'"
|
||||||
|
regexp: "FTPSITES='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_ftp_sites is not none
|
||||||
|
|
||||||
|
- name: Configure SSHOK
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "SSHOK='{{ minifirewall_ssh_ok | join(' ') }}'"
|
||||||
|
regexp: "SSHOK='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_ssh_ok is not none
|
||||||
|
|
||||||
|
- name: Configure SMTPOK
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "SMTPOK='{{ minifirewall_smtp_ok | join(' ') }}'"
|
||||||
|
regexp: "SMTPOK='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_smtp_ok is not none
|
||||||
|
|
||||||
|
- name: Configure SMTPSECUREOK
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "SMTPSECUREOK='{{ minifirewall_smtp_secure_ok | join(' ') }}'"
|
||||||
|
regexp: "SMTPSECUREOK='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_smtp_secure_ok is not none
|
||||||
|
|
||||||
|
- name: Configure NTPOK
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "NTPOK='{{ minifirewall_ntp_ok | join(' ') }}'"
|
||||||
|
regexp: "NTPOK='.*'"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_ntp_ok is not none
|
||||||
|
|
||||||
|
- name: evomaintenance
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
line: "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s {{ item }} -m state --state ESTABLISHED,RELATED -j ACCEPT"
|
||||||
|
insertafter: "^# EvoMaintenance"
|
||||||
|
loop: "{{ evomaintenance_hosts }}"
|
||||||
|
|
||||||
|
- name: remove minifirewall example rule for the evomaintenance
|
||||||
|
lineinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
regexp: '^#.*(--sport 5432).*(-s X\.X\.X\.X)'
|
||||||
|
state: absent
|
||||||
|
when: evomaintenance_hosts | length > 0
|
||||||
|
|
||||||
|
- name: Stat minifirewall config file (after)
|
||||||
|
stat:
|
||||||
|
path: "{{ minifirewall_main_file }}"
|
||||||
|
register: minifirewall_after
|
||||||
|
|
||||||
|
- name: restart minifirewall
|
||||||
|
command: /etc/init.d/minifirewall restart
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
||||||
|
when:
|
||||||
|
- minifirewall_restart_if_needed | bool
|
||||||
|
- minifirewall_is_running.rc == 0
|
||||||
|
- minifirewall_before.stat.checksum != minifirewall_after.stat.checksum
|
||||||
|
|
||||||
|
- name: restart minifirewall (noop)
|
||||||
|
meta: noop
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: False
|
||||||
|
changed_when: False
|
||||||
|
when: not (minifirewall_restart_if_needed | bool)
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_init_restart
|
||||||
|
verbosity: 2
|
|
@ -9,11 +9,12 @@
|
||||||
|
|
||||||
- name: Stat minifirewall config file (before)
|
- name: Stat minifirewall config file (before)
|
||||||
stat:
|
stat:
|
||||||
path: "{{ minifirewall_main_file }}"
|
path: "/etc/default/minifirewall"
|
||||||
register: minifirewall_before
|
register: minifirewall_before
|
||||||
|
|
||||||
- name: Check if minifirewall is running
|
- name: Check if minifirewall is running
|
||||||
shell: /sbin/iptables -L -n | grep -E "^(DROP\s+udp|ACCEPT\s+icmp)\s+--\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0\s*$"
|
shell:
|
||||||
|
cmd: /sbin/iptables -L -n | grep -E "^(DROP\s+udp|ACCEPT\s+icmp)\s+--\s+0\.0\.0\.0\/0\s+0\.0\.0\.0\/0\s*$"
|
||||||
changed_when: False
|
changed_when: False
|
||||||
failed_when: False
|
failed_when: False
|
||||||
check_mode: no
|
check_mode: no
|
||||||
|
@ -25,14 +26,14 @@
|
||||||
|
|
||||||
- name: Begin marker for IP addresses
|
- name: Begin marker for IP addresses
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR IPS"
|
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
insertbefore: '^# Main interface'
|
insertbefore: '^# Main interface'
|
||||||
create: no
|
create: no
|
||||||
|
|
||||||
- name: End marker for IP addresses
|
- name: End marker for IP addresses
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
create: no
|
create: no
|
||||||
line: "# END ANSIBLE MANAGED BLOCK FOR IPS"
|
line: "# END ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
insertafter: '^PRIVILEGIEDIPS='
|
insertafter: '^PRIVILEGIEDIPS='
|
||||||
|
@ -43,12 +44,16 @@
|
||||||
msg: You must provide at least 1 trusted IP
|
msg: You must provide at least 1 trusted IP
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
msg: "Warning: minifirewall_trusted_ips='0.0.0.0/0', the firewall is useless!"
|
msg: "Warning: minifirewall_trusted_ips contains '0.0.0.0/0', the firewall is useless on IPv4!"
|
||||||
when: minifirewall_trusted_ips == ["0.0.0.0/0"]
|
when: "'0.0.0.0/0' in minifirewall_trusted_ips"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "Warning: minifirewall_trusted_ips contains '::/0', the firewall is useless on IPv6!"
|
||||||
|
when: "'::/0' in minifirewall_trusted_ips"
|
||||||
|
|
||||||
- name: Configure IP addresses
|
- name: Configure IP addresses
|
||||||
blockinfile:
|
blockinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR IPS"
|
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR IPS"
|
||||||
block: |
|
block: |
|
||||||
# Main interface
|
# Main interface
|
||||||
|
@ -60,8 +65,12 @@
|
||||||
# Docker Mode
|
# Docker Mode
|
||||||
# Changes the behaviour of minifirewall to not break the containers' network
|
# Changes the behaviour of minifirewall to not break the containers' network
|
||||||
# For instance, turning it on will disable nat table purge
|
# For instance, turning it on will disable nat table purge
|
||||||
# Also, we'll add the DOCKER-USER chain, in iptable
|
# Also, we'll add the DOCKER-USER chain, in iptables
|
||||||
DOCKER='{{ minifirewall_docker }}'
|
#
|
||||||
|
# WARNING : If the port mapping is different between the host and the container
|
||||||
|
# (ie: Listen on :8090 on host, but :8080 in container)
|
||||||
|
# then you need to give the port used inside the container
|
||||||
|
DOCKER='off'
|
||||||
|
|
||||||
# Trusted IPv4 local network
|
# Trusted IPv4 local network
|
||||||
# ...will be often IP/32 if you don't trust anything
|
# ...will be often IP/32 if you don't trust anything
|
||||||
|
@ -78,21 +87,21 @@
|
||||||
|
|
||||||
- name: Begin marker for ports
|
- name: Begin marker for ports
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR PORTS"
|
line: "# BEGIN ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
insertbefore: '^# Protected services'
|
insertbefore: '^# Protected services'
|
||||||
create: no
|
create: no
|
||||||
|
|
||||||
- name: End marker for ports
|
- name: End marker for ports
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "# END ANSIBLE MANAGED BLOCK FOR PORTS"
|
line: "# END ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
insertafter: '^SERVICESUDP3='
|
insertafter: '^SERVICESUDP3='
|
||||||
create: no
|
create: no
|
||||||
|
|
||||||
- name: Configure ports
|
- name: Configure ports
|
||||||
blockinfile:
|
blockinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR PORTS"
|
marker: "# {mark} ANSIBLE MANAGED BLOCK FOR PORTS"
|
||||||
block: |
|
block: |
|
||||||
# Protected services
|
# Protected services
|
||||||
|
@ -116,106 +125,171 @@
|
||||||
|
|
||||||
- name: Configure DNSSERVEURS
|
- name: Configure DNSSERVEURS
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "DNSSERVEURS='{{ minifirewall_dns_servers | join(' ') }}'"
|
line: "DNSSERVEURS='{{ minifirewall_dns_servers | join(' ') }}'"
|
||||||
regexp: "DNSSERVEURS='.*'"
|
regexp: "DNSSERVEURS=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_dns_servers is not none
|
when: minifirewall_dns_servers is not none
|
||||||
|
|
||||||
- name: Configure HTTPSITES
|
- name: Configure HTTPSITES
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "HTTPSITES='{{ minifirewall_http_sites | join(' ') }}'"
|
line: "HTTPSITES='{{ minifirewall_http_sites | join(' ') }}'"
|
||||||
regexp: "HTTPSITES='.*'"
|
regexp: "HTTPSITES=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_http_sites is not none
|
when: minifirewall_http_sites is not none
|
||||||
|
|
||||||
- name: Configure HTTPSSITES
|
- name: Configure HTTPSSITES
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "HTTPSSITES='{{ minifirewall_https_sites | join(' ') }}'"
|
line: "HTTPSSITES='{{ minifirewall_https_sites | join(' ') }}'"
|
||||||
regexp: "HTTPSSITES='.*'"
|
regexp: "HTTPSSITES=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_https_sites is not none
|
when: minifirewall_https_sites is not none
|
||||||
|
|
||||||
- name: Configure FTPSITES
|
- name: Configure FTPSITES
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "FTPSITES='{{ minifirewall_ftp_sites | join(' ') }}'"
|
line: "FTPSITES='{{ minifirewall_ftp_sites | join(' ') }}'"
|
||||||
regexp: "FTPSITES='.*'"
|
regexp: "FTPSITES=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_ftp_sites is not none
|
when: minifirewall_ftp_sites is not none
|
||||||
|
|
||||||
- name: Configure SSHOK
|
- name: Configure SSHOK
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "SSHOK='{{ minifirewall_ssh_ok | join(' ') }}'"
|
line: "SSHOK='{{ minifirewall_ssh_ok | join(' ') }}'"
|
||||||
regexp: "SSHOK='.*'"
|
regexp: "SSHOK=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_ssh_ok is not none
|
when: minifirewall_ssh_ok is not none
|
||||||
|
|
||||||
- name: Configure SMTPOK
|
- name: Configure SMTPOK
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "SMTPOK='{{ minifirewall_smtp_ok | join(' ') }}'"
|
line: "SMTPOK='{{ minifirewall_smtp_ok | join(' ') }}'"
|
||||||
regexp: "SMTPOK='.*'"
|
regexp: "SMTPOK=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_smtp_ok is not none
|
when: minifirewall_smtp_ok is not none
|
||||||
|
|
||||||
- name: Configure SMTPSECUREOK
|
- name: Configure SMTPSECUREOK
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "SMTPSECUREOK='{{ minifirewall_smtp_secure_ok | join(' ') }}'"
|
line: "SMTPSECUREOK='{{ minifirewall_smtp_secure_ok | join(' ') }}'"
|
||||||
regexp: "SMTPSECUREOK='.*'"
|
regexp: "SMTPSECUREOK=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_smtp_secure_ok is not none
|
when: minifirewall_smtp_secure_ok is not none
|
||||||
|
|
||||||
- name: Configure NTPOK
|
- name: Configure NTPOK
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "NTPOK='{{ minifirewall_ntp_ok | join(' ') }}'"
|
line: "NTPOK='{{ minifirewall_ntp_ok | join(' ') }}'"
|
||||||
regexp: "NTPOK='.*'"
|
regexp: "NTPOK=('|\").*('|\")"
|
||||||
create: no
|
create: no
|
||||||
when: minifirewall_ntp_ok is not none
|
when: minifirewall_ntp_ok is not none
|
||||||
|
|
||||||
- name: evomaintenance
|
- name: Configure PROXY
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "/sbin/iptables -A INPUT -p tcp --sport 5432 --dport 1024:65535 -s {{ item }} -m state --state ESTABLISHED,RELATED -j ACCEPT"
|
line: "PROXY='{{ minifirewall_proxy }}'"
|
||||||
insertafter: "^# EvoMaintenance"
|
regexp: "PROXY=('|\").*('|\")"
|
||||||
loop: "{{ evomaintenance_hosts }}"
|
create: no
|
||||||
|
when: minifirewall_proxy is not none
|
||||||
|
|
||||||
- name: remove minifirewall example rule for the evomaintenance
|
- name: Configure PROXYPORT
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
regexp: '^#.*(--sport 5432).*(-s X\.X\.X\.X)'
|
line: "PROXYPORT='{{ minifirewall_proxyport }}'"
|
||||||
state: absent
|
regexp: "PROXYPORT=('|\").*('|\")"
|
||||||
when: evomaintenance_hosts | length > 0
|
create: no
|
||||||
|
when: minifirewall_proxyport is not none
|
||||||
|
|
||||||
|
# Warning: keep double quotes for the value,
|
||||||
|
# since we often reference a shell variable that needs to be interpolated
|
||||||
|
- name: Configure PROXYBYPASS
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "PROXYBYPASS=\"{{ minifirewall_proxybypass | join(' ') }}\""
|
||||||
|
regexp: "PROXYBYPASS=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_proxybypass is not none
|
||||||
|
|
||||||
|
- name: Configure BACKUPSERVERS
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "BACKUPSERVERS='{{ minifirewall_backupservers | join(' ') }}'"
|
||||||
|
regexp: "BACKUPSERVERS=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_backupservers is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS='{{ minifirewall_sysctl_icmp_echo_ignore_broadcasts }}'"
|
||||||
|
regexp: "SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_icmp_echo_ignore_broadcasts is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES='{{ minifirewall_sysctl_icmp_ignore_bogus_error_responses }}'"
|
||||||
|
regexp: "SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_icmp_ignore_bogus_error_responses is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_ACCEPT_SOURCE_ROUTE
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_ACCEPT_SOURCE_ROUTE='{{ minifirewall_sysctl_accept_source_route }}'"
|
||||||
|
regexp: "SYSCTL_ACCEPT_SOURCE_ROUTE=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_accept_source_route is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_TCP_SYNCOOKIES
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_TCP_SYNCOOKIES='{{ minifirewall_sysctl_tcp_syncookies }}'"
|
||||||
|
regexp: "SYSCTL_TCP_SYNCOOKIES=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_tcp_syncookies is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_ICMP_REDIRECTS
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_ICMP_REDIRECTS='{{ minifirewall_sysctl_icmp_redirects }}'"
|
||||||
|
regexp: "SYSCTL_ICMP_REDIRECTS=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_icmp_redirects is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_RP_FILTER
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_RP_FILTER='{{ minifirewall_sysctl_rp_filter }}'"
|
||||||
|
regexp: "SYSCTL_RP_FILTER=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_rp_filter is not none
|
||||||
|
|
||||||
|
- name: Configure SYSCTL_LOG_MARTIANS
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "SYSCTL_LOG_MARTIANS='{{ minifirewall_sysctl_log_martians }}'"
|
||||||
|
regexp: "SYSCTL_LOG_MARTIANS=('|\").*('|\")"
|
||||||
|
create: no
|
||||||
|
when: minifirewall_sysctl_log_martians is not none
|
||||||
|
|
||||||
- name: Stat minifirewall config file (after)
|
- name: Stat minifirewall config file (after)
|
||||||
stat:
|
stat:
|
||||||
path: "{{ minifirewall_main_file }}"
|
path: "/etc/default/minifirewall"
|
||||||
register: minifirewall_after
|
register: minifirewall_after
|
||||||
|
|
||||||
- name: restart minifirewall
|
- name: restart minifirewall
|
||||||
# service:
|
|
||||||
# name: minifirewall
|
|
||||||
# state: restarted
|
|
||||||
command: /etc/init.d/minifirewall restart
|
command: /etc/init.d/minifirewall restart
|
||||||
register: minifirewall_init_restart
|
register: minifirewall_init_restart
|
||||||
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
|
||||||
changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout"
|
|
||||||
when:
|
when:
|
||||||
- minifirewall_restart_if_needed | bool
|
- minifirewall_restart_if_needed | bool
|
||||||
- minifirewall_is_running.rc == 0
|
- minifirewall_is_running.rc == 0
|
||||||
- minifirewall_before.stat.checksum != minifirewall_after.stat.checksum
|
- minifirewall_before.stat.checksum != minifirewall_after.stat.checksum or minifirewall_upgrade_script is changed or minifirewall_upgrade_config is changed
|
||||||
|
|
||||||
- name: restart minifirewall (noop)
|
|
||||||
meta: noop
|
|
||||||
register: minifirewall_init_restart
|
|
||||||
failed_when: False
|
|
||||||
changed_when: False
|
|
||||||
when: not (minifirewall_restart_if_needed | bool)
|
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
var: minifirewall_init_restart
|
var: minifirewall_init_restart
|
||||||
|
|
24
minifirewall/tasks/install.legacy.yml
Normal file
24
minifirewall/tasks/install.legacy.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: dependencies are satisfied
|
||||||
|
apt:
|
||||||
|
name: iptables
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: init script is copied
|
||||||
|
template:
|
||||||
|
src: minifirewall.legacy.j2
|
||||||
|
dest: /etc/init.d/minifirewall
|
||||||
|
force: "{{ minifirewall_force_upgrade_script | default('no') }}"
|
||||||
|
mode: "0700"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
|
||||||
|
- name: configuration is copied
|
||||||
|
copy:
|
||||||
|
src: minifirewall.legacy.conf
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
force: "{{ minifirewall_force_upgrade_config | default('no') }}"
|
||||||
|
mode: "0600"
|
||||||
|
owner: root
|
||||||
|
group: root
|
|
@ -6,19 +6,38 @@
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: init script is copied
|
- name: init script is copied
|
||||||
template:
|
copy:
|
||||||
src: minifirewall.j2
|
src: minifirewall
|
||||||
dest: /etc/init.d/minifirewall
|
dest: /etc/init.d/minifirewall
|
||||||
force: "{{ minifirewall_force_upgrade_script | default('no') }}"
|
force: "{{ minifirewall_force_upgrade_script | default('no') }}"
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
|
register: minifirewall_upgrade_script
|
||||||
|
|
||||||
- name: configuration is copied
|
- name: configuration is copied
|
||||||
copy:
|
copy:
|
||||||
src: minifirewall.conf
|
src: minifirewall.conf
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
force: "{{ minifirewall_force_upgrade_config | default('no') }}"
|
force: "{{ minifirewall_force_upgrade_config | default('no') }}"
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
|
register: minifirewall_upgrade_config
|
||||||
|
|
||||||
|
- name: includes directory is present
|
||||||
|
file:
|
||||||
|
path: /etc/minifirewall.d/
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: examples for includes are present
|
||||||
|
copy:
|
||||||
|
src: "minifirewall.d/"
|
||||||
|
dest: "/etc/minifirewall.d/"
|
||||||
|
force: "no"
|
||||||
|
mode: "0600"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
|
|
@ -4,19 +4,105 @@
|
||||||
set_fact:
|
set_fact:
|
||||||
minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}"
|
minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}"
|
||||||
|
|
||||||
- include: install.yml
|
# Legacy or modern mode? ##############################################
|
||||||
|
|
||||||
- include: config.yml
|
- name: Check minifirewall
|
||||||
|
stat:
|
||||||
|
path: /etc/init.d/minifirewall
|
||||||
|
register: _minifirewall_check
|
||||||
|
|
||||||
- include: nrpe.yml
|
# Legacy versions of minifirewall don't define the VERSION variable
|
||||||
|
- name: Look for minifirewall version
|
||||||
- include: activate.yml
|
shell: "grep -E '^\\s*VERSION=' /etc/init.d/minifirewall"
|
||||||
|
failed_when: False
|
||||||
- include: tail.yml
|
|
||||||
when: minifirewall_tail_included | bool
|
|
||||||
|
|
||||||
- name: Force restart minifirewall
|
|
||||||
command: /bin/true
|
|
||||||
notify: restart minifirewall
|
|
||||||
changed_when: False
|
changed_when: False
|
||||||
when: minifirewall_restart_force | bool
|
check_mode: False
|
||||||
|
register: _minifirewall_version_check
|
||||||
|
|
||||||
|
- name: Set install mode to legacy if needed
|
||||||
|
set_fact:
|
||||||
|
minifirewall_install_mode: legacy
|
||||||
|
minifirewall_main_file: "{{ minifirewall_legacy_main_file }}"
|
||||||
|
minifirewall_tail_file: "{{ minifirewall_legacy_tail_file }}"
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode != 'modern'
|
||||||
|
- not (minifirewall_force_upgrade_script | bool)
|
||||||
|
- _minifirewall_version_check.rc == 1 # grep didn't find but the file exists
|
||||||
|
|
||||||
|
- name: Set install mode to modern if not legacy
|
||||||
|
set_fact:
|
||||||
|
minifirewall_install_mode: modern
|
||||||
|
when: minifirewall_install_mode != 'legacy'
|
||||||
|
|
||||||
|
- name: Debug install mode
|
||||||
|
debug:
|
||||||
|
var: minifirewall_install_mode
|
||||||
|
verbosity: 1
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
- name: Fail if minifirewall_main_file is defined (legacy mode)
|
||||||
|
fail:
|
||||||
|
msg: "Variable minifirewall_main_file is deprecated and not configurable anymore."
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode != 'legacy'
|
||||||
|
- minifirewall_main_file is defined
|
||||||
|
|
||||||
|
- name: Install tasks (modern mode)
|
||||||
|
include: install.yml
|
||||||
|
when: minifirewall_install_mode != 'legacy'
|
||||||
|
|
||||||
|
- name: Install tasks (legacy mode)
|
||||||
|
include: install.legacy.yml
|
||||||
|
when: minifirewall_install_mode == 'legacy'
|
||||||
|
|
||||||
|
- name: Config tasks (modern mode)
|
||||||
|
include: config.yml
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode != 'legacy'
|
||||||
|
- minifirewall_update_config | bool
|
||||||
|
|
||||||
|
- name: Config tasks (legacy mode)
|
||||||
|
include: config.legacy.yml
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode == 'legacy'
|
||||||
|
- minifirewall_update_config | bool
|
||||||
|
|
||||||
|
- name: Utils tasks
|
||||||
|
include: utils.yml
|
||||||
|
|
||||||
|
- name: NRPE tasks
|
||||||
|
include: nrpe.yml
|
||||||
|
|
||||||
|
- name: Activation tasks
|
||||||
|
include: activate.yml
|
||||||
|
|
||||||
|
- name: Tail tasks (modern mode)
|
||||||
|
include: tail.yml
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode != 'legacy'
|
||||||
|
- minifirewall_tail_included | bool
|
||||||
|
|
||||||
|
- name: Tail tasks (legacy mode)
|
||||||
|
include: tail.legacy.yml
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode == 'legacy'
|
||||||
|
- minifirewall_tail_included | bool
|
||||||
|
|
||||||
|
# Restart?
|
||||||
|
|
||||||
|
- name: Force restart minifirewall (modern mode)
|
||||||
|
command: /etc/init.d/minifirewall restart
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode != 'legacy'
|
||||||
|
- minifirewall_restart_force | bool
|
||||||
|
|
||||||
|
- name: Force restart minifirewall (legacy mode)
|
||||||
|
command: /etc/init.d/minifirewall restart
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
||||||
|
when:
|
||||||
|
- minifirewall_install_mode == 'legacy'
|
||||||
|
- minifirewall_restart_force | bool
|
50
minifirewall/tasks/tail.legacy.yml
Normal file
50
minifirewall/tasks/tail.legacy.yml
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
- name: Add some rules at the end of minifirewall file
|
||||||
|
template:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "{{ minifirewall_tail_file }}"
|
||||||
|
force: "{{ minifirewall_tail_force | bool }}"
|
||||||
|
follow: yes
|
||||||
|
loop: "{{ query('first_found', templates) }}"
|
||||||
|
vars:
|
||||||
|
templates:
|
||||||
|
- "templates/minifirewall-tail/minifirewall.{{ inventory_hostname }}.tail.j2"
|
||||||
|
- "templates/minifirewall-tail/minifirewall.{{ host_group | default('all') }}.tail.j2"
|
||||||
|
- "templates/minifirewall-tail/minifirewall.default.tail.j2"
|
||||||
|
- "templates/minifirewall.default.tail.j2"
|
||||||
|
register: minifirewall_tail_template
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_tail_template
|
||||||
|
verbosity: 1
|
||||||
|
|
||||||
|
- name: source minifirewall.tail at the end of the main file
|
||||||
|
blockinfile:
|
||||||
|
dest: "{{ minifirewall_main_file }}"
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED EXTERNAL RULES"
|
||||||
|
block: ". {{ minifirewall_tail_file }}"
|
||||||
|
insertbefore: EOF
|
||||||
|
register: minifirewall_tail_source
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_tail_source
|
||||||
|
verbosity: 1
|
||||||
|
|
||||||
|
- name: restart minifirewall
|
||||||
|
command: /etc/init.d/minifirewall restart
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
||||||
|
when:
|
||||||
|
- minifirewall_tail_template is changed
|
||||||
|
- minifirewall_restart_if_needed | bool
|
||||||
|
|
||||||
|
- name: restart minifirewall (noop)
|
||||||
|
meta: noop
|
||||||
|
register: minifirewall_init_restart
|
||||||
|
failed_when: False
|
||||||
|
changed_when: False
|
||||||
|
when: not (minifirewall_restart_if_needed | bool)
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: minifirewall_init_restart
|
||||||
|
verbosity: 1
|
|
@ -4,6 +4,7 @@
|
||||||
src: "{{ item }}"
|
src: "{{ item }}"
|
||||||
dest: "{{ minifirewall_tail_file }}"
|
dest: "{{ minifirewall_tail_file }}"
|
||||||
force: "{{ minifirewall_tail_force | bool }}"
|
force: "{{ minifirewall_tail_force | bool }}"
|
||||||
|
follow: yes
|
||||||
loop: "{{ query('first_found', templates) }}"
|
loop: "{{ query('first_found', templates) }}"
|
||||||
vars:
|
vars:
|
||||||
templates:
|
templates:
|
||||||
|
@ -17,26 +18,10 @@
|
||||||
var: minifirewall_tail_template
|
var: minifirewall_tail_template
|
||||||
verbosity: 1
|
verbosity: 1
|
||||||
|
|
||||||
- name: source minifirewall.tail at the end of the main file
|
|
||||||
blockinfile:
|
|
||||||
dest: "{{ minifirewall_main_file }}"
|
|
||||||
marker: "# {mark} ANSIBLE MANAGED EXTERNAL RULES"
|
|
||||||
block: ". {{ minifirewall_tail_file }}"
|
|
||||||
insertbefore: EOF
|
|
||||||
register: minifirewall_tail_source
|
|
||||||
|
|
||||||
- debug:
|
|
||||||
var: minifirewall_tail_source
|
|
||||||
verbosity: 1
|
|
||||||
|
|
||||||
- name: restart minifirewall
|
- name: restart minifirewall
|
||||||
# service:
|
|
||||||
# name: minifirewall
|
|
||||||
# state: restarted
|
|
||||||
command: /etc/init.d/minifirewall restart
|
command: /etc/init.d/minifirewall restart
|
||||||
register: minifirewall_init_restart
|
register: minifirewall_init_restart
|
||||||
failed_when: "'starting IPTables rules is now finish : OK' not in minifirewall_init_restart.stdout"
|
failed_when: "'minifirewall failed' in minifirewall_init_restart.stdout"
|
||||||
changed_when: "'starting IPTables rules is now finish : OK' in minifirewall_init_restart.stdout"
|
|
||||||
when:
|
when:
|
||||||
- minifirewall_tail_template is changed
|
- minifirewall_tail_template is changed
|
||||||
- minifirewall_restart_if_needed | bool
|
- minifirewall_restart_if_needed | bool
|
||||||
|
|
21
minifirewall/tasks/utils.yml
Normal file
21
minifirewall/tasks/utils.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
|
||||||
|
- name: /usr/share/scripts exists
|
||||||
|
file:
|
||||||
|
dest: /usr/share/scripts
|
||||||
|
mode: "0700"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: blacklist-countries.sh is copied
|
||||||
|
copy:
|
||||||
|
src: blacklist-countries.sh
|
||||||
|
dest: /usr/share/scripts/blacklist-countries.sh
|
||||||
|
force: "no"
|
||||||
|
mode: "0700"
|
||||||
|
owner: root
|
||||||
|
group: root
|
0
minifirewall/templates/minifirewall.j2 → minifirewall/templates/minifirewall.legacy.j2
Executable file → Normal file
0
minifirewall/templates/minifirewall.j2 → minifirewall/templates/minifirewall.legacy.j2
Executable file → Normal file
213
munin/files/plugins/dhcp_pool
Normal file
213
munin/files/plugins/dhcp_pool
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Rien Broekstra <rien@rename-it.nl>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; version 2 dated June,
|
||||||
|
# 1991.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Munin plugin to measure saturation of DHCP pools.
|
||||||
|
#
|
||||||
|
# Configuration variables:
|
||||||
|
#
|
||||||
|
# conffile - path to dhcpd's configuration file (default "/etc/dhcpd.conf")
|
||||||
|
# leasefile - path to dhcpd's leases file (default "/var/lib/dhcp/dhcpd.leases")
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
#
|
||||||
|
# config (required)
|
||||||
|
#
|
||||||
|
# Version 1.0, 2-12-2008
|
||||||
|
#
|
||||||
|
#%# family=auto
|
||||||
|
#%# capabilities=autoconf
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
use Time::Local;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my $CONFFILE = exists $ENV{'conffile'} ? $ENV{'conffile'} : "/etc/dhcp/dhcpd.conf";
|
||||||
|
my $LEASEFILE = exists $ENV{'leasefile'} ? $ENV{'leasefile'} : "/var/lib/dhcp/dhcpd.leases";
|
||||||
|
|
||||||
|
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
|
||||||
|
if (-e ${CONFFILE} and -e ${LEASEFILE}) {
|
||||||
|
my %pools;
|
||||||
|
%pools = determine_pools();
|
||||||
|
if (%pools) {
|
||||||
|
print "yes\n";
|
||||||
|
} else {
|
||||||
|
print "no (no pools defined in config)\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print "no (no config or lease file)\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ( defined $ARGV[0] and $ARGV[0] eq "config" ) {
|
||||||
|
my (%pools, $start, $label);
|
||||||
|
|
||||||
|
# Print general information
|
||||||
|
print "graph_title DHCP pool usage (in %)\n";
|
||||||
|
print "graph_args --upper-limit 100 -l 0\n";
|
||||||
|
print "graph_vlabel %\n";
|
||||||
|
#___ORI___# print "graph_category network\n";
|
||||||
|
print "graph_category dhcpd\n";
|
||||||
|
|
||||||
|
# Determine the available IP pools
|
||||||
|
%pools = determine_pools();
|
||||||
|
|
||||||
|
# Print a label for each pool
|
||||||
|
foreach $start (sort (keys %pools)) {
|
||||||
|
$label = ip2string($start);
|
||||||
|
$label =~ s/\./\_/g;
|
||||||
|
print "_$label.label Pool " . ip2string($start) . " - " . ip2string($start + $pools{$start} - 1) . "\n";
|
||||||
|
print "_$label.warning 90\n";
|
||||||
|
print "_$label.critical 100\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my (@activeleases, %pools, $start, $end, $size, $free, $label, $lease);
|
||||||
|
|
||||||
|
# Determine all leased IP addresses
|
||||||
|
@activeleases = determine_active_leases();
|
||||||
|
|
||||||
|
# Determine the available IP pools
|
||||||
|
%pools = determine_pools();
|
||||||
|
|
||||||
|
# For each pool, count how many leases from that pool are currently active
|
||||||
|
foreach $start (keys %pools) {
|
||||||
|
$size = $pools{$start};
|
||||||
|
$end = $start+$size-1;
|
||||||
|
$free = $size;
|
||||||
|
|
||||||
|
foreach $lease (@activeleases) {
|
||||||
|
if ($lease >= $start && $lease <= $end) {
|
||||||
|
$free--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$label = ip2string($start);
|
||||||
|
$label =~ s/\./\_/g;
|
||||||
|
print "_$label.value ".sprintf("%.1f", 100*($size-$free)/$size)."\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse dhcpd.conf for range statements.
|
||||||
|
#
|
||||||
|
# Returns a hash with start IP -> size
|
||||||
|
sub determine_pools {
|
||||||
|
my (%pools, @conffile, $line, $start, $end, $size);
|
||||||
|
|
||||||
|
open(CONFFILE, "<${CONFFILE}") || exit -1;
|
||||||
|
@conffile = <CONFFILE>;
|
||||||
|
close (CONFFILE);
|
||||||
|
|
||||||
|
foreach $line (@conffile) {
|
||||||
|
next if $line =~ /^\s*#/;
|
||||||
|
|
||||||
|
if ($line =~ /range[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
|
||||||
|
$start = string2ip($1);
|
||||||
|
$end = string2ip($2);
|
||||||
|
|
||||||
|
defined($start) || next;
|
||||||
|
defined($end) || next;
|
||||||
|
|
||||||
|
# The range statement gives the lowest and highest IP addresses in a range.
|
||||||
|
$size = $end - $start + 1;
|
||||||
|
|
||||||
|
$pools{$start} = $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return %pools;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Very simple parser for dhcpd.leases. This will break very easily if dhcpd decides to
|
||||||
|
# format the file differently. Ideally a simple recursive-descent parser should be used.
|
||||||
|
#
|
||||||
|
# Returns an array with currently leased IP's
|
||||||
|
sub determine_active_leases {
|
||||||
|
my (@leasefile, $startdate, $enddate, $lease, @activeleases, $mytz, $line, %saw);
|
||||||
|
|
||||||
|
open(LEASEFILE, "<${LEASEFILE}") || exit -1;
|
||||||
|
@leasefile = <LEASEFILE>;
|
||||||
|
close (LEASEFILE);
|
||||||
|
|
||||||
|
@activeleases = ();
|
||||||
|
|
||||||
|
# Portable way of converting a GMT date/time string to timestamp is setting TZ to UTC, and then calling mktime()
|
||||||
|
$mytz = $ENV{'TZ'};
|
||||||
|
$ENV{'TZ'} = 'UTC 0';
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
foreach $line (@leasefile) {
|
||||||
|
if ($line =~ /lease ([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
|
||||||
|
$lease = string2ip($1);
|
||||||
|
defined($lease) || next;
|
||||||
|
|
||||||
|
undef $startdate;
|
||||||
|
undef $enddate;
|
||||||
|
}
|
||||||
|
elsif ($line =~ /starts \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
|
||||||
|
$startdate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
|
||||||
|
}
|
||||||
|
elsif ($line =~ /ends \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
|
||||||
|
$enddate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
|
||||||
|
}
|
||||||
|
elsif ($line =~ /binding state active/) {
|
||||||
|
if (defined($enddate) && defined($startdate) && defined($lease)) {
|
||||||
|
if ($startdate < time() && $enddate > time()) {
|
||||||
|
push (@activeleases, $lease);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set TZ back to its original setting
|
||||||
|
if (defined($mytz)) {
|
||||||
|
$ENV{'TZ'} = $mytz;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete $ENV{'TZ'};
|
||||||
|
}
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
# Sort the array, strip doubles, and return
|
||||||
|
return grep(!$saw{$_}++, @activeleases);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper routine to convert an IP address a.b.c.d into an integer
|
||||||
|
#
|
||||||
|
# Returns an integer representation of an IP address
|
||||||
|
sub string2ip {
|
||||||
|
my $string = shift;
|
||||||
|
defined($string) || return undef;
|
||||||
|
if ($string =~ /([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)/) {
|
||||||
|
if ($1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $1 << 24 | $2 << 16 | $3 << 8 | $4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns a dotted quad notation of an
|
||||||
|
#
|
||||||
|
sub ip2string {
|
||||||
|
my $ip = shift;
|
||||||
|
defined ($ip) || return undef;
|
||||||
|
return sprintf ("%d.%d.%d.%d", ($ip >> 24) & 0xff, ($ip >> 16) & 0xff, ($ip >> 8) & 0xff, $ip & 0xff);
|
||||||
|
}
|
|
@ -12,6 +12,10 @@
|
||||||
- munin
|
- munin
|
||||||
- packages
|
- packages
|
||||||
|
|
||||||
|
- name: Ensure /usr is still writable
|
||||||
|
include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: Replace localdomain in Munin config
|
- name: Replace localdomain in Munin config
|
||||||
replace:
|
replace:
|
||||||
|
@ -31,6 +35,18 @@
|
||||||
tags:
|
tags:
|
||||||
- munin
|
- munin
|
||||||
|
|
||||||
|
- include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
|
||||||
|
- name: Install some Munin plugins (disabled)
|
||||||
|
copy:
|
||||||
|
src: 'plugins/{{ item }}'
|
||||||
|
dest: '/usr/share/munin/plugins/{{ item }}'
|
||||||
|
loop:
|
||||||
|
- dhcp_pool
|
||||||
|
tags:
|
||||||
|
- munin
|
||||||
|
|
||||||
- name: Ensure some Munin plugins are disabled
|
- name: Ensure some Munin plugins are disabled
|
||||||
file:
|
file:
|
||||||
path: '/etc/munin/plugins/{{ item }}'
|
path: '/etc/munin/plugins/{{ item }}'
|
||||||
|
|
223
nagios-nrpe/files/plugins/check_dhcp_pool
Executable file
223
nagios-nrpe/files/plugins/check_dhcp_pool
Executable file
|
@ -0,0 +1,223 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Rien Broekstra <rien@rename-it.nl>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; version 2 dated June,
|
||||||
|
# 1991.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Configuration variables:
|
||||||
|
#
|
||||||
|
# conffile - path to dhcpd's configuration file (default "/etc/dhcpd.conf")
|
||||||
|
# leasefile - path to dhcpd's leases file (default "/var/lib/dhcp/dhcpd.leases")
|
||||||
|
#
|
||||||
|
|
||||||
|
use POSIX;
|
||||||
|
use Time::Local;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my $CONFFILE = exists $ENV{'conffile'} ? $ENV{'conffile'} : "/etc/dhcp/dhcpd.conf";
|
||||||
|
my $LEASEFILE = exists $ENV{'leasefile'} ? $ENV{'leasefile'} : "/var/lib/dhcp/dhcpd.leases";
|
||||||
|
my $WARNING_LEVEL = 70;
|
||||||
|
my $CRITICAL_LEVEL = 90;
|
||||||
|
|
||||||
|
my (@activeleases, %dhcp_pools, $pool_start, $pool_end, $pool_size, $pool_free, $pool_usage, $pool_status, $label, $lease, $nagios_return_code, $nagios_ok, $nagios_warning, $nagios_critical, @nagios_text, @nagios_perfdata);
|
||||||
|
|
||||||
|
# Determine all leased IP addresses
|
||||||
|
@activeleases = determine_active_leases();
|
||||||
|
|
||||||
|
# Determine the available IP pools
|
||||||
|
%dhcp_pools = determine_pools();
|
||||||
|
|
||||||
|
# Nagios return code
|
||||||
|
$nagios_return_code = 0;
|
||||||
|
$nagios_ok = 0;
|
||||||
|
$nagios_warning = 0;
|
||||||
|
$nagios_critical = 0;
|
||||||
|
|
||||||
|
# For each pool, count how many leases from that pool are currently active
|
||||||
|
foreach $pool_start (keys %dhcp_pools) {
|
||||||
|
$pool_size = $dhcp_pools{$pool_start};
|
||||||
|
$pool_end = $pool_start+$pool_size-1;
|
||||||
|
$pool_free = $pool_size;
|
||||||
|
|
||||||
|
foreach $lease (@activeleases) {
|
||||||
|
if ($lease >= $pool_start && $lease <= $pool_end) {
|
||||||
|
$pool_free--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$label = ip2string($pool_start)."-".ip2string($pool_end);
|
||||||
|
$pool_usage = sprintf("%.1f", 100*($pool_size-$pool_free)/$pool_size);
|
||||||
|
|
||||||
|
if ($pool_usage >= $CRITICAL_LEVEL) {
|
||||||
|
$nagios_return_code = 2;
|
||||||
|
$nagios_critical++;
|
||||||
|
$pool_status = "CRITICAL";
|
||||||
|
} elsif ($pool_usage >= $WARNING_LEVEL) {
|
||||||
|
if ($nagios_return_code == 0 ) {
|
||||||
|
$nagios_return_code = 1;
|
||||||
|
}
|
||||||
|
$nagios_warning++;
|
||||||
|
$pool_status = "WARNING";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$nagios_ok++;
|
||||||
|
$pool_status = "OK";
|
||||||
|
}
|
||||||
|
|
||||||
|
push(@nagios_text, "$pool_status : $label - $pool_usage \n");
|
||||||
|
push(@nagios_perfdata, "$label=$pool_usage%;$WARNING_LEVEL%;$CRITICAL_LEVEL%;;" );
|
||||||
|
# 'label'=value[UOM];[warn];[crit];;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
print nagios_code_2_txt($nagios_return_code)." - ".$nagios_critical." CRIT / ".$nagios_warning." WARN / ".$nagios_ok." OK \n\n";
|
||||||
|
|
||||||
|
print grep(/CRITICAL/, @nagios_text);
|
||||||
|
print grep(/WARNING/, @nagios_text);
|
||||||
|
print grep(/OK/, @nagios_text);
|
||||||
|
|
||||||
|
print "|@nagios_perfdata";
|
||||||
|
|
||||||
|
exit $nagios_return_code;
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
###### FUNCTIONS
|
||||||
|
|
||||||
|
# Parse dhcpd.conf for range statements.
|
||||||
|
#
|
||||||
|
# Returns a hash with start IP -> size
|
||||||
|
sub determine_pools {
|
||||||
|
my (%pools, @conffile, $line, $start, $end, $size);
|
||||||
|
|
||||||
|
open(CONFFILE, "<${CONFFILE}") || exit -1;
|
||||||
|
@conffile = <CONFFILE>;
|
||||||
|
close (CONFFILE);
|
||||||
|
|
||||||
|
foreach $line (@conffile) {
|
||||||
|
next if $line =~ /^\s*#/;
|
||||||
|
|
||||||
|
if ($line =~ /range[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
|
||||||
|
$start = string2ip($1);
|
||||||
|
$end = string2ip($2);
|
||||||
|
|
||||||
|
defined($start) || next;
|
||||||
|
defined($end) || next;
|
||||||
|
|
||||||
|
# The range statement gives the lowest and highest IP addresses in a range.
|
||||||
|
$size = $end - $start + 1;
|
||||||
|
|
||||||
|
$pools{$start} = $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return %pools;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Very simple parser for dhcpd.leases. This will break very easily if dhcpd decides to
|
||||||
|
# format the file differently. Ideally a simple recursive-descent parser should be used.
|
||||||
|
#
|
||||||
|
# Returns an array with currently leased IP's
|
||||||
|
sub determine_active_leases {
|
||||||
|
my (@leasefile, $startdate, $enddate, $lease, @activeleases, $mytz, $line, %saw);
|
||||||
|
|
||||||
|
open(LEASEFILE, "<${LEASEFILE}") || exit -1;
|
||||||
|
@leasefile = <LEASEFILE>;
|
||||||
|
close (LEASEFILE);
|
||||||
|
|
||||||
|
@activeleases = ();
|
||||||
|
|
||||||
|
# Portable way of converting a GMT date/time string to timestamp is setting TZ to UTC, and then calling mktime()
|
||||||
|
$mytz = $ENV{'TZ'};
|
||||||
|
$ENV{'TZ'} = 'UTC 0';
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
foreach $line (@leasefile) {
|
||||||
|
if ($line =~ /lease ([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
|
||||||
|
$lease = string2ip($1);
|
||||||
|
defined($lease) || next;
|
||||||
|
|
||||||
|
undef $startdate;
|
||||||
|
undef $enddate;
|
||||||
|
}
|
||||||
|
elsif ($line =~ /starts \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
|
||||||
|
$startdate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
|
||||||
|
}
|
||||||
|
elsif ($line =~ /ends \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
|
||||||
|
$enddate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
|
||||||
|
}
|
||||||
|
elsif ($line =~ /binding state active/) {
|
||||||
|
if (defined($enddate) && defined($startdate) && defined($lease)) {
|
||||||
|
if ($startdate < time() && $enddate > time()) {
|
||||||
|
push (@activeleases, $lease);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set TZ back to its original setting
|
||||||
|
if (defined($mytz)) {
|
||||||
|
$ENV{'TZ'} = $mytz;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete $ENV{'TZ'};
|
||||||
|
}
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
# Sort the array, strip doubles, and return
|
||||||
|
return grep(!$saw{$_}++, @activeleases);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helper routine to convert an IP address a.b.c.d into an integer
|
||||||
|
#
|
||||||
|
# Returns an integer representation of an IP address
|
||||||
|
sub string2ip {
|
||||||
|
my $string = shift;
|
||||||
|
defined($string) || return undef;
|
||||||
|
if ($string =~ /([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)/) {
|
||||||
|
if ($1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $1 << 24 | $2 << 16 | $3 << 8 | $4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Returns a dotted quad notation of an
|
||||||
|
#
|
||||||
|
sub ip2string {
|
||||||
|
my $ip = shift;
|
||||||
|
defined ($ip) || return undef;
|
||||||
|
return sprintf ("%d.%d.%d.%d", ($ip >> 24) & 0xff, ($ip >> 16) & 0xff, ($ip >> 8) & 0xff, $ip & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Return textual status of return code
|
||||||
|
#
|
||||||
|
sub nagios_code_2_txt{
|
||||||
|
my $code = shift;
|
||||||
|
defined ($code) || return undef;
|
||||||
|
|
||||||
|
if($code == 0 ) { return "OK" }
|
||||||
|
elsif( $code == 1 ) { return "WARNING" }
|
||||||
|
elsif( $code == 2 ) { return "CRITICAL" }
|
||||||
|
}
|
|
@ -1,30 +1,40 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Verify that given mountpoints have 'read-write' option.
|
||||||
|
|
||||||
output=$(mktemp --tmpdir $(basename $0).XXXXXXXXXX)
|
output=$(mktemp --tmpdir $(basename "$0").XXXXXXXXXX)
|
||||||
critical_count=0
|
critical_count=0
|
||||||
ok_count=0
|
ok_count=0
|
||||||
|
|
||||||
trap "rm -f $output" EXIT
|
trap "rm -f $output" EXIT
|
||||||
|
|
||||||
for mountpoint in $@; do
|
for mountpoint in $@; do
|
||||||
|
# We verify no mointpoints have 'read-only' option instead of checking
|
||||||
|
# for 'read-write' option, because there could be multiple device
|
||||||
|
# mounted on a sigle path. In that edge case only checking for the
|
||||||
|
# presence of the 'read-write' option would yeild a flase positive.
|
||||||
if findmnt -O ro --noheadings "$mountpoint" 1>/dev/null 2>&1; then
|
if findmnt -O ro --noheadings "$mountpoint" 1>/dev/null 2>&1; then
|
||||||
echo "CRITICAL - $mountpoint" >> "$output"
|
echo "CRITICAL - $mountpoint" >> "$output"
|
||||||
critical_count=$(( critical_count + 1))
|
critical_count=$(( critical_count + 1))
|
||||||
else
|
else
|
||||||
echo "OK - $mountpoint" >> "$output"
|
echo "OK - $mountpoint" >> "$output"
|
||||||
ok_count=$(( ok_count + 1))
|
ok_count=$(( ok_count + 1))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
total_count=$(( ok_count + critical_count ))
|
total_count=$(( ok_count + critical_count ))
|
||||||
|
|
||||||
|
plural=''
|
||||||
|
test "$total_count" -gt 1 && plural='s'
|
||||||
|
|
||||||
if [ $ok_count -eq $total_count ]; then
|
if [ $ok_count -eq $total_count ]; then
|
||||||
printf "OK - %d/%d no read-only mountpoint\n\n" "$ok_count" "$total_count"
|
printf "OK - %d/%d mountpoint%s have 'read-write' option\n\n" \
|
||||||
|
"$ok_count" "$total_count" "$plural"
|
||||||
cat "$output"
|
cat "$output"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
printf "CRITICAL - %d/%d read-only mountpoint\n\n" "$critical_count" "$total_count"
|
printf "CRITICAL - %d/%d mountpoint%s don't have 'read-write' option\n\n" \
|
||||||
|
"$critical_count" "$total_count" "$plural"
|
||||||
cat "$output"
|
cat "$output"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ command[check_bkctld_jails]=sudo /usr/sbin/bkctld check-jails
|
||||||
command[check_bkctld]=sudo /usr/sbin/bkctld check
|
command[check_bkctld]=sudo /usr/sbin/bkctld check
|
||||||
command[check_postgrey]=/usr/lib/nagios/plugins/check_tcp -p10023
|
command[check_postgrey]=/usr/lib/nagios/plugins/check_tcp -p10023
|
||||||
command[check_influxdb]=/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -u /health -p 8086 -r '"status":"pass"'
|
command[check_influxdb]=/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -u /health -p 8086 -r '"status":"pass"'
|
||||||
|
command[check_dhcpd]=/usr/lib/nagios/plugins/check_procs -c1:1 -C dhcpd -t 60
|
||||||
|
|
||||||
# Local checks (not packaged)
|
# Local checks (not packaged)
|
||||||
command[check_mem]={{ nagios_plugins_directory }}/check_mem -f -C -w 20 -c 10
|
command[check_mem]={{ nagios_plugins_directory }}/check_mem -f -C -w 20 -c 10
|
||||||
|
@ -83,6 +84,7 @@ command[check_php-fpm80]=sudo {{ nagios_plugins_directory }}/check_phpfpm_multi
|
||||||
command[check_php-fpm81]=sudo {{ nagios_plugins_directory }}/check_phpfpm_multi /var/lib/lxc/php81/rootfs/etc/php/8.1/fpm/pool.d/
|
command[check_php-fpm81]=sudo {{ nagios_plugins_directory }}/check_phpfpm_multi /var/lib/lxc/php81/rootfs/etc/php/8.1/fpm/pool.d/
|
||||||
command[check_ipmi_sensors]=sudo /usr/lib/nagios/plugins/check_ipmi_sensor
|
command[check_ipmi_sensors]=sudo /usr/lib/nagios/plugins/check_ipmi_sensor
|
||||||
command[check_raid_status]=/usr/lib/nagios/plugins/check_raid
|
command[check_raid_status]=/usr/lib/nagios/plugins/check_raid
|
||||||
|
command[check_dhcp_pool]={{ nagios_plugins_directory }}/check_dhcp_pool
|
||||||
|
|
||||||
# Check HTTP "many". Use this to check many websites (http, https, ports, sockets and SSL certificates).
|
# Check HTTP "many". Use this to check many websites (http, https, ports, sockets and SSL certificates).
|
||||||
# Beware! All checks must not take more than 10s!
|
# Beware! All checks must not take more than 10s!
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Evolix default customizations
|
# Evolix default customizations
|
||||||
|
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
server_names_hash_max_size 512;
|
server_names_hash_max_size 512;
|
||||||
server_names_hash_bucket_size 128;
|
server_names_hash_bucket_size 128;
|
||||||
|
|
|
@ -10,7 +10,7 @@ domain="$(echo "$1"|xargs)"
|
||||||
|
|
||||||
if [ ! -f "/etc/ssl/private/dkim-${servername}.private" ]; then
|
if [ ! -f "/etc/ssl/private/dkim-${servername}.private" ]; then
|
||||||
echo "Generate DKIM keys ..."
|
echo "Generate DKIM keys ..."
|
||||||
opendkim-genkey -D /etc/ssl/private/ -r -d "${domain}" -s "dkim-${servername}"
|
opendkim-genkey -h sha256 -b 4096 -D /etc/ssl/private/ -r -d "${domain}" -s "dkim-${servername}"
|
||||||
chown opendkim:opendkim "/etc/ssl/private/dkim-${servername}.private"
|
chown opendkim:opendkim "/etc/ssl/private/dkim-${servername}.private"
|
||||||
chmod 640 "/etc/ssl/private/dkim-${servername}.private"
|
chmod 640 "/etc/ssl/private/dkim-${servername}.private"
|
||||||
mv "/etc/ssl/private/dkim-${servername}.txt" "/etc/ssl/certs/"
|
mv "/etc/ssl/private/dkim-${servername}.txt" "/etc/ssl/certs/"
|
||||||
|
|
|
@ -23,6 +23,6 @@ Then, you can use `shellpki` to generate client certificates.
|
||||||
* `openvpn_netmask`: netmask of the network to use for OpenVPN
|
* `openvpn_netmask`: netmask of the network to use for OpenVPN
|
||||||
* `openvpn_netmask_cidr`: automatically generated prefix length of the netmask, in CIDR notation
|
* `openvpn_netmask_cidr`: automatically generated prefix length of the netmask, in CIDR notation
|
||||||
|
|
||||||
## TODO
|
## Dependencies
|
||||||
|
|
||||||
* See TODO tasks in tasks/*.yml
|
* Files in `files/shellpki/*` are gotten from the upstream [shellpki](https://gitea.evolix.org/evolix/shellpki) and must be updated when the upstream is.
|
||||||
|
|
26
openvpn/files/shellpki/cert-expirations.sh
Normal file
26
openvpn/files/shellpki/cert-expirations.sh
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
carp=$(/sbin/ifconfig carp0 2>/dev/null | grep 'status' | cut -d' ' -f2)
|
||||||
|
|
||||||
|
if [ "$carp" = "backup" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Warning : all times are in UTC !\n"
|
||||||
|
|
||||||
|
echo "CA certificate:"
|
||||||
|
openssl x509 -enddate -noout -in /etc/shellpki/cacert.pem \
|
||||||
|
| cut -d '=' -f 2 \
|
||||||
|
| sed -e "s/^\(.*\)\ \(20..\).*/- \2 \1/"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Client certificates:"
|
||||||
|
cat /etc/shellpki/index.txt \
|
||||||
|
| grep ^V \
|
||||||
|
| awk -F "/" '{print $1,$5}' \
|
||||||
|
| awk '{print $2,$5}' \
|
||||||
|
| sed 's/CN=//' \
|
||||||
|
| sed -E 's/([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})Z (.*)/- 20\1 \2 \3 \4:\5:\6 \7/' \
|
||||||
|
| awk '{if ($3 == "01") $3="Jan"; else if ($3 == "02") $3="Feb"; else if ($3 == "03") $3="Mar"; else if ($3 == "04") $3="Apr"; else if ($3 == "05") $3="May"; else if ($3 == "06") $3="Jun"; else if ($3 == "07") $3="Jul"; else if ($3 == "08") $3="Aug"; else if ($3 == "09") $3="Sep"; else if ($3 == "10") $3="Oct"; else if ($3 == "11") $3="Nov"; else if ($3 == "12") $3="Dec"; print $0;}' \
|
||||||
|
| sort -n -k 2 -k 3M -k 4
|
58
openvpn/files/shellpki/openssl.cnf
Normal file
58
openvpn/files/shellpki/openssl.cnf
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default
|
||||||
|
|
||||||
|
[ CA_default ]
|
||||||
|
dir = /etc/shellpki
|
||||||
|
certs = $dir/certs
|
||||||
|
new_certs_dir = $dir/tmp
|
||||||
|
database = $dir/index.txt
|
||||||
|
certificate = $dir/cacert.pem
|
||||||
|
serial = $dir/serial
|
||||||
|
crl = $dir/crl.pem
|
||||||
|
private_key = $dir/cakey.key
|
||||||
|
RANDFILE = $dir/.rand
|
||||||
|
default_days = 365
|
||||||
|
default_crl_days= 365
|
||||||
|
default_md = sha256
|
||||||
|
preserve = no
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = supplied
|
||||||
|
stateOrProvinceName = supplied
|
||||||
|
organizationName = supplied
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = supplied
|
||||||
|
emailAddress = supplied
|
||||||
|
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
[ v3_ocsp ]
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
extendedKeyUsage = OCSPSigning
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = FR
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
stateOrProvinceName = State or Province
|
||||||
|
stateOrProvinceName_default = 13
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
localityName_default = Marseille
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Evolix
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
commonName = Common Name (eg, your name or your server\'s hostname)
|
||||||
|
commonName_max = 64
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_default = security@evolix.net
|
||||||
|
emailAddress_max = 40
|
1106
openvpn/files/shellpki/shellpki
Executable file
1106
openvpn/files/shellpki/shellpki
Executable file
|
@ -0,0 +1,1106 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# shellpki is a wrapper around OpenSSL to manage a small PKI
|
||||||
|
#
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
VERSION="22.04"
|
||||||
|
|
||||||
|
show_version() {
|
||||||
|
cat <<END
|
||||||
|
shellpki version ${VERSION}
|
||||||
|
|
||||||
|
Copyright 2010-2022 Evolix <info@evolix.fr>,
|
||||||
|
Thomas Martin <tmartin@evolix.fr>,
|
||||||
|
Gregory Colpart <reg@evolix.fr>,
|
||||||
|
Romain Dessort <rdessort@evolix.fr>,
|
||||||
|
Benoit Série <bserie@evolix.fr>,
|
||||||
|
Victor Laborie <vlaborie@evolix.fr>,
|
||||||
|
Daniel Jakots <djakots@evolix.fr>,
|
||||||
|
Patrick Marchand <pmarchand@evolix.fr>,
|
||||||
|
Jérémy Lecour <jlecour@evolix.fr>,
|
||||||
|
Jérémy Dubois <jdubois@evolix.fr>
|
||||||
|
and others.
|
||||||
|
|
||||||
|
shellpki comes with ABSOLUTELY NO WARRANTY. This is free software,
|
||||||
|
and you are welcome to redistribute it under certain conditions.
|
||||||
|
See the MIT Licence for details.
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: ${0} <subcommand> [options] [CommonName]
|
||||||
|
Warning: [options] always must be before [CommonName] and after <subcommand>
|
||||||
|
|
||||||
|
EOF
|
||||||
|
show_usage_init
|
||||||
|
show_usage_create
|
||||||
|
show_usage_revoke
|
||||||
|
show_usage_list
|
||||||
|
show_usage_check
|
||||||
|
show_usage_ocsp
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Show version :
|
||||||
|
|
||||||
|
${0} --version
|
||||||
|
|
||||||
|
Show help :
|
||||||
|
|
||||||
|
${0} --help
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_init() {
|
||||||
|
cat <<EOF
|
||||||
|
Initialize PKI (create CA key and self-signed certificate) :
|
||||||
|
|
||||||
|
${0} init [options] <commonName_for_CA>
|
||||||
|
|
||||||
|
Options
|
||||||
|
--non-interactive do not prompt the user, and exit if an error occurs
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_create() {
|
||||||
|
cat <<EOF
|
||||||
|
Create a client certificate with key and CSR directly generated on server :
|
||||||
|
|
||||||
|
${0} create [options] <commonName>
|
||||||
|
|
||||||
|
Options
|
||||||
|
-f, --file, --csr-file create a client certificate from a CSR (doesn't need key)
|
||||||
|
-p, --password prompt the user for a password to set on the client key
|
||||||
|
--password-file if provided with a path to a readable file, the first line is read and set as password on the client key
|
||||||
|
--days specify how many days the certificate should be valid
|
||||||
|
--end-date specify until which date the certificate should be valid, in "YYYY/MM/DD hh:mm:ss" format, UTC +0
|
||||||
|
--non-interactive do not prompt the user, and exit if an error occurs
|
||||||
|
--replace-existing if the certificate already exists, revoke it before creating a new one
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_revoke() {
|
||||||
|
cat <<EOF
|
||||||
|
Revoke a client certificate :
|
||||||
|
|
||||||
|
${0} revoke [options] <commonName>
|
||||||
|
|
||||||
|
Options
|
||||||
|
--non-interactive do not prompt the user, and exit if an error occurs
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_list() {
|
||||||
|
cat <<EOF
|
||||||
|
List certificates :
|
||||||
|
|
||||||
|
${0} list <options>
|
||||||
|
|
||||||
|
Options
|
||||||
|
-a, --all list all certificates: valid and revoked ones
|
||||||
|
-v, --valid list all valid certificates
|
||||||
|
-r, --revoked list all revoked certificates
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_check() {
|
||||||
|
cat <<EOF
|
||||||
|
Check expiration date of valid certificates :
|
||||||
|
|
||||||
|
${0} check
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
show_usage_ocsp() {
|
||||||
|
cat <<EOF
|
||||||
|
Run OCSP_D server :
|
||||||
|
|
||||||
|
${0} ocsp <ocsp_uri:ocsp_port>
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo "${1}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo "${1}" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_ca_password() {
|
||||||
|
"${OPENSSL_BIN}" rsa \
|
||||||
|
-in "${CA_KEY}" \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
}
|
||||||
|
get_real_path() {
|
||||||
|
# --canonicalize is supported on Linux
|
||||||
|
# -f is supported on Linux and OpenBSD
|
||||||
|
readlink -f -- "${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
ask_ca_password() {
|
||||||
|
attempt=${1:-0}
|
||||||
|
max_attempts=3
|
||||||
|
|
||||||
|
trap 'unset CA_PASSWORD' 0
|
||||||
|
|
||||||
|
if [ ! -f "${CA_KEY}" ]; then
|
||||||
|
error "You must initialize your PKI with \`shellpki init' !"
|
||||||
|
fi
|
||||||
|
if [ "${attempt}" -gt 0 ]; then
|
||||||
|
warning "Invalid password, retry."
|
||||||
|
fi
|
||||||
|
if [ "${attempt}" -ge "${max_attempts}" ]; then
|
||||||
|
error "Maximum number of attempts reached (${max_attempts})."
|
||||||
|
fi
|
||||||
|
if [ -z "${CA_PASSWORD:-}" ]; then
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
error "In non-interactive mode, you must pass CA_PASSWORD as environment variable"
|
||||||
|
fi
|
||||||
|
stty -echo
|
||||||
|
printf "Password for CA key: "
|
||||||
|
read -r CA_PASSWORD
|
||||||
|
stty echo
|
||||||
|
printf "\n"
|
||||||
|
fi
|
||||||
|
if [ -z "${CA_PASSWORD:-}" ] || ! verify_ca_password; then
|
||||||
|
unset CA_PASSWORD
|
||||||
|
attempt=$(( attempt + 1 ))
|
||||||
|
ask_ca_password "${attempt}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
ask_user_password() {
|
||||||
|
trap 'unset PASSWORD' 0
|
||||||
|
|
||||||
|
if [ -z "${PASSWORD:-}" ]; then
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
error "In non-interactive mode, you must pass PASSWORD as environment variable or use --password-file"
|
||||||
|
fi
|
||||||
|
stty -echo
|
||||||
|
printf "Password for user key: "
|
||||||
|
read -r PASSWORD
|
||||||
|
stty echo
|
||||||
|
printf "\n"
|
||||||
|
fi
|
||||||
|
if [ -z "${PASSWORD:-}" ]; then
|
||||||
|
warning "Warning: empty password from input"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
replace_existing_or_abort() {
|
||||||
|
cn=${1:?}
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
if [ "${replace_existing}" -eq 1 ]; then
|
||||||
|
revoke --non-interactive "${cn}"
|
||||||
|
else
|
||||||
|
error "${cn} already exists, use \`--replace-existing' to force"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "${replace_existing}" -eq 1 ]; then
|
||||||
|
revoke "${cn}"
|
||||||
|
else
|
||||||
|
printf "%s already exists, do you want to revoke and recreate it ? [y/N] " "${cn}"
|
||||||
|
read -r REPLY
|
||||||
|
resp=$(echo "${REPLY}" | tr 'Y' 'y')
|
||||||
|
|
||||||
|
if [ "${resp}" = "y" ]; then
|
||||||
|
revoke "${cn}"
|
||||||
|
else
|
||||||
|
error "Aborted"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
umask 0177
|
||||||
|
|
||||||
|
[ -d "${CA_DIR}" ] || mkdir -m 0750 "${CA_DIR}"
|
||||||
|
[ -d "${CRT_DIR}" ] || mkdir -m 0750 "${CRT_DIR}"
|
||||||
|
[ -f "${INDEX_FILE}" ] || touch "${INDEX_FILE}"
|
||||||
|
[ -f "${CRL}" ] || touch "${CRL}"
|
||||||
|
[ -f "${SERIAL}" ] || echo "01" > "${SERIAL}"
|
||||||
|
|
||||||
|
non_interactive=0
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||||
|
while :; do
|
||||||
|
case ${1:-} in
|
||||||
|
--non-interactive)
|
||||||
|
non_interactive=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
# End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
# ignore unknown options
|
||||||
|
warning "Warning: unknown option (ignored): \`$1'"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case: If no more options then break out of the loop.
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
cn="${1:-}"
|
||||||
|
if [ -z "${cn}" ]; then
|
||||||
|
show_usage_init >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${CA_KEY}" ]; then
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
error "${CA_KEY} already exists, erase it manually if you want to start over."
|
||||||
|
else
|
||||||
|
printf "%s already exists, do you really want to erase it ? [y/N] " "${CA_KEY}"
|
||||||
|
read -r REPLY
|
||||||
|
resp=$(echo "${REPLY}" | tr 'Y' 'y')
|
||||||
|
if [ "${resp}" = "y" ]; then
|
||||||
|
rm -f "${CA_KEY}" "${CA_CERT}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
passout_arg=""
|
||||||
|
if [ -n "${CA_PASSWORD:-}" ]; then
|
||||||
|
passout_arg="-passout pass:${CA_PASSWORD}"
|
||||||
|
elif [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
error "In non-interactive mode, you must pass CA_PASSWORD as environment variable."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${CA_KEY}" ]; then
|
||||||
|
"${OPENSSL_BIN}" genrsa \
|
||||||
|
-out "${CA_KEY}" \
|
||||||
|
${passout_arg} \
|
||||||
|
-aes256 \
|
||||||
|
"${CA_KEY_LENGTH}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the CA key"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${CA_CERT}" ]; then
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
error "${CA_CERT} already exists, erase it manually if you want to start over."
|
||||||
|
else
|
||||||
|
printf "%s already exists, do you really want to erase it ? [y/N] " "${CA_CERT}"
|
||||||
|
read -r REPLY
|
||||||
|
resp=$(echo "${REPLY}" | tr 'Y' 'y')
|
||||||
|
if [ "${resp}" = "y" ]; then
|
||||||
|
rm "${CA_CERT}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${CA_CERT}" ]; then
|
||||||
|
ask_ca_password 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${CA_CERT}" ]; then
|
||||||
|
"${OPENSSL_BIN}" req \
|
||||||
|
-new \
|
||||||
|
-batch \
|
||||||
|
-sha512 \
|
||||||
|
-x509 \
|
||||||
|
-days 3650 \
|
||||||
|
-extensions v3_ca \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
-key "${CA_KEY}" \
|
||||||
|
-out "${CA_CERT}" \
|
||||||
|
-config /dev/stdin <<EOF
|
||||||
|
$(cat "${CONF_FILE}")
|
||||||
|
commonName_default = ${cn}
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the CA certificate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
-config "${CONF_FILE}" \
|
||||||
|
-passin pass:${CA_PASSWORD} \
|
||||||
|
-gencrl \
|
||||||
|
-out "${CRL}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp() {
|
||||||
|
umask 0177
|
||||||
|
|
||||||
|
ocsp_uri="${1:-}"
|
||||||
|
if [ -z "${ocsp_uri}" ]; then
|
||||||
|
show_usage_ocsp >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ocsp_csr_file="${CSR_DIR}/ocsp.csr"
|
||||||
|
|
||||||
|
url=$(echo "${ocsp_uri}" | cut -d':' -f1)
|
||||||
|
port=$(echo "${ocsp_uri}" | cut -d':' -f2)
|
||||||
|
|
||||||
|
if [ ! -f "${OCSP_KEY}" ]; then
|
||||||
|
"${OPENSSL_BIN}" genrsa \
|
||||||
|
-out "${OCSP_KEY}" \
|
||||||
|
"${KEY_LENGTH}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the OCSP key"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${OPENSSL_BIN}" req \
|
||||||
|
-batch \
|
||||||
|
-new \
|
||||||
|
-key "${OCSP_KEY}" \
|
||||||
|
-out "${ocsp_csr_file}" \
|
||||||
|
-config /dev/stdin <<EOF
|
||||||
|
$(cat "${CONF_FILE}")
|
||||||
|
commonName_default = ${url}
|
||||||
|
[ usr_cert ]
|
||||||
|
authorityInfoAccess = OCSP;URI:http://${ocsp_uri}
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the OCSP request"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${OCSP_CERT}" ]; then
|
||||||
|
ask_ca_password 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${OCSP_CERT}" ]; then
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
-extensions v3_ocsp \
|
||||||
|
-in "${ocsp_csr_file}" \
|
||||||
|
-out "${OCSP_CERT}" \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
-config "${CONF_FILE}"
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the OCSP certificate"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${OPENSSL_BIN}" ocsp \
|
||||||
|
-ignore_err \
|
||||||
|
-index "${INDEX_FILE}" \
|
||||||
|
-port "${port}" \
|
||||||
|
-rsigner "${OCSP_CERT}" \
|
||||||
|
-rkey "${OCSP_KEY}" \
|
||||||
|
-CA "${CA_CERT}" \
|
||||||
|
-text
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
from_csr=0
|
||||||
|
ask_pass=0
|
||||||
|
non_interactive=0
|
||||||
|
replace_existing=0
|
||||||
|
days=""
|
||||||
|
end_date=""
|
||||||
|
days_set=0
|
||||||
|
end_date_set=0
|
||||||
|
password_set=0
|
||||||
|
password_file_set=0
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||||
|
while :; do
|
||||||
|
case ${1:-} in
|
||||||
|
-f|--file|--csr-file)
|
||||||
|
# csr-file option, with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
from_csr=1
|
||||||
|
csr_file=$(get_real_path "${2}")
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error accessing file \`${2}'"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
error "Argument error: \`--csr-file' requires a value"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--file=?*|--csr-file=?*)
|
||||||
|
from_csr=1
|
||||||
|
# csr-file option, with value separated by =
|
||||||
|
csr_file=$(get_real_path "${1#*=}")
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error accessing file \`${1#*=}'"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--file=|--csr-file=)
|
||||||
|
# csr-file options, without value
|
||||||
|
error "Argument error: \`--csr-file' requires a value"
|
||||||
|
;;
|
||||||
|
-p|--password)
|
||||||
|
ask_pass=1
|
||||||
|
password_set=1
|
||||||
|
;;
|
||||||
|
--password-file)
|
||||||
|
# password-file option, with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
password_file=$(get_real_path "${2}")
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error accessing file \`${2}'"
|
||||||
|
fi
|
||||||
|
password_file_set=1
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
error "Argument error: \`--password-file' requires a value"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--password-file=?*)
|
||||||
|
# password-file option, with value separated by =
|
||||||
|
password_file=$(get_real_path "${1#*=}")
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error accessing file \`${1#*=}'"
|
||||||
|
fi
|
||||||
|
password_file_set=1
|
||||||
|
;;
|
||||||
|
--password-file=)
|
||||||
|
# password-file options, without value
|
||||||
|
error "Argument error: \`--password-file' requires a value"
|
||||||
|
;;
|
||||||
|
--days)
|
||||||
|
# days option, with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
days=${2}
|
||||||
|
days_set=1
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
error "Argument error: \`--days' requires a value"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--days=?*)
|
||||||
|
# days option, with value separated by =
|
||||||
|
days=${1#*=}
|
||||||
|
days_set=1
|
||||||
|
;;
|
||||||
|
--days=)
|
||||||
|
# days options, without value
|
||||||
|
error "Argument error: \`--days' requires a value"
|
||||||
|
;;
|
||||||
|
--end-date)
|
||||||
|
# end-date option, with value separated by space
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
end_date=${2}
|
||||||
|
end_date_set=1
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
error "Argument error: \`--end-date' requires a value"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--end-date=?*)
|
||||||
|
# end-date option, with value separated by =
|
||||||
|
end_date=${1#*=}
|
||||||
|
end_date_set=1
|
||||||
|
;;
|
||||||
|
--end-date=)
|
||||||
|
# end-date options, without value
|
||||||
|
error "Argument error: \`--end-date' requires a value"
|
||||||
|
;;
|
||||||
|
--non-interactive)
|
||||||
|
non_interactive=1
|
||||||
|
;;
|
||||||
|
--replace-existing)
|
||||||
|
replace_existing=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
# End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
# ignore unknown options
|
||||||
|
warning "Warning: unknown option (ignored): \`$1'"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case: If no more options then break out of the loop.
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "${days_set}" -eq 1 ] && [ "${end_date_set}" -eq 1 ]; then
|
||||||
|
error "Argument error: \`--end-date' and \`--days' cannot be used together."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${password_set}" -eq 1 ] && [ "${password_file_set}" -eq 1 ]; then
|
||||||
|
error "Argument error: \`--password' and \`--password-file' cannot be used together."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The name of the certificate
|
||||||
|
cn="${1:-}"
|
||||||
|
|
||||||
|
# Set expiration argument
|
||||||
|
crt_expiration_arg=""
|
||||||
|
if [ -n "${days}" ]; then
|
||||||
|
if [ "${days}" -gt 0 ]; then
|
||||||
|
crt_expiration_arg="-days ${days}"
|
||||||
|
else
|
||||||
|
error "Argument error: \"${days}\" is not a valid value for \`--days'."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -n "${end_date}" ]; then
|
||||||
|
if [ "${SYSTEM}" = "linux" ]; then
|
||||||
|
cert_end_date=$(TZ=:Zulu date --date "${end_date}" +"%Y%m%d%H%M%SZ" 2> /dev/null)
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Invalid end date format: \`${end_date}' can't be parsed by date(1). Expected format: YYYY/MM/DD [hh[:mm[:ss]]]."
|
||||||
|
else
|
||||||
|
crt_expiration_arg="-enddate ${cert_end_date}"
|
||||||
|
fi
|
||||||
|
elif [ "${SYSTEM}" = "openbsd" ]; then
|
||||||
|
cert_end_date=$(TZ=:Zulu date -f "%C%y/%m/%d %H:%M:%S" -j "${end_date}" +"%Y%m%d%H%M%SZ" 2> /dev/null)
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Invalid end date format: \`${end_date}' can't be parsed by date(1). Expected format: YYYY/MM/DD hh:mm:ss."
|
||||||
|
else
|
||||||
|
crt_expiration_arg="-enddate ${cert_end_date}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error "System ${SYSTEM} not supported."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
batch_arg="-batch"
|
||||||
|
else
|
||||||
|
batch_arg=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${from_csr}" -eq 1 ]; then
|
||||||
|
if [ "${ask_pass}" -eq 1 ]; then
|
||||||
|
warning "Warning: -p|--password is ignored with -f|--file|--crt-file"
|
||||||
|
fi
|
||||||
|
if [ -n "${password_file:-}" ]; then
|
||||||
|
warning "Warning: --password-file is ignored with -f|--file|--crt-file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
crt_file="${CRT_DIR}/${cn}.crt"
|
||||||
|
|
||||||
|
# ask for CA passphrase
|
||||||
|
ask_ca_password 0
|
||||||
|
|
||||||
|
# check if csr_file is a CSR
|
||||||
|
"${OPENSSL_BIN}" req \
|
||||||
|
-noout \
|
||||||
|
-subject \
|
||||||
|
-in "${csr_file}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "${csr_file} is not a valid CSR !"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if csr_file contain a CN
|
||||||
|
"${OPENSSL_BIN}" req \
|
||||||
|
-noout \
|
||||||
|
-subject \
|
||||||
|
-in "${csr_file}" \
|
||||||
|
| grep -Eo "CN\s*=[^,/]*" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "${csr_file} doesn't contain a CommonName !"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get CN from CSR
|
||||||
|
cn=$("${OPENSSL_BIN}" req -noout -subject -in "${csr_file}" | grep -Eo "CN\s*=[^,/]*" | cut -d'=' -f2 | xargs)
|
||||||
|
|
||||||
|
# check if CN already exists
|
||||||
|
if [ -f "${crt_file}" ]; then
|
||||||
|
replace_existing_or_abort "${cn}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ca sign and generate cert
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
batch_arg="-batch"
|
||||||
|
else
|
||||||
|
batch_arg=""
|
||||||
|
fi
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
${batch_arg} \
|
||||||
|
-config "${CONF_FILE}" \
|
||||||
|
-in "${csr_file}" \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
-out "${crt_file}" \
|
||||||
|
${crt_expiration_arg}
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the certificate"
|
||||||
|
else
|
||||||
|
echo "The certificate file is available at \`${crt_file}'"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -z "${cn}" ]; then
|
||||||
|
show_usage_create >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
csr_file="${CSR_DIR}/${cn}-${SUFFIX}.csr"
|
||||||
|
crt_file="${CRT_DIR}/${cn}.crt"
|
||||||
|
key_file="${KEY_DIR}/${cn}-${SUFFIX}.key"
|
||||||
|
ovpn_file="${OVPN_DIR}/${cn}-${SUFFIX}.ovpn"
|
||||||
|
pkcs12_file="${PKCS12_DIR}/${cn}-${SUFFIX}.p12"
|
||||||
|
|
||||||
|
# ask for CA passphrase
|
||||||
|
ask_ca_password 0
|
||||||
|
|
||||||
|
if [ "${ask_pass}" -eq 1 ]; then
|
||||||
|
ask_user_password
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if CN already exists
|
||||||
|
if [ -f "${crt_file}" ]; then
|
||||||
|
replace_existing_or_abort "${cn}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# generate private key
|
||||||
|
pass_args=""
|
||||||
|
if [ -n "${password_file:-}" ]; then
|
||||||
|
pass_args="-aes256 -passout file:${password_file}"
|
||||||
|
elif [ -n "${PASSWORD:-}" ]; then
|
||||||
|
pass_args="-aes256 -passout pass:${PASSWORD}"
|
||||||
|
fi
|
||||||
|
"${OPENSSL_BIN}" genrsa \
|
||||||
|
-out "${key_file}" \
|
||||||
|
${pass_args} \
|
||||||
|
"${KEY_LENGTH}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -eq 0 ]; then
|
||||||
|
echo "The KEY file is available at \`${key_file}'"
|
||||||
|
else
|
||||||
|
error "Error generating the private key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# generate csr req
|
||||||
|
pass_args=""
|
||||||
|
if [ -n "${password_file:-}" ]; then
|
||||||
|
pass_args="-passin file:${password_file}"
|
||||||
|
elif [ -n "${PASSWORD:-}" ]; then
|
||||||
|
pass_args="-passin pass:${PASSWORD}"
|
||||||
|
fi
|
||||||
|
"${OPENSSL_BIN}" req \
|
||||||
|
-batch \
|
||||||
|
-new \
|
||||||
|
-key "${key_file}" \
|
||||||
|
-out "${csr_file}" \
|
||||||
|
${pass_args} \
|
||||||
|
-config /dev/stdin <<EOF
|
||||||
|
$(cat "${CONF_FILE}")
|
||||||
|
commonName_default = ${cn}
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the CSR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ca sign and generate cert
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
${batch_arg} \
|
||||||
|
-config "${CONF_FILE}" \
|
||||||
|
-passin pass:${CA_PASSWORD} \
|
||||||
|
-in "${csr_file}" \
|
||||||
|
-out "${crt_file}" \
|
||||||
|
${crt_expiration_arg}
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the certificate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if CRT is a valid
|
||||||
|
"${OPENSSL_BIN}" x509 \
|
||||||
|
-noout \
|
||||||
|
-subject \
|
||||||
|
-in "${crt_file}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
rm -f "${crt_file}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${crt_file}" ]; then
|
||||||
|
error "Error in CSR creation"
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 640 "${crt_file}"
|
||||||
|
|
||||||
|
echo "The CRT file is available in ${crt_file}"
|
||||||
|
|
||||||
|
# generate pkcs12 format
|
||||||
|
pass_args=""
|
||||||
|
if [ -n "${password_file:-}" ]; then
|
||||||
|
# Hack for pkcs12 :
|
||||||
|
# If passin and passout files are the same path, it expects 2 lines
|
||||||
|
# so we make a temporary copy of the password file
|
||||||
|
password_file_out=$(mktemp)
|
||||||
|
cp "${password_file}" "${password_file_out}"
|
||||||
|
pass_args="-passin file:${password_file} -passout file:${password_file_out}"
|
||||||
|
elif [ -n "${PASSWORD:-}" ]; then
|
||||||
|
pass_args="-passin pass:${PASSWORD} -passout pass:${PASSWORD}"
|
||||||
|
else
|
||||||
|
pass_args="-passout pass:"
|
||||||
|
fi
|
||||||
|
"${OPENSSL_BIN}" pkcs12 \
|
||||||
|
-export \
|
||||||
|
-nodes \
|
||||||
|
-inkey "${key_file}" \
|
||||||
|
-in "${crt_file}" \
|
||||||
|
-out "${pkcs12_file}" \
|
||||||
|
${pass_args}
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "Error generating the pkcs12 file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${password_file_out:-}" ]; then
|
||||||
|
# Hack for pkcs12 :
|
||||||
|
# Destroy the temporary file
|
||||||
|
rm -f "${password_file_out}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 640 "${pkcs12_file}"
|
||||||
|
echo "The PKCS12 config file is available at \`${pkcs12_file}'"
|
||||||
|
|
||||||
|
# generate openvpn format
|
||||||
|
if [ -e "${CA_DIR}/ovpn.conf" ]; then
|
||||||
|
cat "${CA_DIR}/ovpn.conf" - > "${ovpn_file}" <<EOF
|
||||||
|
<ca>
|
||||||
|
$(cat "${CA_CERT}")
|
||||||
|
</ca>
|
||||||
|
|
||||||
|
<cert>
|
||||||
|
$(cat "${crt_file}")
|
||||||
|
</cert>
|
||||||
|
|
||||||
|
<key>
|
||||||
|
$(cat "${key_file}")
|
||||||
|
</key>
|
||||||
|
EOF
|
||||||
|
chmod 640 "${ovpn_file}"
|
||||||
|
echo "The OpenVPN config file is available at \`${ovpn_file}'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy files if destination exists
|
||||||
|
if [ -d "${COPY_DIR}" ]; then
|
||||||
|
for file in "${crt_file}" "${key_file}" "${pkcs12_file}" "${ovpn_file}"; do
|
||||||
|
if [ -f "${file}" ]; then
|
||||||
|
new_file="${COPY_DIR}/$(basename "${file}")"
|
||||||
|
if [ "${replace_existing}" -eq 1 ]; then
|
||||||
|
cp -f "${file}" "${COPY_DIR}/"
|
||||||
|
else
|
||||||
|
if [ "${non_interactive}" -eq 1 ]; then
|
||||||
|
if [ -f "${new_file}" ]; then
|
||||||
|
echo "File \`${file}' has not been copied to \`${new_file}', it already exists" >&2
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
cp "${file}" "${COPY_DIR}/"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cp -i "${file}" "${COPY_DIR}/"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "File \`${file}' has been copied to \`${new_file}'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
chown -R ${PKI_USER}:${PKI_USER} "${COPY_DIR}/"
|
||||||
|
chmod -R u=rwX,g=rwX,o= "${COPY_DIR}/"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
revoke() {
|
||||||
|
non_interactive=0
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||||
|
while :; do
|
||||||
|
case ${1:-} in
|
||||||
|
--non-interactive)
|
||||||
|
non_interactive=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
# End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
# ignore unknown options
|
||||||
|
warning "Warning: unknown option (ignored): \`$1'"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default case: If no more options then break out of the loop.
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# The name of the certificate
|
||||||
|
cn="${1:-}"
|
||||||
|
|
||||||
|
if [ -z "${cn}" ]; then
|
||||||
|
show_usage_revoke >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
crt_file="${CRT_DIR}/${cn}.crt"
|
||||||
|
# check if CRT exists
|
||||||
|
if [ ! -f "${crt_file}" ]; then
|
||||||
|
error "Unknow CN: ${cn} (\`${crt_file}' not found)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if CRT is a valid
|
||||||
|
"${OPENSSL_BIN}" x509 \
|
||||||
|
-noout \
|
||||||
|
-subject \
|
||||||
|
-in "${crt_file}" \
|
||||||
|
>/dev/null 2>&1
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -ne 0 ]; then
|
||||||
|
error "${crt_file} is not a valid CRT, you must delete it !"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ask for CA passphrase
|
||||||
|
ask_ca_password 0
|
||||||
|
|
||||||
|
echo "Revoke certificate ${crt_file} :"
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
-config "${CONF_FILE}" \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
-revoke "${crt_file}"
|
||||||
|
# shellcheck disable=SC2181
|
||||||
|
if [ "$?" -eq 0 ]; then
|
||||||
|
rm "${crt_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${OPENSSL_BIN}" ca \
|
||||||
|
-config "${CONF_FILE}" \
|
||||||
|
-passin pass:"${CA_PASSWORD}" \
|
||||||
|
-gencrl \
|
||||||
|
-out "${CRL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
if [ ! -f "${INDEX_FILE}" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
show_usage_list >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case "${1:-}" in
|
||||||
|
-a|--all)
|
||||||
|
list_valid=0
|
||||||
|
list_revoked=0
|
||||||
|
;;
|
||||||
|
-v|--valid)
|
||||||
|
list_valid=0
|
||||||
|
list_revoked=1
|
||||||
|
;;
|
||||||
|
-r|--revoked)
|
||||||
|
list_valid=1
|
||||||
|
list_revoked=0
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
warning "unknow option ${1} (ignored)"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "${list_valid}" -eq 0 ]; then
|
||||||
|
certs=$(grep "^V" "${INDEX_FILE}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${list_revoked}" -eq 0 ]; then
|
||||||
|
certs=$(grep "^R" "${INDEX_FILE}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${list_valid}" -eq 0 ] && [ "${list_revoked}" -eq 0 ]; then
|
||||||
|
certs=$(cat "${INDEX_FILE}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${certs}" | grep -Eo "CN\s*=[^,/]*" | cut -d'=' -f2 | xargs -n1
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_end_date() {
|
||||||
|
"${OPENSSL_BIN}" x509 -noout -enddate -in "${1}" | cut -d'=' -f2
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
# default expiration alert
|
||||||
|
# TODO: permit override with parameters
|
||||||
|
min_day=90
|
||||||
|
cur_epoch=$(date -u +'%s')
|
||||||
|
|
||||||
|
for cert in "${CRT_DIR}"/*; do
|
||||||
|
end_date=$(cert_end_date "${cert}")
|
||||||
|
end_epoch=$(date -ud "${end_date}" +'%s')
|
||||||
|
diff_epoch=$(( end_epoch - cur_epoch ))
|
||||||
|
diff_day=$(( diff_epoch / 60 / 60 / 24 ))
|
||||||
|
if [ "${diff_day}" -lt "${min_day}" ]; then
|
||||||
|
if [ "${diff_day}" -le 0 ]; then
|
||||||
|
echo "${cert} has expired"
|
||||||
|
else
|
||||||
|
echo "${cert} expire in ${diff_day} days"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
is_user() {
|
||||||
|
getent passwd "${1}" >/dev/null
|
||||||
|
}
|
||||||
|
is_group() {
|
||||||
|
getent group "${1}" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
# Know what system we are on, because OpenBSD and Linux do not implement date(1) in the same way
|
||||||
|
SYSTEM=$(uname | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
# default config
|
||||||
|
# TODO: override with /etc/default/shellpki
|
||||||
|
CONF_FILE="/etc/shellpki/openssl.cnf"
|
||||||
|
|
||||||
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
|
PKI_USER="_shellpki"
|
||||||
|
else
|
||||||
|
PKI_USER="shellpki"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${USER}" != "root" ] && [ "${USER}" != "${PKI_USER}" ]; then
|
||||||
|
error "Please become root before running ${0} !"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# retrieve CA path from config file
|
||||||
|
CA_DIR=$(grep -E "^dir" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1)
|
||||||
|
CA_KEY=$(grep -E "^private_key" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
CA_CERT=$(grep -E "^certificate" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
OCSP_KEY="${CA_DIR}/ocsp.key"
|
||||||
|
OCSP_CERT="${CA_DIR}/ocsp.pem"
|
||||||
|
CRT_DIR=$(grep -E "^certs" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
TMP_DIR=$(grep -E "^new_certs_dir" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
INDEX_FILE=$(grep -E "^database" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
SERIAL=$(grep -E "^serial" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
CRL=$(grep -E "^crl" "${CONF_FILE}" | cut -d'=' -f2 | xargs -n1 | sed "s~\$dir~${CA_DIR}~")
|
||||||
|
|
||||||
|
# directories for clients key, csr, crt
|
||||||
|
KEY_DIR="${CA_DIR}/private"
|
||||||
|
CSR_DIR="${CA_DIR}/requests"
|
||||||
|
PKCS12_DIR="${CA_DIR}/pkcs12"
|
||||||
|
OVPN_DIR="${CA_DIR}/openvpn"
|
||||||
|
|
||||||
|
COPY_DIR="$(dirname "${CONF_FILE}")/copy_output"
|
||||||
|
|
||||||
|
CA_KEY_LENGTH=4096
|
||||||
|
if [ "${CA_KEY_LENGTH}" -lt 4096 ]; then
|
||||||
|
error "CA key must be at least 4096 bits long."
|
||||||
|
fi
|
||||||
|
KEY_LENGTH=2048
|
||||||
|
if [ "${KEY_LENGTH}" -lt 2048 ]; then
|
||||||
|
error "User key must be at least 2048 bits long."
|
||||||
|
fi
|
||||||
|
|
||||||
|
OPENSSL_BIN=$(command -v openssl)
|
||||||
|
SUFFIX=$(TZ=:Zulu /bin/date +"%Y%m%d%H%M%SZ")
|
||||||
|
|
||||||
|
if ! is_user "${PKI_USER}" || ! is_group "${PKI_USER}"; then
|
||||||
|
error "You must create ${PKI_USER} user and group !"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "${CONF_FILE}" ]; then
|
||||||
|
error "${CONF_FILE} is missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${CA_DIR}" "${CRT_DIR}" "${KEY_DIR}" "${CSR_DIR}" "${PKCS12_DIR}" "${OVPN_DIR}" "${TMP_DIR}"
|
||||||
|
|
||||||
|
command=${1:-help}
|
||||||
|
|
||||||
|
case "${command}" in
|
||||||
|
init)
|
||||||
|
shift
|
||||||
|
init "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
ocsp)
|
||||||
|
shift
|
||||||
|
ocsp "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
create)
|
||||||
|
shift
|
||||||
|
create "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
revoke)
|
||||||
|
shift
|
||||||
|
revoke "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
list)
|
||||||
|
shift
|
||||||
|
list "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
check)
|
||||||
|
shift
|
||||||
|
check "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
version|--version)
|
||||||
|
show_version
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
help|--help)
|
||||||
|
show_usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
show_usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# fix right
|
||||||
|
chown -R "${PKI_USER}":"${PKI_USER}" "${CA_DIR}"
|
||||||
|
chmod 750 "${CA_DIR}" "${CRT_DIR}" "${KEY_DIR}" "${CSR_DIR}" "${PKCS12_DIR}" "${OVPN_DIR}" "${TMP_DIR}"
|
||||||
|
chmod 600 "${INDEX_FILE}"* "${SERIAL}"* "${CA_KEY}" "${CRL}"
|
||||||
|
chmod 640 "${CA_CERT}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
|
@ -12,11 +12,6 @@
|
||||||
- client
|
- client
|
||||||
- server
|
- server
|
||||||
|
|
||||||
- name: Clone shellpki repo
|
|
||||||
git:
|
|
||||||
repo: "https://gitea.evolix.org/evolix/shellpki.git"
|
|
||||||
dest: /root/shellpki
|
|
||||||
|
|
||||||
- name: Create the shellpki user
|
- name: Create the shellpki user
|
||||||
user:
|
user:
|
||||||
name: shellpki
|
name: shellpki
|
||||||
|
@ -38,30 +33,14 @@
|
||||||
|
|
||||||
- name: Copy shellpki files
|
- name: Copy shellpki files
|
||||||
copy:
|
copy:
|
||||||
src: "{{ item.source }}"
|
src: "shellpki/{{ item.source }}"
|
||||||
dest: "{{ item.destination }}"
|
dest: "{{ item.destination }}"
|
||||||
remote_src: yes
|
|
||||||
with_items:
|
|
||||||
- { source: "/root/shellpki/openssl.cnf", destination: "/etc/shellpki/openssl.cnf" }
|
|
||||||
- { source: "/root/shellpki/shellpki", destination: "/usr/local/sbin/shellpki" }
|
|
||||||
|
|
||||||
- include_role:
|
|
||||||
name: evolix/remount-usr
|
|
||||||
|
|
||||||
- name: Change files permissions
|
|
||||||
file:
|
|
||||||
dest: "{{ item.dest }}"
|
|
||||||
mode: "{{ item.mode }}"
|
mode: "{{ item.mode }}"
|
||||||
owner: "{{ item.owner }}"
|
owner: "{{ item.owner }}"
|
||||||
group: "{{ item.group }}"
|
group: "{{ item.group }}"
|
||||||
with_items:
|
with_items:
|
||||||
- { dest: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "shellpki", group: "shellpki" }
|
- { source: "openssl.cnf", destination: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "shellpki", group: "shellpki" }
|
||||||
- { dest: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "root" }
|
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "root" }
|
||||||
|
|
||||||
- name: Delete local shellpki repo
|
|
||||||
file:
|
|
||||||
state: absent
|
|
||||||
dest: "/root/shellpki"
|
|
||||||
|
|
||||||
- name: Add sudo rights
|
- name: Add sudo rights
|
||||||
lineinfile:
|
lineinfile:
|
||||||
|
@ -251,30 +230,16 @@
|
||||||
notify: restart nagios-nrpe-server
|
notify: restart nagios-nrpe-server
|
||||||
when: nrpe_evolix_config.stat.exists
|
when: nrpe_evolix_config.stat.exists
|
||||||
|
|
||||||
# BEGIN TODO : Get this script from master branch when cloning it at the beginning when dev branch is merged with master (this script is currently not available on master branch)
|
|
||||||
- name: Clone dev branch of shellpki repo
|
|
||||||
git:
|
|
||||||
repo: "https://gitea.evolix.org/evolix/shellpki.git"
|
|
||||||
dest: /root/shellpki-dev
|
|
||||||
version: dev
|
|
||||||
|
|
||||||
- include_role:
|
- include_role:
|
||||||
name: evolix/remount-usr
|
name: evolix/remount-usr
|
||||||
|
|
||||||
- name: Copy shellpki script
|
- name: Copy shellpki script
|
||||||
copy:
|
copy:
|
||||||
src: "/root/shellpki-dev/cert-expirations.sh"
|
src: "shellpki/cert-expirations.sh"
|
||||||
dest: "/usr/share/scripts/cert-expirations.sh"
|
dest: "/usr/share/scripts/cert-expirations.sh"
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
remote_src: yes
|
|
||||||
|
|
||||||
- name: Delete local shellpki-dev repo
|
|
||||||
file:
|
|
||||||
state: absent
|
|
||||||
dest: "/root/shellpki-dev"
|
|
||||||
# END TODO
|
|
||||||
|
|
||||||
- name: Install cron to warn about certificates expiration
|
- name: Install cron to warn about certificates expiration
|
||||||
cron:
|
cron:
|
||||||
|
|
|
@ -13,11 +13,6 @@
|
||||||
group: wheel
|
group: wheel
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
|
||||||
- name: Clone shellpki repo
|
|
||||||
git:
|
|
||||||
repo: "https://gitea.evolix.org/evolix/shellpki.git"
|
|
||||||
dest: /root/shellpki
|
|
||||||
|
|
||||||
- name: Create the shellpki user
|
- name: Create the shellpki user
|
||||||
user:
|
user:
|
||||||
name: _shellpki
|
name: _shellpki
|
||||||
|
@ -36,27 +31,14 @@
|
||||||
|
|
||||||
- name: Copy shellpki files
|
- name: Copy shellpki files
|
||||||
copy:
|
copy:
|
||||||
src: "{{ item.source }}"
|
src: "shellpki/{{ item.source }}"
|
||||||
dest: "{{ item.destination }}"
|
dest: "{{ item.destination }}"
|
||||||
remote_src: yes
|
|
||||||
with_items:
|
|
||||||
- { source: "/root/shellpki/openssl.cnf", destination: "/etc/shellpki/openssl.cnf" }
|
|
||||||
- { source: "/root/shellpki/shellpki", destination: "/usr/local/sbin/shellpki" }
|
|
||||||
|
|
||||||
- name: Change files permissions
|
|
||||||
file:
|
|
||||||
dest: "{{ item.dest }}"
|
|
||||||
mode: "{{ item.mode }}"
|
mode: "{{ item.mode }}"
|
||||||
owner: "{{ item.owner }}"
|
owner: "{{ item.owner }}"
|
||||||
group: "{{ item.group }}"
|
group: "{{ item.group }}"
|
||||||
with_items:
|
with_items:
|
||||||
- { dest: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "_shellpki", group: "_shellpki"}
|
- { source: "openssl.cnf", destination: "/etc/shellpki/openssl.cnf", mode: "0640", owner: "_shellpki", group: "_shellpki" }
|
||||||
- { dest: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "wheel" }
|
- { source: "shellpki", destination: "/usr/local/sbin/shellpki", mode: "0755", owner: "root", group: "wheel" }
|
||||||
|
|
||||||
- name: Delete local shellpki repo
|
|
||||||
file:
|
|
||||||
state: absent
|
|
||||||
dest: "/root/shellpki"
|
|
||||||
|
|
||||||
- name: Add sudo rights
|
- name: Add sudo rights
|
||||||
lineinfile:
|
lineinfile:
|
||||||
|
@ -193,27 +175,13 @@
|
||||||
notify: restart nrpe
|
notify: restart nrpe
|
||||||
when: nrpe_evolix_config.stat.exists
|
when: nrpe_evolix_config.stat.exists
|
||||||
|
|
||||||
# BEGIN TODO : Get this script from master branch when cloning it at the beginning when dev branch is merged with master (this script is currently not available on master branch)
|
|
||||||
- name: Clone dev branch of shellpki repo
|
|
||||||
git:
|
|
||||||
repo: "https://gitea.evolix.org/evolix/shellpki.git"
|
|
||||||
dest: /root/shellpki-dev
|
|
||||||
version: dev
|
|
||||||
|
|
||||||
- name: Copy shellpki script
|
- name: Copy shellpki script
|
||||||
copy:
|
copy:
|
||||||
src: "/root/shellpki-dev/cert-expirations.sh"
|
src: "shellpki/cert-expirations.sh"
|
||||||
dest: "/usr/share/scripts/cert-expirations.sh"
|
dest: "/usr/share/scripts/cert-expirations.sh"
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
owner: root
|
owner: root
|
||||||
group: wheel
|
group: wheel
|
||||||
remote_src: yes
|
|
||||||
|
|
||||||
- name: Delete local shellpki-dev repo
|
|
||||||
file:
|
|
||||||
state: absent
|
|
||||||
dest: "/root/shellpki-dev"
|
|
||||||
# END TODO
|
|
||||||
|
|
||||||
- name: Install cron to warn about certificates expiration
|
- name: Install cron to warn about certificates expiration
|
||||||
cron:
|
cron:
|
||||||
|
|
|
@ -6,6 +6,7 @@ port 1194
|
||||||
proto udp
|
proto udp
|
||||||
dev tun
|
dev tun
|
||||||
mode server
|
mode server
|
||||||
|
topology subnet
|
||||||
keepalive 10 120
|
keepalive 10 120
|
||||||
tls-exit
|
tls-exit
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ smtp-amavis unix - - y - 2 lmtp
|
||||||
-o smtpd_hard_error_limit=1000
|
-o smtpd_hard_error_limit=1000
|
||||||
-o smtpd_client_connection_count_limit=0
|
-o smtpd_client_connection_count_limit=0
|
||||||
-o smtpd_client_connection_rate_limit=0
|
-o smtpd_client_connection_rate_limit=0
|
||||||
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
|
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
|
||||||
|
|
||||||
pre-cleanup unix n - n - 0 cleanup
|
pre-cleanup unix n - n - 0 cleanup
|
||||||
-o virtual_alias_maps=
|
-o virtual_alias_maps=
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# munin
|
# Redis
|
||||||
|
|
||||||
Installation and basic configuration of Redis.
|
Installation and basic configuration of Redis.
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,14 @@
|
||||||
tags:
|
tags:
|
||||||
- redis
|
- redis
|
||||||
- log2mail
|
- log2mail
|
||||||
|
|
||||||
|
- name: log2mail user is in redis group
|
||||||
|
user:
|
||||||
|
name: log2mail
|
||||||
|
groups: redis
|
||||||
|
append: yes
|
||||||
|
state: present
|
||||||
|
notify: restart log2mail
|
||||||
|
tags:
|
||||||
|
- redis
|
||||||
|
- log2mail
|
|
@ -49,6 +49,7 @@
|
||||||
- used_keys
|
- used_keys
|
||||||
- used_memory
|
- used_memory
|
||||||
notify: restart munin-node
|
notify: restart munin-node
|
||||||
|
when: not ansible_check_mode
|
||||||
tags:
|
tags:
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
- used_keys
|
- used_keys
|
||||||
- used_memory
|
- used_memory
|
||||||
notify: restart munin-node
|
notify: restart munin-node
|
||||||
|
when: not ansible_check_mode
|
||||||
tags:
|
tags:
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,14 @@
|
||||||
- packages
|
- packages
|
||||||
when: redis_sentinel_install | bool
|
when: redis_sentinel_install | bool
|
||||||
|
|
||||||
|
- name: Linux kernel overcommit memory setting is enabled
|
||||||
|
sysctl:
|
||||||
|
name: "vm.overcommit_memory"
|
||||||
|
value: "1"
|
||||||
|
sysctl_file: "/etc/sysctl.d/evolinux-redis.conf"
|
||||||
|
state: present
|
||||||
|
reload: yes
|
||||||
|
|
||||||
- name: Get Redis version
|
- name: Get Redis version
|
||||||
shell: "redis-server -v | grep -Eo '(v=\\S+)' | cut -d'=' -f 2 | grep -E '^([0-9]|\\.)+$'"
|
shell: "redis-server -v | grep -Eo '(v=\\S+)' | cut -d'=' -f 2 | grep -E '^([0-9]|\\.)+$'"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
- redis
|
- redis
|
||||||
- nrpe
|
- nrpe
|
||||||
|
|
||||||
|
- name: "Remount /usr with RW for 'install check_redis instance'"
|
||||||
|
include_role:
|
||||||
|
name: evolix/remount-usr
|
||||||
|
|
||||||
- name: install check_redis_instances
|
- name: install check_redis_instances
|
||||||
copy:
|
copy:
|
||||||
src: check_redis_instances.sh
|
src: check_redis_instances.sh
|
||||||
|
|
|
@ -7,4 +7,3 @@ squid_whitelist_items: []
|
||||||
|
|
||||||
squid_localproxy_enable: False
|
squid_localproxy_enable: False
|
||||||
|
|
||||||
minifirewall_main_file: /etc/default/minifirewall
|
|
||||||
|
|
43
squid/tasks/minifirewall.legacy.yml
Normal file
43
squid/tasks/minifirewall.legacy.yml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
- name: Check if Minifirewall is present
|
||||||
|
stat:
|
||||||
|
path: "/etc/default/minifirewall"
|
||||||
|
check_mode: no
|
||||||
|
register: minifirewall_test
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: HTTPSITES list is commented in minifirewall
|
||||||
|
replace:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
regexp: "^(HTTPSITES='[^0-9])"
|
||||||
|
replace: '#\1'
|
||||||
|
notify: restart minifirewall
|
||||||
|
|
||||||
|
- name: all HTTPSITES are authorized in minifirewall
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
line: "HTTPSITES='0.0.0.0/0'"
|
||||||
|
regexp: "HTTPSITES='.*'"
|
||||||
|
insertafter: "^#HTTPSITES="
|
||||||
|
notify: restart minifirewall
|
||||||
|
|
||||||
|
- name: add iptables rules for the proxy
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
regexp: "^#? *{{ item }}"
|
||||||
|
line: "{{ item }}"
|
||||||
|
insertafter: "^# Proxy"
|
||||||
|
loop:
|
||||||
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT"
|
||||||
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d {{ squid_address }} -j ACCEPT"
|
||||||
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.0/8 -j ACCEPT"
|
||||||
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8888"
|
||||||
|
notify: restart minifirewall
|
||||||
|
|
||||||
|
- name: remove minifirewall example rule for the proxy
|
||||||
|
lineinfile:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
regexp: '^#.*(-t nat).*(-d X\.X\.X\.X)'
|
||||||
|
state: absent
|
||||||
|
notify: restart minifirewall
|
||||||
|
when: minifirewall_test.stat.exists
|
|
@ -1,29 +1,37 @@
|
||||||
---
|
---
|
||||||
- name: Check if Minifirewall is present
|
- name: Check if Minifirewall is present
|
||||||
stat:
|
stat:
|
||||||
path: "{{ minifirewall_main_file }}"
|
path: "/etc/default/minifirewall"
|
||||||
check_mode: no
|
check_mode: no
|
||||||
register: minifirewall_test
|
register: minifirewall_test
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- name: HTTPSITES list is commented in minifirewall
|
- name: HTTPSITES list is commented in minifirewall
|
||||||
replace:
|
replace:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
regexp: "^(HTTPSITES='[^0-9])"
|
regexp: "^(HTTPSITES='[^0-9])"
|
||||||
replace: '#\1'
|
replace: '#\1'
|
||||||
notify: restart minifirewall
|
notify: restart minifirewall
|
||||||
|
|
||||||
- name: all HTTPSITES are authorized in minifirewall
|
- name: all HTTPSITES are authorized in minifirewall
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
line: "HTTPSITES='0.0.0.0/0'"
|
line: "HTTPSITES='0.0.0.0/0'"
|
||||||
regexp: "HTTPSITES='.*'"
|
regexp: "HTTPSITES='.*'"
|
||||||
insertafter: "^#HTTPSITES="
|
insertafter: "^#HTTPSITES="
|
||||||
notify: restart minifirewall
|
notify: restart minifirewall
|
||||||
|
|
||||||
- name: add iptables rules for the proxy
|
# The PROXY variable means that minifirewall is "modern"
|
||||||
|
- name: Look for PROXY variable
|
||||||
|
shell: "grep -E '^\\s*PROXY=' /etc/default/minifirewall"
|
||||||
|
failed_when: False
|
||||||
|
changed_when: False
|
||||||
|
check_mode: False
|
||||||
|
register: _minifirewall_proxy_var_check
|
||||||
|
|
||||||
|
- name: Set proxy configuration for minifirewall (legacy mode)
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
regexp: "^#? *{{ item }}"
|
regexp: "^#? *{{ item }}"
|
||||||
line: "{{ item }}"
|
line: "{{ item }}"
|
||||||
insertafter: "^# Proxy"
|
insertafter: "^# Proxy"
|
||||||
|
@ -33,11 +41,21 @@
|
||||||
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.0/8 -j ACCEPT"
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.0/8 -j ACCEPT"
|
||||||
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8888"
|
- "/sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8888"
|
||||||
notify: restart minifirewall
|
notify: restart minifirewall
|
||||||
|
when: _minifirewall_proxy_var_check.rc == 1
|
||||||
|
|
||||||
- name: remove minifirewall example rule for the proxy
|
- name: remove minifirewall example rule for the proxy (legacy mode)
|
||||||
lineinfile:
|
lineinfile:
|
||||||
dest: "{{ minifirewall_main_file }}"
|
dest: "/etc/default/minifirewall"
|
||||||
regexp: '^#.*(-t nat).*(-d X\.X\.X\.X)'
|
regexp: '^#.*(-t nat).*(-d X\.X\.X\.X)'
|
||||||
state: absent
|
state: absent
|
||||||
notify: restart minifirewall
|
notify: restart minifirewall
|
||||||
|
when: _minifirewall_proxy_var_check.rc == 1
|
||||||
|
|
||||||
|
- name: Set proxy configuration for minifirewall (modern mode)
|
||||||
|
replace:
|
||||||
|
dest: "/etc/default/minifirewall"
|
||||||
|
replace: "PROXY='on'"
|
||||||
|
regexp: "PROXY='.*'"
|
||||||
|
notify: restart minifirewall
|
||||||
|
when: _minifirewall_proxy_var_check.rc == 0
|
||||||
when: minifirewall_test.stat.exists
|
when: minifirewall_test.stat.exists
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
- ansible_distribution_release == "buster"
|
- ansible_distribution_release == "buster"
|
||||||
- tomcat_version is not defined
|
- tomcat_version is not defined
|
||||||
|
|
||||||
- name: Set Tomcat version to 10 on Debian 11 if missing
|
- name: Set Tomcat version to 9 on Debian 11 if missing
|
||||||
set_fact:
|
set_fact:
|
||||||
tomcat_version: 10
|
tomcat_version: 9
|
||||||
when:
|
when:
|
||||||
- ansible_distribution_release == "bullseye"
|
- ansible_distribution_release == "bullseye"
|
||||||
- tomcat_version is not defined
|
- tomcat_version is not defined
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
include_role:
|
include_role:
|
||||||
name: evolix/apt
|
name: evolix/apt
|
||||||
tasks_from: evolix_public.yml
|
tasks_from: evolix_public.yml
|
||||||
|
tags:
|
||||||
|
- vrrpd
|
||||||
|
|
||||||
- name: Install vrrpd packages
|
- name: Install vrrpd packages
|
||||||
apt:
|
apt:
|
||||||
|
@ -10,12 +12,13 @@
|
||||||
allow_unauthenticated: yes
|
allow_unauthenticated: yes
|
||||||
state: present
|
state: present
|
||||||
tags:
|
tags:
|
||||||
- vrrpd
|
- vrrpd
|
||||||
|
|
||||||
- name: Adjust sysctl config
|
- name: Adjust sysctl config
|
||||||
sysctl:
|
sysctl:
|
||||||
name: "{{ item.name }}"
|
name: "{{ item.name }}"
|
||||||
value: "{{ item.value }}"
|
value: "{{ item.value }}"
|
||||||
|
sysctl_file: /etc/sysctl.d/vrrpd.conf
|
||||||
sysctl_set: yes
|
sysctl_set: yes
|
||||||
state: present
|
state: present
|
||||||
loop:
|
loop:
|
||||||
|
@ -26,4 +29,4 @@
|
||||||
- { name: 'net.ipv4.conf.all.arp_announce', value: 2 }
|
- { name: 'net.ipv4.conf.all.arp_announce', value: 2 }
|
||||||
- { name: 'net.ipv4.ip_nonlocal_bind', value: 1 }
|
- { name: 'net.ipv4.ip_nonlocal_bind', value: 1 }
|
||||||
tags:
|
tags:
|
||||||
- vrrpd
|
- vrrpd
|
||||||
|
|
Loading…
Reference in a new issue