Compare commits

...
Sign in to create a new pull request.

85 commits
fvs ... main

Author SHA1 Message Date
Andreas B. Mundt
04a7f48f73 Avoid always 'changed' status 2026-02-03 16:57:28 +01:00
Andreas B. Mundt
e4509661f6 Ansible 'service' module fails with mitogen, switch to 'systemd' 2026-02-03 15:12:58 +01:00
Andreas B. Mundt
9f0feb8818 Deploy another ssh pubkey 2026-02-03 13:16:37 +01:00
Raphael Dannecker
cd27d1f97c Serialize domain joins 2026-02-02 09:18:31 +01:00
Andreas B. Mundt
287af56b3a Add missing host to inventory 2026-01-27 15:40:26 +01:00
Raphael Dannecker
cbff18a88c Package needed for teaching web development 2026-01-26 18:12:17 +01:00
Raphael Dannecker
6467557934 Package needed for teaching with tony 2026-01-26 12:07:49 +01:00
Raphael Dannecker
e45cf5c0d8 Set primary video output device for some devices 2026-01-26 09:56:37 +01:00
Raphael Dannecker
b0c45eef59 Don't force secure boot measurement for TPM disk encryption 2026-01-26 09:54:56 +01:00
Raphael Dannecker
46c34fe0b5 Remove Calligra from devices due to compatibility issues 2026-01-26 09:53:09 +01:00
Raphael Dannecker
72c3847108 Fix graphics card compatibility on Lenovo 32CB boards 2025-12-22 13:43:59 +01:00
Raphael Dannecker
879850373e Increase default font size for codeblocks 2025-12-22 10:31:14 +01:00
Raphael Dannecker
787a8c843f Set default NumLock state to ON for KDE 2025-12-22 10:15:17 +01:00
Raphael Dannecker
37eb2b8232 Prevent login without krb5-ticket on non localhome machines 2025-12-18 16:27:29 +01:00
Raphael Dannecker
cf7bf30e05 Make IP addresses of teacherpc configurable (for the firewall in exam mode) 2025-12-18 16:18:23 +01:00
Raphael Dannecker
a008ef0506 Correct the determination of the teacher's PC's IP address (a75934c) 2025-12-18 12:37:32 +01:00
Raphael Dannecker
60b585f306 Fix condition, when ad.user_input is not defined (Part II) 2025-12-18 08:02:00 +01:00
Raphael Dannecker
a72f16fd20 Fix condition, when ad.user_input is not defined 2025-12-18 07:40:30 +01:00
Raphael Dannecker
e02add04ae Set the environment variable for the path to KiCad's 3D models (NFS) 2025-12-17 19:41:38 +01:00
Raphael Dannecker
f89b113049 Enable ARP support in nftable for outbound restriction in exam_mode 2025-12-17 18:50:16 +01:00
Raphael Dannecker
194fbbc735 Fix a syntax error in the var section of a task 2025-12-17 18:28:34 +01:00
Raphael Dannecker
2b45174f0f Prevent luks-detection task from aborting on unencrypted devices 2025-12-17 18:23:10 +01:00
Raphael Dannecker
9ee19d1459 Apply outbound restriction in exam_mode on macvtap interfaces too 2025-12-17 13:26:03 +01:00
Raphael Dannecker
93a0f07846 Apply libvirt firewall policy only on devices with vm_support 2025-12-17 13:25:49 +01:00
Raphael Dannecker
405fed1fcf No longer logout when /lmn/media directory not present (not present on localhome devices anymore) 2025-12-15 12:30:16 +01:00
Raphael Dannecker
241f13d136 Add domjoin user, password and disk_encryption passphrase to inventory 2025-12-15 12:26:09 +01:00
Raphael Dannecker
e45275181f Encryption role for luks encrypted drives including TPM2 support 2025-12-15 12:19:17 +01:00
Raphael Dannecker
b807d2142e Reboot system after initial ansible-run 2025-12-15 12:18:53 +01:00
Raphael Dannecker
37b8b94c9d Make domjoin user and password configurable via inventory and join domain only when necessary 2025-12-15 12:18:29 +01:00
Raphael Dannecker
c53e43f4ce Tag tasks for basic installation 2025-12-15 12:18:09 +01:00
Raphael Dannecker
3bfc3de6a1 Allow using tags using import_role instead of include_role 2025-12-15 12:17:43 +01:00
Raphael Dannecker
9797ac3d4e Add package php-sqlite3 (required for teaching purposes) 2025-12-11 14:23:21 +01:00
Raphael Dannecker
51ae283d6d Activate outbound traffic restriction in exam-mode for PCRooms 2025-12-11 08:23:28 +01:00
Raphael Dannecker
f032517a94 Restrict outbound traffic in exam-mode 2025-12-10 17:16:37 +01:00
Raphael Dannecker
857b834232 Fix NETHOME detection issue for examusers, staff and parents 2025-12-10 17:16:00 +01:00
Raphael Dannecker
63dec2f8b7 Add hosts to inventory 2025-12-04 08:16:34 +01:00
Raphael Dannecker
e7b2f7edd9 Provide a skript to delete VM disks in /lmn/vm 2025-11-27 17:03:49 +01:00
Raphael Dannecker
3ac7e99bb0 Due to new media tables, change the default audio output for some PCs 2025-11-27 16:02:10 +01:00
Raphael Dannecker
98bdee5f4d Add package libsqlite3-dev (required for teaching purposes) 2025-11-27 15:58:27 +01:00
Raphael Dannecker
e8015d70d1 Update browser bookmarks (webuntis) 2025-11-27 15:58:20 +01:00
Andreas B. Mundt
15cd06f4d6 Fix type=user VMs 2025-11-17 12:30:58 +01:00
Raphael Dannecker
fb9ffa53bb Fix graphic issues in Chromium for specific video cards 2025-11-10 17:28:56 +01:00
Andreas B. Mundt
fee6a0bc18 Fixes for trixie livebox images (dracut) 2025-11-10 08:18:53 +01:00
Raphael Dannecker
f95b220aa0 Allow multiple entries for debian and match IPv4 more strictly 2025-10-29 16:40:12 +01:00
Raphael Dannecker
148a478121 Add new hosts to inventory 2025-10-08 12:22:50 +02:00
Raphael Dannecker
9a83ebca6b Fix screen resolution for C157 2025-10-07 10:34:53 +02:00
Raphael Dannecker
8ec701595a Prevent simultaneous logins from multiple users (multi-seat mode)
Because the home directory is mounted via pam_mount using the user's Kerberos ticket,
simultaneous login of two users is not possible.
2025-10-06 20:20:59 +02:00
Raphael Dannecker
cb37d52271 Eliminate bind mounts that are no longer required for virtual machines (VMs) 2025-10-06 20:13:58 +02:00
Raphael Dannecker
b4caaf036d Implement timeout for krb5 ticket retrieval during VPN connections 2025-10-06 13:12:08 +02:00
Raphael Dannecker
61833201cb Remove the Nextcloud/WebDAV integration 2025-10-05 16:49:16 +02:00
Raphael Dannecker
998bcb515a Add firmware-sof-signed package for audio output on different Lenovo devices 2025-10-05 16:01:03 +02:00
Raphael Dannecker
ad9c0e7243 zulucrypt-gui package has been removed from Trixie 2025-10-05 15:55:59 +02:00
Raphael Dannecker
e83616292f Set firefox and thunderbird as default applications 2025-10-05 15:55:25 +02:00
Raphael Dannecker
62f2ac58f4 Freeplane package has been removed from Trixie 2025-10-05 15:54:13 +02:00
Raphael Dannecker
34fbb44b22 Fix Ansible boolean syntax for compatibility with new version 2025-10-05 15:51:14 +02:00
Raphael Dannecker
fdc44b8a6d Move outbound traffic restriction from teacher pc to classromm pcs 2025-10-02 08:54:05 +02:00
Raphael Dannecker
29d77f3ba3 Due to new media tables, the audio output on some devices has changed 2025-10-02 08:40:41 +02:00
Raphael Dannecker
f69cc6efb7 Add more links to firefox bookmarks 2025-10-02 08:05:00 +02:00
Raphael Dannecker
191e953bb0 Force vminfo.service to run on every vm start 2025-10-02 08:04:44 +02:00
Raphael Dannecker
51d4e34a07 No longer output error messages from the vminfo script to stdout
The error messages were corrupting the contents of the .vminfo.json file.
Error messages are now sent to stderr.
2025-10-02 08:04:00 +02:00
Raphael Dannecker
2660cc05c8 Fix home directory for localhomes in vminfo.service 2025-10-02 08:03:43 +02:00
Raphael Dannecker
1b1758809a Force use of /lmn/media/USER share for legacy VMs
- Introduced VMLEGACY environment variable to ensure that old VMs
  utilize the legacy media share located at /lmn/media/USER.
- This change is aimed at maintaining compatibility with older
  virtual machines that rely on the previous media share structure.
2025-10-02 08:03:24 +02:00
Raphael Dannecker
a7c879d267 Sync desktop starters from fileserver instead of server 2025-10-02 08:02:22 +02:00
Raphael Dannecker
e875ac00a4 Configure SSSD for hourly ticket lifetime checks and renewal 2025-10-02 08:01:05 +02:00
Raphael Dannecker
b688a8df59 Refactor VM volume mounting
- Replace bind-mounts on /lmn/media/$USER with separate
  mounting for Home and Share SMB shares in the VM.
- Update vm-run to start virtiofsd with /lmn/media/$USER
  (/home/$USER on localhome machines).
- Use vm-vminfo to generate a JSON file containing user
  information, including Username, Groups, printer list
  krb5-ticket and some more
- Configure vminfo.service (systemd-timer) to periodically
  call vm-vminfo.
- Ensure krb5-ticket (TGT) is injected into the Windows VM.
- Mount SMB-Home and SMB-Share shares as part of the new structure.
2025-10-02 08:00:13 +02:00
Raphael Dannecker
efd48de6c7 The virt-viewer package must be explicitly selected for trixie 2025-06-05 13:02:12 +02:00
Raphael Dannecker
db6197d0a0 Prevents the --options option in vm-run from interfering with other options 2025-06-05 12:48:10 +02:00
Raphael Dannecker
563ac18483 Add host to inventory 2025-06-04 11:20:58 +02:00
Raphael Dannecker
76c7cc042a Configure display resolution / audio out for specific clients 2025-06-04 10:49:47 +02:00
Raphael Dannecker
84865291e0 Allow multiple macvtap-VMs to use the same MAC address 2025-06-04 10:26:56 +02:00
Raphael Dannecker
6e119e0129 Omit backports, because Trixie does not have backports yet 2025-06-04 10:21:18 +02:00
Andreas B. Mundt
6063e65089 Fixes for trixie 2025-05-14 12:33:39 +02:00
Andreas B. Mundt
0e0950d184 Fix conditionals for ansible version in trixie 2025-05-14 12:33:39 +02:00
Raphael Dannecker
ce31924a3c Remove unnecessary systemd-resolved 2025-05-08 07:16:12 +02:00
Raphael Dannecker
f0fd1d5aa0 Skip delegate_to tasks when running in installer 2025-05-07 14:38:01 +02:00
Raphael Dannecker
e060ba9161 Prevent playbook abort if iwd was not installed 2025-05-07 13:35:32 +02:00
Raphael Dannecker
dfb9cf5ee7 Fix playbook check if delegate_to host is accessible 2025-05-07 13:32:17 +02:00
Raphael Dannecker
233e8e4ecf Improve documentation 2025-04-09 16:08:46 +02:00
Raphael Dannecker
3580a9141b Avoid the need to use ssh keys for ansible connections to localhost 2025-04-09 14:18:17 +02:00
Raphael Dannecker
39d2491e36 Use defaults for kde_desktop_pkg in inventory-sample 2025-04-09 08:38:18 +02:00
Raphael Dannecker
9f5ecfc4f1 Improve documentation about installation via pxe 2025-04-08 18:35:47 +02:00
Raphael Dannecker
0406669109 Add vaultpw to debian installer preseeding 2025-04-08 11:19:19 +02:00
Raphael Dannecker
4f69dc0dfe Merge fvs branch into main 2025-04-08 08:06:36 +02:00
Andreas B. Mundt
92bacc4dd3 Merge branch 'fvs' 2024-03-12 19:45:10 +01:00
andi
24fcf70e1d Initial commit 2024-03-12 17:53:49 +00:00
57 changed files with 1832 additions and 928 deletions

