Skip to content

Commit 8fefd0c

Browse files
authored
Merge pull request #395 from defnull/patch-collection
Multiple fixes and features, including security hardening.
2 parents 937b50c + 8164270 commit 8fefd0c

File tree

24 files changed

+200
-67
lines changed

24 files changed

+200
-67
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,26 @@ A secret seed used to generate other host-local secrets and passwords. Override
8181
* **`bbb_local_ip`** (default: `127.0.0.1`)\
8282
IP of your loopback device.
8383

84-
* **`bbb_bind_ip4`** (default: `{{ ansible_default_ipv4.address }}`)\
84+
* **`bbb_bind_ip4`** (default: `{{ ansible_facts.default_ipv4.address }}`)\
8585
IP (v4) address public services should bind to. This may be a LAN IP if your
8686
server is behind a NAT router and does not know its own public IP. Do not
8787
forget to set `bbb_public_ip4` in this case!
8888

89-
* **`bbb_public_ip4`** (default: `{{ ansible_default_ipv4.address }}`)\
89+
* **`bbb_public_ip4`** (default: `{{ ansible_facts.default_ipv4.address }}`)\
9090
Public IPv4 address of your server. Required if ansible cannot detect your
9191
public IP automatically. This may happen if your server is behind a NAT router
9292
and your public IP is not assigned to the primary interface, or if your primary
9393
interface has multiple IPs assigned and the first one is not your public IP.
9494

95-
* **`bbb_bind_ip6`** (default: `{{ ansible_default_ipv6.address | default(None) }}`)\
95+
* **`bbb_bind_ip6`** (default: `{{ ansible_facts.default_ipv6.address | default(None) }}`)\
9696
Same as `bbb_bind_ip4` but for IPv6. Set this to `None` to disable IPv6 even
9797
if your server technically supports it.
9898

99-
* **`bbb_public_ip6`** (default: `{{ ansible_default_ipv6.address | default(None) }}`)\
99+
* **`bbb_public_ip6`** (default: `{{ ansible_facts.default_ipv6.address | default(None) }}`)\
100100
Same as `bbb_public_ip4` but for IPv6. Set this to `None` to disable IPv6 even
101101
if your server technically supports it.
102102

103-
* **`bbb_net_mtu`** (default: `{{ ansible_default_ipv4.mtu | default(1500) }}`)\
103+
* **`bbb_net_mtu`** (default: `{{ ansible_facts.default_ipv4.mtu | default(1500) }}`)\
104104
MTU (maximum transfer unit) for outgoing packets. Some cloud environments
105105
use a smaller MTU and docker needs extra configuration in that case.
106106

@@ -150,7 +150,7 @@ You can either use ACME (e.g. letsencrypt) to auto-generate certificates, or cop
150150

151151
* **`bbb_ufw_rules`** (default: `{}`)\
152152
A hash of named rules. Each rule can define `rule` (default: allow), `direction` (default: in), `from` (default: any), `to` (default: any) and `port` (required) properties. There are a bunch of default rules for BBB that can be overridden by using the same rule-name. Take special care to the `ssh` rule, which allows traffic from any IP to port 22 by default.
153-
To remove a named rule, set it to `false`. Just removing the named rule from config will not actually remove the rule in ufw.
153+
To remove a named rule, set it to `False`. Just removing the named rule from config will not actually remove the rule in ufw.
154154

155155
* **`bbb_ufw_reject_networks`** (default: `[]`)\
156156
Block outgoing traffic to these networks in addition to `bbb_ufw_reject_networks_default`, which contains all non-routeable (LAN) networks by default. This prevets a certain group of security issues where the BBB server is tricked into accessing non-public services on the private LAN.
@@ -246,7 +246,7 @@ rest, you are on your own. Good luck!
246246
* **`bbb_dialin_provider`** (required if `bbb_dialin_enable` is true)\
247247
Domain or IP of your SIP provider, also known as registrar. Example: `sip.example.com`
248248

249-
* **`bbb_dialin_provider_ip`** (required if `bbb_dialin_enable` and `bbb_firewall_enable` are true)\
249+
* **`bbb_dialin_provider_ip`** (required if `bbb_dialin_enable` and `bbb_ufw_enable` are true)\
250250
IP or network of your SIP provider. Example: `1.2.3.4` or ``
251251

