It would be nice to, e.g., detect that SELinux or AppArmor are enabled and tell the user that nothing will work.
Ideally we should also say "here's how to fix it" but I've never known anyone to actually do that.
It would be nice to, e.g., detect that SELinux or AppArmor are enabled and tell the user that nothing will work.
Ideally we should also say "here's how to fix it" but I've never known anyone to actually do that.
PROBLEM
Trying to look at the repo through diffusion causes errors listed below; however the commit does go properly (through command line) and one can see the commit number in phabricator.
ERRORS PRODUCED
Command failed with error #128! COMMAND git cat-file --batch-check STDOUT (empty) STDERR fatal: Not a git repository (or any of the parent directories): .git Command failed with error #128! COMMAND git cat-file --batch-check STDOUT (empty) STDERR fatal: Not a git repository (or any of the parent directories): .git Command failed with error #128! COMMAND git for-each-ref --sort='-creatordate' --format='%(objectname)%01%(objecttype)%01%(refname)%01%(*objectname)%01%(*objecttype)%01%(subject)%01%(creator)' 'refs/tags/' STDOUT (empty) STDERR fatal: Not a git repository (or any of the parent directories): .git Command failed with error #128! COMMAND git for-each-ref --sort='-creatordate' --format='%(objectname)%01%(objecttype)%01%(refname)%01%(*objectname)%01%(*objecttype)%01%(subject)%01%(creator)' 'refs/heads/' STDOUT (empty) STDERR fatal: Not a git repository (or any of the parent directories): .git
CAUSE
This issue happens due to SELinux being enabled, you can verify by temporarily setting selinux to not enforce, check and if it works then re-enable and follow resolution below.
setenforce 0
Alternatively you can use audit2why to check for git errors:
grep git /var/log/audit/audit.log | audit2why
Please remember to turn on SELinux after.
SUGGESTION FOR PHABRICATOR DETECTION
Much like phabricator throws a setup error once it detects files can't be uploaded we should do the same thing here. On error produced we should throw a setup issue to resolve. Also this can be made into a script and made available to the user.
RESOLUTION
To fix this issue you need to create an SELinux policy to allow everything through.
Generate a policy rule to allow phabricator to run locally using git (webserver):
rep git /var/log/audit/audit.log | audit2allow -m phabgitlocal > phabgitlocal.te
You can view the policy rules by using cat:
# bash: cat phabgitlocal.te module phabgitlocal 1.0; require { type httpd_t; type var_t; class file { read getattr open }; } #============= httpd_t ============== allow httpd_t var_t:file { read getattr open };
The next step, now that the above looks okay, is to create a policy module that you can install:
#bash: grep git /var/log/audit/audit.log | audit2allow -M phabgitlocal.te ******************** IMPORTANT *********************** To make this policy package active, execute: semodule -i phabgitlocal.te.pp
And finally lets go ahead and install it:
#bash: selinux -i phabgitlocal.te.pp #bash:
The first code block underneath the Resolution heading is missing the starting 'g' in grep.
This solution was very helpful on a CentOS 7 install. Thank you.
A related issue. /notification/status just returns:
[cURL/7] (http://127.0.0.1:22281/status/) <CURLE_COULDNT_CONNECT> The cURL library raised an error while making a request. You may be able to find more information about this error (error code: 7) on the cURL site: http://curl.haxx.se/libcurl/c/libcurl-errors.html#CURLECOULDNTCONNECT
This is caused by SELinux here on my instance running on a plain CentOS 7.
It can be (temporarily) worked around using: setsebool -P httpd_can_network_connect on
I'll try to come up with a proper permanent solution.
Just throwing this on here in case it helps anyone. I'm working through an SELinux + phabricator install with hosting over SSH instead of HTTP, and so far I've had to do this to get clone working:
[root@phab]# ausearch -m avc -ts recent | audit2allow -v #============= sshd_t ============== # src="sshd_t" tgt="mysqld_t" class="unix_stream_socket", perms="connectto" # comm="php" exe="" path="" #!!!! This avc can be allowed using the boolean 'daemons_enable_cluster_mode' allow sshd_t mysqld_t:unix_stream_socket connectto; # src="sshd_t" tgt="mysqld_var_run_t" class="sock_file", perms="write" # comm="php" exe="" path="" #!!!! This avc is allowed in the current policy allow sshd_t mysqld_var_run_t:sock_file write; [root@phab]# ausearch -m avc -ts recent | audit2allow -M sshd_mysql2 [root@phab]# semodule -i sshd_mysql2.pp
This is in addition to using setfacl to allow my vcs-user rwx in the arcanist, libphutil, and phabricator directories under the phabricator root.
@storrgie - SELinux is very nice for tightening security, but unless you are very well versed in it is a pain in arse... and ruins everything you love. Phabricator + SE Linux.... Well, either disable SELinux or happy hunting!
It wasn't too much of a hunt, but I did go easy mode towards the end (audit2allow). For others he is my basic install notes on Fedora 23 server:
Lots adapted from the following resources:
adduser --system phacility
dnf install mariadb-server systemctl start mariadb.service systemctl enable mariadb.service sudo mysql_secure_installation
We must make a user account and grant it way too much privileges because phabricator installs so many schemas:
mysql -u root -p GRANT ALL PRIVILEGES ON *.* TO "phabricator"@"localhost" IDENTIFIED BY "<pass>"; FLUSH PRIVILEGES; EXIT;
dnf install php php-cli php-common php-mysql php-process php-devel php-gd php-mbstring php-xml php-opcache php-pecl-apcu python-pygments
Now we will get php working. We're going to use a fastcgi process manager called
php-fpm.
dnf install php-fpm
The default behavior of the php interpreter is to do its best to process the
file that is as near to the requested file as possible. This is a possible
security risk. We will change the default configuration so that the interpreter
will only process the exact file path.
vim /etc/php.ini # Find the line cgi.fix_pathinfo, uncomment, change to 0
By default php-fpm is listening on a socket, this is better (in our case) than
tcp because there is no overhead.
vim /etc/nginx/nginx.conf ````` server { listen 443 ssl; listen [::]:443 ssl; server_name phabricator.domain.tld; root /opt/phacility/phabricator/webroot; ssl_certificate "/etc/pki/tls/certs/orolo.domain.tld/phabricator.domain.tld.crt"; ssl_certificate_key "/etc/pki/tls/certs/orolo.domain.tld/phabricator.domain.tld.key"; ssl_client_certificate "/etc/pki/tls/certs/orolo.domain.tld/ca.domain.tld.crt"; ssl_verify_client on; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers PROFILE=SYSTEM; ssl_prefer_server_ciphers on; access_log /var/log/nginx/phabricator.domain.tld.access.log main; index index.php; client_max_body_size 512m; location / { index index.php; rewrite ^/(.*)$ /index.php?__path__=/$1 last; } location ~ \.php$ { # SECURITY : Zero day Exploit Protection try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/run/php-fpm/www.sock; fastcgi_index index.php; include fastcgi.conf; #required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; #variables to make the $_SERVER populate in PHP fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; } } ````` firewall-cmd --permanent --zone=FedoraServer --add-port=443/tcp firewall-cmd --zone=FedoraServer --list-all firewall-cmd --complete-reload firewall-cmd --zone=FedoraServer --list-all
mkdir /opt/phacility chown root:root /opt/phacility chmod 755 /opt/phacility cd /opt/phacility git clone https://github.com/phacility/libphutil.git cd /opt/phacility/libphutil git checkout stable git clone https://github.com/phacility/arcanist.git cd /opt/phacility/arcanist git checkout stable git clone https://github.com/phacility/phabricator.git cd /opt/phacility/phabricator git checkout stable mkdir /opt/phacility/files chmod -R 777 /opt/phacility/files mkdir /opt/phacility/git chown -R phacility:phacility /opt/phacility/* semanage fcontext -a -s system_u -t httpd_sys_content_t "/opt/phacility(/.*)?" semanage fcontext -a -t httpd_sys_rw_content_t "/opt/phacility/files(/.*)?" restorecon -F -R -v /opt/phacility su phacility # because we want the /<phab>/config/local/local.json to be created with proper ownership cd /opt/phacility/phabricator ./bin/config set mysql.user phabricator ./bin/config set mysql.pass <pass> ./bin/config set phabricator.base-uri 'https://phabricator.domain.tld/' ./bin/config storage.local-disk.path /opt/phacility/files/ exit # back to root
cd /opt/phacility/phabricator ./bin/config set phd.user phacility vim /lib/systemd/system/phabricator-phd.service ``` [Unit] Description=phabricator-phd After=network.target nginx.service php-fpm.service mysqld.service [Service] User=phacility Group=phacility Type=oneshot Environment="PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin" ExecStart=/opt/phacility/phabricator/bin/phd start ExecStop=/opt/phacility/phabricator/bin/phd stop RemainAfterExit=yes [Install] WantedBy=multi-user.target ``` systemctl start phabricator-phd.service systemctl enable phabricator-phd.service
phabricator runs its own ssh daemon on 22 by default, which gives us that nice looking git@phabricator.domain.tld.
adduser --system git visudo git ALL=(phacility) SETENV: NOPASSWD: /bin/git-upload-pack, /bin/git-receive-pack cd /opt/phacility/phabricator ./bin/config set diffusion.ssh-user git mkdir /opt/phacility/git chown phacility:phacility /opt/phacility/git ./bin/config set repository.default-local-path /opt/phacility/git cp /usr/lib/systemd/system/sshd.service /usr/lib/systemd/system/phabricator-sshd.service vim /usr/lib/systemd/system/phabricator-sshd.service ``` [Unit] Description=OpenSSH server daemon for Phabricator Diffusion After=sshd.service [Service] EnvironmentFile=-/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D -f /etc/ssh/phabricator_sshd_config $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target ``` vim /etc/ssh/phabricator_sshd_config ``` AuthorizedKeysCommand /opt/phacility/phabricator-ssh-hook.sh AuthorizedKeysCommandUser git AllowUsers git # You may need to tweak these options, but mostly they just turn off everything # dangerous. Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key PermitRootLogin no AllowAgentForwarding no AllowTcpForwarding no PrintMotd no PrintLastLog no PasswordAuthentication no AuthorizedKeysFile none PidFile /var/run/phabricator-sshd.pid ``` semanage fcontext -a -s system_u -t etc_t /etc/ssh/phabricator_sshd_config restorecon -F -v /etc/ssh/phabricator_sshd_config mkdir /opt/phacility/sshd vim /opt/phacility/sshd/phabricator-ssh-hook.sh ``` #!/bin/sh # NOTE: Replace this with the username that you expect users to connect with. VCSUSER="git" # NOTE: Replace this with the path to your Phabricator directory. ROOT="/opt/phacility/phabricator" if [ "$1" != "$VCSUSER" ]; then exit 1 fi exec "$ROOT/bin/ssh-auth" $@ ``` chown -R root:root /opt/phacility/sshd chmod -R 755 /opt/phacility/sshd firewall-cmd --permanent --zone=FedoraServer --add-port=22/tcp firewall-cmd --zone=FedoraServer --list-all firewall-cmd --complete-reload firewall-cmd --zone=FedoraServer --list-all systemctl enable phabricator-sshd.service systemctl start phabricator-sshd.service systemctl restart phabricator-phd.service systemctl restart php-fpm.service systemctl restart nginx.service
Phab has a lot of things going (especially due to that git hook), so we're going to ultimately rely on audit2allow to help us.
setenforce 0 getenforce # verify
Now within phabricator create a repository, add you pub key, and clone that repository to your developmental machine.
Now back to the server
mkdir /opt/phacility/selinux cd /opt/phacility/selinux ausearch -m avc -ts recent | audit2allow -M phacility semodule -i phacility.pp setenforce 1 getenforce # verify
You can examine the .te of that file to see what audit2allow produced.
systemctl stop nginx.service systemctl stop php-fpm.service systemctl stop phabricator-phd.service cd /opt/phacility/arcanist/ git pull cd /opt/phacility/libphutil/ git pull cd /opt/phacility/phabricator git pull ./bin/storage upgrade --user phabricator --password <pass> systemctl start nginx.service systemctl start php-fpm.service systemctl start phabricator-phd.service