Browse Source

Add initial project

tags/6.8.0
Tristan Pilat 1 year ago
parent
commit
b555fb1222
50 changed files with 1993 additions and 0 deletions
  1. +146
    -0
      README.md
  2. +33
    -0
      evolixisation.yml
  3. +5
    -0
      hosts
  4. +16
    -0
      prerequisite.yml
  5. +26
    -0
      roles/accounts/tasks/main.yml
  6. +19
    -0
      roles/base/defaults/main.yml
  7. +198
    -0
      roles/base/files/evomaintenance.sh
  8. +33
    -0
      roles/base/files/evomaintenance.tpl
  9. +1
    -0
      roles/base/files/installurl
  10. +17
    -0
      roles/base/files/kshrc
  11. +27
    -0
      roles/base/files/profile
  12. +11
    -0
      roles/base/files/vimrc
  13. +222
    -0
      roles/base/files/zzz_evobackup
  14. +3
    -0
      roles/base/handlers/main.yml
  15. +13
    -0
      roles/base/tasks/doas.yml
  16. +63
    -0
      roles/base/tasks/dotfiles.yml
  17. +20
    -0
      roles/base/tasks/evobackup.yml
  18. +51
    -0
      roles/base/tasks/evomaintenance.yml
  19. +19
    -0
      roles/base/tasks/mail.yml
  20. +9
    -0
      roles/base/tasks/main.yml
  21. +31
    -0
      roles/base/tasks/packages.yml
  22. +29
    -0
      roles/base/tasks/sudo.yml
  23. +11
    -0
      roles/base/templates/doas.conf.j2
  24. +13
    -0
      roles/base/templates/evomaintenance.j2
  25. +28
    -0
      roles/base/templates/mailevomaintenance.sh.j2
  26. +31
    -0
      roles/etc-git/README.md
  27. +4
    -0
      roles/etc-git/defaults/main.yml
  28. +3
    -0
      roles/etc-git/files/gitignore
  29. +56
    -0
      roles/etc-git/tasks/commit.yml
  30. +118
    -0
      roles/etc-git/tasks/main.yml
  31. +18
    -0
      roles/forwarding/tasks/main.yml
  32. +13
    -0
      roles/nagios-nrpe/README.md
  33. +13
    -0
      roles/nagios-nrpe/defaults/main.yml
  34. +65
    -0
      roles/nagios-nrpe/files/plugins_bsd/check_carp_if
  35. +23
    -0
      roles/nagios-nrpe/files/plugins_bsd/check_ipsecctl.sh
  36. +9
    -0
      roles/nagios-nrpe/files/plugins_bsd/check_openvpn
  37. +12
    -0
      roles/nagios-nrpe/files/plugins_bsd/check_ospfd_simple
  38. +5
    -0
      roles/nagios-nrpe/handlers/main.yml
  39. +60
    -0
      roles/nagios-nrpe/tasks/main.yml
  40. +38
    -0
      roles/nagios-nrpe/templates/evolix_bsd.cfg.j2
  41. +166
    -0
      roles/nagios-nrpe/templates/plugins_bsd/check_free_mem.sh.j2
  42. +22
    -0
      roles/nagios-nrpe/templates/plugins_bsd/check_pf_states.j2
  43. +7
    -0
      roles/pf/tasks/main.yml
  44. +74
    -0
      roles/pf/templates/pf.conf.j2
  45. +140
    -0
      roles/post-install/files/ldap.sh
  46. +5
    -0
      roles/post-install/tasks/ldif.yml
  47. +4
    -0
      roles/post-install/tasks/main.yml
  48. +9
    -0
      roles/post-install/tasks/update.yml
  49. +21
    -0
      tasks/commit_etc_git.yml
  50. +33
    -0
      vars/main.yml

+ 146
- 0
README.md View File

@@ -0,0 +1,146 @@
# EvoBSD 1.0

EvoBSD is an ansible project used for customising OpenBSD hosts
used by Evolix.

## How to install an OpenBSD machine

**Note :** The system must be installed with a root account only. Put your public key in the remote root's autorized_keys (/root/.ssh/authorized_keys)

1 - Install ansible's prerequisites

```
ansible-playbook prerequisite.yml -CDi hosts -l HOSTNAME
```

2 - Run it!

```
ansible-playbook evolixisation.yml --ask-vault-pass -CDKi hosts -l HOSTNAME
```

### Try it on a disposable system!

The easiest way to try EvoBSD is by using packer and vmm :

* First of all let's install go and packer on your host system

```
# pkg_add go packer
```