252252
* **`bbb_dialin_provider_username`** (required if `bbb_dialin_enable` is true)\
@@ -405,6 +405,8 @@ This role generates configuration with sensible defaults out of the box and cove
405405
* **`bbb_config_presentation`** (default: `{}`)\
406406
Custom overrides for `/etc/bigbluebutton/recording/presentation.yml`. This will be deep-merged into the role-managed configuration. List values will not be merged, but replaced.
407407

408+
* **`bbb_config_video`** (default: `{}`)\
409+
Custom overrides for `/etc/bigbluebutton/recording/video.yml`. This will be deep-merged into the role-managed configuration. List values will not be merged, but replaced.
408410

409411
### Other stuff not full migrated to BBB 3.0 yet.
410412

defaults/main.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ bbb_ssl_key: /etc/bigbluebutton/ssl/private.key
3737

3838
bbb_set_hostname: "{{ bbb_hostname }}"
3939
bbb_local_ip: "127.0.0.1"
40-
bbb_bind_ip4: "{{ ansible_default_ipv4.address }}"
41-
bbb_bind_ip6: "{{ ansible_default_ipv6.address | default(None) }}"
42-
bbb_public_ip4: "{{ ansible_default_ipv4.address }}"
43-
bbb_public_ip6: "{{ ansible_default_ipv6.address | default(None) }}"
44-
bbb_net_mtu: "{{ ansible_default_ipv4.mtu | default(1500) }}"
40+
bbb_bind_ip4: "{{ ansible_facts.default_ipv4.address }}"
41+
bbb_bind_ip6: "{{ ansible_facts.default_ipv6.address | default(None) }}"
42+
bbb_public_ip4: "{{ ansible_facts.default_ipv4.address }}"
43+
bbb_public_ip6: "{{ ansible_facts.default_ipv6.address | default(None) }}"
44+
bbb_net_mtu: "{{ ansible_facts.default_ipv4.mtu | default(1500) }}"
4545

4646
# Firewall
4747

@@ -89,6 +89,7 @@ bbb_config_web: {} # bbb-web.properties
8989
bbb_config_html5: {} # bbb-html5.yml
9090
bbb_config_etherpad: {} # etherpad.json
9191
bbb_config_presentation: {} # recording/presentation.yml
92+
bbb_config_video: {} # recording/video.yml
9293

9394
### STUN/TURN Servers
9495

@@ -102,6 +103,7 @@ bbb_turn_servers: [] # e.g. [{url: "turns:turn.example.com:443?transport=tcp", s
102103

103104
# bbb_cluster_proxy: frontend.example.com
104105
bbb_cluster_node: "{{ bbb_hostname | split('.') | first }}"
106+
bbb_cluster_crossorigin: "{{ bbb_cluster_proxy is defined and not bbb_hostname.endswith('.' + bbb_cluster_proxy) }}"
105107

106108
### Freeswitch config
107109
bbb_freeswitch_socket_password: "{{ ('fsp' + bbb_host_seed) | hash('sha256') }}"
@@ -124,6 +126,7 @@ bbb_dialin_enable: false
124126
# bbb_dialin_default_number: "613-555-1234"
125127
bbb_dialin_pin_minlen: 5
126128
bbb_dialin_pin_maxlen: 5
129+
bbb_dialin_pin_stdlen: "{{ bbb_dialin_pin_minlen }}"
127130
bbb_dialin_pin_timeout: 10000
128131
bbb_dialin_pin_maxwait: 5000
129132
bbb_dialin_pin_retries: 3