View file

@ -1,6 +1,12 @@
# Installation on existing client # Installation on existing client
An easy method to test the lmn-client is to run the playbook manual on a fresh installed client. A straightforward way to test the lmn-client is to manually run the playbook on a freshly installed client.
This can be done in the following ways:
On the client using ansible-pull
On the client by checking out the lmn-client repository and running the playbook locally
On a target device by checking out the lmn-client repository locally and executing the playbook against the target device
## Direct call via ansible-pull ## Direct call via ansible-pull
@ -9,10 +15,10 @@ With two simple commands you can install the lmn-client with default configurati
Steps: Steps:
* Install debian on client (via USB or PXE) * Install debian on client (via USB or PXE)
* Install additional packages: ansible * Install additional packages: ansible
`sudo apt install ansible` `sudo apt install ansible`
* Run Playbook * Run Playbook
`ansible-pull -i inventory.yml -l localhost, --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml` `sudo ansible-pull --verbose -i inventory-sample.yml -l localhost --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml`
## Checkout git and run ansible locally ## Checkout git and run ansible locally
@ -24,10 +30,12 @@ Steps:
* Install debian on client (via USB or PXE) * Install debian on client (via USB or PXE)
* Install additional packages: ansible, git * Install additional packages: ansible, git
`sudo apt install ansible git` `sudo apt install ansible git`
* Checkout Repository * Checkout Repository
`git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git` `git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git`
* Change into repository directory
`cd lmn-client`
* Create inventory * Create inventory
`cp inventory.yml inventory-myschool.yml` `cp inventory-sample.yml inventory-myschool.yml`
* Edit inventory-myschool.yml * Edit inventory-myschool.yml
e.g.: `nano inventory-myschool.yml` e.g.: `nano inventory-myschool.yml`
* Run Playbook * Run Playbook

View file

@ -2,15 +2,28 @@
* **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp** * **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp**
Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository. Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository.
Linux kernel and initial Ramdisk from debian repository. Linux kernel and initial Ramdisk from debian repository.
Client must have access to the internet (noproxy group).
* **Using your own repository and LinuxMuster.Net tftp** * **Using your own repository and LinuxMuster.Net tftp**
Here you can use your own inventory and make many custom settings. Here you can use your own inventory and make many custom settings.
Linux kernel and initial Ramdisk from debian repository. Linux kernel and initial Ramdisk from debian repository.
Client must have access to the internet (noproxy group).
* **Using your own repository and livebox tftp** * **Using your own repository and livebox tftp**
Additional kernel and Ramdisk from your own infrastrukture. Additional kernel and Ramdisk from your own infrastrukture.
Client does not need direct internet access.
## Using codeberg repository and LinuxMuster.Net tftp ## Using codeberg repository and LinuxMuster.Net tftp
### Requirements / firewall settings
The computer on which the linuxclient is to be installed must have access to the Internet (add host to noproxy group)
The following resources are downloaded from the internet:
* The repository is provided by codeberg.org
* the Linux kernel, the initial ramdisk and the installation files are loaded from debian.org.
* mscorefonts from Microsoft
### Modification LinuxMuster.Net server ### Modification LinuxMuster.Net server
Create grub config for device group `lmnclient` on your schools server: Create grub config for device group `lmnclient` on your schools server:
@ -25,9 +38,12 @@ set default=1
menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' { menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' {
echo -n "Enter domain join password: " echo -n "Enter domain join password: "
read adpw read adpw
set vaultpw="dummy"
# echo -n "Enter vault password"
# read vaultpw
linux (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux auto=true priority=high \ 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 \ url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/main/misc/preseed.cfg interface=auto \
playbook=lmn-client.yml adpw="${adpw}" --- playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" ---
initrd (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz initrd (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
} }
``` ```
@ -47,4 +63,52 @@ classroom;mypc01;lmnclient;F2:81:6B:C9:E3:EF;10.0.5.51;;;;classroom-studentcompu
* confirm `hostname` and `domain` (you will be asked in network setup) * 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) * ... Get a cup of coffee ... wait until reboot ... login (Logging in may take a few minutes after installation)
## Using your own livebox server
## Using your own repository and LinuxMuster.Net tftp
If you fork the lmn-client repository, you can customize the preseeding and inventory to your needs.
Use the instructions in the previous section and customize the repository in `/srv/linbo/boot/grub/lmnclient.cfg`.
It makes sense to encrypt your inventory via `ansible-vault`.
When using encrypted inventories you have to provide the vault password by commenting in the two lines in the `/srv/linbo/boot/grub/lmnclient.cfg`.
## Using your own repository and livebox tftp
The next improvement will be to use your own livebox with following functionalities:
* Providing linux kernel and initial ramdisk for installer
* Can be used as cache for debian packages (aptcacher)
* Can provide mscorefonts and libdvdcss (multimedia codecs)
* Can be used to boot live systems (netboot) via pxe
### Installing the livebox server
* Install debian VM and configure network
* Install additional packages: ansible
`sudo apt install ansible`
* Run livebox playbook
`ansible-pull -i localhost, --url=https://salsa.debian.org/andi/debian-lan-ansible.git -C master livebox.yml`
* Set DNS entry for your new livebox server
### Modification LinuxMuster.Net server
The file `/srv/linbo/boot/grub/lmnclient.cfg` might look like this:
```
# ### 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
set vaultpw="dummy"
# echo -n "Enter vault password"
# read vaultpw
linux (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/linux auto=true priority=high \
url=https://codeberg.org/MySchool/lmn-client/raw/branch/main/misc/preseed-myschool.cfg interface=auto \
playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" ---
initrd (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/initrd.gz
}
```

View file

@ -2,10 +2,9 @@
all: all:
vars: vars:
domain: "{{ ansible_domain }}" domain: "{{ ansible_domain }}"
security_defaultuser_login_disable: false
kde_desktop_pkg:
- akonadi-backend-sqlite
# Comment out on productive systems when ssh key is provided
security_defaultuser_login_disable: false
## Proxy configuration (see: doc/localproxy.md) ## Proxy configuration (see: doc/localproxy.md)
# localproxy: true # localproxy: true
@ -59,7 +58,6 @@ all:
# - vim # - vim
# - mc # - mc
# - tmux # - tmux
# - debconf-utils
## WLAN configuration (see: doc/vpn.md): ## WLAN configuration (see: doc/vpn.md):
## ##
@ -105,6 +103,7 @@ all:
hosts: hosts:
localhost: localhost:
ansible_connection: local
laptops: laptops:
children: children:

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,7 @@
- lmn_network - lmn_network
- role: up2date_debian - role: up2date_debian
tags: upgrade tags: upgrade
- lmn_encrypt
- lmn_sssd - lmn_sssd
- lmn_mount - lmn_mount
- lmn_kde - lmn_kde
@ -63,7 +64,7 @@
- role: lmn_localhome - role: lmn_localhome
when: localhome when: localhome
- role: lmn_localuser - role: lmn_localuser
when: localuser when: localuser|bool
- role: lmn_exam - role: lmn_exam
when: exam_mode when: exam_mode
- role: lmn_wlan - role: lmn_wlan
@ -80,15 +81,17 @@
loop_var: rolename loop_var: rolename
when: custom_roles is defined when: custom_roles is defined
- name: Final tasks - name: Import role security
ansible.builtin.include_role: ansible.builtin.import_role:
name: "{{ role }}" name: lmn_security
loop_control:
loop_var: role - name: Import role finish
loop: ansible.builtin.import_role:
- lmn_security name: lmn_finish
- lmn_finish
- lmn_tmpfixes - name: Import role tmpfixes
ansible.builtin.import_role:
name: lmn_tmpfixes
- name: Apply roles that must run serial - name: Apply roles that must run serial

107
lmn-vault
View file

@ -1,107 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
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

View file

@ -50,13 +50,11 @@ d-i apt-setup/contrib boolean true
d-i mirror/country string manual d-i mirror/country string manual
d-i mirror/http/hostname string deb.debian.org d-i mirror/http/hostname string deb.debian.org
d-i mirror/http/directory string /debian 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://aptcache.pn.steinbeis.schule:3142/
#d-i mirror/http/proxy string http://192.168.1.17:3142/ d-i mirror/http/proxy string
#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: # NTP server to use:
d-i clock-setup/ntp-server string server.pn.steinbeis.schule #d-i clock-setup/ntp-server string server.pn.steinbeis.schule
### Backports: ### Backports:
#apt-setup-udeb apt-setup/services-select multiselect security, updates, backports #apt-setup-udeb apt-setup/services-select multiselect security, updates, backports
@ -129,10 +127,9 @@ d-i preseed/late_command string \
in-target mount -v -t tmpfs tmpfs /dev/shm ; \ in-target mount -v -t tmpfs tmpfs /dev/shm ; \
echo "$vaultpw" > /target/dev/shm/vaultpw ; \ echo "$vaultpw" > /target/dev/shm/vaultpw ; \
in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \ in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \
-l localhost \ --vault-password-file /dev/shm/vaultpw -l localhost \
-i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C fvs $playbook ; \ -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main $playbook ; \
fi fi
## --vault-password-file /dev/shm/vaultpw -l localhost \
# #
## When installing in combination with ansible-pull, ## When installing in combination with ansible-pull,
## export your ansible playbook like: ## export your ansible playbook like:

Binary file not shown.

155
misc/vm/injector.ps1 Normal file
View file

@ -0,0 +1,155 @@
param(
[string]$ticketb64
)
# BASE64
$ticket = New-Object System.Byte
#reading from b64
$ticket = [System.Convert]::FromBase64String($ticketb64)
if ($ticket -eq $null){
write-host "[-] Be Sure entering the correct mode"
write-host "[-] Cannot receive ticket from file or b64"
exit;
}
# ------------------- FUNCTIONS -----------------------#
$ptt = @"
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
public enum KERB_PROTOCOL_MESSAGE_TYPE
{
KerbDebugRequestMessage,
KerbQueryTicketCacheMessage,
KerbChangeMachinePasswordMessage,
KerbVerifyPacMessage,
KerbRetrieveTicketMessage,
KerbUpdateAddressesMessage,
KerbPurgeTicketCacheMessage,
KerbChangePasswordMessage,
KerbRetrieveEncodedTicketMessage,
KerbDecryptDataMessage,
KerbAddBindingCacheEntryMessage,
KerbSetPasswordMessage,
KerbSetPasswordExMessage,
KerbVerifyCredentialMessage,
KerbQueryTicketCacheExMessage,
KerbPurgeTicketCacheExMessage,
KerbRefreshSmartcardCredentialsMessage,
KerbAddExtraCredentialsMessage,
KerbQuerySupplementalCredentialsMessage,
KerbTransferCredentialsMessage,
KerbQueryTicketCacheEx2Message,
KerbSubmitTicketMessage,
KerbAddExtraCredentialsExMessage
}
[StructLayout(LayoutKind.Sequential)]
public struct KERB_CRYPTO_KEY32
{
public int KeyType;
public int Length;
public int Offset;
}
[StructLayout(LayoutKind.Sequential)]
public struct KERB_SUBMIT_TKT_REQUEST
{
public KERB_PROTOCOL_MESSAGE_TYPE MessageType;
public LUID LogonId;
public int Flags;
public KERB_CRYPTO_KEY32 Key;
public int KerbCredSize;
public int KerbCredOffset;
}
[StructLayout(LayoutKind.Sequential)]
public struct LSA_STRING_IN
{
public ushort Length;
public ushort MaximumLength;
public IntPtr buffer;
}
[DllImport("secur32.dll", SetLastError=false)]
public static extern int LsaLookupAuthenticationPackage([In] IntPtr LsaHandle,[In] ref LSA_STRING_IN PackageName,[Out] out UInt32 AuthenticationPackage);
[DllImport("Secur32.dll", SetLastError = true)]
public static extern int LsaCallAuthenticationPackage(IntPtr LsaHandle,uint AuthenticationPackage,IntPtr ProtocolSubmitBuffer,int SubmitBufferLength,out IntPtr ProtocolReturnBuffer,out ulong ReturnBufferLength,out int ProtocolStatus);
[DllImport("secur32.dll", SetLastError=false)]
public static extern int LsaConnectUntrusted([Out] out IntPtr LsaHandle);
[DllImport("secur32.dll", SetLastError=false)]
public static extern int LsaDeregisterLogonProcess([In] IntPtr LsaHandle);
[DllImport("advapi32.dll", SetLastError=true)]
public static extern uint LsaNtStatusToWinError(uint status);
"@
Function ConnectToLsa()
{
$lsahandle = New-Object System.IntPtr
[int]$retcode = [KRB.PTT]::LsaConnectUntrusted([ref]$lsahandle)
if ($retcode -ne 0){
write-host "[-] LsaConnectUntrusted Error (NTSTATUS): ", $retcode -ForegroundColor Red
exit;
}
return $lsahandle
}
#-------------------------------- ENTRY POINT ----------------------------#
$assemblies = [System.Reflection.Assembly]::LoadWithPartialName("System.Security.Principal")
Add-Type -MemberDefinition $ptt -Namespace "KRB" -Name "PTT" -ReferencedAssemblies $assemblies.location -UsingNamespace System.Security.Principal
# CONNECTING TO LSA
$LsaHandle = ConnectToLsa
write-host "[?] LSA HANDLE: ", $LsaHandle
# EXTRACTING KERBEROS AP
$retcode = New-Object System.Int32
$authPackage = New-Object System.Int32
$name = "kerberos"
$importnantlsastring = New-Object KRB.PTT+LSA_STRING_IN
$importnantlsastring.Length = [uint16]$name.Length
$importnantlsastring.MaximumLength = [uint16]($name.Length + 1)
$importnantlsastring.buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($name)
$retcode = [KRB.PTT]::LsaLookupAuthenticationPackage($lsaHandle,[ref]$importnantlsastring,[ref]$authPackage)
if ($retcode -ne 0){
write-host "[-] Error LsaLookupAuthPckg (NTSTATUS): ", $retcode -ForegroundColor Red
exit;
}
write-host "[?] Kerberos Package: ", $authPackage
# GETTING CURRENT LUID (INJECT PURPOSES)
$output = klist
$CurrLuid = $output.split("`n")[1].split(":")[1]
$sysIntCurrLuid = [convert]::ToInt32($CurrLuid,16)
$luidFinally = New-Object KRB.PTT+LUID
$luidFinally.LowPart = $sysIntCurrLuid
# TICKET INJECTING
$protocolReturnBuffer = New-Object System.IntPtr
$ReturnBufferLength = New-Object System.Int32
$ProtocolStatus = New-Object System.Int32
$KrbRequestInfo = New-Object KRB.PTT+KERB_SUBMIT_TKT_REQUEST
$KrbRequestInfoType = $KrbRequestInfo.getType()
$KrbRequestInfo.MessageType = [KRB.PTT+KERB_PROTOCOL_MESSAGE_TYPE]::KerbSubmitTicketMessage
$KrbRequestInfo.KerbCredSize = $ticket.Length
$KrbRequestInfo.KerbCredOffset = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$KrbRequestInfoType)
$KrbRequestInfo.LogonId = $luidFinally
$inputBufferSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$KrbRequestInfoType) + $ticket.Length
$inputBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($inputBufferSize)
[System.Runtime.InteropServices.Marshal]::StructureToPtr($KrbRequestInfo,$inputBuffer,$false)
[System.IntPtr]$PtrToCred = $inputBuffer.ToInt64() + $KrbRequestInfo.KerbCredOffset
[System.Runtime.InteropServices.Marshal]::Copy($ticket,0,$PtrToCred,$ticket.Length)
$ntstatus = [KRB.PTT]::LsaCallAuthenticationPackage($lsaHandle,$authPackage,$inputBuffer,$inputBufferSize,[ref]$protocolReturnBuffer,[ref]$ReturnBufferLength,[ref]$ProtocolStatus)
if(($ProtocolStatus -ne 0) -or ($ntstatus -ne 0))
{
Write-Host "[!] Error in LsaCallAuthenticationPackage" -ForegroundColor Red
write-host " NTSTATUS: ", $ntstatus, " Protocol Status: ", $ProtocolStatus
if ($ProtocolStatus -eq -1073741517){
" Ticket may be out of date"
}
exit;
}
if($inputBuffer -ne [System.IntPtr]::Zero)
{
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($inputBuffer)
[System.Object]$ticket = $null
}
klist