* Then we gonna use [packer-builder-vmm](https://github.com/prep/packer-builder-vmm) project availbale on Github

```
$ go get -u github.com/prep/packer-builder-vmm/cmd/packer-builder-vmm
```

* We have to create a definition file for packer

```
$ vim openbsd.json
```

{
"description": "OpenBSD installation on VMM",

"variables": {
"hostname": "evobsd",
"domain": "example.com",

"password": "evolix"
},

"builders": [
{
"type": "vmm",
"vm_name": "evobsd",
"disk_size": "2G",
"format": "qcow2",
"mem_size": "1024M",

"iso_urls": ["downloads/install64.fs", "https://ftp.nluug.nl/pub/OpenBSD/6.4/amd64/install64.fs"],
"iso_checksum": "7aa4344cb39efbf67300f97ac7eec005b607e8c19d4e31a0a593a8ee2b7136e4",
"iso_checksum_type": "sha256",

"boot_wait": "10s",
"boot_command": [
"S<enter>",

"cat <<EOF >disklabel.template<enter>",
"/ 1G-* 100%<enter>",
"EOF<enter>",

"cat <<EOF >install.conf<enter>",
"System hostname = {{user `hostname`}}<enter>",
"DNS domain name = {{user `domain`}}<enter>",
"Password for root account = {{user `password`}}<enter>",
"Do you expect to run the X Window System = no<enter>",
"Setup a user = no<enter>",
"Which disk is the root disk = sd1<enter>",
"Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout = c<enter>",
"URL to autopartitioning template for disklabel = file://disklabel.template<enter>",
"Location of sets = disk<enter>",
"Is the disk partition already mounted = no<enter>",
"Set name(s) = -bsd.rd<enter>",
"Set name(s) = done<enter>",
"Directory does not contain SHA256.sig. Continue without verification = yes<enter>",
"What timezone are you in = Europe/Paris<enter>",
"EOF<enter>",

"install -af install.conf<enter>",
"<wait2m>",

"/sbin/halt -p<enter><wait15>"
]
}
]
}


* You need your unprivileged user to be able to run vmctl through doas

```
# echo "permit nopass myunprivilegeduser as root cmd /usr/sbin/vmctl
```

* Eventually you can build your virtual machine

```
$ packer build openbsd.json
```

* Once the building is done, run your VM like this

```
doas vmctl start evobsd -cL -d output-vmm/evobsd.qcow2
```

## Contributions

Contributions to this project are most welcome! The best way is to create a
pull request so that after review it's merged.

## License

MIT License

Copyright (c) 2019 Evolix

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 33
- 0
evolixisation.yml View File

@@ -0,0 +1,33 @@
# Playbook command
# ansible-playbook evolixisation.yml --ask-vault-pass -CDKi hosts -l HOSTNAME

---
- name: Evolixisation of an OpenBSD system
hosts: openbsd
become: true
become_user: root
become_method: sudo


vars_files:
- vars/main.yml
# - vars/secrets.yml

roles:
- etc-git
- base
- forwarding
- pf
- accounts
- nagios-nrpe
- post-install

post_tasks:
- include: "tasks/commit_etc_git.yml"
vars:
commit_message: "Ansible - Evolixisation"

environment:
PKG_PATH: "http://ftp.openbsd.org/pub/OpenBSD/{{ ansible_distribution_version }}/packages/{{ ansible_architecture }}/"

# vim:ft=ansible

+ 5
- 0
hosts View File

@@ -0,0 +1,5 @@
[openbsd]
foo.example.com

[openbsd:vars]
ansible_python_interpreter=/usr/local/bin/python2.7

+ 16
- 0
prerequisite.yml View File

@@ -0,0 +1,16 @@
# Playbook command
# ansible-playbook prerequisite.yml -CDi hosts -l HOSTNAME

---
- hosts: all
become: yes
become_method: su
user: root
gather_facts: no

tasks:

- name: Install ansible's prerequisite
raw: export PKG_PATH=http://ftp.eu.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(uname -p)/; pkg_add -z python-2

# vim:ft=ansible

+ 26
- 0
roles/accounts/tasks/main.yml View File

@@ -0,0 +1,26 @@
---
- name: Create admins accounts
user:
state: present
name: '{{ item.value.name }}'
uid: '{{ item.value.uid }}'
password: '{{ item.value.password_hash_openbsd }}'
groups: wheel
shell: /bin/ksh
append: yes
with_dict:
"{{ evolix_users }}"
tags:
- admin

- name: Add admins ssh keys
lineinfile:
state: present
dest: '/home/{{ item.value.name }}/.ssh/authorized_keys'
line: '{{ item.value.ssh_keys }}'
create: yes
with_dict:
"{{ evolix_users }}"
tags:
- admin


+ 19
- 0
roles/base/defaults/main.yml View File

@@ -0,0 +1,19 @@
---
ntpd_servers:
- "ntp.evolix.net"

general_alert_email: "root@localhost"
general_technical_realm: "example.com"

evomaintenance_realm: "example.com"
evomaintenance_alert_email: "evomaintenance-{{ inventory_hostname }}@{{ evomaintenance_realm }}"
evomaintenance_hostname: "{{ inventory_hostname }}.{{ general_technical_realm }}"
evomaintenance_pg_host: Null
evomaintenance_pg_passwd: Null
evomaintenance_pg_db: Null
evomaintenance_pg_table: Null
evomaintenance_from_domain: "{{ evomaintenance_realm }}"
evomaintenance_from: "evomaintenance@{{ evomaintenance_from_domain }}"
evomaintenance_full_from: "Evomaintenance <{{ evomaintenance_from }}>"
evomaintenance_urgency_from: mama.doe@example.com
evomaintenance_urgency_tel: "06.00.00.00.00"

+ 198
- 0
roles/base/files/evomaintenance.sh View File

@@ -0,0 +1,198 @@
#!/bin/sh

# EvoMaintenance script
# Dependencies (all OS): git postgresql-client
# Dependencies (Debian): sudo

# version 0.4.1
# Copyright 2007-2018 Evolix <info@evolix.fr>

get_system() {
uname -s
}

get_fqdn() {
if [ "$(get_system)" = "Linux" ]; then
hostname --fqdn
elif [ "$(get_system)" = "OpenBSD" ]; then
hostname
else
echo "OS not detected!"
exit 1
fi
}

get_tty() {
if [ "$(get_system)" = "Linux" ]; then
ps -o tty= | tail -1
elif [ "$(get_system)" = "OpenBSD" ]; then
env | grep SSH_TTY | cut -d"/" -f3
else
echo "OS not detected!"
exit 1
fi
}

get_who() {
who=$(LC_ALL=C who -m)

if [ -n "${who}" ]; then
echo "${who}"
else
LC_ALL=C who | grep $(get_tty) | tr -s ' '
fi
}

get_begin_date() {
echo "$(date "+%Y") $(echo $(get_who) | cut -d" " -f3,4,5)"
}

get_ip() {
ip=$(echo $(get_who) | cut -d" " -f6 | sed -e "s/^(// ; s/)$//")
[ -z "${ip}" ] && ip="unknown (no tty)"
[ "${ip}" = ":0" ] && ip="localhost"

echo "${ip}"
}

get_end_date() {
date +"%Y %b %d %H:%M"
}

get_now() {
date +"%Y-%m-%dT%H:%M:%S%z"
}

test -f /etc/evomaintenance.cf && . /etc/evomaintenance.cf

[ -n "${HOSTNAME}" ] || HOSTNAME=$(get_fqdn)
[ -n "${EVOMAINTMAIL}" ] || EVOMAINTMAIL=evomaintenance-$(echo "${HOSTNAME}" | cut -d- -f1)@${REALM}
[ -n "${LOGFILE}" ] || LOGFILE=/var/log/evomaintenance.log

# Treat unset variables as an error when substituting.
# Only after this line, because some config variables might be missing.
set -u

REAL_HOSTNAME=$(get_fqdn)
if [ "${HOSTNAME}" = "${REAL_HOSTNAME}" ]; then
HOSTNAME_TEXT="${HOSTNAME}"
else
HOSTNAME_TEXT="${HOSTNAME} (${REAL_HOSTNAME})"
fi

# TTY=$(get_tty)
# WHO=$(get_who)
IP=$(get_ip)
BEGIN_DATE=$(get_begin_date)
END_DATE=$(get_end_date)
USER=$(logname)

PATH=${PATH}:/usr/sbin

SENDMAIL_BIN=$(command -v sendmail)
GIT_BIN=$(command -v git)

GIT_REPOSITORIES="/etc /etc/bind"

# git statuses
GIT_STATUSES=""

if test -x "${GIT_BIN}"; then
# loop on possible directories managed by GIT
for dir in ${GIT_REPOSITORIES}; do
# tell Git where to find the repository and the work tree (no need to `cd …` there)
export GIT_DIR="${dir}/.git" GIT_WORK_TREE="${dir}"
# If the repository and the work tree exist, try to commit changes
if test -d "${GIT_DIR}" && test -d "${GIT_WORK_TREE}"; then
CHANGED_LINES=$(${GIT_BIN} status --porcelain | wc -l | tr -d ' ')
if [ "${CHANGED_LINES}" != "0" ]; then
STATUS=$(${GIT_BIN} status --short | tail -n 10)
# append diff data, without empty lines
GIT_STATUSES=$(printf "%s\n%s\n%s\n" "${GIT_STATUSES}" "${GIT_DIR} (last 10 lines)" "${STATUS}" | sed -e '/^$/d')
fi
fi
# unset environment variables to prevent accidental influence on other git commands
unset GIT_DIR GIT_WORK_TREE
done
if [ -n "${GIT_STATUSES}" ]; then
echo "/!\ There are some uncommited changes. If you proceed, everything will be commited."
echo "${GIT_STATUSES}"
echo ""
fi
fi

# get input from stdin
echo "> Please, enter details about your maintenance"
read TEXTE

if [ "${TEXTE}" = "" ]; then
echo "no value..."
exit 1
fi

# recapitulatif
BLOB=$(cat <<END
Host : $HOSTNAME_TEXT
User : $USER
IP : $IP
Begin : $BEGIN_DATE
End : $END_DATE
Message : $TEXTE
END
)

echo ""
echo "${BLOB}"
echo ""
echo "> Press <Enter> to submit, or <Ctrl+c> to cancel."
read enter

# write log
echo "----------- $(get_now) ---------------" >> "${LOGFILE}"
echo "${BLOB}" >> "${LOGFILE}"

# git commit
GIT_COMMITS=""

if test -x "${GIT_BIN}"; then
# loop on possible directories managed by GIT
for dir in ${GIT_REPOSITORIES}; do
# tell Git where to find the repository and the work tree (no need to `cd …` there)
export GIT_DIR="${dir}/.git" GIT_WORK_TREE="${dir}"
# If the repository and the work tree exist, try to commit changes
if test -d "${GIT_DIR}" && test -d "${GIT_WORK_TREE}"; then
CHANGED_LINES=$(${GIT_BIN} status --porcelain | wc -l | tr -d ' ')
if [ "${CHANGED_LINES}" != "0" ]; then
${GIT_BIN} add --all
${GIT_BIN} commit --message "${TEXTE}" --author="${USER} <${USER}@evolix.net>" --quiet
# Add the SHA to the log file if something has been committed
SHA=$(${GIT_BIN} rev-parse --short HEAD)
STATS=$(${GIT_BIN} show --stat | tail -1)
# append commit data, without empty lines
GIT_COMMITS=$(printf "%s\n%s : %s –%s" "${GIT_COMMITS}" "${GIT_DIR}" "${SHA}" "${STATS}" | sed -e '/^$/d')
fi
fi
# unset environment variables to prevent accidental influence on other git commands
unset GIT_DIR GIT_WORK_TREE
done
if [ -n "${GIT_COMMITS}" ]; then
echo "${GIT_COMMITS}" >> "${LOGFILE}"
fi
fi

# insert into PG
# SQL_TEXTE=`echo "${TEXTE}" | sed "s/'/\\\\\\'/g ; s@/@\\\\\/@g ; s@\\&@et@g"`
SQL_TEXTE=`echo "${TEXTE}" | sed "s/'/''/g"`

PG_QUERY="INSERT INTO evomaint(hostname,userid,ipaddress,begin_date,end_date,details) VALUES ('${HOSTNAME}','${USER}','${IP}','${BEGIN_DATE}',now(),'${SQL_TEXTE}')"
echo "${PG_QUERY}" | psql ${PGDB} ${PGTABLE} -h ${PGHOST} --quiet

# send mail
MAIL_TEXTE=$(echo "${TEXTE}" | sed -e "s@/@\\\\\/@g ; s@&@\\\\&@")
MAIL_GIT_COMMITS=$(echo "${GIT_COMMITS}" | sed -e "s@/@\\\\\/@g ; s@&@\\\\&@")

cat /usr/share/scripts/evomaintenance.tpl | \
sed -e "s/__TO__/${EVOMAINTMAIL}/ ; s/__HOSTNAME__/${HOSTNAME_TEXT}/ ; s/__USER__/${USER}/ ; s/__BEGIN_DATE__/${BEGIN_DATE}/ ; s/__END_DATE__/${END_DATE}/ ; s/__GIT_COMMITS__/${MAIL_GIT_COMMITS}/ ; s/__TEXTE__/${MAIL_TEXTE}/ ; s/__IP__/${IP}/ ; s/__FULLFROM__/${FULLFROM}/ ; s/__FROM__/${FROM}/ ; s/__URGENCYFROM__/${URGENCYFROM}/ ; s/__URGENCYTEL__/${URGENCYTEL}/" | \
${SENDMAIL_BIN} -oi -t -f ${FROM}

exit 0

+ 33
- 0
roles/base/files/evomaintenance.tpl View File

@@ -0,0 +1,33 @@
From: __FULLFROM__
Content-Type: text/plain; charset=UTF-8
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
To: __TO__
Subject: [evomaintenance] Intervention sur __HOSTNAME__ (__USER__)

Bonjour,

Une intervention vient de se terminer sur votre serveur.
Voici les renseignements sur l'intervention :

Nom du serveur : __HOSTNAME__
Personne ayant réalisée l'intervention : __USER__
Intervention réalisée depuis : __IP__
Début de l'intervention : __BEGIN_DATE__
Fin de l'intervention : __END_DATE__

###
Renseignements sur l'intervention :
__TEXTE__
###

__GIT_COMMITS__

Pour réagir à cette intervention, vous pouvez répondre à ce message
(sur l'adresse mail __FROM__). En cas d'urgence, utilisez
l'adresse __URGENCYFROM__ ou notre téléphone portable d'astreinte
(__URGENCYTEL__)

Cordialement,
--
__FULLFROM__

+ 1
- 0
roles/base/files/installurl View File

@@ -0,0 +1 @@
https://cdn.openbsd.org/pub/OpenBSD

+ 17
- 0
roles/base/files/kshrc View File

@@ -0,0 +1,17 @@
alias vi='vim'
sudo() { if [[ $# == "1" ]] && [[ $1 == "su" ]]; then command sudo -i; else command sudo "$@"; fi }

##
# Caracterisation du shell
##

bind -m '^L'='^U 'clear'^M^Y'
bind '^[[4~'=end-of-line
bind '^[[1~'=beginning-of-line
bind '^[[3~'=delete-char-forward
bind '^[[8~'=end-of-line
bind '^[[7~'=beginning-of-line
bind '^[Oc'=forward-word
bind '^[Od'=backward-word
bind '^[^[[C'=forward-word
bind '^[^[[D'=backward-word

+ 27
- 0
roles/base/files/profile View File

@@ -0,0 +1,27 @@
# $OpenBSD: dot.profile,v 1.9 2010/12/13 12:54:31 millert Exp $
#
# sh/ksh initialization

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/sbin:/usr/local/bin
export PATH HOME TERM
export PS1="\u@\h:\w\\$ "
HISTFILE=$HOME/.histfile
export HISTSIZE=10000
export HISTCONTROL='ignoredups:ignorespace'
export TMOUT=36000
export PAGER=less
umask 022

export ENV='~/.kshrc'

case "$-" in
*i*) # interactive shell
if [ -x /usr/bin/tset ]; then
if [ X"$XTERM_VERSION" = X"" ]; then
eval `/usr/bin/tset -sQ '-munknown:?vt220' $TERM`
else
eval `/usr/bin/tset -IsQ '-munknown:?vt220' $TERM`
fi
fi
;;
esac

+ 11
- 0
roles/base/files/vimrc View File

@@ -0,0 +1,11 @@
syntax on
set hlsearch
set background=dark
set expandtab
set tabstop=4
set softtabstop=0
set shiftwidth=4
set smarttab
set backspace=indent,eol,start
set showcmd
set encoding=utf-8

+ 222
- 0
roles/base/files/zzz_evobackup View File

@@ -0,0 +1,222 @@
#!/bin/sh

#
# Script Evobackup plus ou moins forké
# See https://forge.evolix.org/projects/evobackup
#

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin

## lang = C for english outputs
LANGUAGE=C
LANG=C

## Force umask
umask 077

## Verify other evobackup process and kill if needed
PIDFILE=/var/run/evobackup.pid
if [ -e $PIDFILE ]; then
# Killing the childs of evobackup.
for pid in $(ps h --ppid $(cat $PIDFILE) -o pid | tr -s '\n' ' '); do
kill -9 $pid;
done
# Then kill the main PID.
kill -9 $(cat $PIDFILE)
echo "$0 tourne encore (PID `cat $PIDFILE`). Processus killé" >&2
fi
echo "$$" > $PIDFILE
trap "rm -f $PIDFILE" EXIT

# Variable to choose different backup server with date
NODE=$(expr `date +%d` % 2 + 2)

# port SSH
SSH_PORT=2XXX

# email adress for notifications
MAIL={{ general_alert_email }}

# backup server used
SRV=node$NODE.backup2.evolix.net

# choose "linux" or "bsd"
SYSTEME=$(uname | tr '[:upper:]' '[:lower:]')

## We use /home/backup : feel free to use your own dir
mkdir -p -m 700 /home/backup

## OpenLDAP : example with slapcat
# slapcat -l /home/backup/ldap.bak

### MySQL

## example with global and compressed mysqldump
# mysqldump --defaults-extra-file=/etc/mysql/debian.cnf -P 3306 \
# --opt --all-databases --force --events --hex-blob | gzip --best > /home/backup/mysql.bak.gz

## example with two dumps for each table (.sql/.txt) for all databases
# for i in $(echo SHOW DATABASES | mysql --defaults-extra-file=/etc/mysql/debian.cnf -P 3306 \
# | egrep -v "^(Database|information_schema|performance_schema)" ); \
# do mkdir -p /home/mysqldump/$i ; chown -RL mysql /home/mysqldump ; \
# mysqldump --defaults-extra-file=/etc/mysql/debian.cnf --force -P 3306 -Q --opt --events --hex-blob --skip-comments -T \
# /home/mysqldump/$i $i; done

## example with compressed SQL dump for each databases
# mkdir -p /home/mysqldump/
# for i in $(mysql --defaults-extra-file=/etc/mysql/debian.cnf -P 3306 -e 'show databases' -s --skip-column-names \
# | egrep -v "^(Database|information_schema|performance_schema)"); do
# mysqldump --defaults-extra-file=/etc/mysql/debian.cnf --force -P 3306 --events --hex-blob $i | gzip --best > /home/mysqldump/${i}.sql.gz
# done

## example with *one* uncompressed SQL dump for *one* database (MYBASE)
# mkdir -p -m 700 /home/mysqldump/MYBASE
# chown -RL mysql /home/mysqldump/
# mysqldump --defaults-extra-file=/etc/mysql/debian.cnf --force -Q \
# --opt --events --hex-blob --skip-comments -T /home/mysqldump/MYBASE MYBASE

## example with mysqlhotcopy
# mkdir -p /home/mysqlhotcopy/
# mysqlhotcopy BASE /home/mysqlhotcopy/

## example for multiples MySQL instances
# mysqladminpasswd=`cat /root/.my.cnf |grep -m1 'password = .*' |cut -d" " -f3`
# grep -E "^port\s*=\s*\d*" /etc/mysql/my.cnf |while read instance; do
# instance=$(echo $instance |tr -d '\t')
# instance=${instance// /}
# instance=${instance//port=/}
# if [ "$instance" != "3306" ]
# then
# mysqldump -P $instance --opt --all-databases --hex-blob -u mysqladmin -p$mysqladminpasswd > /home/backup/mysql.$instance.bak
# fi
# done

### PostgreSQL

## example with pg_dumpall (warning: you need space in ~postgres)
# su - postgres -c "pg_dumpall > ~/pg.dump.bak"
# mv ~postgres/pg.dump.bak /home/backup/

## example with all tables from MYBASE excepts TABLE1 and TABLE2
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f /home/backup/pg-backup.tar -t 'TABLE1' -t 'TABLE2' MYBASE

## example with only TABLE1 and TABLE2 from MYBASE
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f /home/backup/pg-backup.tar -T 'TABLE1' -T 'TABLE2' MYBASE

## MongoDB : example with mongodump
## don't forget to create use with read-only access
## > use admin
## > db.addUser("mongobackup", "PASS", true);
# mongodump -u mongobackup -pPASS -o /home/backup/mongodump/ >/dev/null 2>&1 |grep -v "^connected to:"

## Redis : example with copy .rdb file
# cp /var/lib/redis/dump.rdb /home/backup/

## ElasticSearch : example with rsync (warning: don't forget to use NFS if you have a cluster)
## Disable ES translog flush
# curl -s -XPUT 'localhost:9200/_settings' -d '{"index.translog.disable_flush": true}' >/dev/null
## Flushes translog
# curl -s 'localhost:9200/_flush' | grep -qe '"ok":true'
## If it succeed, do an rsync of the datadir
# if [ $? -eq 0 ]; then
# rsync -a /var/lib/elasticsearch /home/backup/
# else
# echo "Error when flushing ES translog indexes."
# fi
## In any case re-enable translog flush
# curl -s -XPUT 'localhost:9200/_settings' -d '{"index.translog.disable_flush": false}' > /dev/null

## Dump MBR / table partitions with dd and sfdisk
## Linux
# dd if=/dev/sda of=/home/backup/MBR bs=512 count=1 2>&1 | egrep -v "(records in|records out|512 bytes)"
# sfdisk -d /dev/sda > /home/backup/partitions 2>&1 | egrep -v "(Warning: extended partition does not start at a cylinder boundary|DOS and Linux will interpret the contents differently)"
## OpenBSD
# disklabel sd0 > /home/backup/partitions

# backup MegaCli config
#megacli -CfgSave -f /home/backup/megacli_conf.dump -a0 >/dev/null

## Dump network routes with mtr and traceroute (warning: could be long with aggressive firewalls)
for addr in 8.8.8.8 backup.evolix.net www.evolix.fr www.evolix.net; do
mtr -r $addr > /home/backup/mtr-${addr} 2>/dev/null
traceroute -n $addr > /home/backup/traceroute-${addr} 2>/dev/null
done

## Dump process with ps
ps aux >/home/backup/ps.out

if [ $SYSTEME = "linux" ]; then
## Dump network connections with netstat
netstat -taupen >/home/backup/netstat.out

## List Debian packages
dpkg -l >/home/backup/packages
else
## Dump network connections with netstat
netstat -finet -atn >/home/backup/netstat.out

## List OpenBSD packages
pkg_info -m >/home/backup/packages
fi

HOSTNAME=$(hostname)

DATE=$(/bin/date +"%d-%m-%Y")

DEBUT=$(/bin/date +"%d-%m-%Y ; %H:%M")

if [ $SYSTEME = "linux" ]; then
rep="/bin /boot /lib /opt /sbin /usr"
else
rep="/bsd /bin /sbin /usr"
fi

/usr/local/bin/rsync -avzh --stats --delete --delete-excluded --force --ignore-errors --partial \
--exclude "lost+found" \
--exclude ".nfs.*" \
--exclude "/var/log" \
--exclude "/var/log/evobackup*" \
--exclude "/var/lib/mysql" \
--exclude "/var/lib/postgres" \
--exclude "/var/lib/postgresql" \
--exclude "/var/lib/sympa" \
--exclude "/var/lib/metche" \
--exclude "/var/run" \
--exclude "/var/lock" \
--exclude "/var/state" \
--exclude "/var/apt" \
--exclude "/var/cache" \
--exclude "/usr/src" \
--exclude "/usr/doc" \
--exclude "/usr/share/doc" \
--exclude "/usr/obj" \
--exclude "dev" \
--exclude "/var/spool/postfix" \
--exclude "/var/lib/amavis/amavisd.sock" \
--exclude "/var/lib/munin/*tmp*" \
--exclude "/var/lib/php5" \
--exclude "/var/spool/squid" \
--exclude "/var/lib/elasticsearch" \
--exclude "/var/lib/amavis/tmp" \
--exclude "/var/lib/clamav/*.tmp" \
--exclude "/home/mysqltmp" \
$rep \
/etc \
/root \
/var \
/home \
-e "ssh -p $SSH_PORT" \
root@${SRV}:/var/backup/ \
| tail -30 >> /var/log/evobackup.log

FIN=$(/bin/date +"%d-%m-%Y ; %H:%M")

echo "EvoBackup - $HOSTNAME - START $DEBUT" \
>> /var/log/evobackup.log

echo "EvoBackup - $HOSTNAME - STOP $FIN" \
>> /var/log/evobackup.log

tail -10 /var/log/evobackup.log | \
mail -s "[info] EvoBackup - Client $HOSTNAME" \
$MAIL

+ 3
- 0
roles/base/handlers/main.yml View File

@@ -0,0 +1,3 @@
---
- name: newaliases
shell: smtpctl update table aliases

+ 13
- 0
roles/base/tasks/doas.yml View File

@@ -0,0 +1,13 @@
---
- name: Configure doas
template:
src: doas.conf.j2
dest: /etc/doas.conf
owner: root
group: wheel
mode: "0640"
backup: no
tags:
- doas



+ 63
- 0
roles/base/tasks/dotfiles.yml View File

@@ -0,0 +1,63 @@
---
- name: Customize root's .profile
copy:
src: profile
dest: /root/.profile
tags:
- admin
- dotfiles

- name: Copy vim default configuration
copy:
src: vimrc
dest: /root/.vimrc
mode: "0644"
tags:
- admin
- dotfiles
- vim

- name: Customize .kshrc environment file
copy:
src: kshrc
dest: /root/.kshrc
tags:
- admin
- dotfiles

- name: Change default .profile skeleton
copy:
src: profile
dest: /etc/skel/.profile
tags:
- admin
- dotfiles

- name: Add evomaintenance trap .profile skeleton with doas
lineinfile:
state: present
dest: /etc/skel/.profile
insertafter: EOF
line: 'trap "doas /usr/share/scripts/evomaintenance.sh" 0'
create: yes
tags:
- admin
- dotfiles

- name: Add vim configuration to dotfiles for new users
copy:
src: vimrc
dest: /etc/skel/.vimrc
mode: "0644"
tags:
- admin
- dotfiles
- vim

- name: Customize .kshrc environment file for new users
copy:
src: kshrc
dest: /etc/skel/.kshrc
tags:
- admin
- dotfiles

+ 20
- 0
roles/base/tasks/evobackup.yml View File

@@ -0,0 +1,20 @@
---
- name: Copy zzz_evobackup script
copy:
src: zzz_evobackup
dest: /usr/share/scripts/zzz_evobackup
owner: root
group: wheel
mode: "0755"
force: no
tags:
- evobackup

- name: Add evobackup cron (disabled)
lineinfile:
path: /etc/daily.local
line: '#sh /usr/share/scripts/zzz_evobackup'
owner: root
mode: "0700"
tags:
- evobackup

+ 51
- 0
roles/base/tasks/evomaintenance.yml View File

@@ -0,0 +1,51 @@
---
- name: Create scripts directory
file:
path: /usr/share/scripts/
state: directory
owner: root
group: wheel
mode: "0700"
tags:
- evomaintenance

- name: Copy evomaintenance script and template
copy: src={{ item.src }} dest={{ item.dest }} owner=root group=wheel mode="0755"
with_items:
- { src: 'evomaintenance.sh', dest: '/usr/share/scripts/' }
- { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/' }
tags:
- evomaintenance
- script-evomaintenance

- name: Configure evomaintenance
template:
src: evomaintenance.j2
dest: /etc/evomaintenance.cf
owner: root
group: wheel
mode: "0600"
backup: no
tags:
- evomaintenance

- name: Copy mailevomaintenance
template:
src: mailevomaintenance.sh.j2
dest: /usr/share/scripts/mailevomaintenance.sh
owner: root
group: wheel
mode: "0700"
tags:
- evomaintenance
- mailevomaintenance

- name: Add mailevomaintenance cron
cron:
name: "mailevomaintenance"
job: "/usr/share/scripts/mailevomaintenance.sh"
minute: "50"
hour: "22"
disabled: yes
tags:
- mailevomaintenance

+ 19
- 0
roles/base/tasks/mail.yml View File

@@ -0,0 +1,19 @@
---
- name: Configure rc.local
lineinfile:
path: /etc/rc.local
line: 'date | mail -s "boot/reboot of $(hostname -s)" {{ general_alert_email }}'
create: yes
tags:
- misc

- name: Set root mail alias
replace:
dest: /etc/mail/aliases
regexp: "# root:"
replace: "root: {{ general_alert_email }}"
backup: no
notify:
- newaliases
tags:
- mail

+ 9
- 0
roles/base/tasks/main.yml View File

@@ -0,0 +1,9 @@
---
# tasks file for evobsd-base
- include: packages.yml
- include: doas.yml
- include: dotfiles.yml
- include: evomaintenance.yml
- include: mail.yml
- include: sudo.yml
- include: evobackup.yml

+ 31
- 0
roles/base/tasks/packages.yml View File

@@ -0,0 +1,31 @@
---

- name: Configure installurl
copy:
dest: /etc/installurl
src: installurl
tags:
- pkg

- name: Install packages (vim rsync mtr etc)
openbsd_pkg:
name: "{{ item }}"
state: present
with_items:
- wget
- vim--no_x11
- rsync--
- mtr--
- iftop
- postgresql-client
tags:
- pkg

- name: Install sudo
openbsd_pkg:
name: "{{ item }}"
state: present
with_items:
- sudo--
tags:
- pkg

+ 29
- 0
roles/base/tasks/sudo.yml View File

@@ -0,0 +1,29 @@
---
# dont't break the tab!
- name: Allow wheel group to run command as root in sudo
lineinfile:
dest: /etc/sudoers
insertafter: '# and set environment variables.'
line: '%wheel ALL=(ALL) SETENV: ALL'
validate: 'visudo -cf %s'
backup: no
tags:
- sudo

- name: Configure sudoers for evomaintenance and monitoring
blockinfile:
state: present
dest: /etc/sudoers
insertafter: EOF
block: |
Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh
%wheel ALL=NOPASSWD: MAINT
_nrpe ALL=(root) NOPASSWD: /usr/local/libexec/nagios/plugins/check_ipsecctl.sh
_nrpe ALL=(root) NOPASSWD: /usr/local/libexec/nagios/check_mailq
_nrpe ALL=(root) NOPASSWD: /usr/local/libexec/nagios/plugins/check_ospfd_simple
validate: 'visudo -cf %s'
backup: no
tags:
- sudo



+ 11
- 0
roles/base/templates/doas.conf.j2 View File

@@ -0,0 +1,11 @@
# {{ ansible_managed }}
permit setenv {ENV PS1 SSH_AUTH_SOCK SSH_TTY} :wheel
permit nopass root
permit setenv {ENV PS1 SSH_AUTH_SOCK SSH_TTY} nopass :wheel as root cmd /usr/share/scripts/evomaintenance.sh
permit nopass _nrpe cmd /usr/local/libexec/nagios/check_ipsecctl.sh
permit nopass _nrpe as root cmd /sbin/bioctl args sd2
permit nopass _nrpe as root cmd /usr/local/libexec/nagios/check_openbgpd
permit nopass _collectd as root cmd /usr/sbin/bgpctl
permit nopass _nrpe as root cmd /usr/local/libexec/nagios/plugins/check_ospfd
permit nopass _nrpe as root cmd /usr/local/libexec/nagios/plugins/check_ospf6d
permit nopass _nrpe as root cmd /usr/local/libexec/nagios/plugins/check_pf_states

+ 13
- 0
roles/base/templates/evomaintenance.j2 View File

@@ -0,0 +1,13 @@
HOSTNAME={{ evomaintenance_hostname }}
EVOMAINTMAIL={{ evomaintenance_alert_email or general_alert_email | mandatory }}

export PGPASSWORD={{ evomaintenance_pg_passwd | mandatory }}

PGDB={{ evomaintenance_pg_db | mandatory }}
PGTABLE={{ evomaintenance_pg_table | mandatory }}
PGHOST={{ evomaintenance_pg_host | mandatory }}
FROM={{ evomaintenance_from }}
FULLFROM="{{ evomaintenance_full_from }}"
URGENCYFROM={{ evomaintenance_urgency_from }}
URGENCYTEL="{{ evomaintenance_urgency_tel }}"
REALM="{{ evomaintenance_realm }}"

+ 28
- 0
roles/base/templates/mailevomaintenance.sh.j2 View File

@@ -0,0 +1,28 @@
#!/bin/sh

set -eu

cd /etc && _STATUS=$(/usr/local/bin/git status --porcelain)
[ -n "${_STATUS}" ] || exit 0

if [ -e /etc/realname ]; then
_HOSTNAME=$(/bin/cat /etc/realname)
else
_HOSTNAME=$(/bin/hostname)
fi


TMPFILE=$(/usr/bin/mktemp) || exit 1
echo "Dear NOC,\n\nSome changes in /etc/ were not committed." >> $TMPFILE

echo "" >> $TMPFILE
echo "${_STATUS}" >> $TMPFILE

echo "" >> $TMPFILE
/usr/bin/last | head -n 10 >> $TMPFILE
echo "" >> $TMPFILE
echo "Please answer this mail to notify people when you've corrected the problem." >> $TMPFILE

/bin/cat $TMPFILE | mail -s "Verif etc-git ${_HOSTNAME}" noc@{{ evomaintenance_realm }}

/bin/rm $TMPFILE

+ 31
- 0
roles/etc-git/README.md View File

@@ -0,0 +1,31 @@
# etc-git

Put /etc under Git version control.

## Tasks

The main part (installation and configuration) is in the `tasks/main.yml` file.

There is also an independant task that can be executed to commit changes made in `/etc/.git`, for example when a playbook is run :

```
- name: My Splendid Playbook
[…]

pre_tasks:
- include_role:
name: etc-git
tasks_from: commit.yml
vars:
commit_message: "Ansible pre-run my splendid playbook"

roles :
[…]

post_tasks:
- include_role:
name: etc-git
tasks_from: commit.yml
vars:
commit_message: "Ansible pre-run my splendid playbook"
```

+ 4
- 0
roles/etc-git/defaults/main.yml View File

@@ -0,0 +1,4 @@
---
commit_message: Ansible run

etc_git_monitor_status: True

+ 3
- 0
roles/etc-git/files/gitignore View File

@@ -0,0 +1,3 @@
aliases.db
*.swp
random.seed

+ 56
- 0
roles/etc-git/tasks/commit.yml View File

@@ -0,0 +1,56 @@
---
- name: is /etc clean?
command: git status --porcelain
args:
chdir: /etc
changed_when: False
register: git_status
when: not ansible_check_mode
ignore_errors: yes
tags:
- etc-git
- commit-etc

- debug:
var: git_status
verbosity: 3
tags:
- etc-git
- commit-etc

- name: fetch current Git user.email
git_config:
name: user.email
repo: /etc
scope: local
register: git_config_user_email
ignore_errors: yes
tags:
- etc-git
- commit-etc

- name: set commit author
set_fact:
commit_author: '{% if ansible_env.SUDO_USER is not defined %}root{% else %}{{ ansible_env.SUDO_USER }}{% endif %}'
commit_email: '{% if git_config_user_email.config_value is not defined or git_config_user_email.config_value == "" %}root@localhost{% else %}{{ git_config_user_email.config_value }}{% endif %}'
tags:
- etc-git
- commit-etc

- name: /etc modifications are committed
shell: "git add -A . && git commit -m \"{{ commit_message | mandatory }}\" --author \"{{ commit_author | mandatory }} <{{ commit_email | mandatory }}>\""
args:
chdir: /etc
register: etc_commit_end_run
when: not ansible_check_mode and git_status.stdout != ""
ignore_errors: yes
tags:
- etc-git
- commit-etc

- debug:
var: etc_commit_end_run
verbosity: 4
tags:
- etc-git
- commit-etc

+ 118
- 0
roles/etc-git/tasks/main.yml View File

@@ -0,0 +1,118 @@
---

- name: Git is installed
openbsd_pkg:
name: git
state: present
tags:
- etc-git

- name: /etc is versioned with git
command: "git init ."
args:
chdir: /etc
creates: /etc/.git/
warn: no
register: git_init
tags:
- etc-git

- name: Git user.email is configured
git_config:
name: user.email
repo: /etc
scope: local
value: "root@{{ ansible_fqdn | default('localhost') }}"
tags:
- etc-git

- name: /etc/.git is secure
file:
path: /etc/.git
owner: root
mode: "0700"
state: directory
tags:
- etc-git

- name: /etc/.gitignore is present
copy:
src: gitignore
dest: /etc/.gitignore
owner: root
mode: "0600"
tags:
- etc-git

- name: does /etc/ have any commit?
command: "git log"
args:
chdir: /etc
warn: no
changed_when: False
failed_when: False
register: git_log
check_mode: no
tags:
- etc-git

- name: initial commit is present?
shell: "git add -A . && git commit -m \"Initial commit via Ansible\""
args:
chdir: /etc
warn: no
register: git_commit
when: git_log.rc != 0 or (git_init is defined and git_init.changed)
tags:
- etc-git

- name: Optimize script is installed in monthly crontab
lineinfile:
path: /etc/monthly.local
line: '/usr/local/bin/git --git-dir /etc/.git gc --quiet'
owner: root
mode: "0700"
create: yes
tags:
- etc-git

- name: cron job for /etc/.git status is installed
lineinfile:
path: /etc/daily.local
line: '/usr/local/bin/git --git-dir=/etc/.git --work-tree=/etc status --short'
owner: root
mode: "0700"
create: yes
when: etc_git_monitor_status
tags:
- etc-git

- name: cron job for /etc/.git status is removed
lineinfile:
path: /etc/daily.local
line: '/usr/local/bin/git --git-dir=/etc/.git --work-tree=/etc status --short'
owner: root
mode: "0700"
state: absent
when: not etc_git_monitor_status
tags:
- etc-git

- name: hourly cron job for /etc/.git status is installed
cron:
name: git status
minute: 42
job: "who > /dev/null || /usr/local/bin/git --git-dir=/etc/.git --work-tree=/etc status --short"
when: etc_git_monitor_status
tags:
- etc-git

- name: hourly cron job for /etc/.git status is removed
cron:
name: git status
minute: 42
job: "who > /dev/null || /usr/local/bin/git --git-dir=/etc/.git --work-tree=/etc status --short"
state: absent
when: not etc_git_monitor_status
tags:
- etc-git

+ 18
- 0
roles/forwarding/tasks/main.yml View File

@@ -0,0 +1,18 @@
---
- name: Enable IPv4 forwarding
sysctl:
name: net.inet.ip.forwarding
value: 1
state: present
reload: yes
tags:
- net

- name: Enable IPv6 forwarding
sysctl:
name: net.inet6.ip6.forwarding
value: 1
state: present
reload: yes
tags:
- net

+ 13
- 0
roles/nagios-nrpe/README.md View File

@@ -0,0 +1,13 @@
# nagios-nrpe

Installation and custom configuration of Nagios NRPE server.

## Tasks

Everything is in the `tasks/main.yml` file.

## Available variables

* `nagios_nrpe_allowed_hosts` : list of IP/hosts authorized (default: none).

The full list of variables (with default values) can be found in `defaults/main.yml`.

+ 13
- 0
roles/nagios-nrpe/defaults/main.yml View File

@@ -0,0 +1,13 @@
---
evolix_trusted_ips: []
additional_trusted_ips: []
# Let's merge evolix_trusted_ips with additional_trusted_ips
nagios_nrpe_allowed_hosts: "{{ evolix_trusted_ips | union(additional_trusted_ips) | unique }}"
nagios_nrpe_ldap_dc: "dc=DOMAIN,dc=EXT"
nagios_nrpe_ldap_passwd: LDAP_PASSWD
nagios_nrpe_pgsql_passwd: PGSQL_PASSWD
nagios_nrpe_amavis_from: "foobar@{{ ansible_domain }}"

nagios_nrpe_check_proxy_host: "www.example.com"

nagios_plugins_directory: "/usr/local/lib/nagios/plugins"

+ 65
- 0
roles/nagios-nrpe/files/plugins_bsd/check_carp_if View File

@@ -0,0 +1,65 @@
#!/bin/sh

# Copyright (c) 2012, Claudiu Vasadi
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of the FreeBSD Project.


#
# Script to check the state (master/backup) of a carp internface
# $1 - carp if
# $2 - state
#

. /usr/local/libexec/nagios/utils.sh

# check if $1 and $2 is set
if [ -z "$1" ];then
echo "carp interface not set. Exiting ..."
exit "$STATE_CRITICAL"
fi

if [ -z "$2" ];then
echo "Interface status not set. Exiting ..."
exit "$STATE_CRITICAL"
fi

# check if the carp interface exists or not
ifconfig $1 > /dev/null
if [ $? != "0" ];then
echo "carp interface $1 does not exist. Exiting ...."
exit "$STATE_CRITICAL"
fi

# check state
ifconfig $1 | grep -i $2 > /dev/null
if [ $? != "0" ];then
echo "NOT_OK - $1 should be $2"
exit "$STATE_CRITICAL"
else
echo "OK - $1 is $2"
exit "$STATE_OK"
fi

+ 23
- 0
roles/nagios-nrpe/files/plugins_bsd/check_ipsecctl.sh View File

@@ -0,0 +1,23 @@
#!/bin/sh
IPSECCTL="/sbin/ipsecctl -s sa"
STATUS=0

LINE1=`$IPSECCTL | grep "from $1 to $2" `
if [ $? -eq 1 ]; then
STATUS=2;
OUTPUT1="No VPN from $1 to $2 "
fi

LINE2=`$IPSECCTL | grep "from $2 to $1" `
if [ $? -eq 1 ]; then
STATUS=2;
OUTPUT2="No VPN from $2 to $1"
fi

if [ $STATUS -eq 0 ]; then
echo "VPN OK - $3 is up"
exit $STATUS
else
echo "VPN DOWN - $3 is down ($OUTPUT1 $OUTPUT2)"
exit $STATUS
fi

+ 9
- 0
roles/nagios-nrpe/files/plugins_bsd/check_openvpn View File

@@ -0,0 +1,9 @@
#!/bin/sh

if netstat -an|grep '.1194' >/dev/null; then
echo "VPN OK"
return 0
else
echo "PROCESS NOT LISTENING"
return 2
fi

+ 12
- 0
roles/nagios-nrpe/files/plugins_bsd/check_ospfd_simple View File

@@ -0,0 +1,12 @@
#!/bin/sh

. /usr/local/libexec/nagios/utils.sh

# check if ospfd is running
if [[ "$(ospfctl show 2>&1)" = *"/var/run/ospfd.sock:"* ]]; then
echo "CRITICAL - OSPFD not running"
exit "$STATE_CRITICAL"
else
echo "OK - OSPFD is running"
exit "$STATE_OK"
fi

+ 5
- 0
roles/nagios-nrpe/handlers/main.yml View File

@@ -0,0 +1,5 @@
---
- name: restart nrpe
service:
name: nrpe
state: restarted

+ 60
- 0
roles/nagios-nrpe/tasks/main.yml View File

@@ -0,0 +1,60 @@
---
- name: Install nrpe
openbsd_pkg:
name: "{{ item }}"
state: present
with_items:
- nrpe--

- name: Install monitoring-plugins
openbsd_pkg:
name: "{{ item }}"
state: present
with_items:
- monitoring-plugins

- name: Create nrpe.d dir
file:
path: /etc/nrpe.d
state: directory
owner: root
group: wheel
mode: "0755"

- name: Include nrpe.d dir in nrpe.cfg
lineinfile:
dest: /etc/nrpe.cfg
line: 'include_dir=/etc/nrpe.d'

- name: custom configuration is present
template:
src: evolix_bsd.cfg.j2
dest: /etc/nrpe.d/evolix.cfg
notify: restart nrpe

- name: Nagios plugins are installed
copy:
src: plugins_bsd/
dest: /usr/local/libexec/nagios/plugins/
owner: root
group: wheel
mode: "0755"
notify: restart nrpe

- name: Nagios plugins are installed - template
template:
src: plugins_bsd/{{ item }}.j2
dest: /usr/local/libexec/nagios/plugins/{{ item }}
owner: root
group: wheel
mode: "0755"
with_items:
- 'check_pf_states'
- 'check_free_mem.sh'
notify: restart nrpe

- name: Starting and enabling nrpe
service:
name: nrpe
enabled: yes
state: started

+ 38
- 0
roles/nagios-nrpe/templates/evolix_bsd.cfg.j2 View File

@@ -0,0 +1,38 @@
#
# Custom NRPE configuration file.
# Part of the EvoBSD distribution.
#

# Allowed IPs
allowed_hosts={{ nagios_nrpe_allowed_hosts | join(',') }}

command[check_users]=/usr/local/libexec/nagios/check_users -w 5 -c 10
command[check_load]=/usr/local/libexec/nagios/check_load -w 15,10,5 -c 30,25,20
command[check_disk1]=/usr/local/libexec/nagios/check_disk -x /lib/init/rw -x /dev -x /dev/shm -w 10% -c 3% -W 10% -K 3% -C -w 5% -c 2% -W 5% -K 2% -p /home
command[check_zombie_procs]=/usr/local/libexec/nagios/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/local/libexec/nagios/check_procs -w 150 -c 200
command[check_imap]=/usr/local/libexec/nagios/check_imap -H localhost
command[check_smtp]=/usr/local/libexec/nagios/check_smtp -H localhost -f {{ general_alert_email }}
command[check_dns]=/usr/local/libexec/nagios/check_dns -H evolix.net
command[check_swap]=/usr/local/libexec/nagios/check_swap --no-swap=ok -a -w 30% -c 20%
command[check_ntp]=/usr/local/libexec/nagios/check_ntp -H ntp.evolix.net
command[check_http]=/usr/local/libexec/nagios/check_http -H localhost -p 80
command[check_onduleur]=/usr/local/libexec/nagios/check_ups -H localhost -u onduleur
# Pour check_mailq, ajouter dans sudo :
# _nrpe ALL=NOPASSWD: /usr/local/libexec/nagios/check_mailq
command[check_mailq]=sudo /usr/local/libexec/nagios/check_mailq -w 10 -c 20
command[check_bind]=/usr/local/libexec/nagios/check_dig -l evolix.net -H localhost
command[check_ssh]=/usr/local/libexec/nagios/check_ssh -p 22 localhost
command[check_proxy]=/usr/local/libexec/nagios/check_tcp -p PORT
#command[check_vpn]=/usr/local/libexec/nagios/check_ping -H IPDISTANTE -p 1 -w 5000,100% -c 5000,100%
command[check_vpn]=sudo /usr/local/libexec/nagios/plugins/check_ipsecctl.sh IPDISTANTE IPLOCALE "VPN MARSEILLE-ROME"
command[check_openvpn]=/usr/local/libexec/nagios/plugins/check_openvpn
command[check_pf_states]=doas /usr/local/libexec/nagios/plugins/check_pf_states
command[check_carp1]=/usr/local/libexec/nagios/plugins/check_carp_if carp0 master
command[check_mem]=/usr/local/libexec/nagios/plugins/check_free_mem.sh -w 20 -c 10
command[check_dhcpclient]=/usr/local/libexec/nagios/check_dhcp -i INTERFACE
command[check_smb]=/usr/local/libexec/nagios/check_tcp -H IPLOCALE -p 445
#command[check_ospfd]=doas /usr/local/libexec/nagios/plugins/check_ospfd
#command[check_ospf6d]=doas /usr/local/libexec/nagios/plugins/check_ospf6d
command[check_ospfd_simple]=sudo /usr/local/libexec/nagios/plugins/check_ospfd_simple
command[check_mysql]=/usr/local/libexec/nagios/check_mysql -H 127.0.0.1 -f /etc/nrpe.d/.my.cnf

+ 166
- 0
roles/nagios-nrpe/templates/plugins_bsd/check_free_mem.sh.j2 View File

@@ -0,0 +1,166 @@
#!/bin/ksh

################################################################################
# Sample Nagios plugin to monitor free memory on the local machine #
# Author: Daniele Mazzocchio (http://www.kernel-panic.it/) #
################################################################################

VERSION="Version 1.0"
AUTHOR="(c) 2007-2009 Daniele Mazzocchio (danix@kernel-panic.it)"

PROGNAME=`/usr/bin/basename $0`

# Constants
BYTES_IN_MB=$(( 1024 * 1024 ))
KB_IN_MB=1024

# Exit codes
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3

# Helper functions #############################################################

function print_revision {
# Print the revision number
echo "$PROGNAME - $VERSION"
}

function print_usage {
# Print a short usage statement
echo "Usage: $PROGNAME [-v] -w <limit> -c <limit>"
}

function print_help {
# Print detailed help information
print_revision
echo "$AUTHOR\n\nCheck free memory on local machine\n"
print_usage

/bin/cat <<__EOT

Options:
-h
Print detailed help screen
-V
Print version information

-w INTEGER
Exit with WARNING status if less than INTEGER MB of memory are free
-w PERCENT%
Exit with WARNING status if less than PERCENT of memory is free
-c INTEGER
Exit with CRITICAL status if less than INTEGER MB of memory are free
-c PERCENT%
Exit with CRITICAL status if less than PERCENT of memory is free
-v
Verbose output
__EOT
}

# Main #########################################################################

# Total memory size (in MB)
tot_mem=$(( `/sbin/sysctl -n hw.physmem` / BYTES_IN_MB))
# Free memory size (in MB)
{% if ansible_distribution_version | version_compare("6.2",'<') %}
free_mem=$(( `/usr/bin/vmstat | /usr/bin/tail -1 | /usr/bin/awk '{ print $5 }'` / KB_IN_MB ))
{% else %}
free_mem=$(/usr/bin/vmstat | /usr/bin/tail -1 | /usr/bin/awk '{ print $4 }' | tr -d 'M')
{% endif %}
# Free memory size (in percentage)
free_mem_perc=$(( free_mem * 100 / tot_mem ))

# Verbosity level
verbosity=0
# Warning threshold
thresh_warn=
# Critical threshold
thresh_crit=

# Parse command line options
while [ "$1" ]; do
case "$1" in
-h | --help)
print_help
exit $STATE_OK
;;
-V | --version)
print_revision
exit $STATE_OK
;;
-v | --verbose)
: $(( verbosity++ ))
shift
;;
-w | --warning | -c | --critical)
if [[ -z "$2" || "$2" = -* ]]; then
# Threshold not provided
echo "$PROGNAME: Option '$1' requires an argument"
print_usage
exit $STATE_UNKNOWN
elif [[ "$2" = +([0-9]) ]]; then
# Threshold is a number (MB)
thresh=$2
elif [[ "$2" = +([0-9])% ]]; then
# Threshold is a percentage
thresh=$(( tot_mem * ${2%\%} / 100 ))
else
# Threshold is neither a number nor a percentage
echo "$PROGNAME: Threshold must be integer or percentage"
print_usage
exit $STATE_UNKNOWN
fi
[[ "$1" = *-w* ]] && thresh_warn=$thresh || thresh_crit=$thresh
shift 2
;;
-?)
print_usage
exit $STATE_OK
;;
*)
echo "$PROGNAME: Invalid option '$1'"
print_usage
exit $STATE_UNKNOWN
;;
esac
done