files/ImageMagick-policy.xml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE policymap [
3+
<!ELEMENT policymap (policy)*>
4+
<!ATTLIST policymap xmlns CDATA #FIXED "">
5+
<!ELEMENT policy EMPTY>
6+
<!ATTLIST policy xmlns CDATA #FIXED "">
7+
<!ATTLIST policy domain NMTOKEN #REQUIRED>
8+
<!ATTLIST policy name NMTOKEN #IMPLIED>
9+
<!ATTLIST policy pattern CDATA #IMPLIED>
10+
<!ATTLIST policy rights NMTOKEN #IMPLIED>
11+
<!ATTLIST policy stealth NMTOKEN #IMPLIED>
12+
<!ATTLIST policy value CDATA #IMPLIED>
13+
]>
14+
<!--
15+
Creating a security policy that fits your specific local environment
16+
before making use of ImageMagick is highly advised. You can find guidance on
17+
setting up this policy at https://imagemagick.org/script/security-policy.php,
18+
and it's important to verify your policy using the validation tool located
19+
at https://imagemagick-secevaluator.doyensec.com/.
20+
Web-safe ImageMagick security policy:
21+
This security protocol designed for web-safe usage focuses on situations
22+
where ImageMagick is applied in publicly accessible contexts, like websites.
23+
It deactivates the capability to read from or write to any image formats
24+
other than web-safe formats like GIF, JPEG, and PNG. Additionally, this
25+
policy prohibits the execution of image filters and indirect reads, thereby
26+
thwarting potential security breaches. By implementing these limitations,
27+
the web-safe policy fortifies the safeguarding of systems accessible to
28+
the public, reducing the risk of exploiting ImageMagick's capabilities
29+
for potential attacks.
30+
-->
31+
<policymap>
32+
<!-- Set maximum parallel threads. -->
33+
<policy domain="resource" name="thread" value="2"/>
34+
<!-- Set maximum time to live in seconds or neumonics, e.g. "2 minutes". When
35+
this limit is exceeded, an exception is thrown and processing stops. -->
36+
<policy domain="resource" name="time" value="60"/>
37+
<!-- Set maximum number of open pixel cache files. When this limit is
38+
exceeded, any subsequent pixels cached to disk are closed and reopened
39+
on demand. -->
40+
<policy domain="resource" name="file" value="768"/>
41+
<!-- Set maximum amount of memory in bytes to allocate for the pixel cache
42+
from the heap. When this limit is exceeded, the image pixels are cached
43+
to memory-mapped disk. -->
44+
<policy domain="resource" name="memory" value="256MiB"/>
45+
<!-- Set maximum amount of memory map in bytes to allocate for the pixel
46+
cache. When this limit is exceeded, the image pixels are cached to
47+
disk. -->
48+
<policy domain="resource" name="map" value="512MiB"/>
49+
<!-- Set the maximum width * height of an image that can reside in the pixel
50+
cache memory. Images that exceed the area limit are cached to disk. -->
51+
<policy domain="resource" name="area" value="16KP"/>
52+
<!-- Set maximum amount of disk space in bytes permitted for use by the pixel
53+
cache. When this limit is exceeded, the pixel cache is not be created
54+
and an exception is thrown. -->
55+
<policy domain="resource" name="disk" value="1GiB"/>
56+
<!-- Set the maximum length of an image sequence. When this limit is
57+
exceeded, an exception is thrown. -->
58+
<policy domain="resource" name="list-length" value="16"/>
59+
<!-- Set the maximum width of an image. When this limit is exceeded, an
60+
exception is thrown. -->
61+
<policy domain="resource" name="width" value="4KP"/>
62+
<!-- Set the maximum height of an image. When this limit is exceeded, an
63+
exception is thrown. -->
64+
<policy domain="resource" name="height" value="4KP"/>
65+
<!-- Periodically yield the CPU for at least the time specified in
66+
milliseconds. -->
67+
<policy domain="resource" name="throttle" value="2"/>
68+
<!-- Do not create temporary files in the default shared directories, instead
69+
specify a private area to store only ImageMagick temporary files. -->
70+
<!-- <policy domain="resource" name="temporary-path" value="/magick/tmp/"/> -->
71+
<!-- Force memory initialization by memory mapping select memory
72+
allocations. -->
73+
<policy domain="cache" name="memory-map" value="anonymous"/>
74+
<!-- Ensure all image data is fully flushed and synchronized to disk. -->
75+
<policy domain="cache" name="synchronize" value="true"/>
76+
<!-- Replace passphrase for secure distributed processing -->
77+
<!-- <policy domain="cache" name="shared-secret" value="secret-passphrase" stealth="true"/> -->
78+
<!-- Do not permit any delegates to execute. -->
79+
<policy domain="delegate" rights="none" pattern="*"/>
80+
<!-- Do not permit any image filters to load. -->
81+
<policy domain="filter" rights="none" pattern="*"/>
82+
<!-- Don't read/write from/to stdin/stdout. -->
83+
<policy domain="path" rights="none" pattern="-"/>
84+
<!-- don't read sensitive paths. -->
85+
<policy domain="path" rights="none" pattern="/*"/>
86+
<!-- allow access to required paths. -->
87+
<policy domain="path" rights="read|write" pattern="/var/bigbluebutton/*"/>
88+
<policy domain="path" rights="read|write" pattern="/tmp/*"/>
89+
<!-- Indirect reads are not permitted. -->
90+
<policy domain="path" rights="none" pattern="@*"/>
91+
<!-- Deny all image modules and specifically exempt reading or writing
92+
web-safe image formats. -->
93+
<policy domain="module" rights="none" pattern="*" />
94+
<policy domain="module" rights="read | write" pattern="{BMP,GIF,JPEG,PDF,PNG,TIFF,WEBP}"/>
95+
<policy domain="module" rights="read | write" pattern="{MPC}" stealth="true"/>
96+
<policy domain="module" rights="write" pattern="{JSON,INFO,PNM,PS,SVG}"/>
97+
<!-- This policy sets the number of times to replace content of certain
98+
memory buffers and temporary files before they are freed or deleted. -->
99+
<policy domain="system" name="shred" value="1"/>
100+
<!-- Enable the initialization of buffers with zeros, resulting in a minor
101+
performance penalty but with improved security. -->
102+
<policy domain="system" name="memory-map" value="anonymous"/>
103+
<!-- Set the maximum amount of memory in bytes that are permitted for
104+
allocation requests. -->
105+
<policy domain="system" name="max-memory-request" value="256MiB"/>
106+
</policymap>