View file

@ -0,0 +1,73 @@
# Installiere alle Mounts aus target.csv
# Geprüft wird, ob das Laufwerk bereits vorhanden
# 11.05.2025 da
function Mount-Drive {
param (
[string]$DriveLetter,
[string]$TargetPath
)
try {
& "C:\Program Files (x86)\WinFsp\bin\launchctl-x64.exe" start virtiofs viofs$DriveLetter $TargetPath \\.\${DriveLetter}:
Write-Verbose "Laufwerk hinzugefügt: $DriveLetter"
} catch {
Write-Error "Fehler beim Hinzufügen des Laufwerks ${DriveLetter}: $_"
}
}
function Import-VMInfo {
param (
[string]$Path
)
if (Test-Path $Path) {
return Get-Content -Path $Path -Raw | ConvertFrom-Json
} else {
Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)."
Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt."
Pause
exit
}
}
# Laufwerk Y: mit weiteren Mountpoint-Infos mounten
& "C:\Program Files\Virtio-Win\VioFS\virtiofs.exe" -m Y:
#Mount-Drive -DriveLetter "Y" -TargetPath "VM-Data"
# VMInfo aus JSON File einlesen
$VMInfoPath = "Y:\.vminfo.json"
# Schleife, die auf das Laufwerk wartet
while (-not (Test-Path $VMInfoPath)) {
Write-Host "Warte auf $VMInfoPath..."
Start-Sleep -Seconds 1
}
$VMInfo = Import-VMInfo -Path $VMInfoPath
# Weitere Laufwerke einbinden
#foreach ($virtiofs in $VMInfo.VirtioFS) {
# $targetDrive = $virtiofs.Drive
# if (-not (Get-PSDrive -Name $targetDrive -ErrorAction SilentlyContinue)) {
# Mount-Drive -DriveLetter $targetDrive -TargetPath $virtiofs.Target
# } else {
# Write-Error "Laufwerk bereits vorhanden: $targetDrive"
# }
#}
# Drucker installieren
foreach ($drucker in $VMInfo.Printers) {
# Überprüfen, ob der Drucker bereits vorhanden ist
$druckerName = $drucker.Name
$druckerVorhanden = Get-Printer | Where-Object { $_.Name -eq $druckerName }
# Umwandlung in HTTP-URL
$httpUrl = $drucker.IppURL -replace "ipp://", "http://" -replace "122.1", "122.1:631"
if (-not $druckerVorhanden) {
# Drucker hinzufügen, wenn er nicht vorhanden ist
Add-Printer -PortName $httpUrl -Name $druckerName -DriverName "Microsoft IPP Class Driver"
Write-Host "Drucker hinzugefuegt: $druckerName"
} else {
Write-Host "Drucker bereits vorhanden: $druckerName"
}
}

BIN
misc/vm/vm-prepare-sys.xml Executable file

Binary file not shown.

102
misc/vm/vm-prepare-user.ps1 Normal file
View file