if [[ -z "$thresh_warn" || -z "$thresh_crit" ]]; then
# One or both thresholds were not specified
echo "$PROGNAME: Threshold not set"
print_usage
exit $STATE_UNKNOWN
elif [[ "$thresh_crit" -gt "$thresh_warn" ]]; then
# The warning threshold must be greater than the critical threshold
echo "$PROGNAME: Warning free space should be more than critical free space"
print_usage
exit $STATE_UNKNOWN
fi

if [[ "$verbosity" -ge 2 ]]; then
# Print debugging information
/bin/cat <<__EOT
Debugging information:
Warning threshold: $thresh_warn MB
Critical threshold: $thresh_crit MB
Verbosity level: $verbosity
Total memory: $tot_mem MB
Free memory: $free_mem MB ($free_mem_perc%)
__EOT
fi

if [[ "$free_mem" -lt "$thresh_crit" ]]; then
# Free memory is less than the critical threshold
echo "MEMORY CRITICAL - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"
exit $STATE_CRITICAL
elif [[ "$free_mem" -lt "$thresh_warn" ]]; then
# Free memory is less than the warning threshold
echo "MEMORY WARNING - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"
exit $STATE_WARNING
else
# There's enough free memory!
echo "MEMORY OK - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"
exit $STATE_OK
fi

