# selinux_policy Cookbook

[![Cookbook Version](https://img.shields.io/cookbook/v/selinux_policy.svg)](https://supermarket.chef.io/cookbooks/selinux_policy)
[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)

This cookbook can be used to manage SELinux policies and components (rather than just enable / disable enforcing). I made it because I needed some SELinux settings done, and the `execute`s started to look annoying.

## Requirements

Needs an SELinux policy active (so its values can be managed). Can work with a disabled SELinux system (see attribute `allow_disabled`), which will generate warnings and do nothing (but won't break the run). Also requires SELinux's management tools, namely `semanage`, `setsebool` and `getsebool`. Tools are installed by the `selinux_policy::install` recipe (for RHEL/Debian and the like).

### Chef Infra Client

- 13 or later

### Platforms

- rhel
- fedora

## Attributes

These attributes affect the way all of the resource behave.

- `node['selinux_policy']['allow_disabled']` - Whether to allow runs when SELinux is disabled. Will generate warnings, but the run won't fail. Defaults to `true`, set to `false` if you don't have any machines with disabled SELinux.

## Usage

- `selinux_policy::install` - Installs SELinux policy management tools

This cookbook's functionality is exposed via resources, so it should be called from a wrapper cookbook. Remember to add `depends 'selinux_policy'` to your `metadata.rb`.

### boolean

Represents an SELinux [boolean](http://wiki.gentoo.org/wiki/SELinux/Tutorials/Using_SELinux_booleans). You can either `set` it, meaning it will be changed without persistence (it will revert to default in the next reboot), or `setpersist` it (default action), so it'll keep it value after rebooting. Using `setpersist` requires an active policy (so that the new value can be saved somewhere).

Properties:

- `name`: boolean's name. Defaults to resource name.
- `value`: Its new value (`true`/`false`).
- `force`: Use `setsebool` even if the current value agrees with the requested one.

Example usage:

```ruby
include_recipe 'selinux_policy::install'

selinux_policy_boolean 'httpd_can_network_connect' do
    value true
    # Make sure nginx is started if this value was modified
    notifies :start,'service[nginx]', :immediate
end
```

**Note**: Due to ruby interperting `0` as `true`, using `value 0` is unwise.

### port

Allows assigning a network port to a certain SELinux context. As explained [here](http://wiki.centos.org/HowTos/SELinux#head-ad837f60830442ae77a81aedd10c20305a811388), it can be useful for running Apache on a non-standard port.

Actions:

- `addormodify` (default): Assigns the port to the right context, whether it's already listed another context or not at all.
- `add`: Assigns the port to the right context it's if not listed (only uses `-a`).
- `modify`: Changes the port's context if it's already listed (only uses `-m`).
- `delete`: Removes the port's context if it's listed (uses `-d`).

Properties:

- `port`: The port in question, defaults to resource name.
- `protocol`: `tcp`/`udp`.
- `secontext`: The SELinux context to assign the port to. Unnecessary when using `delete`.

Example usage:

```ruby
include_recipe 'selinux_policy::install'

# Allow nginx to bind to port 5678, by giving it the http_port_t context
selinux_policy_port '5678' do
    protocol 'tcp'
    secontext 'http_port_t'
end
```

### module

Manages SEModules

Actions:

- `fetch`: Prepares the module's files for compilation. Allow `remote_directory`-like behavior
- `compile`: Translates a module source directory into a `NAME.pp` file. Uses `make` logic for idempotence.
- `install`: Adds a compiled module (`pp`) to the current policy. Only installs if the module was modified this run, `force` is enabled or it's missing from the current policy. **Note:** I wish I could compare the existing module to the one generated, but the `extract` capability was only added in [Aug 15](https://github.com/SELinuxProject/selinux/commit/65c6325271b54d3de9c17352a57d469dfbd12729). I'll be happy to see a better idea.
- `deploy` (default): Runs `fetch`, `compile`, `install` in that order.
- `remove`: Removes a module.

Properties:

- `name`: The module name. Defaults to resource name.
- `directory`: Directory where module is stored. Defaults to a directory inside the Chef cache.
- `content`: The module content, can be extracted from `audit2allow -m NAME`. This can be used to create simple modules without using external files.
- `directory_source`: Copies files cookbook to the module directory (uses `remote_directory`). Allows keeping all of the module's source files in the cookbook. **Note:** You can pre-create the module directory and populate it in any other way you'd choose.
- `cookbook`: Modifies the source cookbook for the `remote_directory`.
- `force`: Installs the module even if it seems fine. Ruins idempotence but should help solve some weird cases.

Example usage:

```ruby
include_recipe 'selinux_policy::install'

# Allow openvpn to write/delete in '/etc/openvpn'
selinux_policy_module 'openvpn-googleauthenticator' do
  content <<-eos
    module dy-openvpn-googleauthenticator 1.0;

    require {
        type openvpn_t;
        type openvpn_etc_t;
        class file { write unlink };
    }


    #============= openvpn_t ==============
    allow openvpn_t openvpn_etc_t:file { write unlink };
  eos
  action :deploy
end
```

### fcontext

Allows managing the SELinux context of files. This can be used to grant SELinux-protected daemons access to additional / moved files.

Actions:

- `addormodify` (default): Assigns the file regexp to the right context, whether it's already listed another context or not at all.
- `add`: Assigns the file regexp to the right context it's if not listed (only uses -a).
- `modify`: Changes the file regexp context if it's already listed (only uses -m).
- `delete`: Removes the file regexp context if it's listed (uses -d).

Properties:

- `file_spec`: This is the file regexp in question, defaults to resource name.
- `secontext`: The SELinux context to assign the file regexp to. Not required for `:delete`
- `file_type`: Restrict the fcontext to specific file types. See the table below for an overview. See also <https://en.wikipedia.org/wiki/Unix_file_types> for more info
- **a** All files
- **f** Regular files
- **d** Directory
- **c** Character device
- **b** Block device
- **s** Socket
- **l** Symbolic link
- **p** Namedpipe

Example usage (see mysql cookbook for example daemons ):

```ruby
include_recipe 'selinux_policy::install'

# Allow http servers (nginx/apache) to modify moodle files
selinux_policy_fcontext '/var/www/moodle(/.*)?' do
  secontext 'httpd_sys_rw_content_t'
end

# Allow a custom mysql daemon to access its files.
{'mysqld_etc_t' => "/etc/mysql-#{service_name}(/.*)?",
'mysqld_etc_t' => "/etc/mysql-#{service_name}/my\.cnf",
'mysqld_log_t' => "/var/log/mysql-#{service_name}(/.*)?",
'mysqld_db_t' => "/opt/mysql_data_#{service_name}(/.*)?",
'mysqld_var_run_t' => "/var/run/mysql-#{service_name}(/.*)?",
'mysqld_initrc_exec_t' => "/etc/rc\.d/init\.d/mysql-#{service_name}"}.each do |sc, f|
  selinux_policy_fcontext f do
    secontext sc
  end
end

# Adapt a symbolic link
selinux_policy_fcontext '/var/www/symlink_to_webroot' do
  secontext 'httpd_sys_rw_content_t'
  filetype 'l'
end
```

### permissive

Allows some types to misbehave without stopping them. Not as good as specific policies, but better than disabling SELinux entirely.

Actions:

- `add`: Adds a permissive, unless it's already added
- `delete`: Deletes a permissive if it's listed

Example usage:

```ruby
include_recipe 'selinux_policy::install'

# Disable enforcement on Nginx
# As described on http://nginx.com/blog/nginx-se-linux-changes-upgrading-rhel-6-6/

selinux_policy_permissive 'nginx' do
  notifies :restart, 'service[nginx]'
end
```

## Original Author

[Nitzan Raz](https://github.com/BackSlasher) ([backslasher](http://backslasher.net))