Compare commits

..

3 Commits

Author SHA1 Message Date
chris 6e086dbac0 Add virusfilter support for Samba homes and update AppArmor configuration 2026-05-29 18:43:06 +02:00
chris 56a2c8464f Add virusfilter support to Samba shares and configure ClamAV database checks 2026-05-26 14:18:36 +02:00
chris 1f78326503 Adds handlers to reload AppArmor and restart ClamAV
Ensures AppArmor profile for ClamAV is reloaded and the ClamAV daemon is restarted when necessary, improving service reliability and reflecting updated security profiles.
2026-05-26 14:16:45 +02:00
7 changed files with 241 additions and 56 deletions
+3
View File
@@ -3201,6 +3201,9 @@ samba_user: []
base_home: /home base_home: /home
# include vfs object 'virusfilter' to (private) homes shares
samba_homes_virusfilter: false
# remove_samba_users: # remove_samba_users:
# - name: name1 # - name: name1
# - name: name2 # - name: name2
+5
View File
@@ -495,6 +495,11 @@ samba_user:
- gubitz-partner - gubitz-partner
password: '20.mal-te/26%' password: '20.mal-te/26%'
- name: jovis
groups:
- intern
password: '20.jo-vis_26!'
- name: hh-lucke - name: hh-lucke
groups: [] groups: []
password: 'Ole20Steffen_17' password: 'Ole20Steffen_17'
+14
View File
@@ -643,6 +643,8 @@ samba_user:
base_home: /data/home base_home: /data/home
samba_homes_virusfilter: true
remove_samba_users: remove_samba_users:
- name: howe-staff-1 - name: howe-staff-1
- name: gerhard - name: gerhard
@@ -661,6 +663,7 @@ samba_shares:
group_write_list: a-jur group_write_list: a-jur
file_create_mask: !!str 664 file_create_mask: !!str 664
dir_create_mask: !!str 2775 dir_create_mask: !!str 2775
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -672,6 +675,7 @@ samba_shares:
group_write_list: kanzlei group_write_list: kanzlei
file_create_mask: !!str 664 file_create_mask: !!str 664
dir_create_mask: !!str 2775 dir_create_mask: !!str 2775
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -692,6 +696,7 @@ samba_shares:
group_write_list: wildvang group_write_list: wildvang
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -703,6 +708,7 @@ samba_shares:
# group_write_list: aulmann # group_write_list: aulmann
# file_create_mask: !!str 660 # file_create_mask: !!str 660
# dir_create_mask: !!str 2770 # dir_create_mask: !!str 2770
# vfs_object_virusfilter: true
# vfs_object_recycle: true # vfs_object_recycle: true
# recycle_path: '@Recycle' # recycle_path: '@Recycle'
# vfs_object_recycle_is_visible: true # vfs_object_recycle_is_visible: true
@@ -714,6 +720,7 @@ samba_shares:
# group_write_list: howe # group_write_list: howe
# file_create_mask: !!str 660 # file_create_mask: !!str 660
# dir_create_mask: !!str 2770 # dir_create_mask: !!str 2770
# vfs_object_virusfilter: true
# vfs_object_recycle: true # vfs_object_recycle: true
# recycle_path: '@Recycle' # recycle_path: '@Recycle'
# vfs_object_recycle_is_visible: true # vfs_object_recycle_is_visible: true
@@ -725,6 +732,7 @@ samba_shares:
group_write_list: stahmann group_write_list: stahmann
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -736,6 +744,7 @@ samba_shares:
group_write_list: traine group_write_list: traine
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -747,6 +756,7 @@ samba_shares:
group_write_list: public group_write_list: public
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -758,6 +768,7 @@ samba_shares:
group_write_list: advoware group_write_list: advoware
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -769,6 +780,7 @@ samba_shares:
group_write_list: intern group_write_list: intern
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: false vfs_object_recycle_is_visible: false
@@ -780,6 +792,7 @@ samba_shares:
group_write_list: alle group_write_list: alle
file_create_mask: !!str 660 file_create_mask: !!str 660
dir_create_mask: !!str 2770 dir_create_mask: !!str 2770
vfs_object_virusfilter: true
vfs_object_recycle: true vfs_object_recycle: true
recycle_path: '@Recycle' recycle_path: '@Recycle'
vfs_object_recycle_is_visible: true vfs_object_recycle_is_visible: true
@@ -791,6 +804,7 @@ samba_shares:
# group_write_list: web # group_write_list: web
# file_create_mask: !!str 660 # file_create_mask: !!str 660
# dir_create_mask: !!str 2770 # dir_create_mask: !!str 2770
# vfs_object_virusfilter: true
# vfs_object_recycle: true # vfs_object_recycle: true
# recycle_path: '@Recycle' # recycle_path: '@Recycle'
+7
View File
@@ -112,3 +112,10 @@
daemon_reload: yes daemon_reload: yes
state: restarted state: restarted
- name: Reload AppArmor profile clamd
command: apparmor_parser -r /etc/apparmor.d/usr.sbin.clamd
- name: Restart clamav-daemon
service:
name: clamav-daemon
state: restarted
+131 -30
View File
@@ -1,24 +1,23 @@
--- ---
# --- # ---
# Samba Server # Samba Server
# --- # ---
- name: (samba-install.yml) Ensure samba packages server are installed. - name: (samba-config-server.yml) Ensure samba packages server are installed.
package: package:
pkg: '{{ apt_install_server_samba }}' pkg: "{{ apt_install_server_samba }}"
state: present state: present
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
tags: tags:
- samba-server - samba-server
- name: (samba-install.yml) Ensure quarantine directory exists - name: (samba-config-server.yml) Ensure quarantine directory exists
file: file:
path: /data/samba/QUARANTINE path: /data/samba/QUARANTINE
owner: root owner: root
group: root group: root
mode: '0750' mode: "0750"
state: directory state: directory
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
@@ -37,7 +36,7 @@
recurse: no recurse: no
with_items: "{{ samba_shares }}" with_items: "{{ samba_shares }}"
loop_control: loop_control:
label: '{{ item.name }}' label: "{{ item.name }}"
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
tags: tags:
@@ -47,9 +46,9 @@
# Virusfilter (ClamAV) - only when at least one share has vfs_object_virusfilter: true # Virusfilter (ClamAV) - only when at least one share has vfs_object_virusfilter: true
# --- # ---
- name: (samba-install.yml) Ensure virusfilter (ClamAV) packages are installed - name: (samba-config-server.yml) Ensure virusfilter (ClamAV) packages are installed
package: package:
pkg: '{{ apt_install_server_samba_virusfilter }}' pkg: "{{ apt_install_server_samba_virusfilter }}"
state: present state: present
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
@@ -58,13 +57,13 @@
- samba-server - samba-server
- samba-virusfilter - samba-virusfilter
- name: (samba-install.yml) Ensure clamav-daemon and clamav-freshclam services are enabled - name: (samba-config-server.yml) Check if ClamAV virus databases are present
service: find:
name: "{{ item }}" paths: /var/lib/clamav
enabled: yes patterns:
loop: - "*.cvd"
- clamav-daemon - "*.cld"
- clamav-freshclam register: clamav_db_files
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0 - samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
@@ -72,7 +71,67 @@
- samba-server - samba-server
- samba-virusfilter - samba-virusfilter
- name: (samba-install.yml) Ensure clamav user is member of all Samba groups - name: (samba-config-server.yml) Stop clamav-freshclam service before initial database download
service:
name: clamav-freshclam
state: stopped
failed_when: false
when:
- inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
- clamav_db_files.files | length == 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Ensure clamav-daemon service is started before database update
service:
name: clamav-daemon
state: started
enabled: yes
failed_when: false
when:
- inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Download initial ClamAV virus databases via freshclam
command: freshclam
when:
- inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
- clamav_db_files.files | length == 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Ensure clamav-daemon service is enabled and started
service:
name: clamav-daemon
state: started
enabled: yes
when:
- inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Ensure clamav-freshclam service is enabled and started
service:
name: clamav-freshclam
state: started
enabled: yes
when:
- inventory_hostname in groups['samba_server']
- samba_shares | selectattr('vfs_object_virusfilter', 'defined') | selectattr('vfs_object_virusfilter', 'equalto', true) | list | length > 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Ensure clamav user is member of all Samba groups
user: user:
name: clamav name: clamav
groups: "{{ item.name }}" groups: "{{ item.name }}"
@@ -89,17 +148,62 @@
- samba-server - samba-server
- samba-virusfilter - samba-virusfilter
- name: (samba-install.yml) Configure AppArmor local profile for clamd (data paths) - name: (samba-config-server.yml) Ensure clamav user is member of all Samba user groups (homes virusfilter)
blockinfile: user:
path: /etc/apparmor.d/local/usr.sbin.clamd name: clamav
create: yes groups: "{{ item.name }}"
append: yes
loop: "{{ samba_user }}"
loop_control:
label: "{{ item.name }}"
when:
- inventory_hostname in groups['samba_server']
- samba_homes_virusfilter | default(false) | bool
- samba_user | length > 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Get home directories of samba users via getent (homes virusfilter)
ansible.builtin.getent:
database: passwd
key: "{{ item.name }}"
loop: "{{ samba_user }}"
loop_control:
label: "{{ item.name }}"
register: samba_user_getent
when:
- inventory_hostname in groups['samba_server']
- samba_homes_virusfilter | default(false) | bool
- samba_user | length > 0
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Ensure home directories are group-traversable for clamd (homes virusfilter)
file:
path: "{{ item.ansible_facts.getent_passwd[item.item.name][4] }}"
mode: "0750"
state: directory
loop: "{{ samba_user_getent.results | default([]) }}"
loop_control:
label: "{{ item.item.name }}"
when:
- inventory_hostname in groups['samba_server']
- samba_homes_virusfilter | default(false) | bool
- item.ansible_facts is defined
tags:
- samba-server
- samba-virusfilter
- name: (samba-config-server.yml) Configure AppArmor local profile for clamd (data paths)
template:
src: etc/apparmor.d/local/usr.sbin.clamd.j2
dest: /etc/apparmor.d/local/usr.sbin.clamd
owner: root owner: root
group: root group: root
mode: "0644" mode: "0644"
marker: "# {mark} ANSIBLE MANAGED - smba virusfilter paths"
block: |
/data/** r,
/data/samba/QUARANTINE/** rw,
notify: Reload AppArmor profile clamd notify: Reload AppArmor profile clamd
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
@@ -109,7 +213,7 @@
- samba-server - samba-server
- samba-virusfilter - samba-virusfilter
- name: (samba-install.yml) Ensure AllowAllMatchScan is enabled in clamd.conf - name: (samba-config-server.yml) Ensure AllowAllMatchScan is enabled in clamd.conf
lineinfile: lineinfile:
path: /etc/clamav/clamd.conf path: /etc/clamav/clamd.conf
regexp: "^#?\\s*AllowAllMatchScan\\s" regexp: "^#?\\s*AllowAllMatchScan\\s"
@@ -124,7 +228,6 @@
- samba-server - samba-server
- samba-virusfilter - samba-virusfilter
# --- # ---
# /etc/samba/smb.conf # /etc/samba/smb.conf
# --- # ---
@@ -204,7 +307,7 @@
- name: (samba-config-server.yml) Check if cleaning up trash dirs is configured - name: (samba-config-server.yml) Check if cleaning up trash dirs is configured
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /root/bin/samba/conf/clean_samba_trash.conf path: /root/bin/samba/conf/clean_samba_trash.conf
regexp: '^trash_dirs=*' regexp: "^trash_dirs=*"
state: absent state: absent
check_mode: true check_mode: true
changed_when: false changed_when: false
@@ -262,7 +365,5 @@
job: "{{ samba_cronjob_permissions.job }}" job: "{{ samba_cronjob_permissions.job }}"
when: when:
- inventory_hostname in groups['samba_server'] - inventory_hostname in groups['samba_server']
- (clean_samba_trash_dirs.found | int) > 0 # << int -> bool - (clean_samba_trash_dirs.found | int) > 0 # << int -> bool
tags: [samba-server, samba-cron] tags: [samba-server, samba-cron]
@@ -0,0 +1,11 @@
# {{ ansible_managed }}
# see: roles/common/tasks/samba-config-server.yml
/data/** r,
/data/samba/QUARANTINE/** rw,
{% if samba_homes_virusfilter | default(false) | bool %}
{{ base_home }}/** r,
{% if base_home != '/home' %}
/home/** r,
{% endif %}
{% endif %}
+45 -1
View File
@@ -305,6 +305,14 @@
# next parameter to 'no' if you want to be able to write to them. # next parameter to 'no' if you want to be able to write to them.
read only = no read only = no
{% if samba_homes_virusfilter | default(false) | bool %}
# Virusfilter aktiv: Gruppe benötigt Leserecht, damit clamd (als Gruppenmitglied)
# Dateien und Verzeichnisse direkt öffnen kann (SCAN-Kommando an clamd).
create mask = 0640
force create mode = 0040
directory mask = 0750
force directory mode = 0050
{% else %}
# File creation mask is set to 0700 for security reasons. If you want to # File creation mask is set to 0700 for security reasons. If you want to
# create files with group=rw permissions, set next parameter to 0775. # create files with group=rw permissions, set next parameter to 0775.
create mask = 0700 create mask = 0700
@@ -312,6 +320,7 @@
# Directory creation mask is set to 0700 for security reasons. If you want to # Directory creation mask is set to 0700 for security reasons. If you want to
# create dirs. with group=rw permissions, set next parameter to 0775. # create dirs. with group=rw permissions, set next parameter to 0775.
directory mask = 0700 directory mask = 0700
{% endif %}
# By default, \\server\username shares can be connected to by anyone # By default, \\server\username shares can be connected to by anyone
# with access to the samba server. # with access to the samba server.
@@ -319,6 +328,35 @@
# to \\server\username # to \\server\username
# This might need tweaking when using external authentication schemes # This might need tweaking when using external authentication schemes
valid users = %S valid users = %S
{% if samba_homes_virusfilter | default(false) | bool %}
# --- Virusfilter-Einstellungen [homes] ---
vfs objects = virusfilter
virusfilter:scanner = clamav
virusfilter:socket path = /var/run/clamav/clamd.ctl
virusfilter:infected file action = delete
virusfilter:cache entry limit = 1000
virusfilter:cache time limit = 60
virusfilter:max file size = 26214400
virusfilter:min file size = 10
virusfilter:scan on open = yes
virusfilter:scan on close = yes
# Fehlercode bei infizierter Datei (beim Öffnen)
virusfilter:infected file errno on open = EACCES
# Fehlercode beim Schließen
virusfilter:infected file errno on close = EACCES
virusfilter:connect timeout = 30000
virusfilter:io timeout = 60000
{% endif %}
# Un-comment the following and create the netlogon directory for Domain Logons # Un-comment the following and create the netlogon directory for Domain Logons
# (you need to configure Samba to act as a domain controller too.) # (you need to configure Samba to act as a domain controller too.)
@@ -489,7 +527,13 @@
# Scan-Zeitpunkt: nur beim Öffnen, nicht beim Schließen # Scan-Zeitpunkt: nur beim Öffnen, nicht beim Schließen
virusfilter:scan on open = yes virusfilter:scan on open = yes
virusfilter:scan on close = no virusfilter:scan on close = yes
# Fehlercode bei infizierter Datei (beim Öffnen)
virusfilter:infected file errno on open = EACCES
# Fehlercode beim Schließen
virusfilter:infected file errno on close = EACCES
# Timeouts (Millisekunden) # Timeouts (Millisekunden)
virusfilter:connect timeout = 30000 virusfilter:connect timeout = 30000