+ 22
- 0
roles/nagios-nrpe/templates/plugins_bsd/check_pf_states.j2 View File

@@ -0,0 +1,22 @@
#!/bin/sh

# Script writen by Evolix

_MAX_STATES_LIMIT=$(/sbin/pfctl -sm | /usr/bin/grep states | awk '{print $4}')
_WARNING_STATES_LIMIT=$((_MAX_STATES_LIMIT*10/100))
_CRTICAL_STATES_LIMIT=$((_MAX_STATES_LIMIT*15/100))

. /usr/local/libexec/nagios/utils.sh

_CHECK_STATES=$(/sbin/pfctl -si | /usr/bin/grep current | awk '{print $3}')

if [ $_CHECK_STATES -lt $_WARNING_STATES_LIMIT ];then
echo "OK: States number ($_CHECK_STATES) is below threshold (warn : $_WARNING_STATES_LIMIT / crit : $_CRTICAL_STATES_LIMIT / max : $_MAX_STATES_LIMIT)"
exit "$STATE_OK"
elif [ $_CHECK_STATES -ge $_WARNING_STATES_LIMIT ] && [ $_CHECK_STATES -lt $_CRTICAL_STATES_LIMIT ];then
echo "WARNING: States number is $_CHECK_STATES (threshold WARNING = $_WARNING_STATES_LIMIT, max = $_MAX_STATES_LIMIT)"
exit "$STATE_WARNING"
else
echo "CRITICAL: States number is $_CHECK_STATES (threshold CRITICAL = $_CRTICAL_STATES_LIMIT, max = $_MAX_STATES_LIMIT)"
exit "$STATE_CRITICAL"
fi

