Wiki source code of Icinga 2

Version 1.2 by Sebastian Marsching on 2022/04/03 14:08

Show last authors
1 {{toc/}}
2
3 # Using a Certificate Revocation List (CRL) with Icinga 2
4
5 **Before you start**: There is a [bug](https://github.com/Icinga/icinga2/issues/5040) in Icinga 2 (at least up to version 2.6.2) that prevents a CRL from being loaded, so you have to ensure that you use a newer version or patch the bug yourself.
6
7 Icinga 2 makes managing the CA easy by using the `icinga2 pki` commands. However, it does not provide any commands for generating a CRL. This means that the regular `openssl` tool needs to be used for that. The functions for generating a CRL are part of the `ca` module, so one first has to create a CA configuration for OpenSSL. For the rest of this tutorial, we assume that the certificates for Icinga 2 are stored in the default location (`/var/lib/icinga2/ca`).
8
9 First, we create the directory `/var/lib/icinga2/ca/crl` and a number of files needed in this directory:
10
11 ```bash
12 mkdir /var/lib/icinga2/ca/crl
13 cd /var/lib/icinga2/ca/crl
14 touch index.txt
15 echo "unique_subject = no" >index.txt.attr
16 echo "0000" >crlnumber.txt
17 touch crl.pem
18
19 ```
20
21 Next, we create the configuration file for OpenSSL as `/var/lib/icinga2/ca/crl/openssl.cnf`:
22
23 # OpenSSL configuration for CRL generation
24 #
25 ####################################################################
26 [ ca ]
27 default_ca = CA_default # The default ca section
28
29 ####################################################################
30 [ CA_default ]
31 database = /var/lib/icinga2/ca/crl/index.txt
32 crlnumber = /var/lib/icinga2/ca/crl/crlnumber.txt
33 certificate = /var/lib/icinga2/ca/ca.crt
34 private_key = /var/lib/icinga2/ca/ca.key
35
36 crl_extensions = crl_ext # name of the section containing the
37 # CRL extensions
38 default_crl_days = 365 # how long before next CRL
39 default_crl_hours = 0
40 default_md = sha256 # use SHA256 for signing the CRL
41 unique_subject = no # do not enforce unique certificate
42 # subjects
43
44 ####################################################################
45 [ crl_ext ]
46 # CRL extensions.
47
48 Finally, we want two shell scripts. One for generating the CRL and one for revoking a certificate.
49
50 ```bash
51 #!/bin/bash
52
53 # Find the path to this file (this script might be referenced through a
54 # symbolic link).
55 CURRENT_WORKING_DIRECTORY="`pwd`"
56 THIS_FILE="$0"
57 cd "`dirname "$THIS_FILE"`"
58 THIS_FILE="`basename "$THIS_FILE"`"
59 while [ -L "$THIS_FILE" ]; do
60 THIS_FILE="`readlink "$THIS_FILE"`"
61 cd "`dirname "$THIS_FILE"`"
62 THIS_FILE="`basename "$THIS_FILE"`"
63 done
64 THIS_FILE="`pwd -P `/$THIS_FILE"
65 cd "$CURRENT_WORKING_DIRECTORY"
66 BASE_DIR="`dirname "$THIS_FILE"`"
67
68 openssl ca -config "$BASE_DIR/openssl.cnf" -gencrl -out "$BASE_DIR/crl.pem"
69 ```
70
71 ```bash
72 #!/bin/bash
73
74 # Find the path to this file (this script might be referenced through a
75 # symbolic link).
76 CURRENT_WORKING_DIRECTORY="`pwd`"
77 THIS_FILE="$0"
78 cd "`dirname "$THIS_FILE"`"
79 THIS_FILE="`basename "$THIS_FILE"`"
80 while [ -L "$THIS_FILE" ]; do
81 THIS_FILE="`readlink "$THIS_FILE"`"
82 cd "`dirname "$THIS_FILE"`"
83 THIS_FILE="`basename "$THIS_FILE"`"
84 done
85 THIS_FILE="`pwd -P `/$THIS_FILE"
86 cd "$CURRENT_WORKING_DIRECTORY"
87 BASE_DIR="`dirname "$THIS_FILE"`"
88
89 for cert in "$@"; do
90 openssl ca -config "$BASE_DIR/openssl.cnf" -revoke "$cert"
91 done
92 ```
93
94 Do not forget to make the shell scripts executable:
95
96 ```bash
97 chmod a+x /var/lib/icinga2/ca/crl/gen-crl.sh
98 chmod a+x /var/lib/icinga2/ca/crl/revoke.sh
99 ```
100
101 You might also want to change the owner of these files, though this step is entirely optional:
102
103 ```bash
104 chown -R nagios:nagios /var/lib/icinga2/ca/crl
105 ```
106
107 Now in order to revoke a certificate, you call `revoke.sh` with the certificate file as the parameter. For example:
108
109 ```bash
110 /var/lib/icinga2/ca/crl/revoke.sh /var/lib/icinga2/ca/host.example.com.crt
111 ```
112
113 After revoking a certificate, you have to regenerate the CRL in order to include the revoked certificate in the CRL:
114
115 ```bash
116 /var/lib/icinga2/ca/crl/gen-crl.sh
117 ```
118
119 In order to actually use the CRL, you have to distribute it to the Icinga 2 nodes. How to do this is outside of the scope of this tutorial. One might simply use [scp](http://man.openbsd.org/scp) or one could use a configuration management tool like [SaltStack](https://saltstack.com/).
120
121 One thing to consider when distributing the CRL is its validity period: When using a CRL, Icinga 2 will start to reject **all** certificates (even the ones which have not expired yet and have not been revoked either) when the CRL has expired. This means that a new CRL has to be distributed before the old one expires. Choosing a longer validity period (by changing the `crldays` and `crlhours` options in the OpenSSL configuration) might help so that you can distribute the CRL less often. For example, the certificiates generated by Icinga 2 are valid for 5475 days (approximately 15 years). However, in contrast to certificates, there is no way to revoke a CRL. This means that if an attacker got hold of a CRL (which is not unlikely because a CRL is generally considered public information) and found a way to inject that CRL in the distribution process, he might be able to make a node use an old version of the CRL, thus accepting certificates that have been revoked in the meantime. When using a secure channel (like SSH) for distributing the CRL, you might not be worried too much about this scenario.
122
123 In order to make Icinga 2 use the CRL, it has to be registered with the API listener. The following configuration (typically stored in `/etc/icinga2/features-available/api.conf`) assumes that the CRL is stored in `/etc/icinga2/pki/crl.pem`.
124
125 /**
126 * The API listener is used for distributed monitoring setups.
127 */
128
129 object ApiListener "api" {
130 cert_path = SysconfDir + "/icinga2/pki/" + NodeName + ".crt"
131 key_path = SysconfDir + "/icinga2/pki/" + NodeName + ".key"
132 ca_path = SysconfDir + "/icinga2/pki/ca.crt"
133 crl_path = SysconfDir + "/icinga2/pki/crl.pem"
134
135 ticket_salt = TicketSalt
136 }
137
138 # Building a Python 3 compatble Debian package for Pynag
139
140 Ubuntu 18.04 includes the `python-pynag` package, but only for Python 2. There is no `python3-pynag` package, because the upstream version of Pynag is not compatible with Python 3. Luckily, there is a [fork](https://github.com/netmarkjp/) that is compatible with Python 3. The following shell script can be used to build a Debian package of this fork. This package should be compatible with Ubuntu as well.
141
142 ```bash
143 PYNAG_VERSION=0.9.1
144 PYNAG_GIT_COMMIT=bcdbd435dd48f9bf791b5d41307da93683cb17b3
145
146 # We need python-stdeb and python3-stdeb in order to build the Debian packages.
147 # For some reason apt-get does not automatically install dh-python, python-all,
148 # and python3-all, even though they are needed (and recommended) for
149 # python-stdeb to work correctly.
150 sudo apt-get -y install dh-python python-all python3-all python-stdeb and python3-stdeb
151
152 curl -L -o pynag-$PYNAG_VERSION.tar.gz https://github.com/netmarkjp/pynag/archive/$PYNAG_GIT_COMMIT.tar.gz
153
154 # We have to specify DEB_BUILD_OPTIONS=nocheck because the tests have some
155 # additional dependencies that we do not want to install.
156 # We do not build the package for Python 2 because for Python 2, we can use the
157 # original version shipped with Ubuntu.
158 DEB_BUILD_OPTIONS=nocheck py2dsc-deb --with-python2=false --with-python3=true pynag-$PYNAG_VERSION.tar.gz
159 ```