diff --git a/README.md b/README.md index 41e0e77..07ad798 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,42 @@ # lmn-client -Ansible playbooks and roles to deploy Debian clients for LinuxMuster. \ No newline at end of file +Ansible playbooks and roles to deploy Debian clients for LinuxMuster. + +## Default tasks + +* **Install/Update Debian** +* **Install KDE-Plasma Desktop** +* **Join domain** +* **Activate kerberos-support** +* **Mount homes from server** +* **Install printer** + Installs local cups (printserver) and configures/installs all subscribed printers on login. Printers can be subscribed by user or by machine + +## Following optional modules are available: + +* [custom_roles](doc/custom_roles.md) + Runs own ansible roles. +* [exam_mode](doc/exam_mode.md) + Starts local firewall and removes local directories of exam users the day after. +* [localhome](doc/localhome.md) + Sometimes a local home directory makes more sense than the home on a network share. +* [localproxy](doc/localproxy.md) + Creates a http-proxy running in user context and authentication on parent with users krb5-ticket. +* [localuser](doc/localuser.md) + Creates a local guest user with home on tmpfs. +* [misc_clonescreen](doc/misc_clonescreen.md) + CloneScreen on presenter PCs +* [vm_support](doc/vm_support.md) + VMs based on Qemu/KVM in school network. +* [vpn](doc/vpn.md) + Provides VPN access to school network. +* [wlan](doc/wlan.md) + Provides WLAN access via WPA Personal/Enterprise. + +## Installation + +Following possibilities: + +* [Install client via PXE-Boot](doc/install_pxe.md) +* [Run playbook on existing client](doc/install_ontop.md) +* Install client via USB-Stick including ansible-playbook diff --git a/doc/custom_roles.md b/doc/custom_roles.md new file mode 100644 index 0000000..4d1ec47 --- /dev/null +++ b/doc/custom_roles.md @@ -0,0 +1,50 @@ +# Custom roles + +- Custom ansible roles can be stored in `roles/custom` +- To include custom roles, you can list them in `custom_roles`. + +## Configuration / Variables + + * **custom_roles** + List of roles which will be applied + Type: *List of Strings* + Default: [] + + +## Example + +All hosts (e.g. 10.0.2.14) will get `role_a` and `role_c`, +but hosts in group laptop (e.g. 10.0.32.14) will get `role_a` and `role_b` + +``` +roles/custom/ +├── role_a +│   └── tasks +│   └── main.yml +├── role_b +│   └── tasks +│   └── main.yml +└── role_c + └── tasks + └── main.yml +``` + +inventory.yml + +```yaml +all: + vars: + custom_roles: + - role_a + - role c +desktops: + hosts: + 10.0.2.[1:128]: +laptops: + hosts: + 10.0.32.[1:50]: + vars: + custom_roles: + - role_a + - role_b +``` diff --git a/doc/exam_mode.md b/doc/exam_mode.md new file mode 100644 index 0000000..246dd3a --- /dev/null +++ b/doc/exam_mode.md @@ -0,0 +1,27 @@ +# exam_mode + +## Description / use cases + +Activating exam_mode provides following functionalities: +* when -exam user logs in, firewalld.service will start and prevent communication between devices in the same local network +* home- and media-directory of -exam users will be renamed (on the next day) and removed (after some days). + This is important due the fact, that -exam user will be new created (with new user-id) on exam-mode initialisation. + Without renaming/deleting the home- and media-directory, the -exam user couldn't log in twice on the same pc. + Particularly important on machines with localhome + +## Requirements + +none + +## Example + +Per default, all hosts will get exam_mode. But we don't want exam_mode on teacher devices + +inventory.yml +``` +teacherdevices: + hosts: + 10.0.14.[1..75] + vars: + exam_mode: false +``` diff --git a/doc/install_ontop.md b/doc/install_ontop.md new file mode 100644 index 0000000..e44633c --- /dev/null +++ b/doc/install_ontop.md @@ -0,0 +1,53 @@ +# Installation on existing client + +An easy method to test the lmn-client is to run the playbook manual on a fresh installed client. + +## Direct call via ansible-pull + +With two simple commands you can install the lmn-client with default configuration. + +Steps: + +* Install debian on client (via USB or PXE) +* Install additional packages: ansible + `sudo apt install ansible` +* Run Playbook + `ansible-pull -i inventory.yml -l localhost, --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml` + +## Checkout git and run ansible locally + +When checking out the repository you can customize the installation by editing the inventory before run the playbook. +You can repeat the process as often as you like and gradually adapt your inventory settings to your needs. + +Steps: + +* Install debian on client (via USB or PXE) +* Install additional packages: ansible, git + `sudo apt install ansible git` +* Checkout Repository + `git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git` +* Create inventory + `cp inventory.yml inventory-myschool.yml` +* Edit inventory-myschool.yml + e.g.: `nano inventory-myschool.yml` +* Run Playbook + `ansible-playbook -i inventory-myschool.yml -l localhost lmn-client.yml` + +## Run with other target device + +If you want to run the play on an other target pc: + +* You have to add the target IP or hostname in the inventory. +* SSH access on target must be configured (deploy ssh public-key on target host) + +`ansible-playbook -i inventory-myschool.yml -l target lmn-client.yml` + +## Upload changes to your own remote repository + +If you are satisfied with your changes, you can upload the changes to your own remote repository. + +* Create new git repository on your git service (e.g. https://codeberg.org) +* Add new remote origin + `git remote add myorigin git@codeberg.org:myname/mylmn-client.git` +* Push the repository to the new remote + `push -u myorigin main` diff --git a/doc/install_pxe.md b/doc/install_pxe.md new file mode 100644 index 0000000..bfe7a8d --- /dev/null +++ b/doc/install_pxe.md @@ -0,0 +1,50 @@ +# Installation via PXE/Grub + +* **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp** + Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository. + Linux kernel and initial Ramdisk from debian repository. +* **Using your own repository and LinuxMuster.Net tftp** + Here you can use your own inventory and make many custom settings. + Linux kernel and initial Ramdisk from debian repository. +* **Using your own repository and livebox tftp** + Additional kernel and Ramdisk from your own infrastrukture. + +## Using codeberg repository and LinuxMuster.Net tftp + +### Modification LinuxMuster.Net server + +Create grub config for device group `lmnclient` on your schools server: + +/srv/linbo/boot/grub/lmnclient.cfg +``` +# ### NOT managed by linuxmuster.net ### + +# edit to your needs +set default=1 + +menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' { + echo -n "Enter domain join password: " + read adpw + linux (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux auto=true priority=high \ + url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/fvs/misc/preseed.cfg interface=auto \ + playbook=lmn-client.yml adpw="${adpw}" --- + initrd (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz +} +``` + +Insert host in devices.csv and set device group to `lmnclient`: + +devices.csv +``` +classroom;mypc01;lmnclient;F2:81:6B:C9:E3:EF;10.0.5.51;;;;classroom-studentcomputer;;1;;;;; +``` + +### On client PC + +* In BIOS-Setting: Set boot to UEFI +* Start via PXE +* When asked for domain-join-password: Enter password of `global-admin` +* confirm `hostname` and `domain` (you will be asked in network setup) +* ... Get a cup of coffee ... wait until reboot ... login (Logging in may take a few minutes after installation) + +## Using your own livebox server diff --git a/doc/localhome.md b/doc/localhome.md new file mode 100644 index 0000000..2fb47fc --- /dev/null +++ b/doc/localhome.md @@ -0,0 +1,64 @@ +# localhome + +## Description / Use cases +Sometimes a local home directory makes more sense than the home on a network share. + +For example, with: +* Laptops with Wi-Fi connectivity +* Laptops that are also used outside the school network (e.g., teacher devices) +* Devices assigned to a specific user who synchronizes data using a sync client + +## Requirements +Nothing + +## Activation / Default +To enable the local home directory, set the variable `localhome` to `true` (default: false). + +## Configuration / Variables + + * **localhome** + This flag indicates whether to use home on local disk. + If set to `true` local user's home will be on local disk. + Type: *Boolean* + Values: + * `false` <-- (default) + * `true` + * **localhome_logout_missing_serverhome** + If this flag is set to `true`, the user will be logged out if mounting the serverhome failed. + Sometimes mounting the server homes fails, but the user still logs in. + For laptops used in schools, it's better to force the server home. + For teacher devices that can also be used outside of school, this flag must not be set. + Type:: *Boolean* + Values: + * `false` + * `true` <-- (default) + +## Example + +* Hosts in group `laptops` will get the localhome. Teacherlaptops will be part of the `laptop` group (children-entry). +* All computers in the desktop group, except the PC with IP address 10.0.2.33, will have their home directory on the network (default).\ + The PC with IP address 10.0.2.33 also has a local home directory. +* Hosts in group `desktop` will have home on net (default). +* If mounting the server home fails on a local home device (except for teacher devices), the user is automatically logged out. + +inventory.yml +``` +laptops: + hosts: + 10.0.1.[1-64]: + children: + teacherlaptops + vars: + localhome: true +teacherlaptops: + hosts: + 10.0.3.[1-32]: + vars: + localhome_logout_missing_serverhome: false +desktops: + hosts: + 10.0.2.[1-32]: + 10.0.2.33: + localhome: true + 10.0.2.[34-64]: +``` diff --git a/doc/localproxy.md b/doc/localproxy.md new file mode 100644 index 0000000..aeff890 --- /dev/null +++ b/doc/localproxy.md @@ -0,0 +1,44 @@ +# Local http proxy + +Some clients encounter difficulties with Kerberos authentication on the HTTP proxy server. To address this issue, we propose setting up a local Squid HTTP proxy that operates as a systemd process in user kontext. This local proxy will authenticate with the parent proxy using the user's Kerberos ticket. Additionally, this setup is ideal for accessing the parent proxy from virtual machines as anonymous user. + +The decision to install the local proxy is contingent upon the value of the variable `localproxy`. + +Choices: + +* `false` <- (default) +* `true` + +The parent proxy can be set with the variable `localproxy_parent`. + +Default: `firewall.{{ domain }}` + +## Configuration / Variables + + * **localproxy** + This flag indicates whether to install the local proxy. + If set to `true` local Squid proxy will be installed. + Type: *Boolean* + Values: + * `false` <-- (default) + * "username" + * **localproxy_parent** + This variable specifies the name of the parent HTTP proxy that accepts the user's Kerberos ticket. + Default: "firewall.{{ domain }}" + Type: *String* + +## Example + +* Enable the local proxy on all devices. +* The parent proxy will be set to `firewall.{{ domain }}` (default). + +inventory.yml + +```yaml +all: + vars: + localproxy: true +classrooms: + hosts: + 10.0.10.[1:80] +``` diff --git a/doc/localuser.md b/doc/localuser.md new file mode 100644 index 0000000..df65823 --- /dev/null +++ b/doc/localuser.md @@ -0,0 +1,58 @@ +# Local guest user + +Creates a local guest user with home on tmpfs. + +The decision whether a guest user is created depends on the value of the variable `localuser`. + +Choices: + +* `false` <- (default) +* `"username"` + +The associated password can be determined using the variable `localuser_password`. + +Default: `Muster!` + +## Configuration / Variables + + * **localuser** + Username of local guest account + If set to `false` no user will be created + Type: *String*/*Boolean* + Values: + * `false` <-- (default) + * "username" + * **localuser_password** + Password of local guest user + Default: "Muster!" + Type: *String* + * **localuser_secretsalt** + Salt for creation of password hash + Default: "4ANAxPycC3q" + Type: *String* + + +## Example + +* Create local guest user only on devices in group laptops. +* Devices in group teacherlaptop will not get a local guest user, even though they are part of the laptop group.. +* Username: guestuser +* Password: topsecret + +inventory.yml + +```yaml +laptops: + hosts: + 10.0.14.[1:40] + children: + teacherlaptops + vars: + localuser: guestuser + localuser_password: topsecret +teacherlaptops: + hosts: + 10.0.20.[1:80] + vars: + localuser: false +``` diff --git a/doc/misc_clonescreen.md b/doc/misc_clonescreen.md new file mode 100644 index 0000000..9f5e8e9 --- /dev/null +++ b/doc/misc_clonescreen.md @@ -0,0 +1,56 @@ +# CloneScreen on PresenterPCs + +Presentation PCs have a habit of displaying the primary screen on the wrong device. Furthermore, the workspace is extended by default instead of mirrored. + +These issues can be resolved using the 'misc_clonescreen' variable. +If the login screen appears on the wrong device, this can be corrected using the `dual_screen` variable. +Furthermore, the display devices are mirrored by default instead of extended. + +If the cabling does not properly support large screen resolutions, the desired resolution and refresh rate can be set. + +## Configuration / Variables + + * **misc_clonescreen** + This flag indicates whether to prepare clonescreen mode. + If set to `true` clonescreen will be default. + Type: *Boolean* + Values: + * `false` <-- (default) + * "username" + * **misc_clonescreen_mode** + This variable specifies the resolution and frequency of display. + Default: "1920x1080@60" + Type: *String* + * **dual_screen** + Array with X11 and Wayland naming of desired primary display. + Type: *String* + Example: [DisplayPort-3, DP-4] + * **audio_output** + Array of audio-output device to be selected. + Example: [pci-0000_00_1f.3, analog-stereo] + + +## Example + +* Hosts in group `classroom` will be clonescreen PCs. +* Screen will be cloned and mode 1920x1080@60 (default) will be selected. +* On host with IP 10.0.2.80 screen resolution is limited to 1024x768 at 60 Hertz +* Audio output HDMI (default) is selected. +* On host with IP 10.0.5.80 audio out is preset to analog-stereo +* On Hosts with IP 10.0.3.80 primary screen will be swapped to device with name `DisplayPort-3` (X11) / `DP-4` (Wayland) + +inventory.yml +``` +classroom: + hosts: + 10.0.2.80: + misc_clonescreen_mode: 1024x768@60 + 10.0.3.80: + dual_screen: [DisplayPort-3, DP-4] + 10.0.4.80: + 10.0.5.80: + audio_output: [pci-0000_00_1f.3, analog-stereo] + 10.0.6.80: + vars: + misc_clonescreen: true +``` diff --git a/doc/vm_support.md b/doc/vm_support.md new file mode 100644 index 0000000..b6abed1 --- /dev/null +++ b/doc/vm_support.md @@ -0,0 +1,44 @@ +# VM support + +lmn_client provides scripts to +* create +* modify +* distribute +* run + +VMs based on Qemu/KVM in school network. + +## Requirements + +* For distribution of VMs, you have to run a `seedbox` with aria2 server (torrent server). + Repository with ansible-playbook for seedbox install: https://codeberg.org/digitalsouveraeneschule/... +* `seedbox`-hostname must be resolvable via DNS + +## Configuration / Variables + + * **vm_support** + This flag indicates whether to activate VM support. + Type: *Boolean* + Values: + * `false` <-- (default) + * `true` + * **vm_torrent_serv** + Name of the torrent server. + Type: *String* + Default: `vm_torrent_serv: "seedbox.{{ domain }}"` + * **vm_uploadseed_pwd** + Password for upload-seed. Used for image upload to torrent-server. + Type: *String* + Default: `secret = "token:topsecret"` + +## Example + +Enable VM support on all clients. + +inventory.yml +``` +all: + vars: + vm_support: true + vm_torrent_serv: "myseedbox.linuxmuster.net" # default: seedbox.{{ domain }} +``` diff --git a/doc/vpn.md b/doc/vpn.md new file mode 100644 index 0000000..f7e6715 --- /dev/null +++ b/doc/vpn.md @@ -0,0 +1,46 @@ +# VPN + +Provides VPN access to school network via + +- Wireguard + +Which vpn method is used is determined by the variable `vpn` + +Choices: +* `"none"` <- (default) +* `"wg"` + +## Description / use cases + +* This module provides a NetworkManager Config with valid wireguard credentials. +* Private/public keys will be created and configured on wireguard-server. +* After VPN-connection is established, network shares will be connected and printers will be installed too. + +## Requirements + +* You need to run a wireguard server. For installation see https://codeberg.... +* The user, running this playbook, must have access to the wireguard-Server via ssh. + +## Example + +VPN profile will be created on teacher devices + +inventory.yml +```yaml +infrastructure: + hosts: + wg_server: + ansible_host: 10.0.0.16 + ansible_user: ansible + +teacherdevices: + hosts: + 10.0.14.[1..75] + vars: + vpn: wg + wg_endpoint: "203.0.113.1:51820" + wg_allowed_ips: "10.0.0.0/16;" + wg_ip_cdr: 24 + wg_dns: "9.9.9.9" + wg_dns_search: "example.com" +``` diff --git a/doc/wlan.md b/doc/wlan.md new file mode 100644 index 0000000..f718f65 --- /dev/null +++ b/doc/wlan.md @@ -0,0 +1,190 @@ +# WLAN support + +Supported modes authenticating via WLAN: + +* **WPA-Personal** (WPA-PSK) + authentication via preshared key (psk) +* **WPA-Enterprise** (WPA-802.1x) with **EAP-TLS** + authentication via client certificates (eap-tls) + +Which method is used is determined by the variable `wlan` + +Choices: +* `"none"` <- (default) +* `"psk"` +* `"eap-tls"` + +## Common Configuration / Variables + +* **wlan** + Authentication mode + Type: *String* + Values: + * "none" <-- (default) + * "psk" <-- set to use WPA-Personal + * "eap-tls" <-- set to use WPA-Enterprise with EAP-TLS +* **wlan_ssid** + SSID of used WLAN + Type: *String* +* **wlan_enable_on_boot** + If set to `true` wlan will be enabled on boot + Type: *Boolean* + Default: `true` + +## WPA-Personal + +### Requirements + +WLAN with configured WPA-Personal (WPA-PSK) + +### Additional Configuration / Variables + +* **wlan_password** + Password of WLAN. Only for `wlan: "psk"` + Type: *String* + +### Examples + +#### One class of devices with wlan access + +inventory.yml +```yaml +laptop: + hosts: + 10.0.13.[1-28]: + vars: + wlan: "psk" + wlan_ssid: "devicesPSK" + wlan_password: "topsecretpasswd" +``` + +#### Two device classes with different wlan access + +inventory.yml +```yaml +laptop_students: + hosts: + 10.0.13.[1-28]: + vars: + wlan: "psk" + wlan_ssid: "Students" + wlan_password: "topsecretpasswd1" +laptop_teachers: + hosts: + 10.0.23.[1-82]: + vars: + wlan: "psk" + wlan_ssid: "Teachers" + wlan_password: "topsecretpasswd2" +``` + +## WPA-Enterprise with EAP-TLS + +Authentication is based on individual certificates, which will be automaticaly created on the radius server. +Every devices gets his own certificate. When creating new certificates, the old one will be revoked. + +### Requirements + +* You need to run a freeradius server. For installation see https://codeberg.... +* The user, running this playbook, must have access to the radius-Server via ssh. + +### Additional Configuration / Variables + +* **wlan_eap_ca** + CA data for certs and crl + Type: *Dictionary of Strings*Keys: + * C <-- default: "DE" + * ST <-- default: "Baden-Wuerttemberg" + * L <-- default: "Reutlingen" + * O <-- default: "Linuxschule" + * emailAddress <-- default: "admin@example.com" + * CN <-- default: "Radius Certificate Authority" + * password <-- default: "OtherVerySecurePassw0rd" +* **wlan_force_issue** + Force to issue a new certificateOnly for `wlan: "eap-tls"` + Type: *Bolean* + Values: + * true + * false <-- (default) +* **wlan_eap_ca_crl** + URL of the certificate revocation list + Type: *String* + Default: "http://radius.{{ domain }}/radius-ca.crl" + +### Examples + +inventory.yml: +```yaml +infrastructure: + hosts: + radius_server: + ansible_host: 10.0.0.15 + ansible_user: ansible +laptop: + vars: + wlan: "eap-tls" + wlan_ssid: "devices8021x" + wlan_eap_ca: + C: "DE" + ST: "Baden-Wuerttemberg" + L: "Reutlingen" + O: "Linuxschule" + emailAddress: "admin@example.com" + CN: "Radius Certificate Authority" + password: "secret4radiusCA" + wlan_eap_ca_crl: "http://radius.example.com/radius-ca.crl" +``` + +## complex example with both modes + +We have three groups of devices (one with psk, two with eap-tls): + +inventory.yml +```yaml +all: + vars: + wlan_ssid: "WLAName" # teacher and staff are using the same ssid + wlan_eap_ca: + C: "DE" + ST: "Baden-Wuerttemberg" + L: "Reutlingen" + O: "Linuxschule" + emailAddress: "admin@example.com" + CN: "Radius Certificate Authority" + password: "secret4radiusCA" + wlan_eap_ca_crl: "http://radius.example.com/radius-ca.crl" + +infrastructure: + hosts: + radius_server: + ansible_host: 10.0.0.15 + ansible_user: ansible + +laptop_students: + hosts: + 10.0.13.[1-28]: + vars: + wlan: "psk" + wlan_ssid: "Students" # ssid "WLAN" from group "all" will be overwritten + wlan_password: "topsecretpasswd" +laptop_teachers: + hosts: + 10.0.23.[1-82]: + vars: + wlan: "eap-tls" + wlan_enable_on_boot: false +laptop_staff: + hosts: + 10.0.61.[1-20]: + vars: + wlan: "eap-tls" +``` + +## example: Force issue of new certs + +The issue of certificates can be forced. + +Force issue of new certs for hosts in group laptop_teacher. +If there is a valid certificate, the old one will be revoked and a new certificate will be issued. + +ansible-playbook -i myinventory.yml -l laptop_teachers lmn-client.yml -e "wlan_force_issue=true" diff --git a/inventory-sample.yml b/inventory-sample.yml new file mode 100644 index 0000000..5cca733 --- /dev/null +++ b/inventory-sample.yml @@ -0,0 +1,153 @@ +--- +all: + vars: + domain: "{{ ansible_domain }}" + security_defaultuser_login_disable: false + kde_desktop_pkg: + - akonadi-backend-sqlite + + + ## Proxy configuration (see: doc/localproxy.md) + # localproxy: true + # no_proxy: "firewall.{{ domain }},server.{{ domain }},.{{ domain }}" + + # kerberize_uris: "idam.{{ domain }}, server.{{ domain }}, *.{{ domain }}" + + ## Configure additional apt options. E.g. Apt-cacher? + # apt_conf: "Acquire::http::Proxy \"http://aptcache.{{ domain }}:3142/\";" + + ## Configure NTP-Server + # ntp_serv: "server.{{ domain }}" + + ## NFS-Server for additional mount. Comment out or leave empty to use no additional NFS-Server: + # nfs_server: "files.{{ domain }}" + + ## List of print servers. The order of the print servers determines which print server the printer will be installed from: + # printservers: + # - "server.{{ domain }}" + # - "print.{{ domain }}" + + ## PAM mount nextcloud. Comment out or leave empty to skip: + # web_dav: "https://nc.{{ domain }}/remote.php/dav/files/%(USER)" + + ## Local mirror for mscorefonts. Comment out or leave empty to use no mirror: + # mirror_msfonts: "http://livebox.{{ domain }}/mscorefonts/" + + ## Local mirror for libdvdcss. Comment out or leave empty to use no mirror: + # mirror_dvdcss: "http://livebox.{{ domain }}/libdvdcss/" + + ## SSH-keys to deploy: + ## passwordless login for default-user (ansible) + ## + # keys2deploy: + # - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI........ admin1@example.com' + # - 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI........ admin2@example.com' + + ## Use grub-mkpasswd-pbkdf2 to calculate the password hash: + # grub_pwd: 'grub.pbkdf2.sha512.10000.EF6E2F4F758771751EF4A8A85B1F3F25F35A3AF859DBF0BB8153D9DF6B48D27A2DCDF4ECDC0711D2A93DCBBCF2C4D6FC69D02E1179AB14B62750BDD502C81C95.442C213A064A98E5FF089F3E647C6481327750127D310ABC39596176233C0CE75311EE818EE7F77BD961BBB723A15F853DE6DDD3BF30C7273769C7AC2587CD28' + + ## Installs VM-support (QEMU/KVM) + ## Additional infrastructure (seedbox) nedded. See: doc/vm.md + ## + # vm_support: true + # vm_torrent_serv: "seedbox.{{ domain }}" + # vm_uploadseed_pwd: secret = "token:topsecret" + + ## Additional packages to install + ## + # extra_pkgs: + # - vim + # - mc + # - tmux + # - debconf-utils + + ## WLAN configuration (see: doc/vpn.md): + ## + ## WPA Personal + # wlan: psk + # wlan_ssid: devicesPSK + # wlan_password: "topsecretpasswd" + # + ## WPA Enterprise with EAP-TLS + ## Additional infrastructure (radius server) needed. See: doc/vpn.md + # wlan: eap-tls + # wlan_ssid: devicesEAPtls + # wlan_eap_ca: + # C: DE + # ST: Baden-Wuerttemberg + # L: Reutlingen + # O: Linuxschule + # emailAddress: admin@example.com + # CN: Radius Certificate Authority + # password: "secret4radiusCA" + # wlan_eap_ca_crl: "http://radius.{{ domain }}/radius-ca.crl" + + ## VPN Configuration (Wireguard) + ## Additional infrastructure needed (see: doc/vpn.md) + ## + # vpn: wg # only set on hosts/groups, which will get wireguard profiles + # wg_endpoint: "203.0.113.1:51820" + # wg_allowed_ips: "10.0.0.0/16;" + # wg_ip_cdr: 24 + # wg_dns: "9.9.9.9" + # wg_dns_search: "{{ domain }}" + + ## Reporter service + ## Enable automatic reports + # misc_reporter: true + ## Server to which reports should be sent. If you don't want to use reporting, this can be empty: + # misc_reporter_serv: "collector.{{ domain }}" + + ## Additional roles to run (see: doc/custom_roles.md): + ## + # custom_roles: + # - fvs + + hosts: + localhost: + +laptops: + children: + teacherlaptop: # teacherlaptops will get laptop vars too + hosts: + vars: + ## Activate WLAN and select authentication mode (see: doc/wlan.md) + wlan: psk # (none|psk|eap-tls) + + ## Use localhome on mobile devices + localhome: true + + ## Create local guest user + localuser: guest + localuser_password: !unsafe Muster! + +teacherlaptop: + hosts: + vars: + exam_mode: false + # vpn: wg + extra_pkgs1: + - plasma-discover + - nextcloud-desktop + - dolphin-nextcloud + sudo_permissions: + "%role-teacher": + - /usr/bin/apt + - /usr/sbin/cryptsetup + polkit_rules: + "role-teacher": + - "org.freedesktop.NetworkManager.settings.modify.system" + - "org.freedesktop.packagekit.package-install" + - "org.freedesktop.packagekit.package-reinstall" + - "org.freedesktop.packagekit.system-update" + - "org.freedesktop.packagekit.upgrade-system" + - "org.freedesktop.packagekit.package-install-untrusted" + localuser: false + localhome_logout_missing_serverhome: false + wlan_enable_on_boot: false + misc_avoid_suspend: false + misc_pwroff: false + misc_pwroff_idle: false + misc_reporter: false # privacy for teachers + printer_admin_group: role-teacher + fvs_remove_discover: false # Custom role feature to give teachers package store diff --git a/inventory.yml b/inventory.yml index 845c75b..81076e7 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,152 +1,649 @@ $ANSIBLE_VAULT;1.1;AES256 -63633264306266356564663836343363656536353265653630623231313232316232373364396234 -3236316538656536366265323139396261613363653261620a336663633534646530613832646330 -37636232373730363966333835333935346534373737373366333137393336343333386638373236 -3761336362363136320a313937373361636337613464383266643763356436623163353164373133 -66653337346637633231663433653465353963656561633037633131643931363439323737303636 -37313630326337313333633632343232373562363662396161343866393031383564383239626461 -35316334333464393064643534626166333264663932316533303963343038653162656232656165 -33346162393633633736623532386333653464646335626236356466343439633130653836623462 -34613337623034313834663231343830623836313037313435306633356131326235346364643234 -65646361336234343937653139303034333438626238366531656230653639373636346565643035 -65306130386331643037633165613635393433653537333238393365343736623932363432663166 -36376266313936393931366333303863353033643962303861393536383966343932373233356234 -64663834663965373038333265616532313161656337613035393736653864393562656630326561 -66343634383139386133326463633333313164303638313636663361373036396235636332323563 -31383337636535313139636661306430396335323237653364333838616434363931333861656262 -35366431646161396234666135343663343266626538363833356666613932303766373238363030 -64353666363662633836383135313738376235653565323039323962326665323334303731393535 -35303161636133376631386437626432363463383536343530396533316330393537643036346438 -34373939373938356466363261643936323964313232313331623237643564326239353861666636 -31363462336137373365333366383635303639643263303633386637303839363531336133353035 -66643039313764353935346133396233373735626163383734333736383062663038643464323137 -30613239393864333365663331313634373338616238303735646532386135336664623635373934 -34633366303736316438613733316230343039373434653565313631623931646363333139363332 -66353934396632613330313061336336626531656334633237633536613138393938353364623137 -34636231643565316435356334663736326463643131393135636366373338326233636564326165 -31646632326430353036363163303839336638393962373665346237373831393639376231396362 -38366438656236646436653634356235386238366233666433656161316636643035353165373837 -30653036346236306162626536393937653235306236313036633135653139656261666361316336 -66333835343735333937396362353330383139663635386236373531653837383231356535326330 -64323735383833306463636461373061376133366261356166626466656365663730383133353062 -35356136623464656662613438313535316466323538313438313963383532616232336564346534 -64333736316238393232623763306539373034366566306561336161336630613133633762636131 -34653565353031373436666363613164343964626164366537646438363965396366623765383333 -39656630383564623735666663643836363963356563303137343064373434343336663536353562 -30636165623032343136363534373761626638346432323661653730633264323837356163656132 -66323533316130356364353536303536613365663536346431306634623938613531373465323738 -33336132663431613338653432613863323665393532346130313332316366633439323664363361 -61323233303732393637303366336336626638353931663365326266386632666235343164623336 -65653861353133353661646463383133613733653561333136656665333338636331616262346661 -66383862323664626632613865663933313338633839313864303366306631613565633734353564 -38333137633933323538313632393233373836653365333531356336616265396163353365356162 -66636637646436343834313165363830346339636532343362333133666437323862636439323438 -39363934623766666464623838396465323539366433653334636365653665356237373235646661 -63316135626430363637383637363366313563326165393263393539353738313936373365346364 -62393931353138656633343933313337306266623834653038383437313238643530333130623666 -37653532333966666564343131316463383836373831393964333664653538616662383733623462 -31393131666662323236623838343630316434303961323663346262656538313464393564323132 -39623037323334613632666536366363306139646431646465376535393331333366333537343561 -66333862353036393930623632313737333062363464353437663966313438636261306165353032 -32306533363463316661653334306261336236323366353037353461613632633934333734373038 -37356230613336353938633562343632633031616635343461316333373062646137396163653235 -65653661386637376330313438323630353432353064383263626339333262363566366633613531 -66636237363265313266323038376163356437376532656362626436366235393335646165323061 -61663162313463613431393762633165653035343061333035333439616165646237356633323631 -65333861663236633064646563346233653231656430623564666265363834633635336163313864 -39646538613164393161306137393065623935643937393935313438363434623538373963663461 -39636530373739306333346132636533633861363530613437663632303963336634376639366134 -31323032393135336136636338366634393236303334633664343865613839663966373339373239 -61643765393539626337303264373133366265643438333935666633343738653761626437323861 -38633030653931313762333764316134393566306435303338623832653035393766663539663164 -64643136656338343334396234363139363337323033333163323261356431356362636435363838 -64333866313031333937353034376337346631343338626364343034616635633138313039613464 -33336439356438616234306666646132623230646161373938656239323134653435663734653235 -64646338343161363364316639336538646439313939326337346339376466666136333165636161 -64393732313538373334363431363836626364643834333265653135653035636330656464613731 -36316266316430336166393564306462363232336335626335616165313734633466636534353035 -37626637633534656235363530633866633062626537383935313763373562633737313032643462 -61353561366639306437626332643633626463313663366561646331373735393032616332326562 -36626266316236363930616662636134623865356632303465316266616663353039616261396663 -34373037623763393263316166343131643531663134616165386636653562336135346333326461 -39623964656137323439316166666132616561666235633439326464383937653738336435646134 -64383661363962333838376135323864633234386662643864336132343231366266363632313666 -31356339633938316636616537633335333564396631336238383063383164393238656438646131 -31373164313062623930636438346437623736353830396533343730366162343164393661396263 -63383837633335366534343137663634646631366234656365383235353532626163393537376537 -37643661666464303133313362366230313132363738643765613735613462333861633736643664 -38303537303338626139323566306536616236353563613862323435636165373434316432663864 -39373033326134626530663932623230396531636433346432653262666430653866656330613861 -64646265363562623663353532616663383830383633366462323235383966383263396535363536 -30633266386339656230326365303330376138313432653132323138333863663961613538623566 -62636565613130633166656639653264376461663737356162336331313834613662353430656431 -35313237633837623562396539623336313562313765383035373036333233356461366336383838 -65616164623762303033633130636364666630633465633435616666313031343863386261373033 -39623638313761393434333431646638363062303437373765666435386531343339323862666132 -38666635363431613530313766386165633032643836663861653434656231383333666633643266 -32333336383334303763323237653934313032643261326233376335616230386234346161353431 -63643733643634313133336332663933656363393861633831346261353334376464633562326534 -31663066656130363965656361626464613463323764383036623063386166653839366637376135 -34646466313836353234383762376165356439626532646430313730326166313839356263633966 -39643731613363613564356337653931626666363337356138333335393463393865666636393532 -33353366633465303765373936316334633331323930653235313231343039616238663433613365 -31373866666466363965346637656435383433626563313330316132376364366532316331343534 -32353462646536343538346130383139663334313331323935396537313835366161613539653164 -38666265306664623666396530383464653661356562613037323362303361323537326239323661 -66383230386437656132653966333062343536623861373461326333646266366430613563306436 -32623132303966323638643639343537643135396566323630313038636465353830636439343465 -34333136613435653037303437646439623035643539623663633561616137656138373063653662 -35643830613235663931386634626463333331313864666662313534626464663635616437313061 -66373039396333336639623637353839656333386635363733636636306132333130643131656438 -64333561323464333631356465393665613635356265343764346531613538633137366231343032 -30323832346266653238633432383334393661333737383761303238613734623534646232633562 -63643066663363306432366662643362663665313431616665653239386666623864633639383431 -37393630636363303438383665326663323561653335396238353138616533323965353031336465 -39383132666564333661383831323539313334393632653865353662373439663438656534653133 -63353562373637323436316530666639613637353866633931343536306230323765643335376563 -33626661366339663161653334666232626464636134623537336237663662343833613564306366 -64613132313038663761626562323832343937316136363666393438656165653666326463656565 -39663032656537313563346138323731626562396566646535633830636638643463323334356365 -65396564633530386237626664353734366336363339336162373139373036666339313531316265 -63313266316238383363333262373038653062653561656466643837343863633562633530366433 -61333663366361306233353463646636386335343131396461613562653264306432326663313436 -37656538356534393065386263373264623664333738306363373465323663313831323665323862 -37613366313361376137363663393334623237326663383766663736333133353931356264663163 -65653439356463393938626331323835383232386638323531326661613433343833343130626531 -61656461333565666633353739626266653138316163326565336461333934376235376639623338 -66396662323338663966653731386633623331626339653664383366316466653661366630333966 -63343930363565343464373731386237396363353562633634663935373733373663356537333134 -38623362633936616533646535626533376366663535626364646536333333313664356532356130 -33366164303836643730656439386537633761653032333061306261646364373961323334623831 -35393832323830336633303030653963393532376466353966333039313661373263303136636534 -65623830646662396236626263313763623833346236343361373465633434366131326362663034 -64323161383832663765636566363932613434353031653031633262363233653630343736653436 -35333435663562303135646531663033373538376366323638333031653962306563383733393235 -64333763663163306537346638633763363932336337633039633865633931656136356537366466 -66373639303037623066383239383335643664666362303364396465633361396536383133653939 -31336438646531376364303731313430396464373432646234356637663966333665636136653761 -39396138343439353565343139643165313864643132386633643836366564636130623666303933 -36623563326434656439333962336132343662663936653866316163633339336361376633396530 -66356639366330613335353633613831303535633538633233306666383761633864386538666266 -61383861393863626434613333633430396636666433306533623432356464633764663433373931 -38636538313830366438313964666430353237656639633763386332613636636462653634343831 -62626638633863353165366438656465376466633966356133366263636666343632313761653766 -65336461346531356631376462623737316538373363353230333436303532333835396435646634 -39306438663436636532373063643138366531313936306135666466333765646630336532313238 -64623530626334303638626364343864613164353732386262323439343735383164333232363434 -34666165353366343566656163373738663065643132303734623533326634346238343630643838 -64393833646132613761356334306539303233323466336533363938313633343834356239613034 -64653935373761396331323936616334303561613762623733613637653031623564366538373630 -61313733333863303630633036353535393532326134636139343532396163346537383665663838 -61386637353566306134393430366633636437616565343465393333306138376462633131623332 -65343035653066396533336238393365663432393537323431366532353232333036353662386363 -35313162646432626632633032636162343764343463366236386438323131623766363937336436 -31333332373731643164626137643162393964393334643237393133366237323562623839356534 -31343163656366616638663265323939663765666563333239306563653265343765613432633430 -63613231326333313437313166326236346538656236373933313262616334656264376430626263 -65396261386439646562343235326630353265356362666131316664343430343534353062613232 -64313234323430396139373331356434363663646339653566303638623839383330623630613662 -33653863333534656665313362326338346338303434363932323635666463323536343865386235 -31366134643263303630653534306364616466323538626335366231333762643961656165316534 -34626532393730323034663434386234313939336262333266656134613938613433396337376531 -343631376663336639636437653165333163 +62386339393366643763383339373037363365316132633835363530353330653839303732353335 +6231343438366132343632383066386163336532373633330a626636643034633261373662313138 +37336632633465646638363763306436333566376133656237373731613539363530656266336339 +3339313039373766360a306631373166663330373233343762613631636432306333383265313639 +65656638306665313862316137383939393336303633646463316536646162323563383263623637 +39323134626333333661666636326636313263396663653864643262373733326535653764313065 +31656135313263313535386364623237376336616430303737306534333839326531383964636264 +36336164656636366431346434643536663361313634386233356132633133666237633037623439 +37356136383063356530336230373231623062306163646235633633623439346634636161623062 +30383438663361373938653630653562366436303235663963363631656630303165386465396632 +30313639633364633439346230666264363762646264396336663934346533353562636437316461 +39636665346565343437303032313761633536633266653866643235316464346533666536316664 +39346662373338356639613238626237353737363533396330653239373033393665663263353165 +36626265323266333337363365356538393933616266613965353662323263353832386264363337 +35656631656365366132303465306432366235363931386238633265656162396632656463316465 +66363734663233663866656263353631323762343665353535356561313237313036393138636163 +36386562333339373832383364373465323862616661343865646662626331646639646164313439 +30333239346136303432323035626135623937353862646562373336636134633034393837656164 +31373932323135353836646236316163343966643731343831333033386338393737303264626134 +63373862383732663462656639643335613232633839386434633832636534376133376432643638 +31353136313538376531613239373965303730323536393039633861393338323861306662313639 +36366636396364386136663865613564633566666262656538373637383133376333623934666262 +35373134633133383535353436613932333466383961313361333730303164353463633531356561 +34626335653335306435333364636235623862616266353961313138663032326338343665343035 +66393562373835656634326164643638623364333239613363333138303938616337623366346663 +37343662663239396666633038386636633963613934616461363664333631663663316531626266 +65636661306635333839393835363839383763343164616631666238373737666366323232346234 +32626630626564353433393463626566383331343365396336646239303462633665643439633538 +36383365356435626237663630353364396166653365653363663362663838376532666236316663 +31393565363962316632663463313063333331316564383031363939646361363837623037626630 +32393761353066316663316165666434313766653666653537326638353165346438663565323836 +62383434616266366336363537376166663261303834353531323835626463326132326432336338 +39316464373362646333663763663334363035393336366266356639393735373563616130343931 +36383862363162613161343836313737363663353763323831306561313931343835316565326661 +34383236626335316266646362333535626338303962363632373663653136383138336263393435 +34326638353762343132393537343166643630666433386538326634613862313831633361303732 +39363862306562313765303066663932636531343935383466363738373039306135646162613164 +39386464623439356635366666323433303235303866653962363932643964383432323064636334 +63356231623139663661353364666432323335613738346130343536343633396333373963636234 +33623734323966626532663030646362323765663661383364613734663066313363653566303965 +64313136336236346430663636656634653039626165613631636532323164323330333263646366 +65393337353136396533393961613738336366313138373432306263393362613735336137393763 +37623365616139613638623664333039346533646638353538346464633465663634373463653963 +31366632306437616435356339633561346237373833356565663139363534373037626566356339 +62363739653934636635386465353163346263353034343861656135336435393930663561396634 +38393335303633326330373066623135336530633032653537366631343961346639656539666231 +62326134333364313237373035363637636265343236383931303438356463366361363936633964 +36393865626137353064613336656637353039353061353532663230396462363431393636663239 +61346565663764363666393034633239613431626133656134393661393435333334633736623730 +37656334656131623038363761343863643966313730316330363061326336353839623833643635 +35653333663239363436326131663537613735616632616165316435666134613862643265383638 +64323637623364313564313730643766376138663436356530663236313133353161643336663163 +34353735386433363362393336366236303132376235303163363231396266306462643261643730 +64333938353166333664383865616262383935666531633466653832383237623566353738376137 +63393937656235336432343163313933303532646432663437383635386164303039386535393334 +32356462626633623036616531383636633533346537316132623438663365373966343831333061 +33613431383038623162656262333031386265613561646530653737363339383631303137306131 +65643961393138373137613637396465346432333266303838653935373061316532636466316439 +62343863626564656232316236373735303734623933353634643337653036353639643139383462 +36616134373065616162336235353564663735393332636166306133373336373139643466653262 +62373735303130376534343930303532316332313737656434666665346133383534343066623634 +39383332626337323061373530666137333133653237353131363261366664623363393864616436 +32356238343137336430386262633962626466623438323437376566663666623236333432316532 +37356138343132393362373266396631353138373639363062623135666631383966313761303635 +33366136303632303965353634626334653533633737313032383036303430656662636230336137 +65653163326631636437363436663163376465373566366665333635326437376438633665336335 +62623666363435396561346436383433633936383261383639326535623861626539653833633738 +35626462383733363162616239343261346239303964376163636433313663353831633838396561 +30333331363336663336333937306437643332643332333061366638313837383532373036653461 +38316233346532633266373438336563613835316634396664663738366138613039616338353666 +62396166643461623136656266663637343862633237643665386530656436393363313134383639 +62386139663035663363653763366139396632656639623065383466633939363433393339323664 +66316138383238313562396462633731323037366461616434333865643363653339656364633265 +33613234613766626461366430343663633864363536646664323230323338383130306633613165 +33336133363466323062363961316632643133303962646230316336623731616230353932316562 +66303565346534363030323763336562353061633230373230303465336562396463376464643637 +63333137666562363135303264316332323031326638343032313934626663373362613133646334 +61653130636266633034383538636236313033373334613336356533633936643933336365346133 +37626263623035646232663433333532623031623462386336383032653735333335633931363733 +37386435343331393133333937626431303330613261396237306262623563633632323936316535 +65353638396430373937393536333565363830303333373863313762343465613861383262393366 +30633261326638383538623662653839393130323539646165646439613039396135656161656532 +65313662613533336161306639663131666132313037393338303261636433646434633761376538 +62626135633733323063316230636534393334336634643330323037393566303838336137313165 +37636632656338383664323264636132653432346164323533323739623730343937633938353735 +62313035323830303964363665313235313066336330336231613833316138326234393331636166 +37383731613537333464303431663236393933656462623165356335623165616661373665326235 +30333162636437346465633031633734623366356466396262613139623262326631666638326635 +32373631633234323365386532396561613366643139613539323266653130333537643465396563 +35346638326265343564343733303535643230663238336535343937626463343537653666663030 +33663563653865376135666633396164373332326336313130336661633136613233356237666137 +65306431636535356531333566303065643065653963313763393066353630363135336365656333 +63636239336264613161656135303633636336646531323534623063333439626331613138363239 +64656262313936616161326564663632653037663430653635356533393134663331353130366235 +38366639623662663230343039353861626432663933633137313238633332353739396436373633 +37353236363164306130326662346230336135663861346532383139663362656365646430373038 +61353932363561656537633534393430363236383566343839646231343730633864613036643530 +36633534343164376466336161333833653136376664353661346436353233616430396230386437 +64393430623864646334623137343537656563313865323336643064643766633035653265316539 +62636434653931613337336337383066373235653335656161656438373165616561323765323931 +31353661373532626231656361623038626361366632663764333764663737363137333732613234 +62376437393637316663353739333935343866373164333364346165313632313639636139356535 +38343639646362636635346634363064386636623635663536366461373431343362653839383138 +34323737313832343963366536666234363439386337353838323233376464646362343737313665 +36643237316238616265313332303162383033323363396330303766313734353563353133316530 +62643032326237626433363932666164336161346532646634363564326432396637346665636637 +36623561633861396439623835376434653738623862613333643162343362613865323363363434 +32633638306438653638343239383137396530356564356338623330303661663630656639666461 +62313232343461633636336538326537323266666466646261633336393464306438653136613637 +34336133623361336563306462373963613336383265646637313139653765656433346238386231 +31646362353736646431303937633033386435316336323062346235323232383466313566636162 +61366430313335313161333163393164353530303938386435623830353962373831393235616531 +31656565633534666164303532633235306133616536646161393365616231383866326635376630 +38666363386232633865366533373630356139393030626230653834613230346664383734616336 +39653736633237303161306632333138646633356463373063663064396561613162663138366339 +33326235313165343866363234353336643934656363383464353036353138626638373362393263 +36326438303366623137383530393434353933326163356634333837653830363037316565626466 +36643339376262386430383530343934646361303831633863653765303530373765336531326535 +36646330366635366339303731376662623366636163353738646535363363326437623439336466 +39373861323738363734613032383136313335306462386436633962666139366165343263616338 +64306536393966613235376264383463313763383161343634336362393865373865383366313839 +65623761626166366437323234373130393237643963376235316535646166326663646335353036 +62366562386364343734313261363636636639633639663830666130613833383766316461613236 +37653030326661623838643861353339353562366537346535363065356235393963376331623064 +36316464626439353464393638373963326333373037333761663239343431626563313735363031 +33613663613038326465623462623565343963333064623464313039376332323935353736616262 +66646161623564316439666431393462633463633432643763636535326538356135663535383734 +30323063323361376165626436633632636234653062623337346562386338663733396532323331 +61316539393566306334616435343665623931323866313636663033663161383964646430663263 +38663833303063356637343130323362313734646564633261653934666665376661653033373934 +64393934616465383964353464336136636436323563366562623839623862366332343339613334 +63373063656663316138653939323165383735623263646438376533316638623734636261663035 +33636465396431356334383063633866623063316163343262623831616137643165366564646532 +65303033313137636562353238663564303034393166313864353330656335663233643763626239 +35346334386130653462343531336431623639376165653263373539316163383038336636613136 +30626137666133623063376333646134643536653138333464623930323931613461366465633437 +32386531323739343363373737326263323836333438356133613065306633326131343838333363 +62356331623163393230373838383866323063633739313339353839336232363430323165666531 +34316231376232396464356436326165616266323430313632393362313966376563613534633339 +61346532386537356262633936366533376239616531373133353633336235316534363436393238 +34373232383665373539346664316463613962383961386530323539313538306165383038333736 +31343463373938636630336364653931343931363461663261373333363336353438613266333232 +66316333613134363630366632623861363135373335613837653937666466623163613231376431 +61623964353534316464373737326134666538393662323663306563633430616363353833373131 +61323563653235646139623139303162616235323664613463336364326638363762653665666433 +30656634393965306436616261303330313037373030353266383833326539626263326462363833 +36656538663733313533653864646232333934333031363433613839323632333166313162646461 +32653935393738646163343263633563333132616436613930613038313462633735636131653265 +64663439323665313130653931623564373737616632386338336465363564373233616466393934 +62373763326533343830366438386430306166323834646362313838313662386637613961643138 +38383362633730353730333335316439663631396430623135313565313431646465336631613666 +64316638646531356563666631626663383939396461313631366462326161643730346436633734 +63626633303336626137333565306664616363386162316264636331386134633461636162333835 +66326139393733373262343537323136633233616331373730653966353736613538633430643264 +33623731366330323161643230393635646366623139326534353561616632636338333232386431 +35353539333831613064626165386536636664373933633833363736613335323434383663336561 +34616130656232326631613835646131353936326631396334663335386236653066326564656238 +33623065303039666461383864323031313737316565366133326136333138393731653731663036 +32663135323464653030626430303439353030393865316266383164616233613039613032353130 +37326430373439363631323061333431386430613361656439303734393730326264643731326638 +37343836393439316330653432303633303439623337613336626662323338633535346563343938 +31333963303866313763666436653265306164633731376432663634623131613166623535656362 +64643232383863633261613061373131313933626666643631666238663931336566343561333439 +66653939353665363065656631323130326664343464303338333161623639383962356538623237 +33656337323733353738353034636138656138373762343336316336346264393434306338336136 +66643966336130346263643232373334626433326334633363616337343466313438343133366637 +35336561353531306164316639643262316235383631626636633133343837663032343032613362 +33356330343833333438663465363364653633306134646537656361383864356461393963313666 +33316236326665346233653331663132313531663263623762393039663365303333663231373262 +63643634363762393863303739626162636131366564623333373534316461383861646332373532 +61343736396465646538363765653864626636376361333935366536343133666432323530376333 +36333664326538336438323138393561616536343932363733316164316133656631333233626562 +33376234663863623365373365303936376164373530653839393631303732356662663536633135 +36326439646465613363633233633836643162333164663266393161626231393138616538643738 +35303532636532656266623434333162323230646636366334663238613733326237636232623763 +37643066613361313436346531373835343131613061326366643638396633626261303630623338 +32313632653336316531333065343830656365306430623565393935333065663537316130633936 +66376231626239383165626536626564306331623935336331666662376264643765396464323135 +38353438613435333864326633326530623036396665313762613865383365366137303166306436 +35646238306262613432333434346639393939333264656530303637393566633934633062666661 +62646537306132663164643663313138646639363131346133616366313137333965396137316433 +31613439613433383663663666313237613336326134343437373637363038643332376532383339 +34663735386235313532633431313630366537326135366132373063333035613939363832336433 +65663230626536666565303031663062356639376538396531346263346139386436633434623363 +65323462393138313932623239373132326463323830616237323665656437336562333666396366 +30313632363138666534383631313366653532336238303036623235303866643632663335653066 +32616363326134343038336431393436326565343732646438333336386366383066346231353833 +61363565303737346561643938666133363565383632346465656335363864386236393432633832 +34663863393063656562623134316235366536663638653563323465666566613464373666376530 +37366364633537666231653065366664646632393638663535643931633264616431626366626563 +66656561376664303838653437306433666131323761323639663665376262386564336363376638 +32343661326138653734316161356130313636616434623434613765386538366131353036643532 +30353237323831373562376332346466366437643165633738623066636563393036623765376639 +38303135306563356533663238386233646636306266353034343433383830383330653032663130 +32313932303338646637363762653232613138373665396436336264353534623633616138383235 +30373433626332653032343937653964373161343462393139336235396439303739346330656166 +31643936333139656232353932326531633566363366306466666137623832313435333161366331 +63333432383034396439323466663235656536663831643035626332373234643837666630626332 +64363531306531393737666230363631336666366536363464353266303633663563316234653634 +62313135346639376366306463383837636531353564306530623134373236613635303132383263 +32326663376138393633383132643964656365633966656231376439316165353630623764326137 +61303234646566343863653130343738373331373433353732663837326334633530666636326434 +31336135613431326131353864613331643137396661333566303632336661626134666565623133 +63383865646464613537383533636462333133386639363837653436366237666164613639396666 +30643034306330393062313132663661636163383336373134663130666132373534383734643731 +30303163353563306465383134626137376630373731323939653531356436323337616662653565 +61313131663262636437666531623466623438326136653332666238336566623963343334623266 +39663134636666326261633634383264393662383733353663343734306534363934356165663638 +62623437633031663364306231663162616630393531346130333764656431616161626466343462 +64333865396463666161363134393932613636333330316136363737336130343663653063623036 +36393038336462373933313934353939336132313135623534393361656639333864613637626137 +66656331376235636661363534393163336439656264396663373665383737633263373934643231 +61316436343539646662316639343662336438383335383838373261643838396439316632653838 +64643135343938366236626463613036386230316263376165336232303434656230366561646164 +62656466396439666363613634366633623935376630313034633230643162333334313436643930 +34333837353937636339363364353333326238343536623131333561376230646237366437333836 +37613363663663656266326439316334383837613633336339396335396539636562636334316338 +61313536316364386262666663396261356538306536333761633763303762363232313332373438 +65316263353165653336343562343164306566353630326333653664356165376361326366333964 +64623261393636626439343738653731663130643839306639663239623834366364613832326233 +31396432343136306365393132613531303632656363303833313139363939356132393230633966 +39383432613135646435396262646461623735313135356230383533613136656639643539366233 +34306231313032303537626532316263663337303362663635323731333561343933663265373639 +39313461353561316539643436343764636665316233303438643736303464363839313135633333 +38653936663234663830313632623566336333633561656631336132323231353432323031663863 +66613363343431656437633631336638383932653336303762613730623534633936306333646135 +61613261613932653361623263656237643534326132613339653861343666393466613439303734 +31303430343132636332343134303936366262333566316638636233656330333734636636376164 +36383536313534306535336438633435353463353630326461336366666535313638363862616136 +36616236353033343566626332646133656235623162633736303762306430336238663835653263 +61326466663161646531383137333439656531383566303164366637656661306638623439323164 +61663163353263373864323734373434303530643764633762303139333336323832643063653734 +32373266373239366633636637613433336532663135626238333936353431343532316536653061 +37393131633066666637623538633530653730323362373432656439333332366638336361666239 +63646631633762333938636338323537343734396133313332393436326630383639333034643961 +65643139303531376163613833666532333734633438623935353635613635336262373432636462 +34323738386631616266313462346265356164316238323239646462643762333166666132633965 +37333535376235613538363938353135616366393964346164633861396331633139613463393035 +31313262356436646261636139383431643637383235623334353861343064666437356465373339 +31323364646635306163646131646339383931613461613330636561313235663934376632373132 +31633235346339373763303138356464646231373266366431633038646533616161613462333231 +65623835353963376532313535306331636639643635323434323362326462376239383630663962 +32393634366233616133323531633030336635623134393730626630636465653065633462666661 +63363637326139333030633333626531353866633839376661646437353939316166366137363865 +35383536666462343135623266363939623335613632613830316432343363313538623364666634 +37646531346433336365653935326437343461323861336133306233613931636231316232643034 +35396539373663633237623862623964383463613936623061376333323439653963633861663631 +64623866396263663038373561656239643664383233336433623036393930636264303662643434 +62366632323864633733626135343339623030636334356331393732363139326662326563663366 +36313262323933313631633562343230363032656636666465373062656664333964323537633362 +30343266393230393665626463316639336665383763343332333339383464333533653135353365 +34306135613839326361623663633033623238306234666564626565313137326431383763646433 +35316339366234353936326466363435323331353165653531373733643232356236383838303930 +61373538363238613635313031653434396265316434353335386332666135323366393062376162 +30353730613433383364636164306336396430633133333839383261366162363930303131303762 +32373461396264643232623337643266616562393865393864363161616337636436383131643932 +61316232313835363634353930636664323539643133333632626631666430363534383866656631 +30656634333836623133623731373861366333643637336566353064393332626461376334333733 +30383164306561383738333238353766666565656137643661623466313535623936353831303863 +64653762656364356664383365343264306336663563373763316532303537336138613238323438 +64376130656466393564613766633036623336393931313132393430313663373334353134363030 +39646665306137613034653830666437333832393464343265336162393231386437303539363861 +62333032393134666331363030336463363639366235656266363830653337333965303934626530 +31616532323334383665663936376130396334656137623537646663346166343262353764653439 +30396332346235653462633034653535396361383934646632386534643530313134343034323636 +32383538636537316532626230363361313330653534353962363932326331323966303833386330 +34623632356136616166636434633437356261313233333165303237346464396436343931376263 +39633963313062623636663533316538356162613734373830363838346133383564353336613437 +31643233343437393765376431613338383331363632613632396265656638646434663631303363 +35386332343033623534666530363831343262343736333366396238643030333337313838396534 +64633937636332313432326266643735383262643334613034643465366666336638393461616361 +31383038656235653239373164666265663865666537663335396137353939343233616435646362 +36393266633863393965363163376332383837626532343034363034346665343663326163653266 +61666236653837316639333832636536353534626365333939343734633863613032666437383864 +64326234303438363434626566306435376237336137316465626432383234383434343666333332 +33363333633132393265313662313731353162656337363730366439653532643438333639393664 +32623561636531376234613565323661613635623337303963653862393435663562333137383531 +37353532666639326334366133376162646262666439616135316432333934656631326566393965 +61643135653965343032316339353433323636353734313834666163633431366331393035393564 +32313966346634646263623130653934323736303364653930633439343339343432346538303831 +62333462343533386166623831383437373732373037356236376530353639346662663930336235 +65303564313939373532303137376565356364353332663961323366323264353738306331353963 +38343333653764323835303432643230663733643132333866303039656136326630303962643963 +39343737353166653862333030356533316165343766646231306532336530343964633136326563 +38646330386438373931323961653832613638303261653333396337623331323837623431656137 +33373631336462623531326438323739653662613139393866383263343134633335383738656363 +30333665663063373661623761356438633262356334373262613934333064326239376633633039 +66613534326662343435383438306133613765326361376537663331323938623436636164366135 +35323730363036643765376537336432333066303137333534353537633234626666336334333530 +39396133626434383132373435343165383563383564323864333639623764633064353131633165 +33333862613538363233633735653730326633346563383732353563643862356561616261393731 +66373662353937646462363262363865343531366463393761316665383230313331626630326236 +32353439323039316335343237623730393966356132656534633933333737653935613932643231 +63366163373062656630316661623131333462366564333462336333663833666363396639373936 +64613530383861643339353965666530663437356431353731623464336461383030306563393262 +39346566306565623331336234646439316461646366636566386236323464303138306663373265 +39346135663264366566623731656532323236316130383865346136353238353534303736363635 +34623532363033656437656235643066316364333164626662333536396631653531323437643564 +66386635653436616461633162316165343638326264303066633437313734383666623636666538 +66636634306532393339346633356431303537636364323832633737353139313138346632356238 +39393634666138383339323335306462623330333931326266366135616666613533633531653539 +39646535383666646662653936386231616230306536396432333536313834646538643936303366 +63666431663965343336343362356465306461313532616462383233316261336439663936313639 +35663261656534613634316235663139323937616261333530393235653836336138353630636335 +65616236366233626336356566326633646664356264313736306665316434613535393535353038 +38356331343436626230376334303138303962316231636631656233396231336437346435376532 +35316232306137333332663236393631636436633736353962663332626233363536633733353436 +62613565616332353461633930333636616164656635663064623463656238383430386135353030 +63626534393930663462323634343936346261653635636430616564643630313836316135646638 +36613363613238626364393434383966376430373838323461653131323563346364656330396562 +66373231643732316138383236636535366339623865393935383364373765636335656139396261 +35326339343266663863636361386431623238633139396264613166343564353236626237616161 +36626233356361666530323632393437623238663835616539373939636434353966643734653835 +30356437353566323266353233646532383335363366636333336335363634303038633965376165 +38306164663837366633306633393163356564643533663134653439663666316366383666623536 +39653666303363346131383064633835323261343361396462343566613237313732323366373864 +61313762353737616633633538616162353761353131636336623265313861616634376434363961 +36366662313737653465353363313537376361613534383563303764356136393563306230613466 +33356437613965633661336164633239346666636137666332303430633766643036346439326134 +30376636306436376564623338636231366536663530353537356461663864323234663530626633 +63656535633336346631386163643138326638663061373331623762376335646661316362363636 +36333732336138663034386139326566616236373061636661373038306135613031633139666635 +36626333646631636437323334653164316335396532396536356261346438383265643535306362 +62303034303161386465393062623963303131363165343066633765656431303035646664306661 +66333531383665646166393130386463323537386237383632333431333265616664323364306564 +64656463313133386330393266633932643863656436396265653161323665373861393031393338 +33373463303032326231313035646564663961363031613362356635623030376465383337373033 +30336263326364613633656532613439333631343665353866616263323137613163363333666664 +61383831616630373836343233373935633262383136663931643539653337643232363132376364 +65353662343539373437633133376638653633393864343866633865306231353264306262313261 +33366332316531616234333766323232343336613564313135656531306535643430636666346234 +38343532653666636235373366356635343339346237386436633234643738633033383664366264 +31396464366363323937333834626230383038653434346361316166343930366536373761353433 +62313638376132373661316436333430653735393737383235386164636535386130313533633830 +63616335643233373165393733613266646138353437356666316139633933346565633561353734 +30656261636265306633396633383638646233623164383236343335626432613866653834616434 +37663861373062653061316631373064336663353061306261303733313632373163326261663262 +32396263613639383534386236623836303635613631393763313130656134656236623238353661 +38643538343135386131393133336237373733613238663763653431636436376232646637386339 +37626131396237396239323031613265306262326466656634363266393064326631383633656338 +31313130343064326135616433343533653563666663393230363735633239363537376463663466 +61353865333361373538616236393235613366333635633664333631653361333962386462373761 +30313066356564363432363739346430346633386436613739363939336665636239323930636130 +61633639363635353333356266383661313638353162373535613165333063343332383231633331 +63313339306235303361393362333635313331623365666166383937313663376261653838376563 +37386237393762356339663434626639363666663931613832653539616630343137383230346163 +39326138383165326131616639623033633164626466663439386333393231373537616439326161 +33366634313739346266663564343330653062393139616464393634313234336165356338303439 +34366537613163653339373062646431643537316635343438343031613937343734356130636230 +35353334323130303439613233333439303234313530343861316261613036326266396134393938 +30393032393864656661346464666262343431386364626662353736343234363861663437326532 +65663835306366313362656135386430666633383165623965663838646433613835363836643365 +62373730343831633033613631396535333232333331636163366162613131356132643835663766 +63643531663237333935393330353733323730643732386362333734316632636265653731663039 +37623365336562623766643833653533343238396139336231326262326330316338343738663031 +37383334333634366464653836353238373061386334333437626537616135363736313364306366 +34396636383934306664363835633965353463333465333966306537353735323564643565623261 +31343932316537346561316662306139343266636463393130653434666666393338366531303734 +66323965346632306535623931326133663161663464643337373761343661633763393666636162 +66346566383937626161633339663732666436343437386233396332633261303533666436396430 +64303566396530616365613935623763323962616564373130383637623334636134623637326465 +64303037333035303930616133396336616432663338396634383037323238623961353136323965 +31326266383838653236616435313936396537323761636436626539323336663037316161393433 +64626233323935396232636337316634623037656231653661303462333961346230666230313834 +66626661643231386135363565336437633738613263636364663336313137376635396162366235 +35316638353430393837386265356465363834666366636432656237646634666533636631663530 +36656434353038626332336263353832376563363035373437316262383733326661353762393934 +31333532656666343136343635343435386337363962363037336331623239373035633631346337 +31316231623761366235303538336339626134653238343132343838346363353266346239353663 +64613566313263626537333830646439396536366135346362333162366539363537616332386262 +32663862313739316330636334346664353666363933623563643365383630373866656537633033 +39373331663663623831383830656237653034333932376263356566613162326566346537373632 +36356161643766343934643636633633363135653537396333613532656464663535653863323066 +63393662666463626635663062386430336233613637363263306564353563616439666436656162 +62363330376430336663393565613736306165336630383336363263643032653062346661343766 +65646537343063663864333933363938613438326163353235306239346236656561346264343039 +32616331373062323066306232383030373130303565666463326434383331343361393331343039 +65653536306538353830333434373433333030353465313866393966666434663238323232323364 +30343535383631313431636462356630323439323965353033383536363866323461373538666332 +63623935343665323033326432356432323730353864646431633035363831313735623063316465 +34623064303864393365373635353263343033653064313163633936366564616661346532343138 +66383130396232353166613531343338636664363164613165613737353762333466616530643937 +65666530363165346331356262363065653861386261623566346135383030656163303332323436 +63306137623430613661333733643161386138623934313863643561313061363061663435353335 +32353362663064613364653236613862383830356431333839636163623432346638303230666438 +38353766646231383436636463346436393561613339316430323463363731303762353330346532 +38646130663862323466326136313332306561613933646637366235646338343161666161383431 +37626230303633303664366161653437643331386435363631313935643764643835383662353536 +65626132313961343564373538396237363934343335633231656362316238633030623365663063 +30623232663930643639303437336563363131333531333238333663333136353964363439363836 +37376233646330323364363764393732326462316235393633626134356138653430346537393764 +32393739363637376534313836346239626639636332326666386334636234353535623035363266 +64633661383438363336656539373033313635626239313232373233613764323665663762343461 +32343938653135313863316233376632396666366636643036623566393739393537333235396239 +34303034396138656531343662613838316363646461643136643432653132306466623837303532 +65316139316432633039373239326539383165313430656364646336333863303464643961346363 +36623830363235316436306563313239636463613537623962393061616632356632356136646531 +66653561323232343231613863356466643030303066396665623638383662666465373833343733 +31356563623761636630626630356362646164373662383562613264663966326631353237366130 +34393439356263383732643665323431653738633236313539366535396664616261333232306535 +63306662346465303835616666333434393361306462653861323430366566353435333231353935 +34383264663930303662663462626535346130613033396435653934633933366464343166306165 +64623461323365623634346463386234386561306339613461613438663034333334643365343531 +32303637616336616463383566386139323639613731303263646162613262343531306665326261 +66393038653234376132646136613263383531656632373631326361313332613739386465343935 +37626331633063336232326333343037646432323265326131653665333863653337663961383737 +36663361663232373338623931393538393461646538646565323730393562353836623263343832 +38303333386363313634643930663832656262616537666531393536656664303539306563653265 +64666538333135656132643637346666353930356635393764333538396662316366353166376433 +33626232383666343030363263626266656538616562663735353534663164376434346631383762 +31376561376430333036393131356564663737633064616361353038633839656164633536613631 +66646665613132623062383465623738363330633039373135343333363039643332363331333365 +36306636373238396430336530633763613332336432363933303733346133653666373132393063 +30633437356363666235326263386566643062343534353238633062393565633838623839316634 +62323239376532383163376237366431313734366665646161626232616566323631383536656632 +36653535643537616230626633306630383934373135363538656339626432666563663638316363 +30316262336461303438643964366434366332336535343437666432663566323761306563623261 +30633965623530346165633936616366623536666230363130386633633061343730373365303833 +66646334646634366433626331626137386531323661386132316235613966663730336432333764 +66306532303566333834613537666639616663633466633633613832363164623536373738613265 +38323038343862323166663533613830666362353630323035336235393565663230623562356166 +64306331363234336433323364316232653934366662323465393961393862373738343063316434 +36343035396536363136323734623132373763366636633939616339323965306564303031663331 +63306463623732373462313035623532646334623532363666633461613066323933393433376463 +62626563666565663438393332646435333939653439306234363930303637373965643366656131 +31383834666565623861356531663164646165313638353237643831343337313362306232393737 +36653062323561346661326133326635643363336465616636316666613335623235346161376136 +36666264633232653638626138643934616366663938336562353333393265373137383833356234 +32303638646436393865656336653664313136653831336636386664333965383461663166356363 +30383139323134303035626438626632613562663164393934663636636338336134626530356134 +33643930643532376532303466396264386166646166316166366661383263666563333764643365 +38633438306538316338623631616337303933373432646664313736613035626365356433323737 +31323364616464633830643133383661366161613137356431663330633032386136326334343264 +61633333356230326236353330316264383738303033323930666562393932343235313932666133 +32623636643563623166383231396433303735303534356334623330323933666636366365626266 +38653038306135326431343832336331623564633364663033653766623832383630643964643032 +35633431663062353339333266633835366430646563356434373537393937313932346432623633 +64373632343264353066633436626531636232653038613263653038323830616164303361393732 +34643233633731373637336137383763303736353237316134393835663032393861353934633038 +30626531356333346336373535313433623035333466343066346265326336643162323133656339 +37323561326137653939303839343837393763653465363462356161363963353865386539623333 +35383637356666633731396638643966303063313430393038393234346433646566326632363637 +65306466613230353261616366323634313837373030623563613562333833653263346230376439 +35643836346335373261326365336531353733636236373466353332383737613639633034323161 +66393432653336636362313962616237316232663038343665343065313030313937343834356436 +34326266343364616366343039303332353161373263313730373839643361326333616464306133 +64643863633336363762306131303431636366613038623562653035626537353466643231356561 +37393035656533666638336637373932346662346436313561313964316139613763616335316435 +33656230356365373365633830653835376639373365623663346635396361333338376139666232 +33626662616662626363636564306530613034663039653636663838326162616263343562393661 +64353134363737623139633734306430353265323835373833373261363031383163343938373862 +30363735633531376230376161643037663762316466396134626462346133626264353064333039 +66333531613735313333376336313565376632346565373134386433663935626363336635356337 +61633264363635303833613462346263636433383634326330393236663835626432326336396133 +36396462323365633338663935343733346365356233653436613962356366383365326262663236 +34316233626130336635333933646463663461653364313338343534633630663733336261363431 +37343664333633383536633464326466653432353733343933616264316364666661396631336135 +64306637623234643735643430323262626539383439373363356139643362663939336665376139 +35613864303837363635353564393532336162393566313339633866316266363261623266633032 +61343365393762386465356164646531313865633633313866313162393431393132613131643462 +38646131363036313964333930663234396139613362326331333538376364323461353839366562 +62313066663830313862326162326166356537653135313036326239353032636634656433316530 +63336532663935616633373261653666333662643561313235353466303632623364336165623334 +63346334303762326363643838336362616466333631376135643466306638313038353765353034 +61613033623132653930623634376537643230323330343534646365356339333938396565336533 +33303730666433646465623231306233353130626237353236373836333438666565626566326531 +30373637353237393934343064616663663762343135313865386331326266386639353430306130 +39353534663362323665616166373733623639333164656633363537613437616635363639316232 +37373365336531323639663935313836313338653030396133356365336437373963313231636332 +65663433646665383836643362383739653663636338346137636263386366386234306130303264 +30393266376138646465613436613736373662643365663330313230346139613465383136333463 +38626661643165356364626164663164366534316462376633653231626233393934303333313963 +39643362633761353731643239663334646266613536383661626462633062653231616236326332 +32393634643030656535633139336132343639313939313436393865336361633430376166313230 +63383435663766646537363136373138316166333031663736616461316134343461356438366361 +37326663343434323563613231633530316364643164646464386361656632633539353135303432 +34386162376235326631653764613866323432366166663966356534346463306231656665346333 +35356633356262303236386633316539363536653438633334623161343136623161313463626633 +61373637303630633233383430346534613336363739653332376461383531653832333264356163 +32346562636662323066643932326436326333323537323932343033653862356163353730353438 +31313531306462636131626136613135646231343633323065623363643661303336313463373130 +30636630623734636536366631653031326162383034623233623463326434366635383836613361 +61356463336335646662353735333662633231396331336336636235663839353163616234363733 +32373438393730656461383537353038653739326335313732636639656263643033346635316465 +63306437613863643932396361346335303331366535393863613663313133393730333039306233 +63376563366636313435623664323632383139653932643461383536313734343430613736393734 +38313061623163313931616564623366353266333237643639366166313564336437376664303938 +30306233633437376233353237393331313734633063666165323637363938353239653539613439 +36346232626466396431386664396535663162336166313438363265353232363365633034383331 +36393164386235613134663566666539323539313735383636303631336337386366643561346331 +65353962366336653139356433366465616637386333636439333365396563363663656231346333 +63366636336131656237396234353837303035323637343265303566333761353431613135356635 +31313664316635636564346531323638633266356634323164393563383935343738346632333237 +35656464356338356538366664636265306165653334316363336435666262636634326636383934 +36313136373038326363366263616438306561653565656435643063613537643732643332363037 +63633962333637326434363936346633313634363961613063303664323761313533646638666139 +64616436366638353166656133323131633461363663616336353730336639653463383033323061 +30646237653463313261643237343933663032346133336339393965626166623066373735623836 +30653331656635373838633062333638333037316439323663323838616530663530623434653964 +37616362373331633030396261333038373162336536373731396363646334333665396630376263 +37656634373138636633386163393234613434376265393065306333353661326266636633323634 +62633031363965346337363031663263313538393064363761366336356462383737313633353236 +35613261653563663663663832373664383262306232373430323934376330376166363738343962 +61323863336664383266313264613563636464363566356637396261353039626166623331626234 +39353762353536646338613066656533303332666664353863343838356464616437623934343263 +31313838326531356432353563326334643665663735366233666534343733323865636562326530 +63333166303936643736623066653832346339343133346632343164373630616538633936633631 +36376663343934666133343535646662623038666633616130323163346533393765653337353832 +36616563393930343065666361376635326464333435303736386661396263346331636131386336 +64326665643536363563343964623536306238376535656330323061663431653532633434386634 +33346133656630636565613065323634616333396363346534303163393337613830366662303731 +61633530393463633635346136656366333030623038616439363631383466303962333238373661 +35386332613264303739343931336366653431393134303833323464383439656661303163636464 +61363462363064393364633061336262353261336662363462636462336462636535366662333534 +63363666626137636633356631653862626639346634373238353636666236623964373231383264 +31666563353034386365636264346464326237663235353136346339393436383035663034313630 +37333963373135643430653761643662353334646439313262393635656662353439616334356338 +65313166643934623065353164633965303166653830306165333837346262393563616335343764 +39313033373339626534613838343239323661613530323666356665353431356439646231613638 +63323862353230373562393039656361376434366237653365373937336332313762333561386432 +61343435356633396465353133333066333563313330396234626165393364653031353939633731 +37623439336262373838393533626162333937623133396365373034613962623161393231303562 +65626133623833383465396632366137396135363434306337353038333633653264616437633635 +66396435663931653534643239613636333862613263613434396261323238333461623661613437 +64633331393461333831633162623333623663376165343530326262613362653730663463313039 +33316638623664663837383837306163663461373636643032303933366338303633613830356665 +34363165663232386237643464646163663136396232626138333165653162303339616362396230 +37383766313039643438346136623864326334653938393039633961373339376665633536336437 +39383033393635613034333634373834386266626534363833313534393134303138363162316533 +33653333373962643965336465326635653732306338656631356564363961366462636230373030 +63393837356631366638663964326530666536643932343861616665633331373230336530356138 +39303738386166336334633433353339613366643436313064653333626130313361656237623163 +35663263633136373765343330343338306636663534383730353235636434656138643466383261 +62373661616137613164363665353535633637613263646361313337336533363665626462383633 +61383731303132393138663639396433343530336266633939653366633438626139666161653638 +62623866393533346136343339363334666333613666613031613135626235633564353463366664 +30393130356664343434633132313537383063663130646464346263636133303034316266303739 +30656661303231303434333562656237633233616539333239303266373363613034626263613531 +35393937333761633232386333353134613362396138353030613934353935356637623630356533 +30626431366234383834383866353436326333386564353537663136623761623736313861366336 +31336331373537313739353933303261336238613630636462353031653133333139306363326566 +32373264306338353638393965343933656162373438373366333338623434313032373538623835 +63316434306262643532616232646430316635306535316635326564316664353063343331653963 +61306530396630323031386534653062636533613931613632306637343364623464386137623330 +39396166306333346665323139356135643662363564633631383362303636616336613732383763 +35353861343565383739336535623962666239663963626162373861343738663364386439353133 +62666232333533376563383536363239366135306134616439643738306331643539383034663363 +37366366643838666338396537373232623232326263616165616639353939323463663638643132 +61353038646233646231393961663863373466306461373832363435613635383836363633393039 +64346134633837333332366135363736323234336235626630653965353039663964383535373931 +63303262346661373535376161393136656436303235386333663033656164363636346632616433 +31353932643266343361626431383835623761653633656131373134633163343137363536336661 +34316633386263306432333338313462393031383832333533656436336230666363316133396162 +65663861616538306333373032626539663535373161383462366164373764343437323562626136 +38653336663263306533376466323132623261386166666435353438663763316665653039623532 +38323730626666353636663830373765383138303330386663663737623531346630363936393966 +37663839623464393136303934306438376362313233643838373939323938666635626630633035 +31333466393833393361393965353636616661353166323937313032663139386431333163663035 +62373265306132643465363765376663623430656264613839336234343766613833323235353333 +66656639366130656534316639306638366465336661643263666337323030666263623036306362 +64316634353139666434396261653161646339663263663131386339346631653932653834626562 +62386665616131386138633839353262353230316264383130656330313333326538636261393863 +37633665613631343130313163376337363963653134626131643531353565666537613636373663 +63333633313561363438653035303563303532613736373634613362313663386563656339656634 +64616666346532376537336130353233623832336237376663663837643134636361616533666530 +63373065663833363734356130613230613739633134643766373935396531373965383862656330 +32306639356365383332643462336331383731643864636264633234616132386538396533613432 +32646638656233333661626335306361646435306234653436323361643866633235313962313637 +61333637663463643066333562373535363439636666643538626133623432643932666662653233 +33306137613735626135373430393033373132356666633337303134323231323235326434323639 +63326362306136333065393734396339336665313035663637303533393834373664623864386234 +31313062316334333130336138326132636366356266653531333435386231653063646531353933 +37326533663431376461383632643266663531626235393131663464373439396666343236313262 +35316165313962383632623262366164386130323065646436343236623230636664306539613031 +37363564343438376637386366376139613332623765663166373731316262303630326234383063 +35303330333364303366363135376262323365633561336264626333323564396132346362626164 +30623637333263366164373465353562356561376238353332353461623939633035643562356266 +64666131376335663832373136646266633363386139363864363939386534636461313237666661 +31383063366362306466633039363730376130373661366331643836356533303062323030396330 +35623431663561653264383531626136653363336339366332363431323635393561363763613134 +37643733633138396432623031666333616136643735646235346632306461313136653837326135 +36643935303264303532396332356561643063373263303536626433623264393432343933363237 +65616237656131356537366337316437363831303064326436393761623734303238336334653131 +38363437373264373636653531346665666363616233643563336133316439643663336263613964 +66613835336638386631386565343233313435356434393637326339623933306134343332316132 +64326434393134643866323935663331336539396636303666623364363133613861303366313736 +61623465646336643161313839326333316632653365626231616264616633623336633463663232 +65313465313965316139316531623863373235633362633731636633393534663662623663623533 +65653762623938343833653639373730363932366330373237653830316438356666333636663938 +66353139333162376439306530653839306436393832333030336632643830376663653132633633 +36373965646666613436383931643662383263633066356666666362306430373636336438626231 +37653338336462616333353937626363663765346664623862616162353865633463393263626537 +32333336383633383237613731346465613635633633383065643038333536616331333966373232 +66663231343266393865663165383937633439373064383636323137363566646133616332656566 +35343335376465653939653933393161396265396136363936656433316566613336613537623365 +37393364326337633362303662656333613934663362323331343135666136376365663765346439 +35303465303163333732343737383135303635613865346331376537336566623561643837333433 +36633930376330623737633836376239663333616134356530623264303337666432326332646433 +31633034303166616134353736613838383231666363623563316430326461393462333564626335 +62646337643066313563343466303231643334666437383135393432663538623464313735663431 +63336166323839656531633862326534353136303264616266373431363036643335616562363438 +63643464356662333065666663643464623139353833353536323466663462313630366235303065 +34623433613736646465616466633232656362356137366634393735623031343531633231306334 +33393137343637343734613133366239306135383931353637313561376161666562396237386436 +61386637376563346633303032626361353462323963366233613566643434666532383965626661 +66663165336164313431653363653939653262326537623630643237636163613066323434653633 +38613939316463663833643062303933383165393939333233643139666462363037613032306135 +32643266333938653962366231363364616339656137646432666466653363636265643364656363 +32313966356238356266356339636465376133653861306233343635303135303735623037383339 +37626335333030643932306164316535353933346462666337353366633966346363366337623133 +65343766653261353365643039333164663231323031393233623062366432373430396563663264 +37313962363831316137663064313631646433353033336537636132623663393637336438366463 +36393565633936346134643465306639633737363431656161376533633434636663656535613037 +61643330383366663266626436326466646234333831386632633566663831336437646563333635 +65616339626561353065626462633530633461643764373866376264636337636431366638623839 +31366338653632333037353233623962303866303334353033343739636637616239626237343764 +39356464396239383235396132316665366238373833303266343535636164623862656139613064 +33393264363634636231653235613133656138663763326263386334303537333733653132346533 +61383739663963643365393638616233323138616131376461323233643262656633636435303566 +32656438303466306361653366656464303335663661656437373031356365336334373961386264 +32396230326431376137356534336566643137356361316232333939343362323766393232373639 +35363465356235323331333265303535623630666236376230633364643237653762386630323836 +38363136373331623964623964373163363930313138393030353636643930633335323761383764 +37316135393466323139643738366537396133636465393565613765633938306164633263653032 +35353931643438633436306464316230333437373532356261613565643164656330643862386635 +36616237653834653134646439636266643131613761373833346338623439383861636330383133 +34616630313465303535613032626536303762623331653435333633303262326464306330393832 +30623265346438656137383937306366646530613564306230353939626366653536653738323139 +63363332626532346462313635353366333235323837353961323862343334353232313464626236 +30633336316465666637626239373730383965653737663639336261306264343530643364663561 +64666265613762313032633837333433643537666562653534643364346637356363653732306561 +39623538623763653136353464663164356232623333363033646666396232666261323233653661 +65393536653237383863653134356134653533316631623231616539653861363538376362663066 +61646261656336363931303935353764313562653736633431633263656261623039613737373432 +31373165386161373038643831333937333366636230326133616430346131386663653964313866 +37626234396631646639626436326466666561303734346134653764353234376136656662366539 +39376161616162653337353235643236323832653835356235363634346365346462346162306333 +61326534393264666163383466616166626463626666616438653765346638383763636338376463 +35616466306230383233366266653064343962393731393434363435333466616462376633336338 +61643061613963666636336366663562346366616135326462383864326562346534353032343662 +37363861653866363630373565346266623037663233326432316562356661333538666332313465 +33333930343965313030363262653862626461393162653135666666336262663634653333313434 +37373030356665616238363438613739366337383961666662363364343535393033666336636465 +39333431353939366439393761343039626663386164653330663135313839356535393362376135 +66353531353461333539633135363832393235333535333066373461346363343863323239626335 +65313638623638313437303865653736626133653239643232306437663237313432346633616565 +37303539333830663235393862396665313164623263353932313036333362643361383732346631 +33336330656565616331 diff --git a/lmn-client.yml b/lmn-client.yml index 75edb58..5584d6e 100644 --- a/lmn-client.yml +++ b/lmn-client.yml @@ -20,16 +20,17 @@ - name: Apply common configuration to the machines hosts: all # desktop:laptop remote_user: ansible - become: yes + become: true pre_tasks: - - pause: + - name: Ask for global-admin AD password + ansible.builtin.pause: prompt: "Enter global-admin AD password. Leave empty to skip domain join" echo: false register: adpw no_log: true when: "ansible_cmdline.adpw is not defined" - name: Preseed apparmor - debconf: + ansible.builtin.debconf: name: apparmor question: apparmor/homedirs value: >- @@ -37,41 +38,12 @@ /srv/samba/schools/default-school/students/*/ /srv/samba/schools/default-school/examusers/ vtype: string - - vars_files: lmn-vault - vars: - domain: "{{ ansible_domain }}" - kerberize_uris: "{{ vault_kerberize_uris }}" ## example.org - apt_conf: "{{ vault_apt_conf }}" ## Acquire::http::Proxy "http://aptcache.example.org:3142/"; - ntp_serv: "{{ vault_ntp_serv }}" ## ntp.example.org - proxy: "{{ vault_proxy }}" ## http://firewall.example.org:3128 - no_proxy: "{{ vault_no_proxy }}" ## firewall.example.org,server.example.org,idam.example.org,dw.example.org - printservers: "{{ vault_printservers }}" ## ['10.0.0.1', '10.0.0.15'] - - ## PAM mount nextcloud, remove or leave empty to skip: - web_dav: "{{ vault_web_dav }}" ## https://nc.example.org/remote.php/dav/files/%(USER) - - ## Local mirror for mscorefonts. Remove or leave empty to use no mirror: - mirror_msfonts: "{{ vault_mirror_msfonts }}" ## http://livebox.example.org/mscorefonts/ - - ## Local mirror for libdvdcss. Remove or leave empty to use no mirror: - mirror_dvdcss: "{{ vault_mirror_dvdcss }}" ## http://livebox.example.org/libdvdcss/ - - uploadseed_pwd: "{{ vault_uploadseed_pwd }}" - rsyncsecret: "{{ vault_rsyncsecret }}" - keys2deploy: "{{ vault_keys2deploy }}" ## ['ssh-ed25519 AAAAC…uYlnS0', 'ssh-ed25519 AAAA…KTM'] - localuser: "{{ vault_localuser }}" ## needed here for the (universal) pam-mount configuration - - ## Use grub-mkpasswd-pbkdf2 to calculate the password hash: - grub_pwd: "{{ vault_grub_pwd }}" - nfs4: false - extra_pkgs: - - vim - - mc - - tmux - - krb5-user - - debconf-utils - extra_pkgs_bpo: [] # [ linux-image-amd64 ] + - name: Preseed unattended-upgrades + ansible.builtin.debconf: + name: unattended-upgrades + question: unattended-upgrades/enable_auto_updates + value: true + vtype: boolean roles: - lmn_network @@ -80,234 +52,52 @@ - lmn_sssd - lmn_mount - lmn_kde - - lmn_fvs ## school specific customization - - lmn_vm - - lmn_printer + - role: lmn_vm + when: vm_support + - role: lmn_printer + when: printservers is defined - kerberize - - lmn_security + - lmn_misc + - role: lmn_localproxy + when: localproxy + - role: lmn_localhome + when: localhome + - role: lmn_localuser + when: localuser + - role: lmn_exam + when: exam_mode + - role: lmn_wlan + when: + - ansible_interfaces | select('search', 'wl.+') | first is defined + - wlan != 'none' tasks: - ## Temporary fixes and quirks: - - name: Fix 8086:4909 external graphics card - 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: Include custom roles + ansible.builtin.include_role: + name: "custom/{{ rolename }}" + loop: "{{ custom_roles }}" + loop_control: + loop_var: rolename + when: custom_roles is defined - - name: Fix sound on 312A - replace: - dest: "/etc/default/grub" - regexp: 'GRUB_CMDLINE_LINUX="snd-intel-dspcfg.dsp_driver=1"$' - replace: 'GRUB_CMDLINE_LINUX=""' - notify: Run update-grub - when: ansible_board_vendor == "LENOVO" and ansible_board_name == "312A" - - - name: Fix sound on 312A and 312D - apt: - name: firmware-sof-signed - state: latest - when: > - ansible_board_vendor == "LENOVO" and - (ansible_board_name == "312D" or ansible_board_name == "312A") - - - name: Install customized CodeBlocks packages - block: - - name: Check for old CodeBlocks - command: - cmd: dpkg -l codeblocks - register: codeblocks_version - changed_when: False - - - name: Download codeblocks zip archive - ansible.builtin.get_url: - url: "http://livebox.pn.steinbeis.schule/codeblocks/CodeBlocks.zip" - dest: /tmp/CodeBlocks.zip - use_proxy: False - when: codeblocks_version.stdout is not search('svn13456') - - - name: Unpack zip archive and install packages manually - shell: - cmd: unzip -d /tmp/cb/ CodeBlocks.zip && dpkg -i cb/*.deb - chdir: /tmp/ - when: codeblocks_version.stdout is not search('svn13456') - when: groups.PCroom is defined and inventory_hostname in groups.PCroom - - ## Temporarily fix boot order - - name: Check for the buggy kernel - stat: - path: /boot/vmlinuz-6.1.0-17-amd64 - register: bug - - - name: Check for the fixed kernel - stat: - path: /boot/vmlinuz-6.1.0-18-amd64 - register: fix - - - name: Work around kernel with CIFS regression - block: - - name: Make sure kernel package -16 is available - ansible.builtin.apt: - name: linux-image-6.1.0-16-amd64 - state: present - - name: Set 6.1.0-16 as default kernel in grub - lineinfile: - dest: /etc/default/grub - regexp: '^(GRUB_DEFAULT=).*' - line: '\g<1>"Debian GNU/Linux, with Linux 6.1.0-16-amd64"' - backrefs: yes - notify: Run update-grub - when: bug.stat.exists and not fix.stat.exists - - - name: Set latest kernel in grub - lineinfile: - dest: /etc/default/grub - regexp: '^(GRUB_DEFAULT=).*' - line: '\g<1>0' - backrefs: yes - when: fix.stat.exists or not bug.stat.exists - notify: Run update-grub - -## Clean up stuff from obsolete/faulty tasks: - - name: Remove packages we do not need anymore - ansible.builtin.apt: - name: - - unattended-upgrades - - cachefilesd - state: absent - purge: True - - - name: Remove virtiofs service - file: - path: /etc/systemd/system/virtiofs@.service - state: absent - - - name: Fix mount point permissions and owner - file: - path: "{{ item }}" - mode: '0755' - owner: root - group: root + - name: Final tasks + ansible.builtin.include_role: + name: "{{ role }}" + loop_control: + loop_var: role loop: - - /srv/samba - - /srv/samba/schools + - lmn_security + - lmn_finish + - lmn_tmpfixes - - name: Remove pam_mount sysvol mount - blockinfile: - dest: /etc/security/pam_mount.conf.xml - marker: "" - block: | - rootansibleDebian-gdmsddm{{ localuser }} - - state: absent - - name: check if rmlpr.timer is installed - stat: path=/etc/systemd/system/rmlpr.timer - register: rmlpr - - - name: disable rmlpr.timer - systemd: - name: rmlpr.timer - enabled: false - when: rmlpr.stat.exists - - - name: check if vmimage-torrent.service is installed - stat: path=/etc/systemd/system/vmimage-torrent.service - register: vmimagetorrent - - - name: disable vmimage-torrent.service - systemd: - name: vmimage-torrent.service - enabled: false - when: vmimagetorrent.stat.exists - - - name: Remove deprecated files and directories - file: - path: "{{ item }}" - state: absent - with_items: - - /etc/linuxmuster-linuxclient7 - - /usr/lib/python3/dist-packages/linuxmusterLinuxclient7 - - /usr/share/linuxmuster-linuxclient7 - - /usr/local/bin/onLogin - - /etc/sudoers.d/90-lmn-sudotools - - /etc/systemd/system/rmlpr.service - - /etc/systemd/system/rmlpr.timer - - /usr/local/bin/sync-vm.sh - - /usr/local/bin/run-vm.sh - - /usr/local/bin/rebase-vm.sh - - /usr/local/bin/create-vm.sh - - /usr/local/bin/upload-vm.sh - - /usr/local/bin/vmimage-torrent - - /etc/systemd/system/vmimage-torrent.service - - /usr/local/bin/linbo-torrenthelper.sh - - /usr/local/bin/link-images.sh - - /usr/local/bin/start-virtiofsd.sh - - /etc/sudoers.d/90-lmn-upload-vm - - /etc/sudoers.d/90-lmn-sync-vm - - /etc/sudoers.d/90-lmn-startvirtiofsd - - /etc/sudoers.d/90-lmn-link-images - - /etc/rsync.secret - - - name: check if vm_usage_information.txt exists - stat: path=/lmn/vm/vm_usage_information.txt - register: vm_usage_information - - - name: pre-fill vm_usage_information.txt - shell: - cmd: | - ls -tr *.qcow2 > vm_usage_information.txt || touchvm_usage_information.txt - chown lmnsynci:lmnsynci vm_usage_information.txt - chdir: /lmn/vm/ - when: not vm_usage_information.stat.exists - -## bookworm fixes/hacks: - - name: Work around sddm hang on shutdown - ansible.builtin.lineinfile: - path: /etc/systemd/system.conf - line: DefaultTimeoutStopSec=5s - insertafter: '^#DefaultTimeoutStopSec=.*' - -################# - - - name: Timestamp successfull run and send up-to-date report - ansible.builtin.shell: - cmd: date --iso-8601=seconds >> /root/.ansible/stamps && /usr/local/sbin/reporter - changed_when: False - tags: upgrade - -################# - -- name: Apply additional laptop configuration - hosts: laptop +- name: Apply roles that must run serial + hosts: all remote_user: ansible - become: yes - vars_files: lmn-vault - vars: - ssid: "{{ vault_ssid }}" - wifipasswd: "{{ vault_wifipasswd }}" - localuser: "{{ vault_localuser }}" - localuser_pwd: "{{ vault_localuser_pwd }}" + become: true + serial: 1 + ignore_unreachable: true + roles: - - role: lmn_wlan_iwd - when: ansible_interfaces | select('search', 'wl.+') | first is defined - - lmn_networkd - - lmn_localuser - tasks: - - name: Remove deprecated files and directories (laptop-class) - file: - path: "{{ item }}" - state: absent - with_items: - - /etc/systemd/network/80-wlan-dhcp.network - - /etc/systemd/network/wlan-dhcp.network - - /etc/systemd/network/virbr1.netdev - - /etc/systemd/network/virbr1.network - - /etc/systemd/network/wlan-dhcp.network + - role: lmn_vpn + when: vpn != "none" diff --git a/lmn-vault b/lmn-vault index 9479d19..01cc8c1 100644 --- a/lmn-vault +++ b/lmn-vault @@ -1,112 +1,107 @@ $ANSIBLE_VAULT;1.1;AES256 -65646637366132333430346461646331313431363233363736306264633633396665626332623934 -6439363764316132383635626137313764633162636362340a613832323934646431663632396361 -36323539663238363738393131363034333561343233383238396234613434633334323235626637 -6266326166333334650a353637383131313136613635333237616361353732663734613833306538 -35643831653332346634616139363032656433623032383832363837653231306465353766343961 -65313134303434333635306634633731313462396535383662616134653762343732366431373032 -65346564663335633936636662626162636134636339343463376166666333346133616136626665 -66373064303562323564363864366363663336383862336632373436666330373465636135623762 -36656632346664326463646666313663343662363865343166376363313866663536623234383561 -61616637653630316230626337653135396134323636303538346435663639643662646133383363 -39393234333934656166366633356663326162396431383362306339623534646162613339383836 -39666464666163633033653434306365393933383232653364363062356133356239626538633338 -32303030626538373637323533303964643838383331366365326465666530623965613731663261 -33626563386262353531353635356430333633633665393230613561633836653636636639313663 -37373736346234313134313232376164633332386563383863343266626231373237643063663533 -39343939393331653665633335653264376531383364376565646239616231343531336134626531 -38396630363865376161313835376261646637383438323537626433323232353632386439393933 -32306238643436653666333561643764633831343962643165356232663932633763396437383634 -35313763323633643439376333643836613637613339343731636633313064386231613135623832 -32643934376233663865326534313735633535316635393932646263313135373633636333333737 -33386365363830336139323763303734383966616165356462333734333666343830356234616662 -30616434623237653138623538643331373432663137323333376632343065316431313734333965 -64333237396236666664613466623039626634343238363136363438663730626132646562646536 -61653562666636613164373464663931356565623862306332653230396230326636363638393862 -62663765373436303831613435383866323138316633336532336632383065343537326332653235 -30383764396361396565323035346531396365623130636538396238613037353438346365363331 -64383636376566306136653033613638323865653266383136373231353063303434636332363166 -37373462353530326663386139333536616138386431373763383838336365336634366339636637 -32356263653964343461393162396539303534343562653032643461626235373339666363646637 -37633934393036356331363563303330316234393535376338646235663235383966396634383166 -37656633373562643530663037333735396638363963323837653831396233653962356536616236 -37323139306131323561303061633136303234316335363361633766623530303762663465353163 -33313733386265346333663065366536616533326364613231313330373137616130373539313131 -37316637653934653035373965636633626262626561313338646261313530356163356364663834 -64663037666133626261386266666633336666323362373237626639373535333937336331353039 -30313833353766626332376432326531616464643364313232386633613361623234653536313830 -61626666333037393564303738646333643534623138366264353339326331386433343733623837 -63646431646533383331356334656466316465623735613537646536623364636632323566626233 -31663263623539343562383836366134366236346539386532373735633237373363636438366632 -39613330336365626137363765313930623262666263393835626532333262343265313761356333 -34623663633636373734326662363865396635613933393464356436393161303132663564366437 -35323166643762333862656561306239343034643562316534316236636362363162306131633961 -31653736613732643930666338333131373634333166633466656663636163396266306538626666 -65326163646137373236633363663063383162393435356163366665653033666161333037303035 -35396334663135373863646664613137666565356161353865316164633939323037323664346331 -63313230333565336232663166616465363038326663633066623531363338623430313332333138 -34363532643036343831353463356665646363363239643835396661356665393035303561653337 -62663335636533366334643636653366303231353630633166343832313133303663393836623036 -33616563636266356130356635663538343236356632376461626532626436616334386330356430 -62323864323534333032643737656164343633636365623664336236626239633138626230383536 -39306534383933326638666130383139316334373530373335633238316238353038643136366533 -38396661626661373964363630633963373732343161663065386539306637313633303534663466 -66396361373163313865373131636239613930333963663462306636626431363934343136616330 -30643763343838316338643463323833666639616437336361303363393361356431356266353233 -63366366336231386530313961356538613136366530343338353063343332333165323763613566 -34653133633532613332376634616234383237666261363038613437646366356332636530623534 -30613735663666636232623230633161663064666436333161633334356336383038386535336133 -39663963333031383961643232636539313137346132336462336165313862653366303135353730 -63303834313462646633333232646661623731613439633434663266303834376635346438356438 -39303066663633656234633131366330356363636535373034613037363837326562306562663538 -61316666643230626662663266373330643865393938313232306130376333306536393930363037 -66636562396339633763656431653036646361313632313932636231626333303337366266623238 -39616336656537363439373231643132363264306135346437386465326265666137353032336261 -61323234643662653233353737346661373630376630343635383834313038373162643135343434 -37613634333330326132623437623834363539343037643764303631613463343863643065643063 -33326537376130346365323361343266663331343038663037623438666362656236613065366235 -65363130356133353739623733376531636438643535633731646431653837343531313531373436 -31356139393363646262623664663261613931636330663436336466633038643763336337336330 -33393433346332623538653262303462636363363338346538376463373838363036343634363131 -31636332343931643436393464656165616631373339336537623130343630346164383830313165 -36316364653739646330663762356332393262653931613933643963626433633532353766663632 -65616262666433383763363636303131373064636261616661613139373766336639376336393962 -65336332303164353763636332323031363363653262386331313038646564393131303366653834 -33303464303566656363343464336164363264626436306465633261386464663764636431353037 -31363034323331333235346137653139323835326135653337323339346239383038363861313638 -31363136353037396634326239306665303230616131363965653439656361356538623135613238 -66366639333331306337323562343934313532323633613034353863623839636135393465383832 -34323031326262306161613439323836646538363136336537313266343662383935373762666138 -64336132356662366436326664653234303034623066313736353439396334653630643136336431 -31386330326636303334313535363564383964623538656666376136366365633538386139333862 -65336662653965343035306534393962616438636366646664383231316365366435663763643663 -64383034336565663561626262636263616336303066396164633464313830363338303932356638 -32373162313330303935316137366435373532346363386461303933643237383830623335626639 -33383335653436353831303163656530613962303439383563376534663738383035346433303834 -31663863343864656463643433383938393464613865356134346261663333616537663066333965 -32366466373165633936323232333237383638313434366437376237653837363532393564323035 -64623234376538666237653938346634346532656135333165353864383739353737643965636539 -63626134376330346538656539333362633765363735656161323635323164323038633139653663 -64616466353137623937333237633163646266326437663833393437336662356465336566353832 -30653063666261613534393439663664326336353338393439336137386662316137666236636337 -32326336396430633136333064383164373033366230333832333564616364663931653233333233 -62353264343865663865323461643032633465336564646161303039356266303738306435353131 -30376431616631613463313666383664343962306265613361376365353361303162653834623631 -33643762306232636134666366373637353234353265303437306261383861333235383530383638 -62353338323535333438376335636339386161326564623037323861343134396637366362646335 -66633865386339666265396438353362333463376361306666313331353063313331636539343835 -66326661386532343865653365356531663365663865666439653039643333363363653838616436 -38333037353333373866316333613538373263386334626665363239353162376335373238613737 -31616465326138663934356530353263653133636232396134316163343131316664633964643437 -37353937653665326638663631383733646563336162643361643366633564663439396639373966 -66356163343731353430626537326466393538363939313134343464643666323037356639323538 -35626137303439316233313664326535396234326432396132646361663936636362626232383530 -37366334333035656638383161663732393864333562373761303031353262303666626436373065 -66396233393864373463363065373461353538626135663937656330326632663863353438643838 -63663438356663313039616135393833623838366530353735333161663739366431393139623737 -63306464353039323065623765363665663266393934653962303761383362646364373239313062 -38353737663434646138303562303835373439653137656234653333313234366436623963386636 -66313837393636373537663030393331613633306531306339306261636366343362333736363465 -32316662666664636437393736383130663235373266393263623131643339323266633633336334 -30643737396364303462363262653332346637643466323339633435323436366430626339393537 -633439343732646238343833663731646631 +30323066396237616634646638353133663731623734383863373431363930356262636162323264 +3737353636623963643737353762663064663935306631320a353231326664353433633339363733 +33333038346638316335333534636163333564633137663063646334333832633935323763336633 +3662303830303363380a663633643139343630373838383337346631366539636333346666383434 +37336232376466613665313934616537313064653566353763613161613866393139656165363835 +61336131343162313566363562303464623938313036396463376463636334356561666136666161 +36333131663432336238303831626137323635323636633966336639616265656637363432393436 +65636338646234363863373666366131333333356166313933376331666633653132396161616661 +32663932666531393066623935663462353534373666313465663034343438303331303632633863 +33623534653031393431646238356135326130643362363238366666306161353237376461356338 +33393738323338643764356363646530653938313633393730323036323030623236643133396366 +31313837336438393035373936656662633330643933323039356539386133653764326639343938 +38323863643338613564633964646432306664353163666231616135353235616233623632623564 +32616636376539303132376130343966666261646434626366393262643131356230353937663530 +66396235333839633461323139663431343634633634663865373564613133633465353861326430 +65356163653162363237303839353930636163663136393831613964306334663863323034336333 +37396265666538316630333937366234366636316233393430353334633433663461626263346666 +61646532613562333663653162356533356465313764363032666166366365636465653037343734 +39613730396262343039373433346237316131343832656539346365383133623964383764393832 +33333138386264376161653261656563613738643563663238656562333066626137656164393036 +62643938656138356134303666353332643263643238326137386264356632616138613436373331 +64653730663332393964323831336332396233333031633832643564313238643334303132393536 +31356633656536306237346366633461353661386530303663376133666562346565356438323036 +35643266646136373132653537646138356238306130613034656539396230356633386330333933 +34393435376266666361383164666266663563396466393239653362663232366164376137376166 +33663634313236366563656537366535363264623861646564336466363665343433383532666562 +66326332636536363836383135343361663636393138623362643636623533363931396563353261 +66383565616432616361353338303038663730343566653438336661656431303837393464643466 +65386436396132323261313361343164393163303830653736626637383531613432343435396630 +66373831396264646464353565363633333666333361386639353165643566376430653264316432 +37353163323337643461636331646561313465383032383761373665336666303535333363613862 +66386132636133623263366436326131666632623238356530396361323962316463666261353137 +34366266303739613462386235616337383334633234336261613231366131316535373866306133 +61356438356235303335363638663861383332383931343032326238383536623437313039383639 +31663632613135383037313032623064623633376663656634323534373463343932323964313464 +62656134623836333835633061626331623461653565336438636431306434323638666336623862 +63343835623661633534646437616134623962323139363265306462656633653463616366613232 +38613830336639316139643732373938396435363966663330366335303232666563303633633463 +33366663623062393262323530633163363363343930343265363430303130303436376664646431 +65303263626263653865343161363064386163323636663264353539393031383639303835636461 +32666462373063346431353732346330636432643534633538316638316661393866303039346333 +32623637336434333836303936613066313562373834653338613139326337366664666231393863 +62653333353736383431383534313164346639663037643366333931633539343137356464643236 +39396561306565666262303337316532623564653632353533316235643732656336613730643361 +36303761346165353561616364326430343763323966643238616630643639323639663932306139 +63333733643536376132383236343937313639623763663161323835353333313838346136386533 +31383065373030623231626533343333646339643231373936663336303834666639623431366336 +37653361313161393433363039633139373338346230366465343261326535303331616437396264 +62356533636436663532663233353938623265663139376636653532303561356130336630393432 +62646331326163366336373164333839626666636335303836363766346264363931626161643039 +62613139306634323162613131393739373133343034373633353532616637373666613131326337 +37613437323132396132333030386132613538313339656234366435383561656331326238306563 +61616133336365656662333064326233313630646633386138333533386435356262323737316335 +64313862366533373235633161363139376638336331373163653762396666373536333663313963 +34396134613633333631653930373965393532313038616331386332376432613032653537356334 +38636362623539336134613832313065653539646366343430356431653361333662323334653663 +61326561313433363561633631653039386662383766326136363266353536393063643532363038 +35613866313634313434636463663138636165356432336234613032336635636263336439313061 +30666639316665353733653338376162643338316533613632303433646239663138376536636330 +32386234626430393833666263623135386561633230326664313137343463336631363763643931 +39616139396261393366313736636265303466333533336430663439303239373963666333613537 +35363138653831653435626132383135633631386462633038363966313838663236396532366163 +62616165376635613164326439623563653037616638383032326339346230663935376635383263 +62306532323764633631366535383233316335316439393539313565306465353365343636333462 +62616231393035646235643734373764326334643366613135346433653639303864323464343034 +31303161353963663839373565396466353033333165316134633936653161346436326362643534 +32366665633338323130633737613934343031323766663164633134373464656132303735316337 +66663361333136333839653062373133343761386439323463643336303137383932386665326136 +64356531353933383235633039326266666232303764326338366462653834623736336362653233 +35353963356231613539656630623334663763313837383261663163343266613463613366666430 +66396534663531633261336162366436333534633461636136643230336466636265663531356336 +62336565646234303765323866316562396561316464393636356262313663316437393634656238 +63613530303164653264373863336238646666323938303631366162636265643161616433343232 +35343638396437376337306262643161626234636338643264396362653836653337633632303166 +65663133396462316466663038346565623132356631343865613462323035666537343134363436 +32373539303763373134336534643930636234643338376536376666346561393731316666343364 +36653561303563646233653865353736356537343938383930336130623964623866313539636335 +32666536396538313032613939666632333839303062386366353639613862653134323162643533 +62663131303233323666353336363461646231376163343563396463356634653532633266306433 +34363930656562366563643937633862646565393930303537626338623631313436613564616530 +39353663623939313235306231373537393535326238623038633232366131303730333838663838 +65366437333665333364336535303434383934663532303035313639646635653833666566383163 +32666334373237326266366337353636636465613963366538326362363132653466333634333534 +63366537653866346133353635356332656164336632333465316363376238653563316661386132 +64343063306663376430363163323161336166313762613066663061346236343731343836643731 +32306365656534353733356561373561386334373661303530326332333061636536363364386233 +63313035653166313164333537313662636136613565323433333738376237626263373538336266 +35646633663165396366613162616338616532383437383630663061666338616131356534656636 +36353036326533316339313833356466386163343065653037363038303239643361306335353262 +66393361363936373630326533306164366237353161346335303136633561363265643135363165 +63333833656637636635363931393965663933396265643239363939363337396666633366373233 +37656630376262643836643063383762623331653761353030333736366462663964363032626536 +63363136343464373230353330313830653730333438393238393232353932316337616636356138 +61326638613433666131643830323565623466643333373432323330626265326363356161326538 +61336537666137333166333439343535313135323438376633326535343964626136386138633038 +62363432613861356134376237393436356361373839316637376234303566313164666534663837 +37613763653636363231396163616236626662323761353065383535623266616561323733326437 +65666662386163643232613664346432386233643534626335353336346561303032653163346234 +61333164613832386631316430643537303161613161613631363534366166303834363230643839 +34363233656165623236323634313566373166373565353837303162313262333035663738326637 +34313435643630393738613462373034303264653964393563393739386537653836363833383534 +37383937316166333533633161643463353961393737353561343933613830623061346235353263 +64633839396466393361383462636635653464343239303736656561303033386465323036323964 +32356536356437643436396162643334653631636339363161373437666538396430343162366139 +39343564366338363965633139633338376436353230356134633163316362393032653561613763 +6465303166646337336264633666363638643436333466306565 diff --git a/lmn-www-server.yml b/lmn-www-server.yml index fb751fc..87d18b6 100644 --- a/lmn-www-server.yml +++ b/lmn-www-server.yml @@ -22,6 +22,7 @@ roles: - up2date_debian + - lmn_extrapackages - lmn_sssd - kerberize diff --git a/misc/preseed.cfg b/misc/preseed.cfg new file mode 100644 index 0000000..09c6cfe --- /dev/null +++ b/misc/preseed.cfg @@ -0,0 +1,152 @@ +#### Preconfiguration file +## +## The following preseeding might be used to install a basic system +## completely automatically. +## +## A user 'ansible' is set up and ssh login with public key +## authentication is configured. The idea is to allow further +## customization of the system after installation using ansible. +## +## Modify at least the public ssh key in 'authorized_keys' (see +## below). +## +## For more examples and comments consult: +## https://www.debian.org/releases/stable/example-preseed.txt +## + +## To change default values: +#d-i foo/bar seen false +#d-i foo/bar string value + +## Useful boot parameters: +## DEBCONF_DEBUG=5 +## locale?=de_DE + +## To set the hostname manually during installation, use priority=high +## as boot parameter and uncomment this line: +d-i debconf/priority string critical + +## Preseeding only locale sets language, country and locale: +d-i debian-installer/locale string de_DE +d-i keyboard-configuration/xkb-keymap select de + +## Use hostname assigned by DHCP: +d-i netcfg/get_hostname string unassigned-hostname +d-i netcfg/get_domain string unassigned-domain + +## Skip root account: +d-i passwd/root-login boolean false + +# If non-free firmware is needed for the network or other hardware, you can +# configure the installer to always try to load it, without prompting. Or +# change to false to disable asking. +#d-i hw-detect/load_firmware boolean true + +### Apt setup +d-i apt-setup/non-free-firmware boolean true +d-i apt-setup/non-free boolean true +d-i apt-setup/contrib boolean true + +d-i mirror/country string manual +d-i mirror/http/hostname string deb.debian.org +d-i mirror/http/directory string /debian +#d-i mirror/http/proxy string http://10.167.0.253:3142/ +#d-i mirror/http/proxy string http://192.168.1.17:3142/ +#d-i mirror/http/proxy string http://aptcache.steinbeisschule-reutlingen.de:3142/ +d-i mirror/http/proxy string http://aptcache.pn.steinbeis.schule:3142/ + +# NTP server to use: +d-i clock-setup/ntp-server string server.pn.steinbeis.schule + +### Backports: +#apt-setup-udeb apt-setup/services-select multiselect security, updates, backports +apt-setup-udeb apt-setup/services-select multiselect security, updates + +### Ansible User +d-i passwd/user-fullname string Ansible User +d-i passwd/username string ansible +d-i passwd/user-password password insecure +d-i passwd/user-password-again password insecure +#d-i passwd/user-password-crypted password [crypt(3) hash] + +### Do not ask about support for non-efi systems: +d-i partman-efi/non_efi_system boolean true + +### Leave this empty to use the only available hard drive: +d-i partman-auto/disk string +#d-i partman-auto/disk string /dev/sdd +#d-i partman-auto/disk string /dev/vda + +### Regular partitions: +d-i partman-auto/method string regular +d-i partman-auto/choose_recipe select atomic +## This makes partman automatically partition without confirmation: +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +# ### Enable to set up LVM: +# d-i partman-auto/method string lvm +# ## Use only 50% of the available physical volume size and then +# ## adjust the logical volume sizes later with ansible, if needed: +# d-i partman-auto-lvm/guided_size PERCENT 50% +# # If one of the disks that are going to be automatically partitioned +# # contains an old LVM configuration, the user will normally receive a +# # warning. This can be preseeded away... +# d-i partman-lvm/device_remove_lvm boolean true +# # The same applies to pre-existing software RAID array: +# d-i partman-md/device_remove_md boolean true +# # And the same goes for the confirmation to write the lvm partitions. +# d-i partman-lvm/confirm boolean true +# d-i partman-lvm/confirm_nooverwrite boolean true +# # You can choose one of the three predefined partitioning recipes: +# # - atomic: all files in one partition +# # - home: separate /home partition +# # - multi: separate /home, /var, and /tmp partitions +# d-i partman-auto/choose_recipe select multi + +# Enable popcon: +popularity-contest popularity-contest/participate boolean true + +### Package selection +#tasksel tasksel/first multiselect standard, ssh-server, gnome-desktop, print-server +tasksel tasksel/first multiselect standard, ssh-server, kde-desktop + +### Individual additional packages to install +#d-i pkgsel/include string firmware-linux ansible git +d-i pkgsel/include string ansible git firmware-linux +#d-i pkgsel/include string firmware-linux ansible/buster-backports git +#d-i pkgsel/include string firmware-linux + +### GRUB on default disk: +d-i grub-installer/bootdev string default + +### This command is run just before the install finishes: +d-i preseed/late_command string \ + if [ -n "$playbook" ] ; then \ + mkdir -v /target/dev/shm ; \ + in-target mount -v -t tmpfs tmpfs /dev/shm ; \ + echo "$vaultpw" > /target/dev/shm/vaultpw ; \ + in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \ + -l localhost \ + -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C fvs $playbook ; \ + fi +## --vault-password-file /dev/shm/vaultpw -l localhost \ +# +## When installing in combination with ansible-pull, +## export your ansible playbook like: +## +## git daemon --verbose --export-all \ +## --base-path=/dir/of/playbook -- /dir/of/playbook +## +## Conditions may be applied in the playbook like: +## when: run_in_installer|default(false)|bool +## when: not run_in_installer|default(false)|bool + +### Avoid that last message about the install being complete. +d-i finish-install/reboot_in_progress note + +## Do not modify boot order (netboot first): +grub-efi-amd64 grub2/update_nvram boolean false +##grub-efi-amd64 grub2/force_efi_extra_removable boolean true diff --git a/roles/custom/fvs/defaults/main.yml b/roles/custom/fvs/defaults/main.yml new file mode 100644 index 0000000..f118d79 --- /dev/null +++ b/roles/custom/fvs/defaults/main.yml @@ -0,0 +1,2 @@ +--- +fvs_remove_discover: true # Remove discover to disable update_notify diff --git a/roles/lmn_fvs/files/fvs-config.js b/roles/custom/fvs/files/fvs-config.js similarity index 100% rename from roles/lmn_fvs/files/fvs-config.js rename to roles/custom/fvs/files/fvs-config.js diff --git a/roles/lmn_vm/files/fvs.directory b/roles/custom/fvs/files/fvs.directory similarity index 100% rename from roles/lmn_vm/files/fvs.directory rename to roles/custom/fvs/files/fvs.directory diff --git a/roles/lmn_vm/files/fvs.menu b/roles/custom/fvs/files/fvs.menu similarity index 100% rename from roles/lmn_vm/files/fvs.menu rename to roles/custom/fvs/files/fvs.menu diff --git a/roles/lmn_fvs/files/lmn-dolphin.sh b/roles/custom/fvs/files/lmn-dolphin.sh similarity index 54% rename from roles/lmn_fvs/files/lmn-dolphin.sh rename to roles/custom/fvs/files/lmn-dolphin.sh index 7b5d3a3..489e9e7 100644 --- a/roles/lmn_fvs/files/lmn-dolphin.sh +++ b/roles/custom/fvs/files/lmn-dolphin.sh @@ -1,3 +1,6 @@ if [[ "$UID" -gt 10000 ]] && [[ ! -f ~/.local/share/user-places.xbel.lmn ]] ; then (sleep 30 ; lmn-patch-dolphin.sh) & fi +if [[ "$UID" -gt 10000 ]] && [[ -f ~/.local/share/user-places.xbel ]] ; then + lmn-fixhome-dolphin.sh +fi diff --git a/roles/custom/fvs/files/lmn-fixhome-dolphin.sh b/roles/custom/fvs/files/lmn-fixhome-dolphin.sh new file mode 100644 index 0000000..017f949 --- /dev/null +++ b/roles/custom/fvs/files/lmn-fixhome-dolphin.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash + +set -eu + +file="${1:-$HOME/.local/share/user-places.xbel}" + +[[ -e "$file" ]] || exit 0 + +if id | grep -q teachers; then + exit 0 +fi + +NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") +[[ -d $NETHOME ]] || exit 0 + +if FOUND=$(grep -o "/srv/samba/schools/default-school/students/.*/$USER" $file); then + if [[ "$NETHOME" != "$FOUND" ]] ; then + sed -i "s|/srv/samba/schools/default-school/students/.*/$USER|$NETHOME|g" $file + fi +fi diff --git a/roles/lmn_fvs/files/lmn-patch-dolphin.sh b/roles/custom/fvs/files/lmn-patch-dolphin.sh similarity index 69% rename from roles/lmn_fvs/files/lmn-patch-dolphin.sh rename to roles/custom/fvs/files/lmn-patch-dolphin.sh index 7e7c8e2..60707c8 100755 --- a/roles/lmn_fvs/files/lmn-patch-dolphin.sh +++ b/roles/custom/fvs/files/lmn-patch-dolphin.sh @@ -16,19 +16,45 @@ fi id="$(grep ID "$file" | sed -E "s|^.+ID>([[:digit:]]+)/([[:digit:]]+) ++ Home@Server ++ ++ ++ ++ ++ ++ $IDENTITY/${NUM1} ++ true ++ ++ ++ " +else + HOMEONSERVER=$'+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+\n+' +fi patch=" --- a/$file +++ b/$file -@@ -98,9 +98,33 @@ +@@ -98,9 +98,45 @@ true +$HOMEONSERVER + + Tausch + @@ -36,7 +62,7 @@ patch=" + + + -+ $IDENTITY/${NUM1} ++ $IDENTITY/${NUM2} + true + + @@ -48,7 +74,7 @@ patch=" + + + -+ $IDENTITY/${NUM2} ++ $IDENTITY/${NUM3} + true + + diff --git a/roles/lmn_fvs/files/lmn-reset-dolphin.sh b/roles/custom/fvs/files/lmn-reset-dolphin.sh similarity index 100% rename from roles/lmn_fvs/files/lmn-reset-dolphin.sh rename to roles/custom/fvs/files/lmn-reset-dolphin.sh diff --git a/roles/custom/fvs/files/lmn-sync b/roles/custom/fvs/files/lmn-sync new file mode 100644 index 0000000..16668f8 --- /dev/null +++ b/roles/custom/fvs/files/lmn-sync @@ -0,0 +1,20 @@ +#!/usr/bin/bash +# +# Synchronize local program directory and desktop starters +# +set -eu + +if ! nslookup server; then + exit 0 +fi + +#[[ -d /usr/local/lmn ]] || mkdir -p /usr/local/lmn +#rsync -rlptD --chown=pgmadmin:root --chmod=F755,D755 rsync://server:/local-program/ /usr/local/lmn + +RSYNC_COMMAND=$(rsync -ai --delete --exclude=mimeinfo.cache \ + --chown=root:root --chmod=F644,D755 "rsync://server:/desktopstarter" \ + /usr/local/share/applications/ | sed '/ \.\//d') +if [[ $? -eq 0 ]] && [[ -n "${RSYNC_COMMAND}" ]]; then + echo "${RSYNC_COMMAND}" + update-desktop-database /usr/local/share/applications +fi diff --git a/roles/custom/fvs/files/lmn-sync.service b/roles/custom/fvs/files/lmn-sync.service new file mode 100644 index 0000000..2f22cc8 --- /dev/null +++ b/roles/custom/fvs/files/lmn-sync.service @@ -0,0 +1,6 @@ +[Unit] +Description=Synchronize program data and desktop starters + +[Service] +Type=simple +ExecStart=/usr/local/sbin/lmn-sync diff --git a/roles/custom/fvs/files/lmn-sync.timer b/roles/custom/fvs/files/lmn-sync.timer new file mode 100644 index 0000000..2386de3 --- /dev/null +++ b/roles/custom/fvs/files/lmn-sync.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Run lmn-sync after boot +After=network-online.target + +[Timer] +OnBootSec=0min + +[Install] +WantedBy=timers.target diff --git a/roles/lmn_fvs/files/policies.json b/roles/custom/fvs/files/policies.json similarity index 76% rename from roles/lmn_fvs/files/policies.json rename to roles/custom/fvs/files/policies.json index 08797b5..1fd5fb0 100644 --- a/roles/lmn_fvs/files/policies.json +++ b/roles/custom/fvs/files/policies.json @@ -1,11 +1,11 @@ { "policies": { "Proxy": { - "Mode": "system" + "Mode": "autoDetect" }, "OverrideFirstRunPage": "https://www.steinbeisschule-reutlingen.de", "Homepage": { - "URL": "https://www.debian.org", + "URL": "https://www.steinbeisschule-reutlingen.de", "Locked": false, "StartPage": "previous-session" }, @@ -19,25 +19,41 @@ "name": "FvS-Homepage" }, { - "url": "https://server.pn.steinbeis.schule", - "name": "Schulkonsole/Passwort ändern" - }, - { - "url": "https://dw.steinbeis.schule", - "name": "FvS-Hilfesystem" + "url": "https://idam.steinbeis.schule/realms/fvs/account/#/security/signingin", + "name": "Authentifizierung/Passwort" }, { "url": "https://mail.steinbeis.schule", "name": "FvS-eMail" }, { - "url": "https://nc.steinbeis.schule", - "name": "FvS-Nextcloud" + "url": "https://dw.steinbeis.schule", + "name": "FvS-Hilfesystem" }, { "url": "https://moodle.steinbeis.schule", "name": "FvS-Moodle" }, + { + "url": "https://nc.steinbeis.schule", + "name": "FvS-Nextcloud" + }, + { + "url": "https://server.pn.steinbeis.schule", + "name": "Schulkonsole" + }, + { + "url": "https://peleus.webuntis.com/WebUntis/?school=Ferd.von+Steinbeis#/basic/login", + "name": "FvS-Stundenplan" + }, + { + "url": "https://kreis-reutlingen.schulanmeldungen.com/anmeldeformulare/avdual", + "name": "Anmeldung AVdual" + }, + { + "url": "https://steinbeisschule-reutlingen.schulanmeldungen.com/", + "name": "Anmeldung FVS" + }, { "name": "Debian", "children": [ diff --git a/roles/custom/fvs/handlers/main.yml b/roles/custom/fvs/handlers/main.yml new file mode 100644 index 0000000..d6688c6 --- /dev/null +++ b/roles/custom/fvs/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: Run update-desktop-database + ansible.builtin.command: update-desktop-database "{{ item }}" + loop: + - /usr/local/share/applications + - /usr/local/share/desktop-directories + - /etc/xdg/menus/applications-merged diff --git a/roles/lmn_fvs/tasks/main.yml b/roles/custom/fvs/tasks/main.yml similarity index 67% rename from roles/lmn_fvs/tasks/main.yml rename to roles/custom/fvs/tasks/main.yml index 1dcfcc6..738b4fe 100644 --- a/roles/lmn_fvs/tasks/main.yml +++ b/roles/custom/fvs/tasks/main.yml @@ -14,11 +14,12 @@ vtype: string when: mirror_msfonts is defined and mirror_msfonts | length > 0 - - name: Install desktop EDU packages and some more - apt: + ansible.builtin.apt: name: - atftp + - audacity + - biber - calligraplan - cmake ## for kdevelop - codelite @@ -30,32 +31,50 @@ - filezilla - freeplane - git + - git-cola - gitg - gitk + - git-gui - htop + - jq - jupyter + - kchmviewer - kdevelop - kdevelop-php - kdevelop-python - krita + - libasound2-dev + - libdbus-glib-1-2 ## needed for zotero - libnotify-bin ## needed for pwroff script + - libwayland-dev + - libxcursor-dev + - libxi-dev + - libxinerama-dev + - libxkbcommon-dev + - libxrandr-dev - links2 - minder + - mosquitto-clients - neovim - net-tools - netcat-openbsd - nmap + - okular-extra-backends ## needed for CHM files - pdf-presenter-console - php-cli - pipx - planner - pulseview + - python3-paho-mqtt - python3-websockets - qpdfview - shellcheck - sigrok - sigrok-cli + - texlive-lang-german - texlive-latex-recommended + - texlive-xetex + - texstudio - tmux - tree - ttf-mscorefonts-installer @@ -70,15 +89,17 @@ http_proxy: '' # this is needed to avoid ttf-mscorefonts-installer picking up aptcacher - name: Remove update notifications from plasma-discover - apt: + ansible.builtin.apt: name: - plasma-discover autoremove: true state: absent + when: fvs_remove_discover - name: Make sure wireshark works for all users after installation and upgrades ansible.builtin.copy: dest: /etc/apt/apt.conf.d/92wireshark4all + mode: '0644' content: | ## Modify permissions after installation/upgrade to allow all ## users dumping packages on network interfaces for wireshark @@ -101,69 +122,52 @@ ansible.builtin.copy: src: policies.json dest: /etc/firefox-esr/policies/ + mode: '0644' +- name: Create chromium policies directory + ansible.builtin.file: + path: /etc/chromium/policies/managed + state: directory + mode: '0755' -- name: Copy some scripts - copy: - src: "{{ item }}" - dest: /usr/local/sbin/ - mode: 0755 - loop: - - pwroff - - bootorder.sh - - reporter - -- name: Provide services and timers for some scripts - copy: - src: "{{ item }}" - dest: "/etc/systemd/system/{{ item }}" - mode: 0644 - loop: - - pwroff.service - - pwroff.timer - - reporter.service - - reporter.timer - -- name: Enable pwroff.timer - systemd: - name: "{{ item }}" - enabled: true - loop: - - pwroff.timer - - reporter.timer - -- name: PXE first boot order - command: /usr/local/sbin/bootorder.sh - register: cmd_result - changed_when: cmd_result.stdout is not search('Nothing to do.') - when: groups.PCroom is defined and inventory_hostname in groups.PCroom +- name: Set chromium proxy-policy to auto_detect + ansible.builtin.copy: + dest: /etc/chromium/policies/managed/proxy.json + mode: '0644' + content: | + { + "ProxyMode": "auto_detect" + } - name: Copy dolphin config scripts ansible.builtin.copy: src: "{{ item }}" dest: /usr/local/bin/ - mode: 0755 + mode: '0755' loop: - lmn-reset-dolphin.sh - lmn-patch-dolphin.sh + - lmn-fixhome-dolphin.sh - name: Configure KDE dolphin menu ansible.builtin.copy: src: lmn-dolphin.sh dest: /etc/profile.d/ + mode: '0644' - name: Copy fvs-config.js to configure plasma ansible.builtin.copy: src: fvs-config.js dest: /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/fvs-config.js - mode: 0644 + mode: '0644' - name: Configure some KDE aspects - blockinfile: + ansible.builtin.blockinfile: path: /etc/xdg/kdeglobals create: true + mode: '0644' block: | [KDE] SingleClick=false @@ -173,64 +177,36 @@ #action/switch_user=false #action/lock_screen=false -- name: Shut down when idle for too long - ansible.builtin.copy: - dest: /etc/xdg/powermanagementprofilesrc - content: | - [AC][SuspendSession][$i] - idleTime=7200000 - suspendType=8 - - name: Start with empty session by default ansible.builtin.copy: dest: /etc/xdg/ksmserverrc + mode: '0644' content: | [General] loginMode=emptySession -- name: Fix primary screen for class room PCs with projector - block: - - name: Switch projector off for login - lineinfile: - dest: /usr/share/sddm/scripts/Xsetup - line: 'xrandr --output {{ dual_screen[0] }} --off' - - name: Deploy fix-screen script - ansible.builtin.template: - src: lmn-fix-screen.j2 - dest: /usr/local/bin/lmn-fix-screen - mode: '0755' - - name: Deploy fix-screen autostarter - ansible.builtin.copy: - dest: /etc/xdg/autostart/lmn-fix-screen.desktop - content: | - [Desktop Entry] - Name=fix-screen - Exec=lmn-fix-screen - Type=Application - NoDisplay=true - when: dual_screen is defined - -#- name: Avoid starting kscreen (confusing autodetection) -# ansible.builtin.copy: -# dest: /etc/xdg/kded5rc -# content: | -# [Module-kscreen] -# autoload=false +# - name: Avoid starting kscreen (confusing autodetection) +# ansible.builtin.copy: +# dest: /etc/xdg/kded5rc +# content: | +# [Module-kscreen] +# autoload=false # -#- name: Disable automatic lock screen and user specific modifications -# ansible.builtin.copy: -# path: /etc/xdg/kscreenlockerrc -# content: | -# [Daemon][$i] -# Autolock=false -# LockOnResume=false +# - name: Disable automatic lock screen and user specific modifications +# ansible.builtin.copy: +# path: /etc/xdg/kscreenlockerrc +# content: | +# [Daemon][$i] +# Autolock=false +# LockOnResume=false # - name: Download libdvdcss from mirror ansible.builtin.get_url: url: "{{ mirror_dvdcss }}/libdvdcss.so.2.2.0" dest: /usr/lib/x86_64-linux-gnu/libdvdcss.so.2.2.0 - use_proxy: False + mode: '0644' + use_proxy: false when: mirror_dvdcss is defined and mirror_dvdcss | length > 0 - name: Link library so name @@ -241,7 +217,7 @@ when: mirror_dvdcss is defined and mirror_dvdcss | length > 0 - name: Patch sddm login screen to show hostname - blockinfile: + ansible.builtin.blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml marker: // {mark} ANSIBLE MANAGED BLOCK insertbefore: '\s+//Footer' @@ -256,3 +232,22 @@ text: sddm.hostName + " | <{{ ansible_date_time['date'] }}>" font.pointSize: config.fontSize } + +- name: Set git default-branch to main + ansible.builtin.copy: + dest: /etc/gitconfig + mode: '0644' + content: | + [init] + defaultBranch = main + +- name: Adjust mmcblk-device gid to allow users to access SD-cards + ansible.builtin.copy: + dest: /etc/udev/rules.d/80-mmcblk.rules + mode: '0644' + content: | + KERNEL=="mmcblk[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" + KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" + +- name: Include sync + ansible.builtin.include_tasks: sync.yml diff --git a/roles/custom/fvs/tasks/sync.yml b/roles/custom/fvs/tasks/sync.yml new file mode 100644 index 0000000..0aed203 --- /dev/null +++ b/roles/custom/fvs/tasks/sync.yml @@ -0,0 +1,58 @@ +--- +- name: Create directory for local .desktop-Files + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: '0755' + loop: + - /usr/local/share/applications + - /usr/local/share/desktop-directories + notify: Run update-desktop-database + +- name: Copy fvs.directory + ansible.builtin.copy: + src: fvs.directory + dest: /usr/local/share/desktop-directories/ + mode: '0644' + notify: Run update-desktop-database + +- name: Copy fvs.menu + ansible.builtin.copy: + src: fvs.menu + dest: /etc/xdg/menus/applications-merged/ + mode: '0644' + notify: Run update-desktop-database + +- name: Copy lmn-sync script + ansible.builtin.copy: + src: lmn-sync + dest: /usr/local/sbin/ + mode: '0755' + register: lmn_sync + +- name: Run lmn-sync script + ansible.builtin.shell: /usr/local/sbin/lmn-sync + when: lmn_sync.changed # noqa: no-handler + +- name: Deploy sudo configurations (lmn-sync for role-teacher) + ansible.builtin.copy: + dest: /etc/sudoers.d/90-lmn-sync + owner: root + group: root + mode: '0700' + content: | + %role-teacher ALL=(root) NOPASSWD: /usr/local/sbin/lmn-sync + +- name: Provide lmn-sync service and timer + ansible.builtin.copy: + src: "{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: '0644' + loop: + - lmn-sync.service + - lmn-sync.timer + +- name: Enable lmn-sync.timer + ansible.builtin.systemd: + name: lmn-sync.timer + enabled: true diff --git a/roles/kerberize/handlers/main.yml b/roles/kerberize/handlers/main.yml index 3ac7e3e..1e2ceab 100644 --- a/roles/kerberize/handlers/main.yml +++ b/roles/kerberize/handlers/main.yml @@ -1,5 +1,5 @@ -- name: reload sshd - systemd: +- name: Reload sshd + ansible.builtin.systemd: name: sshd state: reloaded when: not run_in_installer|default(false)|bool diff --git a/roles/kerberize/tasks/main.yml b/roles/kerberize/tasks/main.yml index ee17a3e..4f6644d 100644 --- a/roles/kerberize/tasks/main.yml +++ b/roles/kerberize/tasks/main.yml @@ -1,28 +1,30 @@ - name: Install kerberos packages - apt: + ansible.builtin.apt: name: krb5-user - state: latest - name: Kerberize sshd server ansible.builtin.copy: dest: /etc/ssh/sshd_config.d/kerberize.conf + mode: '0644' content: | GSSAPIAuthentication yes - notify: "reload sshd" + notify: "Reload sshd" - name: Kerberize ssh client, authenticate and delegate credentials ansible.builtin.copy: dest: /etc/ssh/ssh_config.d/kerberize.conf + mode: '0644' content: | GSSAPIAuthentication yes GSSAPIDelegateCredentials yes - name: Check if firefox is available - stat: path=/etc/firefox-esr/firefox-esr.js + ansible.builtin.stat: + path: /etc/firefox-esr/firefox-esr.js register: firefox - name: Kerberize firefox for sites in the local domain - lineinfile: + ansible.builtin.lineinfile: dest: /etc/firefox-esr/firefox-esr.js line: "{{ item }}" with_items: @@ -32,14 +34,16 @@ when: firefox.stat.exists - name: Ensures /etc/chromium/policies/managed dir exists - file: + ansible.builtin.file: path: "/etc/chromium/policies/managed" state: directory + mode: '0755' - name: Kerberize chromium for sites in the local domain - copy: + ansible.builtin.copy: dest: /etc/chromium/policies/managed/idam.json + mode: '0644' content: | { - "AuthServerAllowlist": "idam.steinbeis.schule" + "AuthServerAllowlist": "{{ kerberize_uris | default(ansible_domain) }}" } diff --git a/roles/lmn_exam/defaults/main.yml b/roles/lmn_exam/defaults/main.yml new file mode 100644 index 0000000..da8c198 --- /dev/null +++ b/roles/lmn_exam/defaults/main.yml @@ -0,0 +1,2 @@ +--- +exam_mode: true diff --git a/roles/lmn_exam/files/pam-exec.sh b/roles/lmn_exam/files/pam-exec.sh new file mode 100644 index 0000000..4f54861 --- /dev/null +++ b/roles/lmn_exam/files/pam-exec.sh @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +# exit if not running as root. Because other user don't have privileges to start/stop firewalld. +[[ "${UID}" -eq "0" ]] || exit 0 + +if [[ "${PAM_USER}" =~ -exam$ ]]; then + systemctl start firewalld.service + if systemctl is-enabled --quiet libvirtd.service; then + systemctl restart libvirtd.service + fi +elif ! (users | grep -q -- "-exam"); then + systemctl stop firewalld.service + if systemctl is-enabled --quiet libvirtd.service; then + systemctl restart libvirtd.service + fi +fi diff --git a/roles/lmn_exam/files/rmexam b/roles/lmn_exam/files/rmexam new file mode 100755 index 0000000..ad71551 --- /dev/null +++ b/roles/lmn_exam/files/rmexam @@ -0,0 +1,16 @@ +#!/usr/bin/bash +# +# rename -exam directories in /home and /lmn/media older than 12h +# remove -exam.* directories in /home and /lmn/media older than 10d +# + +set -eu + +for dir in /home/ /lmn/media ; do + if [[ -d "${dir}" ]]; then + find "${dir}" -maxdepth 1 -mindepth 1 -name '*-exam' -type d -cmin +720 \ + -exec bash -c 'mv "$0" "$0".$( date +%Y%m%d-%H%M --reference="$0" )' {} \; + find "${dir}" -maxdepth 1 -mindepth 1 -name '*-exam.*' -type d -cmin +14400 \ + -exec rm -rf {} \; + fi +done diff --git a/roles/lmn_exam/files/rmexam.service b/roles/lmn_exam/files/rmexam.service new file mode 100644 index 0000000..f442780 --- /dev/null +++ b/roles/lmn_exam/files/rmexam.service @@ -0,0 +1,6 @@ +[Unit] +Description=Rename/Remove -exam directories older than 12h/10d + +[Service] +Type=simple +ExecStart=/usr/local/sbin/rmexam diff --git a/roles/lmn_exam/files/rmexam.timer b/roles/lmn_exam/files/rmexam.timer new file mode 100644 index 0000000..7fba65d --- /dev/null +++ b/roles/lmn_exam/files/rmexam.timer @@ -0,0 +1,8 @@ +[Unit] +Description=Run rmexam after boot + +[Timer] +OnBootSec=0min + +[Install] +WantedBy=timers.target diff --git a/roles/lmn_exam/tasks/main.yml b/roles/lmn_exam/tasks/main.yml new file mode 100644 index 0000000..0e3bc4e --- /dev/null +++ b/roles/lmn_exam/tasks/main.yml @@ -0,0 +1,70 @@ +--- +# Requirement: Install firewalld after installing libvirt +- name: Install firewalld packages + ansible.builtin.apt: + name: + - firewalld + register: result + +- name: Stop firewalld-service + ansible.builtin.systemd: + name: firewalld + state: stopped + when: result.changed # noqa: no-handler + +- name: Disable firewalld-service + ansible.builtin.systemd: + name: firewalld + enabled: false + +- name: Add virbr0 to libvirt zone + ansible.posix.firewalld: + zone: libvirt + interface: virbr0 + permanent: true + state: enabled + when: vm_support is defined and vm_support + +- name: Permit access to cups from libvirt + ansible.posix.firewalld: + zone: libvirt + port: 631/tcp + permanent: true + state: enabled + when: vm_support is defined and vm_support # and printing is defined and printing + +- name: Permit access to usersquid from libvirt + ansible.posix.firewalld: + zone: libvirt + port: 3128/tcp + permanent: true + state: enabled + when: vm_support is defined and vm_support # and localsquid is defined and localsquid + +- name: Copy some scripts + ansible.builtin.copy: + src: "{{ item }}" + dest: /usr/local/sbin/ + mode: '0755' + loop: + - pam-exec.sh + - rmexam + +- name: Enable login script via pam_exec.so + ansible.builtin.lineinfile: + dest: /etc/pam.d/common-session + line: 'session optional pam_exec.so /usr/local/sbin/pam-exec.sh' + +- name: Provide rmexam services and timers for some scripts + ansible.builtin.copy: + src: "{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: '0644' + loop: + - rmexam.service + - rmexam.timer + +- name: Enable rmexam.timer + ansible.builtin.systemd: + name: rmexam.timer + enabled: true diff --git a/roles/lmn_finish/defaults/main.yml b/roles/lmn_finish/defaults/main.yml new file mode 100644 index 0000000..4db4d23 --- /dev/null +++ b/roles/lmn_finish/defaults/main.yml @@ -0,0 +1,6 @@ +extra_pkgs: [] +extra_pkgs1: [] +extra_pkgs2: [] +extra_pkgs_bpo: [] +extra_pkgs_bpo1: [] +extra_pkgs_bpo2: [] diff --git a/roles/lmn_finish/tasks/main.yaml b/roles/lmn_finish/tasks/main.yaml new file mode 100644 index 0000000..5f3a787 --- /dev/null +++ b/roles/lmn_finish/tasks/main.yaml @@ -0,0 +1,33 @@ +--- +- name: Install extra packages from stable + ansible.builtin.apt: + name: "{{ item }}" + loop: + - "{{ extra_pkgs }}" + - "{{ extra_pkgs1 }}" + - "{{ extra_pkgs2 }}" + +- name: Add backports for {{ ansible_distribution_release }} + ansible.builtin.apt_repository: + repo: > + deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports + main non-free-firmware + state: present + update_cache: true +# when: extra_pkgs_bpo|length + +- name: Install extra packages from backports + ansible.builtin.apt: + name: "{{ item }}" + state: latest # noqa package-latest + default_release: "{{ ansible_distribution_release }}-backports" + loop: + - "{{ extra_pkgs_bpo }}" + - "{{ extra_pkgs_bpo1 }}" + - "{{ extra_pkgs_bpo2 }}" + +- 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 + changed_when: false + tags: upgrade diff --git a/roles/lmn_fvs/templates/lmn-fix-screen.j2 b/roles/lmn_fvs/templates/lmn-fix-screen.j2 deleted file mode 100644 index 2aa7cc2..0000000 --- a/roles/lmn_fvs/templates/lmn-fix-screen.j2 +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/bash -# -# Set the primary screen after login -# -set -eu - -sleep 5 -if [[ "$XDG_SESSION_TYPE" = wayland ]] ; then - kscreen-doctor output.{{ dual_screen[1] }}.priority.1 -fi diff --git a/roles/lmn_kde/defaults/main.yml b/roles/lmn_kde/defaults/main.yml new file mode 100644 index 0000000..779142b --- /dev/null +++ b/roles/lmn_kde/defaults/main.yml @@ -0,0 +1,36 @@ +--- +kde_desktop_pkg: + - akonadi-backend-sqlite + - arduino + - bluefish + - calligra + - codeblocks + - dia + - flameshot + - freecad + - fritzing + - ghex + - gimp + - inkscape + - kde-full + - keepassxc + - librecad + - mu-editor + - openboard + - qtcreator + - spyder + - sqlite3 + - sqlitebrowser + - task-german-desktop + - task-german-kde-desktop + - task-kde-desktop + - thonny + - thunderbird-l10n-de + - vlc + - vym + - webext-privacy-badger + - webext-ublock-origin-chromium + - webext-ublock-origin-firefox + - xdg-desktop-portal-kde + - xdg-desktop-portal-wlr # share screen in browser + - xournalpp diff --git a/roles/lmn_kde/handlers/main.yml b/roles/lmn_kde/handlers/main.yml deleted file mode 100644 index e2b8cdf..0000000 --- a/roles/lmn_kde/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -- name: Run update-grub - command: update-grub diff --git a/roles/lmn_kde/tasks/main.yml b/roles/lmn_kde/tasks/main.yml index 99c5c84..052606b 100644 --- a/roles/lmn_kde/tasks/main.yml +++ b/roles/lmn_kde/tasks/main.yml @@ -1,58 +1,23 @@ --- - name: Install desktop and educational packages - apt: - name: - - akonadi-backend-sqlite - - arduino - - bluefish - - calligra - - codeblocks - - dia - - flameshot - - freecad - - fritzing - - ghex - - gimp - - inkscape - - kde-full - - keepassxc - - librecad - - mu-editor - - openboard - - qtcreator - - spyder - - sqlite3 - - sqlitebrowser - - task-german-desktop - - task-german-kde-desktop - - task-kde-desktop - - thonny - - thunderbird-l10n-de - - vlc - - vym - - webext-privacy-badger - - webext-ublock-origin-chromium - - webext-ublock-origin-firefox - - xdg-desktop-portal-kde - - xdg-desktop-portal-wlr # share screen in browser - - xournalpp - autoremove: true - state: latest + ansible.builtin.apt: + name: "{{ kde_desktop_pkg }}" -- name: Add {{ ansible_distribution_release }}-backports - apt_repository: +- name: Add backports {{ ansible_distribution_release }} + ansible.builtin.apt_repository: repo: deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main non-free-firmware state: present update_cache: true - name: Install extra packages from backports - apt: + ansible.builtin.apt: name: - filius - kicad - kicad-doc-de - libreoffice - libreoffice-l10n-de + - libreoffice-qt5 state: latest # noqa package-latest autoremove: true default_release: "{{ ansible_distribution_release }}-backports" @@ -65,16 +30,17 @@ mode: '0755' - name: Use sqlite in akonadi - blockinfile: + ansible.builtin.blockinfile: path: /etc/xdg/akonadi/akonadiserverrc create: true + mode: '0644' block: | [%General] Driver=QSQLITE3 ## Akonadi complains if not set: - name: Add home dirs to apparmor - lineinfile: + ansible.builtin.lineinfile: dest: /etc/apparmor.d/tunables/home.d/ubuntu line: >- @{HOMEDIRS}+=/srv/samba/schools/default-school/teachers/ @@ -82,89 +48,26 @@ /srv/samba/schools/default-school/examusers/ -- name: tune SDDM login - blockinfile: +- name: Tune SDDM login + ansible.builtin.blockinfile: path: /etc/sddm.conf create: true + mode: '0644' block: | [Users] MaximumUid=999 RememberLastUser=false RememberLastSession=false -- name: Enable wake-on-lan for all ethernet connections - ansible.builtin.copy: - dest: /etc/NetworkManager/conf.d/wake-on-lan.conf - content: | - [connection] - ethernet.wake-on-lan=64 - -- name: Create directory to avoid suspend - ansible.builtin.file: - path: /etc/systemd/sleep.conf.d/ - state: directory - mode: '0755' - -- name: Avoid suspending - blockinfile: - path: /etc/systemd/sleep.conf.d/nosuspend.conf - create: true - block: | - [Sleep] - AllowSuspend=no - AllowHibernation=no - AllowSuspendThenHibernate=no - AllowHybridSleep=no - - name: Deploy dolphin script - copy: + ansible.builtin.copy: src: lmn-fix-dolphin.sh dest: /usr/local/bin/ mode: '0755' -################# general settings ################## -- name: Enable boot splash screen - replace: - dest: "/etc/default/grub" - regexp: '"quiet"$' - replace: '"quiet splash"' - notify: Run update-grub - -- name: Protect editing grub menu entries - blockinfile: - path: /etc/grub.d/40_custom - block: | - set superusers='root' - export superusers - password_pbkdf2 root {{ grub_pwd }} - notify: Run update-grub - -- name: Allow booting grub menu entries - lineinfile: - dest: /etc/grub.d/10_linux - line: CLASS="${CLASS} --unrestricted" - insertafter: '^CLASS=.*' - firstmatch: true - notify: Run update-grub - -- name: Disable Grub submenus - lineinfile: - dest: /etc/default/grub - line: 'GRUB_DISABLE_SUBMENU=true' - insertafter: '^GRUB_TIMEOUT=.*' - notify: Run update-grub - -- name: Grub timeout - lineinfile: - dest: /etc/default/grub - regexp: '^(GRUB_TIMEOUT=).*' - line: '\g<1>1' - backrefs: yes - notify: Run update-grub - -- name: Keyboard compose key - lineinfile: - dest: /etc/default/keyboard - regexp: '^(XKBOPTIONS=).*' - line: '\1"compose:caps"' - backrefs: yes +- name: Default KDE filepicker + ansible.builtin.lineinfile: + path: /etc/environment.d/90lmn-filepicker.conf + create: true + mode: '0644' + line: GTK_USE_PORTAL=1 diff --git a/roles/lmn_localhome/defaults/main.yml b/roles/lmn_localhome/defaults/main.yml new file mode 100644 index 0000000..3ebcb77 --- /dev/null +++ b/roles/lmn_localhome/defaults/main.yml @@ -0,0 +1,3 @@ +--- +localhome: false +localhome_logout_missing_serverhome: true diff --git a/roles/lmn_localhome/files/lmn-create-unisonconfig.sh b/roles/lmn_localhome/files/lmn-create-unisonconfig.sh new file mode 100644 index 0000000..56f3b4e --- /dev/null +++ b/roles/lmn_localhome/files/lmn-create-unisonconfig.sh @@ -0,0 +1,29 @@ +#!/usr/bin/bash +# +# create ~/.unison/SyncHome.prf if not exists +# +set -eu + +[[ -f ~/.unison/SyncHome.prf ]] && exit 0 + +mkdir -p ~/.unison + +if id | grep teachers; then + NETHOME="$(find /srv/samba/schools/default-school/teachers/ -maxdepth 1 -type d -name "${USER}")" +else + NETHOME="$(find /srv/samba/schools/default-school/students/ -maxdepth 2 -type d -name "${USER}")" +fi + +if [[ ! -f ~/.unison/SyncHome.prf ]]; then + echo "# Unison preferences +label = Sync Home on Server +path = Bilder +path = Dokumente +path = Musik +path = Videos +root = $HOME +root = $NETHOME +dontchmod = true +perms = 0" > ~/.unison/SyncHome.prf +fi + diff --git a/roles/lmn_localhome/tasks/main.yml b/roles/lmn_localhome/tasks/main.yml new file mode 100644 index 0000000..3122720 --- /dev/null +++ b/roles/lmn_localhome/tasks/main.yml @@ -0,0 +1,39 @@ +--- +- name: Enable pam_mkhomedir.so + ansible.builtin.lineinfile: + dest: /etc/pam.d/common-session + line: "session optional pam_mkhomedir.so umask=0077" + insertbefore: '^session\s*optional\s*pam_mount.so' + +- name: Patch sddm login screen to inform about localhome + ansible.builtin.blockinfile: + path: /usr/share/sddm/themes/debian-breeze/Main.qml + marker: // {mark} ANSIBLE MANAGED BLOCK localhome + insertbefore: '\s+//Footer' + block: | + Text { + id: localhome + anchors.top: parent.top + anchors.left: parent.left + anchors.topMargin: 10 + anchors.leftMargin: 15 + color: "#ffffff" + text: "Lokale Anmeldung!\nHome-Verzeichnis liegt nicht im Netz!" + font.pointSize: config.fontSize + } + +- name: Copy unison-createconfig scripts + ansible.builtin.copy: + src: lmn-create-unisonconfig.sh + dest: /usr/local/bin/ + mode: '0755' + +- name: Install auto-logout-script for first login in /etc/profile.d/ + ansible.builtin.copy: + dest: /etc/profile.d/lmn-logout.sh + mode: '0755' + content: | + [[ "${UID}" -gt 10000 ]] && ! findmnt "/lmn/media/${USER}/home" > /dev/null && exit 0 + {% if localhome_logout_missing_serverhome %} + [[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0 + {% endif %} diff --git a/roles/lmn_localproxy/defaults/main.yml b/roles/lmn_localproxy/defaults/main.yml new file mode 100644 index 0000000..491de17 --- /dev/null +++ b/roles/lmn_localproxy/defaults/main.yml @@ -0,0 +1,3 @@ +--- +localproxy: false +localproxy_parent: "firewall.{{ domain }}" diff --git a/roles/lmn_localproxy/files/usersquid.service b/roles/lmn_localproxy/files/usersquid.service new file mode 100644 index 0000000..dbba4a0 --- /dev/null +++ b/roles/lmn_localproxy/files/usersquid.service @@ -0,0 +1,11 @@ +[Unit] +Description=Run squid in usermode using user kerberos ticket + +[Service] +Type=simple +ExecStart=/usr/local/bin/startusersquid.sh +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=xdg-desktop-autostart.target diff --git a/roles/lmn_localproxy/tasks/main.yml b/roles/lmn_localproxy/tasks/main.yml new file mode 100644 index 0000000..b9944ed --- /dev/null +++ b/roles/lmn_localproxy/tasks/main.yml @@ -0,0 +1,48 @@ +--- +- name: Install squid + ansible.builtin.apt: + name: + - squid + +- name: Disable squid + ansible.builtin.systemd: + name: squid + enabled: false + state: stopped + +- name: Deploy squid user mode configuration + ansible.builtin.template: + src: "{{ item }}.j2" + dest: "/etc/squid/{{ item }}" + mode: '0644' + loop: + - squid-usermode.conf + - squid-usermode-external.conf + +- name: Deploy startusersquid script + ansible.builtin.template: + src: startusersquid.sh.j2 + dest: /usr/local/bin/startusersquid.sh + mode: '0755' + +- name: Provide usersquid service + ansible.builtin.copy: + src: usersquid.service + dest: /etc/systemd/user/usersquid.service + mode: '0644' + +- name: Enable usersquid service + ansible.builtin.systemd: + name: usersquid.service + scope: global + enabled: true + +- name: Deploy http proxy config + ansible.builtin.copy: + dest: /etc/environment.d/10-lmn-proxy.conf + mode: '0644' + content: | + http_proxy="http://localhost:3128" + https_proxy="http://localhost:3128" + ftp_proxy="http://localhost:3128" + no_proxy="{{ no_proxy }}" diff --git a/roles/lmn_localproxy/templates/squid-usermode-external.conf.j2 b/roles/lmn_localproxy/templates/squid-usermode-external.conf.j2 new file mode 100644 index 0000000..175b480 --- /dev/null +++ b/roles/lmn_localproxy/templates/squid-usermode-external.conf.j2 @@ -0,0 +1,14 @@ +acl local-servers dstdomain .{{ domain }} +cache_peer {{ localproxy_parent }} parent 3128 0 no-query default login=NEGOTIATE auth-no-keytab +never_direct deny local-servers +always_direct allow all +#access_log stdio:/tmp/access.log squid +access_log none +cache_log /dev/null +logfile_rotate 0 +pid_filename none +{% if vm_support %} +http_port 192.168.122.1:3128 +{% endif %} +http_port 127.0.0.1:3128 +http_access allow all diff --git a/roles/lmn_vm/templates/squid-usermode.conf.j2 b/roles/lmn_localproxy/templates/squid-usermode.conf.j2 similarity index 62% rename from roles/lmn_vm/templates/squid-usermode.conf.j2 rename to roles/lmn_localproxy/templates/squid-usermode.conf.j2 index 586dbb1..8ec4915 100644 --- a/roles/lmn_vm/templates/squid-usermode.conf.j2 +++ b/roles/lmn_localproxy/templates/squid-usermode.conf.j2 @@ -1,5 +1,5 @@ acl local-servers dstdomain .{{ domain }} -cache_peer firewall.{{ domain }} parent 3128 0 no-query default login=NEGOTIATE auth-no-keytab +cache_peer {{ localproxy_parent }} parent 3128 0 no-query default login=NEGOTIATE auth-no-keytab never_direct deny local-servers never_direct allow all #access_log stdio:/tmp/access.log squid @@ -7,5 +7,8 @@ access_log none cache_log /dev/null logfile_rotate 0 pid_filename none +{% if vm_support %} http_port 192.168.122.1:3128 +{% endif %} +http_port 127.0.0.1:3128 http_access allow all diff --git a/roles/lmn_localproxy/templates/startusersquid.sh.j2 b/roles/lmn_localproxy/templates/startusersquid.sh.j2 new file mode 100755 index 0000000..2bb39a7 --- /dev/null +++ b/roles/lmn_localproxy/templates/startusersquid.sh.j2 @@ -0,0 +1,8 @@ +#!/usr/bin/bash +# + +if nslookup firewall.{{ domain }}; then + /usr/sbin/squid --foreground -f /etc/squid/squid-usermode.conf +else + /usr/sbin/squid --foreground -f /etc/squid/squid-usermode-external.conf +fi diff --git a/roles/lmn_localuser/defaults/main.yml b/roles/lmn_localuser/defaults/main.yml new file mode 100644 index 0000000..4a2ae0b --- /dev/null +++ b/roles/lmn_localuser/defaults/main.yml @@ -0,0 +1,4 @@ +--- +localuser: false +localuser_password: "Muster!" +localuser_secretsalt: "4ANAxPycC3q" diff --git a/roles/lmn_localuser/tasks/main.yml b/roles/lmn_localuser/tasks/main.yml index 6b619f6..26e8fa2 100644 --- a/roles/lmn_localuser/tasks/main.yml +++ b/roles/lmn_localuser/tasks/main.yml @@ -15,7 +15,7 @@ uid: 1001 password_expire_min: 99999 createhome: false - password: "{{ localuser_pwd }}" + password: "{{ localuser_password | password_hash('sha512',localuser_secretsalt) }}" - name: Prepare generator for local guest user ansible.builtin.copy: diff --git a/roles/lmn_misc/defaults/main.yml b/roles/lmn_misc/defaults/main.yml new file mode 100644 index 0000000..e9f1ebd --- /dev/null +++ b/roles/lmn_misc/defaults/main.yml @@ -0,0 +1,9 @@ +--- +misc_avoid_suspend: true +misc_pwroff: true +misc_pwroff_idle: true +misc_pxe_first: false +misc_reporter: false +misc_reporter_serv: "localhost 1234" +misc_clonescreen: false +misc_clonescreen_mode: "1920x1080@60" diff --git a/roles/lmn_fvs/files/bootorder.sh b/roles/lmn_misc/files/bootorder.sh similarity index 100% rename from roles/lmn_fvs/files/bootorder.sh rename to roles/lmn_misc/files/bootorder.sh diff --git a/roles/lmn_fvs/files/pwroff b/roles/lmn_misc/files/pwroff similarity index 100% rename from roles/lmn_fvs/files/pwroff rename to roles/lmn_misc/files/pwroff diff --git a/roles/lmn_fvs/files/pwroff.service b/roles/lmn_misc/files/pwroff.service similarity index 100% rename from roles/lmn_fvs/files/pwroff.service rename to roles/lmn_misc/files/pwroff.service diff --git a/roles/lmn_fvs/files/pwroff.timer b/roles/lmn_misc/files/pwroff.timer similarity index 100% rename from roles/lmn_fvs/files/pwroff.timer rename to roles/lmn_misc/files/pwroff.timer diff --git a/roles/lmn_fvs/files/reporter b/roles/lmn_misc/files/reporter similarity index 95% rename from roles/lmn_fvs/files/reporter rename to roles/lmn_misc/files/reporter index f665a6f..2ee481f 100755 --- a/roles/lmn_fvs/files/reporter +++ b/roles/lmn_misc/files/reporter @@ -11,7 +11,7 @@ n=0 cmds=( 'uname -a' - 'tail -1 /root/.ansible/stamps' + '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" | \ diff --git a/roles/lmn_fvs/files/reporter.service b/roles/lmn_misc/files/reporter.service similarity index 100% rename from roles/lmn_fvs/files/reporter.service rename to roles/lmn_misc/files/reporter.service diff --git a/roles/lmn_fvs/files/reporter.timer b/roles/lmn_misc/files/reporter.timer similarity index 100% rename from roles/lmn_fvs/files/reporter.timer rename to roles/lmn_misc/files/reporter.timer diff --git a/roles/lmn_misc/handlers/main.yml b/roles/lmn_misc/handlers/main.yml new file mode 100644 index 0000000..8a20c3b --- /dev/null +++ b/roles/lmn_misc/handlers/main.yml @@ -0,0 +1,2 @@ +- name: Run update-grub + ansible.builtin.command: update-grub diff --git a/roles/lmn_misc/tasks/main.yml b/roles/lmn_misc/tasks/main.yml new file mode 100644 index 0000000..22134c5 --- /dev/null +++ b/roles/lmn_misc/tasks/main.yml @@ -0,0 +1,217 @@ +--- +- name: Enable wake-on-lan for all ethernet connections + ansible.builtin.copy: + dest: /etc/NetworkManager/conf.d/wake-on-lan.conf + mode: '0644' + content: | + [connection] + ethernet.wake-on-lan=64 + +- name: Prepare directory for apt-daily override + ansible.builtin.file: + path: /etc/systemd/system/apt-daily.timer.d/ + mode: '0755' + state: directory + +- name: Run apt update early to avoid outdated package lists + ansible.builtin.copy: + dest: /etc/systemd/system/apt-daily.timer.d/override.conf + mode: '0644' + content: | + [Timer] + RandomizedDelaySec=30m + +# Avoid suspend + +- name: Create directory to avoid suspend + ansible.builtin.file: + path: /etc/systemd/sleep.conf.d/ + state: directory + mode: '0755' + when: misc_avoid_suspend + +- name: Avoid suspending + ansible.builtin.blockinfile: + path: /etc/systemd/sleep.conf.d/nosuspend.conf + create: true + mode: '0644' + block: | + [Sleep] + AllowSuspend=no + AllowHibernation=no + AllowSuspendThenHibernate=no + AllowHybridSleep=no + when: misc_avoid_suspend + +# Auto Poweroff + +- name: Copy pwroff script + ansible.builtin.copy: + src: pwroff + dest: /usr/local/sbin/ + mode: '0755' + +- name: Provide services and timers for pwroff + ansible.builtin.copy: + src: "{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: '0644' + loop: + - pwroff.service + - pwroff.timer + when: misc_pwroff + +- name: Enable pwroff.timer + ansible.builtin.systemd: + name: pwroff.timer + enabled: true + when: misc_pwroff + +# Shut down when idle for too long + +- name: Shut down when idle for too long + ansible.builtin.copy: + dest: /etc/xdg/powermanagementprofilesrc + mode: '0644' + content: | + [AC][SuspendSession] + idleTime=7200000 + suspendType=8 + when: misc_pwroff_idle + +# Boot splash + +- name: Enable boot splash screen + ansible.builtin.replace: + dest: "/etc/default/grub" + regexp: '"quiet"$' + replace: '"quiet splash"' + notify: Run update-grub + +# Grub settings + +- name: Protect editing grub menu entries + ansible.builtin.blockinfile: + path: /etc/grub.d/40_custom + block: | + set superusers='root' + export superusers + password_pbkdf2 root {{ grub_pwd }} + notify: Run update-grub + when: grub_pwd|default(false) + +- name: Allow booting grub menu entries + ansible.builtin.lineinfile: + dest: /etc/grub.d/10_linux + line: CLASS="${CLASS} --unrestricted" + insertafter: '^CLASS=.*' + firstmatch: true + notify: Run update-grub + +- name: Disable Grub submenus + ansible.builtin.lineinfile: + dest: /etc/default/grub + line: 'GRUB_DISABLE_SUBMENU=true' + insertafter: '^GRUB_TIMEOUT=.*' + notify: Run update-grub + +- name: Grub timeout + ansible.builtin.lineinfile: + dest: /etc/default/grub + regexp: '^(GRUB_TIMEOUT=).*' + line: '\g<1>1' + backrefs: true + notify: Run update-grub + +# PXE first boot order + +- name: Copy some scripts + ansible.builtin.copy: + src: bootorder.sh + dest: /usr/local/sbin/ + mode: '0755' + when: misc_pxe_first + +- name: PXE first boot order + ansible.builtin.command: /usr/local/sbin/bootorder.sh + register: cmd_result + changed_when: cmd_result.stdout is not search('Nothing to do.') + when: misc_pxe_first + +# Disable Caps Lock + +- name: Keyboard compose key + ansible.builtin.lineinfile: + dest: /etc/default/keyboard + regexp: '^(XKBOPTIONS=).*' + line: '\1"compose:caps"' + backrefs: true + +# Activate unattended upgrades + +- name: Install unattended-upgrades + ansible.builtin.apt: + name: + - unattended-upgrades + +- name: Update all packages unattended + ansible.builtin.replace: + path: /etc/apt/apt.conf.d/50unattended-upgrades + regexp: '^//(\s+"origin=.+-updates";)$' + replace: ' \1' + +# Install reporter + +- name: Copy reporter + ansible.builtin.template: + src: reporter.j2 + dest: /usr/local/sbin/reporter + mode: '0755' + +- name: Provide services and timers for reporter + ansible.builtin.copy: + src: "{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: '0644' + loop: + - reporter.service + - reporter.timer + when: misc_reporter + +- name: Enable reporter.timer + ansible.builtin.systemd: + name: reporter.timer + enabled: true + when: misc_reporter + +# Prepare CloneScreen on Presenter PCs + +- name: Fix primary screen for class room PCs with projector + when: misc_clonescreen + block: + - name: Set primary screen for login + ansible.builtin.blockinfile: + path: /usr/share/sddm/scripts/Xsetup + block: | + xrandr --output {{ dual_screen[0] }} --primary + when: dual_screen is defined + - name: Reset primary screen for login + ansible.builtin.blockinfile: + path: /usr/share/sddm/scripts/Xsetup + state: absent + when: dual_screen is not defined + - name: Deploy fix-screen script + ansible.builtin.template: + src: lmn-fix-screen.j2 + dest: /usr/local/bin/lmn-fix-screen + mode: '0755' + - name: Deploy fix-screen autostarter + ansible.builtin.copy: + dest: /etc/xdg/autostart/lmn-fix-screen.desktop + mode: '0644' + content: | + [Desktop Entry] + Name=fix-screen + Exec=lmn-fix-screen + Type=Application + NoDisplay=true diff --git a/roles/lmn_misc/templates/lmn-fix-screen.j2 b/roles/lmn_misc/templates/lmn-fix-screen.j2 new file mode 100644 index 0000000..a70ec3b --- /dev/null +++ b/roles/lmn_misc/templates/lmn-fix-screen.j2 @@ -0,0 +1,29 @@ +#!/usr/bin/bash +# +# Set the primary screen after login +# Clone screen on all displays +# Set audio-default-sink +# +set -eu + +if [[ "$XDG_SESSION_TYPE" = wayland ]] ; then + while ! kscreen-doctor -o; do + sleep 1 + done + sleep 2 + {% if dual_screen is defined %} + kscreen-doctor output.{{ dual_screen[1] }}.priority.1 + {% endif %} + for N in $(kscreen-doctor -j | jq -r .outputs[].name) ; do + kscreen-doctor output.$N.mode.{{ misc_clonescreen_mode }} output.$N.position.0,0 output.$N.scale.$(kscreen-doctor -j | jq .outputs[].scale | sort | head -1); + done +fi +{% if audio_output is defined %} + 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 + 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 +fi +{% endif %} diff --git a/roles/lmn_misc/templates/reporter.j2 b/roles/lmn_misc/templates/reporter.j2 new file mode 100755 index 0000000..6a19bec --- /dev/null +++ b/roles/lmn_misc/templates/reporter.j2 @@ -0,0 +1,33 @@ +#!/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="{{ misc_reporter_serv }} 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_mount/defaults/main.yml b/roles/lmn_mount/defaults/main.yml index cf3a823..138287f 100644 --- a/roles/lmn_mount/defaults/main.yml +++ b/roles/lmn_mount/defaults/main.yml @@ -1,2 +1,3 @@ smb_server: "server" smb_share: "default-school/" +nfs4: false diff --git a/roles/lmn_mount/tasks/main.yml b/roles/lmn_mount/tasks/main.yml index c2cf63c..0f09299 100644 --- a/roles/lmn_mount/tasks/main.yml +++ b/roles/lmn_mount/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Install needed packages - apt: + ansible.builtin.apt: name: - libpam-mount - cifs-utils @@ -10,7 +10,7 @@ state: latest - name: Configure pam_mount for Webdav Nextcloud - blockinfile: + ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml marker: "" block: | @@ -18,14 +18,14 @@ fstype="davfs" path="{{ web_dav }}" mountpoint="/lmn/media/%(USER)/nextcloud" - options="username=%(USER),nosuid,nodev,uid=%(USER),gid=1010,grpid,file_mode=0770,dir_mode=0770,forceuid,forcegid" - >rootansibleDebian-gdmsddm{{ localuser }} + options="username=%(USER),nosuid,nodev,uid=%(USER),gid=%(USERGID),grpid,file_mode=0700,dir_mode=0700,forceuid,forcegid" + >rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} insertafter: "" when: web_dav is defined and web_dav | length > 0 - name: Configure pam_mount for LMN homes - blockinfile: + ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml marker: "" block: | @@ -34,8 +34,8 @@ server="{{ smb_server }}" path="{{ smb_share }}" mountpoint="/srv/samba/schools/default-school" - options="sec=krb5i,cruid=%(USERUID),user=%(USER),gid=1010,file_mode=0770,dir_mode=0770,mfsymlinks,nobrl,actimeo=600{{ cifsopt | default(",cache=loose") }}" - >rootansibleDebian-gdmsddm{{ localuser }} + options="sec=krb5i,cruid=%(USERUID),user=%(USER),gid=%(USERGID),file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600{{ cifsopt | default(",cache=loose") }}" + >rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} insertafter: "" @@ -55,6 +55,7 @@ ansible.builtin.file: path: /etc/systemd/user-environment-generators/ state: directory + mode: '0755' - name: Prepare generator for persistent user cache directory ansible.builtin.copy: @@ -92,6 +93,15 @@ state: present fstype: none +- name: Mount NFSv4 tools directory + ansible.posix.mount: + src: "{{ nfs_server }}:tools" + path: /lmn/tools + opts: rw,_netdev,x-systemd.automount,x-systemd.idle-timeout=10s,timeo=100,soft + state: present + fstype: nfs4 + when: nfs_server is defined + - name: Mount NFSv4 home directory ansible.posix.mount: src: server:/default-school diff --git a/roles/lmn_network/tasks/main.yml b/roles/lmn_network/tasks/main.yml index 0c7176a..7a39349 100644 --- a/roles/lmn_network/tasks/main.yml +++ b/roles/lmn_network/tasks/main.yml @@ -1,29 +1,23 @@ --- -- name: Deploy http proxy config - copy: - dest: /etc/environment.d/10-lmn-proxy.conf - content: | - http_proxy="{{ proxy }}" - https_proxy="{{ proxy }}" - ftp_proxy="{{ proxy }}" - no_proxy="{{ no_proxy }}" - - name: Set aptcache ansible.builtin.copy: dest: /etc/apt/apt.conf + mode: '0644' content: > {{ apt_conf }} + when: apt_conf|default(false) - name: Set NTP server ansible.builtin.lineinfile: path: /etc/systemd/timesyncd.conf insertafter: '^#NTP=' line: NTP={{ ntp_serv }} + when: ntp_serv|default(false) - name: Add proposed-updates repository - apt_repository: + ansible.builtin.apt_repository: repo: > deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-proposed-updates main non-free-firmware state: present - when: groups.R202 is defined and inventory_hostname in groups.R202 + when: "'R202' in group_names" diff --git a/roles/lmn_networkd/tasks/main.yml b/roles/lmn_networkd/tasks/main.yml deleted file mode 100644 index 31e9742..0000000 --- a/roles/lmn_networkd/tasks/main.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -# temporary disable network manager -- name: Use iwd but ignore interfaces managed by systemd-networkd (wlan0,en*) - blockinfile: - dest: /etc/NetworkManager/NetworkManager.conf - block: | - [device] - match-device=interface-name:wlx* - wifi.backend=iwd - [connection] - match-device=interface-name:wlx* - ipv4.route-metric=2048 - [keyfile] - unmanaged-devices=interface-name:wlan0;interface-name:en*;interface-name:vm* - -- name: Enable Networkmanager - ansible.builtin.systemd: - name: NetworkManager.service - #state: started - enabled: true - -- name: Configure systemd-networkd virbr1.netdev - ansible.builtin.copy: - dest: "/etc/systemd/network/30-{{ item }}.netdev" - content: | - [NetDev] - Name={{ item }} - Kind=bridge - loop: - - virbr1 - - virbr2 - -- name: Set MAC-Address of virtio1 to ethernet nic - ansible.builtin.lineinfile: - path: /etc/systemd/network/30-virbr1.netdev - line: "MACAddress={{ ansible_facts[ansible_interfaces | select('search', '^en.*') | first].macaddress }}" - when: ansible_interfaces | select('search', '^en.*') - -- name: Configure systemd-networkd ethernet.network - ansible.builtin.copy: - dest: /etc/systemd/network/40-ethernet.network - content: | - [Match] - Name=enp* - [Network] - Bridge=virbr1 - -- name: Configure systemd-networkd ethernet-usb.network - ansible.builtin.copy: - dest: /etc/systemd/network/40-ethernet-usb.network - content: | - [Match] - Name=enx* - [Network] - Bridge=virbr2 - -- name: Configure systemd-networkd virbr1.network - ansible.builtin.copy: - dest: /etc/systemd/network/50-virbr1.network - content: | - [Match] - Name=virbr1 - [Network] - DHCP=yes - [DHCPv4] - UseDomains=true - RouteMetric=512 - -- name: Configure systemd-networkd virbr2.network - ansible.builtin.copy: - dest: /etc/systemd/network/50-virbr2.network - content: | - [Match] - Name=virbr2 - [Network] - DHCP=yes - [DHCPv4] - UseDomains=false - RouteMetric=2048 - -- name: Configure systemd-networkd wlan.network - ansible.builtin.copy: - dest: /etc/systemd/network/60-wlan0-dhcp.network - content: | - [Match] - Name=wlan0 - [Network] - DHCP=yes - [DHCPv4] - UseDomains=true diff --git a/roles/lmn_printer/defaults/main.yml b/roles/lmn_printer/defaults/main.yml new file mode 100644 index 0000000..c9c42f9 --- /dev/null +++ b/roles/lmn_printer/defaults/main.yml @@ -0,0 +1,2 @@ +--- +printer_admin_group: "" diff --git a/roles/lmn_printer/tasks/main.yml b/roles/lmn_printer/tasks/main.yml index 419edd9..960b1fa 100644 --- a/roles/lmn_printer/tasks/main.yml +++ b/roles/lmn_printer/tasks/main.yml @@ -1,26 +1,25 @@ --- - name: Install cups - apt: + ansible.builtin.apt: name: - cups - state: latest - name: Disable cups printer browsing - lineinfile: + ansible.builtin.lineinfile: dest: /etc/cups/cupsd.conf regexp: '^(Browsing ).*' line: '\1No' - backrefs: yes + backrefs: true -- name: Listen on VMBridge - lineinfile: +- name: Listen on all Interfaces + ansible.builtin.lineinfile: dest: /etc/cups/cupsd.conf - line: 'Listen 192.168.122.1:631' - insertafter: 'Listen localhost:631' + line: 'Listen *:631' + regexp: '^Listen localhost' state: present - name: Allow access from localhost and from VM - blockinfile: + ansible.builtin.blockinfile: dest: /etc/cups/cupsd.conf block: | Allow localhost @@ -32,28 +31,37 @@ - "/" - "/admin" +- name: Allow group role-teacher to manage printers + ansible.builtin.lineinfile: + dest: /etc/cups/cups-files.conf + line: "SystemGroup root lpadmin {{ printer_admin_group }}" + regexp: '^SystemGroup' + state: present + when: printer_admin_group | length + - name: Disable cups-browsed ansible.builtin.systemd: name: cups-browsed.service state: stopped - enabled: no + enabled: false - name: Install install-printers.sh - template: + ansible.builtin.template: src: install-printers.sh.j2 dest: /usr/local/bin/install-printers.sh - mode: 0755 + mode: '0755' - name: Install lmn-install-printers sudoers - copy: + ansible.builtin.copy: src: 90-lmn-install-printers dest: /etc/sudoers.d/ - mode: 0660 + mode: '0660' owner: root group: root - name: Run printer script from /etc/profile.d/ - copy: + ansible.builtin.copy: dest: /etc/profile.d/lmn-printer.sh + mode: '0644' content: | [[ "${UID}" -gt 10000 ]] && (sudo /usr/local/bin/install-printers.sh > /dev/null &) diff --git a/roles/lmn_printer/templates/install-printers.sh.j2 b/roles/lmn_printer/templates/install-printers.sh.j2 index 3e6629c..e9129a0 100644 --- a/roles/lmn_printer/templates/install-printers.sh.j2 +++ b/roles/lmn_printer/templates/install-printers.sh.j2 @@ -2,10 +2,13 @@ set -eu +## Exit if first printserver is not reachable +ping -c1 -W1 {{ printservers | first }} || exit 0 + printservers="{{ printservers | join(' ') }}" hostgroup="$(id -Gn "${HOSTNAME^^}$")" usergroup="$(id -Gn "${SUDO_USER}")" -installedprinters="$(lpstat -p | cut -f 2 -d" ")" +installedprinters="$(lpstat -v | cut -f 3 -d" " | sed 's/:$//' )" cat < "/lmn/media/${SUDO_USER}/.printerlist.csv" +installedprinters="$(lpstat -v | cut -f 3 -d" " | sed 's/:$//' )" ## Add all printers needed: for ps in $printservers ; do echo "Checking print server '$ps' for available printers:" - printers="$(lpstat -h "$ps" -U "${SUDO_USER}" -v | sed -E 's/^.+ (\w+): .+$/\1/')" + printers="$(timeout 5 lpstat -h "$ps" -U "${SUDO_USER}" -v | sed -E 's/^.+ (\w+): .+$/\1/')" echo -e "$printers\n" for p in $printers; do if [[ "${hostgroup}" =~ "$p" ]] || [[ "${usergroup}" =~ "$p" ]] ; then @@ -41,8 +43,8 @@ for ps in $printservers ; do timeout 10 lpadmin -p "$p" -E -v \ "ipp://$ps/printers/$p" \ -m "driverless:ipp://$ps/printers/$p" || echo "Adding queue '$p' failed." + installedprinters+=" $p" fi - echo "$p;ipp://192.168.122.1/printers/$p" >> "/lmn/media/${SUDO_USER}/.printerlist.csv" fi done done diff --git a/roles/lmn_security/defaults/main.yml b/roles/lmn_security/defaults/main.yml new file mode 100644 index 0000000..fef2163 --- /dev/null +++ b/roles/lmn_security/defaults/main.yml @@ -0,0 +1,2 @@ +--- +security_defaultuser_login_disable: true diff --git a/roles/lmn_security/handlers/main.yml b/roles/lmn_security/handlers/main.yml index 4a3b124..1a145ab 100644 --- a/roles/lmn_security/handlers/main.yml +++ b/roles/lmn_security/handlers/main.yml @@ -1,5 +1,11 @@ - name: Reload sshd - systemd: + ansible.builtin.systemd: name: sshd state: reloaded when: not run_in_installer|default(false)|bool + +- name: Restart polkit + ansible.builtin.systemd: + name: polkit + state: restarted + when: not run_in_installer|default(false)|bool diff --git a/roles/lmn_security/tasks/main.yml b/roles/lmn_security/tasks/main.yml index 3ce31d5..62e2754 100644 --- a/roles/lmn_security/tasks/main.yml +++ b/roles/lmn_security/tasks/main.yml @@ -4,12 +4,13 @@ user: ansible key: "{{ item }}" loop: "{{ keys2deploy }}" + when: keys2deploy is defined - name: Allow sudo without password for ansible ansible.builtin.lineinfile: path: /etc/sudoers.d/95-lmn-ansible line: 'ansible ALL=(root) NOPASSWD: ALL' - create: True + create: true owner: root group: root mode: '0700' @@ -17,13 +18,35 @@ - name: Disable ansible user login ansible.builtin.user: name: ansible - password_lock: True + password_lock: true + when: security_defaultuser_login_disable - name: Limit SSH access to user ansible ansible.builtin.blockinfile: dest: /etc/ssh/sshd_config.d/local.conf create: true + mode: '0644' block: | PasswordAuthentication no AllowUsers ansible notify: Reload sshd + +- name: Deploy sudo configurations + ansible.builtin.copy: + dest: /etc/sudoers.d/90-lmn-security + owner: root + group: root + mode: '0700' + content: | + {% for user, programs in sudo_permissions.items() %} + {{ user }} ALL=(root) NOPASSWD: {% for program in programs %}{{ program }}{% if not loop.last %}, {% endif %}{% endfor %} + {% endfor %} + when: sudo_permissions is defined + +- name: Deploy polkit configurations + ansible.builtin.template: + src: polkit_rules.j2 + dest: /etc/polkit-1/rules.d/lmn-security.rules + mode: '0644' + notify: Restart polkit + when: polkit_rules is defined diff --git a/roles/lmn_security/templates/polkit_rules.j2 b/roles/lmn_security/templates/polkit_rules.j2 new file mode 100644 index 0000000..28985a8 --- /dev/null +++ b/roles/lmn_security/templates/polkit_rules.j2 @@ -0,0 +1,12 @@ +// /etc/polkit-1/rules.d/lmn-security.rules + +polkit.addRule(function(action, subject) { +{% for group, privlist in polkit_rules.items() %} + if (subject.isInGroup("{{ group }}")){ + {% for priv in privlist %} + if (action.id == "{{ priv }}") { return polkit.Result.YES; } + {% endfor %} + } +{% endfor %} +}); + diff --git a/roles/lmn_sssd/handlers/main.yml b/roles/lmn_sssd/handlers/main.yml index c7c508b..6fdda36 100644 --- a/roles/lmn_sssd/handlers/main.yml +++ b/roles/lmn_sssd/handlers/main.yml @@ -1,3 +1,6 @@ -- name: restart sssd - service: name=sssd state=restarted enabled=yes - listen: "restart sssd" +- name: Restart sssd + ansible.builtin.service: + 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 069f67c..ed44ce5 100644 --- a/roles/lmn_sssd/tasks/main.yml +++ b/roles/lmn_sssd/tasks/main.yml @@ -1,22 +1,21 @@ --- - name: Install needed packages - apt: + ansible.builtin.apt: name: - sssd-ad - sssd-tools - adcli - state: latest - name: Provide user identities from AD - template: + ansible.builtin.template: src: sssd.conf.j2 dest: /etc/sssd/sssd.conf - mode: 0600 - notify: restart sssd + mode: '0600' + notify: Restart sssd ## Either one of the variables is defined: - name: Join the domain - shell: + ansible.builtin.shell: cmd: > echo "{{ ansible_cmdline.adpw | default('') + adpw.user_input | default('') }}" | adcli join --stdin-password -U global-admin {{ domain | upper }} diff --git a/roles/lmn_sssd/templates/sssd.conf.j2 b/roles/lmn_sssd/templates/sssd.conf.j2 index 0c10c3c..fc3bf48 100644 --- a/roles/lmn_sssd/templates/sssd.conf.j2 +++ b/roles/lmn_sssd/templates/sssd.conf.j2 @@ -17,3 +17,6 @@ ad_gpo_access_control = disabled ad_gpo_ignore_unreadable = True ad_maximum_machine_account_password_age = 0 ignore_group_members = True +{% if localhome is defined and localhome %} +override_homedir = /home/%u +{% endif %} diff --git a/roles/lmn_tmpfixes/files/spyder.patch b/roles/lmn_tmpfixes/files/spyder.patch new file mode 100644 index 0000000..39f7c04 --- /dev/null +++ b/roles/lmn_tmpfixes/files/spyder.patch @@ -0,0 +1,23 @@ +--- /usr/lib/python3/dist-packages/spyder/plugins/editor/widgets/editor.py 2024-06-20 07:16:54.096395325 +0200 ++++ /usr/lib/python3/dist-packages/spyder/plugins/editor/widgets/editor.py 2024-06-20 14:39:07.693577124 +0200 +@@ -2370,15 +2370,16 @@ + else: + # Else, testing if it has been modified elsewhere: + lastm = QFileInfo(finfo.filename).lastModified() +- if to_text_string(lastm.toString()) \ +- != to_text_string(finfo.lastmodified.toString()): ++ dt = finfo.lastmodified.msecsTo(lastm) ++ if dt > 1000: + if finfo.editor.document().isModified(): + self.msgbox = QMessageBox( + QMessageBox.Question, + self.title, +- _("%s has been modified outside Spyder." ++ _("It looks like %s has been modified " ++ "outside Spyder. The working copy is from %i milliseconds ago." + "
Do you want to reload it and lose all " +- "your changes?") % name, ++ "your changes?") % (name, dt), + QMessageBox.Yes | QMessageBox.No, + self) + answer = self.msgbox.exec_() diff --git a/roles/lmn_tmpfixes/tasks/bookworm.yml b/roles/lmn_tmpfixes/tasks/bookworm.yml new file mode 100644 index 0000000..ff89fc8 --- /dev/null +++ b/roles/lmn_tmpfixes/tasks/bookworm.yml @@ -0,0 +1,72 @@ +--- +## Temporary fixes and quirks: +- name: Remove disturbing NetworkManager connection + ansible.builtin.file: + path: "/etc/NetworkManager/system-connections/Wired connection 1" + state: absent + when: ansible_interfaces | select('search', '^en[pso].+') | length > 1 + +- 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: Fix sound on 312A + ansible.builtin.replace: + dest: "/etc/default/grub" + regexp: 'GRUB_CMDLINE_LINUX="snd-intel-dspcfg.dsp_driver=1"$' + replace: 'GRUB_CMDLINE_LINUX=""' + notify: Run update-grub + when: ansible_board_vendor == "LENOVO" and ansible_board_name == "312A" + +- name: Fix sound on 312A and 312D + ansible.builtin.apt: + name: firmware-sof-signed + state: latest + when: > + ansible_board_vendor == "LENOVO" and + (ansible_board_name == "312D" or ansible_board_name == "312A") + +- name: Install customized CodeBlocks packages + when: "'PCroom' in group_names" + block: + - name: Check for old CodeBlocks + ansible.builtin.command: + cmd: dpkg -l codeblocks + register: codeblocks_version + changed_when: false + + - name: Download codeblocks zip archive + ansible.builtin.get_url: + url: "http://livebox.pn.steinbeis.schule/codeblocks/CodeBlocks.zip" + dest: /tmp/CodeBlocks.zip + mode: '0644' + use_proxy: false + register: new_codeblocks + when: codeblocks_version.stdout is not search('svn13544') + + - name: Unpack zip archive and install packages manually + ansible.builtin.shell: + cmd: unzip -d /tmp/cb/ CodeBlocks.zip && dpkg -i cb/*.deb + chdir: /tmp/ + when: new_codeblocks.changed | default(false) + +- name: Work around sddm hang on shutdown + ansible.builtin.lineinfile: + path: /etc/systemd/system.conf + line: DefaultTimeoutStopSec=5s + insertafter: '^#DefaultTimeoutStopSec=.*' + +- name: Check if spyder is installed + ansible.builtin.stat: + path: /usr/lib/python3/dist-packages/spyder/plugins/editor/widgets/editor.py + register: spyder + +- name: Patch spyder to fix 'file-has-changed' issues on CIFS + ansible.posix.patch: + src: spyder.patch + dest: /usr/lib/python3/dist-packages/spyder/plugins/editor/widgets/editor.py + when: spyder.stat.exists diff --git a/roles/lmn_tmpfixes/tasks/cleanup.yml b/roles/lmn_tmpfixes/tasks/cleanup.yml new file mode 100644 index 0000000..bc173ea --- /dev/null +++ b/roles/lmn_tmpfixes/tasks/cleanup.yml @@ -0,0 +1,170 @@ +--- +# clean up stuff from obsolete/faulty tasks: +- name: Remove sddm login screen patch with deprecated marker (homeondisk) + ansible.builtin.blockinfile: + path: /usr/share/sddm/themes/debian-breeze/Main.qml + marker: // {mark} ANSIBLE MANAGED BLOCK homeondisk + state: absent + +- name: Remove packages we do not need anymore + ansible.builtin.apt: + name: + - cachefilesd + - mosquitto + state: absent + purge: true + +- name: Remove virtiofs service + ansible.builtin.file: + path: /etc/systemd/system/virtiofs@.service + state: absent + +- name: Fix mount point permissions and owner + ansible.builtin.file: + path: "{{ item }}" + mode: '0755' + owner: root + group: root + loop: + - /srv/samba + - /srv/samba/schools + +- name: Remove pam_mount sysvol mount + ansible.builtin.blockinfile: + dest: /etc/security/pam_mount.conf.xml + marker: "" + block: | + rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} + + state: absent + +- name: Remove pam_mount for VM bind mounts + ansible.builtin.blockinfile: + dest: /etc/security/pam_mount.conf.xml + marker: "" + state: absent + +- name: Check if rmlpr.timer is installed + ansible.builtin.stat: + path: /etc/systemd/system/rmlpr.timer + register: rmlpr + +- name: Disable rmlpr.timer + ansible.builtin.systemd: + name: rmlpr.timer + enabled: false + when: rmlpr.stat.exists + +- name: Check if vmimage-torrent.service is installed + ansible.builtin.stat: + path: /etc/systemd/system/vmimage-torrent.service + register: vmimagetorrent + +- name: Disable vmimage-torrent.service + ansible.builtin.systemd: + name: vmimage-torrent.service + enabled: false + when: vmimagetorrent.stat.exists + +- name: Remove deprecated files and directories + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - /etc/linuxmuster-linuxclient7 + - /usr/lib/python3/dist-packages/linuxmusterLinuxclient7 + - /usr/share/linuxmuster-linuxclient7 + - /usr/local/bin/onLogin + - /etc/sudoers.d/90-lmn-sudotools + - /etc/systemd/system/rmlpr.service + - /etc/systemd/system/rmlpr.timer + - /usr/local/bin/sync-vm.sh + - /usr/local/bin/run-vm.sh + - /usr/local/bin/rebase-vm.sh + - /usr/local/bin/create-vm.sh + - /usr/local/bin/upload-vm.sh + - /usr/local/bin/vmimage-torrent + - /etc/systemd/system/vmimage-torrent.service + - /usr/local/bin/linbo-torrenthelper.sh + - /usr/local/bin/link-images.sh + - /usr/local/bin/start-virtiofsd.sh + - /etc/sudoers.d/90-lmn-upload-vm + - /etc/sudoers.d/90-lmn-sync-vm + - /etc/sudoers.d/90-lmn-startvirtiofsd + - /etc/sudoers.d/90-lmn-link-images + - /etc/rsync.secret + - /etc/systemd/network/30-virbr1.netdev + - /etc/systemd/network/30-virbr2.netdev + - /etc/systemd/network/40-ethernet.network + - /etc/systemd/network/40-ethernet-usb.network + - /etc/systemd/network/50-virbr1.network + - /etc/systemd/network/50-virbr2.network + - /etc/systemd/network/60-wlan0-dhcp.network + - /etc/NetworkManager/system-connections/macvlan-vm-macvtap.nmconnection + - /etc/tmpfiles.d/clean-exam.conf + - /etc/polkit-1/rules.d/lmn-networkmanager.rules + - /etc/polkit-1/rules.d/lmn-packagekit.rules + +- name: Check if vm_usage_information.txt exists + ansible.builtin.stat: + path: /lmn/vm/vm_usage_information.txt + register: vm_usage_information + +- name: Pre-fill vm_usage_information.txt + ansible.builtin.shell: + cmd: | + ls -tr *.qcow2 > vm_usage_information.txt || touchvm_usage_information.txt + chown lmnsynci:lmnsynci vm_usage_information.txt + chdir: /lmn/vm/ + when: vm_support and not vm_usage_information.stat.exists + +- name: Detect if IPP-Everywhere printers exist + ansible.builtin.shell: + cmd: grep "IPP Everywhere" /etc/cups/printers.conf + register: ipp_everywhere + failed_when: false + changed_when: false + +- name: Delete old IPP-Everywhere printers + ansible.builtin.shell: + cmd: | + for p in $(lpstat -p | cut -d" " -f2); do + lpadmin -x "$p" + done + when: not ipp_everywhere.rc + +- name: Remove old VM-printerlists + ansible.builtin.shell: + cmd: rm -f /lmn/media/*/.printerlist.csv + +- name: Remove Listen on VMBridge + ansible.builtin.lineinfile: + dest: /etc/cups/cupsd.conf + line: 'Listen 192.168.122.1:631' + state: absent + +- name: Remove NetworkManager Ansible-Block for non-laptops + ansible.builtin.blockinfile: + path: /etc/NetworkManager/NetworkManager.conf + state: absent + when: "'laptop' not in group_names" + +- name: Remove pam-exec from common-auth + ansible.builtin.lineinfile: + dest: /etc/pam.d/common-auth + line: "auth optional pam_exec.so /usr/local/sbin/pam-exec.sh" + state: absent + when: exam_mode + +- name: Remove pam-mkhomedir from common-session + ansible.builtin.lineinfile: + dest: /etc/pam.d/common-session + line: "session optional pam_mkhomedir.so umask=0077" + state: absent + when: localhome diff --git a/roles/lmn_tmpfixes/tasks/main.yml b/roles/lmn_tmpfixes/tasks/main.yml new file mode 100644 index 0000000..8e90138 --- /dev/null +++ b/roles/lmn_tmpfixes/tasks/main.yml @@ -0,0 +1,10 @@ +--- +- name: Remove disturbing NetworkManager connection + ansible.builtin.include_tasks: + file: "{{ taskfile }}" + loop_control: + loop_var: taskfile + loop: + - bookworm.yml + - cleanup.yml + when: ansible_distribution_release == "bookworm" diff --git a/roles/lmn_vm/defaults/main.yml b/roles/lmn_vm/defaults/main.yml new file mode 100644 index 0000000..11c04c0 --- /dev/null +++ b/roles/lmn_vm/defaults/main.yml @@ -0,0 +1,4 @@ +--- +vm_support: false +vm_torrent_serv: "seedbox.{{ domain }}" +vm_uploadseed_pwd: secret = "token:topsecret" diff --git a/roles/lmn_vm/files/lmn-mounthome b/roles/lmn_vm/files/lmn-mounthome deleted file mode 100644 index 062c4f7..0000000 --- a/roles/lmn_vm/files/lmn-mounthome +++ /dev/null @@ -1,3 +0,0 @@ -%examusers ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh -%role-student ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh -%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh diff --git a/roles/lmn_vm/files/mounthome.sh b/roles/lmn_vm/files/mounthome.sh deleted file mode 100755 index 5cb0405..0000000 --- a/roles/lmn_vm/files/mounthome.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/bash -set -eu - -home="$(getent passwd "$SUDO_UID" | cut -d : -f 6 | sed 's|/srv/samba/schools/default-school/||')" - -exit_script() { - echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log" - findmnt "/lmn/media/${SUDO_USER}/oldhome" && umount "/lmn/media/${SUDO_USER}/oldhome" && rmdir "/lmn/media/${SUDO_USER}/oldhome" - findmnt "/lmn/media/${SUDO_USER}/oldprojects" && umount "/lmn/media/${SUDO_USER}/oldprojects" && rmdir "/lmn/media/${SUDO_USER}/oldprojects" - findmnt "/lmn/media/${SUDO_USER}/linuxhome" && umount "/lmn/media/${SUDO_USER}/linuxhome" && rmdir "/lmn/media/${SUDO_USER}/linuxhome" - trap - SIGHUP SIGINT SIGTERM # clear the trap - kill -- -$$ # Sends SIGTERM to child/sub processes -} - -exit_script_home() { - echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log" - umount "/lmn/media/${SUDO_USER}/home" - trap - SIGHUP SIGINT SIGTERM # clear the trap - kill -- -$$ # Sends SIGTERM to child/sub processes -} - -########################## - -if [[ "$#" -gt 0 ]] && [[ "$1" = '-u' ]]; then - findmnt "/lmn/media/${SUDO_USER}/home" && umount "/lmn/media/${SUDO_USER}/home" && rmdir "/lmn/media/${SUDO_USER}/home" - #findmnt "/lmn/media/${SUDO_USER}/share" && umount "/lmn/media/${SUDO_USER}/share" && rmdir "/lmn/media/${SUDO_USER}/share" - findmnt "/lmn/media/${SUDO_USER}/oldhome" && umount "/lmn/media/${SUDO_USER}/oldhome" && rmdir "/lmn/media/${SUDO_USER}/oldhome" - findmnt "/lmn/media/${SUDO_USER}/oldprojects" && umount "/lmn/media/${SUDO_USER}/oldprojects" && rmdir "/lmn/media/${SUDO_USER}/oldprojects" - findmnt "/lmn/media/${SUDO_USER}/linuxhome" && umount "/lmn/media/${SUDO_USER}/linuxhome" && rmdir "/lmn/media/${SUDO_USER}/linuxhome" -elif [ "$#" -gt 0 ] && [ "$1" = '-o' ]; then - echo "Einbinden der Daten des alten/bisherigen Systems (PaedML Novell)." - echo "Bitte den Username und Passwort aus dem ALTEN System eingeben." - read -rp "Username: " username - read -srp "Passwort: " PASSWD - export PASSWD - echo - mkdir -p "/lmn/media/${SUDO_USER}/oldhome" - mkdir -p "/lmn/media/${SUDO_USER}/oldprojects" - #errcode=$(mount -t cifs -o "username=${username},uid=${SUDO_UID},gid=1010,file_mode=0770,dir_mode=0770,forceuid,forcegid" \ - # "//192.168.1.2/DOCS/fvs" "/lmn/media/${SUDO_USER}/oldhome") - #if [[ ! "${errcode}" ]]; then - mount -t cifs -o "username=${username},uid=${SUDO_UID},gid=1010,file_mode=0770,dir_mode=0770,forceuid,forcegid,nobrl,mfsymlinks" \ - "//192.168.1.2/DOCS/fvs" "/lmn/media/${SUDO_USER}/oldhome" - mount -t cifs -o "username=${username},uid=${SUDO_UID},gid=1010,file_mode=0770,dir_mode=0770,forceuid,forcegid,nobrl,mfsymlinks" \ - "//192.168.1.2/DATA/fvs/projekte" "/lmn/media/${SUDO_USER}/oldprojects" - #echo "Mounting successfull!" - echo "Einbindung erfolgreich!" - echo "Dieses Fenster bitte nicht schließen!" - #echo "Um weiter zu arbeiten: + " - trap exit_script SIGHUP SIGINT SIGTERM - sleep infinity -elif [ "$#" -gt 0 ] && [ "$1" = '-l' ]; then - echo "Einbinden des Netboot-Home-Verzeichnises. Daten des alten/bisherigen Systems (PaedML Novell)." - echo "Bitte den Username und Passwort aus dem ALTEN System (PaedML Novell) eingeben." - echo "Bitte auch Groß- und Kleinschreibung achten." - read -rp "Username: " username - mkdir -p "/lmn/media/${SUDO_USER}/linuxhome" - mount -t fuse -o "allow_other,uid=${SUDO_UID},gid=1010,reconnect" \ - "sshfs#${username}@home.steinbeisschule-reutlingen.de:" "/lmn/media/${SUDO_USER}/linuxhome" - #echo "Mounting successfull!" - echo "Einbindung erfolgreich!" - echo "Dieses Fenster bitte nicht schließen!" - #echo "Um weiter zu arbeiten: + " - trap exit_script SIGHUP SIGINT SIGTERM - sleep infinity -fi diff --git a/roles/lmn_vm/files/pam-umount.sh b/roles/lmn_vm/files/pam-umount.sh index 0d90dd5..7f9778f 100644 --- a/roles/lmn_vm/files/pam-umount.sh +++ b/roles/lmn_vm/files/pam-umount.sh @@ -13,12 +13,12 @@ slp=false shutdownVMs(){ local VM for VM in $(sudo -u $usr XDG_RUNTIME_DIR="/run/user/$uid" \ - XDG_CONFIG_HOME="/tmp/$uid/.config/" \ + XDG_CONFIG_HOME="/var/tmp/vm/$uid" \ XDG_CACHE_HOME="/var/cache/user/$uid/" \ virsh list --state-running | \ sed -nE "s/.*\s+(\S+)\s+running/\1/p") ; do sudo -u $usr XDG_RUNTIME_DIR="/run/user/$uid" \ - XDG_CONFIG_HOME="/tmp/$uid/.config/" \ + XDG_CONFIG_HOME="/var/tmp/vm/$uid" \ XDG_CACHE_HOME="/var/cache/user/$uid/" \ virsh destroy "$VM" 2>&1 | systemd-cat || true slp=true diff --git a/roles/lmn_vm/files/virtiofsd b/roles/lmn_vm/files/virtiofsd index 471c24d..83fa42a 100755 Binary files a/roles/lmn_vm/files/virtiofsd and b/roles/lmn_vm/files/virtiofsd differ diff --git a/roles/lmn_vm/files/vm-netboot b/roles/lmn_vm/files/vm-netboot index 2f4c062..c21024f 100755 --- a/roles/lmn_vm/files/vm-netboot +++ b/roles/lmn_vm/files/vm-netboot @@ -5,7 +5,7 @@ set -eu ## Imporant for all virsh libvirt calls: -export XDG_CONFIG_HOME="/tmp/${UID}/.config" +export XDG_CONFIG_HOME="/var/tmp/vm/${UID}" menu=(standard "CLI Standard Debian GNU/Linux NFS" standard-ram "CLI Standard Debian GNU/Linux RAM" @@ -17,8 +17,10 @@ img=$(dialog --clear --backtitle "Virtual Machine Chooser" \ ## If the menu is canceled, $0 stops here because of set -e -mac="$(ip link | grep -A1 "vm-macvtap" | \ +# FIXME: Use first device found for now: +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")" if [[ $# -eq 0 ]] ; then mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo) @@ -47,21 +49,25 @@ case "$img" in ;; esac -type="ethernet,mac=${mac},target.dev=vm-macvtap,xpath1.set=./target/@managed=no" +type="ethernet,mac=${mac},target.dev=${tapdev},xpath1.set=./target/@managed=no" +n=0 for vm in $(virsh --connect qemu:///session list --all --name) ; do if virsh domiflist "$vm" | grep -q "$mac" ; then type="user" virt-manager & - break + fi + if [[ "${img}$n" = "$vm" ]] ; then + n=$((n+1)) fi done +kargs+=(hostname="${img}$n") ## FIXME: use passt, needs more settings for correct DNS/gateway # type=user,xpath1.create=./backend,xpath2.set=./backend/@type=passt,xpath3.create=./ip,xpath4.set=./ip/@family=ipv4,xpath5.set=./ip/@address=172.16.1.1,xpath6.set=./ip/@prefix=24,xpath7.create=./portForward,xpath8.set=./portForward/@proto=tcp,xpath9.set=./portForward/range/@start=2001,xpath10.set=./portForward/range/@end=2500,xpath11.set=./portForward/range/@to=1 http_proxy='' \ exec virt-install \ - --name "$img" \ + --name "${img}$n" \ --osinfo debiantesting \ --nodisks --import --noreboot --transient \ --controller type=scsi,model=virtio-scsi \ diff --git a/roles/lmn_vm/files/vm-run b/roles/lmn_vm/files/vm-run index 5ef6e2a..a957a49 100755 --- a/roles/lmn_vm/files/vm-run +++ b/roles/lmn_vm/files/vm-run @@ -19,6 +19,9 @@ options: --os OS operating system (win10|linux|..) --data-disk size additional data-disk --bridge virbrX additional network interface on bridge virbrX + --uid uid set uid on guest + --gid gid set gid on guest + --macvtap additional network interface on device macvtap --options options additional options for virt-install command EOF } @@ -31,8 +34,8 @@ exit_script() { } check_images() { - # sync vm-torrents and machine definition file - sudo -u lmnsynci /usr/local/bin/vm-sync get_file "${VM_NAME}.qcow2.torrent" + # sync vm-torrent and TPM data + sudo -u lmnsynci /usr/local/bin/vm-sync get_file "${VM_NAME}.qcow2.torrent" "${VM_NAME}.permall" [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" ]] && sudo -u lmnsynci /usr/local/bin/vm-sync delete_outdated_image "${VM_NAME}.qcow2" BACKINGARRAY=() @@ -103,6 +106,80 @@ create_clone() { cd "${VM_DIR}" qemu-img create -f qcow2 -F qcow2 -b "${VM_NAME}.qcow2" "${VM_NAME}-clone.qcow2" + if [[ -f "${VM_SYSDIR}/${VM_NAME}.permall" ]]; then + # Copy tpm file + if [[ ! -f "${VM_NAME}.permall" ]]; then + echo "copy tpm-file" + cp "${VM_SYSDIR}/${VM_NAME}.permall" . + fi + # create tpm-clone file + echo "create tpm-clone-file" + cp "${VM_NAME}.permall" "${VM_NAME}-clone.permall" + fi + +} + +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" + done +} + +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" +Drive;Remotepath +H;\\\\10.190.1.1${NETHOME//\//\\} +T;\\\\10.190.1.1\default-school\share +EOF + echo "${USER}" > "/lmn/media/${USER}/.user" +} + +start_virtiofsd() { + # BEGIN temporary fix, while linux-starter are not migrated to --uid and --gid + if [[ "$LIBVIRTOSINFO" =~ debian.* ]]; then + [[ "$GUEST_UID" == 0 ]] && GUEST_UID=1010 + [[ "$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 +} + +ask_really_persistent() { + cat << EOF >&2 + +!!!!!!!!!!!!!!! Wichtig !!!!!!!!!!!!!! + +Auf dem Computer existiert noch keine persistente VM mit dem Namen ${VM_NAME}. +Das Anlegen persistenter Maschinen sollte nur auf Computern geschehen, +die dem jeweiligen Benutzer zugeordnet sind. +In Klassenzimmern oder Computerräumen ist das Verwenden persistenter +Maschinen normalerweise nicht sinnvoll und sprengt die verfügbaren +Festplattenkapazität. + +EOF + read -rp "Ist die Installation einer persistenten VM wirklich gewünscht? ja/nein " answer + if [[ "${answer,,}" == "ja" ]]; then + VM_DIR="${VM_DIR_PERSISTENT}" + echo "Die VM ${VM_NAME} wird persistent auf der Festplatte angelegt!" + sleep 5 + else + PERSISTENT=0; + VM_DIR="${VM_DIR_CONF}" + echo "Die VM ${VM_NAME} wird nicht persistent gestartet!" + sleep 5 + fi } QEMU='qemu:///session' @@ -112,10 +189,13 @@ PERSISTENT=0 LIBVIRTOSINFO="win10" LIBVIRTOPTS="" NO_VIEWER=0 +GUEST_UID=0 +GUEST_GID=0 source /etc/lmn/vm.conf +VM_DIR_CONF="${VM_DIR}" -TEMP=$(getopt -o no:ps --long new,no-viewer,options:,persistent,system,memory:,data-disk:,heads:,cpu:,bridge:,os:,help -n $0 -- "$@") +TEMP=$(getopt -o no:ps --long new,no-viewer,options:,persistent,system,memory:,data-disk:,heads:,cpu:,bridge:,macvtap,os:,uid:,gid:,help -n $0 -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi eval set -- "$TEMP" @@ -124,7 +204,7 @@ while true; do case "$1" in -p | --persistent ) PERSISTENT=1; - VM_DIR="${VM_DIR_PERSISTENT}" + VM_DIR="${VM_DIR_PERSISTENT}" shift ;; -n | --new ) @@ -180,10 +260,27 @@ while true; do fi shift 2 ;; + --macvtap ) + for interface in $(ip link | sed -En 's/.*(macvtap-.*)@.*/\1/p'); do + mac="$(ip link | grep -A1 "${interface}" | \ + sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")" + type="ethernet,mac=${mac},target.dev=${interface},xpath1.set=./target/@managed=no,model.type=virtio" + LIBVIRTOPTS="${LIBVIRTOPTS} --network type=$type" + done + shift + ;; --os ) LIBVIRTOSINFO=$2 shift 2 ;; + --uid ) + GUEST_UID=$2 + shift 2 + ;; + --gid ) + GUEST_GID=$2 + shift 2 + ;; --help ) show_help exit 1 @@ -201,32 +298,48 @@ fi VM_NAME=$1 -# check, if we have to start squid -if ! killall -s 0 squid; then - echo "starting squid." - /usr/sbin/squid -f /etc/squid/squid-usermode.conf +systemctl --user restart usersquid.service & + +# check, if persistent VM is really wanted +if [[ "${PERSISTENT}" == 1 ]] && [[ ! -f "${VM_DIR_PERSISTENT}/${VM_NAME}.qcow2" ]]; then + ask_really_persistent fi # because virsh has problems with long pathnames, using diffent configdir -export XDG_CONFIG_HOME="/tmp/${UID}/.config" +export XDG_CONFIG_HOME="/var/tmp/vm/${UID}" if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then echo "VM not yet running." - sudo /usr/local/bin/desktop-sync - check_images + # only when school-network is reachable + if nslookup "${SEEDBOX_HOST}"; then + check_images + fi if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then create_clone "${VM_NAME}" fi # delete the old vm - virsh --connect=qemu:///session undefine "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist" + virsh --connect=qemu:///session undefine --nvram "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist" #trap exit_script SIGHUP SIGINT SIGTERM + create_printerlist + create_mountlist + # start virtiofsd-service - [[ "${QEMU}" = 'qemu:///session' ]] && sudo /usr/local/bin/vm-virtiofsd "${VM_NAME}" + [[ "${QEMU}" = 'qemu:///session' ]] && start_virtiofsd + + uuid=$(openssl rand -hex 16) + uuid="${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}" + + if [[ -f "${VM_DIR}/${VM_NAME}-clone.permall" ]]; then + mkdir -p "/var/tmp/vm/${UID}/.config/libvirt/qemu/swtpm/${uuid}/tpm2/" + ln "${VM_DIR}/${VM_NAME}-clone.permall" "/var/tmp/vm/${UID}/.config/libvirt/qemu/swtpm/${uuid}/tpm2/tpm2-00.permall" + LIBVIRTOPTS="${LIBVIRTOPTS} --tpm backend.type=emulator,backend.version=2.0,model=tpm-crb " + fi # finally, create the new vm virt-install \ + --uuid="${uuid}" \ --osinfo "${LIBVIRTOSINFO}" \ --name "${VM_NAME}-clone" \ --import \ @@ -240,6 +353,11 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then --check path_in_use=off \ --connect="${QEMU}" \ --noautoconsole \ + --redirdev usb,type=spicevmc \ + --redirdev usb,type=spicevmc \ + --redirdev usb,type=spicevmc \ + --redirdev usb,type=spicevmc \ + --redirdev usb,type=spicevmc \ ${LIBVIRTOPTS} # --dry-run \ diff --git a/roles/lmn_vm/files/vm-sync b/roles/lmn_vm/files/vm-sync index a9713ed..72f5c6b 100755 --- a/roles/lmn_vm/files/vm-sync +++ b/roles/lmn_vm/files/vm-sync @@ -20,9 +20,9 @@ get_torrent() { exit 1 fi cd "${VM_SYSDIR}" - echo Size needed: $(get_image_size "${VM_NAME}.qcow2.torrent") + echo Size needed: $(get_image_size "${VM_NAME}.qcow2.torrent") " Bytes (VM-Image) + 5GB (spare)" echo Size available: $(df --block-size=1 --output=avail "${VM_SYSDIR}" | sed 1d) - while [[ $(get_image_size "${VM_NAME}.qcow2.torrent") -gt $(df --block-size=1 --output=avail "${VM_SYSDIR}" | sed 1d) ]]; do + while [[ $(( $(get_image_size "${VM_NAME}.qcow2.torrent") + 15000000000 )) -gt $(df --block-size=1 --output=avail "${VM_SYSDIR}" | sed 1d) ]]; do echo "Not enough space to get ${VM_NAME}." FILENAME="$(head -1 vm_usage_information.txt)" if [[ -z $FILENAME ]]; then @@ -79,8 +79,18 @@ delete_outdated_image() { cd "${VM_SYSDIR}" qcowsize=$(stat -c%s "${FILENAME}") if [[ -f "${FILENAME}.torrent" ]] && [[ "${qcowsize}" != $(get_image_size "${FILENAME}.torrent") ]]; then - sudo vm-aria2 stop "${FILENAME%.qcow2}" - rm -f "${FILENAME}" + cat << EOF >&2 + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Es wurde eine neueres VM-Image auf dem Server gefunden. +Das Herunterladen des Images via WLAN benötigt viel Zeit. +EOF + read -rp "Soll das neue Image wirklich herunter geladen werden? j/n " answer + if [[ "${answer,,}" == "j" ]]; then + sudo vm-aria2 stop "${FILENAME%.qcow2}" + rm -f "${FILENAME}" + fi fi } diff --git a/roles/lmn_vm/files/vm-upload b/roles/lmn_vm/files/vm-upload index 1fbdda3..32900d9 100755 --- a/roles/lmn_vm/files/vm-upload +++ b/roles/lmn_vm/files/vm-upload @@ -24,6 +24,10 @@ upload_image() { echo "copy private VM-Diskimage to system-dir" chown lmnsynci:lmnsynci "${VM_DIR}/${VM_NAME}.qcow2" ln -f "${VM_DIR}/${VM_NAME}.qcow2" "${VM_SYSDIR}/${VM_NAME}.qcow2" + if [[ -f "${VM_DIR}/${VM_NAME}.permall" ]]; then + cp "${VM_DIR}/${VM_NAME}.permall" "${VM_SYSDIR}/${VM_NAME}.permall" + chown lmnsynci:lmnsynci "${VM_SYSDIR}/${VM_NAME}.permall" + fi fi cd "${VM_SYSDIR}" if [[ -f "/tmp/${VM_NAME}.qcow2.torrent" ]]; then @@ -31,6 +35,10 @@ upload_image() { fi uploadseed --server "${SEEDBOX_HOST}:${SEEDBOX_RPC_PORT}" --dht-port "${SEEDBOX_PORT}" \ --pwdfile "${SEEDBOX_PWFILE}" --no-cert "${VM_NAME}.qcow2" + if [[ -f "${VM_SYSDIR}/${VM_NAME}.permall" ]]; then + uploadseed --server "${SEEDBOX_HOST}:${SEEDBOX_RPC_PORT}" --dht-port "${SEEDBOX_PORT}" \ + --pwdfile "${SEEDBOX_PWFILE}" --no-cert "${VM_NAME}.permall" + fi } source /etc/lmn/vm.conf diff --git a/roles/lmn_vm/handlers/main.yml b/roles/lmn_vm/handlers/main.yml index 6af3160..e8829ac 100644 --- a/roles/lmn_vm/handlers/main.yml +++ b/roles/lmn_vm/handlers/main.yml @@ -1,11 +1,9 @@ - name: Reload libvirtd - systemd: + ansible.builtin.systemd: name: libvirtd.service listen: reload libvirtd -- name: Run update-desktop-database - command: update-desktop-database "{{ item }}" - loop: - - /usr/local/share/applications - - /usr/local/share/desktop-directories - - /etc/xdg/menus/applications-merged +- name: Just force systemd to reread configs + ansible.builtin.systemd_service: + daemon_reload: true + listen: daemon reload diff --git a/roles/lmn_vm/tasks/main.yml b/roles/lmn_vm/tasks/main.yml index 0d87a4e..a39325a 100644 --- a/roles/lmn_vm/tasks/main.yml +++ b/roles/lmn_vm/tasks/main.yml @@ -4,32 +4,31 @@ - name: Allow users to attach to bridge ansible.builtin.copy: dest: /etc/apt/apt.conf.d/94qemu-bridge-suid + mode: '0644' content: | ## Modify permissions after installation/upgrade ## to run qemu-bridge as root DPkg::Post-Invoke {"/usr/bin/chmod 4755 /usr/lib/qemu/qemu-bridge-helper || true"; }; -- name: install libvirt packages - apt: +- name: Install libvirt packages + ansible.builtin.apt: name: - aria2 - mktorrent - libvirt-daemon-system - virt-manager - dialog # for vm-netboot menu - state: latest - autoremove: true - #- name: allow all users to use VMs - # lineinfile: - # dest: /etc/libvirt/libvirtd.conf - # line: 'auth_unix_rw = "none"' - # insertafter: '#auth_unix_rw = "polkit"' - # notify: reload libvirtd + # - name: allow all users to use VMs + # lineinfile: + # dest: /etc/libvirt/libvirtd.conf + # line: 'auth_unix_rw = "none"' + # insertafter: '#auth_unix_rw = "polkit"' + # notify: reload libvirtd - name: Configure pam_mount for VM bind mounts - blockinfile: + ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml marker: "" block: | @@ -38,18 +37,24 @@ path="~" mountpoint="/lmn/media/%(USER)/home" options="bind" - >rootansibleDebian-gdmsddm{{ localuser }} + >rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} rootansibleDebian-gdmsddm{{ localuser }} + >rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} + + rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} insertafter: "" - name: Use umount script for proper cleanup - blockinfile: + ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml marker: "" block: | @@ -61,16 +66,16 @@ ansible.builtin.copy: src: pam-umount.sh dest: /usr/local/sbin/pam-umount.sh - mode: "0755" + mode: '0755' - name: Insert domain in default-network - lineinfile: + ansible.builtin.lineinfile: path: /etc/libvirt/qemu/networks/default.xml line: ' ' insertafter: '' - name: Autostart default network for VMs - file: + ansible.builtin.file: src: /etc/libvirt/qemu/networks/default.xml dest: /etc/libvirt/qemu/networks/autostart/default.xml state: link @@ -83,74 +88,60 @@ create_home: false - name: Create /etc/lmn directory - file: + ansible.builtin.file: path: /etc/lmn state: directory + mode: '0755' - name: Create /lmn directory - file: + ansible.builtin.file: path: /lmn state: directory + mode: '0755' - name: Create /lmn/media directory - file: + ansible.builtin.file: path: /lmn/media state: directory mode: '1777' - name: Create /var/vm directory - file: + ansible.builtin.file: path: /var/vm state: directory mode: '1777' - name: Create vm directory - file: + ansible.builtin.file: path: /lmn/vm state: directory owner: lmnsynci group: lmnsynci - mode: 0755 + mode: '0755' -- name: Install squid - apt: - name: - - squid - state: latest - autoremove: true - -- name: Disable squid - systemd: - name: squid - enabled: false - state: stopped - -- name: Deploy squid user mode configuration - template: - src: squid-usermode.conf.j2 - dest: /etc/squid/squid-usermode.conf +- name: Create cleanup-vm.conf + ansible.builtin.copy: + dest: /etc/tmpfiles.d/clean-vm.conf mode: '0644' + content: | + D /var/tmp/vm 1777 root root - - name: Deploy sudo configurations - copy: - src: "{{ item }}" - dest: "/etc/sudoers.d/90-{{ item }}" + ansible.builtin.copy: + src: lmn-vm + dest: /etc/sudoers.d/90-lmn-vm owner: root group: root mode: '0700' - loop: - - lmn-mounthome - - lmn-vm - name: Deploy vmimages scripts - copy: + ansible.builtin.copy: src: "{{ item }}" dest: /usr/local/bin/ owner: root group: root mode: '0755' loop: - - mounthome.sh - vm-create - vm-rebase - vm-run @@ -164,11 +155,12 @@ - desktop-sync - name: Deploy vm configuration file vm.conf - ansible.builtin.copy: - src: vm.conf + ansible.builtin.template: + src: vm.conf.j2 dest: /etc/lmn/vm.conf owner: root group: root + mode: '0644' - name: Deploy aria2 RPC password file ansible.builtin.copy: @@ -177,7 +169,7 @@ group: lmnsynci mode: '0640' content: | - {{ uploadseed_pwd }} + {{ vm_uploadseed_pwd }} - name: Prepare directory for aria2 dht.dat ansible.builtin.file: @@ -185,15 +177,18 @@ state: directory owner: lmnsynci group: lmnsynci + mode: '0755' - name: Prepare directory for qemu bridge config ansible.builtin.file: path: /etc/qemu/ state: directory + mode: '0755' - name: Deploy bridge.conf needed for qemu session mode ansible.builtin.copy: dest: /etc/qemu/bridge.conf + mode: '0644' content: | allow virbr0 allow virbr1 @@ -201,66 +196,32 @@ - name: Configure macvtap interface ansible.builtin.copy: - dest: /etc/NetworkManager/system-connections/macvlan-vm-macvtap.nmconnection + dest: "/etc/NetworkManager/system-connections/macvlan-vm-macvtap-{{ item }}.nmconnection" mode: '0600' content: | [connection] - id=macvlan-vm-macvtap + id=macvlan-macvtap-{{ item[3:9] }} type=macvlan - interface-name=vm-macvtap + interface-name=macvtap-{{ item[3:9] }} [macvlan] mode=2 - parent={{ ansible_default_ipv4['interface'] }} + parent={{ item }} tap=true [ipv4] method=disabled [ipv6] method=disabled [proxy] + loop: "{{ ansible_interfaces | select('search', '^en[pso].+') }}" - name: Adjust interface permissions for user mode VMs ansible.builtin.copy: dest: /etc/udev/rules.d/80-macvlan.rules + mode: '0644' content: | - SUBSYSTEMS=="net", KERNELS=="vm-macvtap", MODE="0666" - - -- name: Create directory for local .desktop-Files - ansible.builtin.file: - path: "{{ item }}" - state: directory - mode: '0755' - loop: - - /usr/local/share/applications - - /usr/local/share/desktop-directories - notify: Run update-desktop-database - -- name: Copy fvs.directory - ansible.builtin.copy: - src: fvs.directory - dest: /usr/local/share/desktop-directories/ - notify: Run update-desktop-database - -- name: Copy fvs.menu - ansible.builtin.copy: - src: fvs.menu - dest: /etc/xdg/menus/applications-merged/ - notify: Run update-desktop-database - -- name: check if sync.desktop is installed - stat: path=/usr/local/share/applications/sync.desktop - register: syncdesktop - -- name: remove deprecated desktop-files - ansible.builtin.shell: rm -f /usr/local/share/applications/*.desktop - when: not syncdesktop.stat.exists - notify: Run update-desktop-database - -- name: Copy initial sync starter - ansible.builtin.copy: - src: sync.desktop - dest: /usr/local/share/applications/ - notify: Run update-desktop-database + {% for interface in (ansible_interfaces | select('search', '^en[pso].+')) %} + SUBSYSTEMS=="net", KERNELS=="macvtap-{{ interface[3:9] }}", MODE="0666" + {% endfor %} - name: Start virt-manager in session mode by default ansible.builtin.copy: diff --git a/roles/lmn_vm/files/vm.conf b/roles/lmn_vm/templates/vm.conf.j2 similarity index 72% rename from roles/lmn_vm/files/vm.conf rename to roles/lmn_vm/templates/vm.conf.j2 index 8bd4189..7f69a21 100644 --- a/roles/lmn_vm/files/vm.conf +++ b/roles/lmn_vm/templates/vm.conf.j2 @@ -1,6 +1,6 @@ # variables for LMN VM submodule -SEEDBOX_HOST="seedbox.pn.steinbeis.schule" +SEEDBOX_HOST="{{ vm_torrent_serv }}" SEEDBOX_PORT=6789 SEEDBOX_RPC_PORT=6800 SEEDBOX_PWFILE="/etc/lmn/uploadseed.conf" @@ -9,9 +9,11 @@ DESKTOPSTARTERDIR="/srv/samba/schools/default-school/share/school/AdminIT/deskto VM_SYSDIR="/lmn/vm" if [[ -v SUDO_UID ]]; then - VM_DIR="/tmp/${SUDO_UID}/vm" + VM_DIR="/var/tmp/vm/${SUDO_UID}/vm" VM_DIR_PERSISTENT="/var/vm/${SUDO_UID}" else - VM_DIR="/tmp/${UID}/vm" + VM_DIR="/var/tmp/vm/${UID}/vm" VM_DIR_PERSISTENT="/var/vm/${UID}" fi + +VM_MEDIADIR="/lmn/media/${USER}" diff --git a/roles/lmn_vpn/defaults/main.yml b/roles/lmn_vpn/defaults/main.yml new file mode 100644 index 0000000..2c6e23f --- /dev/null +++ b/roles/lmn_vpn/defaults/main.yml @@ -0,0 +1,8 @@ +--- +vpn: none +# Wireguad config +wg_endpoint: "203.0.113.1:51820" +wg_allowed_ips: "10.0.0.0/16;" +wg_ip_cdr: 24 +wg_dns: "9.9.9.9" +wg_dns_search: "example.com" diff --git a/roles/lmn_vpn/files/10-lmn-mount.sh b/roles/lmn_vpn/files/10-lmn-mount.sh new file mode 100755 index 0000000..6f42725 --- /dev/null +++ b/roles/lmn_vpn/files/10-lmn-mount.sh @@ -0,0 +1,43 @@ +#!/usr/bin/bash +# +set -eu + +if [[ "$CONNECTION_ID" = "VPN-Schule" ]]; then + USERNAME=$(ps -o pid,user,args -C sddm-helper | sed -nE 's/.*user (.*)$/\1/p') + USERID=$(id -u "${USERNAME}") + GROUPID=$(id -g "${USERNAME}") + KRB5CCNAME=$(ls /tmp/krb5cc_"${USERID}"_*) + export KRB5CCNAME + printenv >&2 + if [[ "$NM_DISPATCHER_ACTION" = "up" ]]; 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 + + 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" + umount /srv/samba/schools/default-school + fi + fi +fi diff --git a/roles/lmn_vpn/files/mountserver b/roles/lmn_vpn/files/mountserver new file mode 100644 index 0000000..71c61cc --- /dev/null +++ b/roles/lmn_vpn/files/mountserver @@ -0,0 +1,26 @@ +#!/usr/bin/bash +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 +} + +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!" +trap exit_script SIGHUP SIGINT SIGTERM +sleep infinity diff --git a/roles/lmn_vpn/tasks/main.yml b/roles/lmn_vpn/tasks/main.yml new file mode 100644 index 0000000..b6da7e0 --- /dev/null +++ b/roles/lmn_vpn/tasks/main.yml @@ -0,0 +1,31 @@ +--- +- name: Copy mountserver script to /usr/local/bin + ansible.builtin.copy: + src: mountserver + dest: /usr/local/bin/ + mode: "0755" + +- name: Copy NetworkManager dispatcher-script (10-lmn-mount.sh) + ansible.builtin.copy: + src: 10-lmn-mount.sh + dest: /etc/NetworkManager/dispatcher.d/ + mode: "0755" + +- name: Create link to dispatcher-script (10-lmn-mount.sh) + ansible.builtin.file: + src: ../10-lmn-mount.sh + dest: /etc/NetworkManager/dispatcher.d/pre-down.d/10-lmn-mount.sh + state: link + +- name: Deploy sudo configurations (apt for role-teacher) + ansible.builtin.copy: + dest: /etc/sudoers.d/90-lmn-vpn + owner: root + group: root + mode: '0700' + content: | + %role-teacher ALL=(root) NOPASSWD: /usr/local/bin/mountserver + +- name: Configure Wireguard + ansible.builtin.include_tasks: wg_config.yml + when: vpn is defined and vpn == "wg" diff --git a/roles/lmn_vpn/tasks/wg_config.yml b/roles/lmn_vpn/tasks/wg_config.yml new file mode 100644 index 0000000..d1bf9ce --- /dev/null +++ b/roles/lmn_vpn/tasks/wg_config.yml @@ -0,0 +1,138 @@ +--- +- name: Install wireguard packages + ansible.builtin.apt: + name: + - wireguard + +- name: Check if wg_server is reachable + ansible.builtin.command: echo "Test if wg_server is reachable" + delegate_to: wireguard_server + register: result + changed_when: false + +- name: Inform that wg_server is unreachable + ansible.builtin.debug: + msg: | + Couldn't access wg_server. Possible reasons + * server not reachable + * no matching ssh-key + changed_when: true + when: result.unreachable is defined and result.unreachable + +- name: Configure WG Server + when: result.unreachable is not defined or not result.unreachable + block: + - name: Set facts wg_clientname + ansible.builtin.set_fact: + wg_clientname: "{{ ansible_hostname }}" + + - name: Get Wiregard-Privatekey from server + ansible.builtin.shell: + cmd: grep PrivateKey /etc/wireguard/wg0.conf | sed -En 's/.*=\s*(.+)/\1/p' + register: wg_serverprivkey + changed_when: false + delegate_to: wireguard_server + + - name: Create public key (Server) + ansible.builtin.command: + cmd: "wg pubkey" + args: + stdin: "{{ wg_serverprivkey.stdout }}" + changed_when: false + register: wg_serverpubkey + + - name: Set facts wg_publickey (Server) + ansible.builtin.set_fact: + wg_serverpublickey: "{{ wg_serverpubkey.stdout }}" + + - name: Check if Wiregard-Config exists on server + ansible.builtin.command: + cmd: "grep -A 3 '# BEGIN ANSIBLE MANAGED BLOCK {{ wg_clientname }}' /etc/wireguard/wg0.conf" + register: wg_serverconfig + failed_when: false + changed_when: false + delegate_to: wireguard_server + + - name: Set facts wg_ip + ansible.builtin.set_fact: + wg_ip: "{{ wg_serverconfig.stdout | regex_search('AllowedIPs = ([0-9.]+)/32', '\\1', multiline=True) | first }}" + when: wg_serverconfig.rc == 0 and wg_ip is not defined + + - name: Check if Wireguard exists on client + ansible.builtin.stat: + path: /etc/NetworkManager/system-connections/wg0.nmconnection + register: wg_clientconfig + + - name: Search IP address in NetworkManager config + ansible.builtin.command: + cmd: cat /etc/NetworkManager/system-connections/wg0.nmconnection + register: wg_address + changed_when: false + when: wg_clientconfig.stat.exists + + - name: Set facts wg_ip + ansible.builtin.set_fact: + wg_ip: "{{ wg_address.stdout | regex_search('address1=([0-9.]+)/.*', '\\1', multiline=True) | first }}" + when: wg_address.rc is defined and wg_address.rc == 0 and wg_ip is not defined + + - name: Set facts wg_privatekey + ansible.builtin.set_fact: + wg_privatekey: "{{ wg_address.stdout | regex_search('private-key=(.*)$', '\\1', multiline=True) | first }}" + when: wg_address.rc is defined and wg_address.rc == 0 and wg_privatekey is not defined + + - name: Search maximum AllowedIP + ansible.builtin.shell: + cmd: grep AllowedIPs /etc/wireguard/wg0.conf | sed -En 's/.*=\s*([0-9.]+)\/32.*/\1/p' | sort -t . -k 3,3n -k 4,4n | tail -n 1 + register: wg_ipmax + changed_when: false + delegate_to: wireguard_server + when: wg_ip is not defined + + - name: Set facts wg_ip + ansible.builtin.set_fact: + wg_ip: "{{ wg_ipmax.stdout | ansible.utils.ipmath(1) }}" + when: wg_ipmax.rc is defined and wg_ipmax.rc == 0 and wg_ipmax.stdout and wg_ip is not defined + + - name: Create private key + ansible.builtin.command: + cmd: "wg genkey" + register: wg_genkey + changed_when: false + when: wg_privatekey is not defined + + - name: Set facts wg_privatekey + ansible.builtin.set_fact: + wg_privatekey: "{{ wg_genkey.stdout }}" + when: wg_genkey.stdout is defined + + - name: Create Wireguard-Config + ansible.builtin.template: + src: wg0.nmconnection.j2 + dest: /etc/NetworkManager/system-connections/wg0.nmconnection + mode: '0600' + + - name: Create public key + ansible.builtin.command: + cmd: "wg pubkey" + args: + stdin: "{{ wg_privatekey }}" + register: wg_pubkey + changed_when: false + + - name: Set facts wg_publickey + ansible.builtin.set_fact: + wg_publickey: "{{ wg_pubkey.stdout }}" + + - name: Print WG IP + ansible.builtin.debug: + msg: "{{ wg_publickey }} -- {{ wg_pubkey.stdout }}" + + - name: Set Wireguard Serverconfig + ansible.builtin.blockinfile: + marker: "# {mark} ANSIBLE MANAGED BLOCK {{ wg_clientname }}" + path: /etc/wireguard/wg0.conf + block: | + [Peer] + PublicKey = {{ wg_publickey }} + AllowedIPs = {{ wg_ip }}/32 + delegate_to: wireguard_server diff --git a/roles/lmn_vpn/templates/wg0.nmconnection.j2 b/roles/lmn_vpn/templates/wg0.nmconnection.j2 new file mode 100644 index 0000000..c135e2b --- /dev/null +++ b/roles/lmn_vpn/templates/wg0.nmconnection.j2 @@ -0,0 +1,26 @@ +[connection] +id=VPN-Schule +type=wireguard +autoconnect=false +interface-name=wg0 + +[wireguard] +listen-port=51820 +private-key={{ wg_privatekey }} +mtu=1280 + +[wireguard-peer.{{ wg_serverpublickey }}] +endpoint={{ wg_endpoint }} +allowed-ips={{ wg_allowed_ips }} + +[ipv4] +address1={{ wg_ip }}/{{ wg_ip_cdr }} +dns={{ wg_dns }} +dns-search={{ wg_dns_search }} +method=manual + +[ipv6] +addr-gen-mode=stable-privacy +method=ignore + +[proxy] diff --git a/roles/lmn_wlan/defaults/main.yaml b/roles/lmn_wlan/defaults/main.yaml new file mode 100644 index 0000000..f3c1c44 --- /dev/null +++ b/roles/lmn_wlan/defaults/main.yaml @@ -0,0 +1,15 @@ +--- +wlan: none +wlan_force_issue: false +wlan_ssid: "Linux-Wlan" +wlan_password: "VerySecurePassw0rd" +wlan_eap_ca: + C: "DE" + ST: "Baden-Wuerttemberg" + L: "Reutlingen" + O: "Linuxschule" + emailAddress: "admin@example.com" + CN: "Radius Certificate Authority" + password: "OtherVerySecurePassw0rd" +wlan_eap_ca_crl: "http://radius.{{ domain }}/radius-ca.crl" +wlan_enable_on_boot: true diff --git a/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml new file mode 100644 index 0000000..74bc7c4 --- /dev/null +++ b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml @@ -0,0 +1,52 @@ +--- +# WPA-Enterprise (EAP-TLS) - Check if certificate needs to be re-enrolled +- name: Check if certificate is already active on client + ansible.builtin.stat: + path: "/etc/ssl/certs/{{ wlan_ssid }}.crt" + register: cert_client_active + +- name: Extract serial from certificate + ansible.builtin.command: 'openssl x509 -noout -serial -in /etc/ssl/certs/{{ wlan_ssid }}.crt' + changed_when: false + register: cert_serial + when: cert_client_active.stat.exists + +- name: Download crl from radius-server + ansible.builtin.get_url: + force: true + mode: "0644" + url: "{{ wlan_eap_ca_crl }}" + dest: /tmp/radius-ca.crl + when: cert_client_active.stat.exists + +- name: Get radius-server ca crl + community.crypto.x509_crl_info: + path: /tmp/radius-ca.crl + list_revoked_certificates: true + register: radius_crl + when: cert_client_active.stat.exists + +- name: Check if radius-server is reachable + ansible.builtin.command: echo "Test if radius-server is reachable" + delegate_to: radius_server + register: radius_reachable + changed_when: false + ignore_unreachable: true + +- name: Inform that radius_server is unreachable + ansible.builtin.debug: + msg: + - "Couldn't access radius_server. Possible reasons" + - "* server not reachable" + - "* no matching ssh-key" + changed_when: true + when: radius_reachable.unreachable is defined and radius_reachable.unreachable + +- name: Issue radius certificate + ansible.builtin.include_tasks: eap-tls_issue-certificate.yaml + when: + - radius_reachable.unreachable is not defined or not radius_reachable.unreachable + - | + ( not cert_client_active.stat.exists ) or + (cert_serial.stdout | replace('serial=','') | int(base=16) ) in ( radius_crl.revoked_certificates | map(attribute='serial_number') | list ) or + wlan_force_issue diff --git a/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml new file mode 100644 index 0000000..a3258df --- /dev/null +++ b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml @@ -0,0 +1,112 @@ +--- +# WPA-Enterprise (EAP-TLS) - (re-)enroll certificate on client +- name: Create private key for client certificate + community.crypto.openssl_privatekey: + path: /etc/ssl/private/{{ wlan_ssid }}.key + +- name: Check if a certificate is already issued to client + ansible.builtin.stat: + path: "/etc/freeradius/3.0/certs/issued/{{ ansible_hostname }}.crt" + register: cert_already_issued + delegate_to: radius_server + +- name: Revoke already existing client certificate + community.crypto.x509_crl: + path: "/etc/freeradius/3.0/certs/ca.crl" + privatekey_path: "/etc/freeradius/3.0/certs/ca.key" + privatekey_passphrase: "{{ wlan_eap_ca.password }}" + crl_mode: "update" + issuer: + C: "{{ wlan_eap_ca.C }}" + ST: "{{ wlan_eap_ca.ST }}" + L: "{{ wlan_eap_ca.L }}" + O: "{{ wlan_eap_ca.O }}" + emailAddress: "{{ wlan_eap_ca.emailAddress }}" + CN: "{{ wlan_eap_ca.CN }}" + last_update: "+0s" + next_update: "+365d" + revoked_certificates: + - path: "/etc/freeradius/3.0/certs/issued/{{ ansible_hostname }}.crt" + revocation_date: "{{ ansible_date_time.iso8601_basic_short | replace('T', '') }}Z" + reason: "unspecified" + delegate_to: radius_server + when: cert_already_issued.stat.exists + +- name: Create CSR for client certificate + community.crypto.openssl_csr_pipe: + common_name: "{{ ansible_hostname }}" + country_name: "{{ wlan_eap_ca.C }}" + state_or_province_name: "{{ wlan_eap_ca.ST }}" + locality_name: "{{ wlan_eap_ca.L }}" + organization_name: "{{ wlan_eap_ca.O }}" + privatekey_path: /etc/ssl/private/{{ wlan_ssid }}.key + email_address: "{{ wlan_eap_ca.emailAddress }}" + register: csr + +- name: Sign CSR on Radius + community.crypto.x509_certificate_pipe: + csr_content: "{{ csr.csr }}" + provider: ownca + ownca_path: /etc/freeradius/3.0/certs/ca.pem + ownca_privatekey_path: /etc/freeradius/3.0/certs/ca.key + ownca_privatekey_passphrase: "{{ wlan_eap_ca.password }}" + ownca_not_after: +1825d # 5 Years + delegate_to: radius_server + register: certificate + +- name: Create issued-Notice folder on radius-server + ansible.builtin.file: + dest: "/etc/freeradius/3.0/certs/issued" + state: directory + mode: '0755' + delegate_to: radius_server + +- name: Copy client certificate to radius-server + ansible.builtin.copy: + dest: "/etc/freeradius/3.0/certs/issued/{{ ansible_hostname }}.crt" + mode: "0644" + content: "{{ certificate.certificate }}" + delegate_to: radius_server + +- name: Write certificate to client + ansible.builtin.copy: + dest: /etc/ssl/certs/{{ wlan_ssid }}.crt + mode: '0644' + content: "{{ certificate.certificate }}" + +- name: Check if NetworkManager config exists {{ wlan_ssid }} + ansible.builtin.stat: + path: /etc/NetworkManager/system-connections/{{ wlan_ssid }}.nmconnection + register: nm_connection + +- name: Create or modify connection via nmcli {{ wlan_ssid }} + ansible.builtin.command: > + nmcli c {% if nm_connection.stat.exists %} modify {{ wlan_ssid }} {% else %} add {% endif %} + type wifi + ifname {{ ansible_interfaces | select('search', 'wl.+') | first }} + con-name "{{ wlan_ssid }}" + connection.permissions "" + 802-11-wireless.ssid "{{ wlan_ssid }}" + 802-11-wireless-security.key-mgmt wpa-eap + 802-1x.eap tls + 802-1x.identity {{ ansible_hostname }} + 802-1x.client-cert /etc/ssl/certs/{{ wlan_ssid }}.crt + 802-1x.private-key /etc/ssl/private/{{ wlan_ssid }}.key + 802-1x.private-key-password dummy + changed_when: false + +# Temporary fix used to migrate from IWD to WPA-Supplicant - Will be removed later +- name: Enable wpa-supplicant + ansible.builtin.systemd: + name: wpa_supplicant.service + enabled: true + +- name: Disable iwd + ansible.builtin.systemd: + name: iwd.service + enabled: false + +- name: Remove deprecated NetworkManager config + ansible.builtin.blockinfile: + path: /etc/NetworkManager/NetworkManager.conf + state: absent diff --git a/roles/lmn_wlan/tasks/main.yaml b/roles/lmn_wlan/tasks/main.yaml new file mode 100644 index 0000000..1fb7ec2 --- /dev/null +++ b/roles/lmn_wlan/tasks/main.yaml @@ -0,0 +1,42 @@ +--- +# Setup requirements +- name: Install packages related to wifi + ansible.builtin.apt: + name: + - systemd-resolved + - firmware-realtek # for our wifi sticks + +- name: Provide service to enable WiFi on boot + ansible.builtin.copy: + dest: /etc/systemd/system/enable-wifi.service + mode: '0644' + content: | + [Unit] + Description=Switch WiFi on + After=NetworkManager.service + + [Service] + Type=oneshot + ExecStart=/usr/bin/nmcli radio wifi on + + [Install] + WantedBy=multi-user.target + when: wlan_enable_on_boot + +- name: Enable the enable-wifi service + ansible.builtin.systemd: + name: enable-wifi.service + enabled: true + daemon_reload: true + when: wlan_enable_on_boot + +# lmn_wlan - Initial configuration based on the WLAN variable +# When WLAN type is set to PSK +- name: Configure WPA-PSK + ansible.builtin.include_tasks: wpa-psk.yaml + when: wlan == 'psk' + +# When WLAN type is set to EAP-TLS (802.1x) +- name: Configure WPA-Enterprise (EAP-TLS) + ansible.builtin.include_tasks: eap-tls_check-certificate.yaml + when: wlan == 'eap-tls' diff --git a/roles/lmn_wlan_nm/tasks/main.yml b/roles/lmn_wlan/tasks/wpa-psk.yaml similarity index 70% rename from roles/lmn_wlan_nm/tasks/main.yml rename to roles/lmn_wlan/tasks/wpa-psk.yaml index 7122c7f..f6936b0 100644 --- a/roles/lmn_wlan_nm/tasks/main.yml +++ b/roles/lmn_wlan/tasks/wpa-psk.yaml @@ -1,13 +1,14 @@ --- +# WPA-PSK - Configure SSID on client - name: Configure WLAN for devices community.general.nmcli: - conn_name: "{{ ssid }}" + conn_name: "{{ wlan_ssid }}" type: wifi - ssid: "{{ ssid }}" + ssid: "{{ wlan_ssid }}" ifname: "{{ ansible_interfaces | select('search', 'wl.+') | first }}" wifi_sec: key-mgmt: wpa-psk - psk: "{{ wifipasswd }}" + psk: "{{ wlan_password }}" autoconnect: true state: present when: | @@ -15,9 +16,9 @@ ansible_interfaces | select('search', 'wl.+') | first is defined - name: Provide WLAN config during installation - template: + ansible.builtin.template: src: ssid.nmconnection.j2 - dest: "/etc/NetworkManager/system-connections/{{ ssid }}.nmconnection" + dest: "/etc/NetworkManager/system-connections/{{ wlan_ssid }}.nmconnection" mode: '0600' when: | run_in_installer|default(false)|bool and diff --git a/roles/lmn_wlan_nm/templates/ssid.nmconnection.j2 b/roles/lmn_wlan/templates/ssid.nmconnection.j2 similarity index 100% rename from roles/lmn_wlan_nm/templates/ssid.nmconnection.j2 rename to roles/lmn_wlan/templates/ssid.nmconnection.j2 diff --git a/roles/lmn_wlan_iwd/tasks/main.yml b/roles/lmn_wlan_iwd/tasks/main.yml deleted file mode 100644 index c8ff1c1..0000000 --- a/roles/lmn_wlan_iwd/tasks/main.yml +++ /dev/null @@ -1,60 +0,0 @@ -## Make sure to use an initrd providing firmware: -## wget https://cdimage.debian.org/cdimage/firmware/testing/current/firmware.cpio.gz -## cat initrd.gz firmware.cpio.gz > initrd-fw.gz ---- -- name: Install packages related to iwd and wifi - ansible.builtin.apt: - name: - - iwd - - systemd-resolved - - firmware-realtek # for our wifi sticks - - rfkill - state: latest - -- name: Disable wpa-supplicant - ansible.builtin.systemd: - name: wpa_supplicant.service - enabled: False - -- name: Enable iwd - ansible.builtin.systemd: - name: iwd.service - enabled: True - -- name: Prepare directory for iwd - file: - path: /var/lib/iwd/ - state: directory - -- name: Configure iwd for wifi device - ansible.builtin.copy: - dest: /var/lib/iwd/{{ ssid }}.psk - content: | - [Security] - Passphrase={{ wifipasswd }} - -- name: Enable systemd-networkd - ansible.builtin.systemd: - name: systemd-networkd.service - enabled: True - - -- name: Provide service to enable WiFi on boot - ansible.builtin.copy: - dest: /etc/systemd/system/enable-wifi.service - content: | - [Unit] - Description=Switch WiFi on - - [Service] - Type=oneshot - ExecStart=/usr/sbin/rfkill enable wifi - - [Install] - WantedBy=multi-user.target - -- name: Enable the enable-wifi service - ansible.builtin.systemd: - name: enable-wifi.service - enabled: True - daemon_reload: True diff --git a/roles/up2date_debian/defaults/main.yml b/roles/up2date_debian/defaults/main.yml deleted file mode 100644 index 97d8c9b..0000000 --- a/roles/up2date_debian/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -extra_pkgs: "" -extra_pkgs_bpo: "" diff --git a/roles/up2date_debian/tasks/main.yml b/roles/up2date_debian/tasks/main.yml index b71d0d8..02def13 100644 --- a/roles/up2date_debian/tasks/main.yml +++ b/roles/up2date_debian/tasks/main.yml @@ -1,49 +1,28 @@ # Update lists and upgrade packages. -- name: update apt package lists - apt: +- name: Update apt package lists + ansible.builtin.apt: update_cache: true cache_valid_time: 86400 -- block: - - name: upgrade packages - apt: +- name: Try to upgrade packages + block: + - name: Upgrade packages + ansible.builtin.apt: upgrade: dist autoremove: true autoclean: true rescue: - name: Looks like dpkg was interrupted, configure manually - command: + ansible.builtin.command: cmd: dpkg --configure -a + changed_when: true - name: Try again to upgrade packages - apt: + ansible.builtin.apt: upgrade: dist autoremove: true autoclean: true -- name: install etckeeper - apt: +- name: Install etckeeper + ansible.builtin.apt: name: etckeeper - state: latest # noqa package-latest - -- name: install extra packages from stable - apt: - name: "{{ extra_pkgs }}" - state: latest # noqa package-latest - when: extra_pkgs|length - -- name: add {{ ansible_distribution_release }}-backports - apt_repository: - repo: > - deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports - main non-free-firmware - state: present - update_cache: true - when: extra_pkgs_bpo|length - -- name: install extra packages from backports - apt: - name: "{{ extra_pkgs_bpo }}" - state: latest # noqa package-latest - default_release: "{{ ansible_distribution_release }}-backports" - when: extra_pkgs_bpo|length diff --git a/tools/emitter b/tools/emitter index be950c1..a117ba2 100755 --- a/tools/emitter +++ b/tools/emitter @@ -15,7 +15,7 @@ debug=false ## date of latest git commit in ansible repository: git_date="$(date --iso-8601=seconds --date="$(git log --date=iso-strict | \ - head -3 | sed -nE "s/^Date:\s+(.+)$/\1/p")")" + head -4 | sed -nE "s/^Date:\s+(.+)$/\1/p")")" echo "Latest commit in git at: $git_date." if [[ $# = 0 ]] ; then @@ -52,7 +52,8 @@ find_outdated(){ ipa="$(sed -nE "s|^.+default via.+ src ($r) metric.+|\1|p" "$file" | head -1)" echo -ne "\n Outdated '$ipa': $file" fi - hlist="$hlist,$ipa" + ## limit number of hosts addressed in one ansible run: + [[ n -lt 30 ]] && hlist="$hlist,$ipa" n=$(( n + 1 )) if [[ $(date --date="$d" +%s) -lt $(date --date="$git_date" +%s) ]] ; then ## ansible run needed at least on one machine, run it on all: @@ -78,6 +79,7 @@ run_ansible(){ while IFS= read -r ipa ; do echo "Ansible for IP address '$ipa' failed." done < "$dir/$pbook.retry" + > "$dir/$pbook.retry" fi fi }