+ 7
- 0
roles/pf/tasks/main.yml View File

@@ -0,0 +1,7 @@
---
- name: Setup pf.conf
template:
src: pf.conf.j2
dest: /etc/pf.conf
mode: "0600"
backup: yes

+ 74
- 0
roles/pf/templates/pf.conf.j2 View File

@@ -0,0 +1,74 @@
# MANAGED BY ANSIBLE, MODIFICATIONS WILL BE LOST

######################
##### INTERFACES #####
######################

ext_if="{{ ansible_default_ipv4.device }}"
#lan_if="em1"

###########################
##### TABLES & LISTES #####
###########################

# Evolix
table <evolix> { 88.179.18.233, 31.170.9.129, 31.170.8.4 }

# Port en entrée
# 2222 = ssh secondaire
# 5666 = nrpe
#tcp_in = "{ domain, ldap, ldaps, imap, imaps, pop3, pop3s, ssh, smtp, http, https, ftp, ftp-data, smtps, submission, 2222 }"
tcp_in = "{ http, https }"

# 33433><33626 = traceroute
#udp_in = "{ domain, ntp, 33433><33626 }"
udp_in = "{ 33433><33626 }"


###################
##### OPTIONS #####
###################

set block-policy return
set optimization normal
#set optimization aggressive
#set limit states 150000
#set limit src-nodes 25000
#set limit tables 10000
#set limit table-entries 3000
set skip on lo
match in all scrub (no-df)