@ -0,0 +1,102 @@
# Installiere alle Mounts aus target.csv
# Geprüft wird, ob das Laufwerk bereits vorhanden
# 11.05.2025 da
function Import-VMInfo {
param (
[string]$Path
)
if (Test-Path $Path) {
return Get-Content -Path $Path -Raw | ConvertFrom-Json
} else {
Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)."
Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt."
Pause
exit
}
}
function Add-PathToQuickAccess([string[]]$path){
$path | %{
write-host "Adding path '$($_)' to Quick acccess list." -F Green
try{
$link = (New-Object -Com Shell.Application).NameSpace($_).Self
if(!$link){throw "Item path not valid to be pinned."}
$link.Verbs()| ?{$_.Name.replace('&','') -match 'An Schnellzugriff anheften|Pin to Quick access'} | %{$_.DoIt()}
}catch{
write-error "Error adding path. $($_.Exception.Message)"
}
}
}
$VMInfoPath = "Y:\.vminfo.json"
# Schleife, die auf das Laufwerk wartet
while (-not (Test-Path $VMInfoPath)) {
Write-Host "Warte auf $VMInfoPath..."
Start-Sleep -Seconds 1
}
# VMInfo aus JSON File einlesen
$VMInfo = Import-VMInfo -Path $VMInfoPath
& $PSScriptRoot\injector.ps1 $VMInfo.krb5.cred
$klistOutput = klist
$serverping = Test-Connection -ComputerName "server.pn.steinbeis.schule" -Count 2 -Quiet
if ($serverping) {
if ($klistOutput -like "*Client*") {
foreach ($Mount in $VMInfo.Mounts) {
net use /persistent:no "$($Mount.Drive):" "$($Mount.RemotePath)"
#New-SMBMapping -Localpath "$($Mount.Drive):" -Remotepath $Mount.RemotePath
Write-Host("net use $($Mount.Drive): $($Mount.RemotePath)")
}
} else {
#if (-not ($klistOutput -like "*Client*") -or (-not (Test-Path "H:"))) {
$Credential = Get-Credential -Message "Die automatische Einbindung der Netzlaufwerke ist fehlgeschlagen.`nBitte geben Sie Ihre Anmeldeinformationen für das Netzlaufwerk ein" $VMInfo.User
# Laufwerke einbinden
foreach ($Mount in $VMInfo.Mounts) {
net use /persistent:no "$($Mount.Drive):" "$($Mount.RemotePath)" /user:"$($Credential.UserName)" "$($Credential.GetNetworkCredential().Password)"
Write-Host("net use /persistent:no `"$($Mount.Drive):`" `"$($Mount.RemotePath)`"")
#New-SMBMapping -Localpath "$($Mount.Drive):" -Remotepath "$($Mount.RemotePath)" -UserName "$($Credential.UserName)" -Password "$($Credential.GetNetworkCredential().Password)"
#Write-Host("New-SMBMapping -Localpath $($Mount.Drive): -Remotepath $Mount.RemotePath")
}
}
} else {
Add-Type -AssemblyName System.Windows.Forms
$message = "Der Server kann derzeit nicht erreicht werden.`nDaher können die Netzlaufwerke derzeit nicht verbunden werden.`nVersuchen Sie es zu einem späteren Zeitpunkt erneut mit dem Skript: Netzlaufwerke-verbinden"
$title = "Server nicht erreichbar"
[System.Windows.Forms.MessageBox]::Show($message, $title, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
}
# Ändere den Namen der Netzlaufwerke
$shell = New-Object -ComObject Shell.Application
foreach ($Mount in $VMInfo.Mounts) {
$folder = $shell.Namespace("$($Mount.Drive):")
if ($folder) {
$folder.Self.Name = $Mount.Name
Write-Host "Das Netzlaufwerk $($Mount.Drive): wurde in '$($Mount.Name)' umbenannt."
} else {
Write-Host "Fehler beim Zugriff auf das Netzlaufwerk."
}
}
# Pfade zur Schnellzugriff hinzufügen
Add-PathToQuickAccess $VMInfo.QuickAccess
# Pfade für Standardorte ändern
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
foreach ($USF in $VMInfo.UserShellFolders) {
Write-Host "Set-ItemProperty -Path $regPath -Name $($USF.Name) -Value $($USF.Path)"
Set-ItemProperty -Path $regPath -Name "$($USF.Name)" -Value "$($USF.Path)"
}
# Explorer Neustart erzwingen (evtl. nicht notwendig)
Stop-Process -Name explorer -Force
# Start-Process explorer
# Bei Lehrern Papercut-Client starten
if (($VMInfo.Groups -contains "teachers") -and -not (Get-Process -Name pc-client -ErrorAction SilentlyContinue)) {
& "C:\custom\papercut\pc-client.exe" -m --user $VMInfo.User
}

BIN
misc/vm/vm-prepare-user.xml Executable file

Binary file not shown.

View file

@ -0,0 +1,30 @@
# Injects krb5-credential from .vminfo.json if available
# 02.07.2025 da
function Import-VMInfo {
param (
[string]$Path
)
if (Test-Path $Path) {
return Get-Content -Path $Path -Raw | ConvertFrom-Json
} else {
Write-Error "Fehler beim Einlesen der VMInfo Datei ($Path nicht gefunden)."
Write-Error "Tipp: Beim Neustart der VM wird diese Datei neu angelegt."
Pause
exit
}
}
$VMInfoPath = "Y:\.vminfo.json"
# Schleife, die auf das Laufwerk wartet
if (-not (Test-Path $VMInfoPath)) {
Write-Host "$VMInfoPath nicht gefunden. Skript beenden."
exit
}
# VMInfo aus JSON File einlesen
$VMInfo = Import-VMInfo -Path $VMInfoPath
& $PSScriptRoot\injector.ps1 $VMInfo.krb5.cred

BIN
misc/vm/vm-update-user.xml Executable file

Binary file not shown.

View file

@ -0,0 +1,15 @@
if [[ "$UID" -gt 10000 ]] && [[ ! -f ~/.config/codeblocks/default.conf ]] ; then
mkdir -p ~/.config/codeblocks
cat <<EOF > ~/.config/codeblocks/default.conf
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocksConfig version="1">
<editor>
<FONT>
<str>
<![CDATA[Monospace 18]]>
</str>
</FONT>
</editor>
</CodeBlocksConfig>
EOF
fi

View file

@ -16,11 +16,16 @@ fi
id="$(grep ID "$file" | sed -E "s|^.+ID>([[:digit:]]+)/([[:digit:]]+)</ID.+$|\1:\2|" \ id="$(grep ID "$file" | sed -E "s|^.+ID>([[:digit:]]+)/([[:digit:]]+)</ID.+$|\1:\2|" \
| sort -n -t: -k2 | tail -1 )" | sort -n -t: -k2 | tail -1 )"
if id | grep -q teachers; then for dir in teachers examusers staff parents; do
NETHOME=/srv/samba/schools/default-school/teachers/$USER if [[ -d "/srv/samba/schools/default-school/${dir}/${USER}" ]]; then
else NETHOME="/srv/samba/schools/default-school/${dir}/${USER}"
break
fi
done
if [[ -z "${NETHOME+x}" ]]; then
NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") NETHOME=(/srv/samba/schools/default-school/students/*/"$USER")
fi fi
[[ -d $NETHOME ]] || exit 0 [[ -d $NETHOME ]] || exit 0
IDENTITY="${id%%:*}" IDENTITY="${id%%:*}"
@ -49,7 +54,7 @@ fi
patch=" patch="
--- a/$file --- a/$file
+++ b/$file +++ b/$file
@@ -98,9 +98,45 @@ @@ -98,9 +98,33 @@
<isSystemItem>true</isSystemItem> <isSystemItem>true</isSystemItem>
</metadata> </metadata>
</info> </info>
@ -66,18 +71,6 @@ $HOMEONSERVER
+ <isSystemItem>true</isSystemItem> + <isSystemItem>true</isSystemItem>
+ </metadata> + </metadata>
+ </info> + </info>
+ </bookmark>
+ <bookmark href=\"file:///lmn/media/$USER/nextcloud\">
+ <title>Nextcloud</title>
+ <info>
+ <metadata owner=\"http://freedesktop.org\">
+ <bookmark:icon name=\"folder-cloud\"/>
+ </metadata>
+ <metadata owner=\"http://www.kde.org\">
+ <ID>$IDENTITY/${NUM3}</ID>
+ <isSystemItem>true</isSystemItem>
+ </metadata>
+ </info>
+ </bookmark> + </bookmark>
<bookmark href=\"remote:/\"> <bookmark href=\"remote:/\">
<title>Network</title> <title>Network</title>

View file

@ -12,7 +12,7 @@ fi
#rsync -rlptD --chown=pgmadmin:root --chmod=F755,D755 rsync://server:/local-program/ /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 \ RSYNC_COMMAND=$(rsync -ai --delete --exclude=mimeinfo.cache \
--chown=root:root --chmod=F644,D755 "rsync://server:/desktopstarter" \ --chown=root:root --chmod=F644,D755 "rsync://fileserver:/desktopstarter" \
/usr/local/share/applications/ | sed '/ \.\//d') /usr/local/share/applications/ | sed '/ \.\//d')
if [[ $? -eq 0 ]] && [[ -n "${RSYNC_COMMAND}" ]]; then if [[ $? -eq 0 ]] && [[ -n "${RSYNC_COMMAND}" ]]; then
echo "${RSYNC_COMMAND}" echo "${RSYNC_COMMAND}"

View file

@ -3,9 +3,9 @@
"Proxy": { "Proxy": {
"Mode": "autoDetect" "Mode": "autoDetect"
}, },
"OverrideFirstRunPage": "https://www.steinbeisschule-reutlingen.de", "OverrideFirstRunPage": "https://www.steinbeis.schule",
"Homepage": { "Homepage": {
"URL": "https://www.steinbeisschule-reutlingen.de", "URL": "https://www.steinbeis.schule",
"Locked": false, "Locked": false,
"StartPage": "previous-session" "StartPage": "previous-session"
}, },
@ -15,7 +15,7 @@
"toplevel_name": "FvS-Reutlingen" "toplevel_name": "FvS-Reutlingen"
}, },
{ {
"url": "https://www.steinbeisschule-reutlingen.de", "url": "https://www.steinbeis.schule",
"name": "FvS-Homepage" "name": "FvS-Homepage"
}, },
{ {
@ -27,7 +27,7 @@
"name": "FvS-eMail" "name": "FvS-eMail"
}, },
{ {
"url": "https://dw.steinbeis.schule", "url": "https://info.steinbeis.schule",
"name": "FvS-Hilfesystem" "name": "FvS-Hilfesystem"
}, },
{ {
@ -35,15 +35,23 @@
"name": "FvS-Moodle" "name": "FvS-Moodle"
}, },
{ {
"url": "https://nc.steinbeis.schule", "url": "https://cloud.steinbeis.schule",
"name": "FvS-Nextcloud" "name": "FvS-Schulcloud"
},
{
"url": "https://nct.steinbeis.schule",
"name": "FvS-Nextcloud-Teacher (Nur für Lehrer)"
},
{
"url": "https://git.steinbeis.schule",
"name": "FvS-Git Versionsverwaltung"
}, },
{ {
"url": "https://server.pn.steinbeis.schule", "url": "https://server.pn.steinbeis.schule",
"name": "Schulkonsole" "name": "Schulkonsole"
}, },
{ {
"url": "https://peleus.webuntis.com/WebUntis/?school=Ferd.von+Steinbeis#/basic/login", "url": "https://steinbeis.webuntis.com/WebUntis/?school=steinbeis#/basic/login",
"name": "FvS-Stundenplan" "name": "FvS-Stundenplan"
}, },
{ {

View file

@ -29,7 +29,6 @@
- elpa-magit - elpa-magit
- emacs - emacs
- filezilla - filezilla
- freeplane
- git - git
- git-cola - git-cola
- gitg - gitg
@ -46,6 +45,7 @@
- libasound2-dev - libasound2-dev
- libdbus-glib-1-2 ## needed for zotero - libdbus-glib-1-2 ## needed for zotero
- libnotify-bin ## needed for pwroff script - libnotify-bin ## needed for pwroff script
- libsqlite3-dev
- libwayland-dev - libwayland-dev
- libxcursor-dev - libxcursor-dev
- libxi-dev - libxi-dev
@ -62,10 +62,13 @@
- okular-extra-backends ## needed for CHM files - okular-extra-backends ## needed for CHM files
- pdf-presenter-console - pdf-presenter-console
- php-cli - php-cli
- php-sqlite3
- pipx - pipx
- planner - planner
- pulseview - pulseview
- python3-legacy-cgi
- python3-paho-mqtt - python3-paho-mqtt
- python3-pgzero
- python3-websockets - python3-websockets
- qpdfview - qpdfview
- shellcheck - shellcheck
@ -82,7 +85,7 @@
- unison-gtk - unison-gtk
- w3m - w3m
- wireshark - wireshark
- zulucrypt-gui # - zulucrypt-gui ## no longer in trixie
autoremove: true autoremove: true
state: latest state: latest
environment: environment:
@ -155,6 +158,11 @@
dest: /etc/profile.d/ dest: /etc/profile.d/
mode: '0644' mode: '0644'
- name: Copy codeblocks config scripts
ansible.builtin.copy:
src: lmn-codeblocks.sh
dest: /etc/profile.d/
mode: '0644'
- name: Copy fvs-config.js to configure plasma - name: Copy fvs-config.js to configure plasma
ansible.builtin.copy: ansible.builtin.copy:
@ -162,6 +170,16 @@
dest: /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/fvs-config.js dest: /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/fvs-config.js
mode: '0644' mode: '0644'
- name: Configure default KDE applications
ansible.builtin.blockinfile:
path: /etc/xdg/mimeapps.list
create: true
mode: '0644'
block: |
[Default Applications]
x-scheme-handler/http=firefox-esr.desktop;
x-scheme-handler/https=firefox-esr.desktop;
x-scheme-handler/mailto=thunderbird.desktop;
- name: Configure some KDE aspects - name: Configure some KDE aspects
ansible.builtin.blockinfile: ansible.builtin.blockinfile:
@ -170,13 +188,22 @@
mode: '0644' mode: '0644'
block: | block: |
[KDE] [KDE]
SingleClick=false #SingleClick=false
[KDE Action Restrictions][$i] [KDE Action Restrictions][$i]
action/start_new_session=false action/start_new_session=false
#action/switch_user=false action/switch_user=false
#action/lock_screen=false #action/lock_screen=false
- name: Configure NumLock ON
ansible.builtin.blockinfile:
path: /etc/xdg/kcminputrc
create: true
mode: '0644'
block: |
[Keyboard]
NumLock=0
- name: Start with empty session by default - name: Start with empty session by default
ansible.builtin.copy: ansible.builtin.copy:
dest: /etc/xdg/ksmserverrc dest: /etc/xdg/ksmserverrc
@ -220,7 +247,7 @@
ansible.builtin.blockinfile: ansible.builtin.blockinfile:
path: /usr/share/sddm/themes/debian-breeze/Main.qml path: /usr/share/sddm/themes/debian-breeze/Main.qml
marker: // {mark} ANSIBLE MANAGED BLOCK marker: // {mark} ANSIBLE MANAGED BLOCK
insertbefore: '\s+//Footer' insertbefore: '^}$'
block: | block: |
Text { Text {
id: hostname id: hostname
@ -249,5 +276,12 @@
KERNEL=="mmcblk[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" 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" KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users"
- name: Set KiCad 3Dmodel path
ansible.builtin.lineinfile:
path: /etc/environment.d/90lmn-kicad.conf
create: true
mode: '0644'
line: KICAD9_3DMODEL_DIR=/lmn/tools/KiCad/kicad-packages3D
- name: Include sync - name: Include sync
ansible.builtin.include_tasks: sync.yml ansible.builtin.include_tasks: sync.yml

View file

@ -0,0 +1,3 @@
---
encrypt_passphrase_initial: Muster!
encrypt_tpm2: false

View file

@ -0,0 +1,5 @@
- name: Run update-grub
ansible.builtin.command: update-grub
- name: Run update-dracut
ansible.builtin.command: dracut -f

View file

@ -0,0 +1,46 @@
---
- name: Find device with LUKS holder
vars:
partitions: "{{ item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') }}"
ansible.builtin.set_fact:
encrypt_device: "/dev/disk/by-id/{{ partitions[0].value.links.ids[0] }}"
when:
- item.value.partitions is defined
- item.value.partitions | dict2items | length > 0
- item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') | length > 0
loop: "{{ ansible_devices | dict2items }}"
- name: Get luks slots
ansible.builtin.command:
cmd: "systemd-cryptenroll {{ encrypt_device }}"
register: encrypt_slots_result
changed_when: false
when: encrypt_device is defined
- name: Change Password of Luks password slot
ansible.builtin.command:
cmd: >
systemd-run -P --wait
-p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase_initial }}
-p SetCredential=cryptenroll.new-passphrase:{{ encrypt_passphrase }}
systemd-cryptenroll --password {{ encrypt_device }} --wipe-slot=password
no_log: true
when:
- encrypt_device is defined
- encrypt_passphrase is defined
- encrypt_slots_result.stdout_lines | length == 2
- encrypt_slots_result.stdout_lines[1].startswith(' 0')
- name: TPM Device Check
ansible.builtin.stat:
path: /dev/tpm0
register: tpm_device
when: encrypt_device is defined
- name: Include TPM2 role
ansible.builtin.include_tasks:
file: tpm2.yml
when:
- encrypt_device is defined
- encrypt_tpm2
- tpm_device.stat.exists

View file

@ -0,0 +1,42 @@
---
- name: Install tpm2-tools and dracut
ansible.builtin.apt:
name:
- tpm2-tools
- dracut
- name: Enable tpm2-tss crypt module on dracut
ansible.builtin.copy:
dest: /etc/dracut.conf.d/crypt.conf
content: add_dracutmodules+=" tpm2-tss crypt "
mode: '0644'
notify: Run update-dracut
- name: Comment out root device in crypttab
ansible.builtin.lineinfile:
dest: /etc/crypttab
regexp: '^([^#].*)'
line: '#\1'
backrefs: true
- name: Insert luks support to GRUB_CMDLINE_LINUX
ansible.builtin.lineinfile:
dest: /etc/default/grub
regexp: '^(GRUB_CMDLINE_LINUX=).*'
line: '\1"rd.auto rd.luks=1"'
backrefs: true
notify: Run update-grub
- name: Insert TPM2 to Luks slot
ansible.builtin.command:
cmd: >
systemd-run -P --wait
-p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase | default(encrypt_passphrase_initial) }}
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="" {{ encrypt_device }} --wipe-slot=tpm2
no_log: true
when: "'tpm2' not in encrypt_slots_result.stdout"
# - name: Update TPM2 Luks slot
# ansible.builtin.command:
# cmd: systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 --unlock-tpm2-device=auto {{ encrypt_device }} --wipe-slot=tpm2
# when: not grub_config.changed

