Skip to content

Commit 2a437a0

Browse files
authored
Add SELinux support (#1012)
1 parent ad63b2f commit 2a437a0

File tree

9 files changed

+836
-6
lines changed

9 files changed

+836
-6
lines changed

.nfpm.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# this is the base "template" for the package
22
name: nginx-agent
3-
description: NGINX Agent
3+
description: NGINX Agent
44
arch: ${ARCH}
55
version: ${VERSION}
66
priority: optional
@@ -18,8 +18,20 @@ contents:
1818
mode: 0640
1919
- src: ./scripts/packages/nginx-agent.service
2020
dst: /etc/systemd/system/nginx-agent.service
21+
- src: ./scripts/packages/nginx-agent.openrc
22+
dst: /etc/init.d/nginx-agent
23+
packager: apk
2124
- src: ./scripts/nginx-agent.logrotate
2225
dst: /etc/logrotate.d/nginx-agent
26+
- src: ./scripts/selinux/nginx_agent_selinux.8
27+
dst: /usr/share/man/man8/nginx_agent_selinux.8
28+
packager: rpm
29+
- src: ./scripts/selinux/nginx_agent.if
30+
dst: /usr/share/selinux/devel/include/contrib/nginx_agent.if
31+
packager: rpm
32+
- src: ./scripts/selinux/nginx_agent.pp
33+
dst: /usr/share/selinux/packages/nginx_agent.pp
34+
packager: rpm
2335
- dst: /var/log/nginx-agent
2436
type: dir
2537
overrides:
@@ -36,6 +48,8 @@ rpm:
3648
apk:
3749
signature:
3850
key_file: ".key.rsa"
51+
scripts:
52+
postupgrade: "./scripts/packages/postupgrade.sh"
3953
scripts:
4054
preinstall: "./scripts/packages/preinstall.sh"
4155
postinstall: "./scripts/packages/postinstall.sh"

scripts/packages/.local-nfpm.yaml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,26 @@ contents:
1818
mode: 0640
1919
- src: ./scripts/packages/nginx-agent.service
2020
dst: /etc/systemd/system/nginx-agent.service
21-
- dst: /var/log/nginx-agent
22-
type: dir
2321
- src: ./scripts/packages/nginx-agent.openrc
2422
dst: /etc/init.d/nginx-agent
2523
packager: apk
24+
- src: ./scripts/nginx-agent.logrotate
25+
dst: /etc/logrotate.d/nginx-agent
26+
- src: ./scripts/selinux/nginx_agent_selinux.8
27+
dst: /usr/share/man/man8/nginx_agent_selinux.8
28+
packager: rpm
29+
- src: ./scripts/selinux/nginx_agent.if
30+
dst: /usr/share/selinux/devel/include/contrib/nginx_agent.if
31+
packager: rpm
32+
- src: ./scripts/selinux/nginx_agent.pp
33+
dst: /usr/share/selinux/packages/nginx_agent.pp
34+
packager: rpm
35+
- dst: /var/log/nginx-agent
36+
type: dir
2637
overrides:
27-
deb:
28-
depends:
29-
- apt-transport-https
38+
deb:
39+
depends:
40+
- apt-transport-https
3041
scripts:
3142
preinstall: "./scripts/packages/preinstall.sh"
3243
postinstall: "./scripts/packages/postinstall.sh"

scripts/selinux/README.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# SELinux
2+
3+
https://www.redhat.com/en/topics/linux/what-is-selinux
4+
5+
# Table of Contents
6+
- [Prerequisites](#prerequisites)
7+
- [Enable SELinux](#enable-selinux)
8+
- [Install NGINX Agent Policy](#install-nginx-agent-policy)
9+
- [Updating existing policy](#updating-existing-policy)
10+
- [Troubleshooting](#troubleshooting)
11+
- [Policy version does not match](#policy-version-does-not-match)
12+
- [Unknown Type](#unknown-type)
13+
- [Debugging](#debugging)
14+
- [References](#references)
15+
16+
## Prerequisites
17+
```
18+
sudo yum install policycoreutils-devel rpm-build
19+
```
20+
21+
## Enable SELinux
22+
To enable SELinux, update the file `/etc/selinux/config` by setting `SELINUX=enforcing`. Then reboot the machine for the change to take affect.
23+
24+
To validate that SELinux is enabled run the following command:
25+
```
26+
sestatus
27+
```
28+
The output should look something like this:
29+
```
30+
SELinux status: enabled
31+
SELinuxfs mount: /sys/fs/selinux
32+
SELinux root directory: /etc/selinux
33+
Loaded policy name: targeted
34+
Current mode: enforcing
35+
Mode from config file: enforcing
36+
Policy MLS status: enabled
37+
Policy deny_unknown status: allowed
38+
Max kernel policy version: 31
39+
```
40+
41+
42+
## Install NGINX Agent Policy
43+
To install the nginx-agent policy run the following commands:
44+
```
45+
sudo semodule -n -i /usr/share/selinux/packages/nginx_agent.pp
46+
sudo /usr/sbin/load_policy
47+
sudo restorecon -R /usr/bin/nginx-agent
48+
sudo restorecon -R /var/log/nginx-agent
49+
sudo restorecon -R /etc/nginx-agent
50+
```
51+
52+
## Updating existing policy
53+
Check for errors by using the `ausearch` command:
54+
```
55+
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR --raw -se nginx_agent -ts recent
56+
```
57+
Generate new rule based on the errors by using `audit2allow`:
58+
```
59+
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR --raw -se nginx_agent -ts recent | audit2allow
60+
```
61+
62+
Update the `scripts/selinux/nginx_agent.te` file with the output from the `audit2allow` command.
63+
64+
Copy the `scripts/selinux/nginx_agent.te` file to a RHEL 8 machine and build a new `nginx_agent.pp` file by running the following command:
65+
```
66+
make -f /usr/share/selinux/devel/Makefile nginx_agent.pp
67+
```
68+
**[NOTE: The policy has to be built on a RHEL 8 machine. If it is built on a different OS like RHEL 8/9 then we will encounter this issue [Policy version does not match](#policy-version-does-not-match) when installing it on an older OS like RHEL 8. Even if the `audit2allow` command was run on a RHEL 8/9 machine the updates to the policy need to be made on a RHEL 8 machine.]**
69+
70+
Install the policy by following the steps here [Install NGINX Agent Policy](#install-nginx-agent-policy)
71+
72+
Then create a PR with the changes made to the `nginx_agent.te` and `nginx_agent.pp` files.
73+
74+
## Troubleshooting
75+
### Updated Policy Not Working
76+
77+
If after installing an updated policy the following command
78+
```
79+
ps -efZ | grep nginx-agent
80+
```
81+
shows nginx-agent is unconfined `system_u:system_r:unconfined_service_t`
82+
83+
On a RHEL 8 machine run the following command to generate a new policy
84+
```
85+
sepolicy generate --init /usr/bin/nginx-agent
86+
```
87+
88+
Replace the `nginx_agent.te` file on the RHEL 8 machine with the `scripts/selinux/nginx_agent.te` file
89+
90+
Run the following command on the RHEL 8 machine to build the new policy
91+
```
92+
sudo ./nginx_agent.sh
93+
```
94+
95+
Make a PR with the changes to `nginx_agent.fc` `nginx_agent.if` `nginx_agent.pp` and `nginx_agent.te`
96+
97+
**[NOTE: If you need to make additional changes to the policy, you will need to delete the generated files on the RHEL 8 machine and repeat all the steps above again]**
98+
99+
### Policy version does not match
100+
If running the command
101+
```
102+
sudo semodule -n -i /usr/share/selinux/packages/nginx_agent.pp
103+
```
104+
results in the following error
105+
```
106+
libsemanage.semanage_pipe_data: Child process /usr/libexec/selinux/hll/pp failed with code: 255. (No such file or directory).
107+
nginx_agent: libsepol.policydb_read: policydb module version 21 does not match my version range 4-19
108+
nginx_agent: libsepol.sepol_module_package_read: invalid module in module package (at section 0)
109+
nginx_agent: Failed to read policy package
110+
libsemanage.semanage_direct_commit: Failed to compile hll files into cil files.
111+
(No such file or directory).
112+
semodule: Failed!
113+
```
114+
this usually means that the policy file was built on a newer environment than isn't complicate with the environment the policy is being installed on.
115+
116+
To resolve this issue the policy file needs to be rebuilt on a RHEL 8 environment. See [Updating existing policy](#updating-existing-policy) for instruction on how to rebuild a policy file.
117+
118+
### Unknown Type
119+
If running the command
120+
```
121+
sudo semodule -n -i /usr/share/selinux/packages/nginx_agent.pp
122+
```
123+
results in the following error
124+
```
125+
/usr/bin/checkmodule: loading policy configuration from tmp/nginx_agent.tmp
126+
nginx_agent.te:52:ERROR 'unknown type bin_t' at token ';' on line 4301:
127+
```
128+
that means that the type is unknown and needs to be added to the require block in the `nginx_agent.te` file like this:
129+
```
130+
require {
131+
bin_t
132+
}
133+
```
134+
135+
## Debugging
136+
* To check for policy violation look at the file `/var/log/audit/audit.log`
137+
* To check if NGINX Agent is confined by selinux: `ps -efZ | grep nginx-agent`
138+
* For debugging nginx selinux issues refer to this nginx blog: https://www.nginx.com/blog/using-nginx-plus-with-selinux
139+
140+
## References
141+
* https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/writing-a-custom-selinux-policy_using-selinux

scripts/selinux/nginx_agent.fc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/usr/bin/nginx-agent -- gen_context(system_u:object_r:nginx_agent_exec_t,s0)

scripts/selinux/nginx_agent.if

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
## <summary>policy for nginx_agent</summary>
3+
4+
########################################
5+
## <summary>
6+
## Execute nginx_agent_exec_t in the nginx_agent domain.
7+
## </summary>
8+
## <param name="domain">
9+
## <summary>
10+
## Domain allowed to transition.
11+
## </summary>
12+
## </param>
13+
#
14+
interface(`nginx_agent_domtrans',`
15+
gen_require(`
16+
type nginx_agent_t, nginx_agent_exec_t;
17+
')
18+
19+
corecmd_search_bin($1)
20+
domtrans_pattern($1, nginx_agent_exec_t, nginx_agent_t)
21+
')
22+
23+
######################################
24+
## <summary>
25+
## Execute nginx_agent in the caller domain.
26+
## </summary>
27+
## <param name="domain">
28+
## <summary>
29+
## Domain allowed access.
30+
## </summary>
31+
## </param>
32+
#
33+
interface(`nginx_agent_exec',`
34+
gen_require(`
35+
type nginx_agent_exec_t;
36+
')
37+
38+
corecmd_search_bin($1)
39+
can_exec($1, nginx_agent_exec_t)
40+
')

scripts/selinux/nginx_agent.pp

98.4 KB
Binary file not shown.

scripts/selinux/nginx_agent.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/bin/sh -e
2+
3+
DIRNAME=`dirname $0`
4+
cd $DIRNAME
5+
USAGE="$0 [ --update ]"
6+
if [ `id -u` != 0 ]; then
7+
echo 'You must be root to run this script'
8+
exit 1
9+
fi
10+
11+
if [ $# -eq 1 ]; then
12+
if [ "$1" = "--update" ] ; then
13+
time=`ls -l --time-style="+%x %X" nginx_agent.te | awk '{ printf "%s %s", $6, $7 }'`
14+
rules=`ausearch --start $time -m avc --raw -se nginx_agent`
15+
if [ x"$rules" != "x" ] ; then
16+
echo "Found avc's to update policy with"
17+
echo -e "$rules" | audit2allow -R
18+
echo "Do you want these changes added to policy [y/n]?"
19+
read ANS
20+
if [ "$ANS" = "y" -o "$ANS" = "Y" ] ; then
21+
echo "Updating policy"
22+
echo -e "$rules" | audit2allow -R >> nginx_agent.te
23+
# Fall though and rebuild policy
24+
else
25+
exit 0
26+
fi
27+
else
28+
echo "No new avcs found"
29+
exit 0
30+
fi
31+
else
32+
echo -e $USAGE
33+
exit 1
34+
fi
35+
elif [ $# -ge 2 ] ; then
36+
echo -e $USAGE
37+
exit 1
38+
fi
39+
40+
echo "Building and Loading Policy"
41+
set -x
42+
make -f /usr/share/selinux/devel/Makefile nginx_agent.pp || exit
43+
/usr/sbin/semodule -i nginx_agent.pp
44+
45+
# Generate a man page off the installed module
46+
sepolicy manpage -p . -d nginx_agent_t
47+
# Fixing the file context on /usr/bin/nginx-agent
48+
/sbin/restorecon -F -R -v /usr/bin/nginx-agent

0 commit comments

Comments
 (0)