Skip to content

Commit

Permalink
Use the firewall role and the selinux role from the cockpit role (#76)
Browse files Browse the repository at this point in the history
* Since cockpit_port is a public api of the cockpit role, define it
in defaults/main.yml as null.

* Use the firewall role from the cockpit role

- Introduce cockpit_manage_firewall to use the firewall role to
  manage the cockpit service.
  Default to false - means the firewall role is not used.

- Add the test check task tasks/check_port.yml for verifying the
  ports status.

- Add meta/collection-requirements.yml.

* Use the selinux role from the cockpit role

- Introduce cockpit_manage_selinux to use the selinux role to
  manage the ports in the cockpit service.
  Assign websm_port_t to the cockpit service ports.
  Default to false - means the selinux role is not used.

- Add a test playbook tests_port2.yml to check port 443 when
  cockpit_manage_firewall and cockpit_manage_selinux are yes.
  • Loading branch information
nhosoi authored Oct 4, 2022
1 parent d9798fe commit b3ad839
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 35 deletions.
45 changes: 39 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ Installs and configures the Cockpit Web Console for distributions that support i
- RHEL/CentOS 7.x depend on the Extras repository being enabled.
- Recommended to use [`linux-system-roles.firewall`](https://github.com/linux-system-roles/firewall/) to make the Web Console available remotely.

- The role requires the `firewall` role and the `selinux` role from the
`fedora.linux_system_roles` collection, if `cockpit_manage_firewall`
and `cockpit_manage_selinux` is set to yes, respectively.
Please see also `cockpit_manage_firewall` and `cockpit_manage_selinux`
in [`Role Variables`](#role-variables).

If `cockpit` is a role from the `fedora.linux_system_roles` collection
or from the Fedora RPM package, the requirement is already satisfied.

Otherwise, please run the following command line to install the collection.
```
ansible-galaxy collection install -r meta/collection-requirements.yml
```
## Role Variables
Available variables per distribution are listed below, along with default values (see `defaults/main.yml`):
Expand Down Expand Up @@ -81,17 +95,36 @@ Configure settings in the /etc/cockpit/cockpit.conf file. See [`man cockpit.con
cockpit_port: 9090
Cockpit runs on port 9090 by default. You can change the port with this option.

Note that the default SELinux policy does not allow Cockpit to listen to anything else than port 9090, so you need to allow that first, with e.g.
cockpit_manage_firewall: no
Boolean variable to control the `cockpit` firewall service with the `firewall` role.
If the variable is set to `no`, the `cockpit` role does not manage the firewall.
Default to `no`.

NOTE: `cockpit_manage_firewall` is limited to *adding* ports.
It cannot be used for *removing* ports.
If you want to remove ports, you will need to use the firewall system
role directly.

semanage port -m -t websm_port_t -p tcp 443
NOTE: This functionality is supported only when the managed host's `os_family`
is `RedHat`.

for ports that are already defined in the SELinux policy, such as 443, or
cockpit_manage_selinux: no
Boolean flag allowing to configure selinux using the selinux role.
The default SELinux policy does not allow Cockpit to listen to anything else
than port 9090. If you change the port, enable this to use the selinux role
to set the correct port permissions (websm_port_t).
If the variable is set to no, the `cockpit` role does not manage the
SELinux permissions of the cockpit port.

semanage port -a -t websm_port_t -p tcp 9999
NOTE: `cockpit_manage_selinux` is limited to *adding* policy.
It cannot be used for *removing* policy.
If you want to remove policy, you will need to use the selinux system
role directly.

otherwise.
NOTE: This functionality is supported only when the managed host's `os_family`
is `RedHat`.

See the [Cockpit guide](https://cockpit-project.org/guide/latest/listen.html#listen-systemd) for details.
See also the [Cockpit guide](https://cockpit-project.org/guide/latest/listen.html#listen-systemd) for details.

## Certificate setup

Expand Down
9 changes: 9 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ __cockpit_daemon: cockpit.socket
# __cockpit_packages_default set in vars/*
# __cockpit_packages_full set in vars/*
# __cockpit_packages_minimal set in vars/*

# Cockpit runs on port 9090 by default.
cockpit_port: null

# If yes, manage the cockpit ports using the firewall role.
cockpit_manage_firewall: no

# If yes, manage the cockpit ports using the selinux role.
cockpit_manage_selinux: no
3 changes: 3 additions & 0 deletions meta/collection-requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: MIT
collections:
- fedora.linux_system_roles
14 changes: 14 additions & 0 deletions tasks/firewall.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: MIT
---
- name: Ensure the cockpit service is enabled
include_role:
name: fedora.linux_system_roles.firewall
vars:
_cockpit_port: "{{ cockpit_port if cockpit_port is not none else 9090 }}"
_cockpit_port_proto: "{{ _cockpit_port }}/tcp"
firewall: "{{ [{'service': 'cockpit', 'state': 'enabled'}]
if (_cockpit_port | int) == 9090 else
[{'port': _cockpit_port_proto, 'state': 'enabled'}] }}"
when:
- cockpit_manage_firewall | bool
- ansible_facts['os_family'] == 'RedHat'
12 changes: 9 additions & 3 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@
- "setup-{{ ansible_pkg_mgr }}.yml"
- "setup-default.yml"

- name: Configure firewall
include_tasks: firewall.yml

- name: Configure selinux
include_tasks: selinux.yml

- name: Create custom port configuration file directory
file:
path: /etc/systemd/system/cockpit.socket.d/
owner: root
group: root
state: directory
when: cockpit_port is defined
when: cockpit_port is not none

- name: Create custom port configuration file
copy:
Expand All @@ -42,7 +48,7 @@
[Socket]
ListenStream=
ListenStream={{ cockpit_port }}
when: cockpit_port is defined
when: cockpit_port is not none
notify:
- reload systemd
- restart cockpit
Expand All @@ -51,7 +57,7 @@
file:
path: /etc/systemd/system/cockpit.socket.d/listen.conf
state: absent
when: cockpit_port is not defined
when: cockpit_port is none
notify:
- reload systemd
- restart cockpit
Expand Down
13 changes: 13 additions & 0 deletions tasks/selinux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: MIT
---
- name: Ensure the service and the ports status with the selinux role
include_role:
name: fedora.linux_system_roles.selinux
vars:
selinux_ports: "{{ [{'ports': cockpit_port, 'proto': 'tcp',
'setype': 'websm_port_t',
'state': 'present', 'local': 'true'}] }}"
when:
- cockpit_manage_selinux | bool
- ansible_facts['os_family'] == 'RedHat'
- cockpit_port is not none
36 changes: 36 additions & 0 deletions tests/tasks/check_port.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-License-Identifier: MIT
---
- block:
- block:
- name: Check firewall port status when cockpit_manage_firewall is yes
command: firewall-cmd --list-service
register: _result
failed_when: "'cockpit' not in _result.stdout"
changed_when: false
when:
- _cockpit_port | int == 9090

- name: Check firewall port status when cockpit_manage_firewall is yes
command: firewall-cmd --list-port
register: _result
failed_when: "'{{ _cockpit_port }}/tcp' not in _result.stdout"
changed_when: false
when:
- _cockpit_port | int != 9090
when:
- cockpit_manage_firewall | bool

- block:
- name: Install SELinux tools
include_tasks: install_selinux_tools.yml

- name: Check associated selinux ports when cockpit_manage_selinux is yes
shell: |-
set -euo pipefail
semanage port --list | egrep "websm_port_t *tcp" | grep "{{ _cockpit_port }}"
changed_when: false
when: cockpit_manage_selinux | bool
vars:
_cockpit_port: "{{ cockpit_port if cockpit_port is not none else 9090 }}"
when:
- ansible_facts['os_family'] == 'RedHat'
28 changes: 28 additions & 0 deletions tests/tasks/install_selinux_tools.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: MIT
---
- name: Install SELinux python2 tools
package:
name:
- libselinux-python
- policycoreutils-python
state: present
when: ( ansible_python_version is version('3', '<') and
ansible_distribution in ["Fedora", "CentOS", "RedHat", "Rocky"] )

- name: Install SELinux python3 tools
package:
name:
- libselinux-python3
- policycoreutils-python3
state: present
when: ( ansible_python_version is version('3', '>=') and
ansible_distribution in ["Fedora", "CentOS", "RedHat", "Rocky"] )

- name: Install SELinux tool semanage
package:
name:
- policycoreutils-python-utils
state: present
when: ansible_distribution == "Fedora" or
( ansible_distribution_major_version | int > 7 and
ansible_distribution in ["CentOS", "RedHat", "Rocky"] )
6 changes: 6 additions & 0 deletions tests/tests_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
LoginTitle: "hello world"
Session:
IdleTimeout: 60
cockpit_manage_firewall: no
cockpit_manage_selinux: yes
public: true

tasks:
- name: tests
Expand Down Expand Up @@ -58,5 +61,8 @@
command: diff -u /run/cockpit.conf.expected /etc/cockpit/cockpit.conf
changed_when: false

- name: test - ensure cockpit_port is configured for firewall and selinux
include_tasks: tasks/check_port.yml

always:
- include_tasks: tasks/cleanup.yml
6 changes: 6 additions & 0 deletions tests/tests_packages_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
block:
- include_role:
name: linux-system-roles.cockpit
public: true
vars:
cockpit_packages: full
cockpit_manage_firewall: yes
cockpit_manage_selinux: no

- meta: flush_handlers

Expand Down Expand Up @@ -37,5 +40,8 @@
msg: cockpit-doc is not installed
when: "'cockpit-doc' not in ansible_facts.packages"

- name: test - ensure cockpit_port is configured for firewall and selinux
include_tasks: tasks/check_port.yml

always:
- include_tasks: tasks/cleanup.yml
28 changes: 2 additions & 26 deletions tests/tests_port.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,8 @@
tasks:
- name: tests
block:
- name: Install SELinux python2 tools
package:
name:
- libselinux-python
- policycoreutils-python
state: present
when: ( ansible_python_version is version('3', '<') and
ansible_distribution in ["Fedora", "CentOS", "RedHat", "Rocky"] )

- name: Install SELinux python3 tools
package:
name:
- libselinux-python3
- policycoreutils-python3
state: present
when: ( ansible_python_version is version('3', '>=') and
ansible_distribution in ["Fedora", "CentOS", "RedHat", "Rocky"] )

- name: Install SELinux tool semanage
package:
name:
- policycoreutils-python-utils
state: present
when: ansible_distribution == "Fedora" or
( ansible_distribution_major_version | int > 7 and
ansible_distribution in ["CentOS", "RedHat", "Rocky"] )
- name: Install SELinux tools
include_tasks: tasks/install_selinux_tools.yml

- name: Allow cockpit to own customized port in SELinux
shell: if selinuxenabled; then semanage port -m -t websm_port_t -p tcp 443; fi
Expand Down
46 changes: 46 additions & 0 deletions tests/tests_port2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
- name: Test cockpit_* role options
hosts: all
gather_facts: true
tasks:
- name: tests
block:
- name: Run cockpit role
include_role:
name: linux-system-roles.cockpit
public: true
vars:
cockpit_manage_firewall: yes
cockpit_manage_selinux: yes
cockpit_packages: minimal
cockpit_port: 443

- meta: flush_handlers

- name: test - cockpit works on customized port
get_url:
dest: /run/out
url: https://localhost
validate_certs: no

- name: test - HTTP response is something sensible
command: grep 'id="login-user-input"' /run/out

- name: test - cockpit does not listen on port 9090
get_url:
dest: /run/out
url: https://localhost:9090
validate_certs: no
register: result
failed_when: result is succeeded

- name: test - ensure cockpit_port is configured for firewall
include_tasks: tasks/check_port.yml

- name: test - clean up output file
file:
path: /run/out
state: absent

always:
- include_tasks: tasks/cleanup.yml

0 comments on commit b3ad839

Please sign in to comment.