Difference between revisions of "Gitea Setup on Rocky10 with SELinux"
Jump to navigation
Jump to search
(Created page with " =Setup Host= * OS: Rocky Linux 10 minimal * FQDN: gitea01.domain.tld <pre> HOST=$(hostname -f) genpasswd() { local l=$1 [ "$l" == "" ] && l=20 tr -dc A-Za-z...") |
|||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | =Setup= | |
− | =Setup | ||
* OS: Rocky Linux 10 minimal | * OS: Rocky Linux 10 minimal | ||
* FQDN: gitea01.domain.tld | * FQDN: gitea01.domain.tld | ||
+ | |||
+ | ==Disable SELinux== | ||
+ | For now, we set selinux to permissive, once all rules are set and we have no violations anymore, we set to enforce again | ||
<pre> | <pre> | ||
+ | setenforce 0 | ||
+ | sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config | ||
+ | </pre> | ||
+ | ==VARS and Functions== | ||
+ | <pre> | ||
HOST=$(hostname -f) | HOST=$(hostname -f) | ||
− | + | ||
+ | genpasswd() { | ||
local l=$1 | local l=$1 | ||
[ "$l" == "" ] && l=20 | [ "$l" == "" ] && l=20 | ||
tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs | tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs | ||
− | + | } | |
+ | </pre> | ||
+ | |||
+ | ==Install software== | ||
+ | install reverse proxy and base software | ||
+ | dnf -y install openssl wget nginx git policycoreutils-python-utils | ||
+ | |||
+ | |||
+ | ==Move system sshd port to 222== | ||
+ | semanage port -a -t ssh_port_t -p tcp 222 | ||
+ | sed -i 's/^#Port 22/Port 222/' /etc/ssh/sshd_config | ||
+ | systemctl restart sshd | ||
+ | |||
+ | ==Configure Firewall== | ||
+ | |||
+ | * open https | ||
+ | firewall-cmd --permanent --add-port=443/tcp | ||
+ | * open new sshd port | ||
+ | firewall-cmd --permanent --add-port=222/tcp | ||
− | + | * forward port 22 to gitea | |
− | + | firewall-cmd --permanent --add-forward-port=port=22:proto=tcp:toport=2222 | |
− | + | * load new rules | |
− | + | firewall-cmd --reload | |
− | |||
− | + | ==Install/Configure Mariadb== | |
− | + | * install and enable | |
− | + | dnf install -y mariadb-server | |
− | + | systemctl enable --now mariadb | |
− | |||
− | |||
− | systemctl | ||
− | |||
− | + | * secure mariadb | |
− | + | mysql_secure_installation | |
− | mysql_secure_installation | ||
+ | * create gitea database user | ||
+ | <pre> | ||
MARIADB_PW=$(genpasswd) | MARIADB_PW=$(genpasswd) | ||
echo MARIADB_PW=$MARIADB_PW | echo MARIADB_PW=$MARIADB_PW | ||
Line 40: | Line 62: | ||
FLUSH PRIVILEGES; | FLUSH PRIVILEGES; | ||
EOF | EOF | ||
+ | </pre> | ||
− | + | ==Install Gitea== | |
+ | * create gitea user | ||
+ | <pre> | ||
useradd --system --shell /usr/bin/false --comment 'Git Version Control' --create-home --home-dir /var/lib/gitea git | useradd --system --shell /usr/bin/false --comment 'Git Version Control' --create-home --home-dir /var/lib/gitea git | ||
mkdir -p /var/lib/gitea/data | mkdir -p /var/lib/gitea/data | ||
Line 48: | Line 73: | ||
chown root:git /etc/gitea | chown root:git /etc/gitea | ||
chmod 770 /etc/gitea | chmod 770 /etc/gitea | ||
+ | </pre> | ||
+ | * Install gitea | ||
+ | <pre> | ||
GITEA_VERSION=1.23.8 | GITEA_VERSION=1.23.8 | ||
wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/$GITEA_VERSION/gitea-$GITEA_VERSION-linux-amd64 | wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/$GITEA_VERSION/gitea-$GITEA_VERSION-linux-amd64 | ||
chown root:git /usr/local/bin/gitea | chown root:git /usr/local/bin/gitea | ||
chmod 750 /usr/local/bin/gitea | chmod 750 /usr/local/bin/gitea | ||
+ | </pre> | ||
+ | * create systemd service | ||
+ | <pre> | ||
cat <<EOF >/etc/systemd/system/gitea.service | cat <<EOF >/etc/systemd/system/gitea.service | ||
[Unit] | [Unit] | ||
Line 74: | Line 105: | ||
WantedBy=multi-user.target | WantedBy=multi-user.target | ||
EOF | EOF | ||
+ | </pre> | ||
+ | * create gitea config | ||
+ | <pre> | ||
cat <<EOF >/etc/gitea/app.ini | cat <<EOF >/etc/gitea/app.ini | ||
WORK_PATH = /var/lib/gitea/ | WORK_PATH = /var/lib/gitea/ | ||
Line 111: | Line 145: | ||
[oauth2] | [oauth2] | ||
JWT_SECRET = $(genpasswd 32) | JWT_SECRET = $(genpasswd 32) | ||
+ | EOF | ||
+ | </pre> | ||
+ | chown root:git /etc/gitea/app.ini | ||
+ | chmod 660 /etc/gitea/app.ini | ||
− | + | systemctl daemon-reload | |
+ | systemctl enable --now gitea | ||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | ==nginx configuration== | ||
+ | <pre> | ||
openssl req -x509 -newkey rsa:4096 -nodes \ | openssl req -x509 -newkey rsa:4096 -nodes \ | ||
-keyout /etc/pki/tls/private/gitea.key \ | -keyout /etc/pki/tls/private/gitea.key \ | ||
-out /etc/pki/tls/certs/gitea.crt \ | -out /etc/pki/tls/certs/gitea.crt \ | ||
-days 3650 -subj "/CN=$HOST" | -days 3650 -subj "/CN=$HOST" | ||
+ | </pre> | ||
− | chown root:root /etc/pki/tls/private/gitea.key | + | chown root:root /etc/pki/tls/private/gitea.key |
− | chmod 600 /etc/pki/tls/private/gitea.key | + | chmod 600 /etc/pki/tls/private/gitea.key |
− | openssl dhparam -out /etc/nginx/dhparam.pem 4096 | + | openssl dhparam -out /etc/nginx/dhparam.pem 4096 |
+ | <pre> | ||
cat <<EOF >/etc/nginx/conf.d/gitea.conf | cat <<EOF >/etc/nginx/conf.d/gitea.conf | ||
server { | server { | ||
Line 158: | Line 196: | ||
} | } | ||
EOF | EOF | ||
+ | </pre> | ||
− | systemctl enable --now nginx | + | systemctl enable --now nginx |
− | + | ==create gitea application admin== | |
− | su -s /bin/bash git | + | Change to git user, which has no sell as default |
+ | su -s /bin/bash git | ||
+ | <pre> | ||
genpasswd() { | genpasswd() { | ||
local l=$1 | local l=$1 | ||
Line 177: | Line 218: | ||
gitea admin user create --admin --username $ADMIN_USER --password "$ADMIN_PW" --email admin@domain.tld --config /etc/gitea/app.ini | gitea admin user create --admin --username $ADMIN_USER --password "$ADMIN_PW" --email admin@domain.tld --config /etc/gitea/app.ini | ||
exit | exit | ||
+ | </pre> | ||
− | + | =SELinux configuration= | |
− | + | ==Install selinux tools as root== | |
− | |||
− | |||
− | |||
+ | dnf install -y policycoreutils-devel checkpolicy setroubleshoot-server setools-console | ||
+ | > /var/log/audit/audit.log | ||
+ | touch /.autorelabel | ||
+ | reboot | ||
+ | ssh -lroot $HOST -p222 | ||
+ | mkdir -p /root/selinux/gitea | ||
+ | cd /root/selinux/gitea | ||
− | + | [[Category:Linux]] | |
− | + | [[Category:SELinux]] | |
+ | [[Category:Security]] | ||
− | ---------- | + | ==Generate policy default ruleset== |
+ | for r in appstream baseos extras ; do dnf config-manager --set-disabled $r; done | ||
+ | sepolicy generate --init /usr/local/bin/gitea | ||
+ | for r in appstream baseos extras ; do dnf config-manager --set-enabled $r; done | ||
− | + | ==Modify ruleset defaults== | |
− | + | Rename gitea_var_lib_t | |
+ | grep gitea_var_lib_t gitea* | ||
+ | sed -i 's/gitea_var_lib_t/gitea_data_t/g' gitea* | ||
− | + | * Hide permissive setting, we want to use it in enforcing mode | |
− | + | sed -i 's/^permissive/#permissive/' gitea.te | |
− | |||
+ | * Add file context rule | ||
+ | echo '/etc/gitea(/.*)? gen_context(system_u:object_r:gitea_conf_t,s0)' >> gitea.fc | ||
− | + | * <tt>vim gitea.te</tt> | |
− | + | <pre> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
# add in declaration | # add in declaration | ||
type gitea_conf_t; | type gitea_conf_t; | ||
Line 217: | Line 260: | ||
type gitea_port_t; | type gitea_port_t; | ||
corenet_port(gitea_port_t) | corenet_port(gitea_port_t) | ||
− | + | </pre> | |
− | + | * disable rpm building cmd | |
− | sed -i 's/^rpmbuild/#rpmbuild/' gitea.sh | + | sed -i 's/^rpmbuild/#rpmbuild/' gitea.sh |
− | bash gitea.sh | + | * build and load new rules |
+ | bash gitea.sh | ||
− | + | [[Category:Linux]] | |
− | + | [[Category:SELinux]] | |
+ | [[Category:Security]] | ||
− | + | ==Apply new context lables== | |
+ | * Label ports | ||
+ | semanage port -a -t gitea_port_t -p tcp 2222 | ||
+ | semanage port -a -t gitea_port_t -p tcp 3000 | ||
− | + | * Restart gitea | |
− | + | systemctl restart gitea | |
+ | * Verify domain | ||
+ | <pre> | ||
+ | ps -ef -Z | grep gitea | ||
+ | system_u:system_r:gitea_t:s0 git 1714 1 10 07:41 ? 00:00:01 /usr/local/bin/gitea web --config /etc/gitea/app.ini | ||
+ | </pre> | ||
− | + | * verify port lables | |
− | gitea_port_t tcp 2222, 3000 | + | <pre> |
+ | semanage port --list | grep gitea | ||
+ | gitea_port_t tcp 2222, 3000 | ||
+ | </pre> | ||
− | + | * verify file lables | |
− | -rw-rw----. 1 root git system_u:object_r:gitea_conf_t:s0 681 Jul 11 07:23 /etc/gitea/app.ini | + | <pre> |
− | + | ls -lZ /etc/gitea/app.ini /var/lib/gitea/data/ | |
− | + | -rw-rw----. 1 root git system_u:object_r:gitea_conf_t:s0 681 Jul 11 07:23 /etc/gitea/app.ini | |
− | |||
− | |||
− | + | /var/lib/gitea/data/: | |
− | + | drwxr-xr-x. 2 git git system_u:object_r:gitea_data_t:s0 6 Jul 11 07:23 actions_artifacts | |
− | + | [...] | |
− | + | </pre> | |
− | [ | + | [[Category:Linux]] |
− | + | [[Category:SELinux]] | |
+ | [[Category:Security]] | ||
+ | ==Define additional SELinux rules== | ||
+ | * Reset alerts and verify alerts | ||
+ | > /var/log/audit/audit.log | ||
+ | systemctl restart gitea | ||
− | + | * Now test the application with all its functions | |
+ | * verify new alerts | ||
+ | sealert -a /var/log/audit/audit.log | ||
+ | grep 'run: sealert' /var/log/messages | ||
+ | ausearch --raw | audit2allow | ||
− | + | * Review, understand and then add this to gitea.te, gitea.fc, gitea.if | |
− | + | * Then rebuild/install policy with `bash gitea.sh` | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | * finally start over until you have no violations anymore | ||
> /var/log/audit/audit.log | > /var/log/audit/audit.log | ||
− | + | reboot | |
− | |||
sealert -a /var/log/audit/audit.log | sealert -a /var/log/audit/audit.log | ||
grep 'run: sealert' /var/log/messages | grep 'run: sealert' /var/log/messages | ||
Line 280: | Line 330: | ||
− | + | =ReEnable SELinux= | |
− | + | Now we switch back to enforcing and test again | |
− | + | setenforce 1 | |
− | + | sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config | |
− | + | grubby --update-kernel ALL --remove-args selinux | |
− | + | touch /.autorelabel | |
− | + | reboot | |
− | + | sealert -a /var/log/audit/audit.log | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | setenforce 1 | ||
− | sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config | ||
− | grubby --update-kernel ALL --remove-args selinux | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | reboot | ||
− | sealert -a /var/log/audit/audit.log | ||
+ | ==Test if rules are working as expected== | ||
+ | chcon -t home_root_t /etc/gitea/app.ini | ||
+ | > /var/log/audit/audit.log | ||
+ | reboot | ||
+ | sealert -a /var/log/audit/audit.log | ||
+ | restorecon -FRv /etc/gitea/ | ||
+ | > /var/log/audit/audit.log | ||
+ | reboot | ||
+ | sealert -a /var/log/audit/audit.log | ||
+ | <pre> | ||
semanage port -a -t ssh_port_t -p tcp 2222 | semanage port -a -t ssh_port_t -p tcp 2222 | ||
semanage port -a -t ssh_port_t -p tcp 3000 | semanage port -a -t ssh_port_t -p tcp 3000 | ||
Line 329: | Line 359: | ||
semanage port -a -t gitea_port_t -p tcp 3000 | semanage port -a -t gitea_port_t -p tcp 3000 | ||
semanage port -l | grep gitea_ | semanage port -l | grep gitea_ | ||
− | + | gitea_port_t tcp 2222, 3000 | |
> /var/log/audit/audit.log | > /var/log/audit/audit.log | ||
reboot | reboot | ||
sealert -a /var/log/audit/audit.log | sealert -a /var/log/audit/audit.log | ||
ss -tan # port 2222 and 3000 are NOW listening! | ss -tan # port 2222 and 3000 are NOW listening! | ||
+ | </pre> | ||
− | + | [[Category:Linux]] | |
+ | [[Category:SELinux]] | ||
+ | [[Category:Security]] | ||
+ | |||
+ | =Appendix= | ||
+ | ==Final policy files== | ||
</pre> | </pre> | ||
<div class="toccolours mw-collapsible mw-collapsed" style="width:60%"> | <div class="toccolours mw-collapsible mw-collapsed" style="width:60%"> | ||
Line 561: | Line 597: | ||
# Allow Gitea to read system network configuration | # Allow Gitea to read system network configuration | ||
sysnet_read_config(gitea_t); | sysnet_read_config(gitea_t); | ||
− | |||
− | |||
</pre> | </pre> | ||
</div> | </div> | ||
</div> | </div> | ||
− | + | ||
− | + | ==Boolean Analysis: domain_can_mmap_files== | |
− | + | * Lets see what domain_can_mmap_files contains | |
<pre> | <pre> | ||
− | + | getsebool -a | grep domain_can_mmap_files | |
− | + | domain_can_mmap_files --> off | |
− | + | ||
− | + | ||
− | + | semanage boolean -l | grep domain_can_mmap_files | |
− | + | domain_can_mmap_files (off , off) Allow any process to mmap any file on system with attribute file_type. | |
+ | |||
+ | sesearch -b domain_can_mmap_files -A | ||
+ | allow domain file_type:blk_file map; [ domain_can_mmap_files ]:True | ||
+ | allow domain file_type:chr_file map; [ domain_can_mmap_files ]:True | ||
+ | allow domain file_type:file map; [ domain_can_mmap_files ]:True | ||
+ | allow domain file_type:lnk_file map; [ domain_can_mmap_files ]:True | ||
</pre> | </pre> | ||
− | |||
− | |||
[[Category:Linux]] | [[Category:Linux]] | ||
+ | [[Category:SELinux]] | ||
[[Category:Security]] | [[Category:Security]] | ||
− |
Latest revision as of 13:12, 12 July 2025
1 Setup
- OS: Rocky Linux 10 minimal
- FQDN: gitea01.domain.tld
1.1 Disable SELinux
For now, we set selinux to permissive, once all rules are set and we have no violations anymore, we set to enforce again
setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
1.2 VARS and Functions
HOST=$(hostname -f) genpasswd() { local l=$1 [ "$l" == "" ] && l=20 tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs }
1.3 Install software
install reverse proxy and base software
dnf -y install openssl wget nginx git policycoreutils-python-utils
1.4 Move system sshd port to 222
semanage port -a -t ssh_port_t -p tcp 222 sed -i 's/^#Port 22/Port 222/' /etc/ssh/sshd_config systemctl restart sshd
1.5 Configure Firewall
- open https
firewall-cmd --permanent --add-port=443/tcp
- open new sshd port
firewall-cmd --permanent --add-port=222/tcp
- forward port 22 to gitea
firewall-cmd --permanent --add-forward-port=port=22:proto=tcp:toport=2222
- load new rules
firewall-cmd --reload
1.6 Install/Configure Mariadb
- install and enable
dnf install -y mariadb-server systemctl enable --now mariadb
- secure mariadb
mysql_secure_installation
- create gitea database user
MARIADB_PW=$(genpasswd) echo MARIADB_PW=$MARIADB_PW mysql -u root -p <<EOF CREATE DATABASE gitea CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'; CREATE USER 'gitea'@'localhost' IDENTIFIED BY '$MARIADB_PW'; GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'localhost'; FLUSH PRIVILEGES; EOF
1.7 Install Gitea
- create gitea user
useradd --system --shell /usr/bin/false --comment 'Git Version Control' --create-home --home-dir /var/lib/gitea git mkdir -p /var/lib/gitea/data mkdir -p /etc/gitea chown -R git:git /var/lib/gitea chown root:git /etc/gitea chmod 770 /etc/gitea
- Install gitea
GITEA_VERSION=1.23.8 wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/$GITEA_VERSION/gitea-$GITEA_VERSION-linux-amd64 chown root:git /usr/local/bin/gitea chmod 750 /usr/local/bin/gitea
- create systemd service
cat <<EOF >/etc/systemd/system/gitea.service [Unit] Description=Gitea (Git with a cup of tea) After=syslog.target After=network.target Requires=mariadb.service [Service] RestartSec=2s Type=simple User=git Group=git WorkingDirectory=/var/lib/gitea/ ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini Restart=always Environment=USER=git HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea [Install] WantedBy=multi-user.target EOF
- create gitea config
cat <<EOF >/etc/gitea/app.ini WORK_PATH = /var/lib/gitea/ [server] APP_NAME = Gitea: Git with a cup of tea RUN_USER = git RUN_MODE = prod HTTP_PORT = 3000 ROOT_URL = https://$HOST SSH_DOMAIN = $HOST START_SSH_SERVER = true SSH_PORT = 22 SSH_LISTEN_PORT = 2222 OFFLINE_MODE = false [database] DB_TYPE = mysql HOST = 127.0.0.1:3306 NAME = gitea USER = gitea PASSWD = $MARIADB_PW SSL_MODE = disable [security] INSTALL_LOCK = true SECRET_KEY = $(genpasswd 32) INTERNAL_TOKEN = $(genpasswd 32) [lfs] PATH = /var/lib/gitea/data/lfs [service] DISABLE_REGISTRATION = true [oauth2] JWT_SECRET = $(genpasswd 32) EOF
chown root:git /etc/gitea/app.ini chmod 660 /etc/gitea/app.ini
systemctl daemon-reload systemctl enable --now gitea
1.8 nginx configuration
openssl req -x509 -newkey rsa:4096 -nodes \ -keyout /etc/pki/tls/private/gitea.key \ -out /etc/pki/tls/certs/gitea.crt \ -days 3650 -subj "/CN=$HOST"
chown root:root /etc/pki/tls/private/gitea.key chmod 600 /etc/pki/tls/private/gitea.key
openssl dhparam -out /etc/nginx/dhparam.pem 4096
cat <<EOF >/etc/nginx/conf.d/gitea.conf server { listen 443 ssl; server_name $HOST; ssl_certificate /etc/pki/tls/certs/gitea.crt; ssl_certificate_key /etc/pki/tls/private/gitea.key; ssl_dhparam /etc/nginx/dhparam.pem; ssl_protocols TLSv1.2; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; ssl_stapling on; ssl_stapling_verify on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; } } EOF
systemctl enable --now nginx
1.9 create gitea application admin
Change to git user, which has no sell as default
su -s /bin/bash git
genpasswd() { local l=$1 [ "$l" == "" ] && l=20 tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs } ADMIN_USER=$(genpasswd 8) ADMIN_PW=$(genpasswd) echo ADMIN_USER=$ADMIN_USER echo ADMIN_PW=$ADMIN_PW gitea admin user create --admin --username $ADMIN_USER --password "$ADMIN_PW" --email admin@domain.tld --config /etc/gitea/app.ini exit
2 SELinux configuration
2.1 Install selinux tools as root
dnf install -y policycoreutils-devel checkpolicy setroubleshoot-server setools-console > /var/log/audit/audit.log touch /.autorelabel reboot ssh -lroot $HOST -p222
mkdir -p /root/selinux/gitea cd /root/selinux/gitea
2.2 Generate policy default ruleset
for r in appstream baseos extras ; do dnf config-manager --set-disabled $r; done sepolicy generate --init /usr/local/bin/gitea for r in appstream baseos extras ; do dnf config-manager --set-enabled $r; done
2.3 Modify ruleset defaults
Rename gitea_var_lib_t
grep gitea_var_lib_t gitea* sed -i 's/gitea_var_lib_t/gitea_data_t/g' gitea*
- Hide permissive setting, we want to use it in enforcing mode
sed -i 's/^permissive/#permissive/' gitea.te
- Add file context rule
echo '/etc/gitea(/.*)? gen_context(system_u:object_r:gitea_conf_t,s0)' >> gitea.fc
- vim gitea.te
# add in declaration type gitea_conf_t; files_type(gitea_conf_t) type gitea_port_t; corenet_port(gitea_port_t)
- disable rpm building cmd
sed -i 's/^rpmbuild/#rpmbuild/' gitea.sh
- build and load new rules
bash gitea.sh
2.4 Apply new context lables
- Label ports
semanage port -a -t gitea_port_t -p tcp 2222 semanage port -a -t gitea_port_t -p tcp 3000
- Restart gitea
systemctl restart gitea
- Verify domain
ps -ef -Z | grep gitea system_u:system_r:gitea_t:s0 git 1714 1 10 07:41 ? 00:00:01 /usr/local/bin/gitea web --config /etc/gitea/app.ini
- verify port lables
semanage port --list | grep gitea gitea_port_t tcp 2222, 3000
- verify file lables
ls -lZ /etc/gitea/app.ini /var/lib/gitea/data/ -rw-rw----. 1 root git system_u:object_r:gitea_conf_t:s0 681 Jul 11 07:23 /etc/gitea/app.ini /var/lib/gitea/data/: drwxr-xr-x. 2 git git system_u:object_r:gitea_data_t:s0 6 Jul 11 07:23 actions_artifacts [...]
2.5 Define additional SELinux rules
- Reset alerts and verify alerts
> /var/log/audit/audit.log systemctl restart gitea
- Now test the application with all its functions
- verify new alerts
sealert -a /var/log/audit/audit.log grep 'run: sealert' /var/log/messages ausearch --raw | audit2allow
- Review, understand and then add this to gitea.te, gitea.fc, gitea.if
- Then rebuild/install policy with `bash gitea.sh`
- finally start over until you have no violations anymore
> /var/log/audit/audit.log reboot sealert -a /var/log/audit/audit.log grep 'run: sealert' /var/log/messages ausearch --raw | audit2allow ausearch -c 'git' --raw | audit2allow -R
3 ReEnable SELinux
Now we switch back to enforcing and test again
setenforce 1 sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config grubby --update-kernel ALL --remove-args selinux touch /.autorelabel reboot sealert -a /var/log/audit/audit.log
3.1 Test if rules are working as expected
chcon -t home_root_t /etc/gitea/app.ini > /var/log/audit/audit.log reboot sealert -a /var/log/audit/audit.log restorecon -FRv /etc/gitea/ > /var/log/audit/audit.log reboot sealert -a /var/log/audit/audit.log
semanage port -a -t ssh_port_t -p tcp 2222 semanage port -a -t ssh_port_t -p tcp 3000 > /var/log/audit/audit.log reboot sealert -a /var/log/audit/audit.log ss -tan # port 2222 and 3000 are not listening! semanage port -a -t gitea_port_t -p tcp 2222 semanage port -a -t gitea_port_t -p tcp 3000 semanage port -l | grep gitea_ gitea_port_t tcp 2222, 3000 > /var/log/audit/audit.log reboot sealert -a /var/log/audit/audit.log ss -tan # port 2222 and 3000 are NOW listening!
4 Appendix
4.1 Final policy files
File: gitea.fc Modified: 2025-07-12 12:41:42
# Set the security context for the Gitea executable /usr/local/bin/gitea -- gen_context(system_u:object_r:gitea_exec_t,s0) # Set the security context for Gitea data directories /var/lib/gitea(/.*)? gen_context(system_u:object_r:gitea_data_t,s0) # Set the security context for Gitea configuration files /etc/gitea(/.*)? gen_context(system_u:object_r:gitea_conf_t,s0)
File: gitea.if Modified: 2025-07-12 12:43:07
# Interface to allow domain transition to gitea_t when executing gitea_exec_t interface(`gitea_domtrans',` gen_require(` type gitea_t, gitea_exec_t; ') corecmd_search_bin($1) domtrans_pattern($1, gitea_exec_t, gitea_t) ') # Interface to allow execution of gitea_exec_t in the caller's domain interface(`gitea_exec',` gen_require(` type gitea_exec_t; ') corecmd_search_bin($1) can_exec($1, gitea_exec_t) ') # Interface to allow searching of Gitea library directories interface(`gitea_search_lib',` gen_require(` type gitea_data_t; ') allow $1 gitea_data_t:dir search_dir_perms; files_search_var_lib($1) ') # Interface to allow reading of Gitea library files interface(`gitea_read_lib_files',` gen_require(` type gitea_data_t; ') files_search_var_lib($1) read_files_pattern($1, gitea_data_t, gitea_data_t) ') # Interface to allow management of Gitea library files interface(`gitea_manage_lib_files',` gen_require(` type gitea_data_t; ') files_search_var_lib($1) manage_files_pattern($1, gitea_data_t, gitea_data_t) ') # Interface to allow management of Gitea library directories interface(`gitea_manage_lib_dirs',` gen_require(` type gitea_data_t; ') files_search_var_lib($1) manage_dirs_pattern($1, gitea_data_t, gitea_data_t) ') # Interface to allow administration of a Gitea environment interface(`gitea_admin',` gen_require(` type gitea_t; type gitea_data_t; ') allow $1 gitea_t:process { signal_perms }; ps_process_pattern($1, gitea_t) tunable_policy(`deny_ptrace',`',` allow $1 gitea_t:process ptrace; ') files_search_var_lib($1) admin_pattern($1, gitea_data_t) optional_policy(` systemd_passwd_agent_exec($1) systemd_read_fifo_file_passwd_run($1) ') ')
File: gitea.te Modified: 2025-07-12 12:44:36
# Define the Gitea SELinux policy module version policy_module(gitea, 1.0.0) ######################################## # Required types and classes for Gitea SELinux policy require { type gitea_t; type gitea_data_t; type gitea_port_t; type gitea_conf_t; class dir search; class process setpgid; class file { getattr map open read execute execute_no_trans}; class tcp_socket { accept bind listen name_bind name_connect connect create getattr getopt setopt read write}; class udp_socket { connect create getattr setopt }; type tmp_t; type httpd_t; } type gitea_t; type gitea_exec_t; # Initialize the Gitea daemon domain init_daemon_domain(gitea_t, gitea_exec_t) # permissive gitea_t; type gitea_data_t; files_type(gitea_data_t) type gitea_conf_t; files_type(gitea_conf_t) type gitea_port_t; corenet_port(gitea_port_t) ######################################## # gitea policy definitions ############# # Allow Gitea to read and write to its own FIFO files allow gitea_t self:fifo_file rw_fifo_file_perms; # Allow Gitea to create and use Unix stream sockets allow gitea_t self:unix_stream_socket create_stream_socket_perms; # Allow Gitea to search its configuration directory allow gitea_t gitea_conf_t:dir search; # Allow Gitea to get attributes, open, and read its configuration files allow gitea_t gitea_conf_t:file { getattr open read }; # Allow HTTPD to connect to Gitea's TCP socket allow httpd_t gitea_port_t:tcp_socket name_connect; # Allow Gitea to manage its data directories manage_dirs_pattern(gitea_t, gitea_data_t, gitea_data_t) # Allow Gitea to manage its data files manage_files_pattern(gitea_t, gitea_data_t, gitea_data_t) # Allow Gitea to manage its symbolic link files manage_lnk_files_pattern(gitea_t, gitea_data_t, gitea_data_t) # Allow file transitions for Gitea in /var/lib files_var_lib_filetrans(gitea_t, gitea_data_t, { dir file lnk_file }) # Allow Gitea to use interactive file descriptors domain_use_interactive_fds(gitea_t) # Allow Gitea to read files in /etc files_read_etc_files(gitea_t) # Allow Gitea to read localization files miscfiles_read_localization(gitea_t) # Define file transition patterns for Gitea filetrans_pattern(gitea_t, gitea_data_t, gitea_data_t, file); filetrans_pattern(gitea_t, gitea_data_t, gitea_data_t, dir); filetrans_pattern(gitea_t, tmp_t, gitea_data_t, { file dir }); # Allow Gitea to map its data files allow gitea_t gitea_data_t:file map; # Allow Gitea to bind to its TCP socket allow gitea_t gitea_port_t:tcp_socket name_bind; # Allow Gitea to set process group ID allow gitea_t self:process setpgid; # Allow Gitea to perform operations on its TCP socket allow gitea_t self:tcp_socket { accept bind listen read write}; # Allow Gitea to read the password file auth_read_passwd_file(gitea_t) # Allow Gitea to execute shell commands corecmd_check_exec_shell(gitea_t) # Allow Gitea to execute binaries corecmd_exec_bin(gitea_t) # Allow Gitea to bind to generic TCP nodes corenet_tcp_bind_generic_node(gitea_t) # Allow Gitea to read from sysfs dev_read_sysfs(gitea_t) # Allow Gitea to read network sysctl settings kernel_read_net_sysctls(gitea_t) # Allow Gitea to search network sysctl settings kernel_search_network_sysctl(gitea_t) # Allow Gitea to execute its own executable without transition allow gitea_t gitea_exec_t:file execute_no_trans; # Allow Gitea to execute its data files allow gitea_t gitea_data_t:file execute; # Allow Gitea to execute its data files without transition allow gitea_t gitea_data_t:file execute_no_trans; # Allow Gitea to connect to its TCP socket allow gitea_t gitea_port_t:tcp_socket name_connect; # Allow Gitea to perform various operations on its TCP socket allow gitea_t self:tcp_socket { connect create getattr getopt setopt }; # Allow Gitea to perform various operations on its UDP socket allow gitea_t self:udp_socket { connect create getattr setopt }; # Allow Gitea to connect to HTTP ports corenet_tcp_connect_http_port(gitea_t); # Allow Gitea to connect to MySQL ports corenet_tcp_connect_mysqld_port(gitea_t) # Allow Gitea to read generic certificates miscfiles_read_generic_certs(gitea_t); # Allow Gitea to read system network configuration sysnet_read_config(gitea_t);
4.2 Boolean Analysis: domain_can_mmap_files
- Lets see what domain_can_mmap_files contains
getsebool -a | grep domain_can_mmap_files domain_can_mmap_files --> off semanage boolean -l | grep domain_can_mmap_files domain_can_mmap_files (off , off) Allow any process to mmap any file on system with attribute file_type. sesearch -b domain_can_mmap_files -A allow domain file_type:blk_file map; [ domain_can_mmap_files ]:True allow domain file_type:chr_file map; [ domain_can_mmap_files ]:True allow domain file_type:file map; [ domain_can_mmap_files ]:True allow domain file_type:lnk_file map; [ domain_can_mmap_files ]:True