apache — Написание файлов (путем выполнения команд git) из PHP на CentOS7

Я не могу писать файлы в моем каталоге веб-сервера apache. Я использую CentOS 7. Я пытаюсь выполнить команды git из файла PHP, используя exec:

exec("/usr/local/bin/git -C ../myRepo fetch 2>&1", $output, $exec_return_value);

Распечатывая вывод, я вижу, что ошибка проявляется как:

error: cannot open .git/FETCH_HEAD: Permission denied

Я обнаружил (с помощью этого блога: http://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/) что это «ожидаемо», потому что Apache будет выполняться с использованием другого пользователя, который я использую через ssh. Поэтому я должен убедиться, что мои разрешения позволяют этому пользователю иметь доступ для записи.

Я определил, что моя установка Apache выполняется как пользователь с именем «apache», напечатав вывод этого в моем php-файле:

exec("whoami", $debugOutput, $debugRetVal);

Я также настроил SSH, как рекомендовано в той же ссылке. Но, к сожалению, я все еще получаю ту же ошибку в файле PHP:

error: cannot open .git/FETCH_HEAD: Permission denied

Что меня действительно поразило, так это то, что у меня нет проблем с разрешениями, когда я запускаю apache из моей сессии ssh с помощью:

sudo -u apache /usr/local/bin/git -C ../myRepo fetch

Пользователь «apache», по-видимому, имеет различные разрешения при выполнении из PHP. Может кто-нибудь помочь мне понять это?

2

Решение

Поведение, которое я наблюдал, когда пользователь «apache» имел разные разрешения при выполнении из PHP по сравнению с выполнением из моего SSH, было результатом SELinux. Когда SELinux находится в своем «принудительном» режиме (который по умолчанию в CentOS 7), он по существу «накладывает» схему защиты доступа поверх стандартных пользовательских разрешений linux. В упрощенном смысле пользователь «apache» действительно имел разные разрешения, когда он выполнялся вне процесса httpd.

Чтобы получить более подробную информацию, каталог html, который apache «обслуживает», имеет тип контекста SELinux «httpd_sys_content_t». Мой репозиторий git наследовал тот же контекст. Но политика безопасности SELinux работает так, что httpd имеет доступ только для чтения к типу контекста «httpd_sys_content_t». Чтобы httpd имел доступ для записи в файлы, мне нужно было изменить контекст на «httpd_sys_rw_content_t». Я сделал это с помощью:

sudo chcon -R -t httpd_sys_rw_content_t ../myRepo

Это наконец решило мою первоначальную ошибку! К сожалению, всплыла новая ошибка, о которой также упоминалась ссылка из вопроса:

array(5) { [0]=> string(68) "ssh: connect to host PRIVATEGITHOST: Permission denied" [1]=> string(45) "fatal: Could not read from remote repository." [2]=> string(0) "" [3]=> string(51) "Please make sure you have the correct access rights" [4]=> string(26) "and the repository exists." }

Но, как я уже упоминал в своем вопросе, я уже настроил ssh-ключ для пользователя «apache», как было предложено в блоге. Так что на самом деле это была другая ошибка. Ошибка, снова происходящая из SELinux.

По умолчанию существует логическое значение SELinux, называемое httdp_can_network_connect, которое отключено. Это не позволяет httpd создавать собственные внешние подключения. Что вам нужно, если все, что вы делаете, — это обслуживание контента, существующего на вашем сервере. Для моих целей мне нужно было установить это логическое значение при использовании:

sudo setsebool httpd_can_network_connect on

И через 2 дня выдернул мои волосы. Я могу сделать «git fetch» ​​из php-файла.

Я отладил последнюю ошибку с помощью логического значения с помощью инструмента «audit2allow», который просматривает некоторые журналы SELinux и говорит вам на более или менее простом английском языке, как решить эту проблему.

sudo audit2allow -a

OUTPUT:
#============= httpd_t ==============
#!!!! This avc can be allowed using one of the these booleans:
#     nis_enabled, httpd_can_network_connect
allow httpd_t unreserved_port_t:tcp_socket name_connect;

Если у кого-то возникают проблемы с SELinux, связанные с apache / httpd, я настоятельно рекомендую взглянуть на этот инструмент.

Для полноты картины я хотел бы отметить, что изменение контекста файла моего репозитория, как я делал выше, является «временным изменением» и не будет сохраняться после сброса системы. Чтобы навсегда изменить тип контекста, я использовал:

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/myRepo(/.*)?"

Точно так же я использовал это, чтобы навсегда изменить логическое значение:

sudo setsebool -P httpd_can_network_connect on
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]