####################
##### FILTRAGE #####
####################

# politiques par defaut
block log all

# filter rules and anchor for ftp-proxy(8)
#anchor "ftp-proxy/*"
#pass in quick inet proto tcp to port ftp divert-to 127.0.0.1 port 8021

#pass quick proto carp
#pass quick on $pfsync_if proto pfsync

pass out
# 9999 = pfstat, 5666 = nrpe
pass in on $ext_if proto tcp from <evolix> to (self) port { 9999, ssh, 5666 }

# Block Attack
# China 144.0.0.0/16 --> SSH
block in on $ext_if proto tcp from 144.0.0.0/16 to any port ssh

# Autorisation des protocoles
pass in on $ext_if proto tcp to !(self) port $tcp_in
pass in on $ext_if proto udp to !(self) port $udp_in

# FTP actif
# pass in on $ext_if proto tcp from any port 20 to any port 1024:65535


# Acces public
pass in proto { icmp, icmp6 }


+ 140
- 0
roles/post-install/files/ldap.sh View File

@@ -0,0 +1,140 @@
#!/bin/sh

EvoComputerName=$(hostname -s)
dnsPTRrecord=$(hostname)
HardwareMark=$(sysctl hw.vendor| sed 's#hw.vendor=##')
HardwareModel=$(sysctl hw.product| sed 's#hw.product=##')
computerIP=$(ifconfig egress | grep inet | awk -v OFS="\n" '{ print $2, $NF }'| head -1)
computerOS=OpenBSD
computerKernel=$(sysctl kern.osrelease | sed 's#kern.osrelease=##')
HardwareSerial=$(sysctl hw.serialno| sed 's#hw.serialno=##')
clientNumber="XXX"
cpuMark=$(sysctl hw.model| sed 's#hw.model=##')
cpuModel=$(sysctl hw.model| sed 's#hw.model=##')
cpuFreq=$(sysctl hw.cpuspeed| sed 's#hw.cpuspeed=##')
mem=$(expr $(sysctl hw.physmem| sed 's#hw.physmem=##') / 1000000)Mo
eth0Mark=unknown
eth0Model=unknown
eth0MAC=$(ifconfig egress | awk -v OFS="\n" '{ print $2, $NF }' | head -3 | tail -1)
eth0IP=$(ifconfig egress | grep inet | awk -v OFS="\n" '{ print $2, $NF }'| head -1)
screen0Mark=none
screen0Model=none
sdaSize=100G
sdaModel=unknown
swap=unknown
nrpeVersion=$(pkg_info nrpe | head -1 | sed 's/Information for inst://')
openvpnVersion=$(pkg_info openvpn | head -1 | sed 's/Information for inst://')
opensshFingerprintRSA=$(ssh-keyscan -t rsa localhost 2>/dev/null\
| sed -e 's/localhost //' -e 's/ssh-rsa /ssh-rsa,/')
opensshFingerprintED25519=$(ssh-keyscan -t ed25519 localhost 2>/dev/null\
| sed -e 's/localhost //' -e 's/ssh-ed25519 /ssh-ed25519,/')
opensshFingerprintECDSA=$(ssh-keyscan -t ecdsa-sha2-nistp256 localhost 2>/dev/null\
| sed -e 's/localhost //' -e 's/ecdsa-sha2-nistp256 /ecdsa-sha2-nistp256,/')
Fingerprint="${opensshFingerprintRSA}${opensshFingerprintRSA:+;}"\
"${opensshFingerprintED25519}${opensshFingerprintED25519:+;}${opensshFingerprintECDSA}"

