2017-01-12 3 views
2

Je ne peux pas écrire de fichiers dans mon répertoire Apache Webserver. J'utilise CentOS 7. Je suis en train d'exécuter des commandes git à partir d'un fichier PHP en utilisant exec:Ecriture de fichiers (en exécutant des commandes git) à partir de PHP sur CentOS7

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

En imprimant la sortie, je vois que l'erreur manifeste comme:

error: cannot open .git/FETCH_HEAD: Permission denied 

J'ai découvert (avec l'aide de ce blog: http://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/) que c'est "attendu" car Apache va s'exécuter en utilisant un autre utilisateur que ce que j'utilise via ssh. Je dois donc m'assurer que mes permissions permettent à cet utilisateur d'avoir un accès en écriture.

Je décidai que mon installation d'Apache exécute comme un utilisateur nommé « apache » en imprimant la sortie dans mon fichier php:

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

J'ai également mis en place de SSH comme recommandé dans ce même lien. Mais malheureusement, j'obtiens toujours la même erreur dans le fichier PHP:

error: cannot open .git/FETCH_HEAD: Permission denied 

La chose qui m'a vraiment jeté est que je n'ai pas de problèmes d'autorisations lorsque je lance qu'Apache de ma session ssh en utilisant:

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

L'utilisateur "apache" a apparemment des autorisations différentes lorsqu'il s'exécute à partir de PHP. Quelqu'un peut m'aider à trouver la solution?

+0

Vous utilisez un chemin relatif ('../). Êtes-vous sûr que votre commande PHP s'exécute dans le même répertoire que le sudo de ligne de commande que vous avez essayé? Essayez avec le chemin absolu et/ou affichez pwd avant de lancer git pour voir si c'est le problème. –

+0

Lorsque j'imprime "ls -la" contre exactement le même chemin relatif depuis je vois tous les fichiers, et le fait que "apache" possède les fichiers. Donc, il s'exécute à partir de l'endroit que je m'attends. – Josh

Répondre

3

Le comportement que je voyais où l'utilisateur "apache" semblait avoir des autorisations différentes lors de l'exécution de PHP vs l'exécution de mon SSH, était le résultat de SELinux. Lorsque SELinux est dans son mode "enforcing" (ce qui est par défaut dans CentOS 7), il "couche" essentiellement un schéma de protection d'accès en plus des permissions utilisateur linux standard. Dans un sens simpliste, l'utilisateur "apache" avait réellement des permissions différentes lorsqu'il s'exécutait en dehors du processus httpd. Pour plus de détails, le répertoire html qu'apache "serve" a un type de contexte SELinux "httpd_sys_content_t". Donc mon repo git héritait de ce même contexte. Mais le fonctionnement de la politique de sécurité de SELinux est que httpd dispose uniquement d'un accès en lecture au type de contexte "httpd_sys_content_t". Afin que httpd ait un accès en écriture aux fichiers, j'ai besoin de changer le contexte en "httpd_sys_rw_content_t". Je l'ai fait en utilisant:

sudo chcon -R -t httpd_sys_rw_content_t ../myRepo 

Cela a finalement résolu mon erreur d'origine! Malheureusement, il refait surface une nouvelle erreur que le lien de la question a également mentionné:

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." } 

Mais comme je l'ai mentionné dans ma question je l'ai déjà mis en place une clé ssh pour l'utilisateur « apache » comme le blog suggéré. Donc, c'était en fait une erreur différente. Une erreur provenant de nouveau de SELinux.

Par défaut, il existe un booléen SELinux appelé "httdp_can_network_connect" qui est désactivé. Cela empêche httpd de faire des connexions externes de son propre. Ce qui est ce que vous voulez si tout ce que vous faites est de servir le contenu qui existe sur votre serveur. Pour ma je devais définir cette valeur booléenne sur l'utilisation:

sudo setsebool httpd_can_network_connect on 

Et au bout de 2 jours de tirer mes cheveux. Je peux facilement faire un "git fetch" à partir d'un fichier php.J'ai débogué l'erreur finale avec le booléen en utilisant l'outil "audit2allow" qui regarde quelques logs de SELinux et vous dit en anglais plus ou moins clair comment résoudre le problème.

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; 

Si quelqu'un rencontre des problèmes SELinux liés à apache/httpd, je vous recommande vivement de regarder cet outil. Par souci d'exhaustivité, je voulais souligner que changer le contexte de fichier de mon dépôt comme je l'ai fait ci-dessus est une «modification temporaire» et ne persistera pas à travers une réinitialisation du système. Pour changer de façon permanente le type de contexte je:

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

De même, j'utilisé cette option pour modifier de façon permanente le booléen:

sudo setsebool -P httpd_can_network_connect on