]> granicus.if.org Git - icinga2/blob - doc/99-selinux.md
Add missing openssl verify to cluster troubleshooting docs
[icinga2] / doc / 99-selinux.md
1 # <a id="selinux"></a> SELinux
2
3 ## <a id="selinux-introduction"></a> Introduction
4
5 SELinux is a mandatory access control (MAC) system on Linux which adds a fine granular permission system for access to all resources on the system such as files, devices, networks and inter-process communication.
6
7 The most important questions are answered briefly in the [FAQ of the SELinux Project](http://selinuxproject.org/page/FAQ). For more details on SELinux and how to actually use and administrate it on your systems have a look at [Red Hat Enterprise Linux 7 - SELinux User's and Administrator's Guide](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/index.html). For an simplified (and funny) introduction download the [SELinux Coloring Book](https://github.com/mairin/selinux-coloring-book).
8
9 This documentation will use a similar format like the SELinux User's and Administrator's Guide.
10
11 ### <a id="selinux-policy"></a> Policy
12
13 Icinga 2 is providing its own SELinux Policy. At the moment it is not upstreamed to the reference policy because it is under development. Target of the development is a policy package for Red Hat Enterprise Linux 7 and its derivates running the targeted policy which confines Icinga2 with all features and all checks executed.
14
15 ### <a id="selinux-policy-installation"></a> Installation
16
17 Later the policy will be installed by a seperate package and this section will be removed. Now it describes the installation to support development and testing. It assumes that Icinga 2 is already installed from packages and running on the system.
18
19 The policy package will run the daemon in a permissive domain so nothing will be denied also if the system runs in enforcing mode, so please make sure to run the system in this mode.
20
21     # sestatus
22     SELinux status:                 enabled
23     SELinuxfs mount:                /sys/fs/selinux
24     SELinux root directory:         /etc/selinux
25     Loaded policy name:             targeted
26     Current mode:                   enforcing
27     Mode from config file:          enforcing
28     Policy MLS status:              enabled
29     Policy deny_unknown status:     allowed
30     Max kernel policy version:      28
31
32 You can change the configured mode by editing `/etc/selinux/config` and the current mode by executing `setenforce 0`.
33
34 As a prerequisite install the `git`, `selinux-policy-devel` and `audit` package. Enable and start the audit daemon afterwards.
35
36     # yum install git selinux-policy-devel audit
37     # systemctl enable auditd.service
38     # systemctl start auditd.service
39
40 After that clone the icinga2 git repository and checkout the feature branch.
41
42     # git clone git://git.icinga.org/icinga2.git
43     # cd icinga2/
44     # git checkout feature/rpm-selinux-8332
45
46 To create and install the policy package run the installation script which also labels the resources. (The script assumes Icinga 2 was started once after system startup, the labeling of the port will only happen once and fail later on.)
47
48     # cd tools/selinux/
49     # ./icinga.sh
50
51 Some changes to the systemd scripts are also required to handle file contexts correctly. This is at the moment only included in the feature branch, so it has to be copied manually.
52
53     # cp ../../etc/initsystem/{prepare-dirs,safe-reload} /usr/lib/icinga2/
54
55 After that restart Icinga 2 and verify it running in its own domain `icinga2_t`.
56
57     # systemctl restart icinga2.service
58     # ps -eZ | grep icinga2
59     system_u:system_r:icinga2_t:s0   2825 ?        00:00:00 icinga2
60
61 ### <a id="selinux-policy-general"></a> General
62
63 When the SELinux policy package for Icinga 2 is installed, the Icinga 2 daemon (icinga2) runs in its own domain `icinga2_t` and is separated from other confined services.
64
65 Files have to be labeled correctly for allowing icinga2 access to it. For example it writes to its own log files labeled `icinga2_log_t`. Also the API port is labeled `icinga_port_t` and icinga2 is allowed to manage it. Furthermore icinga2 can open high ports and unix sockets to connect to databases and features like graphite. It executes the nagios plugins and transitions to their context if those are labeled for example `nagios_services_plugin_exec_t` or `nagios_system_plugin_exec_t`.
66
67 Additional the Apache webserver is allowed to connect to the Command pipe of Icinga 2 to allow web interfaces sending commands to icinga2. This will perhaps change later on while investigating Icinga Web 2 for SELinux!
68
69 ### <a id="selinux-policy-types"></a> Types
70
71 The command pipe is labeled `icinga2_command_t` and other services can request access to it by using the interface `icinga2_send_commands`.
72
73 The nagios plugins use their own contexts and icinga2 will transition to it. This means plugins have to be labeled correctly for their required permissions. The plugins installed from package should have set their permissions by the corresponding policy module and you can restore them using `restorecon -R -v /usr/lib64/nagios/plugins/`. To label your own plugins use `chcon -t type /path/to/plugin`, for the type have a look at table below.
74
75 Type                              | Domain                       | Use case                                                         | Provided by policy package
76 ----------------------------------|------------------------------|------------------------------------------------------------------|---------------------------
77 nagios_admin_plugin_exec_t        | nagios_admin_plugin_t        | Plugins which require require read access on all file attributes | nagios
78 nagios_checkdisk_plugin_exec_t    | nagios_checkdisk_plugin_t    | Plugins which require read access to all filesystem attributes   | nagios
79 nagios_mail_plugin_exec_t         | nagios_mail_plugin_t         | Plugins which access the local mail service                      | nagios
80 nagios_services_plugin_exec_t     | nagios_services_plugin_t     | Plugins monitoring network services                              | nagios
81 nagios_system_plugin_exec_t       | nagios_system_plugin_t       | Plugins checking local system state                              | nagios
82 nagios_unconfined_plugin_exec_t   | nagios_unconfined_plugin_t   | Plugins running without confinement                              | nagios
83 nagios_eventhandler_plugin_exec_t | nagios_eventhandler_plugin_t | Eventhandler (actually running unconfined)                       | nagios
84 nagios_openshift_plugin_exec_t    | nagios_openshift_plugin_t    | Plugins monitoring openshift                                     | nagios
85 nagios_notification_plugin_exec_t | nagios_notification_plugin_t | Notification commands                                            | icinga (will be moved later)
86
87 If one of those plugin domains causes problems you can set it to permissive by executing `semanage permissive -a domain`.
88
89 The policy provides a role `icinga2adm_r` for confining an user which enables an administrative user managing only Icinga 2 on the system. This user will also execute the plugins in their domain instead of the users one, so you can verify their execution with the same restrictions like they have when executed by icinga2.
90
91 ### <a id="selinux-policy-booleans"></a> Booleans
92
93 SELinux is based on the least level of access required for a service to run. Using booleans you can grant more access in a defined way. The Icinga 2 policy package provides the following booleans.
94
95 **icinga2_can_connect_all** 
96
97 Having this boolean enabled allows icinga2 to connect to all ports. This can be neccesary if you use features which connect to unconfined services.
98
99 ### <a id="selinux-policy-examples"></a> Configuration Examples
100
101 #### <a id="selinux-policy-examples-plugin"></a> Confining a plugin
102
103 Download and install a plugin, for example check_mysql_health.
104
105     # wget http://labs.consol.de/download/shinken-nagios-plugins/check_mysql_health-2.1.9.2.tar.gz
106     # tar xvzf check_mysql_health-2.1.9.2.tar.gz
107     # cd check_mysql_health-2.1.9.2/
108     # ./configure --libexecdir /usr/lib64/nagios/plugins
109     # make
110     # make install
111
112 It is labeled `nagios_unconfined_plugins_exec_t` by default, so it runs without restrictions.
113
114     # ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
115     -rwxr-xr-x. root root system_u:object_r:nagios_unconfined_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
116
117 In this case the plugin is monitoring a service, so it should be labeled `nagios_services_plugin_exec_t` to restrict its permissions.
118
119     # chcon -t nagios_services_plugin_exec_t /usr/lib64/nagios/plugins/check_mysql_health
120     # ls -lZ /usr/lib64/nagios/plugins/check_mysql_health
121     -rwxr-xr-x. root root system_u:object_r:nagios_services_plugin_exec_t:s0 /usr/lib64/nagios/plugins/check_mysql_health
122
123 The plugin still runs fine but if someone changes the script to do weird stuff it will fail to do so.
124
125 #### <a id="selinux-policy-examples-connectall"></a> Allow icinga to connect to all ports.
126
127 You are running graphite on a different port than `2003` and want `icinga2` to connect to it.
128
129 Change the port value for the graphite feature according to your graphite installation before enabling it.
130
131     # cat /etc/icinga2/features-enabled/graphite.conf 
132     /**
133      * The GraphiteWriter type writes check result metrics and
134      * performance data to a graphite tcp socket.
135      */
136
137     library "perfdata"
138
139     object GraphiteWriter "graphite" {
140       //host = "127.0.0.1"
141       //port = 2003
142       port = 2004
143     }
144     # icinga2 feature enable graphite
145
146 Before you restart the icinga2 service allow it to connect to all ports by enabling the boolean ´icinga2_can_connect_all` (now and permanent).
147
148     # setsebool icinga2_can_connect_all true
149     # setsebool -P icinga2_can_connect_all true
150
151 If you restart the daemon now it will successfully connect to graphite.
152
153 #### <a id="selinux-policy-examples-user"></a> Confining a user
154
155 Start by adding the Icinga 2 administrator role `icinga2adm_r` to the administrative SELinux user `staff_u`.
156
157     # semanage user -m -R "staff_r sysadm_r system_r unconfined_r icinga2adm_r" staff_u
158
159 Confine your user login and create a sudo rule.
160
161     # semanage login -a dirk -s staff_u
162     # echo "dirk ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/dirk
163
164 Login to the system using ssh and verify your id.
165
166     $ id -Z
167     staff_u:staff_r:staff_t:s0-s0:c0.c1023
168
169 Try to execute some commands as root using sudo.
170
171     $ sudo id -Z
172     staff_u:staff_r:staff_t:s0-s0:c0.c1023
173     $ sudo vi /etc/icinga2/icinga2.conf
174     "/etc/icinga2/icinga2.conf" [Permission Denied]
175     $ sudo cat /var/log/icinga2/icinga2.log
176     cat: /var/log/icinga2/icinga2.log: Keine Berechtigung
177     $ sudo systemctl reload icinga2.service
178     Failed to get D-Bus connection: No connection to service manager.
179
180 Those commands fail because you only switch to root but do not change your SELinux role. Try again but tell sudo also to switch the SELinux role and type.
181
182     $ sudo -r icinga2adm_r -t icinga2adm_t id -Z
183     staff_u:icinga2adm_r:icinga2adm_t:s0-s0:c0.c1023
184     $ sudo -r icinga2adm_r -t icinga2adm_t vi /etc/icinga2/icinga2.conf
185     "/etc/icinga2/icinga2.conf"
186     $ sudo -r icinga2adm_r -t icinga2adm_t cat /var/log/icinga2/icinga2.log
187     [2015-03-26 20:48:14 +0000] information/DynamicObject: Dumping program state to file '/var/lib/icinga2/icinga2.state'
188     $ sudo -r icinga2adm_r -t icinga2adm_t systemctl reload icinga2.service
189
190 Now the commands will work, but you have always to remember to add the arguments, so change the sudo rule to set it by default.
191
192     # echo "dirk ALL=(ALL) ROLE=icinga2adm_r TYPE=icinga2adm_t NOPASSWD: ALL" > /etc/sudoers.d/dirk
193
194 Now try the commands again without providing the role and type and they will work, but if you try to read apache logs or restart apache for example it will still fail.
195
196     $ sudo cat /var/log/httpd/error_log
197     /bin/cat: /var/log/httpd/error_log: Keine Berechtigung
198     $ sudo systemctl reload httpd.service
199     Failed to issue method call: Access denied
200
201 ## <a id="selinux-bugreports"></a> Bugreports
202
203 If you experience any problems while running in enforcing mode try to reproduce it in permissive mode. If the problem persists it is not related to SELinux because in permissive mode SELinux will not deny anything.
204
205 For now Icinga 2 is running in a permissive domain and adds also some rules for other necessary services so no problems should occure at all. But you can help to enhance the policy by testing Icinga 2 running confined by SELinux.
206
207 When filing a bug report please add the following information additionally to the [normal ones](https://www.icinga.org/icinga/faq/):
208 * Output of `semodule -l | grep -e icinga2 -e nagios -e apache`
209 * Output of `ps -eZ | grep icinga2`
210 * Output of `semanage port -l | grep icinga2`
211 * Output of `audit2allow -li /var/log/audit/audit.log`
212
213 If access to a file is blocked and you can tell which one please provided the output of `ls -lZ /path/to/file` (and perhaps the directory above).
214
215 If asked for full audit.log add `-w /etc/shadow -p w` to `/etc/audit/rules.d/audit.rules`, restart the audit daemon, reproduce the problem and add `/var/log/audit/audit.log` to the bug report. With the added audit rule it will include the path of files access was denied to.
216
217 If asked to provide full audit log with dontaudit rules disabled executed `semodule -DB` before reproducing the problem. After that enable the rules again to prevent auditd spamming your logfile by executing `semodule -B`.