tasks/check-running.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- name: Check for running meetings
1515
when:
1616
- bbb_check_running
17-
- bbb_old_secret
17+
- bbb_old_secret is present
1818
ansible.builtin.uri:
1919
url: https://{{ bbb_hostname }}/bigbluebutton/api/getMeetings?checksum={{ ('getMeetings' + bbb_old_secret) | hash('sha1') }}
2020
return_content: true
@@ -25,7 +25,7 @@
2525
- name: Fail if there are running meetings
2626
when:
2727
- bbb_check_running
28-
- bbb_old_secret
28+
- bbb_old_secret is present
2929
- meetings_result.status | default(500) == 200
3030
- "'<messageKey>noMeetings</messageKey>' not in meetings_result.content"
3131
ansible.builtin.fail:

tasks/check-vars.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
quiet: true
2020
that: "{{ item }}"
2121
loop:
22-
- ansible_distribution_release | lower == bbb_ubuntu_name
22+
- ansible_facts.distribution_release | lower == bbb_ubuntu_name
2323
- bbb_version.startswith(bbb_ubuntu_name)
2424

2525
- name: Check core variables
@@ -44,7 +44,7 @@
4444

4545
- name: Check IPv4 variables
4646
when:
47-
- bbb_bind_ip4 or bbb_public_ip4
47+
- bbb_bind_ip4 is present or bbb_public_ip4 is present
4848
- bbb_github_ci is undefined
4949
ansible.builtin.assert:
5050
quiet: true
@@ -56,7 +56,7 @@
5656

5757
- name: Check IPv6 variables
5858
when:
59-
- bbb_bind_ip6 or bbb_public_ip6
59+
- bbb_bind_ip6 is present or bbb_public_ip6 is present
6060
- bbb_github_ci is undefined
6161
ansible.builtin.assert:
6262
quiet: true
@@ -148,8 +148,8 @@
148148

149149
- name: Check dial-in firewall relevant variables
150150
when:
151-
- bbb_dialin_enable
152-
- bbb_firewall_enable
151+
- bbb_dialin_enable
152+
- bbb_ufw_enable
153153
ansible.builtin.assert:
154154
quiet: true
155155
that: "{{ item }}"

tasks/configure-bbb.yml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
path: "/etc/systemd/system/{{ item }}.service.d"
66
state: directory
77
mode: "0755"
8-
when: item
8+
when: item is present
99
loop: &systemd_overrides
1010
- bbb-html5-frontend@
1111
- bbb-html5-backend@
@@ -22,7 +22,7 @@
2222
src: "systemd-overrides/{{ item }}.j2"
2323
dest: "/etc/systemd/system/{{ item }}.service.d/override.conf"
2424
mode: "0644"
25-
when: item
25+
when: item is present
2626
loop: *systemd_overrides
2727
notify:
2828
- Restart bigbluebutton
@@ -41,12 +41,12 @@
4141
path: "{{ item }}"
4242
state: directory
4343
mode: "0755"
44-
when: item
44+
when: item is present
4545
loop:
4646
- /etc/bigbluebutton/
4747
- /etc/bigbluebutton/recording
4848
- /etc/bigbluebutton/bbb-webrtc-sfu
49-
- "{{ '/etc/bigbluebutton/bbb-webhooks' if bbb_webhooks_enable else False }}"
49+
- "{{ '/etc/bigbluebutton/bbb-webhooks' if bbb_webhooks_enable else None }}"
5050

