forked from ISTI-ansible-roles/ansible-roles
Merge pull request 'Remove some roles that are either obsolete or have been moved to their own repository.' (#216) from adellam/ansible-roles:master into master
This commit is contained in:
commit
f248d8c1c2
|
@ -1,40 +0,0 @@
|
|||
#
|
||||
# The user of this role will need to write a haproxy.cfg template and install it with a dedicated task. Something like
|
||||
|
||||
- name: Configure haproxy
|
||||
template: src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg owner=root group=haproxy mode=0440
|
||||
notify: Reload haproxy
|
||||
tags: [ 'haproxy', 'haproxy_conf' ]
|
||||
|
||||
#
|
||||
# Very complex setup that involves varnish. Taken here:
|
||||
# https://alohalb.wordpress.com/2012/08/25/haproxy-varnish-and-the-single-hostname-website/
|
||||
# For a ssl setup, check here:
|
||||
# http://seanmcgary.com/posts/using-sslhttps-with-haproxy
|
||||
# https://alohalb.wordpress.com/haproxy/haproxy-and-ssl/
|
||||
# https://alohalb.wordpress.com/2013/01/21/mitigating-the-ssl-beast-attack-using-the-aloha-load-balancer-haproxy/
|
||||
# http://blog.haproxy.com/2015/05/06/haproxys-load-balancing-algorithm-for-static-content-delivery-with-varnish/
|
||||
# http://blog.haproxy.com/2012/09/10/how-to-get-ssl-with-haproxy-getting-rid-of-stunnel-stud-nginx-or-pound/
|
||||
# https://serversforhackers.com/using-ssl-certificates-with-haproxy
|
||||
#
|
||||
# Session management workarounds:
|
||||
# http://blog.haproxy.com/2012/03/29/load-balancing-affinity-persistence-sticky-sessions-what-you-need-to-know/
|
||||
# http://serverfault.com/questions/439445/haproxy-my-sessions-are-sort-of-sticky
|
||||
#
|
||||
# Hints to protect from DDOS or too many legitimate requests
|
||||
# http://www.loadbalancer.org/de/blog/black-friday-black-out-protection-with-haproxy
|
||||
#
|
||||
|
||||
When letsencrypt is enabled, the haproxy configurazion file needs to
|
||||
contain not only the https configuration, but also something like:
|
||||
|
||||
frontend http
|
||||
bind 80
|
||||
acl letsencrypt-request path_beg -i /.well-known/acme-challenge/
|
||||
use_backend letsencrypt if letsencrypt-request
|
||||
|
||||
backend letsencrypt
|
||||
mode http
|
||||
server letsencrypt 127.0.0.1:9999
|
||||
|
||||
Where 9999 is the port where the letsencrypt standalone client will listen to.
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
haproxy_latest_release: True
|
||||
haproxy_version: 1.8
|
||||
haproxy_repo_key: 'http://haproxy.debian.net/bernat.debian.org.gpg'
|
||||
haproxy_debian_latest_repo: "deb http://haproxy.debian.net {{ ansible_lsb.codename }}-backports-{{ haproxy_version }} main"
|
||||
haproxy_ubuntu_latest_repo: "ppa:vbernat/haproxy-{{ haproxy_version }}"
|
||||
haproxy_pkg_state: latest
|
||||
haproxy_enabled: True
|
||||
haproxy_k_bind_non_local_ip: True
|
||||
|
||||
haproxy_default_port: 80
|
||||
haproxy_terminate_tls: False
|
||||
haproxy_ssl_port: 443
|
||||
haproxy_admin_port: 8880
|
||||
haproxy_admin_socket: /run/haproxy/admin.sock
|
||||
|
||||
haproxy_letsencrypt_managed: False
|
||||
haproxy_cert_dir: '{{ pki_dir }}/haproxy'
|
||||
|
||||
haproxy_nagios_check: False
|
||||
# It's a percentage
|
||||
haproxy_nagios_check_w: 70
|
||||
haproxy_nagios_check_c: 90
|
||||
|
||||
haproxy_check_interval: 3s
|
||||
haproxy_backend_maxconn: 2048
|
||||
|
||||
haproxy_sysctl_conntrack_max: 131072
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
# vim: se et ts=4:
|
||||
|
||||
#
|
||||
# Copyright (C) 2012, Giacomo Montagner <giacomo@entirelyunlike.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the same terms as Perl 5.10.1.
|
||||
# For more details, see http://dev.perl.org/licenses/artistic.html
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
our $VERSION = "1.0.1";
|
||||
|
||||
# CHANGELOG:
|
||||
# 1.0.0 - first release
|
||||
# 1.0.1 - fixed empty message if all proxies are OK
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use 5.010.001;
|
||||
use File::Basename qw/basename/;
|
||||
use IO::Socket::UNIX;
|
||||
use Getopt::Long;
|
||||
|
||||
sub usage {
|
||||
my $me = basename $0;
|
||||
print <<EOU;
|
||||
NAME
|
||||
$me - check haproxy stats for errors, using UNIX socket interface
|
||||
|
||||
SYNOPSIS
|
||||
$me [OPTIONS]
|
||||
|
||||
DESCRIPTION
|
||||
Get haproxy statistics via UNIX socket and parse information searching for errors.
|
||||
|
||||
OPTIONS
|
||||
-c, --critical
|
||||
Set critical threshold for sessions number (chacks current number of sessions
|
||||
against session limit, if enforced) to the specified percentage.
|
||||
If no session limit (slim) was specified for the given proxy, this option has
|
||||
no effect.
|
||||
|
||||
-d, --dump
|
||||
Just dump haproxy stats and exit;
|
||||
|
||||
-h, --help
|
||||
Print this message.
|
||||
|
||||
-p, --proxy
|
||||
Check only named proxies, not every one. Use comma to separate proxies
|
||||
in list.
|
||||
|
||||
-s, --sock, --socket
|
||||
Use named UNIX socket instead of default (/run/haproxy/admin.sock)
|
||||
|
||||
-w, --warning
|
||||
Set warning threshold for sessions number to the specified percentage (see -c)
|
||||
|
||||
CHECKS AND OUTPUT
|
||||
$me checks every proxy (or the named ones, if -p was given)
|
||||
for status. It returns an error if any of the checked FRONTENDs is not OPEN,
|
||||
any of the checked BACKENDs is not UP, or any of the checkes servers is not UP;
|
||||
$me reports any problem it found.
|
||||
|
||||
EXAMPLES
|
||||
$me -s /var/spool/haproxy/sock
|
||||
Use /var/spool/haproxy/sock to communicate with haproxy.
|
||||
|
||||
$me -p proxy1,proxy2 -w 60 -c 80
|
||||
Check only proxies named "proxy1" and "proxy2", and set sessions number
|
||||
thresholds to 60% and 80%.
|
||||
|
||||
AUTHOR
|
||||
Written by Giacomo Montagner
|
||||
|
||||
REPORTING BUGS
|
||||
Please report any bug to bugs\@entirelyunlike.net
|
||||
|
||||
COPYRIGHT
|
||||
Copyright (C) 2012 Giacomo Montagner <giacomo\@entirelyunlike.net>.
|
||||
$me is distributed under GPL and the Artistic License 2.0
|
||||
|
||||
SEE ALSO
|
||||
Check out online haproxy documentation at <http://haproxy.1wt.eu/>
|
||||
|
||||
EOU
|
||||
}
|
||||
|
||||
my %check_statuses = (
|
||||
UNK => "unknown",
|
||||
INI => "initializing",
|
||||
SOCKERR => "socket error",
|
||||
L4OK => "layer 4 check OK",
|
||||
L4CON => "connection error",
|
||||
L4TMOUT => "layer 1-4 timeout",
|
||||
L6OK => "layer 6 check OK",
|
||||
L6TOUT => "layer 6 (SSL) timeout",
|
||||
L6RSP => "layer 6 protocol error",
|
||||
L7OK => "layer 7 check OK",
|
||||
L7OKC => "layer 7 conditionally OK",
|
||||
L7TOUT => "layer 7 (HTTP/SMTP) timeout",
|
||||
L7RSP => "layer 7 protocol error",
|
||||
L7STS => "layer 7 status error",
|
||||
);
|
||||
|
||||
my @status_names = (qw/OK WARNING CRITICAL UNKNOWN/);
|
||||
|
||||
# Defaults
|
||||
my $swarn = 80.0;
|
||||
my $scrit = 90.0;
|
||||
my $sock = "/run/haproxy/admin.sock";
|
||||
my $dump;
|
||||
my $proxy;
|
||||
my $help;
|
||||
|
||||
# Read command line
|
||||
Getopt::Long::Configure ("bundling");
|
||||
GetOptions (
|
||||
"c|critical=i" => \$scrit,
|
||||
"d|dump" => \$dump,
|
||||
"h|help" => \$help,
|
||||
"p|proxy=s" => \$proxy,
|
||||
"s|sock|socket=s" => \$sock,
|
||||
"w|warning=i" => \$swarn,
|
||||
);
|
||||
|
||||
# Want help?
|
||||
if ($help) {
|
||||
usage;
|
||||
exit 3;
|
||||
}
|
||||
|
||||
# Connect to haproxy socket and get stats
|
||||
my $haproxy = new IO::Socket::UNIX (
|
||||
Peer => $sock,
|
||||
Type => SOCK_STREAM,
|
||||
);
|
||||
die "Unable to connect to haproxy socket: $@" unless $haproxy;
|
||||
print $haproxy "show stat\n" or die "Print to socket failed: $!";
|
||||
|
||||
# Dump stats and exit if requested
|
||||
if ($dump) {
|
||||
while (<$haproxy>) {
|
||||
print;
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Get labels from first output line and map them to their position in the line
|
||||
my $labels = <$haproxy>;
|
||||
chomp($labels);
|
||||
$labels =~ s/^# // or die "Data format not supported.";
|
||||
my @labels = split /,/, $labels;
|
||||
{
|
||||
no strict "refs";
|
||||
my $idx = 0;
|
||||
map { $$_ = $idx++ } @labels;
|
||||
}
|
||||
|
||||
# Variables I will use from here on:
|
||||
our $pxname;
|
||||
our $svname;
|
||||
our $status;
|
||||
|
||||
my @proxies = split ',', $proxy if $proxy;
|
||||
my $exitcode = 0;
|
||||
my $msg;
|
||||
my $checked = 0;
|
||||
while (<$haproxy>) {
|
||||
chomp;
|
||||
next if /^[[:space:]]*$/;
|
||||
my @data = split /,/, $_;
|
||||
if (@proxies) { next unless grep {$data[$pxname] eq $_} @proxies; };
|
||||
|
||||
# Is session limit enforced?
|
||||
our $slim;
|
||||
if ($data[$slim]) {
|
||||
# Check current session # against limit
|
||||
our $scur;
|
||||
my $sratio = $data[$scur]/$data[$slim];
|
||||
if ($sratio >= $scrit || $sratio >= $swarn) {
|
||||
$exitcode = $sratio >= $scrit ? 2 :
|
||||
$exitcode < 2 ? 1 : $exitcode;
|
||||
$msg .= sprintf "%s:%s sessions: %.2f%%; ", $data[$pxname], $data[$svname], $sratio;
|
||||
}
|
||||
}
|
||||
|
||||
# Check of BACKENDS
|
||||
if ($data[$svname] eq 'BACKEND') {
|
||||
if ($data[$status] ne 'UP') {
|
||||
$msg .= sprintf "BACKEND: %s is %s; ", $data[$pxname], $data[$status];
|
||||
$exitcode = 2;
|
||||
}
|
||||
# Check of FRONTENDS
|
||||
} elsif ($data[$svname] eq 'FRONTEND') {
|
||||
if ($data[$status] ne 'OPEN') {
|
||||
$msg .= sprintf "FRONTEND: %s is %s; ", $data[$pxname], $data[$status];
|
||||
$exitcode = 2;
|
||||
}
|
||||
# Check of servers
|
||||
} else {
|
||||
if ($data[$status] ne 'UP') {
|
||||
next if $data[$status] eq 'no check'; # Ignore server if no check is configured to be run
|
||||
$exitcode = 2;
|
||||
our $check_status;
|
||||
$msg .= sprintf "server: %s:%s is %s", $data[$pxname], $data[$svname], $data[$status];
|
||||
$msg .= sprintf " (check status: %s)", $check_statuses{$data[$check_status]} if $check_statuses{$data[$check_status]};
|
||||
$msg .= "; ";
|
||||
}
|
||||
}
|
||||
++$checked;
|
||||
}
|
||||
|
||||
unless ($msg) {
|
||||
$msg = @proxies ? sprintf("checked proxies: %s", join ', ', sort @proxies) : "checked $checked proxies.";
|
||||
}
|
||||
say "Check haproxy $status_names[$exitcode] - $msg";
|
||||
exit $exitcode;
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
LE_SERVICES_SCRIPT_DIR=/usr/local/lib/letsencrypt
|
||||
LE_CERTS_DIR=/etc/letsencrypt/live/$HOSTNAME
|
||||
LE_LOG_DIR=/var/log/letsencrypt
|
||||
HAPROXY_CERTDIR=/etc/pki/haproxy
|
||||
HAPROXY_CERTFILE=$HAPROXY_CERTDIR/haproxy.pem
|
||||
DATE=$( date )
|
||||
echo "$DATE" >> $LE_LOG_DIR/haproxy.log
|
||||
|
||||
if [ -f /etc/default/letsencrypt ] ; then
|
||||
. /etc/default/letsencrypt
|
||||
else
|
||||
echo "No letsencrypt default file" >> $LE_LOG_DIR/haproxy.log
|
||||
fi
|
||||
|
||||
[ ! -d $HAPROXY_CERTDIR ] && mkdir $HAPROXY_CERTDIR
|
||||
|
||||
echo "Building the new certificate file" >> $LE_LOG_DIR/haproxy.log
|
||||
cat ${LE_CERTS_DIR}/{fullchain.pem,privkey.pem} > ${HAPROXY_CERTFILE}
|
||||
chmod 440 ${HAPROXY_CERTFILE}
|
||||
chgrp haproxy ${HAPROXY_CERTFILE}
|
||||
|
||||
echo "Reload the haproxy service" >> $LE_LOG_DIR/haproxy.log
|
||||
service haproxy reload >/dev/null 2>&1
|
||||
echo "Done." >> $LE_LOG_DIR/haproxy.log
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
- name: Restart haproxy
|
||||
service: name=haproxy state=restarted
|
||||
when: haproxy_enabled
|
||||
|
||||
- name: Reload haproxy
|
||||
service: name=haproxy state=reloaded
|
||||
when: haproxy_enabled
|
||||
|
||||
- name: Reload rsyslog
|
||||
service: name=rsyslog state=reloaded
|
||||
when: haproxy_enabled
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
- block:
|
||||
- name: Create the acme hooks directory if it does not yet exist
|
||||
file: dest={{ letsencrypt_acme_sh_services_scripts_dir }} state=directory owner=root group=root
|
||||
|
||||
- name: Install a script that fix the letsencrypt certificate for haproxy and then reload the service
|
||||
template: src=haproxy-letsencrypt-acme.sh.j2 dest={{ letsencrypt_acme_sh_services_scripts_dir }}/haproxy owner=root group=root mode=4555
|
||||
|
||||
- name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now handle the haproxy special case
|
||||
shell: mkdir {{ pki_dir }}/haproxy ; cat {{ letsencrypt_acme_user_home | default(omit) }}/live/{{ ansible_fqdn }}/privkey {{ letsencrypt_acme_user_home | default(omit) }}/live/{{ ansible_fqdn }}/cert > {{ pki_dir }}/haproxy/haproxy.pem
|
||||
args:
|
||||
creates: '{{ pki_dir }}/haproxy/haproxy.pem'
|
||||
tags: [ 'pki', 'ssl', 'letsencrypt', 'haproxy', 'letsencrypt_acme_sh' ]
|
||||
|
||||
when: letsencrypt_acme_sh_install
|
||||
tags: [ 'haproxy', 'letsencrypt', 'letsencrypt_acme_sh' ]
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
- block:
|
||||
- name: Create the acme hooks directory if it does not yet exist
|
||||
file: dest={{ letsencrypt_acme_services_scripts_dir }} state=directory owner=root group=root
|
||||
|
||||
- name: Install a script that fix the letsencrypt certificate for haproxy and then reload the service
|
||||
template: src=haproxy-letsencrypt-acme.sh.j2 dest={{ letsencrypt_acme_services_scripts_dir }}/haproxy owner=root group=root mode=4555
|
||||
|
||||
- name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now handle the haproxy special case
|
||||
shell: mkdir {{ pki_dir }}/haproxy ; cat {{ letsencrypt_acme_user_home | default(omit) }}/live/{{ ansible_fqdn }}/privkey {{ letsencrypt_acme_user_home | default(omit) }}/live/{{ ansible_fqdn }}/cert > {{ pki_dir }}/haproxy/haproxy.pem
|
||||
args:
|
||||
creates: '{{ pki_dir }}/haproxy/haproxy.pem'
|
||||
tags: [ 'pki', 'ssl', 'letsencrypt', 'haproxy' ]
|
||||
|
||||
when: letsencrypt_acme_install
|
||||
tags: [ 'haproxy', 'letsencrypt' ]
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
- name: Install the haproxy NRPE nagios check
|
||||
copy: src=check_haproxy_stats dest={{ nagios_local_plugdir }}/check_haproxy_stats owner=root group=root mode=0555
|
||||
when: haproxy_nagios_check
|
||||
|
||||
- name: Install the haproxy NRPE command configuration
|
||||
template: src=lb.cfg.j2 dest={{ nrpe_include_dir }}/lb.cfg owner=root group=root mode=0444
|
||||
notify: Reload NRPE server
|
||||
when: haproxy_nagios_check
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
---
|
||||
- name: Get the haproxy repo key
|
||||
apt_key: url={{ haproxy_repo_key }} state=present
|
||||
when: haproxy_latest_release
|
||||
tags: haproxy
|
||||
|
||||
- name: Define the haproxy repository
|
||||
apt_repository: repo='{{ haproxy_ubuntu_latest_repo }}' state=present update_cache=yes
|
||||
when:
|
||||
- haproxy_latest_release
|
||||
- is_ubuntu
|
||||
tags: haproxy
|
||||
|
||||
- name: Define the haproxy repository
|
||||
apt_repository: repo='{{ haproxy_debian_latest_repo }}' state=present update_cache=yes
|
||||
when:
|
||||
- haproxy_latest_release
|
||||
- is_debian
|
||||
tags: haproxy
|
||||
|
||||
- name: Install the haproxy package
|
||||
apt: name=haproxy state=present default_release={{ ansible_lsb.codename }}-backports update_cache=yes cache_valid_time=3600
|
||||
when: not haproxy_latest_release
|
||||
register: install_haproxy
|
||||
tags: haproxy
|
||||
|
||||
- name: Install the haproxy package
|
||||
apt: name=haproxy state=latest default_release={{ ansible_lsb.codename }}-backports-{{ haproxy_version }} update_cache=yes cache_valid_time=3600
|
||||
when:
|
||||
- haproxy_latest_release
|
||||
- is_debian
|
||||
register: install_haproxy
|
||||
tags: haproxy
|
||||
|
||||
- name: Install the haproxy package
|
||||
apt: name=haproxy state=latest update_cache=yes cache_valid_time=3600
|
||||
when:
|
||||
- haproxy_latest_release
|
||||
- is_ubuntu
|
||||
register: install_haproxy
|
||||
tags: haproxy
|
||||
|
||||
- name: Enable kernel binding non local IP addresses
|
||||
sysctl: name={{ item }} value=1 reload=yes state=present
|
||||
with_items:
|
||||
- net.ipv4.ip_nonlocal_bind
|
||||
when: haproxy_k_bind_non_local_ip
|
||||
tags: [ 'haproxy', 'haproxy_sysctl' ]
|
||||
|
||||
- name: Disable kernel binding non local IP addresses
|
||||
sysctl: name={{ item }} value=0 reload=yes state=present
|
||||
with_items:
|
||||
- net.ipv4.ip_nonlocal_bind
|
||||
when: not haproxy_k_bind_non_local_ip
|
||||
tags: [ 'haproxy', 'haproxy_sysctl' ]
|
||||
|
||||
- name: Increase the connection tracking table capacity
|
||||
sysctl: name={{ item }} value={{ haproxy_sysctl_conntrack_max }} reload=yes state=present
|
||||
with_items:
|
||||
- net.nf_conntrack_max
|
||||
when: is_not_debian9
|
||||
tags: [ 'haproxy', 'haproxy_sysctl' ]
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
- block:
|
||||
- name: Install the socat binary needed to talk to the haproxy socket
|
||||
apt: name=socat state=latest update_cache=yes cache_valid_time=3600
|
||||
|
||||
- name: Install a script that refreshes the OCSP configuration and reloads haproxy if needed
|
||||
template: src=hapos-upd.j2 dest=/usr/local/bin/hapos-upd owner=root group=root mode=0755
|
||||
|
||||
- name: Install a cron job that refreshes the OCSP configuration
|
||||
cron:
|
||||
name: "Refresh the haproxy OCSP information"
|
||||
user: root
|
||||
special_time: daily
|
||||
job: "/usr/local/bin/hapos-upd --cert {{ haproxy_cert_dir }}/haproxy.pem -v {{ letsencrypt_acme_certs_dir }}/fullchain -s {{ haproxy_admin_socket }} >/var/log/hapos-upd.log 2>&1"
|
||||
|
||||
tags: [ 'haproxy', 'letsencrypt', 'ssl', 'ssl_ocsp' ]
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
- import_tasks: haproxy-service.yml
|
||||
- import_tasks: haproxy-letsencrypt-acme-sh.yml
|
||||
when:
|
||||
- haproxy_letsencrypt_managed
|
||||
- letsencrypt_acme_sh_install
|
||||
- import_tasks: haproxy-letsencrypt-acmetool.yml
|
||||
when:
|
||||
- haproxy_letsencrypt_managed
|
||||
- letsencrypt_acme_install
|
||||
- import_tasks: haproxy-ssl.yml
|
||||
when:
|
||||
- haproxy_letsencrypt_managed
|
||||
|
||||
- import_tasks: haproxy-nagios.yml
|
||||
when:
|
||||
- nagios_enabled is defined
|
||||
- nagios_enabled
|
||||
|
||||
- name: Ensure that haproxy is enabled and started
|
||||
service: name=haproxy state=restarted enabled=yes
|
||||
when: haproxy_enabled
|
||||
ignore_errors: True
|
||||
tags: haproxy
|
||||
|
||||
- name: Haproxy puts a new rsyslog directive. Restart rsyslog to activate it. Reload is not sufficient
|
||||
service: name=rsyslog state=restarted
|
||||
when:
|
||||
- haproxy_enabled
|
||||
- install_haproxy is changed
|
||||
tags: haproxy
|
||||
|
||||
- name: Ensure that haproxy is stopped and disabled if needed
|
||||
service: name=haproxy state=stopped enabled=no
|
||||
when: not haproxy_enabled
|
||||
tags: haproxy
|
|
@ -1,571 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# HAProxy OCSP Stapling Updater
|
||||
# Copyright (c) 2015 Pier Carlo Chiodi - http://www.pierky.com
|
||||
#
|
||||
# https://github.com/pierky/haproxy-ocsp-stapling-updater
|
||||
|
||||
set -o nounset
|
||||
|
||||
VERSION="0.4.1-pre1"
|
||||
|
||||
PROGNAME="hapos-upd"
|
||||
|
||||
if [ -z ${OPENSSL_BIN+x} ]; then
|
||||
OPENSSL_BIN="openssl"
|
||||
fi
|
||||
|
||||
SOCAT_BIN="socat"
|
||||
|
||||
CERT=""
|
||||
VAFILE=""
|
||||
HAPROXY_ADMIN_SOCKET_DEFAULT="/run/haproxy/admin.sock"
|
||||
HAPROXY_ADMIN_SOCKET="$HAPROXY_ADMIN_SOCKET_DEFAULT"
|
||||
GOOD_ONLY=0
|
||||
SYSLOG_PRIO=""
|
||||
DEBUG=0
|
||||
KEEP_TEMP=0
|
||||
OCSP_URL=""
|
||||
OCSP_HOST=""
|
||||
VERIFY=1
|
||||
TMP=""
|
||||
SKIP_UPDATE=0
|
||||
PARTIAL_CHAIN=""
|
||||
|
||||
function Quit() {
|
||||
if [ $KEEP_TEMP -eq 0 ]; then
|
||||
if [ -n "$TMP" ]; then
|
||||
rm -r $TMP &>/dev/null
|
||||
fi
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
function LogError() {
|
||||
MSG="$1"
|
||||
|
||||
if [ -z "$SYSLOG_PRIO" ]; then
|
||||
echo "$MSG" >&2
|
||||
else
|
||||
logger -p "$SYSLOG_PRIO" -s -- "$PROGNAME - $MSG"
|
||||
fi
|
||||
|
||||
echo "$MSG" >>$TMP/log
|
||||
}
|
||||
|
||||
function Error() {
|
||||
if [ $1 -eq 9 ]; then
|
||||
MSG="Error: $2"
|
||||
else
|
||||
MSG="Error processing '$CERT': $2"
|
||||
fi
|
||||
|
||||
LogError "$MSG"
|
||||
|
||||
if [ $1 -eq 9 ]; then
|
||||
echo "Run $PROGNAME -h for help" >&2
|
||||
fi
|
||||
|
||||
Quit $1
|
||||
}
|
||||
|
||||
function Debug() {
|
||||
if [ $DEBUG -eq 1 ]; then
|
||||
echo "$1"
|
||||
fi
|
||||
echo "$1" >>$TMP/log
|
||||
}
|
||||
|
||||
function Trap() {
|
||||
Debug "Aborting"
|
||||
Quit 9
|
||||
}
|
||||
|
||||
function Usage() {
|
||||
echo "
|
||||
HAProxy OCSP Stapling Updater - $VERSION
|
||||
Copyright (c) 2015 Pier Carlo Chiodi - http://www.pierky.com
|
||||
|
||||
https://github.com/pierky/haproxy-ocsp-stapling-updater
|
||||
|
||||
Usage:
|
||||
$PROGNAME [options] --cert crt_full_path
|
||||
|
||||
This script extracts and queries the OCSP server present in a
|
||||
certificate to obtain its revocation status, then updates HAProxy by
|
||||
writing the '.issuer' and the '.ocsp' files and by sending it the
|
||||
'set ssl ocsp-response' command through the local UNIX admin socket.
|
||||
|
||||
The crt_full_path argument is the full path to the certificate bundle
|
||||
used in haproxy 'crt' setting. End-entity (EE) certificate plus any
|
||||
intermediate CA certificates must be concatenated there.
|
||||
An OCSP query is sent to the OCSP server given on the command line
|
||||
(--ocsp-url and --ocsp-host argument); if these arguments are missing,
|
||||
URL and Host header values are automatically extracted from the
|
||||
certificate.
|
||||
If the '.issuer' file already exists it's used to build the OCSP
|
||||
request, otherwise the chain is extracted from crt_full_path and used
|
||||
to identify the issuer.
|
||||
Finally, it writes the related '.issuer' and .'ocsp' files and updates
|
||||
haproxy, using 'socat' and the local UNIX socket (--socket argument,
|
||||
default $HAPROXY_ADMIN_SOCKET_DEFAULT).
|
||||
|
||||
Exit codes:
|
||||
0 OK
|
||||
1 openssl certificates handling error
|
||||
2 OCSP server URL not found
|
||||
3 string parsing / PEM manipulation error
|
||||
4 OCSP error
|
||||
5 haproxy management error
|
||||
9 program error (wrong arguments, missing dependencies)
|
||||
|
||||
Options:
|
||||
|
||||
-d, --debug : don't do anything, print debug messages only.
|
||||
|
||||
--keep-temp : keep temporary directory after exiting (for
|
||||
debug purposes).
|
||||
|
||||
-g, --good-only : do not update haproxy if OCSP response
|
||||
certificate status value is not 'good'.
|
||||
|
||||
-l, --syslog priority : log errors to syslog system log module.
|
||||
The priority may be specified numerically
|
||||
or as a facility.level pair (e.g.
|
||||
local7.error).
|
||||
|
||||
--ocsp-url url : OCSP server URL; use this instead of the
|
||||
one in the EE certificate.
|
||||
|
||||
--ocsp-host host : OCSP server hostname to be used in the
|
||||
'Host:' header; use this instead of the one
|
||||
extracted from the OCSP server URL.
|
||||
|
||||
--partial-chain : Allow partial certificate chain if at least one certificate
|
||||
is in trusted store. Useful when validating an intermediate
|
||||
certificate without the root CA.
|
||||
|
||||
-s, --socket file : haproxy admin socket. If omitted,
|
||||
$HAPROXY_ADMIN_SOCKET_DEFAULT is used by default.
|
||||
This script is distributed with only one
|
||||
method to update haproxy: using 'socat'
|
||||
with a local admin-level UNIX socket.
|
||||
Feel free to implement other mechanisms as
|
||||
needed! The right section in the code is
|
||||
\"UPDATE HAPROXY\", at the end of the script.
|
||||
|
||||
-v, --VAfile file : same as the openssl ocsp -VAfile option
|
||||
with 'file' as argument. For more details:
|
||||
'man ocsp'.
|
||||
If file = \"-\" then the chain extracted
|
||||
from the certificate's bundle (or .issuer
|
||||
file) is used (useful for OCSP responses
|
||||
that don't include the signer certificate).
|
||||
|
||||
--noverify : Do not verify OCSP response.
|
||||
|
||||
-S, --skip-update : Do not notify haproxy of the new OCSP response.
|
||||
|
||||
-h, --help : this help."
|
||||
}
|
||||
|
||||
trap Trap INT TERM
|
||||
|
||||
TMP="`mktemp -d -q -t $PROGNAME.XXXXXXXXXX`"
|
||||
|
||||
# COMMAND LINE PROCESSING
|
||||
# ----------------------------------
|
||||
|
||||
while [[ $# > 0 ]]
|
||||
do
|
||||
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
Usage
|
||||
Quit 0
|
||||
;;
|
||||
|
||||
-d|--debug)
|
||||
DEBUG=1
|
||||
;;
|
||||
|
||||
--keep-temp)
|
||||
KEEP_TEMP=1
|
||||
;;
|
||||
|
||||
-g|--good-only)
|
||||
GOOD_ONLY=1
|
||||
;;
|
||||
|
||||
--noverify)
|
||||
VERIFY=0
|
||||
;;
|
||||
|
||||
--partial-chain)
|
||||
PARTIAL_CHAIN="-partial_chain"
|
||||
;;
|
||||
|
||||
-l|--syslog)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
SYSLOG_PRIO="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
--ocsp-url)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
OCSP_URL="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
--ocsp-host)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
OCSP_HOST="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
-c|--cert)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
CERT="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
-v|--VAfile)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
VAFILE="$2"
|
||||
if [ "$VAFILE" == "-" ]; then
|
||||
VAFILE="$TMP/chain.pem"
|
||||
else
|
||||
if [ ! -e "$VAFILE" ]; then
|
||||
Error 9 "VAfile does not exists: $VAFILE"
|
||||
fi
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
|
||||
-s|--socket)
|
||||
if [ $# -le 1 ]; then
|
||||
Error 9 "mandatory value is missing for $1 argument"
|
||||
fi
|
||||
HAPROXY_ADMIN_SOCKET="$2"
|
||||
shift
|
||||
;;
|
||||
|
||||
-S|--skip-update)
|
||||
SKIP_UPDATE=1
|
||||
;;
|
||||
|
||||
*)
|
||||
Error 9 "unknown option: $1"
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
Debug "Temporary directory: $TMP"
|
||||
|
||||
$OPENSSL_BIN version | grep OpenSSL &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 9 "openssl binary not found; adjust OPENSSL_BIN variable in the script"
|
||||
fi
|
||||
|
||||
$SOCAT_BIN -V | grep socat &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 9 "socat binary not found; adjust SOCAT_BIN variable in the script"
|
||||
fi
|
||||
|
||||
if [ -z "$CERT" ]; then
|
||||
Error 9 "certificate not provided (--cert argument)"
|
||||
fi
|
||||
|
||||
# CURRENT RESPONSE EXPIRED?
|
||||
# ----------------------------------
|
||||
|
||||
ISNEW=1
|
||||
if [ -e $CERT.ocsp ]; then
|
||||
ISNEW=0
|
||||
Debug "An OCSP response already exists: checking its expiration."
|
||||
|
||||
$OPENSSL_BIN ocsp -respin $CERT.ocsp -text -noverify | \
|
||||
grep "Next Update:" &>>$TMP/log
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
CURR_EXP=`$OPENSSL_BIN ocsp -respin $CERT.ocsp -text -noverify | grep "Next Update:" | cut -d ':' -f 2-`
|
||||
CURR_EXP_EPOCH=`date --date="$CURR_EXP" +%s`
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 3 "can't parse Next Update from current OCSP response"
|
||||
fi
|
||||
|
||||
if [ $CURR_EXP_EPOCH -lt `date +%s` ]; then
|
||||
Debug "Current OCSP response expiration: $CURR_EXP - expired"
|
||||
LogError "current OCSP response is expired: please consider running this script more frequently"
|
||||
else
|
||||
Debug "Current OCSP response expiration: $CURR_EXP - NOT expired"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# EXTRACT EE CERTIFICATE INFO
|
||||
# ----------------------------------
|
||||
|
||||
# extract EE certificate
|
||||
$OPENSSL_BIN x509 -in $CERT -outform PEM -out $TMP/ee.pem &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 1 "can't extract EE certificate from $CERT"
|
||||
fi
|
||||
|
||||
# get OCSP server URL
|
||||
if [ -z "$OCSP_URL" ]; then
|
||||
OCSP_URL="`$OPENSSL_BIN x509 -in $TMP/ee.pem -ocsp_uri -noout`"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 1 "can't obtain OCSP server URL from $CERT"
|
||||
fi
|
||||
|
||||
if [ -z "$OCSP_URL" ]; then
|
||||
Error 2 "OCSP server URL not found in the EE certificate"
|
||||
fi
|
||||
|
||||
Debug "OCSP server URL found: $OCSP_URL"
|
||||
else
|
||||
Debug "Using OCSP server URL from command line: $OCSP_URL"
|
||||
fi
|
||||
|
||||
# check OCSP server URL format (http:// or https://)
|
||||
echo "$OCSP_URL" | egrep -i "(http://|https://)" &>/dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 3 "OCSP server URL not in http[s]:// format"
|
||||
fi
|
||||
|
||||
# get OCSP server URL host name
|
||||
if [ -z "$OCSP_HOST" ]; then
|
||||
OCSP_HOST="`echo "$OCSP_URL" | egrep -i "(http://|https://)" | cut -d'/' -f 3`"
|
||||
|
||||
if [ $? -ne 0 -o -z "$OCSP_HOST" ]; then
|
||||
Error 3 "can't extract hostname from OCSP server URL $OCSP_URL"
|
||||
fi
|
||||
|
||||
Debug "OCSP server hostname: $OCSP_HOST"
|
||||
else
|
||||
Debug "Using OCSP server hostname from command line: $OCSP_HOST"
|
||||
fi
|
||||
|
||||
# EXTRACT CHAIN INFO
|
||||
# ----------------------------------
|
||||
|
||||
if [ -e $CERT.issuer ]; then
|
||||
Debug "Using existing chain ($CERT.issuer)"
|
||||
|
||||
# copy .issuer file to temporary chain.pem
|
||||
cp $CERT.issuer $TMP/chain.pem &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 3 "can't copy current chain from $CERT.issuer"
|
||||
fi
|
||||
else
|
||||
Debug "Extracting chain from certificates bundle"
|
||||
|
||||
# get EE certificate's fingerprint
|
||||
FP_EE="`$OPENSSL_BIN x509 -fingerprint -noout -in $TMP/ee.pem`"
|
||||
|
||||
if [ $? -ne 0 -o -z "$FP_EE" ]; then
|
||||
Error 1 "can't obtain EE certificate's fingerprint"
|
||||
fi
|
||||
|
||||
Debug "EE certificate's fingerprint: $FP_EE"
|
||||
|
||||
# get BEGIN CERTIFICATE and END CERTIFICATE separators
|
||||
PEM_BEGIN_CERT="`head $TMP/ee.pem -n 1`"
|
||||
PEM_END_CERT="`tail $TMP/ee.pem -n 1`"
|
||||
|
||||
# get number of certificates in the bundle file
|
||||
NUM_OF_CERTS=`cat $CERT | grep -e "$PEM_BEGIN_CERT" | wc -l`
|
||||
|
||||
if [ $NUM_OF_CERTS -le 1 ]; then
|
||||
Error 3 "can't obtain the number of certificates in the chain"
|
||||
fi
|
||||
|
||||
Debug "$NUM_OF_CERTS certificates found in the bundle"
|
||||
|
||||
# save each certificate in the bundle into $TMP/chain-X.pem
|
||||
cat $CERT | \
|
||||
sed -n -e "/$PEM_BEGIN_CERT/,/$PEM_END_CERT/p" | \
|
||||
awk "/$PEM_BEGIN_CERT/{x=\"$TMP/chain-\" ++i \".pem\";}{print > x;}" &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 3 "can't extract certificates from bundle"
|
||||
fi
|
||||
|
||||
# for each certificate that is extracted from the bundle check if
|
||||
# it's the EE certificate, otherwise uses it to build the chain file
|
||||
for c in `seq 1 $NUM_OF_CERTS`;
|
||||
do
|
||||
# check fingerprint of current and EE certificates
|
||||
FP="`$OPENSSL_BIN x509 -fingerprint -noout -in $TMP/chain-$c.pem`"
|
||||
if [ $? -ne 0 -o -z "$FP" ]; then
|
||||
Error 1 "can't obtain the fingerprint of the certificate n. $c in the bundle"
|
||||
else
|
||||
if [ ! "$FP" == "$FP_EE" ]; then
|
||||
Debug "Bundle certificate n. $c fingerprint: $FP - it's part of the chain"
|
||||
|
||||
# current certificate is not the same as the EE; append to the chain
|
||||
cat $TMP/chain-$c.pem >> $TMP/chain.pem
|
||||
else
|
||||
Debug "Bundle certificate n. $c fingerprint: $FP - EE certificate"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# check if the EE certificate validates against the chain
|
||||
$OPENSSL_BIN verify $PARTIAL_CHAIN -CAfile $TMP/chain.pem $TMP/ee.pem &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ -e $CERT.issuer ]; then
|
||||
Error 1 "can't validate the EE certificate against the existing chain; if it has been changed recently consider removing the current $CERT.issuer file and let this script to figure out a new one"
|
||||
else
|
||||
Error 1 "can't validate the EE certificate against the extracted chain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# OCSP
|
||||
# ----------------------------------
|
||||
|
||||
# query the OCSP server and save its response
|
||||
|
||||
$OPENSSL_BIN version | grep "OpenSSL 1.0" &>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# OpenSSL 1.0.x
|
||||
|
||||
$OPENSSL_BIN ocsp $PARTIAL_CHAIN -issuer $TMP/chain.pem -cert $TMP/ee.pem \
|
||||
-respout $TMP/ocsp.der -noverify \
|
||||
-no_nonce -url $OCSP_URL -header "Host" "$OCSP_HOST" &>>$TMP/log
|
||||
else
|
||||
$OPENSSL_BIN ocsp $PARTIAL_CHAIN -issuer $TMP/chain.pem -cert $TMP/ee.pem \
|
||||
-respout $TMP/ocsp.der -noverify \
|
||||
-no_nonce -url $OCSP_URL -header "Host=$OCSP_HOST" &>>$TMP/log
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 1 "can't receive the OCSP server response"
|
||||
fi
|
||||
|
||||
# process the OCSP response
|
||||
VERIFYOPT=""
|
||||
if [ $VERIFY -eq 0 ]; then
|
||||
VERIFYOPT="-noverify"
|
||||
fi
|
||||
if [ -z "$VAFILE" ]; then
|
||||
$OPENSSL_BIN ocsp $PARTIAL_CHAIN $VERIFYOPT -issuer $TMP/chain.pem -cert $TMP/ee.pem \
|
||||
-respin $TMP/ocsp.der -no_nonce -CAfile $TMP/chain.pem \
|
||||
-out $TMP/ocsp.txt &>>$TMP/ocsp-verify.txt
|
||||
else
|
||||
$OPENSSL_BIN ocsp $PARTIAL_CHAIN $VERIFYOPT -issuer $TMP/chain.pem -cert $TMP/ee.pem \
|
||||
-respin $TMP/ocsp.der -no_nonce -CAfile $TMP/chain.pem \
|
||||
-VAfile $VAFILE \
|
||||
-out $TMP/ocsp.txt &>>$TMP/ocsp-verify.txt
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 1 "can't receive OCSP response"
|
||||
fi
|
||||
|
||||
if [ $VERIFY -eq 1 ]; then
|
||||
Debug "OCSP response verification results: `cat $TMP/ocsp-verify.txt`"
|
||||
|
||||
cat $TMP/ocsp-verify.txt | grep "Response verify OK" &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
grep "signer certificate not found" $TMP/ocsp-verify.txt &>/dev/null
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
Error 4 "OCSP response verification failure: signer certificate not found; try with '--VAfile -' or '--VAfile OCSP-response-signing-certificate-file' arguments"
|
||||
else
|
||||
Error 4 "OCSP response verification failure."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
Debug "OCSP response: `cat $TMP/ocsp.txt`"
|
||||
|
||||
if [ $GOOD_ONLY -eq 1 ]; then
|
||||
cat $TMP/ocsp.txt | head -n 1 | grep ": good" &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 4 "OCSP response, certificate status not good"
|
||||
fi
|
||||
fi
|
||||
|
||||
# UPDATE HAPROXY
|
||||
# ----------------------------------
|
||||
|
||||
# Status:
|
||||
# - $TMP/ocsp.der contains the OCSP response, DER format
|
||||
# - $TMP/ocsp.txt contains the textual OCSP response as produced
|
||||
# by openssl
|
||||
# - the OCSP response has been verified against the chain or
|
||||
# the --VAfile
|
||||
|
||||
if [ $DEBUG -eq 0 ]; then
|
||||
# update .ocsp and .issuer files
|
||||
|
||||
cp $TMP/ocsp.der $CERT.ocsp &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 5 "can't update $CERT.ocsp file"
|
||||
fi
|
||||
|
||||
if [ ! -e $CERT.issuer ]; then
|
||||
cp $TMP/chain.pem $CERT.issuer &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 5 "can't update $CERT.issuer file"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $SKIP_UPDATE -eq 0 ]; then
|
||||
if [ $ISNEW -eq 1 ]; then
|
||||
# no .ocsp file found, maybe it's an initial run
|
||||
Debug "Reloading haproxy."
|
||||
|
||||
service haproxy reload
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 5 "can't reload haproxy with 'service haproxy reload'"
|
||||
fi
|
||||
else
|
||||
# update haproxy via local UNIX socket
|
||||
Debug "Updating haproxy."
|
||||
|
||||
echo "set ssl ocsp-response `base64 -w 0 $TMP/ocsp.der`" | $SOCAT_BIN stdio $HAPROXY_ADMIN_SOCKET &>>$TMP/log
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
Error 5 "can't update haproxy ssl ocsp-response using $HAPROXY_ADMIN_SOCKET socket"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
Debug "Not notifying haproxy because skip-update is set."
|
||||
fi
|
||||
|
||||
else
|
||||
Debug "Debug mode: haproxy update skipped."
|
||||
fi
|
||||
|
||||
# remove temporary files and quit with success
|
||||
Quit 0
|
||||
|
||||
# vim: set tabstop=4 shiftwidth=4 expandtab:
|
|
@ -1,50 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
H_NAME="{{ letsencrypt_acme_sh_certs_data_prefix }}"
|
||||
LE_SERVICES_SCRIPT_DIR=/usr/lib/acme/hooks
|
||||
LE_CERTS_DIR=/var/lib/acme/live/$H_NAME
|
||||
LE_LOG_DIR=/var/log/letsencrypt
|
||||
HAPROXY_CERTDIR=/etc/pki/haproxy
|
||||
HAPROXY_CERTFILE=$HAPROXY_CERTDIR/haproxy.pem
|
||||
DATE=$( date )
|
||||
|
||||
[ ! -d $HAPROXY_CERTDIR ] && mkdir -p $HAPROXY_CERTDIR
|
||||
[ ! -d $LE_LOG_DIR ] && mkdir $LE_LOG_DIR
|
||||
echo "$DATE" >> $LE_LOG_DIR/haproxy.log
|
||||
|
||||
{% if letsencrypt_acme_install %}
|
||||
LE_ENV_FILE=/etc/default/letsencrypt
|
||||
{% endif %}
|
||||
{% if letsencrypt_acme_sh_install %}
|
||||
LE_ENV_FILE=/etc/default/acme_sh_request_env
|
||||
{% endif %}
|
||||
if [ -f "$LE_ENV_FILE" ] ; then
|
||||
. "$LE_ENV_FILE"
|
||||
else
|
||||
echo "No letsencrypt default file" >> $LE_LOG_DIR/haproxy.log
|
||||
fi
|
||||
|
||||
echo "Building the new certificate file" >> $LE_LOG_DIR/haproxy.log
|
||||
cat ${LE_CERTS_DIR}/{fullchain,privkey} > ${HAPROXY_CERTFILE}
|
||||
chmod 440 ${HAPROXY_CERTFILE}
|
||||
chgrp haproxy ${HAPROXY_CERTFILE}
|
||||
|
||||
echo "Reload the haproxy service" >> $LE_LOG_DIR/haproxy.log
|
||||
if [ -x /bin/systemctl ] ; then
|
||||
systemctl reload haproxy >> $LE_LOG_DIR/haproxy.log 2>&1
|
||||
else
|
||||
service haproxy reload >> $LE_LOG_DIR/haproxy.log 2>&1
|
||||
fi
|
||||
|
||||
# Run the OCSP stapling script
|
||||
if [ -x /usr/local/bin/hapos-upd ] ; then
|
||||
echo "Run the OCSP stapling updater script" >> $LE_LOG_DIR/haproxy.log
|
||||
/usr/local/bin/hapos-upd --cert {{ haproxy_cert_dir }}/haproxy.pem -v ${LE_CERTS_DIR}/fullchain -s {{ haproxy_admin_socket }} -v - >> $LE_LOG_DIR/haproxy.log 2>&1
|
||||
else
|
||||
echo "No OCPS stapling updater script" >> $LE_LOG_DIR/haproxy.log
|
||||
fi
|
||||
|
||||
echo "Done." >> $LE_LOG_DIR/haproxy.log
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# Check the haproxy backends status
|
||||
command[lb_check_bk_status]=/usr/bin/sudo {{ nagios_local_plugdir }}/check_haproxy_stats -s {{ haproxy_admin_socket }} -w {{ haproxy_nagios_check_w }} -c {{ haproxy_nagios_check_c }}
|
||||
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
---
|
||||
#
|
||||
# This playbook depends on the php-fpm, mysql role and nginx
|
||||
#
|
||||
mw_install_from_package: False
|
||||
# Distribution packages are always obsolete
|
||||
mw_install_from_tar: True
|
||||
mw_version: 1.33
|
||||
mw_minor_minor: 0
|
||||
mw_download_url: http://releases.wikimedia.org/mediawiki/{{ mw_version }}/mediawiki-{{ mw_version }}.{{ mw_minor_minor }}.tar.gz
|
||||
mw_download_dir: /srv/mediawiki
|
||||
mw_install_dir: /var/www/html
|
||||
mw_conf_dir: /etc/mediawiki
|
||||
mw_servername: '{{ ansible_fqdn }}'
|
||||
mw_db_host: localhost
|
||||
mw_db_table_prefix: 'mw_'
|
||||
|
||||
mw_local_nginx_virtualhost: '{{ mw_local_nginx }}'
|
||||
mw_context: wiki
|
||||
mw_doc_root: '{{ mw_install_dir }}/{{ mw_context }}'
|
||||
mw_wiki_servername: '{{ ansible_fqdn }}'
|
||||
mw_wiki_name: 'Mediawiki Installation'
|
||||
|
||||
mw_upload_subdirs:
|
||||
- archive
|
||||
- thumb
|
||||
- temp
|
||||
|
||||
mw_local_mysql: True
|
||||
mw_local_nginx: True
|
||||
mw_local_memcached: True
|
||||
mw_memcached_hosts: '"127.0.0.1:11211"'
|
||||
|
||||
mw_db_name: mediawiki
|
||||
mw_db_user: mediawiki_u
|
||||
# mw_db_pwd: 'use a vault file'
|
||||
mw_system_user: mwiki
|
||||
# mw_admin_pwd: 'use a vault file'
|
||||
# mw_secret_key: 'use a vault file'
|
||||
|
||||
mw_mysql_db_data:
|
||||
- { name: '{{ mw_db_name }}', user: '{{ mw_db_user }}', pwd: '{{ mw_db_pwd }}', collation: '{{ mysql_default_collation }}', encoding: '{{ mysql_default_encoding }}', user_grant: 'ALL', allowed_hosts: [ '{{ ansible_fqdn }}/32', '127.0.0.1/8', 'localhost' ] }
|
||||
|
||||
mw_id: 'wiki'
|
||||
mw_uri: '/wiki'
|
||||
mw_http_port: 80
|
||||
mw_https_port: 443
|
||||
|
||||
mw_php_version: 7.2
|
||||
|
||||
mw_php_additional_packages:
|
||||
- 'php{{ php_version }}-mbstring'
|
||||
- 'php{{ php_version }}-xmlrpc'
|
||||
- 'php{{ php_version }}-soap'
|
||||
- 'php{{ php_version }}-gd'
|
||||
- 'php{{ php_version }}-xml'
|
||||
- 'php{{ php_version }}-intl'
|
||||
- 'php{{ php_version }}-mysql'
|
||||
- 'php{{ php_version }}-cli'
|
||||
- 'php{{ php_version }}-zip'
|
||||
- 'php{{ php_version }}-curl'
|
||||
- php-apcu
|
||||
- php-wikidiff2
|
||||
- imagemagick
|
||||
- php-imagick
|
||||
|
||||
mw_phpfpm_pools:
|
||||
- { pool_name: '{{ phpfpm_default_pool_name }}', app_context: '{{ phpfpm_default_context }}', user: '{{ phpfpm_default_user }}', group: '{{ phpfpm_default_group }}', listen: '{{ phpfpm_default_listen }}', allowed_clients: '{{ phpfpm_default_allowed_clients }}', pm: '{{ phpfpm_default_pm }}', pm_max_children: '{{ phpfpm_default_pm_max_children }}', pm_start_servers: '{{ phpfpm_default_pm_start_servers }}', pm_min_spare: '{{ phpfpm_default_pm_min_spare_servers }}', pm_max_spare: '{{ phpfpm_default_pm_max_spare_servers }}', pm_max_requests: '{{ phpfpm_default_pm_max_requests }}', pm_status_enabled: '{{ phpfpm_default_pm_status_enabled }}', pm_status_path: '{{ phpfpm_default_pm_status_path }}', ping_enabled: '{{ phpfpm_default_ping_enabled }}', ping_path: '{{ phpfpm_default_ping_path }}', ping_response: '{{ phpfpm_default_ping_response }}', display_errors: '{{ phpfpm_default_display_errors }}', log_errors: '{{ phpfpm_default_log_errors }}', memory_limit: '{{ phpfpm_default_memory_limit }}', slowlog_timeout: '{{ phpfpm_default_slowlog_timeout }}', rlimit_files: '{{ phpfpm_default_rlimit_files }}', php_extensions: '{{ phpfpm_default_extensions }}', define_custom_variables: '{{ phpfpm_default_define_custom_variables }}', admin_write: True, doc_root: '{{ mw_doc_root }}', virthost: '{{ mw_context }}' }
|
||||
|
||||
# This choice is not recommended. The package has a poor list of dependencies. We do not want to deal with those
|
||||
mw_package:
|
||||
- mediawiki
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
dependencies:
|
||||
- { role: '../../library/roles/mysql', when: mw_local_mysql | bool }
|
||||
- role: '../../library/roles/php-fpm'
|
||||
- { role: '../../library/roles/memcached', when: mw_local_memcached | bool }
|
||||
- { role: '../../library/roles/nginx', when: mw_local_nginx | bool }
|
|
@ -1,65 +0,0 @@
|
|||
---
|
||||
- name: Ensure that the download and install dirs exist
|
||||
file: path={{ item }} state=directory
|
||||
with_items:
|
||||
- '{{ mw_download_dir }}'
|
||||
- '{{ mw_install_dir }}'
|
||||
tags: mediawiki
|
||||
|
||||
- name: Download the mediawiki tar file
|
||||
get_url: url={{ mw_download_url }} dest={{ mw_download_dir }}
|
||||
when:
|
||||
- not mw_install_from_package
|
||||
- mw_install_from_tar
|
||||
tags: mediawiki
|
||||
|
||||
- name: Unpack the mediawiki tar file
|
||||
unarchive: copy=no src={{ mw_download_dir }}/mediawiki-{{ mw_version }}.{{ mw_minor_minor }}.tar.gz dest={{ mw_download_dir }}
|
||||
args:
|
||||
creates: '{{ mw_download_dir }}/mediawiki-{{ mw_version }}.{{ mw_minor_minor }}/INSTALL'
|
||||
when: mw_install_from_tar
|
||||
tags: mediawiki
|
||||
|
||||
- name: Move the mediawiki files to the right place
|
||||
command: cp -a {{ mw_download_dir }}/mediawiki-{{ mw_version }}.{{ mw_minor_minor }} {{ mw_doc_root }}
|
||||
args:
|
||||
creates: '{{ mw_doc_root }}/index.php'
|
||||
when: mw_install_from_tar
|
||||
tags: mediawiki
|
||||
|
||||
- name: Create the images subdirs
|
||||
file: dest={{ mw_doc_root }}/images/{{ item }} state=directory
|
||||
with_items: '{{ mw_upload_subdirs }}'
|
||||
tags: mediawiki
|
||||
|
||||
- name: Set the correct ownership of the mediawiki files
|
||||
file: dest={{ mw_doc_root }} owner={{ item.user }} group={{ item.group }} recurse=yes state=directory
|
||||
with_items: '{{ phpfpm_pools }}'
|
||||
tags: mediawiki
|
||||
|
||||
- name: Create the mediawiki conf dir
|
||||
file: path={{ mw_conf_dir }} state=directory
|
||||
tags: mediawiki
|
||||
|
||||
- block:
|
||||
|
||||
- name: Check if the mediawiki instance has been initialized already
|
||||
stat: path={{ mw_doc_root }}/.mwinitialized
|
||||
register: mw_init
|
||||
|
||||
tags: [ 'mediawiki', 'mediawiki_init' ]
|
||||
|
||||
- block:
|
||||
- name: Create a file with the DB password
|
||||
template: src=mw_db_passwd.j2 dest=/tmp/mw_db_passwd owner=root group=root mode=0400
|
||||
|
||||
- name: Create a file with the admin password
|
||||
template: src=mw_admin_passwd.j2 dest=/tmp/mw_admin_passwd owner=root group=root mode=0400
|
||||
|
||||
- name: Initialize the mediawiki instance
|
||||
shell: cd {{ mw_doc_root }} ; php maintenance/install.php --confpath {{ mw_conf_dir }} --dbname {{ mw_db_name }} --dbprefix {{ mw_db_table_prefix }} --dbuser {{ mw_db_user }} --dbpassfile /tmp/mw_db_passwd --with-extensions --scriptpath {{ mw_uri }} --passfile /tmp/mw_admin_passwd --wiki {{ mw_id }} --dbserver {{ mw_db_host }} --dbtype mysql --server https://{{ mw_wiki_servername }} "{{ mw_wiki_name }}" {{ mw_system_user }} && touch {{ mw_doc_root }}/.mwinitialized ; rm -f /tmp/mw_db_passwd /tmp/mw_admin_passwd
|
||||
args:
|
||||
creates: '{{ mw_doc_root }}/.mwinitialized'
|
||||
|
||||
when: mw_init.stat.exists is defined and not mw_init.stat.exists
|
||||
tags: [ 'mediawiki', 'mediawiki_init' ]
|
|
@ -1 +0,0 @@
|
|||
{{ mw_admin_pwd }}
|
|
@ -1 +0,0 @@
|
|||
{{ mw_db_pwd }}
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
http_port: '{{ mw_http_port }}'
|
||||
https_port: '{{ mw_https_port }}'
|
||||
|
||||
php_version: '{{ mw_php_version }}'
|
||||
|
||||
php_additional_packages: '{{ mw_php_additional_packages }}'
|
||||
|
||||
mysql_db_data: '{{ mw_mysql_db_data }}'
|
||||
|
||||
phpfpm_default_pool_name: '{{ mw_system_user }}'
|
||||
phpfpm_default_user: '{{ mw_system_user }}'
|
||||
|
||||
phpfpm_pools: '{{ mw_phpfpm_pools }}'
|
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
prometheus_h_e_install: True
|
||||
prometheus_h_e_version: 0.9.0
|
||||
prometheus_h_e_dir: 'haproxy_exporter-{{ prometheus_h_e_version }}.linux-amd64'
|
||||
prometheus_h_e_file: '{{ prometheus_h_e_dir }}.tar.gz'
|
||||
prometheus_h_e_download_url: 'https://github.com/prometheus/haproxy_exporter/releases/download/v{{ prometheus_h_e_version }}/{{ prometheus_h_e_file }}'
|
||||
prometheus_h_e_user: prometheus
|
||||
prometheus_h_e_home: /opt/prometheus
|
||||
prometheus_h_e_dist_dir: '{{ prometheus_h_e_home }}/dist'
|
||||
prometheus_h_e_logdir: '/var/log/prometheus-haproxy-exporter'
|
||||
prometheus_h_e_cmd: '{{ prometheus_h_e_dist_dir }}/{{ prometheus_h_e_dir }}/haproxy_exporter'
|
||||
prometheus_h_e_port: 9101
|
||||
prometheus_h_e_loglevel: info
|
||||
prometheus_h_e_haproxy_pid: '/run/haproxy.pid'
|
||||
prometheus_h_e_haproxy_stats_port: 8881
|
||||
prometheus_h_e_opts: '--web.listen-address=":{{ prometheus_h_e_port }}" --log.level={{ prometheus_h_e_loglevel }} --haproxy.pid-file="{{ prometheus_h_e_haproxy_pid }}" --haproxy.scrape-uri="http://localhost:{{ prometheus_h_e_haproxy_stats_port }}/;csv"'
|
||||
# List the additional options here
|
||||
prometheus_h_e_additional_opts: ''
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
- name: systemd reload
|
||||
command: systemctl daemon-reload
|
||||
|
||||
- name: Restart haproxy exporter
|
||||
service: name=haproxy_exporter state=restarted
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
- block:
|
||||
- name: Create the user under the haproxy exporter will run
|
||||
user: name={{ prometheus_h_e_user }} home={{ prometheus_h_e_home }} createhome=no shell=/usr/sbin/nologin system=yes
|
||||
|
||||
- name: Create the prometheus haproxy exporter base directory
|
||||
file: dest={{ item }} state=directory owner=root group=root
|
||||
with_items:
|
||||
- '{{ prometheus_h_e_home }}'
|
||||
- '{{ prometheus_h_e_dist_dir }}'
|
||||
|
||||
- name: Create the prometheus haproxy exporter log directory
|
||||
file: dest={{ prometheus_h_e_logdir }} state=directory owner={{ prometheus_h_e_user }} group={{ prometheus_h_e_user }}
|
||||
|
||||
- name: Download the prometheus haproxy exporter
|
||||
get_url: url={{ prometheus_h_e_download_url }} dest=/srv/
|
||||
|
||||
- name: Unarchive the prometheus distribution
|
||||
unarchive: src=/srv/{{ prometheus_h_e_file }} dest={{ prometheus_h_e_dist_dir }} remote_src=yes owner=root group=root
|
||||
args:
|
||||
creates: '{{ prometheus_h_e_dist_dir }}/{{ prometheus_h_e_dir }}/haproxy_exporter'
|
||||
notify: Restart haproxy exporter
|
||||
|
||||
- name: Install the prometheus haproxy exporter upstart script
|
||||
template: src=haproxy_exporter.upstart.j2 dest=/etc/init/haproxy_exporter.conf mode=0644 owner=root group=root
|
||||
when: ansible_service_mgr != 'systemd'
|
||||
|
||||
- name: Install the prometheus haproxy exporter systemd unit
|
||||
template: src=haproxy_exporter.systemd.j2 dest=/etc/systemd/system/haproxy_exporter.service mode=0644 owner=root group=root
|
||||
when: ansible_service_mgr == 'systemd'
|
||||
notify: systemd reload
|
||||
|
||||
- name: Ensure that prometheus haproxy_exporter is started and enabled
|
||||
service: name=haproxy_exporter state=started enabled=yes
|
||||
|
||||
tags: [ 'prometheus', 'haproxy_exporter' ]
|
||||
when: prometheus_h_e_install
|
||||
|
||||
- block:
|
||||
- name: Ensure that prometheus haproxy_exporter is stopped and disabled
|
||||
service: name=haproxy_exporter state=stopped enabled=no
|
||||
|
||||
- name: Remove prometheus haproxy exporter upstart script
|
||||
file: dest=/etc/init/haproxy_exporter.conf state=absent
|
||||
when: ansible_service_mgr != 'systemd'
|
||||
|
||||
- name: Remove the prometheus haproxy exporter systemd unit
|
||||
file: dest=/etc/systemd/system/haproxy_exporter.service state=absent
|
||||
when: ansible_service_mgr == 'systemd'
|
||||
notify: systemd reload
|
||||
|
||||
tags: [ 'prometheus', 'haproxy_exporter' ]
|
||||
when: not prometheus_h_e_install
|
|
@ -1,17 +0,0 @@
|
|||
[Unit]
|
||||
Description=haproxy_exporter - Prometheus exporter for haproxy metrics and stats.
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
|
||||
User={{ prometheus_h_e_user }}
|
||||
Group={{ prometheus_h_e_user }}
|
||||
|
||||
ExecStart={{ prometheus_h_e_cmd }} {{ prometheus_h_e_opts }} {{ prometheus_h_e_additional_opts }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=prometheus_haproxy_exporter.service
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
description "Prometheus haproxy exporter"
|
||||
start on (local-filesystems and net-device-up IFACE!=lo)
|
||||
stop on runlevel [016]
|
||||
|
||||
respawn
|
||||
respawn limit 10 5
|
||||
setuid {{ prometheus_h_e_user }}
|
||||
setgid {{ prometheus_h_e_user }}
|
||||
|
||||
script
|
||||
exec {{ prometheus_h_e_cmd }} {{ prometheus_h_e_opts }} {{ prometheus_h_e_additional_opts }} > {{ prometheus_h_e_logdir }}/haproxy_exporter.log 2>&1
|
||||
end script
|
Loading…
Reference in New Issue