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