Разделение привилегий 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), я выполнил следующие шаги...

  1. dnf install httpd-devel selinux-policy-devel
  2. wget https://download.fedoraproject.org/pub/fedora/linux/releases/31/Everything/source/tree/Packages/m/mod_selinux-2.4.4-14.fc31.src.rpm
  3. rpmbuild --rebuild mod_selinux-2.4.4-14.fc31.src.rpm --define "_rpmdir /tmp"
  4. 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 по сути, использует отчет об ошибках для создания настраиваемой политики, но хотелось бы понять, что именно произошло и где эта настраиваемая политика теперь хранится в системе.

Надеюсь, это поможет, и спасибо, если вы можете дать какое-либо полезное объяснение, почему!

Другие вопросы по тегам