Разделение привилегий 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: это НЕ включает каждый из наших 
       vhostconf файлы / объявления, которые все еще остаются отдельными и включаются индивидуально.
Объявление по умолчанию для контекстов 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 по сути, использует отчет об ошибках для создания настраиваемой политики, но хотелось бы понять, что именно произошло и где эта настраиваемая политика теперь хранится в системе.
Надеюсь, это поможет, и спасибо, если вы можете дать какое-либо полезное объяснение, почему!