Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Major cleanup of testing & documentation #144

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ jobs:
strategy:
matrix:
os:
- 'amazonlinux'
- 'amazonlinux-2'
- 'centos-6'
- 'centos-7'
- 'centos-8'
suite:
- 'default'
- 'setup'
- install
- boolean
- fcontext
- module
- module-directory
- module-remove
- permissive
- port
fail-fast: false

steps:
Expand Down
4 changes: 0 additions & 4 deletions .rubocop.yml

This file was deleted.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

This file is used to changes made in each version of the selinux_policy cookbook.

## Unreleased

- Refactor and clean up test recipes - [@detjensrobert](https://github.com/detjensrobert)
- Add Inspec tests for Kitchen test suites - [@detjensrobert](https://github.com/detjensrobert)
- Idempotency fixes for test recipes - [@detjensrobert](https://github.com/detjensrobert)
- Add ChefSpec tests - [@detjensrobert](https://github.com/detjensrobert)
- Refactor and clean up documentation - [@detjensrobert](https://github.com/detjensrobert)

## 2.4.3 (2020-08-07)

- Ship the correct license file since this cookbook was relicensed - [@tas50](https://github.com/tas50)
Expand Down
204 changes: 20 additions & 184 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,207 +3,43 @@
[![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.
This cookbook can be used to manage SELinux policies and components.

## 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).
Needs an active SELinux policy (so its values can be managed) and management tools, namely `semanage`, `setsebool` and `getsebool`. Tools are installed by the `selinux_policy_install` resource.

If this cookbook needs to run on a node with SELinux disabled, set the `allow_disabled` property on resources to `true`, which will skip the resource and do nothing (but won't break the run).

### Chef Infra Client

- 13 or later
- 15 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.
- CentOS 7+
- Fedora latest

## 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
## Recipes

Example usage:
- `selinux_policy::default`: Does nothing.
- `selinux_policy::install`: Calls `selinux_policy_install`.

```ruby
include_recipe 'selinux_policy::install'
## Resources

# Disable enforcement on Nginx
# As described on http://nginx.com/blog/nginx-se-linux-changes-upgrading-rhel-6-6/
- [`selinux_policy_install`](documentation/resource_install.md)
- [`selinux_policy_boolean`](documentation/resource_boolean.md)
- [`selinux_policy_fcontext`](documentation/resource_fcontext.md)
- [`selinux_policy_module`](documentation/resource_module.md)
- [`selinux_policy_permissive`](documentation/resource_permissive.md)
- [`selinux_policy_port`](documentation/resource_port.md)

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

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

[Nitzan Raz](https://github.com/BackSlasher) ([backslasher](http://backslasher.net))
Tests & documentation: [Robert Detjens](https://github.com/detjensrobert)
31 changes: 31 additions & 0 deletions documentation/resource_boolean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# selinux_policy_boolean

Represents an SELinux [boolean](http://wiki.gentoo.org/wiki/SELinux/Tutorials/Using_SELinux_booleans).

## Actions

| Action | Description |
|---------------|--------------------------------------------------------------------------------|
| `:setpersist` | Default. The new value will persist across reboots. Requires an active policy. |
| `:set` | Sets new value without persistence. Reverts to the default value on reboot. |

## Properties

| Name | Type | Default value | Description |
|------------------|---------|---------------|-----------------------------------------------------------------------------------|
| `name` | String | Resource name | Name of the SELinux boolean |
| `value` | Boolean | | The value to set |
| `force` | Boolean | `false` | Whether to set even if the current value matches the new one. Breaks idempotency. |
| `allow_disabled` | Boolean | `true` | Whether to skip the resource if SELinux is not enabled. |

## Examples

```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
```
62 changes: 62 additions & 0 deletions documentation/resource_fcontext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# selinux_policy_fcontext

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

## Actions

| Action | Description |
|----------------|------------------------------------------------------------------------------|
| `:add` | Assigns the file to the right context if not listed (only uses `-a`). |
| `:addormodify` | Default. Assigns the file to the right context regardless of previous state. |
| `:delete` | Removes the file's context if listed (uses `-d`). |
| `:modify` | Changes the file's context if already listed (only uses `-m`). |
| `:relabel` | Restores context on the file or directory using `restorecon`. |

## Properties

| Name | Type | Default | Description |
|------------------|---------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `file_spec` | String, Regex | Resource name | Path or regular expression to files to modify. |
| `secontext` | String | | The SELinux context to assign the file to. |
| `file_type` | String | | Restrict the resource to only modifying specific file types. See list below or [https://en.wikipedia.org/wiki/Unix_file_types](https://en.wikipedia.org/wiki/Unix_file_types). |
| `allow_disabled` | Boolean | `true` | Whether to skip the resource if SELinux is not enabled. |

Supported file types:

- **`a`** - All files
- **`f`** - Regular files
- **`d`** - Directory
- **`c`** - Character device
- **`b`** - Block device
- **`s`** - Socket
- **`l`** - Symbolic link
- **`p`** - Named pipe

## Examples

```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
```
26 changes: 26 additions & 0 deletions documentation/resource_install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# selinux_policy_install

Installs the required packages and tools to setup a working SELinux environment. A reboot may be required to fully enable SELinux.

## Actions

| Action | Description |
|------------|----------------------------------------|
| `:install` | Default. Installs the needed packages. |

## Properties

None.

## Examples

```ruby
selinux_policy_install 'example' do
notifies :reboot_now, 'reboot[selinux-reboot]', :immediately
end

reboot 'selinux-reboot' do
action :nothing
reason 'Rebooting to enable SELinux.'
end
```
Loading