cat<<EOT>/root/${EvoComputerName}.ldif
# ldapvi --profile evolix --add --in ${EvoComputerName}.ldif

dn: EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
dnsArecord: $EvoComputerName
EvoComputerName: $EvoComputerName
HardwareMark: $HardwareMark
HardwareModel: $HardwareModel
dnsZone: evolix.net
objectClass: EvoComputer
objectClass: top
computerIP: $computerIP
dnsPTRrecord: $dnsPTRrecord
computerOS: $computerOS
computerKernel: $computerKernel
isActive: TRUE
NagiosEnabled: TRUE
NagiosComments: icmp,everytime,10
HardwareSerial: $HardwareSerial
clientNumber: $clientNumber

dn: HardwareName=cpu0,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
HardwareMark: $cpuMark
objectClass: EvoHardware
HardwareName: cpu0
HardwareSize: $cpuFreq
HardwareType: CPU
HardwareModel: $cpuModel

dn: HardwareName=ram0,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
HardwareName: ram0
objectClass: EvoHardware
HardwareSize: $mem
HardwareType: mem
NagiosEnabled: TRUE

dn: HardwareName=eth0,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
HardwareMark: $eth0Mark
objectClass: EvoHardware
HardwareName: eth0
HardwareSize: 1Gigabit
HardwareType: netcard
HardwareAddress: $eth0MAC
HardwareModel: $eth0Model
HardwareIP: $eth0IP

