How do I run Flask+Nginx+uWSGI with SELinux in Enforcing mode?

Viewed 2949

I'm following this tutorial to run Flask on an Nginx server. I've almost got it to work, wherein the page loads when SELinux is set as Permissive but shows a 502 Bad Gateway when SELinux is in the Enforcing mode.

Here are some relevant files:

myproject.ini

[uwsgi]
module = wsgi

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

myproject.service

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=thisuser
Group=nginx
WorkingDirectory=/home/thisuser/public_html
Environment="PATH=/home/thisuser/thisuser_env/bin"
ExecStart=/home/thisuser/thisuser_env/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

thisuser.com.conf (Nginx configuration)

server {
    listen  80;

    server_name thisuser.com www.thisuser.com;
    access_log /home/thisuser/logs/access.log;
    error_log /home/thisuser/logs/error.log;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/thisuser/public_html/myproject.sock;
        try_files $uri $uri/ =404;
    }

}

The location of the Flask files+dirs is /home/thisuser/ and it's contexts are set like so:

[root@dev ~]# ls -ldZ /home/thisuser/
drwx--x--x. thisuser thisuser unconfined_u:object_r:user_home_dir_t:s0 /home/thisuser/
[root@dev ~]# ls -ldZ /home/thisuser/public_html/
drwxrwxr-x. thisuser thisuser unconfined_u:object_r:httpd_sys_content_t:s0 /home/thisuser/public_html/

The errors are as follows:

/var/log/audit/audit.log

type=AVC msg=audit(1498880449.864:156): avc:  denied  { write } for  pid=2667 comm="nginx" name="myproject.sock" dev="dm-2" ino=67165858 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=sock_file
type=SYSCALL msg=audit(1498880449.864:156): arch=c000003e syscall=42 success=no exit=-13 a0=f a1=7f526e12e548 a2=6e a3=7ffdf52991b0 items=0 ppid=2666 pid=2667 auid=4294967295 uid=997 gid=995 euid=997 suid=997 fsuid=997 egid=995 sgid=995 fsgid=995 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)

and

/home/thisuser/logs/error.log

2017/06/30 23:40:49 [crit] 2667#0: *1 connect() to unix:/home/thisuser/public_html/myproject.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.1.15, server: thisuser.com, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/home/thisuser/public_html/myproject.sock:", host: "thisuser.com"

Steps tried:

  • tried changing the sock permissions to chmod-socket = 666
  • used setsebool -P httpd_can_network_connect 1
  • changed FROM user=thisuser to user=nginx
  • added thisuser to the nginx group

The only thing that works is changing SELinux to Permissive. Are there some changes/additions I can make, so that SELinux stays Enforcing?

Edit: http(s) has already been allowed in firewalld

[root@dev ~]# firewall-cmd --permanent --zone=public --add-service=https
[root@dev ~]# firewall-cmd --permanent --zone=public --add-service=http
[root@dev ~]# firewall-cmd --reload
5 Answers

Thank you all for your answers. My goal was to run Python Flask application with NGINX through uWSGI with SELINUX enabled with enforcing mode. I used Unix socket initially but NGINX cannot access socket file when SELINUX is enforced. There is a workaround to set httpd_t in permissive using the command "semanage permissive -a httpd_t". But I wanted no security loophole so only option is to use HTTP as protocol for uwsgi to talk to my application. This is how I made it happen using the ideas suggested in this thread:

myapp.ini file

;This is uWSGI config file
[uwsgi]
module = wsgi:app
; Allow the Python processes to spawn threads
; uWSGI disables Python threads by default
enable-threads = true
callable = app  # This is the call module name of application.py you run

master = true
processes = 1

plugins = python3
project = /usr/local/myapp/bin
chdir = %(project)

socket = 127.0.0.1:3031

chmod-socket = 660
chown-socket=bma:nginx
uid = bma
gid = nginx

socket-timeout = 3600
harakiri = 3600

; remove the socket when the process stops
vacuum = true

; uWSGI will kill the process instead of reloading it
die-on-term = true

My NGINX Conf has:

location /rest/ {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:3031;
}

To launch the uWSGI, I used this command (from my .service file)

/usr/local/bin/uwsgi --socket 127.0.0.1:3031 --ini bma.ini

Finally run the following command to allow httpd to act as a relay:

# setsebool -P httpd_can_network_relay 1

Thats all I had to do. SELinux is fully enforcing. No need to set httpd_t in permissive mode.

Related