Разделение привилегий Apache vhost с использованием контекстов SELinux в CentOS8
У меня есть сервер, на котором будет несколько приложений, одно из которых является проприетарным кодом, а другое с возможностью проверки файлов на сервере из-за характера наших потребностей. Это не годится. Я пытаюсь добиться разделения привилегий для каждого виртуального хоста, чтобы один не мог проверить другой. Есть несколько смягчающих обстоятельств, которые усложнили это...
- CentOS8
- Необходимо использовать SELinux
- Apache 2.4.37, PHP73, FCGI, PHP_FPM... с использованием
mpm_event
- Нет
mod_permissions
,mod_itk/mpm_itk
,mod_selinux
модули из коробки на CentOS8
Поскольку в нашем случае необходимо включить SELinux, а также он обеспечивает наилучшую степень детализации для достижения наших целей, я пошел по этому пути. Чтобы его установить (из Fedora Core 31 src), я выполнил следующие шаги...
-
dnf install httpd-devel selinux-policy-devel
-
wget https://download.fedoraproject.org/pub/fedora/linux/releases/31/Everything/source/tree/Packages/m/mod_selinux-2.4.4-14.fc31.src.rpm
-
rpmbuild --rebuild mod_selinux-2.4.4-14.fc31.src.rpm --define "_rpmdir /tmp"
-
dnf install /tmp/x86_64/mod_selinux-2.4.4-14.el8.x86_64.rpm
Все прошло хорошо, без ошибок, и все было установлено там, где должно быть.
Я объединил наши общесерверные настройки в единый
httpd.conf
файл, а не использовать много разных файлов conf в
conf.d
(в основном это связано с простотой работы с доступными шаблонами и возможностью видеть все в одном месте). NB: это НЕ включает каждый из наших
vhost
conf файлы / объявления, которые все еще остаются отдельными и включаются индивидуально.
Объявление по умолчанию для контекстов httpd:...
selinuxServerDomain *:s0
У меня есть 4x vhosts, которые я хочу разделить, и я хочу оставить место для будущего расширения, поэтому я скорректировал это объявление на следующее и добавил его в свой
httpd.conf
файл...
selinuxServerDomain *:s0-s0:c0.c50
Затем я добавил следующее к каждому из моих
vhost
декларации соответственно...
selinuxDomainVal *:s0:c10
selinuxDomainVal *:s0:c20
selinuxDomainVal *:s0:c30
selinuxDomainVal *:s0:c40
Наконец, я изменил контекст корней документов на каждом из соответствующих сайтов vhost следующим образом...
chcon -R -l s0:c10 /var/www/site1
chcon -R -l s0:c20 /var/www/site2
chcon -R -l s0:c30 /var/www/site3
chcon -R -l s0:c40 /var/www/site4
До использования контекстных сайтов я уже успешно запускал сайты, используя стандартные контексты, связанные с httpd (unconfined_u:object_r:httpd_sys_content_t
,
system_u:object_r:httpd_sys_rw_content_t
), поэтому я оставил их как есть.
Итак, проблема в том, что используя оригинал
*:s0
контекст
systemctl start httpd
работает нормально, хотя ни один из
vhosts
доступны по той очевидной причине, что ни один из порожденных обработчиков не использует правильный контекст.
Однако, когда я меняю объявление контекста на
*:s0-s0:c0.c50
,
systemctl start httpd
терпит неудачу.
status
показывает следующее...
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/httpd.service.d
└─php73-php-fpm.conf
Active: failed (Result: exit-code) since Fri 2020-01-10 09:56:45 EST; 7s ago
Docs: man:httpd.service(8)
Process: 19362 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
Main PID: 19362 (code=exited, status=1/FAILURE)
Status: "Reading configuration..."
Jan 10 09:56:45 myhost.tld systemd[1]: Stopped The Apache HTTP Server.
Jan 10 09:56:45 myhost.tld systemd[1]: Starting The Apache HTTP Server...
Jan 10 09:56:45 myhost.tld systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
Jan 10 09:56:45 myhost.tld systemd[1]: httpd.service: Failed with result 'exit-code'.
Jan 10 09:56:45 myhost.tld systemd[1]: Failed to start The Apache HTTP Server.
Там нет никакой полезной информации. так же
journalctl -xe
показывает те же строки сообщения, без дополнительной помощи. Единственное, что я смог найти, было в
error.log
...
[Fri Jan 10 09:56:45.245476 2020] [core:notice] [pid 19362:tid 139989213628672] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
[Fri Jan 10 09:56:45.253134 2020] [:error] [pid 19362:tid 139989213628672] (13)Permission denied: SELinux: setcon_raw("system_u:system_r:httpd_t:s0-s0:c0.c50") failed
AH00016: Configuration Failed
Но из-за моего относительного младенчества при работе с политиками SEL я не совсем понимаю, о чем они мне говорят. Может ли кто-нибудь помочь пролить свет на то, что я здесь делаю неправильно?
Я пробовал перемещать объявление контекста вверх и вниз в файле conf на случай, если он пытался установить перед другой зависимостью, но без изменений. Я попытался изменить контекст пользователей с
system_u
к
unconfined_u
в контекстах каталога и обратно без изменений. Не знаю, что еще попробовать.
Заранее благодарим за любую помощь, которую вы можете предложить!
РЕДАКТИРОВАТЬ:
Я смог получить более конкретную информацию об отказе от AVC из журнала audit.log...
type=AVC msg=audit(1578928482.042:458750): avc: denied { setcurrent } for pid=11335 comm="httpd" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=process permissive=0
type=SYSCALL msg=audit(1578928482.042:458750): arch=c000003e syscall=1 success=no exit=-13 a0=d a1=55e37564e5c0 a2=29 a3=0 items=0 ppid=1 pid=11335 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)^]ARCH=x86_64 SYSCALL=write AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"
type=PROCTITLE msg=audit(1578928482.042:458750): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
type=SERVICE_START msg=audit(1578928482.054:458751): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=httpd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=failed'^]UID="root" AUID="unset"
Это вообще помогает?
1 ответ
Я отвечаю на это, потому что нашел решение, однако я не совсем понимаю, что я сделал, поэтому, если вы можете прокомментировать, чтобы внести ясность, я уверен, что другие оценят это так же, как и я...
Чтобы получить дополнительную помощь в переводе загадочных заметок в
audit.log
, Я установил две утилиты: setroubleshoot и setools
dnf install setroubleshoot setools
После того, как они были установлены, я провел следующее, чтобы проанализировать
audit.log
Ошибки AVC...
sealert -a /var/log/audit/audit.log
Ответ был на английском языке (vs giberish) и содержал полезный список инструкций по устранению проблемы...
--------------------------------------------------------------------------------
SELinux is preventing /usr/sbin/httpd from using the setcurrent access on a process.
***** Plugin catchall (100. confidence) suggests **************************
If you believe that httpd should be allowed setcurrent access on processes labeled httpd_t by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -X 300 -i my-httpd.pp
Additional Information:
Source Context unconfined_u:system_r:httpd_t:s0
Target Context unconfined_u:system_r:httpd_t:s0
Target Objects Unknown [ process ]
Source httpd
Source Path /usr/sbin/httpd
Port <Unknown>
Host <Unknown>
Source RPM Packages httpd-2.4.37-12.module_el8.0.0+185+5908b0db.x86_64
Target RPM Packages
Policy RPM selinux-policy-3.14.1-61.el8_0.2.noarch
Selinux Enabled True
Policy Type targeted
Enforcing Mode Enforcing
Host Name ##REMOVEDFORPRIVACY###
Platform Linux ##REMOVEDFORPRIVACY###
4.18.0-80.11.2.el8_0.x86_64 #1 SMP Tue Sep 24
11:32:19 UTC 2019 x86_64 x86_64
Alert Count 1
First Seen 2020-01-09 18:02:47 EST
Last Seen 2020-01-09 18:02:47 EST
Local ID 22e251b9-72fc-42a1-875b-0db3ab095f9d
Raw Audit Messages
type=AVC msg=audit(1578610967.597:455070): avc: denied { setcurrent } for pid=11650 comm="httpd" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:system_r:httpd_t:s0 tclass=process permissive=0
type=SYSCALL msg=audit(1578610967.597:455070): arch=x86_64 syscall=write success=no exit=EACCES a0=c a1=56494ec9d5d0 a2=2c a3=0 items=0 ppid=11648 pid=11650 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=959 comm=httpd exe=/usr/sbin/httpd subj=unconfined_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=write AUID=ecms UID=root GID=root EUID=root SUID=root FSUID=root EGID=root SGID=root FSGID=root
Hash: httpd,httpd_t,httpd_t,process,setcurrent
--------------------------------------------------------------------------------
Решением было запустить предложенные команды...
ausearch -c 'httpd' --raw | audit2allow -M my-httpd
semodule -X 300 -i my-httpd.pp
После этого я наконец смог перезапустить Apache.
Совершенно очевидно, что, следуя вышесказанному, я создал настраиваемую политику для службы httpd, но это все, что я понимаю. В командах не упоминается
setcurrent
команда / разрешение, на которое есть ссылка в отчете об ошибке, и ни одна из команд не выводит никаких дополнительных сведений. Я предполагаю, что
ausearch
на срок
httpd
подключен к
audit2allow
по сути, использует отчет об ошибках для создания настраиваемой политики, но хотелось бы понять, что именно произошло и где эта настраиваемая политика теперь хранится в системе.
Надеюсь, это поможет, и спасибо, если вы можете дать какое-либо полезное объяснение, почему!