Wiki source code of Icinga 2

Last modified by Sebastian Marsching on 2022/04/03 22:58

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 Next, we create the configuration file for OpenSSL as `/var/lib/icinga2/ca/crl/openssl.cnf`:
21
22 # OpenSSL configuration for CRL generation
23 #
24 ####################################################################
25 [ ca ]
26 default_ca = CA_default # The default ca section
27
28 ####################################################################
29 [ CA_default ]
30 database = /var/lib/icinga2/ca/crl/index.txt
31 crlnumber = /var/lib/icinga2/ca/crl/crlnumber.txt
32 certificate = /var/lib/icinga2/ca/ca.crt
33 private_key = /var/lib/icinga2/ca/ca.key
34
35 crl_extensions = crl_ext # name of the section containing the
36 # CRL extensions
37 default_crl_days = 365 # how long before next CRL
38 default_crl_hours = 0
39 default_md = sha256 # use SHA256 for signing the CRL
40 unique_subject = no # do not enforce unique certificate
41 # subjects
42
43 ####################################################################
44 [ crl_ext ]
45 # CRL extensions.
46
47 Finally, we want two shell scripts. One for generating the CRL and one for revoking a certificate.
48
49 `/var/lib/icinga2/ca/crl/gen-crl.sh`:
50
51 ```bash
52 #!/bin/bash
53
54 # Find the path to this file (this script might be referenced through a
55 # symbolic link).
56 CURRENT_WORKING_DIRECTORY="`pwd`"
57 THIS_FILE="$0"
58 cd "`dirname "$THIS_FILE"`"
59 THIS_FILE="`basename "$THIS_FILE"`"
60 while [ -L "$THIS_FILE" ]; do
61 THIS_FILE="`readlink "$THIS_FILE"`"
62 cd "`dirname "$THIS_FILE"`"
63 THIS_FILE="`basename "$THIS_FILE"`"
64 done
65 THIS_FILE="`pwd -P `/$THIS_FILE"
66 cd "$CURRENT_WORKING_DIRECTORY"
67 BASE_DIR="`dirname "$THIS_FILE"`"
68
69 openssl ca -config "$BASE_DIR/openssl.cnf" -gencrl -out "$BASE_DIR/crl.pem"
70 ```
71
72 `/var/lib/icinga2/ca/crl/revoke.sh`:
73
74 ```bash
75 #!/bin/bash
76
77 # Find the path to this file (this script might be referenced through a
78 # symbolic link).
79 CURRENT_WORKING_DIRECTORY="`pwd`"
80 THIS_FILE="$0"
81 cd "`dirname "$THIS_FILE"`"
82 THIS_FILE="`basename "$THIS_FILE"`"
83 while [ -L "$THIS_FILE" ]; do
84 THIS_FILE="`readlink "$THIS_FILE"`"
85 cd "`dirname "$THIS_FILE"`"
86 THIS_FILE="`basename "$THIS_FILE"`"
87 done
88 THIS_FILE="`pwd -P `/$THIS_FILE"
89 cd "$CURRENT_WORKING_DIRECTORY"
90 BASE_DIR="`dirname "$THIS_FILE"`"
91
92 for cert in "$@"; do
93 openssl ca -config "$BASE_DIR/openssl.cnf" -revoke "$cert"
94 done
95 ```
96
97 Do not forget to make the shell scripts executable:
98
99 ```bash
100 chmod a+x /var/lib/icinga2/ca/crl/gen-crl.sh
101 chmod a+x /var/lib/icinga2/ca/crl/revoke.sh
102 ```
103
104 You might also want to change the owner of these files, though this step is entirely optional:
105
106 ```bash
107 chown -R nagios:nagios /var/lib/icinga2/ca/crl
108 ```
109
110 Now in order to revoke a certificate, you call `revoke.sh` with the certificate file as the parameter. For example:
111
112 ```bash
113 /var/lib/icinga2/ca/crl/revoke.sh /var/lib/icinga2/ca/host.example.com.crt
114 ```
115
116 After revoking a certificate, you have to regenerate the CRL in order to include the revoked certificate in the CRL:
117
118 ```bash
119 /var/lib/icinga2/ca/crl/gen-crl.sh
120 ```
121
122 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/).
123
124 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.
125
126 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`.
127
128 /**
129 * The API listener is used for distributed monitoring setups.
130 */
131
132 object ApiListener "api" {
133 cert_path = SysconfDir + "/icinga2/pki/" + NodeName + ".crt"
134 key_path = SysconfDir + "/icinga2/pki/" + NodeName + ".key"
135 ca_path = SysconfDir + "/icinga2/pki/ca.crt"
136 crl_path = SysconfDir + "/icinga2/pki/crl.pem"
137
138 ticket_salt = TicketSalt
139 }
140
141 # Building a Python 3 compatble Debian package for Pynag
142
143 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.
144
145 ```bash
146 PYNAG_VERSION=0.9.1
147 PYNAG_GIT_COMMIT=bcdbd435dd48f9bf791b5d41307da93683cb17b3
148
149 # We need python-stdeb and python3-stdeb in order to build the Debian packages.
150 # For some reason apt-get does not automatically install dh-python, python-all,
151 # and python3-all, even though they are needed (and recommended) for
152 # python-stdeb to work correctly.
153 sudo apt-get -y install dh-python python-all python3-all python-stdeb and python3-stdeb
154
155 curl -L -o pynag-$PYNAG_VERSION.tar.gz https://github.com/netmarkjp/pynag/archive/$PYNAG_GIT_COMMIT.tar.gz
156
157 # We have to specify DEB_BUILD_OPTIONS=nocheck because the tests have some
158 # additional dependencies that we do not want to install.
159 # We do not build the package for Python 2 because for Python 2, we can use the
160 # original version shipped with Ubuntu.
161 DEB_BUILD_OPTIONS=nocheck py2dsc-deb --with-python2=false --with-python3=true pynag-$PYNAG_VERSION.tar.gz
162 ```