How can I tell SELinux to permit nginx access to a unix socket without audit2allow?

Solution 1:

It seems ridiculous that you can't set up a policy that allows nginx to write to a socket without first having an attempt denied and then running a tool that enables things that were denied.

Well no, SELinux is Mandatory Access Control, things are denied by default and you have to explicitly allow something. If the policy authors have not considered a particular (franken) stack or a daemon's authors have not made it SELinux aware and written policy for it then you are on your own. You have to analyze what your services are doing and how they are interacting with SELinux and come up with your own policy to allow it. There are tools available to help you audit2why, audit2allow etc.

... Is this the only way?

No, but it depends upon what you are trying to do and how you are trying to do it as to what the solution is. For example you may want to bind nginx (httpd_t) to port 8010 (unreserved_port_t). When you start nginx it fails

Starting nginx: nginx: [emerg] bind() to 0.0.0.0:8010 failed (13: Permission denied)

and you (eventually) look in the audit log and find

type=AVC msg=audit(1457904756.503:41673): avc:  denied  { name_bind } for
pid=30483 comm="nginx" src=8010 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

You might run this through audit2alllow and naively accept it's findings

allow httpd_t port_t:tcp_socket name_bind;

which then allows httpd_t to connect to any tcp port. This may not be what you want.

You can use sesearch to investigate the policy and see what port types httpd_t can name_bind to

sesearch --allow -s httpd_t | grep name_bind
...
allow httpd_t http_port_t : tcp_socket name_bind ;
allow httpd_t http_port_t : udp_socket name_bind ;
...

Amongst other types http_t can bind to http_port_t. Now you can use semanage to dig a bit deeper.

semanage port -l | grep http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
...

Port 8010 isn't listed. As we want nginx to bind to port 8010 it is not unreasonable to add it to the http_port_t list

semanage port -a -t http_port_t -p tcp 8010

Now nginx will be allowed to name_bind to port 8010 nd not every tcp port as above.

How do you know exactly what is being enabled?

Changes to policy are fairly easy to read, running your messages above through audit2allow we get

allow httpd_t httpd_sys_content_t:sock_file write;
allow httpd_t initrc_t:unix_stream_socket connectto;

which seem fairly self explanatory.

The first of those refers to the file with inum 76151. You can use find to get it's name (find / -inum 76151) and then use semanage fcontext -a -t ... to change the policy and restorecon to fix the context.

The second relates to /run/gunicorn/socket which again has the wrong context. Using sesearch we can see that http_t can connectto unix_stream_sockets of type (amongst others) http_t. So we can change the context accordingly for example

semanage fcontext -a -t httpd_t "/run/gunicorn(/.*)?"
restorecon -r /run

This sets the context of /run/gunicorn and the tree| files below it to httpd_t.

How is this supposed to work if your setting up machines under automation?

You need to analyse the system and make appropriate changes in test. You then use your automation tools to deploy the changes, puppet and ansible have support for this.

Of course you can do it all in production with SElinux set to permissive. Collect all the messages, analyse them decide on your changes and deploy them them.

There is much more to know about SELinux but that's the limit of my skills, Michael Hampton is better and Mathew Ife is way better again, they may have more to add.

Solution 2:

The type you want to use is not httpd_sys_content_t. This is for static files that the web server is meant to serve to user agents.

For a socket used for interprocess communication, the type you are looking for is httpd_var_run_t.

Though, please note that because you ran gunicorn unconfined, there may be additional issues communicating with it.