5151
- name: Deploy bbb config files
5252
become: true
@@ -56,7 +56,7 @@
5656
owner: "{{ item.owner | default('root') }}"
5757
group: "{{ item.group | default('bigbluebutton') }}"
5858
mode: "{{ item.mode | default('0640') }}"
59-
when: item.when | default(true)
59+
when: item.when | default(True) is true
6060
loop_control:
6161
label: "{{ item.dest | default('/etc/' + item.src) }}"
6262
loop: &configfiles
@@ -66,12 +66,13 @@
6666
- src: bigbluebutton/bbb-html5.yml
6767
- src: bigbluebutton/bbb-graphql-server.env
6868
- src: bigbluebutton/bbb-graphql-middleware.yml
69-
when: "{{ bbb_cluster_proxy is defined }}"
69+
when: "{{ bbb_cluster_proxy is present }}"
7070
- src: bigbluebutton/turn-stun-servers.xml
7171
- src: bigbluebutton/etherpad.json
7272
group: etherpad
7373
- src: bigbluebutton/recording/recording.yml
7474
- src: bigbluebutton/recording/presentation.yml
75+
- src: bigbluebutton/recording/video.yml
7576
- src: bigbluebutton/bbb-webrtc-sfu/production.yml
7677
- src: bigbluebutton/bbb-webhooks/production.yml
7778
when: "{{ bbb_webhooks_enable }}"
@@ -96,16 +97,31 @@
9697
# changes and restarts. They are also incomplete and buggy...
9798
# TODO: /usr/local/bigbluebutton/bbb-transcription-controller/config/default.yml
9899

99-
- name: Patch more config files
100+
- name: Patch more config files in-place
100101
become: true
101102
ansible.builtin.lineinfile:
102103
path: "{{ item.path }}"
103104
regexp: "{{ item.regexp }}"
104105
line: "{{ item.line }}"
105106
loop_control:
106107
label: "{{ item.path }} ({{ item.line }})"
108+
when: "item.get('when', True) | bool"
107109
loop:
108110
# https://github.com/bigbluebutton/bigbluebutton/issues/22980
109111
- path: /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml
110112
regexp: "^playback_host: .*"
111113
line: "playback_host: {{ bbb_hostname }}"
114+
- path: /usr/share/bbb-web/WEB-INF/classes/application.properties
115+
regexp: "^server.servlet.session.cookie.secure=.*"
116+
line: "server.servlet.session.cookie.secure=true"
117+
- path: /usr/share/bbb-web/WEB-INF/classes/application.properties
118+
regexp: "^server.servlet.session.cookie.SameSite=.*"
119+
line: "server.servlet.session.cookie.SameSite={{ bbb_cluster_crossorigin | ternary('None', 'Lax') }}"
120+
notify: Restart bigbluebutton
121+
122+
- name: Copy hardened ImageMagick profile
123+
become: true
124+
copy:
125+
src: ImageMagick-policy.xml
126+
dest: /etc/ImageMagick-6/policy.xml
127+
mode: "0644"

tasks/configure-freeswitch.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@
131131
lineinfile:
132132
path: /usr/local/bin/fs_clibbb
133133
regexp: ^/opt/freeswitch/bin/fs_cli
134-
line: /opt/freeswitch/bin/fs_cli -p $(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml)
135-
"$@"
134+
line: /opt/freeswitch/bin/fs_cli -p $(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value
135+
/opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml) "$@"
136136

137137
- name: Configure different mute sound
138138
become: true

tasks/main.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
- import_tasks: mixin-helper.yml
2525
- import_tasks: mixin-proxy.yml
26-
when: "bbb_cluster_proxy is defined"
2726
- import_tasks: mixin-backgrounds.yml
2827
- import_tasks: mixin-assets.yml
2928
- import_tasks: mixin-styles.yml

tasks/mixin-assets.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
src: "{{ item.src }}"
66
dest: "{{ bbb_nginx_root }}/{{ item.dest }}"
77
mode: "0644"
8-
when: item.src
8+
when: item.src is present
99
loop_control:
1010
label: "{{ item.dest }}"
1111
loop:

tasks/mixin-proxy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
- name: "Update config for proxy mode"
3+
when: "bbb_cluster_proxy is defined"
34
ansible.builtin.set_fact:
45
bbb_config_web_base: |
56
{{bbb_config_web_base | combine({
@@ -36,3 +37,7 @@
3637
}
3738
}
3839
}, recursive=True)}}
40+
bbb_config_etherpad_base: |
41+
{{bbb_config_etherpad_base | combine({
42+
"cluster_proxies": ["https://"+bbb_cluster_proxy]
43+
})}}

0 commit comments

Comments
 (0)