View file

@ -1,2 +1,3 @@
--- ---
exam_mode: true exam_mode: true
exam_teacherpc_last_digit: 80

View file

@ -5,10 +5,16 @@
if [[ "${PAM_USER}" =~ -exam$ ]]; then if [[ "${PAM_USER}" =~ -exam$ ]]; then
systemctl start firewalld.service systemctl start firewalld.service
if [[ -f /usr/local/sbin/no-way-out-nftable ]]; then
/usr/local/sbin/no-way-out-nftable || true
fi
if systemctl is-enabled --quiet libvirtd.service; then if systemctl is-enabled --quiet libvirtd.service; then
systemctl restart libvirtd.service systemctl restart libvirtd.service
fi fi
elif ! (users | grep -q -- "-exam"); then elif ! (users | grep -q -- "-exam"); then
if /usr/sbin/nft list tables | /usr/bin/grep -q filtermacvtap; then
/usr/sbin/nft delete table netdev filtermacvtap || true
fi
systemctl stop firewalld.service systemctl stop firewalld.service
if systemctl is-enabled --quiet libvirtd.service; then if systemctl is-enabled --quiet libvirtd.service; then
systemctl restart libvirtd.service systemctl restart libvirtd.service

View file

@ -50,6 +50,38 @@
- pam-exec.sh - pam-exec.sh
- rmexam - rmexam
- name: Append teacherPC to exam_destination_allowed_ipv4 addresses
ansible.builtin.set_fact:
exam_destination_allowed_ipv4: "{{ exam_destination_allowed_ipv4 + (exam_teacherpc_ips | default([ ansible_default_ipv4.address.rsplit('.', 1)[0] ~ '.' ~ exam_teacherpc_last_digit ])) }}"
when:
- exam_destination_allowed_ipv4 is defined
- exam_destination_allowed_ipv4 | length > 0
- exam_teacherpc_ips is defined or exam_teacherpc_last_digit | default('') | string | length > 0
- name: Install no-way-out-policy
ansible.builtin.template:
src: no-way-out.xml.j2
dest: "/etc/firewalld/policies/no-way-out-{{ item }}.xml"
mode: '0644'
vars:
zones:
- HOST
- "{{ 'libvirt' if vm_support | default(false) else '' }}"
loop: "{{ zones | reject('match','^$') }}"
when:
- exam_destination_allowed_ipv4 is defined
- exam_destination_allowed_ipv4 | length > 0
- name: Install no-way-out nf-table for macvtap device
ansible.builtin.template:
src: no-way-out-nftable.j2
dest: "/usr/local/sbin/no-way-out-nftable"
mode: '0755'
when:
- exam_destination_allowed_ipv4 is defined
- exam_destination_allowed_ipv4 | length > 0
- vm_support is defined and vm_support
- name: Enable login script via pam_exec.so - name: Enable login script via pam_exec.so
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
dest: /etc/pam.d/common-session dest: /etc/pam.d/common-session

View file

@ -0,0 +1,43 @@
#!/usr/bin/bash
set -eu
interfaces=$(/usr/bin/ip link | /usr/bin/sed -En 's/.*(macvtap-.*)@.*/\1/p')
gateway=$(/usr/bin/ip route list default | /usr/bin/head -1 | /usr/bin/cut -f 3 -d " ")
filterchain=""
for interface in ${interfaces}; do
filterchain=$(cat <<- EOF
${filterchain}
chain filterin_${interface} {
type filter hook ingress device ${interface} priority filter; policy drop;
ip saddr \$allowed_ipv4 accept
ip saddr ${gateway} accept
ip saddr 255.255.255.255 accept
ether type arp accept
}
chain filterout_${interface} {
type filter hook egress device ${interface} priority filter; policy drop;
ip daddr \$allowed_ipv4 accept
ip daddr ${gateway} accept
ip daddr 255.255.255.255 accept
ether type arp accept
}
EOF
)
done
nft_table=$(cat <<- EOF
define allowed_ipv4 = { {{ exam_destination_allowed_ipv4 | join(",") }} }
table netdev filtermacvtap {
${filterchain}
}
EOF
)
echo "$nft_table" | /usr/sbin/nft -f -

View file

@ -0,0 +1,10 @@
<policy target="REJECT">
{% for address in exam_destination_allowed_ipv4 %}
<rule family="ipv4">
<destination address="{{ address }}"/>
<accept/>
</rule>
{% endfor %}
<ingress-zone name="{{ item }}"/>
<egress-zone name="ANY"/>
</policy>

View file

@ -0,0 +1,4 @@
---
- name: Reboot client
ansible.builtin.command:
cmd: "shutdown -r -t 60"

View file

@ -6,6 +6,8 @@
- "{{ extra_pkgs }}" - "{{ extra_pkgs }}"
- "{{ extra_pkgs1 }}" - "{{ extra_pkgs1 }}"
- "{{ extra_pkgs2 }}" - "{{ extra_pkgs2 }}"
tags:
- baseinstall
- name: Add backports for {{ ansible_distribution_release }} - name: Add backports for {{ ansible_distribution_release }}
ansible.builtin.apt_repository: ansible.builtin.apt_repository:
@ -14,7 +16,7 @@
main non-free-firmware main non-free-firmware
state: present state: present
update_cache: true update_cache: true
# when: extra_pkgs_bpo|length when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0
- name: Install extra packages from backports - name: Install extra packages from backports
ansible.builtin.apt: ansible.builtin.apt:
@ -25,6 +27,19 @@
- "{{ extra_pkgs_bpo }}" - "{{ extra_pkgs_bpo }}"
- "{{ extra_pkgs_bpo1 }}" - "{{ extra_pkgs_bpo1 }}"
- "{{ extra_pkgs_bpo2 }}" - "{{ extra_pkgs_bpo2 }}"
when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0
- name: Check if former ansible-stamp exists
ansible.builtin.stat:
path: /var/local/ansible-stamps
register: stamp_exists
- name: Trigger Reboot if no former ansible-run is found
ansible.builtin.debug:
msg: "First Ansible-Run on Client - Reboot handler started"
changed_when: not stamp_exists.stat.exists
notify: "Reboot client"
- name: Timestamp successfull run and send up-to-date report - name: Timestamp successfull run and send up-to-date report
ansible.builtin.shell: ansible.builtin.shell:

View file

@ -3,9 +3,10 @@ kde_desktop_pkg:
- akonadi-backend-sqlite - akonadi-backend-sqlite
- arduino - arduino
- bluefish - bluefish
- calligra # - calligra
- codeblocks - codeblocks
- dia - dia
- filius
- flameshot - flameshot
- freecad - freecad
- fritzing - fritzing
@ -14,8 +15,9 @@ kde_desktop_pkg:
- inkscape - inkscape
- kde-full - kde-full
- keepassxc - keepassxc
- kicad
- kicad-doc-de
- librecad - librecad
- mu-editor
- openboard - openboard
- qtcreator - qtcreator
- spyder - spyder
@ -34,3 +36,5 @@ kde_desktop_pkg:
- xdg-desktop-portal-kde - xdg-desktop-portal-kde
- xdg-desktop-portal-wlr # share screen in browser - xdg-desktop-portal-wlr # share screen in browser
- xournalpp - xournalpp
kde_desktop_pkg_bpo: [ ]

View file

@ -8,19 +8,14 @@
repo: deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main non-free-firmware repo: deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main non-free-firmware
state: present state: present
update_cache: true update_cache: true
when: kde_desktop_pkg_bpo | length > 0
- name: Install extra packages from backports - name: Install extra packages from backports
ansible.builtin.apt: ansible.builtin.apt:
name: name: "{{ kde_desktop_pkg_bpo }}"
- filius
- kicad
- kicad-doc-de
- libreoffice
- libreoffice-l10n-de
- libreoffice-qt5
state: latest # noqa package-latest
autoremove: true autoremove: true
default_release: "{{ ansible_distribution_release }}-backports" default_release: "{{ ansible_distribution_release }}-backports"
when: kde_desktop_pkg_bpo | length > 0
- name: Create akonadi config dir - name: Create akonadi config dir

View file

