From 4effe91b9f0552355ff0bc09d7ff3dc4604da1c1 Mon Sep 17 00:00:00 2001 From: Jeremy Dubois Date: Mon, 24 Jan 2022 19:12:48 +0100 Subject: [PATCH] Write an openvpn role --- openvpn/README.md | 19 ++ openvpn/defaults/main.yml | 7 + openvpn/files/check_openvpn.pl | 215 +++++++++++++++ openvpn/files/check_openvpn_certificates.sh | 140 ++++++++++ openvpn/handlers/main.yml | 6 + openvpn/tasks/main.yml | 285 ++++++++++++++++++++ openvpn/templates/ovpn.conf.j2 | 12 + openvpn/templates/server.conf.j2 | 31 +++ 8 files changed, 715 insertions(+) create mode 100644 openvpn/README.md create mode 100644 openvpn/defaults/main.yml create mode 100644 openvpn/files/check_openvpn.pl create mode 100644 openvpn/files/check_openvpn_certificates.sh create mode 100644 openvpn/handlers/main.yml create mode 100644 openvpn/tasks/main.yml create mode 100644 openvpn/templates/ovpn.conf.j2 create mode 100644 openvpn/templates/server.conf.j2 diff --git a/openvpn/README.md b/openvpn/README.md new file mode 100644 index 00000000..f68b9d66 --- /dev/null +++ b/openvpn/README.md @@ -0,0 +1,19 @@ +# OpenVPN + +Install and configure OpenVPN, based on [our HowtoOpenVPN wiki](https://wiki.evolix.org/HowtoOpenVPN) + +## Tasks + +Everything is in the `tasks/main.yml` file. +Some manual actions are requested at the end of the playbook, to do before finishing the playbook. + +## Variables + +* `openvpn_lan`: 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 + +## TODO + +* Make it compatible with OpenBSD +* See TODO tasks in tasks/main.yml diff --git a/openvpn/defaults/main.yml b/openvpn/defaults/main.yml new file mode 100644 index 00000000..6fcc7197 --- /dev/null +++ b/openvpn/defaults/main.yml @@ -0,0 +1,7 @@ +--- + +# openvpn_lan default to 10."last 2 digit of main IP of server".0/24. For example, if the server IP is 192.0.2.42, then openvpn_lan will be 10.2.42.0/24 +openvpn_lan: "10.{{ ansible_default_ipv4.address | regex_search('([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})', '\\3', '\\4') | join('.') }}.0" +openvpn_netmask: "255.255.255.0" +openvpn_netmask_cidr: "{{ (openvpn_lan + '/' + openvpn_netmask) | ipaddr('prefix') }}" + diff --git a/openvpn/files/check_openvpn.pl b/openvpn/files/check_openvpn.pl new file mode 100644 index 00000000..270fd1e9 --- /dev/null +++ b/openvpn/files/check_openvpn.pl @@ -0,0 +1,215 @@ +#!/usr/bin/perl -w + +####################################################################### +# +# Copyright (c) 2007 Jaime Gascon Romero +# +# License Information: +# 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, or +# (at your option) any later version. +# +# 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, see . +# +# $Id: check_openvpn.pl,v 1.1 2014/09/29 08:39:24 rdessort Exp $ +# $Revision: 1.1 $ +# Home Site: http://emergeworld.blogspot.com/ +# ##################################################################### + +use diagnostics; +use strict; +use Net::Telnet (); +use Getopt::Long qw(:config no_ignore_case); +use vars qw($PROGNAME $VERSION); +use lib "/usr/lib/nagios/plugins/"; +use utils qw(%ERRORS); + +$PROGNAME = "check_openvpn"; +$VERSION = '$Revision: 1.1 $'; + +$ENV{'PATH'}=''; +$ENV{'BASH_ENV'}=''; +$ENV{'ENV'}=''; + +my ($opt_h, $opt_H, $opt_p, $opt_P, $opt_t, $opt_i, $opt_n, $opt_c, $opt_w, $opt_C, $opt_r); + +sub print_help (); +sub print_usage (); + +GetOptions + ("h" => \$opt_h, "help" => \$opt_h, + "H=s" => \$opt_H, "host=s" => \$opt_H, + "p=i" => \$opt_p, "port=i" => \$opt_p, + "P=s" => \$opt_P, "password=s" => \$opt_P, + "t=i" => \$opt_t, "timeout=i" => \$opt_t, + "i" => \$opt_i, "ip" => \$opt_i, + "n" => \$opt_n, "numeric" => \$opt_n, + "c" => \$opt_c, "critical" => \$opt_c, + "w" => \$opt_w, "warning" => \$opt_w, + "C=s" => \$opt_C, "common_name=s" => \$opt_C, + "r=s" => \$opt_r, "remote_ip=s" => \$opt_r, + ) or exit $ERRORS{'UNKNOWN'}; + +# default values +unless ( defined $opt_t ) { + $opt_t = 10; +} + +if ($opt_h) {print_help(); exit $ERRORS{'OK'};} + +if ( ! defined($opt_H) || ! defined($opt_p) ) { + print_usage(); + exit $ERRORS{'UNKNOWN'} +} + +my @lines; +my @clients; +my @clients_ip; +my $t; + +eval { +$t = new Net::Telnet (Timeout => $opt_t, + Port => $opt_p, + Prompt => '/END$/' + ); +$t->open($opt_H); +if ( defined $opt_P ) { + $t->waitfor('/ENTER PASSWORD:$/'); + $t->print($opt_P); +} +$t->waitfor('/^$/'); +@lines = $t->cmd("status 2"); +$t->close; +}; + +if ($@) { + print "OpenVPN Critical: Can't connect to server\n"; + exit $ERRORS{'CRITICAL'}; +} + + +if (defined $opt_i || defined $opt_r) { + foreach (@lines) { + if ($_ =~ /CLIENT_LIST,.*,(\d+\.\d+\.\d+\.\d+):\d+,/) { + push @clients_ip, $1; + } +} + if (defined $opt_i) { + print "OpenVPN OK: "."@clients_ip "; + exit $ERRORS{'OK'}; + } elsif (defined $opt_r) { + if ( ! grep /\b$opt_r\b/, @clients_ip) { + if (defined $opt_c) { + print "OpenVPN CRITICAL: $opt_r don't found"; + exit $ERRORS{'CRITICAL'}; + } else { + print "OpenVPN WARNING: $opt_r don't found"; + exit $ERRORS{'WARNING'}; + } + } + print "OpenVPN OK: "."@clients_ip "; + exit $ERRORS{'OK'}; + } +} + +foreach (@lines) { + if ($_ =~ /CLIENT_LIST,(.*),\d+\.\d+\.\d+\.\d+:\d+,/) { + push @clients, $1; + } +} + +if (defined $opt_C) { + if ( ! grep /\b$opt_C\b/, @clients) { + if (defined $opt_c) { + print "OpenVPN CRITICAL: $opt_C don't found"; + exit $ERRORS{'CRITICAL'}; + } else { + print "OpenVPN WARNING: $opt_C don't found"; + exit $ERRORS{'WARNING'}; + } + } +} + + +if (defined $opt_n) { +print "OpenVPN OK: ".@clients." connected clients."; +exit $ERRORS{'OK'}; +} + +print "OpenVPN OK: "."@clients "; +exit $ERRORS{'OK'}; + +####################################################################### +###### Subroutines #################################################### + +sub print_usage() { + print "Usage: $PROGNAME -H | --host -p | --port [-P | --password] [-t | --timeout] + [-i | --ip] [-n | --numeric] [-C | --common_name] [-r | --remote_ip] [-c | --critical] [-w | --warning]\n\n"; + print " $PROGNAME [-h | --help]\n"; +} + +sub print_help() { + print "$PROGNAME $VERSION\n\n"; + print "Copyright (c) 2007 Jaime Gascon Romero + +Nagios plugin to check the clients connected to a openvpn server. + +"; + print_usage(); + print " +-H | --host + IP address or hostname of the openvpn server. + +-p | --port + Management port interface of the openvpn server. + +-P | --password + Password for the management interface of the openvpn server. + +-t | --timeout + Timeout for the connection attempt. Optional, default 10 seconds. + + + Optional parameters + =================== + +-i | --ip + Prints the IP address of the remote client instead of the common name. + +-n | --numeric + Prints the number of clients connected to the openvpn server. + + + Matching Parameters + =================== + +-C | --common_name + The common name, as it is specified in the client certificate, who is wanted to check. + +-r | --remote_ip + The client remote ip address who is wanted to check. + +-c | --critical + Exits with CRITICAL status if the client specified by the common name or the remote ip address is not connected. + +-w | --warning + Exits with WARNING status if the client specified by the common name or the remote ip address is not connected. + + + Other Parameters + ================ + +-h | --help + Show this help. +"; + +} + +# vim:sts=2:sw=2:ts=2:et diff --git a/openvpn/files/check_openvpn_certificates.sh b/openvpn/files/check_openvpn_certificates.sh new file mode 100644 index 00000000..47dca4b6 --- /dev/null +++ b/openvpn/files/check_openvpn_certificates.sh @@ -0,0 +1,140 @@ +#!/bin/sh + +set -eu + +trap error 0 + +STATE_OK=0 +STATE_WARNING=1 +STATE_CRITICAL=2 +STATE_UNKNOWN=3 +STATE=$STATE_OK +CERT_STATE=$STATE +CA_STATE=$STATE +CERT_ECHO="" +CA_ECHO="" + +error() { + if [ $? -eq 2 ] && [ "X$CERT_ECHO" = "X" ] && [ "X$CA_ECHO" = "X" ] ; then + echo "CRITICAL - The check exited with an error. Is the conf_file var containing the real conf file location ? On Debian, is the check executed with sudo ?" + fi +} + +SYSTEM=$(uname | tr '[:upper:]' '[:lower:]') +date_cmd=$(command -v date) + +# Dates in seconds +_15_days="1296000" +_30_days="2592000" +current_date=$($date_cmd +"%s") + +# Trying to define the OpenVPN conf file location - default to /etc/openvpn/server.conf +conf_file=$(ps auwwwx | grep openvpn | grep -- --config | grep -v sed | sed -e "s/.*config \(\/etc\/openvpn.*.conf\).*/\1/" | head -1) +[ "$SYSTEM" = "openbsd" ] && conf_file=${conf_file:-$(grep openvpn_flags /etc/rc.conf.local | sed -e "s/.*config \(\/etc\/openvpn.*.conf\).*/\1/")} +conf_file=${conf_file:-"/etc/openvpn/server.conf"} + +# Get the cert and ca file location, based on the OpenVPN conf file location +# Done in 2 times because sh does not support pipefail - needed in the case where $conf_file does not exist +cert_file=$(grep -s "^cert " $conf_file) +cert_file=$(echo $cert_file | sed -e "s/^cert *\//\//") +ca_file=$(grep -s "^ca " $conf_file) +ca_file=$(echo $ca_file | sed -e "s/^ca *\//\//") + +# Get expiration date of cert and ca certificates +cert_expiration_date=$(grep "Not After" $cert_file | sed -e "s/.*Not After : //") +ca_expiration_date=$(openssl x509 -enddate -noout -in $ca_file | cut -d '=' -f 2) + +test_cert_expiration() { + # Already expired - Cert file + if [ $current_date -ge $1 ]; then + CERT_ECHO="CRITICAL - The server certificate has expired on $formatted_cert_expiration_date" + CERT_STATE=$STATE_CRITICAL + # Expiration in 15 days or less - Cert file + elif [ $((current_date+_15_days)) -ge $1 ]; then + CERT_ECHO="CRITICAL - The server certificate expires in 15 days or less : $formatted_cert_expiration_date" + CERT_STATE=$STATE_CRITICAL + # Expiration in 30 days or less - Cert file + elif [ $((current_date+_30_days)) -ge $1 ]; then + CERT_ECHO="WARNING - The server certificate expires in 30 days or less : $formatted_cert_expiration_date" + CERT_STATE=$STATE_WARNING + # Expiration in more than 30 days - Cert file + else + CERT_ECHO="OK - The server certificate expires on $formatted_cert_expiration_date" + CERT_STATE=$STATE_OK + fi +} + +test_ca_expiration() { + # Already expired - CA file + if [ $current_date -ge $1 ]; then + CA_ECHO="CRITICAL - The server CA has expired on $formatted_ca_expiration_date" + CA_STATE=$STATE_CRITICAL + # Expiration in 15 days or less - CA file + elif [ $((current_date+_15_days)) -ge $1 ]; then + CA_ECHO="CRITICAL - The server CA expires in 15 days or less : $formatted_ca_expiration_date" + CA_STATE=$STATE_CRITICAL + # Expiration in 30 days or less - CA file + elif [ $((current_date+_30_days)) -ge $1 ]; then + CA_ECHO="WARNING - The server CA expires in 30 days or less : $formatted_ca_expiration_date" + CA_STATE=$STATE_WARNING + # Expiration in more than 30 days - CA file + else + CA_ECHO="OK - The server CA expires on $formatted_ca_expiration_date" + CA_STATE=$STATE_OK + fi +} + +# Linux and BSD systems do not implement 'date' the same way +if [ "$SYSTEM" = "linux" ]; then + + # Cert expiration date human formated then in seconds + formatted_cert_expiration_date=$(TZ="Europe/Paris" $date_cmd -d "$cert_expiration_date" +"%F %T %Z") + seconds_cert_expiration_date=$(TZ="Europe/Paris" $date_cmd -d "$cert_expiration_date" +"%s") + + # CA expiration date human formated then in seconds + formatted_ca_expiration_date=$(TZ="Europe/Paris" $date_cmd -d "$ca_expiration_date" +"%F %T %Z") + seconds_ca_expiration_date=$(TZ="Europe/Paris" $date_cmd -d "$ca_expiration_date" +"%s") + + test_cert_expiration $seconds_cert_expiration_date + test_ca_expiration $seconds_ca_expiration_date + +elif [ "$SYSTEM" = "openbsd" ]; then + + # Cert expiration date for POSIX date, human formated then in seconds + posix_cert_expiration_date=$(echo "$cert_expiration_date" | awk '{ printf $4" "(index("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3" "$2" ",split($3,time,":"); print time[1],time[2],time[3]}' | awk '{printf "%04d%02d%02d%02d%02d.%02d\n", $1, $2, $3, $4, $5, $6}') + cert_zone=$(echo "$cert_expiration_date" | awk '{print $5}') + formatted_cert_expiration_date=$(TZ=$cert_zone $date_cmd -j -z "Europe/Paris" "$posix_cert_expiration_date" +"%F %T %Z") + seconds_cert_expiration_date=$(TZ=$cert_zone $date_cmd -j -z "Europe/Paris" "$posix_cert_expiration_date" +"%s") + + # CA expiration date for POSIX date, human formated then in seconds + posix_ca_expiration_date=$(echo "$ca_expiration_date" | awk '{ printf $4" "(index("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3" "$2" ",split($3,time,":"); print time[1],time[2],time[3]}' | awk '{printf "%04d%02d%02d%02d%02d.%02d\n", $1, $2, $3, $4, $5, $6}') + ca_zone=$(echo "$ca_expiration_date" | awk '{print $5}') + formatted_ca_expiration_date=$(TZ=$ca_zone $date_cmd -j -z "Europe/Paris" "$posix_ca_expiration_date" +"%F %T %Z") + seconds_ca_expiration_date=$(TZ=$ca_zone $date_cmd -j -z "Europe/Paris" "$posix_ca_expiration_date" +"%s") + + test_cert_expiration $seconds_cert_expiration_date + test_ca_expiration $seconds_ca_expiration_date + +# If neither Linux nor BSD +else + + echo "CRITICAL - OS not supported" + STATE=$STATE_CRITICAL + exit $STATE + +fi + +# Display the first one that expires first +if [ $CA_STATE -gt $CERT_STATE ]; then + echo $CA_ECHO + echo $CERT_ECHO + exit $CA_STATE +elif [ $CERT_STATE -gt $CA_STATE ]; then + echo $CERT_ECHO + echo $CA_ECHO + exit $CERT_STATE +else + echo $CERT_ECHO + echo $CA_ECHO + exit $CERT_STATE +fi diff --git a/openvpn/handlers/main.yml b/openvpn/handlers/main.yml new file mode 100644 index 00000000..5ba1926c --- /dev/null +++ b/openvpn/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: restart nagios-nrpe-server + service: + name: nagios-nrpe-server + state: restarted diff --git a/openvpn/tasks/main.yml b/openvpn/tasks/main.yml new file mode 100644 index 00000000..105b3c0b --- /dev/null +++ b/openvpn/tasks/main.yml @@ -0,0 +1,285 @@ +--- + +- name: This role is only compatible with Debian + assert: + that: "ansible_distribution == 'Debian'" + msg: "Only compatible with Debian" + +- name: Install OpenVPN + apt: + name: openvpn + +- name: Delete unwanted OpenVPN folders + file: + state: absent + path: "/etc/openvpn/{{ item }}" + with_items: + - client + - server + +- name: Clone shellpki repo + git: + repo: "https://gitea.evolix.org/evolix/shellpki.git" + dest: /root/shellpki + +- name: Create the shellpki user + user: + name: shellpki + system: yes + create_home: no + home: "/etc/shellpki" + shell: "/usr/sbin/nologin" + +- name: Create /etc/shellpki + file: + path: "/etc/shellpki" + state: directory + +- include_role: + name: evolix/remount-usr + +- name: Copy shellpki files + copy: + src: "{{ item.source }}" + 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: + path: "{{ item.path }}" + mode: "{{ item.mode }}" + with_items: + - { path: "/etc/shellpki/openssl.cnf", mode: "0640" } + - { path: "/usr/local/sbin/shellpki", mode: "0755" } + +- name: Delete local shellpki repo + file: + state: absent + path: "/root/shellpki" + +- name: Change directory owner + file: + path: "/etc/shellpki" + owner: shellpki + recurse: yes + state: directory + +- name: Add sudo rights + lineinfile: + dest: "/etc/sudoers.d/shellpki" + regexp: '/usr/local/sbin/shellpki' + line: "%shellpki ALL = (root) /usr/local/sbin/shellpki" + create: yes + validate: 'visudo -cf %s' + +- name: Deploy OpenVPN client config template + template: + src: "ovpn.conf.j2" + dest: "/etc/shellpki/ovpn.conf" + +- name: Generate dhparam + command: "openssl dhparam -out /etc/shellpki/dh2048.pem 2048" + +- include_role: + name: evolix/remount-usr + +- name: Fix CRL rights in shellpki command + lineinfile: + path: "/usr/local/sbin/shellpki" + regexp: '{{ item.regexp }}' + insertafter: "{{ item.insertafter }}" + line: "{{ item.line }}" + with_items: + - { regexp: '^ chmod 644 /etc/shellpki/crl.pem$', line: " chmod 644 /etc/shellpki/crl.pem", insertafter: '^ chmod 640 "\${CACERT}"$' } + - { regexp: '^ chmod 755 /etc/shellpki/$', line: " chmod 755 /etc/shellpki/", insertafter: '^ chmod 644 /etc/shellpki/crl.pem$' } + +- name: Deploy OpenVPN server config + template: + src: "server.conf.j2" + dest: "/etc/openvpn/server.conf" + +- name: Is minifirewall installed ? + stat: + path: "/etc/default/minifirewall" + check_mode: no + register: minifirewall_config + +- name: Retrieve the default interface + shell: "grep '^INT=' /etc/default/minifirewall | cut -d\\' -f 2" + check_mode: no + changed_when: false + register: minifirewall_int + +- name: Add minifirewall rule in config file + lineinfile: + path: "/etc/default/minifirewall" + line: "{{ item }}" + with_items: + - "# OpenVPN" + - "/sbin/iptables -t nat -A POSTROUTING -s {{ openvpn_lan }}/{{ openvpn_netmask_cidr }} -o $INT -j MASQUERADE" + when: minifirewall_config.stat.exists + +- name: Activate minifirewall rule + iptables: + table: nat + chain: POSTROUTING + source: "{{ openvpn_lan }}/{{ openvpn_netmask_cidr }}" + out_interface: "{{ minifirewall_int.stdout }}" + jump: MASQUERADE + when: minifirewall_config.stat.exists + +- name: Add 1194/udp OpenVPN port to public services in minifirewall + replace: + path: "/etc/default/minifirewall" + regexp: "^SERVICESUDP1='(.*)?'$" + replace: "SERVICESUDP1='\\1 1194'" + backup: yes + when: minifirewall_config.stat.exists + +- name: Activate minifirewall rule for IPv4 + iptables: + chain: INPUT + protocol: udp + destination_port: "1194" + jump: ACCEPT + ip_version: ipv4 + when: minifirewall_config.stat.exists + +- name: Activate minifirewall rule for IPv6 + iptables: + chain: INPUT + protocol: udp + destination_port: "1194" + jump: ACCEPT + ip_version: ipv6 + when: minifirewall_config.stat.exists + +- name: Enable forwarding + sysctl: + name: net.ipv4.ip_forward + value: "1" + sysctl_file: "/etc/sysctl.d/openvpn.conf" + +- name: Generate a password for the management interface + set_fact: + management_pwd: "{{ lookup('password', '/dev/null length=15 chars=ascii_letters,digits') }}" + +- name: Set the management password + copy: + dest: "/etc/openvpn/management-pwd" + content: "{{ management_pwd }}" + +- name: Enable openvpn service + systemd: + name: "openvpn@server.service" + enabled: yes + +- name: Is NRPE installed ? + stat: + path: "/etc/nagios/nrpe.d/evolix.cfg" + check_mode: no + register: nrpe_evolix_config + +- name: Install NRPE check dependencies + apt: + name: libnet-telnet-perl + when: nrpe_evolix_config.stat.exists + +- include_role: + name: evolix/remount-usr + +- name: Install OpenVPN NRPE check + copy: + src: "files/check_openvpn.pl" + dest: "/usr/local/lib/nagios/plugins/check_openvpn" + mode: "0755" + owner: root + group: nagios + when: nrpe_evolix_config.stat.exists + +- name: Add NRPE check + lineinfile: + dest: "/etc/nagios/nrpe.d/evolix.cfg" + regexp: '^command\[check_openvpn\]=' + line: "command[check_openvpn]=/usr/local/lib/nagios/plugins/check_openvpn -H 127.0.0.1 -p 1195 -P {{ management_pwd }}" + notify: restart nagios-nrpe-server + when: nrpe_evolix_config.stat.exists + +- include_role: + name: evolix/remount-usr + +- name: Install OpenVPN certificates NRPE check + copy: + src: "files/check_openvpn_certificates.sh" + dest: "/usr/local/lib/nagios/plugins/check_openvpn_certificates.sh" + mode: "0755" + owner: root + group: nagios + when: nrpe_evolix_config.stat.exists + +- name: Add sudo rights for NRPE check + lineinfile: + dest: "/etc/sudoers.d/openvpn" + regexp: 'check_openvpn_certificates.sh' + line: "nagios ALL=NOPASSWD: /usr/local/lib/nagios/plugins/check_openvpn_certificates.sh" + create: yes + validate: 'visudo -cf %s' + when: nrpe_evolix_config.stat.exists + +- name: Add NRPE check + lineinfile: + dest: "/etc/nagios/nrpe.d/evolix.cfg" + regexp: '^command\[check_openvpn_certificates\]=' + line: "command[check_openvpn_certificates]=sudo /usr/local/lib/nagios/plugins/check_openvpn_certificates.sh" + notify: restart nagios-nrpe-server + 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: + name: evolix/remount-usr + +- name: Copy shellpki script + copy: + src: "/root/shellpki-dev/cert-expirations.sh" + dest: "/usr/share/scripts/cert-expirations.sh" + mode: "0700" +# owner: root +# group: root + remote_src: yes + +- name: Delete local shellpki-dev repo + file: + state: absent + path: "/root/shellpki-dev" +# END TODO + +- name: Install cron to warn about certificates expiration + cron: + name: "OpenVPN certificates expiration" + special_time: monthly + job: '/usr/share/scripts/cert-expirations.sh | mail -E -s "PKI VPN {{ ansible_hostname }} : recapitulatif expirations" {{ client_email }}' + +- name: Warn the user about command to execute manually + pause: + prompt: | + /!\ WARNING /!\ + You have to manually create the CA on the server with "shellpki init {{ ansible_fqdn }}". The command will ask you to create a password, and will ask you again to give the same one several times. + You have to manually generate the CRL on the server with "openssl ca -gencrl -keyfile /etc/shellpki/cakey.key -cert /etc/shellpki/cacert.pem -out /etc/shellpki/crl.pem -config /etc/shellpki/openssl.cnf". The previously created password will be asked + You have to manually create the server's certificate with "shellpki create {{ ansible_fqdn }}" + You have to adjuste the config file "/etc/openvpn/server.conf" for the following parameters : local (to check), cert (to check), key (to add), server (to check), push (to complete if needed). + Finally, you can (re)start the OpenVPN service with "systemctl restart openvpn@server.service" + + Press enter to exit when it's done. + diff --git a/openvpn/templates/ovpn.conf.j2 b/openvpn/templates/ovpn.conf.j2 new file mode 100644 index 00000000..d82b0b42 --- /dev/null +++ b/openvpn/templates/ovpn.conf.j2 @@ -0,0 +1,12 @@ +client +dev tun +tls-client +proto udp + +remote {{ ansible_fqdn }} 1194 + +persist-key +persist-tun + +cipher AES-256-CBC + diff --git a/openvpn/templates/server.conf.j2 b/openvpn/templates/server.conf.j2 new file mode 100644 index 00000000..0508ff9d --- /dev/null +++ b/openvpn/templates/server.conf.j2 @@ -0,0 +1,31 @@ +user nobody +group nogroup + +local {{ ansible_default_ipv4.address }} +port 1194 +proto udp +dev tun +mode server +keepalive 10 120 + +cipher AES-256-GCM # AES + +persist-key +persist-tun + +status /var/log/openvpn-status.log +log-append /var/log/openvpn.log + +ca /etc/shellpki/cacert.pem +cert /etc/shellpki/certs/{{ ansible_fqdn }}.crt +key /etc/shellpki/private/TO_COMPLETE +dh /etc/shellpki/dh2048.pem + +crl-verify /etc/shellpki/crl.pem + +server {{ openvpn_lan }} {{ openvpn_netmask }} + +#push "route 192.0.3.0 255.255.255.0" + +# Management interface (used by check_openvpn for Nagios) +management 127.0.0.1 1195 /etc/openvpn/management-pwd