diff --git a/roles/lmn_encrypt/defaults/main.yml b/roles/lmn_encrypt/defaults/main.yml
new file mode 100644
index 0000000..b9b7837
--- /dev/null
+++ b/roles/lmn_encrypt/defaults/main.yml
@@ -0,0 +1,3 @@
+---
+encrypt_passphrase_initial: Muster!
+encrypt_tpm2: false
diff --git a/roles/lmn_encrypt/handlers/main.yml b/roles/lmn_encrypt/handlers/main.yml
new file mode 100644
index 0000000..0ef929f
--- /dev/null
+++ b/roles/lmn_encrypt/handlers/main.yml
@@ -0,0 +1,5 @@
+- name: Run update-grub
+ ansible.builtin.command: update-grub
+
+- name: Run update-dracut
+ ansible.builtin.command: dracut -f
diff --git a/roles/lmn_encrypt/tasks/main.yml b/roles/lmn_encrypt/tasks/main.yml
new file mode 100644
index 0000000..6c81e7b
--- /dev/null
+++ b/roles/lmn_encrypt/tasks/main.yml
@@ -0,0 +1,46 @@
+---
+- name: Find device with LUKS holder
+ vars:
+ partitions: "{{ item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') }}"
+ ansible.builtin.set_fact:
+ encrypt_device: "/dev/disk/by-id/{{ partitions[0].value.links.ids[0] }}"
+ when:
+ - item.value.partitions is defined
+ - item.value.partitions | dict2items | length > 0
+ - item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') | length > 0
+ loop: "{{ ansible_devices | dict2items }}"
+
+- name: Get luks slots
+ ansible.builtin.command:
+ cmd: "systemd-cryptenroll {{ encrypt_device }}"
+ register: encrypt_slots_result
+ changed_when: false
+ when: encrypt_device is defined
+
+- name: Change Password of Luks password slot
+ ansible.builtin.command:
+ cmd: >
+ systemd-run -P --wait
+ -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase_initial }}
+ -p SetCredential=cryptenroll.new-passphrase:{{ encrypt_passphrase }}
+ systemd-cryptenroll --password {{ encrypt_device }} --wipe-slot=password
+ no_log: true
+ when:
+ - encrypt_device is defined
+ - encrypt_passphrase is defined
+ - encrypt_slots_result.stdout_lines | length == 2
+ - encrypt_slots_result.stdout_lines[1].startswith(' 0')
+
+- name: TPM Device Check
+ ansible.builtin.stat:
+ path: /dev/tpm0
+ register: tpm_device
+ when: encrypt_device is defined
+
+- name: Include TPM2 role
+ ansible.builtin.include_tasks:
+ file: tpm2.yml
+ when:
+ - encrypt_device is defined
+ - encrypt_tpm2
+ - tpm_device.stat.exists
diff --git a/roles/lmn_encrypt/tasks/tpm2.yml b/roles/lmn_encrypt/tasks/tpm2.yml
new file mode 100644
index 0000000..432ce2f
--- /dev/null
+++ b/roles/lmn_encrypt/tasks/tpm2.yml
@@ -0,0 +1,42 @@
+---
+- name: Install tpm2-tools and dracut
+ ansible.builtin.apt:
+ name:
+ - tpm2-tools
+ - dracut
+
+- name: Enable tpm2-tss crypt module on dracut
+ ansible.builtin.copy:
+ dest: /etc/dracut.conf.d/crypt.conf
+ content: add_dracutmodules+=" tpm2-tss crypt "
+ mode: '0644'
+ notify: Run update-dracut
+
+- name: Comment out root device in crypttab
+ ansible.builtin.lineinfile:
+ dest: /etc/crypttab
+ regexp: '^([^#].*)'
+ line: '#\1'
+ backrefs: true
+
+- name: Insert luks support to GRUB_CMDLINE_LINUX
+ ansible.builtin.lineinfile:
+ dest: /etc/default/grub
+ regexp: '^(GRUB_CMDLINE_LINUX=).*'
+ line: '\1"rd.auto rd.luks=1"'
+ backrefs: true
+ notify: Run update-grub
+
+- name: Insert TPM2 to Luks slot
+ ansible.builtin.command:
+ cmd: >
+ systemd-run -P --wait
+ -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase | default(encrypt_passphrase_initial) }}
+ systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="" {{ encrypt_device }} --wipe-slot=tpm2
+ no_log: true
+ when: "'tpm2' not in encrypt_slots_result.stdout"
+
+# - name: Update TPM2 Luks slot
+# ansible.builtin.command:
+# cmd: systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 --unlock-tpm2-device=auto {{ encrypt_device }} --wipe-slot=tpm2
+# when: not grub_config.changed
diff --git a/roles/lmn_exam/defaults/main.yml b/roles/lmn_exam/defaults/main.yml
index da8c198..fc97945 100644
--- a/roles/lmn_exam/defaults/main.yml
+++ b/roles/lmn_exam/defaults/main.yml
@@ -1,2 +1,3 @@
---
exam_mode: true
+exam_teacherpc_last_digit: 80
diff --git a/roles/lmn_exam/files/pam-exec.sh b/roles/lmn_exam/files/pam-exec.sh
index 4f54861..f905cfc 100644
--- a/roles/lmn_exam/files/pam-exec.sh
+++ b/roles/lmn_exam/files/pam-exec.sh
@@ -5,10 +5,16 @@
if [[ "${PAM_USER}" =~ -exam$ ]]; then
systemctl start firewalld.service
+ if [[ -f /usr/local/sbin/no-way-out-nftable ]]; then
+ /usr/local/sbin/no-way-out-nftable || true
+ fi
if systemctl is-enabled --quiet libvirtd.service; then
systemctl restart libvirtd.service
fi
elif ! (users | grep -q -- "-exam"); then
+ if /usr/sbin/nft list tables | /usr/bin/grep -q filtermacvtap; then
+ /usr/sbin/nft delete table netdev filtermacvtap || true
+ fi
systemctl stop firewalld.service
if systemctl is-enabled --quiet libvirtd.service; then
systemctl restart libvirtd.service
diff --git a/roles/lmn_exam/tasks/main.yml b/roles/lmn_exam/tasks/main.yml
index 0e3bc4e..1d0893e 100644
--- a/roles/lmn_exam/tasks/main.yml
+++ b/roles/lmn_exam/tasks/main.yml
@@ -50,6 +50,38 @@
- pam-exec.sh
- rmexam
+- name: Append teacherPC to exam_destination_allowed_ipv4 addresses
+ ansible.builtin.set_fact:
+ exam_destination_allowed_ipv4: "{{ exam_destination_allowed_ipv4 + (exam_teacherpc_ips | default([ ansible_default_ipv4.address.rsplit('.', 1)[0] ~ '.' ~ exam_teacherpc_last_digit ])) }}"
+ when:
+ - exam_destination_allowed_ipv4 is defined
+ - exam_destination_allowed_ipv4 | length > 0
+ - exam_teacherpc_ips is defined or exam_teacherpc_last_digit | default('') | string | length > 0
+
+- name: Install no-way-out-policy
+ ansible.builtin.template:
+ src: no-way-out.xml.j2
+ dest: "/etc/firewalld/policies/no-way-out-{{ item }}.xml"
+ mode: '0644'
+ vars:
+ zones:
+ - HOST
+ - "{{ 'libvirt' if vm_support | default(false) else '' }}"
+ loop: "{{ zones | reject('match','^$') }}"
+ when:
+ - exam_destination_allowed_ipv4 is defined
+ - exam_destination_allowed_ipv4 | length > 0
+
+- name: Install no-way-out nf-table for macvtap device
+ ansible.builtin.template:
+ src: no-way-out-nftable.j2
+ dest: "/usr/local/sbin/no-way-out-nftable"
+ mode: '0755'
+ when:
+ - exam_destination_allowed_ipv4 is defined
+ - exam_destination_allowed_ipv4 | length > 0
+ - vm_support is defined and vm_support
+
- name: Enable login script via pam_exec.so
ansible.builtin.lineinfile:
dest: /etc/pam.d/common-session
diff --git a/roles/lmn_exam/templates/no-way-out-nftable.j2 b/roles/lmn_exam/templates/no-way-out-nftable.j2
new file mode 100644
index 0000000..93305a9
--- /dev/null
+++ b/roles/lmn_exam/templates/no-way-out-nftable.j2
@@ -0,0 +1,43 @@
+#!/usr/bin/bash
+
+set -eu
+
+interfaces=$(/usr/bin/ip link | /usr/bin/sed -En 's/.*(macvtap-.*)@.*/\1/p')
+gateway=$(/usr/bin/ip route list default | /usr/bin/head -1 | /usr/bin/cut -f 3 -d " ")
+
+filterchain=""
+for interface in ${interfaces}; do
+ filterchain=$(cat <<- EOF
+${filterchain}
+
+ chain filterin_${interface} {
+ type filter hook ingress device ${interface} priority filter; policy drop;
+ ip saddr \$allowed_ipv4 accept
+ ip saddr ${gateway} accept
+ ip saddr 255.255.255.255 accept
+ ether type arp accept
+ }
+
+ chain filterout_${interface} {
+ type filter hook egress device ${interface} priority filter; policy drop;
+ ip daddr \$allowed_ipv4 accept
+ ip daddr ${gateway} accept
+ ip daddr 255.255.255.255 accept
+ ether type arp accept
+ }
+EOF
+)
+done
+
+
+
+nft_table=$(cat <<- EOF
+define allowed_ipv4 = { {{ exam_destination_allowed_ipv4 | join(",") }} }
+
+table netdev filtermacvtap {
+${filterchain}
+}
+EOF
+)
+
+echo "$nft_table" | /usr/sbin/nft -f -
diff --git a/roles/lmn_exam/templates/no-way-out.xml.j2 b/roles/lmn_exam/templates/no-way-out.xml.j2
new file mode 100644
index 0000000..7cf782f
--- /dev/null
+++ b/roles/lmn_exam/templates/no-way-out.xml.j2
@@ -0,0 +1,10 @@
+
+{% for address in exam_destination_allowed_ipv4 %}
+
+
+
+
+{% endfor %}
+
+
+
diff --git a/roles/lmn_finish/handlers/main.yml b/roles/lmn_finish/handlers/main.yml
new file mode 100644
index 0000000..bae24ff
--- /dev/null
+++ b/roles/lmn_finish/handlers/main.yml
@@ -0,0 +1,4 @@
+---
+- name: Reboot client
+ ansible.builtin.command:
+ cmd: "shutdown -r -t 60"
diff --git a/roles/lmn_finish/tasks/main.yaml b/roles/lmn_finish/tasks/main.yaml
index 2a44d0e..d7ec865 100644
--- a/roles/lmn_finish/tasks/main.yaml
+++ b/roles/lmn_finish/tasks/main.yaml
@@ -6,6 +6,8 @@
- "{{ extra_pkgs }}"
- "{{ extra_pkgs1 }}"
- "{{ extra_pkgs2 }}"
+ tags:
+ - baseinstall
- name: Add backports for {{ ansible_distribution_release }}
ansible.builtin.apt_repository:
@@ -27,6 +29,18 @@
- "{{ extra_pkgs_bpo2 }}"
when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0
+
+- name: Check if former ansible-stamp exists
+ ansible.builtin.stat:
+ path: /var/local/ansible-stamps
+ register: stamp_exists
+
+- name: Trigger Reboot if no former ansible-run is found
+ ansible.builtin.debug:
+ msg: "First Ansible-Run on Client - Reboot handler started"
+ changed_when: not stamp_exists.stat.exists
+ notify: "Reboot client"
+
- name: Timestamp successfull run and send up-to-date report
ansible.builtin.shell:
cmd: date --iso-8601=seconds >> /var/local/ansible-stamps && /usr/local/sbin/reporter
diff --git a/roles/lmn_kde/defaults/main.yml b/roles/lmn_kde/defaults/main.yml
index 07685bb..065c5ba 100644
--- a/roles/lmn_kde/defaults/main.yml
+++ b/roles/lmn_kde/defaults/main.yml
@@ -3,7 +3,7 @@ kde_desktop_pkg:
- akonadi-backend-sqlite
- arduino
- bluefish
- - calligra
+ # - calligra
- codeblocks
- dia
- filius
diff --git a/roles/lmn_localhome/tasks/main.yml b/roles/lmn_localhome/tasks/main.yml
index f7c54df..ea3cf2e 100644
--- a/roles/lmn_localhome/tasks/main.yml
+++ b/roles/lmn_localhome/tasks/main.yml
@@ -33,7 +33,7 @@
dest: /etc/profile.d/lmn-logout.sh
mode: '0755'
content: |
- [[ "${UID}" -gt 10000 ]] && ! findmnt "/lmn/media/${USER}/home" > /dev/null && exit 0
+ # logout script (may be empty)
{% if localhome_logout_missing_serverhome %}
[[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0
{% endif %}
diff --git a/roles/lmn_misc/files/bootorder.sh b/roles/lmn_misc/files/bootorder.sh
index a0fb6cd..e3ef2a9 100644
--- a/roles/lmn_misc/files/bootorder.sh
+++ b/roles/lmn_misc/files/bootorder.sh
@@ -5,11 +5,11 @@
set -eu
cur="$(efibootmgr | grep -Ei 'BootOrder:' | \
- sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')"
-pxeip4="$(efibootmgr | grep -Ei "IP.*4" | \
- sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')"
+ sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')"
+pxeip4="$(efibootmgr | grep -Ei "IP.{0,5}4" | \
+ sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)"
debian="$(efibootmgr | grep -Ei "debian" | \
- sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')"
+ sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)"
if [[ "$cur" != "$pxeip4" ]] && [[ -n "$pxeip4" ]] && [[ -n "$debian" ]] ; then
efibootmgr -o $pxeip4,$debian
diff --git a/roles/lmn_misc/files/reporter b/roles/lmn_misc/files/reporter
deleted file mode 100755
index 2ee481f..0000000
--- a/roles/lmn_misc/files/reporter
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/bash
-#
-# Send stdout of some commands to monitoring server.
-# Collect the reports with 'nc -u -k -l 1234' on 'sendto'.
-# Use /bin/nc.openbsd, /bin/nc.traditional seems not to work.
-#
-set -eu
-
-sendto="collector.steinbeis.schule 1234"
-n=0
-
-cmds=(
- 'uname -a'
- 'tail -1 /var/local/ansible-stamps'
- 'ip route list default'
- 'ip link show | \
- sed -nE -e "s/^[2-9]: (\S+): .+/\1/p" -e "s/.+ether ([0-9a-f:]+) .+/\1/p" | \
- paste - -'
-)
-# 'w'
-# 'uptime'
-# 'ls -d --full-time /home/ansible/.ansible/tmp/'
-# 'ip addr show'
-# 'apt list --upgradeable -o Apt::Cmd::Disable-Script-Warning=true'
-
-r="$HOSTNAME ------- $(date --rfc-3339=seconds) -------
-$(for c in "${cmds[@]}" ; do
- n=$(( n + 1 ))
- echo -n "$n"
- eval "$c" | sed 's/^/\t/'
-done | sed "s/^/$HOSTNAME /")
-## -------------------------------------------------"
-echo "$r" | nc -w 1 -u $sendto
diff --git a/roles/lmn_misc/tasks/main.yml b/roles/lmn_misc/tasks/main.yml
index 7c15ede..212e418 100644
--- a/roles/lmn_misc/tasks/main.yml
+++ b/roles/lmn_misc/tasks/main.yml
@@ -98,7 +98,7 @@
export superusers
password_pbkdf2 root {{ grub_pwd }}
notify: Run update-grub
- when: grub_pwd | bool | default(false)
+ when: grub_pwd is defined and grub_pwd is truthy
- name: Allow booting grub menu entries
ansible.builtin.lineinfile:
@@ -167,6 +167,8 @@
src: reporter.j2
dest: /usr/local/sbin/reporter
mode: '0755'
+ tags:
+ - baseinstall
- name: Provide services and timers for reporter
ansible.builtin.copy:
@@ -177,12 +179,46 @@
- reporter.service
- reporter.timer
when: misc_reporter
+ tags:
+ - baseinstall
- name: Enable reporter.timer
ansible.builtin.systemd:
name: reporter.timer
enabled: true
when: misc_reporter
+ tags:
+ - baseinstall
+
+# Updater
+
+- name: Provide services and timers for updater
+ ansible.builtin.template:
+ src: "{{ item }}.j2"
+ dest: "/etc/systemd/system/{{ item }}"
+ mode: '0644'
+ loop:
+ - lmn-updater.service
+ - lmn-updater.timer
+ when: misc_updater_repository | default(false) is truthy
+
+- name: Enable updater.timer
+ ansible.builtin.systemd:
+ name: lmn-updater.timer
+ enabled: true
+ when:
+ - misc_updater_repository | default(false) is truthy
+ - misc_updater_autostart | default(false) is truthy
+
+- name: Deploy inventory password file
+ ansible.builtin.copy:
+ dest: /root/.inventory-pw
+ owner: root
+ mode: '0640'
+ content: "{{ misc_updater_inventory_password }}"
+ when:
+ - misc_updater_repository | default(false) is truthy
+ - misc_updater_inventory_password | default(false) is truthy
# Prepare CloneScreen on Presenter PCs
diff --git a/roles/lmn_misc/templates/lmn-fix-screen.j2 b/roles/lmn_misc/templates/lmn-fix-screen.j2
index a70ec3b..0fb2e08 100644
--- a/roles/lmn_misc/templates/lmn-fix-screen.j2
+++ b/roles/lmn_misc/templates/lmn-fix-screen.j2
@@ -22,8 +22,8 @@ fi
pactl set-card-profile alsa_card.{{ audio_output[0] }} output:{{ audio_output[1] }}
pactl set-default-sink alsa_output.{{ audio_output[0] }}.{{ audio_output[1] }}
{% else %}
-if pactl list cards | grep output:hdmi-stereo: | grep verfügbar:\ ja; then
+if pactl list cards | grep output:hdmi-stereo: | grep -E "verfügbar: ja|available: yes"; then
pactl set-card-profile $(pactl list short cards | grep -m1 pci | head -1 | cut -f2) output:hdmi-stereo
- pactl set-default-sink $(pactl list short cards | grep -m1 pci | head -1 | cut -f2 | sed s/card/output/g).output:hdmi-stereo
+ pactl set-default-sink $(pactl list short cards | grep -m1 pci | head -1 | cut -f2 | sed s/card/output/g).hdmi-stereo
fi
{% endif %}
diff --git a/roles/lmn_misc/templates/lmn-updater.service.j2 b/roles/lmn_misc/templates/lmn-updater.service.j2
new file mode 100644
index 0000000..6fe3d85
--- /dev/null
+++ b/roles/lmn_misc/templates/lmn-updater.service.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description=Run LMN Client updates via ansible-pull
+
+[Service]
+Type=oneshot
+User=root
+ExecStart=/usr/bin/ansible-pull --only-if-changed --verbose --vault-password-file /root/.inventory-pw -l %H -d /root/lmn-client \
+ --skip-tags no_ansible_pull -i {{ misc_updater_inventory }} --url={{ misc_updater_repository }} -C {{ misc_updater_branch }} lmn-client.yml
+
diff --git a/roles/lmn_misc/templates/lmn-updater.timer.j2 b/roles/lmn_misc/templates/lmn-updater.timer.j2
new file mode 100644
index 0000000..b64fdea
--- /dev/null
+++ b/roles/lmn_misc/templates/lmn-updater.timer.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description=Run LMN Updater every day
+After=network-online.target
+
+[Timer]
+OnBootSec=5min
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/lmn_misc/templates/reporter.j2 b/roles/lmn_misc/templates/reporter.j2
index 6a19bec..e652b55 100755
--- a/roles/lmn_misc/templates/reporter.j2
+++ b/roles/lmn_misc/templates/reporter.j2
@@ -16,6 +16,7 @@ cmds=(
'ip link show | \
sed -nE -e "s/^[2-9]: (\S+): .+/\1/p" -e "s/.+ether ([0-9a-f:]+) .+/\1/p" | \
paste - -'
+ 'systemctl --failed | grep -v "^$"'
)
# 'w'
# 'uptime'
diff --git a/roles/lmn_mount/tasks/main.yml b/roles/lmn_mount/tasks/main.yml
index 0f09299..504269b 100644
--- a/roles/lmn_mount/tasks/main.yml
+++ b/roles/lmn_mount/tasks/main.yml
@@ -97,7 +97,7 @@
ansible.posix.mount:
src: "{{ nfs_server }}:tools"
path: /lmn/tools
- opts: rw,_netdev,x-systemd.automount,x-systemd.idle-timeout=10s,timeo=100,soft
+ opts: rw,_netdev,x-systemd.automount,x-systemd.idle-timeout=10s,x-systemd.mount-timeout=10,timeo=100,soft
state: present
fstype: nfs4
when: nfs_server is defined
diff --git a/roles/lmn_network/tasks/main.yml b/roles/lmn_network/tasks/main.yml
index 311e4ce..416a173 100644
--- a/roles/lmn_network/tasks/main.yml
+++ b/roles/lmn_network/tasks/main.yml
@@ -5,14 +5,14 @@
mode: '0644'
content: >
{{ apt_conf }}
- when: apt_conf is defined
+ when: apt_conf is defined and apt_conf is truthy
- name: Set NTP server
ansible.builtin.lineinfile:
path: /etc/systemd/timesyncd.conf
insertafter: '^#NTP='
line: NTP={{ ntp_serv }}
- when: ntp_serv is defined
+ when: ntp_serv is defined and ntp_serv is truthy
- name: Add proposed-updates repository
ansible.builtin.apt_repository:
diff --git a/roles/lmn_security/tasks/main.yml b/roles/lmn_security/tasks/main.yml
index 62e2754..6c9edcf 100644
--- a/roles/lmn_security/tasks/main.yml
+++ b/roles/lmn_security/tasks/main.yml
@@ -5,6 +5,8 @@
key: "{{ item }}"
loop: "{{ keys2deploy }}"
when: keys2deploy is defined
+ tags:
+ - baseinstall
- name: Allow sudo without password for ansible
ansible.builtin.lineinfile:
@@ -14,12 +16,16 @@
owner: root
group: root
mode: '0700'
+ tags:
+ - baseinstall
- name: Disable ansible user login
ansible.builtin.user:
name: ansible
password_lock: true
when: security_defaultuser_login_disable
+ tags:
+ - baseinstall
- name: Limit SSH access to user ansible
ansible.builtin.blockinfile:
diff --git a/roles/lmn_sssd/defaults/main.yml b/roles/lmn_sssd/defaults/main.yml
new file mode 100644
index 0000000..e7664ac
--- /dev/null
+++ b/roles/lmn_sssd/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+sssd_domjoin_user: global-admin
diff --git a/roles/lmn_sssd/handlers/main.yml b/roles/lmn_sssd/handlers/main.yml
index 6fdda36..cddc361 100644
--- a/roles/lmn_sssd/handlers/main.yml
+++ b/roles/lmn_sssd/handlers/main.yml
@@ -1,6 +1,5 @@
- name: Restart sssd
- ansible.builtin.service:
+ ansible.builtin.systemd:
name: sssd
state: restarted
enabled: true
- listen: "Restart sssd"
diff --git a/roles/lmn_sssd/tasks/main.yml b/roles/lmn_sssd/tasks/main.yml
index cd4031f..c816d13 100644
--- a/roles/lmn_sssd/tasks/main.yml
+++ b/roles/lmn_sssd/tasks/main.yml
@@ -10,16 +10,27 @@
ansible.builtin.template:
src: sssd.conf.j2
dest: /etc/sssd/sssd.conf
- mode: '0600'
+ mode: '0640'
notify: Restart sssd
- ## Either one of the variables is defined:
+- name: Check if the machine account password and the join are still valid
+ ansible.builtin.shell:
+ cmd: adcli testjoin -D {{ domain | upper }}
+ register: adcli_test_result
+ failed_when: false
+ changed_when: false
+
+ # If domjoin not valid:
- name: Join the domain
ansible.builtin.shell:
cmd: >
- echo "{{ ansible_cmdline.adpw | default('') + adpw.user_input | default('') + joinpw | default('') }}" |
- adcli join --stdin-password -U global-admin {{ domain | upper }}
- when: >
- ansible_cmdline.adpw | default('') | length > 0 or
- adpw.user_input | default('') | length > 0 or
- joinpw is defined
+ echo "{{ ad_passwd }}" | adcli join --stdin-password -U {{ ad_user }} {{ domain | upper }}
+ no_log: true
+ vars:
+ ad_user: "{{ 'global-admin' if (adpw.user_input | default(ansible_cmdline.adpw) | default('') | length > 0) else sssd_domjoin_user }}"
+ ad_passwd: "{{ adpw.user_input | default('') if adpw.user_input | default ('') | length > 0 else ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') }}"
+ throttle: 1
+ when:
+ - adpw.user_input | default('') | length > 0 or
+ ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') | length > 0
+ - adcli_test_result.rc != 0
diff --git a/roles/lmn_sssd/templates/sssd.conf.j2 b/roles/lmn_sssd/templates/sssd.conf.j2
index fc3bf48..1591f1d 100644
--- a/roles/lmn_sssd/templates/sssd.conf.j2
+++ b/roles/lmn_sssd/templates/sssd.conf.j2
@@ -9,7 +9,9 @@ ad_domain = {{ domain }}
id_provider = ad
access_provider = ad
use_fully_qualified_names = False
+{% if localhome is defined and localhome %}
cache_credentials = True
+{% endif %}
krb5_store_password_if_offline = True
default_shell = /usr/bin/bash
# default: # ldap_id_mapping = True
@@ -17,6 +19,7 @@ ad_gpo_access_control = disabled
ad_gpo_ignore_unreadable = True
ad_maximum_machine_account_password_age = 0
ignore_group_members = True
+krb5_renew_interval = 1h
{% if localhome is defined and localhome %}
override_homedir = /home/%u
{% endif %}
diff --git a/roles/lmn_tmpfixes/tasks/main.yml b/roles/lmn_tmpfixes/tasks/main.yml
index 8e90138..4adf52c 100644
--- a/roles/lmn_tmpfixes/tasks/main.yml
+++ b/roles/lmn_tmpfixes/tasks/main.yml
@@ -8,3 +8,53 @@
- bookworm.yml
- cleanup.yml
when: ansible_distribution_release == "bookworm"
+
+- name: Set chromium gl-flags fixing AMD graphic issues
+ ansible.builtin.copy:
+ dest: /etc/chromium.d/fvs
+ content: |
+ export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --use-gl=desktop"
+ when: ansible_board_vendor == "LENOVO" and
+ (ansible_board_name == "312D" or ansible_board_name == "312A")
+
+- name: Fix 8086:4909 external graphics card
+ ansible.builtin.replace:
+ dest: "/etc/default/grub"
+ regexp: 'GRUB_CMDLINE_LINUX=""$'
+ replace: 'GRUB_CMDLINE_LINUX="i915.force_probe=4909"'
+ notify: Run update-grub
+ when: ansible_board_vendor == "LENOVO" and ansible_board_name == "32CB"
+
+- name: Remove calligra
+ ansible.builtin.apt:
+ name:
+ - calligra
+ state: absent
+ purge: true
+ autoremove: true
+
+# CVE-2026-31431 https://copy.fail/#mitigation
+- name: Create modprobe config to disable algif_aead
+ ansible.builtin.lineinfile:
+ path: /etc/modprobe.d/disable-algif.conf
+ line: "install algif_aead /bin/false"
+ create: true
+ mode: '0644'
+
+- name: Remove algif_aead module if loaded
+ community.general.modprobe:
+ name: algif_aead
+ state: absent
+
+# Dirty.Frag
+- name: Create modprobe config to disable modules needed for dirty.frag
+ ansible.builtin.copy:
+ dest: /etc/modprobe.d/dirtyfrag.conf
+ content: |
+ install esp4 /bin/false
+ install esp6 /bin/false
+ install rxrpc /bin/false
+ mode: '0644'
+
+- name: Set VM permissions
+ ansible.builtin.command: chmod -R o+r /lmn/vm
diff --git a/roles/lmn_vm/files/lmn-vm b/roles/lmn_vm/files/lmn-vm
index 7d4011e..bc79403 100644
--- a/roles/lmn_vm/files/lmn-vm
+++ b/roles/lmn_vm/files/lmn-vm
@@ -3,6 +3,11 @@
%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync
%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync
+# vm-delete: Delete VM-Images
+%role-teacher ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
+%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
+%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
+
# vm-aria2: Start/Stop aria2 as systemd-service for VM-Images
lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2
@@ -11,11 +16,6 @@ lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2
%role-student ALL=(root) NOPASSWD: /usr/local/bin/vm-link-images
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/vm-link-images
-# vm-virtiofsd: Start Virtiofsd as systemd-service
-%examusers ALL=(root) NOPASSWD: /usr/local/bin/vm-virtiofsd
-%role-student ALL=(root) NOPASSWD: /usr/local/bin/vm-virtiofsd
-%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/vm-virtiofsd
-
# desktop-sync:
%examusers ALL=(root) NOPASSWD: /usr/local/bin/desktop-sync
%role-student ALL=(root) NOPASSWD: /usr/local/bin/desktop-sync
diff --git a/roles/lmn_vm/files/virtiofsd b/roles/lmn_vm/files/virtiofsd
deleted file mode 100755
index 83fa42a..0000000
Binary files a/roles/lmn_vm/files/virtiofsd and /dev/null differ
diff --git a/roles/lmn_vm/files/vm-delete b/roles/lmn_vm/files/vm-delete
new file mode 100755
index 0000000..84a8aba
--- /dev/null
+++ b/roles/lmn_vm/files/vm-delete
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+set -eu
+
+directory="/lmn/vm"
+
+if [ ! -d "$directory" ]; then
+ echo "No VM directory found."
+ exit 1
+fi
+
+qcow2_files=("$directory"/*.qcow2)
+
+if [ "${#qcow2_files[@]}" -eq 0 ]; then
+ echo "Keine QCOW2-Dateien gefunden."
+ exit 0
+fi
+
+echo "Gefundene QCOW2-Dateien:"
+echo "-------------------------------------------------------------"
+printf "%-50s %10s\n" "Datei" "Größe (MB)"
+echo "-------------------------------------------------------------"
+
+for file in "${qcow2_files[@]}"; do
+ size=$(du -m "$file" | cut -f1) # Größe in MB
+ printf "%-50s %10d\n" "$file" "$size"
+done
+
+echo "-------------------------------------------------------------"
+
+for file in "${qcow2_files[@]}"; do
+ read -rp "Möchtest du die Datei $file löschen? (j/n) " confirmation
+ if [[ "$confirmation" == "j" || "$confirmation" == "J" ]]; then
+ link_count=$(stat -c %h "$file")
+ rm "$file"
+ echo "$file wurde gelöscht."
+ if [ "$link_count" -gt 1 ]; then
+ echo "Achtung: $file hat noch $((link_count - 1)) weitere Hardlinks."
+ echo "Diese liegen evtl. unter:"
+ echo "- /var/tmp/${UID}/vm/ (temporäre VMs, werden automatisch beim Neustart gelöscht)"
+ echo "- /var/vm/${UID}/ (persistente VMs)"
+ fi
+ echo
+ fi
+done
diff --git a/roles/lmn_vm/files/vm-link-images b/roles/lmn_vm/files/vm-link-images
index e4c8618..0eccd04 100755
--- a/roles/lmn_vm/files/vm-link-images
+++ b/roles/lmn_vm/files/vm-link-images
@@ -19,8 +19,9 @@ done
shift "$((OPTIND -1))"
# link system-VM-Images to User VM Directory
-for i in *.qcow2; do
- [[ -f "${VM_DIR}/${i}" ]] || ln "${i}" "${VM_DIR}/${i}"
+for filename in "$@"; do
+ filename="$(basename ${filename})"
+ [[ -f "${VM_DIR}/${filename}" ]] || ln "${filename}" "${VM_DIR}/${filename}"
done
# allow lmnsynci to remove old vm images
diff --git a/roles/lmn_vm/files/vm-netboot b/roles/lmn_vm/files/vm-netboot
index c21024f..92ca621 100755
--- a/roles/lmn_vm/files/vm-netboot
+++ b/roles/lmn_vm/files/vm-netboot
@@ -7,10 +7,10 @@ set -eu
## Imporant for all virsh libvirt calls:
export XDG_CONFIG_HOME="/var/tmp/vm/${UID}"
-menu=(standard "CLI Standard Debian GNU/Linux NFS"
- standard-ram "CLI Standard Debian GNU/Linux RAM"
- kde-desktop "KDE Plasma Desktop Debian GNU/Linux NFS"
- gnome-desktop "Gnome Desktop Debian GNU/Linux NFS")
+menu=(standard-edu "CLI Standard Debian GNU/Linux NFS"
+ standard-edu-ram "CLI Standard Debian GNU/Linux RAM"
+ kde-edu "KDE Plasma Desktop Debian GNU/Linux NFS"
+ gnome-edu "Gnome Desktop Debian GNU/Linux NFS")
img=$(dialog --clear --backtitle "Virtual Machine Chooser" \
--title "Choose the Virtual Machine to Start" \
--menu "Start VM:" 12 70 6 "${menu[@]}" 2>&1 >/dev/tty)
@@ -22,6 +22,8 @@ mac="$(ip link | grep -A1 -m1 "macvtap-" | \
sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")"
tapdev="$(ip link | grep -A1 -m1 "macvtap-" | sed -nE "s%^[1-9]:\s(\S+)@.*%\1%p")"
+livebox=$(host livebox | sed -E "s/.+ ([0-9.]+)$/\1/")
+
if [[ $# -eq 0 ]] ; then
mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo)
cpu=$(sed -En "0,/^cpu cores/s/^cpu cores\s+:\s+([0-9]+)/\1/p" /proc/cpuinfo)
@@ -31,8 +33,8 @@ else
arg=("$@")
fi
-kernel="http://livebox/d-i/n-live/${img%-ram}/live/vmlinuz"
-initrd="http://livebox/d-i/n-live/${img%-ram}/live/initrd.img"
+kernel="http://${livebox}/d-i/n-live/${img%-ram}/live/vmlinuz"
+initrd="http://${livebox}/d-i/n-live/${img%-ram}/live/initrd.img"
kargs=(boot=live components splash locales=de_DE.UTF-8 keyboard-layouts=de
swap=true live-config.timezone=Europe/Berlin)
@@ -42,10 +44,10 @@ case "$img" in
kargs+=(console=ttyS0)
;;&
*-ram)
- kargs+=("fetch=http://10.190.1.2/d-i/n-live/${img%-ram}/live/filesystem.squashfs")
+ kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs rd.live.ram=1")
;;
*)
- kargs+=(netboot=nfs "nfsroot=10.190.1.2:/srv/nfs/debian-live/${img%-ram}")
+ kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs")
;;
esac
diff --git a/roles/lmn_vm/files/vm-run b/roles/lmn_vm/files/vm-run
index 5307c68..3fa4f75 100755
--- a/roles/lmn_vm/files/vm-run
+++ b/roles/lmn_vm/files/vm-run
@@ -90,17 +90,21 @@ create_clone() {
local VM_NAME="$1"
if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" || -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then
- echo "qcow2 File does not exists." >&2
- exit 1
+ echo "qcow2 File does not exists." >&2
+ exit 1
fi
# Create User-VM-Dir and link system VM-Images
[[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}"
- if [[ "${PERSISTENT}" -eq 1 ]]; then
- sudo /usr/local/bin/vm-link-images -p
- else
- sudo /usr/local/bin/vm-link-images
- fi
+ IMAGE="${VM_NAME}.qcow2"
+ while [[ -n ${IMAGE} ]]; do
+ if [[ "${PERSISTENT}" -eq 1 ]]; then
+ sudo /usr/local/bin/vm-link-images -p "${IMAGE}"
+ else
+ sudo /usr/local/bin/vm-link-images "${IMAGE}"
+ fi
+ IMAGE="$(qemu-img info -U "${VM_DIR}/${IMAGE}" | grep "^backing file:" | cut -d ' ' -f 3)"
+ done
# Create backing file
cd "${VM_DIR}"
@@ -121,8 +125,6 @@ create_clone() {
create_printerlist() {
## Prepare .printerlist.csv
- mkdir -p "${VM_MEDIADIR}"
- chgrp "$(id -g)" "${VM_MEDIADIR}"
echo "Name;IppURL" > "${VM_MEDIADIR}/.printerlist.csv"
for p in $(lpstat -v | cut -f 3 -d" " | sed 's/:$//'); do
echo "$p;ipp://192.168.122.1/printers/$p" >> "${VM_MEDIADIR}/.printerlist.csv"
@@ -130,18 +132,30 @@ create_printerlist() {
}
create_mountlist() {
- if id | grep -q teachers; then
- NETHOME=/srv/samba/schools/default-school/teachers/$USER
- else
- NETHOME=(/srv/samba/schools/default-school/students/*/"$USER")
- fi
- NETHOME="${NETHOME#/srv/samba/schools}"
- cat << EOF > "/lmn/media/${USER}/.mounts.csv"
+ NETHOMEPART="${NETHOME#/srv/samba/schools}"
+ cat << EOF > "${VMINFO_DIR}/.mounts.csv"
Drive;Remotepath
-H;\\\\10.190.1.1${NETHOME//\//\\}
-T;\\\\10.190.1.1\default-school\share
+H;\\\\server.pn.steinbeis.schule${NETHOMEPART//\//\\}
+T;\\\\server.pn.steinbeis.schule\\default-school\\share
EOF
- echo "${USER}" > "/lmn/media/${USER}/.user"
+ echo "${USER}" > "/${VMINFO_DIR}/.user"
+}
+
+start_virtiofs_service() {
+ local target_name=$1
+ local shared_dir=$2
+ local drive_letter=$3
+ local socket="/run/user/${UID}/virtiofs-${VM_NAME}-${target_name,,}.sock"
+
+ systemd-run --user /usr/lib/qemu/virtiofsd --uid-map=":${GUEST_UID}:${UID}:1:" --gid-map=":${GUEST_GID}:$(id -g):1:" \
+ --socket-path "${socket}" --shared-dir "${shared_dir}" --syslog
+
+ if [[ $? -ne 0 ]]; then
+ echo "Error starting virtiofsd for ${target_name}." >&2
+ return 1
+ fi
+
+ LIBVIRTOPTS="${LIBVIRTOPTS} --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=${target_name},xpath1.set=./source/@socket=${socket}"
}
start_virtiofsd() {
@@ -151,9 +165,17 @@ start_virtiofsd() {
[[ "$GUEST_GID" == 0 ]] && GUEST_GID=1010
fi
# END temporary fix
- socket="/run/user/$(id -u $USER)/virtiofs-${VM_NAME}.sock"
- systemd-run --user /usr/local/bin/virtiofsd --uid-map=:${GUEST_UID}:${UID}:1: --gid-map=:${GUEST_GID}:$(id -g):1: \
- --socket-path "$socket" --shared-dir "/lmn/media/${USER}" --syslog
+
+ # start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y"
+ # start_virtiofs_service "default-school" "/srv/samba/schools/default-school" "Y"
+
+ # Home@PC / VM-Data
+ # if the environment variable VMLEGACY is set, /lmn/media/USER is forced
+ if [[ "${HOME}" != "${NETHOME}" && ! -v VMLEGACY ]]; then
+ start_virtiofs_service "Home_Linux" "${HOME}" "Y"
+ else
+ start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y"
+ fi
}
ask_really_persistent() {
@@ -184,6 +206,7 @@ EOF
QEMU='qemu:///session'
+
NEWCLONE=0
PERSISTENT=0
LIBVIRTOSINFO="win10"
@@ -316,18 +339,40 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
check_images
fi
if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then
- create_clone "${VM_NAME}"
+ create_clone "${VM_NAME}"
fi
# delete the old vm
virsh --connect=qemu:///session undefine --nvram "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist"
#trap exit_script SIGHUP SIGINT SIGTERM
+ for dir in teachers examusers staff parents; do
+ if [[ -d "/srv/samba/schools/default-school/${dir}/${USER}" ]]; then
+ NETHOME="/srv/samba/schools/default-school/${dir}/${USER}"
+ break
+ fi
+ done
+ if [[ -z "${NETHOME+x}" ]]; then
+ NETHOME=(/srv/samba/schools/default-school/students/*/"$USER")
+ fi
+
+ if [[ "${HOME}" != "${NETHOME}" ]]; then
+ VMINFO_DIR="${HOME}"
+ else
+ VMINFO_DIR="/lmn/media/${USER}"
+ fi
+ mkdir -p "${VM_MEDIADIR}" -m 700
+ chgrp "$(id -g)" "${VM_MEDIADIR}"
create_printerlist
create_mountlist
# start virtiofsd-service
[[ "${QEMU}" = 'qemu:///session' ]] && start_virtiofsd
+ # Create VMInfo Json file
+ #( umask 077; ./vm-create-vminfo > "${VMINFO_DIR}/.vminfo.json" )
+ # Start vminfo.timer
+ systemctl --user restart vminfo.timer
+
uuid=$(openssl rand -hex 16)
uuid="${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
@@ -349,7 +394,6 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
--memorybacking source.type=memfd,access.mode=shared \
--disk "${VM_DIR}/${VM_NAME}-clone.qcow2",driver.discard=unmap,target.bus=scsi,cache=writeback \
--network=bridge=virbr0,model.type=virtio \
- --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=virtiofs,xpath1.set=./source/@socket="/run/user/${UID}/virtiofs-${VM_NAME}.sock" \
--controller type=scsi,model=virtio-scsi \
--check path_in_use=off \
--connect="${QEMU}" \
diff --git a/roles/lmn_vm/files/vm-virtiofsd b/roles/lmn_vm/files/vm-virtiofsd
deleted file mode 100755
index 9326a5f..0000000
--- a/roles/lmn_vm/files/vm-virtiofsd
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/bash
-
-set -eu
-
-# if less than one arguments supplied, display usage
-if [[ $# -ne 1 ]]; then
- echo "This script takes as input the name of the VM " >&2
- echo "Usage: $0 vm_name" >&2
- exit 1
-fi
-
-VM_NAME="$1"
-
-## Make sure VMs can read the base directory:
-chgrp 1010 "/lmn/media/${SUDO_USER}"
-chmod 0775 "/lmn/media/${SUDO_USER}"
-
-socket="/run/user/$(id -u $SUDO_USER)/virtiofs-${VM_NAME}.sock"
-
-# FIXME: This does not work. In windows, there is no virtiofs device.
-# In GNU/Linux it's only readable.
-#
-#if ! systemctl -q is-active virtiofs-${VM_NAME}.socket ; then
-# systemd-run --unit=virtiofs-${VM_NAME} \
-# --slice=system-virtiofs \
-# --collect \
-# --socket-property=ListenStream="$socket" \
-# --socket-property=Accept=no \
-# --socket-property=SocketMode=0700 \
-# --socket-property=SocketUser=${SUDO_USER} \
-# --property=Type=exec \
-# --property=StandardInput=socket \
-# /usr/local/bin/virtiofsd --log-level debug --sandbox none \
-# --syslog --fd=0 --shared-dir "/lmn/media/${SUDO_USER}"
-#else
-# systemctl restart virtiofs-${VM_NAME}.socket
-#fi
-
-if [[ ! -S "$socket" ]] ; then
- systemd-run --unit=virtiofs-${VM_NAME} \
- --slice=system-virtiofs \
- --collect \
- --property=Type=exec \
- --property=SuccessExitStatus=1 \
- --property="ExecStopPost=rm $socket" \
- /usr/local/bin/virtiofsd --socket-path "$socket" \
- --shared-dir "/lmn/media/${SUDO_USER}"
-fi
-sleep 1
-chown "${SUDO_USER}" "$socket"
diff --git a/roles/lmn_vm/files/vm-vminfo b/roles/lmn_vm/files/vm-vminfo
new file mode 100755
index 0000000..c99627d
--- /dev/null
+++ b/roles/lmn_vm/files/vm-vminfo
@@ -0,0 +1,119 @@
+#!/usr/bin/python3
+
+import argparse
+import struct
+import subprocess
+import json
+import sys
+
+from os import environ,path
+from impacket.krb5.ccache import CCache
+from base64 import b64encode
+
+home = ""
+nethome = ""
+vminfo = {}
+
+def get_printers():
+ printers = []
+ try:
+ result = subprocess.run(['lpstat', '-v'], capture_output=True, text=True, check=True)
+ for line in result.stdout.splitlines():
+ # Extrahiere den Druckernamen
+ printer_name = line.split()[2].rstrip(':')
+ ipp_url = f"ipp://192.168.122.1/printers/{printer_name}"
+ printer = { 'Name': printer_name, 'IppURL': ipp_url }
+ printers.append(printer)
+ return printers
+ except subprocess.CalledProcessError as e:
+ sys.stderr.write(f"Fehler beim Abrufen der Drucker: {e}")
+ return []
+
+def get_groups(username):
+ try:
+ result = subprocess.run(['id', '-Gnz', username], capture_output=True, text=True, check=True)
+ groups = result.stdout.strip().split('\0')
+ return groups
+ except subprocess.CalledProcessError as e:
+ sys.stderr.write(f"Fehler beim Abrufen der Gruppen: {e}")
+ return []
+
+def get_krb5 ():
+ krb5 = {}
+ ccachefilename = environ.get('KRB5CCNAME').replace('FILE:', '')
+ if ccachefilename:
+ try:
+ ccache = CCache.loadFile(ccachefilename)
+ cred = ccache.toKRBCRED()
+ cred_enc = b64encode(cred)
+ krb5['cred'] = cred_enc.decode('utf-8')
+ krb5['starttime'] = ccache.credentials[0]['time']['starttime']
+ krb5['endtime'] = ccache.credentials[0]['time']['endtime']
+ krb5['renew_till'] = ccache.credentials[0]['time']['renew_till']
+ except:
+ sys.stderr.write("Fehler beim Ticket laden")
+ return krb5
+
+def get_mounts():
+ mounts = []
+ mounts.append({ 'Drive': 'H', 'RemotePath': '\\\\server.pn.steinbeis.schule' + nethome.replace('/srv/samba/schools','').replace('/','\\'), 'Name': 'Home_Server' })
+ mounts.append({ 'Drive': 'T', 'RemotePath': '\\\\server.pn.steinbeis.schule\\default-school\\share', 'Name': 'Tausch' })
+ if "role-teacher" in vminfo['Groups']:
+ mounts.append({ 'Drive': 'S', 'RemotePath': '\\\\server.pn.steinbeis.schule\\default-school\\students', 'Name': 'SuS' })
+ return mounts
+
+def get_user_folders():
+ HOME="H:"
+ if environ.get('HOME') != nethome:
+ HOME="Y:"
+ folders = []
+ folders.append( {'Name': 'Personal', 'Path': f"{HOME}\Dokumente"} )
+ folders.append( {'Name': 'My Pictures', 'Path': f"{HOME}\Bilder"} )
+ folders.append( {'Name': 'My Music', 'Path': f"{HOME}\Musik"} )
+ folders.append( {'Name': 'My Video', 'Path': f"{HOME}\Videos"} )
+ return folders
+
+def get_quickaccess():
+ quickaccess = []
+ quickaccess.append( 'H:\\transfer' )
+ return quickaccess
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ #parser.add_argument('input_file', help="File in kirbi (KRB-CRED) or ccache format")
+ #parser.add_argument('output_file', help="Output file")
+ return parser.parse_args()
+
+
+def main():
+ global home, nethome
+
+ args = parse_args()
+
+ home = environ.get('HOME')
+
+ vminfo['User'] = environ.get('USER')
+ vminfo['Groups'] = get_groups(environ.get('USER'))
+
+ for dir in ['teachers','examusers','staff','parents']:
+ potential_path = f"/srv/samba/schools/default-school/{dir}/{vminfo['User']}"
+ if path.isdir(potential_path):
+ nethome = potential_path
+ break
+ if not nethome:
+ result = subprocess.run(['find', '/srv/samba/schools/default-school/students/', '-name', vminfo['User'], '-maxdepth', '2', '-type', 'd'], capture_output=True, text=True, check=False)
+ nethome = result.stdout.splitlines()[0]
+
+ vminfo['Printers'] = get_printers()
+ vminfo['krb5'] = get_krb5()
+ vminfo['Mounts'] = get_mounts()
+ vminfo['UserShellFolders'] = get_user_folders()
+ vminfo['QuickAccess'] = get_quickaccess()
+
+ vminfo_json = json.dumps(vminfo, ensure_ascii=False, indent=4)
+ print(vminfo_json)
+
+if __name__ == '__main__':
+ main()
+
+
diff --git a/roles/lmn_vm/tasks/main.yml b/roles/lmn_vm/tasks/main.yml
index a3ce960..053c613 100644
--- a/roles/lmn_vm/tasks/main.yml
+++ b/roles/lmn_vm/tasks/main.yml
@@ -16,10 +16,13 @@
name:
- aria2
- mktorrent
+ - guestfs-tools
- libvirt-daemon-system
- virt-manager
- virt-viewer
- dialog # for vm-netboot menu
+ - python3-impacket
+ - virtiofsd
# - name: allow all users to use VMs
# lineinfile:
@@ -28,32 +31,6 @@
# insertafter: '#auth_unix_rw = "polkit"'
# notify: reload libvirtd
-- name: Configure pam_mount for VM bind mounts
- ansible.builtin.blockinfile:
- dest: /etc/security/pam_mount.conf.xml
- marker: ""
- block: |
-
- rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %}
-
- rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %}
-
- rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %}
-
- insertafter: ""
-
- name: Use umount script for proper cleanup
ansible.builtin.blockinfile:
dest: /etc/security/pam_mount.conf.xml
@@ -143,14 +120,14 @@
group: root
mode: '0755'
loop:
+ - vm-delete
- vm-create
- vm-rebase
- vm-run
- vm-upload
- vm-sync
- vm-link-images
- - vm-virtiofsd
- - virtiofsd
+ - vm-vminfo
- vm-aria2
- uploadseed
- desktop-sync
@@ -237,3 +214,26 @@
src: vm-netboot
dest: /usr/local/bin/
mode: '0755'
+
+- name: Provide vminfo service
+ ansible.builtin.copy:
+ content: |
+ [Unit]
+ Description=Create .vminfo.json for VMs
+ [Service]
+ Type=simple
+ ExecStart=/usr/bin/bash -c 'umask 077; /usr/local/bin/vm-vminfo > "{% if localhome %}/home{% else %}/lmn/media{% endif %}/${USER}/.vminfo.json"'
+ dest: /etc/systemd/user/vminfo.service
+ mode: '0644'
+
+- name: Provide vminfo timer
+ ansible.builtin.copy:
+ content: |
+ [Unit]
+ Description=Timer for vm-info
+ [Timer]
+ OnActiveSec=0s
+ OnUnitActiveSec=1h
+ Persistent=true
+ dest: /etc/systemd/user/vminfo.timer
+ mode: '0644'
diff --git a/roles/lmn_vpn/files/10-lmn-mount.sh b/roles/lmn_vpn/files/10-lmn-mount.sh
index 6f42725..cabbc58 100755
--- a/roles/lmn_vpn/files/10-lmn-mount.sh
+++ b/roles/lmn_vpn/files/10-lmn-mount.sh
@@ -13,30 +13,32 @@ if [[ "$CONNECTION_ID" = "VPN-Schule" ]]; then
# Exit if server is already mounted
findmnt /srv/samba/schools/default-school > /dev/null && exit 0
- if ! klist -s -c "${KRB5CCNAME}"; then
- #echo "try to renew KRB5-Ticket" >&2
- #sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}"
- echo "KRB5-Ticket is expired. Sleep 3 seconds and hope it will be renewed after." >&2
- sleep 3
- fi
+ counter=1
+ while ! klist -s -c "${KRB5CCNAME}"; do
+ (( counter > 30 )) && exit 0
+ echo "KRB5-Ticket is expired. Sleep 1 seconds and hope it will be renewed after." >&2
+ # if (( counter == 10 )); then
+ # echo "try to renew KRB5-Ticket" >&2
+ # sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}"
+ # fi
+ sleep 1
+ ((counter++))
+ done
echo "prepare mountpoints" >&2
umask 0002
mkdir -p /srv/samba/schools/default-school
chmod 777 /srv/samba/schools/default-school
- mkdir -p "/lmn/media/${USERNAME}/share"
-
+
mount -t cifs //server/default-school/ /srv/samba/schools/default-school \
-o "sec=krb5i,cruid=${USERID},user=${USERNAME},uid=${USERID},gid=${GROUPID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10"
echo "after mount" >&2
- mount --bind /srv/samba/schools/default-school/share "/lmn/media/${USERNAME}/share"
SUDO_USER=$USERNAME /usr/local/bin/install-printers.sh
elif [[ "$NM_DISPATCHER_ACTION" = "pre-down" ]]; then
# FIXME: Only umount server when Wireguard-Connection was the only connection to server.
# Dirty fix (works only in fvs-IP-Range)
if ! (ip r s | grep "10.190." | grep -v wg0); then
- echo "Try to umount server shares"
- umount "/lmn/media/${USERNAME}/share"
+ echo "Try to umount server"
umount /srv/samba/schools/default-school
fi
fi
diff --git a/roles/lmn_vpn/files/mountserver b/roles/lmn_vpn/files/mountserver
index 71c61cc..708a26e 100644
--- a/roles/lmn_vpn/files/mountserver
+++ b/roles/lmn_vpn/files/mountserver
@@ -3,7 +3,6 @@ set -eu
exit_script() {
echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log"
- findmnt "/lmn/media/${SUDO_USER}/share" && umount "/lmn/media/${SUDO_USER}/share"
findmnt "/srv/samba/schools/default-school" && umount "/srv/samba/schools/default-school"
trap - SIGHUP SIGINT SIGTERM # clear the trap
kill -- -$$ # Sends SIGTERM to child/sub processes
@@ -14,11 +13,9 @@ findmnt /srv/samba/schools/default-school > /dev/null && exit 0
umask 0002
mkdir -p /srv/samba/schools/default-school
chmod 777 /srv/samba/schools/default-school
-mkdir -p "/lmn/media/${SUDO_USER}/share"
mount -t cifs //server/default-school/ /srv/samba/schools/default-school \
-o "sec=krb5i,cruid=${SUDO_UID},user=${SUDO_USER},uid=${SUDO_UID},gid=${SUDO_GID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10"
-mount --bind /srv/samba/schools/default-school/share "/lmn/media/${SUDO_USER}/share"
echo "Einbindung erfolgreich!"
echo "Dieses Fenster bitte nicht schließen!"
diff --git a/roles/lmn_vpn/tasks/main.yml b/roles/lmn_vpn/tasks/main.yml
index b6da7e0..5daa5d0 100644
--- a/roles/lmn_vpn/tasks/main.yml
+++ b/roles/lmn_vpn/tasks/main.yml
@@ -29,3 +29,5 @@
- name: Configure Wireguard
ansible.builtin.include_tasks: wg_config.yml
when: vpn is defined and vpn == "wg"
+ tags:
+ - no_ansible_pull
diff --git a/roles/lmn_wlan/tasks/main.yaml b/roles/lmn_wlan/tasks/main.yaml
index d5adcea..eb9bacf 100644
--- a/roles/lmn_wlan/tasks/main.yaml
+++ b/roles/lmn_wlan/tasks/main.yaml
@@ -39,3 +39,5 @@
- name: Configure WPA-Enterprise (EAP-TLS)
ansible.builtin.include_tasks: eap-tls_check-certificate.yaml
when: wlan == 'eap-tls'
+ tags:
+ - no_ansible_pull