dn: HardwareName=screen0,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
HardwareMark: $screen0Mark
HardwareName: screen0
objectClass: EvoHardware
HardwareModel: $screen0Model
HardwareType: video

dn: HardwareName=sda,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
objectClass: EvoHardware
HardwareName: sda
HardwareSize: $sdaSize
HardwareType: disk
HardwareModel:${sdaModel}
HardwarePartitioncount: 1
NagiosEnabled: TRUE

dn: HardwareName=swap,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
objectClass: EvoHardware
HardwareName: swap
HardwareSize: $swap
HardwareType: mem
NagiosEnabled: TRUE

dn: ServiceName=nrpe,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
NagiosEnabled: TRUE
ipServiceProtocol: TCP
ServiceVersion: $nrpeVersion
objectClass: EvoService
ServiceName: nrpe
ipServicePort: 5666
ServiceType: monitoring

dn: ServiceName=openssh,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
ipServiceProtocol: tcp
NagiosEnabled: TRUE
ServiceFingerprint: $Fingerprint
objectClass: EvoService
ipServicePort: 22
ServiceName: openssh
ServiceType: ssh
ServiceVersion: OpenSSH 6.7

dn: ServiceName=opensmtpd,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
ipServiceProtocol: tcp
NagiosEnabled: TRUE
objectClass: EvoService
ServiceName: opensmtpd
ipServicePort: 25
ServiceType: smtp
ServiceVersion: OpenSMTPD 5.4.3

dn: ServiceName=ntp,EvoComputerName=${EvoComputerName},ou=computer,dc=evolix,dc=net
NagiosEnabled: TRUE
objectClass: EvoService
ServiceName: ntp
ServiceType: ntp
ServiceVersion: OpenNTPd 4.6

EOT

+ 5
- 0
roles/post-install/tasks/ldif.yml View File

@@ -0,0 +1,5 @@
---
- name: Generate ldif for LDAP
script: ldap.sh
args:
creates: "/root/*.ldif"

+ 4
- 0
roles/post-install/tasks/main.yml View File

@@ -0,0 +1,4 @@
---
# tasks files
- include: ldif.yml
- include: update.yml

+ 9
- 0
roles/post-install/tasks/update.yml View File

@@ -0,0 +1,9 @@
---
- name: Fetch and install openup
get_url:
url: https://stable.mtier.org/openup
dest: /usr/local/bin/openup
mode: "0750"

- name: Install updates (erratas) with openup
shell: /usr/local/bin/openup

+ 21
- 0
tasks/commit_etc_git.yml View File

@@ -0,0 +1,21 @@
---
- name: is /etc clean?
command: git status --porcelain
args:
chdir: /etc
changed_when: False
register: git_status
when: not ansible_check_mode
ignore_errors: yes
tags:
- commit-etc

- name: /etc modifications are committed
shell: "git add -A . && git commit -m \"{{ commit_message | default('Ansible run') }}\" --author=\"{{ ansible_env.SUDO_USER | default('Root') }} <{{ ansible_env.SUDO_USER | default('Root') }}@{{ general_technical_realm }}>\""
args:
chdir: /etc
register: etc_commit_end_evolinux
when: not ansible_check_mode and git_status.stdout != ""
ignore_errors: yes
tags:
- commit-etc

+ 33
- 0
vars/main.yml View File

@@ -0,0 +1,33 @@
---
########################################################
## Edit and uncomment to overwrite the default values ##
########################################################

#ntpd_servers:
#- "ntp.evolix.net"
#
#general_alert_email: "root@localhost"
#general_technical_realm: "example.com"
#
#evomaintenance_realm: "example.com"
#evomaintenance_alert_email: "evomaintenance-{{ inventory_hostname }}@{{ evomaintenance_realm }}"
#evomaintenance_hostname: "{{ inventory_hostname }}.{{ general_technical_realm }}"
#evomaintenance_pg_host: Null
#evomaintenance_pg_passwd: Null
#evomaintenance_pg_db: Null
#evomaintenance_pg_table: Null
#evomaintenance_from_domain: "{{ evomaintenance_realm }}"
#evomaintenance_from: "evomaintenance@{{ evomaintenance_from_domain }}"
#evomaintenance_full_from: "Evomaintenance <{{ evomaintenance_from }}>"
#evomaintenance_urgency_from: mama.doe@example.com
#evomaintenance_urgency_tel: "06.00.00.00.00"
#
#evolix_users:
# foo:
# name: foo
# uid: 1042
# fullname: 'Foo Bar (Evolix)'
# groups: []
# password_hash_openbsd: ''
# ssh_keys:
# - 'ssh-rsa XXXXXXX'

Loading…
Cancel
Save