@ -9,7 +9,7 @@
ansible.builtin.blockinfile: ansible.builtin.blockinfile:
path: /usr/share/sddm/themes/debian-breeze/Main.qml path: /usr/share/sddm/themes/debian-breeze/Main.qml
marker: // {mark} ANSIBLE MANAGED BLOCK localhome marker: // {mark} ANSIBLE MANAGED BLOCK localhome
insertbefore: '\s+//Footer' insertbefore: '^}$'
block: | block: |
Text { Text {
id: localhome id: localhome
@ -33,7 +33,6 @@
dest: /etc/profile.d/lmn-logout.sh dest: /etc/profile.d/lmn-logout.sh
mode: '0755' mode: '0755'
content: | content: |
[[ "${UID}" -gt 10000 ]] && ! findmnt "/lmn/media/${USER}/home" > /dev/null && exit 0
{% if localhome_logout_missing_serverhome %} {% if localhome_logout_missing_serverhome %}
[[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0 [[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0
{% endif %} {% endif %}

View file

@ -5,11 +5,11 @@
set -eu set -eu
cur="$(efibootmgr | grep -Ei 'BootOrder:' | \ cur="$(efibootmgr | grep -Ei 'BootOrder:' | \
sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')" sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')"
pxeip4="$(efibootmgr | grep -Ei "IP.*4" | \ pxeip4="$(efibootmgr | grep -Ei "IP.{0,5}4" | \
sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)"
debian="$(efibootmgr | grep -Ei "debian" | \ debian="$(efibootmgr | grep -Ei "debian" | \
sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)"
if [[ "$cur" != "$pxeip4" ]] && [[ -n "$pxeip4" ]] && [[ -n "$debian" ]] ; then if [[ "$cur" != "$pxeip4" ]] && [[ -n "$pxeip4" ]] && [[ -n "$debian" ]] ; then
efibootmgr -o $pxeip4,$debian efibootmgr -o $pxeip4,$debian

View file

@ -98,7 +98,7 @@
export superusers export superusers
password_pbkdf2 root {{ grub_pwd }} password_pbkdf2 root {{ grub_pwd }}
notify: Run update-grub notify: Run update-grub
when: grub_pwd|default(false) when: grub_pwd | bool | default(false)
- name: Allow booting grub menu entries - name: Allow booting grub menu entries
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@ -167,6 +167,8 @@
src: reporter.j2 src: reporter.j2
dest: /usr/local/sbin/reporter dest: /usr/local/sbin/reporter
mode: '0755' mode: '0755'
tags:
- baseinstall
- name: Provide services and timers for reporter - name: Provide services and timers for reporter
ansible.builtin.copy: ansible.builtin.copy:
@ -177,12 +179,16 @@
- reporter.service - reporter.service
- reporter.timer - reporter.timer
when: misc_reporter when: misc_reporter
tags:
- baseinstall
- name: Enable reporter.timer - name: Enable reporter.timer
ansible.builtin.systemd: ansible.builtin.systemd:
name: reporter.timer name: reporter.timer
enabled: true enabled: true
when: misc_reporter when: misc_reporter
tags:
- baseinstall
# Prepare CloneScreen on Presenter PCs # Prepare CloneScreen on Presenter PCs

View file

@ -5,14 +5,14 @@
mode: '0644' mode: '0644'
content: > content: >
{{ apt_conf }} {{ apt_conf }}
when: apt_conf|default(false) when: apt_conf | bool | default(false)
- name: Set NTP server - name: Set NTP server
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/systemd/timesyncd.conf path: /etc/systemd/timesyncd.conf
insertafter: '^#NTP=' insertafter: '^#NTP='
line: NTP={{ ntp_serv }} line: NTP={{ ntp_serv }}
when: ntp_serv|default(false) when: ntp_serv | bool | default(false)
- name: Add proposed-updates repository - name: Add proposed-updates repository
ansible.builtin.apt_repository: ansible.builtin.apt_repository:

View file

@ -37,7 +37,7 @@
line: "SystemGroup root lpadmin {{ printer_admin_group }}" line: "SystemGroup root lpadmin {{ printer_admin_group }}"
regexp: '^SystemGroup' regexp: '^SystemGroup'
state: present state: present
when: printer_admin_group | length when: printer_admin_group | length > 0
- name: Disable cups-browsed - name: Disable cups-browsed
ansible.builtin.systemd: ansible.builtin.systemd:

View file

@ -5,6 +5,8 @@
key: "{{ item }}" key: "{{ item }}"
loop: "{{ keys2deploy }}" loop: "{{ keys2deploy }}"
when: keys2deploy is defined when: keys2deploy is defined
tags:
- baseinstall
- name: Allow sudo without password for ansible - name: Allow sudo without password for ansible
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@ -14,12 +16,16 @@
owner: root owner: root
group: root group: root
mode: '0700' mode: '0700'
tags:
- baseinstall
- name: Disable ansible user login - name: Disable ansible user login
ansible.builtin.user: ansible.builtin.user:
name: ansible name: ansible
password_lock: true password_lock: true
when: security_defaultuser_login_disable when: security_defaultuser_login_disable
tags:
- baseinstall
- name: Limit SSH access to user ansible - name: Limit SSH access to user ansible
ansible.builtin.blockinfile: ansible.builtin.blockinfile:

View file

@ -0,0 +1,2 @@
---
sssd_domjoin_user: global-admin

View file

@ -1,6 +1,5 @@
- name: Restart sssd - name: Restart sssd
ansible.builtin.service: ansible.builtin.systemd:
name: sssd name: sssd
state: restarted state: restarted
enabled: true enabled: true
listen: "Restart sssd"

View file

@ -10,15 +10,27 @@
ansible.builtin.template: ansible.builtin.template:
src: sssd.conf.j2 src: sssd.conf.j2
dest: /etc/sssd/sssd.conf dest: /etc/sssd/sssd.conf
mode: '0600' mode: '0640'
notify: Restart sssd notify: Restart sssd
## Either one of the variables is defined: - name: Check if the machine account password and the join are still valid
ansible.builtin.shell:
cmd: adcli testjoin -D {{ domain | upper }}
register: adcli_test_result
failed_when: false
changed_when: false
# If domjoin not valid:
- name: Join the domain - name: Join the domain
ansible.builtin.shell: ansible.builtin.shell:
cmd: > cmd: >
echo "{{ ansible_cmdline.adpw | default('') + adpw.user_input | default('') }}" | echo "{{ ad_passwd }}" | adcli join --stdin-password -U {{ ad_user }} {{ domain | upper }}
adcli join --stdin-password -U global-admin {{ domain | upper }} no_log: true
when: > vars:
ansible_cmdline.adpw | default('') | length > 0 or ad_user: "{{ 'global-admin' if (adpw.user_input | default(ansible_cmdline.adpw) | default('') | length > 0) else sssd_domjoin_user }}"
adpw.user_input | default('') | length > 0 ad_passwd: "{{ adpw.user_input | default('') if adpw.user_input | default ('') | length > 0 else ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') }}"
throttle: 1
when:
- adpw.user_input | default('') | length > 0 or
ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') | length > 0
- adcli_test_result.rc != 0

View file

@ -9,7 +9,9 @@ ad_domain = {{ domain }}
id_provider = ad id_provider = ad
access_provider = ad access_provider = ad
use_fully_qualified_names = False use_fully_qualified_names = False
{% if localhome is defined and localhome %}
cache_credentials = True cache_credentials = True
{% endif %}
krb5_store_password_if_offline = True krb5_store_password_if_offline = True
default_shell = /usr/bin/bash default_shell = /usr/bin/bash
# default: # ldap_id_mapping = True # default: # ldap_id_mapping = True
@ -17,6 +19,7 @@ ad_gpo_access_control = disabled
ad_gpo_ignore_unreadable = True ad_gpo_ignore_unreadable = True
ad_maximum_machine_account_password_age = 0 ad_maximum_machine_account_password_age = 0
ignore_group_members = True ignore_group_members = True
krb5_renew_interval = 1h
{% if localhome is defined and localhome %} {% if localhome is defined and localhome %}
override_homedir = /home/%u override_homedir = /home/%u
{% endif %} {% endif %}

View file

@ -8,3 +8,27 @@
- bookworm.yml - bookworm.yml
- cleanup.yml - cleanup.yml
when: ansible_distribution_release == "bookworm" when: ansible_distribution_release == "bookworm"
- name: Set chromium gl-flags fixing AMD graphic issues
ansible.builtin.copy:
dest: /etc/chromium.d/fvs
content: |
export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --use-gl=desktop"
when: ansible_board_vendor == "LENOVO" and
(ansible_board_name == "312D" or ansible_board_name == "312A")
- name: Fix 8086:4909 external graphics card
ansible.builtin.replace:
dest: "/etc/default/grub"
regexp: 'GRUB_CMDLINE_LINUX=""$'
replace: 'GRUB_CMDLINE_LINUX="i915.force_probe=4909"'
notify: Run update-grub
when: ansible_board_vendor == "LENOVO" and ansible_board_name == "32CB"
- name: Remove calligra
ansible.builtin.apt:
name:
- calligra
state: absent
purge: true
autoremove: true

View file

@ -3,6 +3,11 @@
%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync %role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync
%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync %examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync
# vm-delete: Delete VM-Images
%role-teacher ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete
# vm-aria2: Start/Stop aria2 as systemd-service for VM-Images # vm-aria2: Start/Stop aria2 as systemd-service for VM-Images
lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2 lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2

45
roles/lmn_vm/files/vm-delete Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
set -eu
directory="/lmn/vm"
if [ ! -d "$directory" ]; then
echo "No VM directory found."
exit 1
fi
qcow2_files=("$directory"/*.qcow2)
if [ "${#qcow2_files[@]}" -eq 0 ]; then
echo "Keine QCOW2-Dateien gefunden."
exit 0
fi
echo "Gefundene QCOW2-Dateien:"
echo "-------------------------------------------------------------"
printf "%-50s %10s\n" "Datei" "Größe (MB)"
echo "-------------------------------------------------------------"
for file in "${qcow2_files[@]}"; do
size=$(du -m "$file" | cut -f1) # Größe in MB
printf "%-50s %10d\n" "$file" "$size"
done
echo "-------------------------------------------------------------"
for file in "${qcow2_files[@]}"; do
read -rp "Möchtest du die Datei $file löschen? (j/n) " confirmation
if [[ "$confirmation" == "j" || "$confirmation" == "J" ]]; then
link_count=$(stat -c %h "$file")
rm "$file"
echo "$file wurde gelöscht."
if [ "$link_count" -gt 1 ]; then
echo "Achtung: $file hat noch $((link_count - 1)) weitere Hardlinks."
echo "Diese liegen evtl. unter:"
echo "- /var/tmp/${UID}/vm/ (temporäre VMs, werden automatisch beim Neustart gelöscht)"
echo "- /var/vm/${UID}/ (persistente VMs)"
fi
echo
fi
done

View file

@ -19,8 +19,9 @@ done
shift "$((OPTIND -1))" shift "$((OPTIND -1))"
# link system-VM-Images to User VM Directory # link system-VM-Images to User VM Directory
for i in *.qcow2; do for filename in "$@"; do
[[ -f "${VM_DIR}/${i}" ]] || ln "${i}" "${VM_DIR}/${i}" filename="$(basename ${filename})"
[[ -f "${VM_DIR}/${filename}" ]] || ln "${filename}" "${VM_DIR}/${filename}"
done done
# allow lmnsynci to remove old vm images # allow lmnsynci to remove old vm images

View file

@ -7,10 +7,10 @@ set -eu
## Imporant for all virsh libvirt calls: ## Imporant for all virsh libvirt calls:
export XDG_CONFIG_HOME="/var/tmp/vm/${UID}" export XDG_CONFIG_HOME="/var/tmp/vm/${UID}"
menu=(standard "CLI Standard Debian GNU/Linux NFS" menu=(standard-edu "CLI Standard Debian GNU/Linux NFS"
standard-ram "CLI Standard Debian GNU/Linux RAM" standard-edu-ram "CLI Standard Debian GNU/Linux RAM"
kde-desktop "KDE Plasma Desktop Debian GNU/Linux NFS" kde-edu "KDE Plasma Desktop Debian GNU/Linux NFS"
gnome-desktop "Gnome Desktop Debian GNU/Linux NFS") gnome-edu "Gnome Desktop Debian GNU/Linux NFS")
img=$(dialog --clear --backtitle "Virtual Machine Chooser" \ img=$(dialog --clear --backtitle "Virtual Machine Chooser" \
--title "Choose the Virtual Machine to Start" \ --title "Choose the Virtual Machine to Start" \
--menu "Start VM:" 12 70 6 "${menu[@]}" 2>&1 >/dev/tty) --menu "Start VM:" 12 70 6 "${menu[@]}" 2>&1 >/dev/tty)
@ -22,6 +22,8 @@ mac="$(ip link | grep -A1 -m1 "macvtap-" | \
sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")" 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")" tapdev="$(ip link | grep -A1 -m1 "macvtap-" | sed -nE "s%^[1-9]:\s(\S+)@.*%\1%p")"
livebox=$(host livebox | sed -E "s/.+ ([0-9.]+)$/\1/")
if [[ $# -eq 0 ]] ; then if [[ $# -eq 0 ]] ; then
mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo) mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo)
cpu=$(sed -En "0,/^cpu cores/s/^cpu cores\s+:\s+([0-9]+)/\1/p" /proc/cpuinfo) cpu=$(sed -En "0,/^cpu cores/s/^cpu cores\s+:\s+([0-9]+)/\1/p" /proc/cpuinfo)
@ -31,8 +33,8 @@ else
arg=("$@") arg=("$@")
fi fi
kernel="http://livebox/d-i/n-live/${img%-ram}/live/vmlinuz" kernel="http://${livebox}/d-i/n-live/${img%-ram}/live/vmlinuz"
initrd="http://livebox/d-i/n-live/${img%-ram}/live/initrd.img" initrd="http://${livebox}/d-i/n-live/${img%-ram}/live/initrd.img"
kargs=(boot=live components splash locales=de_DE.UTF-8 keyboard-layouts=de kargs=(boot=live components splash locales=de_DE.UTF-8 keyboard-layouts=de
swap=true live-config.timezone=Europe/Berlin) swap=true live-config.timezone=Europe/Berlin)
@ -42,10 +44,10 @@ case "$img" in
kargs+=(console=ttyS0) kargs+=(console=ttyS0)
;;& ;;&
*-ram) *-ram)
kargs+=("fetch=http://10.190.1.2/d-i/n-live/${img%-ram}/live/filesystem.squashfs") kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs rd.live.ram=1")
;; ;;
*) *)
kargs+=(netboot=nfs "nfsroot=10.190.1.2:/srv/nfs/debian-live/${img%-ram}") kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs")
;; ;;
esac esac

View file

@ -90,17 +90,21 @@ create_clone() {
local VM_NAME="$1" local VM_NAME="$1"
if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" || -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" || -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then
echo "qcow2 File does not exists." >&2 echo "qcow2 File does not exists." >&2
exit 1 exit 1
fi fi
# Create User-VM-Dir and link system VM-Images # Create User-VM-Dir and link system VM-Images
[[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}" [[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}"
if [[ "${PERSISTENT}" -eq 1 ]]; then IMAGE="${VM_NAME}.qcow2"
sudo /usr/local/bin/vm-link-images -p while [[ -n ${IMAGE} ]]; do
else if [[ "${PERSISTENT}" -eq 1 ]]; then
sudo /usr/local/bin/vm-link-images sudo /usr/local/bin/vm-link-images -p "${IMAGE}"
fi else
sudo /usr/local/bin/vm-link-images "${IMAGE}"
fi
IMAGE="$(qemu-img info -U "${VM_DIR}/${IMAGE}" | grep "^backing file:" | cut -d ' ' -f 3)"
done
# Create backing file # Create backing file
cd "${VM_DIR}" cd "${VM_DIR}"
@ -130,18 +134,30 @@ create_printerlist() {
} }
create_mountlist() { create_mountlist() {
if id | grep -q teachers; then NETHOMEPART="${NETHOME#/srv/samba/schools}"
NETHOME=/srv/samba/schools/default-school/teachers/$USER cat << EOF > "${VMINFO_DIR}/.mounts.csv"
else
NETHOME=(/srv/samba/schools/default-school/students/*/"$USER")
fi
NETHOME="${NETHOME#/srv/samba/schools}"
cat << EOF > "/lmn/media/${USER}/.mounts.csv"
Drive;Remotepath Drive;Remotepath
H;\\\\10.190.1.1${NETHOME//\//\\} H;\\\\server.pn.steinbeis.schule${NETHOMEPART//\//\\}
T;\\\\10.190.1.1\default-school\share T;\\\\server.pn.steinbeis.schule\\default-school\\share
EOF EOF
echo "${USER}" > "/lmn/media/${USER}/.user" echo "${USER}" > "/${VMINFO_DIR}/.user"
}
start_virtiofs_service() {
local target_name=$1
local shared_dir=$2
local drive_letter=$3
local socket="/run/user/${UID}/virtiofs-${VM_NAME}-${target_name,,}.sock"
systemd-run --user /usr/local/bin/virtiofsd --uid-map=":${GUEST_UID}:${UID}:1:" --gid-map=":${GUEST_GID}:$(id -g):1:" \
--socket-path "${socket}" --shared-dir "${shared_dir}" --syslog
if [[ $? -ne 0 ]]; then
echo "Error starting virtiofsd for ${target_name}." >&2
return 1
fi
LIBVIRTOPTS="${LIBVIRTOPTS} --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=${target_name},xpath1.set=./source/@socket=${socket}"
} }
start_virtiofsd() { start_virtiofsd() {
@ -151,9 +167,17 @@ start_virtiofsd() {
[[ "$GUEST_GID" == 0 ]] && GUEST_GID=1010 [[ "$GUEST_GID" == 0 ]] && GUEST_GID=1010
fi fi
# END temporary fix # 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: \ # start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y"
--socket-path "$socket" --shared-dir "/lmn/media/${USER}" --syslog # start_virtiofs_service "default-school" "/srv/samba/schools/default-school" "Y"
# Home@PC / VM-Data
# if the environment variable VMLEGACY is set, /lmn/media/USER is forced
if [[ "${HOME}" != "${NETHOME}" && ! -v VMLEGACY ]]; then
start_virtiofs_service "Home_Linux" "${HOME}" "Y"
else
start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y"
fi
} }
ask_really_persistent() { ask_really_persistent() {
@ -216,7 +240,7 @@ while true; do
shift shift
;; ;;
-o | --options ) -o | --options )
LIBVIRTOPTS=$2 LIBVIRTOPTS="${LIBVIRTOPTS} $2"
shift 2 shift 2
;; ;;
--no-viewer ) --no-viewer )
@ -267,6 +291,7 @@ while true; do
type="ethernet,mac=${mac},target.dev=${interface},xpath1.set=./target/@managed=no,model.type=virtio" type="ethernet,mac=${mac},target.dev=${interface},xpath1.set=./target/@managed=no,model.type=virtio"
LIBVIRTOPTS="${LIBVIRTOPTS} --network type=$type" LIBVIRTOPTS="${LIBVIRTOPTS} --network type=$type"
done done
LIBVIRTOPTS="${LIBVIRTOPTS} --check mac_in_use=off"
shift shift
;; ;;
--os ) --os )
@ -315,18 +340,38 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
check_images check_images
fi fi
if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then
create_clone "${VM_NAME}" create_clone "${VM_NAME}"
fi fi
# delete the old vm # delete the old vm
virsh --connect=qemu:///session undefine --nvram "${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 #trap exit_script SIGHUP SIGINT SIGTERM
for dir in teachers examusers staff parents; do
if [[ -d "/srv/samba/schools/default-school/${dir}/${USER}" ]]; then
NETHOME="/srv/samba/schools/default-school/${dir}/${USER}"
break
fi
done
if [[ -z "${NETHOME+x}" ]]; then
NETHOME=(/srv/samba/schools/default-school/students/*/"$USER")
fi
if [[ "${HOME}" != "${NETHOME}" ]]; then
VMINFO_DIR="${HOME}"
else
VMINFO_DIR="/lmn/media/${USER}"
fi
create_printerlist create_printerlist
create_mountlist create_mountlist
# start virtiofsd-service # start virtiofsd-service
[[ "${QEMU}" = 'qemu:///session' ]] && start_virtiofsd [[ "${QEMU}" = 'qemu:///session' ]] && start_virtiofsd
# Create VMInfo Json file
#( umask 027; ./vm-create-vminfo > "${VMINFO_DIR}/.vminfo.json" )
# Start vminfo.timer
systemctl --user restart vminfo.timer
uuid=$(openssl rand -hex 16) uuid=$(openssl rand -hex 16)
uuid="${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}" uuid="${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
@ -348,7 +393,6 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
--memorybacking source.type=memfd,access.mode=shared \ --memorybacking source.type=memfd,access.mode=shared \
--disk "${VM_DIR}/${VM_NAME}-clone.qcow2",driver.discard=unmap,target.bus=scsi,cache=writeback \ --disk "${VM_DIR}/${VM_NAME}-clone.qcow2",driver.discard=unmap,target.bus=scsi,cache=writeback \
--network=bridge=virbr0,model.type=virtio \ --network=bridge=virbr0,model.type=virtio \
--filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=virtiofs,xpath1.set=./source/@socket="/run/user/${UID}/virtiofs-${VM_NAME}.sock" \
--controller type=scsi,model=virtio-scsi \ --controller type=scsi,model=virtio-scsi \
--check path_in_use=off \ --check path_in_use=off \
--connect="${QEMU}" \ --connect="${QEMU}" \

117
roles/lmn_vm/files/vm-vminfo Executable file
View file

@ -0,0 +1,117 @@
#!/usr/bin/python3
import argparse
import struct
import subprocess
import json
import sys
from os import environ,path
from impacket.krb5.ccache import CCache
from base64 import b64encode
home = ""
nethome = ""
vminfo = {}
def get_printers():
printers = []
try:
result = subprocess.run(['lpstat', '-v'], capture_output=True, text=True, check=True)
for line in result.stdout.splitlines():
# Extrahiere den Druckernamen
printer_name = line.split()[2].rstrip(':')
ipp_url = f"ipp://192.168.122.1/printers/{printer_name}"
printer = { 'Name': printer_name, 'IppURL': ipp_url }
printers.append(printer)
return printers
except subprocess.CalledProcessError as e:
sys.stderr.write(f"Fehler beim Abrufen der Drucker: {e}")
return []
def get_groups(username):
try:
result = subprocess.run(['id', '-Gnz', username], capture_output=True, text=True, check=True)
groups = result.stdout.strip().split('\0')
return groups
except subprocess.CalledProcessError as e:
sys.stderr.write(f"Fehler beim Abrufen der Gruppen: {e}")
return []
def get_krb5 ():
krb5 = {}
ccachefilename = environ.get('KRB5CCNAME').replace('FILE:', '')
if ccachefilename:
try:
ccache = CCache.loadFile(ccachefilename)
cred = ccache.toKRBCRED()
cred_enc = b64encode(cred)
krb5['cred'] = cred_enc.decode('utf-8')
krb5['starttime'] = ccache.credentials[0]['time']['starttime']
krb5['endtime'] = ccache.credentials[0]['time']['endtime']
krb5['renew_till'] = ccache.credentials[0]['time']['renew_till']
except:
sys.stderr.write("Fehler beim Ticket laden")
return krb5
def get_mounts():
mounts = []
mounts.append({ 'Drive': 'H', 'RemotePath': '\\\\server.pn.steinbeis.schule' + nethome.replace('/srv/samba/schools','').replace('/','\\'), 'Name': 'Home_Server' })
mounts.append({ 'Drive': 'T', 'RemotePath': '\\\\server.pn.steinbeis.schule\default-school\share', 'Name': 'Tausch' })
return mounts
def get_user_folders():
HOME="H:"
if environ.get('HOME') != nethome:
HOME="Y:"
folders = []
folders.append( {'Name': 'Personal', 'Path': f"{HOME}\Dokumente"} )
folders.append( {'Name': 'My Pictures', 'Path': f"{HOME}\Bilder"} )
folders.append( {'Name': 'My Music', 'Path': f"{HOME}\Musik"} )
folders.append( {'Name': 'My Video', 'Path': f"{HOME}\Videos"} )
return folders
def get_quickaccess():
quickaccess = []
quickaccess.append( 'H:\\transfer' )
return quickaccess
def parse_args():
parser = argparse.ArgumentParser()
#parser.add_argument('input_file', help="File in kirbi (KRB-CRED) or ccache format")
#parser.add_argument('output_file', help="Output file")
return parser.parse_args()
def main():
global home, nethome
args = parse_args()
home = environ.get('HOME')
vminfo['User'] = environ.get('USER')
vminfo['Groups'] = get_groups(environ.get('USER'))
for dir in ['teachers','examusers','staff','parents']:
potential_path = f"/srv/samba/schools/default-school/{dir}/{vminfo['User']}"
if path.isdir(potential_path):
nethome = potential_path
break
if not nethome:
result = subprocess.run(['find', '/srv/samba/schools/default-school/students/', '-name', vminfo['User'], '-maxdepth', '2', '-type', 'd'], capture_output=True, text=True, check=False)
nethome = result.stdout.splitlines()[0]
vminfo['Printers'] = get_printers()
vminfo['krb5'] = get_krb5()
vminfo['Mounts'] = get_mounts()
vminfo['UserShellFolders'] = get_user_folders()
vminfo['QuickAccess'] = get_quickaccess()
vminfo_json = json.dumps(vminfo, ensure_ascii=False, indent=4)
print(vminfo_json)
if __name__ == '__main__':
main()

View file

@ -18,7 +18,9 @@
- mktorrent - mktorrent
- libvirt-daemon-system - libvirt-daemon-system
- virt-manager - virt-manager
- virt-viewer
- dialog # for vm-netboot menu - dialog # for vm-netboot menu
- python3-impacket
# - name: allow all users to use VMs # - name: allow all users to use VMs
# lineinfile: # lineinfile:
@ -27,32 +29,6 @@
# insertafter: '#auth_unix_rw = "polkit"' # insertafter: '#auth_unix_rw = "polkit"'
# notify: reload libvirtd # notify: reload libvirtd
- name: Configure pam_mount for VM bind mounts
ansible.builtin.blockinfile:
dest: /etc/security/pam_mount.conf.xml
marker: "<!-- {mark} ANSIBLE MANAGED BLOCK (bind mounts for VMs) -->"
block: |
<!-- bind mounts for the VMs, setting gid here does not work -->
<volume
path="~"
mountpoint="/lmn/media/%(USER)/home"
options="bind"
><not><or><user>root</user><user>ansible</user><user>Debian-gdm</user><user>sddm</user>{% if localuser %}<user>{{ localuser }}</user>{% endif %}</or></not>
</volume>
<volume
path="/srv/samba/schools/default-school/share"
mountpoint="/lmn/media/%(USER)/share"
options="bind"
><not><or><user>root</user><user>ansible</user><user>Debian-gdm</user><user>sddm</user>{% if localuser %}<user>{{ localuser }}</user>{% endif %}</or></not>
</volume>
<volume
path="/srv/samba/schools/default-school"
mountpoint="/lmn/media/%(USER)/school"
options="bind"
><not><or><user>root</user><user>ansible</user><user>Debian-gdm</user><user>sddm</user>{% if localuser %}<user>{{ localuser }}</user>{% endif %}</or></not>
</volume>
insertafter: "<!-- END ANSIBLE MANAGED BLOCK .* -->"
- name: Use umount script for proper cleanup - name: Use umount script for proper cleanup
ansible.builtin.blockinfile: ansible.builtin.blockinfile:
dest: /etc/security/pam_mount.conf.xml dest: /etc/security/pam_mount.conf.xml
@ -142,6 +118,7 @@
group: root group: root
mode: '0755' mode: '0755'
loop: loop:
- vm-delete
- vm-create - vm-create
- vm-rebase - vm-rebase
- vm-run - vm-run
@ -149,6 +126,7 @@
- vm-sync - vm-sync
- vm-link-images - vm-link-images
- vm-virtiofsd - vm-virtiofsd
- vm-vminfo
- virtiofsd - virtiofsd
- vm-aria2 - vm-aria2
- uploadseed - uploadseed
@ -236,3 +214,26 @@
src: vm-netboot src: vm-netboot
dest: /usr/local/bin/ dest: /usr/local/bin/
mode: '0755' mode: '0755'
- name: Provide vminfo service
ansible.builtin.copy:
content: |
[Unit]
Description=Create .vminfo.json for VMs
[Service]
Type=simple
ExecStart=/usr/bin/bash -c 'umask 027; /usr/local/bin/vm-vminfo > "{% if localhome %}/home{% else %}/lmn/media{% endif %}/${USER}/.vminfo.json"'
dest: /etc/systemd/user/vminfo.service
mode: '0644'
- name: Provide vminfo timer
ansible.builtin.copy:
content: |
[Unit]
Description=Timer for vm-info
[Timer]
OnActiveSec=0s
OnUnitActiveSec=1h
Persistent=true
dest: /etc/systemd/user/vminfo.timer
mode: '0644'

View file

@ -13,30 +13,32 @@ if [[ "$CONNECTION_ID" = "VPN-Schule" ]]; then
# Exit if server is already mounted # Exit if server is already mounted
findmnt /srv/samba/schools/default-school > /dev/null && exit 0 findmnt /srv/samba/schools/default-school > /dev/null && exit 0
if ! klist -s -c "${KRB5CCNAME}"; then counter=1
#echo "try to renew KRB5-Ticket" >&2 while ! klist -s -c "${KRB5CCNAME}"; do
#sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}" (( counter > 30 )) && exit 0
echo "KRB5-Ticket is expired. Sleep 3 seconds and hope it will be renewed after." >&2 echo "KRB5-Ticket is expired. Sleep 1 seconds and hope it will be renewed after." >&2
sleep 3 # if (( counter == 10 )); then
fi # echo "try to renew KRB5-Ticket" >&2
# sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}"
# fi
sleep 1
((counter++))
done
echo "prepare mountpoints" >&2 echo "prepare mountpoints" >&2
umask 0002 umask 0002
mkdir -p /srv/samba/schools/default-school mkdir -p /srv/samba/schools/default-school
chmod 777 /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 \ 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" -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 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 SUDO_USER=$USERNAME /usr/local/bin/install-printers.sh
elif [[ "$NM_DISPATCHER_ACTION" = "pre-down" ]]; then elif [[ "$NM_DISPATCHER_ACTION" = "pre-down" ]]; then
# FIXME: Only umount server when Wireguard-Connection was the only connection to server. # FIXME: Only umount server when Wireguard-Connection was the only connection to server.
# Dirty fix (works only in fvs-IP-Range) # Dirty fix (works only in fvs-IP-Range)
if ! (ip r s | grep "10.190." | grep -v wg0); then if ! (ip r s | grep "10.190." | grep -v wg0); then
echo "Try to umount server shares" echo "Try to umount server"
umount "/lmn/media/${USERNAME}/share"
umount /srv/samba/schools/default-school umount /srv/samba/schools/default-school
fi fi
fi fi

View file

@ -3,7 +3,6 @@ set -eu
exit_script() { exit_script() {
echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log" 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" findmnt "/srv/samba/schools/default-school" && umount "/srv/samba/schools/default-school"
trap - SIGHUP SIGINT SIGTERM # clear the trap trap - SIGHUP SIGINT SIGTERM # clear the trap
kill -- -$$ # Sends SIGTERM to child/sub processes kill -- -$$ # Sends SIGTERM to child/sub processes
@ -14,11 +13,9 @@ findmnt /srv/samba/schools/default-school > /dev/null && exit 0
umask 0002 umask 0002
mkdir -p /srv/samba/schools/default-school mkdir -p /srv/samba/schools/default-school
chmod 777 /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 \ 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" -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 "Einbindung erfolgreich!"
echo "Dieses Fenster bitte nicht schließen!" echo "Dieses Fenster bitte nicht schließen!"

View file

@ -5,7 +5,7 @@
- wireguard - wireguard
- name: Check if wg_server is reachable - name: Check if wg_server is reachable
ansible.builtin.command: echo "Test if wg_server is reachable" ansible.builtin.command: echo "reachable"
delegate_to: wireguard_server delegate_to: wireguard_server
register: result register: result
changed_when: false changed_when: false
@ -17,10 +17,12 @@
* server not reachable * server not reachable
* no matching ssh-key * no matching ssh-key
changed_when: true changed_when: true
when: result.unreachable is defined and result.unreachable when: result.stdout is not defined or result.stdout!="reachable"
- name: Configure WG Server - name: Configure WG Server
when: result.unreachable is not defined or not result.unreachable when:
- result.stdout is defined and result.stdout=="reachable"
- not run_in_installer|default(false)|bool
block: block:
- name: Set facts wg_clientname - name: Set facts wg_clientname
ansible.builtin.set_fact: ansible.builtin.set_fact:

View file

@ -27,7 +27,7 @@
when: cert_client_active.stat.exists when: cert_client_active.stat.exists
- name: Check if radius-server is reachable - name: Check if radius-server is reachable
ansible.builtin.command: echo "Test if radius-server is reachable" ansible.builtin.command: echo "reachable"
delegate_to: radius_server delegate_to: radius_server
register: radius_reachable register: radius_reachable
changed_when: false changed_when: false
@ -40,12 +40,13 @@
- "* server not reachable" - "* server not reachable"
- "* no matching ssh-key" - "* no matching ssh-key"
changed_when: true changed_when: true
when: radius_reachable.unreachable is defined and radius_reachable.unreachable when: radius_reachable.stdout is not defined or radius_reachable.stdout!='reachable'
- name: Issue radius certificate - name: Issue radius certificate
ansible.builtin.include_tasks: eap-tls_issue-certificate.yaml ansible.builtin.include_tasks: eap-tls_issue-certificate.yaml
when: when:
- radius_reachable.unreachable is not defined or not radius_reachable.unreachable - radius_reachable.stdout is defined and radius_reachable.stdout=="reachable"
- not run_in_installer|default(false)|bool
- | - |
( not cert_client_active.stat.exists ) or ( 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 (cert_serial.stdout | replace('serial=','') | int(base=16) ) in ( radius_crl.revoked_certificates | map(attribute='serial_number') | list ) or

View file

@ -105,6 +105,7 @@
ansible.builtin.systemd: ansible.builtin.systemd:
name: iwd.service name: iwd.service
enabled: false enabled: false
failed_when: false
- name: Remove deprecated NetworkManager config - name: Remove deprecated NetworkManager config
ansible.builtin.blockinfile: ansible.builtin.blockinfile:

View file

@ -3,7 +3,6 @@
- name: Install packages related to wifi - name: Install packages related to wifi
ansible.builtin.apt: ansible.builtin.apt:
name: name:
- systemd-resolved
- firmware-realtek # for our wifi sticks - firmware-realtek # for our wifi sticks
- name: Provide service to enable WiFi on boot - name: Provide service to enable WiFi on boot