diff --git a/doc/install_ontop.md b/doc/install_ontop.md index e44633c..cbf9090 100644 --- a/doc/install_ontop.md +++ b/doc/install_ontop.md @@ -1,6 +1,12 @@ # 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 @@ -9,10 +15,10 @@ With two simple commands you can install the lmn-client with default configurati Steps: * Install debian on client (via USB or PXE) -* Install additional packages: ansible +* Install additional packages: ansible `sudo apt install ansible` -* Run Playbook - `ansible-pull -i inventory.yml -l localhost, --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml` +* Run Playbook + `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 @@ -24,10 +30,12 @@ Steps: * Install debian on client (via USB or PXE) * Install additional packages: ansible, git `sudo apt install ansible git` -* Checkout Repository +* Checkout Repository `git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git` +* Change into repository directory + `cd lmn-client` * Create inventory - `cp inventory.yml inventory-myschool.yml` + `cp inventory-sample.yml inventory-myschool.yml` * Edit inventory-myschool.yml e.g.: `nano inventory-myschool.yml` * Run Playbook diff --git a/doc/install_pxe.md b/doc/install_pxe.md index bfe7a8d..de90ab6 100644 --- a/doc/install_pxe.md +++ b/doc/install_pxe.md @@ -2,15 +2,28 @@ * **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp** Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository. - Linux kernel and initial Ramdisk from debian repository. + 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** 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** - 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 +### 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 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' { echo -n "Enter domain join password: " 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 \ - url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/fvs/misc/preseed.cfg interface=auto \ - playbook=lmn-client.yml adpw="${adpw}" --- + url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/main/misc/preseed.cfg interface=auto \ + 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 } ``` @@ -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) * ... 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 +} +``` diff --git a/inventory-sample.yml b/inventory-sample.yml index 5cca733..e12857e 100644 --- a/inventory-sample.yml +++ b/inventory-sample.yml @@ -2,10 +2,9 @@ all: vars: 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) # localproxy: true @@ -59,7 +58,6 @@ all: # - vim # - mc # - tmux - # - debconf-utils ## WLAN configuration (see: doc/vpn.md): ## @@ -105,6 +103,7 @@ all: hosts: localhost: + ansible_connection: local laptops: children: diff --git a/inventory.yml b/inventory.yml index 81076e7..906338e 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,649 +1,705 @@ $ANSIBLE_VAULT;1.1;AES256 -62386339393366643763383339373037363365316132633835363530353330653839303732353335 -6231343438366132343632383066386163336532373633330a626636643034633261373662313138 -37336632633465646638363763306436333566376133656237373731613539363530656266336339 -3339313039373766360a306631373166663330373233343762613631636432306333383265313639 -65656638306665313862316137383939393336303633646463316536646162323563383263623637 -39323134626333333661666636326636313263396663653864643262373733326535653764313065 -31656135313263313535386364623237376336616430303737306534333839326531383964636264 -36336164656636366431346434643536663361313634386233356132633133666237633037623439 -37356136383063356530336230373231623062306163646235633633623439346634636161623062 -30383438663361373938653630653562366436303235663963363631656630303165386465396632 -30313639633364633439346230666264363762646264396336663934346533353562636437316461 -39636665346565343437303032313761633536633266653866643235316464346533666536316664 -39346662373338356639613238626237353737363533396330653239373033393665663263353165 -36626265323266333337363365356538393933616266613965353662323263353832386264363337 -35656631656365366132303465306432366235363931386238633265656162396632656463316465 -66363734663233663866656263353631323762343665353535356561313237313036393138636163 -36386562333339373832383364373465323862616661343865646662626331646639646164313439 -30333239346136303432323035626135623937353862646562373336636134633034393837656164 -31373932323135353836646236316163343966643731343831333033386338393737303264626134 -63373862383732663462656639643335613232633839386434633832636534376133376432643638 -31353136313538376531613239373965303730323536393039633861393338323861306662313639 -36366636396364386136663865613564633566666262656538373637383133376333623934666262 -35373134633133383535353436613932333466383961313361333730303164353463633531356561 -34626335653335306435333364636235623862616266353961313138663032326338343665343035 -66393562373835656634326164643638623364333239613363333138303938616337623366346663 -37343662663239396666633038386636633963613934616461363664333631663663316531626266 -65636661306635333839393835363839383763343164616631666238373737666366323232346234 -32626630626564353433393463626566383331343365396336646239303462633665643439633538 -36383365356435626237663630353364396166653365653363663362663838376532666236316663 -31393565363962316632663463313063333331316564383031363939646361363837623037626630 -32393761353066316663316165666434313766653666653537326638353165346438663565323836 -62383434616266366336363537376166663261303834353531323835626463326132326432336338 -39316464373362646333663763663334363035393336366266356639393735373563616130343931 -36383862363162613161343836313737363663353763323831306561313931343835316565326661 -34383236626335316266646362333535626338303962363632373663653136383138336263393435 -34326638353762343132393537343166643630666433386538326634613862313831633361303732 -39363862306562313765303066663932636531343935383466363738373039306135646162613164 -39386464623439356635366666323433303235303866653962363932643964383432323064636334 -63356231623139663661353364666432323335613738346130343536343633396333373963636234 -33623734323966626532663030646362323765663661383364613734663066313363653566303965 -64313136336236346430663636656634653039626165613631636532323164323330333263646366 -65393337353136396533393961613738336366313138373432306263393362613735336137393763 -37623365616139613638623664333039346533646638353538346464633465663634373463653963 -31366632306437616435356339633561346237373833356565663139363534373037626566356339 -62363739653934636635386465353163346263353034343861656135336435393930663561396634 -38393335303633326330373066623135336530633032653537366631343961346639656539666231 -62326134333364313237373035363637636265343236383931303438356463366361363936633964 -36393865626137353064613336656637353039353061353532663230396462363431393636663239 -61346565663764363666393034633239613431626133656134393661393435333334633736623730 -37656334656131623038363761343863643966313730316330363061326336353839623833643635 -35653333663239363436326131663537613735616632616165316435666134613862643265383638 -64323637623364313564313730643766376138663436356530663236313133353161643336663163 -34353735386433363362393336366236303132376235303163363231396266306462643261643730 -64333938353166333664383865616262383935666531633466653832383237623566353738376137 -63393937656235336432343163313933303532646432663437383635386164303039386535393334 -32356462626633623036616531383636633533346537316132623438663365373966343831333061 -33613431383038623162656262333031386265613561646530653737363339383631303137306131 -65643961393138373137613637396465346432333266303838653935373061316532636466316439 -62343863626564656232316236373735303734623933353634643337653036353639643139383462 -36616134373065616162336235353564663735393332636166306133373336373139643466653262 -62373735303130376534343930303532316332313737656434666665346133383534343066623634 -39383332626337323061373530666137333133653237353131363261366664623363393864616436 -32356238343137336430386262633962626466623438323437376566663666623236333432316532 -37356138343132393362373266396631353138373639363062623135666631383966313761303635 -33366136303632303965353634626334653533633737313032383036303430656662636230336137 -65653163326631636437363436663163376465373566366665333635326437376438633665336335 -62623666363435396561346436383433633936383261383639326535623861626539653833633738 -35626462383733363162616239343261346239303964376163636433313663353831633838396561 -30333331363336663336333937306437643332643332333061366638313837383532373036653461 -38316233346532633266373438336563613835316634396664663738366138613039616338353666 -62396166643461623136656266663637343862633237643665386530656436393363313134383639 -62386139663035663363653763366139396632656639623065383466633939363433393339323664 -66316138383238313562396462633731323037366461616434333865643363653339656364633265 -33613234613766626461366430343663633864363536646664323230323338383130306633613165 -33336133363466323062363961316632643133303962646230316336623731616230353932316562 -66303565346534363030323763336562353061633230373230303465336562396463376464643637 -63333137666562363135303264316332323031326638343032313934626663373362613133646334 -61653130636266633034383538636236313033373334613336356533633936643933336365346133 -37626263623035646232663433333532623031623462386336383032653735333335633931363733 -37386435343331393133333937626431303330613261396237306262623563633632323936316535 -65353638396430373937393536333565363830303333373863313762343465613861383262393366 -30633261326638383538623662653839393130323539646165646439613039396135656161656532 -65313662613533336161306639663131666132313037393338303261636433646434633761376538 -62626135633733323063316230636534393334336634643330323037393566303838336137313165 -37636632656338383664323264636132653432346164323533323739623730343937633938353735 -62313035323830303964363665313235313066336330336231613833316138326234393331636166 -37383731613537333464303431663236393933656462623165356335623165616661373665326235 -30333162636437346465633031633734623366356466396262613139623262326631666638326635 -32373631633234323365386532396561613366643139613539323266653130333537643465396563 -35346638326265343564343733303535643230663238336535343937626463343537653666663030 -33663563653865376135666633396164373332326336313130336661633136613233356237666137 -65306431636535356531333566303065643065653963313763393066353630363135336365656333 -63636239336264613161656135303633636336646531323534623063333439626331613138363239 -64656262313936616161326564663632653037663430653635356533393134663331353130366235 -38366639623662663230343039353861626432663933633137313238633332353739396436373633 -37353236363164306130326662346230336135663861346532383139663362656365646430373038 -61353932363561656537633534393430363236383566343839646231343730633864613036643530 -36633534343164376466336161333833653136376664353661346436353233616430396230386437 -64393430623864646334623137343537656563313865323336643064643766633035653265316539 -62636434653931613337336337383066373235653335656161656438373165616561323765323931 -31353661373532626231656361623038626361366632663764333764663737363137333732613234 -62376437393637316663353739333935343866373164333364346165313632313639636139356535 -38343639646362636635346634363064386636623635663536366461373431343362653839383138 -34323737313832343963366536666234363439386337353838323233376464646362343737313665 -36643237316238616265313332303162383033323363396330303766313734353563353133316530 -62643032326237626433363932666164336161346532646634363564326432396637346665636637 -36623561633861396439623835376434653738623862613333643162343362613865323363363434 -32633638306438653638343239383137396530356564356338623330303661663630656639666461 -62313232343461633636336538326537323266666466646261633336393464306438653136613637 -34336133623361336563306462373963613336383265646637313139653765656433346238386231 -31646362353736646431303937633033386435316336323062346235323232383466313566636162 -61366430313335313161333163393164353530303938386435623830353962373831393235616531 -31656565633534666164303532633235306133616536646161393365616231383866326635376630 -38666363386232633865366533373630356139393030626230653834613230346664383734616336 -39653736633237303161306632333138646633356463373063663064396561613162663138366339 -33326235313165343866363234353336643934656363383464353036353138626638373362393263 -36326438303366623137383530393434353933326163356634333837653830363037316565626466 -36643339376262386430383530343934646361303831633863653765303530373765336531326535 -36646330366635366339303731376662623366636163353738646535363363326437623439336466 -39373861323738363734613032383136313335306462386436633962666139366165343263616338 -64306536393966613235376264383463313763383161343634336362393865373865383366313839 -65623761626166366437323234373130393237643963376235316535646166326663646335353036 -62366562386364343734313261363636636639633639663830666130613833383766316461613236 -37653030326661623838643861353339353562366537346535363065356235393963376331623064 -36316464626439353464393638373963326333373037333761663239343431626563313735363031 -33613663613038326465623462623565343963333064623464313039376332323935353736616262 -66646161623564316439666431393462633463633432643763636535326538356135663535383734 -30323063323361376165626436633632636234653062623337346562386338663733396532323331 -61316539393566306334616435343665623931323866313636663033663161383964646430663263 -38663833303063356637343130323362313734646564633261653934666665376661653033373934 -64393934616465383964353464336136636436323563366562623839623862366332343339613334 -63373063656663316138653939323165383735623263646438376533316638623734636261663035 -33636465396431356334383063633866623063316163343262623831616137643165366564646532 -65303033313137636562353238663564303034393166313864353330656335663233643763626239 -35346334386130653462343531336431623639376165653263373539316163383038336636613136 -30626137666133623063376333646134643536653138333464623930323931613461366465633437 -32386531323739343363373737326263323836333438356133613065306633326131343838333363 -62356331623163393230373838383866323063633739313339353839336232363430323165666531 -34316231376232396464356436326165616266323430313632393362313966376563613534633339 -61346532386537356262633936366533376239616531373133353633336235316534363436393238 -34373232383665373539346664316463613962383961386530323539313538306165383038333736 -31343463373938636630336364653931343931363461663261373333363336353438613266333232 -66316333613134363630366632623861363135373335613837653937666466623163613231376431 -61623964353534316464373737326134666538393662323663306563633430616363353833373131 -61323563653235646139623139303162616235323664613463336364326638363762653665666433 -30656634393965306436616261303330313037373030353266383833326539626263326462363833 -36656538663733313533653864646232333934333031363433613839323632333166313162646461 -32653935393738646163343263633563333132616436613930613038313462633735636131653265 -64663439323665313130653931623564373737616632386338336465363564373233616466393934 -62373763326533343830366438386430306166323834646362313838313662386637613961643138 -38383362633730353730333335316439663631396430623135313565313431646465336631613666 -64316638646531356563666631626663383939396461313631366462326161643730346436633734 -63626633303336626137333565306664616363386162316264636331386134633461636162333835 -66326139393733373262343537323136633233616331373730653966353736613538633430643264 -33623731366330323161643230393635646366623139326534353561616632636338333232386431 -35353539333831613064626165386536636664373933633833363736613335323434383663336561 -34616130656232326631613835646131353936326631396334663335386236653066326564656238 -33623065303039666461383864323031313737316565366133326136333138393731653731663036 -32663135323464653030626430303439353030393865316266383164616233613039613032353130 -37326430373439363631323061333431386430613361656439303734393730326264643731326638 -37343836393439316330653432303633303439623337613336626662323338633535346563343938 -31333963303866313763666436653265306164633731376432663634623131613166623535656362 -64643232383863633261613061373131313933626666643631666238663931336566343561333439 -66653939353665363065656631323130326664343464303338333161623639383962356538623237 -33656337323733353738353034636138656138373762343336316336346264393434306338336136 -66643966336130346263643232373334626433326334633363616337343466313438343133366637 -35336561353531306164316639643262316235383631626636633133343837663032343032613362 -33356330343833333438663465363364653633306134646537656361383864356461393963313666 -33316236326665346233653331663132313531663263623762393039663365303333663231373262 -63643634363762393863303739626162636131366564623333373534316461383861646332373532 -61343736396465646538363765653864626636376361333935366536343133666432323530376333 -36333664326538336438323138393561616536343932363733316164316133656631333233626562 -33376234663863623365373365303936376164373530653839393631303732356662663536633135 -36326439646465613363633233633836643162333164663266393161626231393138616538643738 -35303532636532656266623434333162323230646636366334663238613733326237636232623763 -37643066613361313436346531373835343131613061326366643638396633626261303630623338 -32313632653336316531333065343830656365306430623565393935333065663537316130633936 -66376231626239383165626536626564306331623935336331666662376264643765396464323135 -38353438613435333864326633326530623036396665313762613865383365366137303166306436 -35646238306262613432333434346639393939333264656530303637393566633934633062666661 -62646537306132663164643663313138646639363131346133616366313137333965396137316433 -31613439613433383663663666313237613336326134343437373637363038643332376532383339 -34663735386235313532633431313630366537326135366132373063333035613939363832336433 -65663230626536666565303031663062356639376538396531346263346139386436633434623363 -65323462393138313932623239373132326463323830616237323665656437336562333666396366 -30313632363138666534383631313366653532336238303036623235303866643632663335653066 -32616363326134343038336431393436326565343732646438333336386366383066346231353833 -61363565303737346561643938666133363565383632346465656335363864386236393432633832 -34663863393063656562623134316235366536663638653563323465666566613464373666376530 -37366364633537666231653065366664646632393638663535643931633264616431626366626563 -66656561376664303838653437306433666131323761323639663665376262386564336363376638 -32343661326138653734316161356130313636616434623434613765386538366131353036643532 -30353237323831373562376332346466366437643165633738623066636563393036623765376639 -38303135306563356533663238386233646636306266353034343433383830383330653032663130 -32313932303338646637363762653232613138373665396436336264353534623633616138383235 -30373433626332653032343937653964373161343462393139336235396439303739346330656166 -31643936333139656232353932326531633566363366306466666137623832313435333161366331 -63333432383034396439323466663235656536663831643035626332373234643837666630626332 -64363531306531393737666230363631336666366536363464353266303633663563316234653634 -62313135346639376366306463383837636531353564306530623134373236613635303132383263 -32326663376138393633383132643964656365633966656231376439316165353630623764326137 -61303234646566343863653130343738373331373433353732663837326334633530666636326434 -31336135613431326131353864613331643137396661333566303632336661626134666565623133 -63383865646464613537383533636462333133386639363837653436366237666164613639396666 -30643034306330393062313132663661636163383336373134663130666132373534383734643731 -30303163353563306465383134626137376630373731323939653531356436323337616662653565 -61313131663262636437666531623466623438326136653332666238336566623963343334623266 -39663134636666326261633634383264393662383733353663343734306534363934356165663638 -62623437633031663364306231663162616630393531346130333764656431616161626466343462 -64333865396463666161363134393932613636333330316136363737336130343663653063623036 -36393038336462373933313934353939336132313135623534393361656639333864613637626137 -66656331376235636661363534393163336439656264396663373665383737633263373934643231 -61316436343539646662316639343662336438383335383838373261643838396439316632653838 -64643135343938366236626463613036386230316263376165336232303434656230366561646164 -62656466396439666363613634366633623935376630313034633230643162333334313436643930 -34333837353937636339363364353333326238343536623131333561376230646237366437333836 -37613363663663656266326439316334383837613633336339396335396539636562636334316338 -61313536316364386262666663396261356538306536333761633763303762363232313332373438 -65316263353165653336343562343164306566353630326333653664356165376361326366333964 -64623261393636626439343738653731663130643839306639663239623834366364613832326233 -31396432343136306365393132613531303632656363303833313139363939356132393230633966 -39383432613135646435396262646461623735313135356230383533613136656639643539366233 -34306231313032303537626532316263663337303362663635323731333561343933663265373639 -39313461353561316539643436343764636665316233303438643736303464363839313135633333 -38653936663234663830313632623566336333633561656631336132323231353432323031663863 -66613363343431656437633631336638383932653336303762613730623534633936306333646135 -61613261613932653361623263656237643534326132613339653861343666393466613439303734 -31303430343132636332343134303936366262333566316638636233656330333734636636376164 -36383536313534306535336438633435353463353630326461336366666535313638363862616136 -36616236353033343566626332646133656235623162633736303762306430336238663835653263 -61326466663161646531383137333439656531383566303164366637656661306638623439323164 -61663163353263373864323734373434303530643764633762303139333336323832643063653734 -32373266373239366633636637613433336532663135626238333936353431343532316536653061 -37393131633066666637623538633530653730323362373432656439333332366638336361666239 -63646631633762333938636338323537343734396133313332393436326630383639333034643961 -65643139303531376163613833666532333734633438623935353635613635336262373432636462 -34323738386631616266313462346265356164316238323239646462643762333166666132633965 -37333535376235613538363938353135616366393964346164633861396331633139613463393035 -31313262356436646261636139383431643637383235623334353861343064666437356465373339 -31323364646635306163646131646339383931613461613330636561313235663934376632373132 -31633235346339373763303138356464646231373266366431633038646533616161613462333231 -65623835353963376532313535306331636639643635323434323362326462376239383630663962 -32393634366233616133323531633030336635623134393730626630636465653065633462666661 -63363637326139333030633333626531353866633839376661646437353939316166366137363865 -35383536666462343135623266363939623335613632613830316432343363313538623364666634 -37646531346433336365653935326437343461323861336133306233613931636231316232643034 -35396539373663633237623862623964383463613936623061376333323439653963633861663631 -64623866396263663038373561656239643664383233336433623036393930636264303662643434 -62366632323864633733626135343339623030636334356331393732363139326662326563663366 -36313262323933313631633562343230363032656636666465373062656664333964323537633362 -30343266393230393665626463316639336665383763343332333339383464333533653135353365 -34306135613839326361623663633033623238306234666564626565313137326431383763646433 -35316339366234353936326466363435323331353165653531373733643232356236383838303930 -61373538363238613635313031653434396265316434353335386332666135323366393062376162 -30353730613433383364636164306336396430633133333839383261366162363930303131303762 -32373461396264643232623337643266616562393865393864363161616337636436383131643932 -61316232313835363634353930636664323539643133333632626631666430363534383866656631 -30656634333836623133623731373861366333643637336566353064393332626461376334333733 -30383164306561383738333238353766666565656137643661623466313535623936353831303863 -64653762656364356664383365343264306336663563373763316532303537336138613238323438 -64376130656466393564613766633036623336393931313132393430313663373334353134363030 -39646665306137613034653830666437333832393464343265336162393231386437303539363861 -62333032393134666331363030336463363639366235656266363830653337333965303934626530 -31616532323334383665663936376130396334656137623537646663346166343262353764653439 -30396332346235653462633034653535396361383934646632386534643530313134343034323636 -32383538636537316532626230363361313330653534353962363932326331323966303833386330 -34623632356136616166636434633437356261313233333165303237346464396436343931376263 -39633963313062623636663533316538356162613734373830363838346133383564353336613437 -31643233343437393765376431613338383331363632613632396265656638646434663631303363 -35386332343033623534666530363831343262343736333366396238643030333337313838396534 -64633937636332313432326266643735383262643334613034643465366666336638393461616361 -31383038656235653239373164666265663865666537663335396137353939343233616435646362 -36393266633863393965363163376332383837626532343034363034346665343663326163653266 -61666236653837316639333832636536353534626365333939343734633863613032666437383864 -64326234303438363434626566306435376237336137316465626432383234383434343666333332 -33363333633132393265313662313731353162656337363730366439653532643438333639393664 -32623561636531376234613565323661613635623337303963653862393435663562333137383531 -37353532666639326334366133376162646262666439616135316432333934656631326566393965 -61643135653965343032316339353433323636353734313834666163633431366331393035393564 -32313966346634646263623130653934323736303364653930633439343339343432346538303831 -62333462343533386166623831383437373732373037356236376530353639346662663930336235 -65303564313939373532303137376565356364353332663961323366323264353738306331353963 -38343333653764323835303432643230663733643132333866303039656136326630303962643963 -39343737353166653862333030356533316165343766646231306532336530343964633136326563 -38646330386438373931323961653832613638303261653333396337623331323837623431656137 -33373631336462623531326438323739653662613139393866383263343134633335383738656363 -30333665663063373661623761356438633262356334373262613934333064326239376633633039 -66613534326662343435383438306133613765326361376537663331323938623436636164366135 -35323730363036643765376537336432333066303137333534353537633234626666336334333530 -39396133626434383132373435343165383563383564323864333639623764633064353131633165 -33333862613538363233633735653730326633346563383732353563643862356561616261393731 -66373662353937646462363262363865343531366463393761316665383230313331626630326236 -32353439323039316335343237623730393966356132656534633933333737653935613932643231 -63366163373062656630316661623131333462366564333462336333663833666363396639373936 -64613530383861643339353965666530663437356431353731623464336461383030306563393262 -39346566306565623331336234646439316461646366636566386236323464303138306663373265 -39346135663264366566623731656532323236316130383865346136353238353534303736363635 -34623532363033656437656235643066316364333164626662333536396631653531323437643564 -66386635653436616461633162316165343638326264303066633437313734383666623636666538 -66636634306532393339346633356431303537636364323832633737353139313138346632356238 -39393634666138383339323335306462623330333931326266366135616666613533633531653539 -39646535383666646662653936386231616230306536396432333536313834646538643936303366 -63666431663965343336343362356465306461313532616462383233316261336439663936313639 -35663261656534613634316235663139323937616261333530393235653836336138353630636335 -65616236366233626336356566326633646664356264313736306665316434613535393535353038 -38356331343436626230376334303138303962316231636631656233396231336437346435376532 -35316232306137333332663236393631636436633736353962663332626233363536633733353436 -62613565616332353461633930333636616164656635663064623463656238383430386135353030 -63626534393930663462323634343936346261653635636430616564643630313836316135646638 -36613363613238626364393434383966376430373838323461653131323563346364656330396562 -66373231643732316138383236636535366339623865393935383364373765636335656139396261 -35326339343266663863636361386431623238633139396264613166343564353236626237616161 -36626233356361666530323632393437623238663835616539373939636434353966643734653835 -30356437353566323266353233646532383335363366636333336335363634303038633965376165 -38306164663837366633306633393163356564643533663134653439663666316366383666623536 -39653666303363346131383064633835323261343361396462343566613237313732323366373864 -61313762353737616633633538616162353761353131636336623265313861616634376434363961 -36366662313737653465353363313537376361613534383563303764356136393563306230613466 -33356437613965633661336164633239346666636137666332303430633766643036346439326134 -30376636306436376564623338636231366536663530353537356461663864323234663530626633 -63656535633336346631386163643138326638663061373331623762376335646661316362363636 -36333732336138663034386139326566616236373061636661373038306135613031633139666635 -36626333646631636437323334653164316335396532396536356261346438383265643535306362 -62303034303161386465393062623963303131363165343066633765656431303035646664306661 -66333531383665646166393130386463323537386237383632333431333265616664323364306564 -64656463313133386330393266633932643863656436396265653161323665373861393031393338 -33373463303032326231313035646564663961363031613362356635623030376465383337373033 -30336263326364613633656532613439333631343665353866616263323137613163363333666664 -61383831616630373836343233373935633262383136663931643539653337643232363132376364 -65353662343539373437633133376638653633393864343866633865306231353264306262313261 -33366332316531616234333766323232343336613564313135656531306535643430636666346234 -38343532653666636235373366356635343339346237386436633234643738633033383664366264 -31396464366363323937333834626230383038653434346361316166343930366536373761353433 -62313638376132373661316436333430653735393737383235386164636535386130313533633830 -63616335643233373165393733613266646138353437356666316139633933346565633561353734 -30656261636265306633396633383638646233623164383236343335626432613866653834616434 -37663861373062653061316631373064336663353061306261303733313632373163326261663262 -32396263613639383534386236623836303635613631393763313130656134656236623238353661 -38643538343135386131393133336237373733613238663763653431636436376232646637386339 -37626131396237396239323031613265306262326466656634363266393064326631383633656338 -31313130343064326135616433343533653563666663393230363735633239363537376463663466 -61353865333361373538616236393235613366333635633664333631653361333962386462373761 -30313066356564363432363739346430346633386436613739363939336665636239323930636130 -61633639363635353333356266383661313638353162373535613165333063343332383231633331 -63313339306235303361393362333635313331623365666166383937313663376261653838376563 -37386237393762356339663434626639363666663931613832653539616630343137383230346163 -39326138383165326131616639623033633164626466663439386333393231373537616439326161 -33366634313739346266663564343330653062393139616464393634313234336165356338303439 -34366537613163653339373062646431643537316635343438343031613937343734356130636230 -35353334323130303439613233333439303234313530343861316261613036326266396134393938 -30393032393864656661346464666262343431386364626662353736343234363861663437326532 -65663835306366313362656135386430666633383165623965663838646433613835363836643365 -62373730343831633033613631396535333232333331636163366162613131356132643835663766 -63643531663237333935393330353733323730643732386362333734316632636265653731663039 -37623365336562623766643833653533343238396139336231326262326330316338343738663031 -37383334333634366464653836353238373061386334333437626537616135363736313364306366 -34396636383934306664363835633965353463333465333966306537353735323564643565623261 -31343932316537346561316662306139343266636463393130653434666666393338366531303734 -66323965346632306535623931326133663161663464643337373761343661633763393666636162 -66346566383937626161633339663732666436343437386233396332633261303533666436396430 -64303566396530616365613935623763323962616564373130383637623334636134623637326465 -64303037333035303930616133396336616432663338396634383037323238623961353136323965 -31326266383838653236616435313936396537323761636436626539323336663037316161393433 -64626233323935396232636337316634623037656231653661303462333961346230666230313834 -66626661643231386135363565336437633738613263636364663336313137376635396162366235 -35316638353430393837386265356465363834666366636432656237646634666533636631663530 -36656434353038626332336263353832376563363035373437316262383733326661353762393934 -31333532656666343136343635343435386337363962363037336331623239373035633631346337 -31316231623761366235303538336339626134653238343132343838346363353266346239353663 -64613566313263626537333830646439396536366135346362333162366539363537616332386262 -32663862313739316330636334346664353666363933623563643365383630373866656537633033 -39373331663663623831383830656237653034333932376263356566613162326566346537373632 -36356161643766343934643636633633363135653537396333613532656464663535653863323066 -63393662666463626635663062386430336233613637363263306564353563616439666436656162 -62363330376430336663393565613736306165336630383336363263643032653062346661343766 -65646537343063663864333933363938613438326163353235306239346236656561346264343039 -32616331373062323066306232383030373130303565666463326434383331343361393331343039 -65653536306538353830333434373433333030353465313866393966666434663238323232323364 -30343535383631313431636462356630323439323965353033383536363866323461373538666332 -63623935343665323033326432356432323730353864646431633035363831313735623063316465 -34623064303864393365373635353263343033653064313163633936366564616661346532343138 -66383130396232353166613531343338636664363164613165613737353762333466616530643937 -65666530363165346331356262363065653861386261623566346135383030656163303332323436 -63306137623430613661333733643161386138623934313863643561313061363061663435353335 -32353362663064613364653236613862383830356431333839636163623432346638303230666438 -38353766646231383436636463346436393561613339316430323463363731303762353330346532 -38646130663862323466326136313332306561613933646637366235646338343161666161383431 -37626230303633303664366161653437643331386435363631313935643764643835383662353536 -65626132313961343564373538396237363934343335633231656362316238633030623365663063 -30623232663930643639303437336563363131333531333238333663333136353964363439363836 -37376233646330323364363764393732326462316235393633626134356138653430346537393764 -32393739363637376534313836346239626639636332326666386334636234353535623035363266 -64633661383438363336656539373033313635626239313232373233613764323665663762343461 -32343938653135313863316233376632396666366636643036623566393739393537333235396239 -34303034396138656531343662613838316363646461643136643432653132306466623837303532 -65316139316432633039373239326539383165313430656364646336333863303464643961346363 -36623830363235316436306563313239636463613537623962393061616632356632356136646531 -66653561323232343231613863356466643030303066396665623638383662666465373833343733 -31356563623761636630626630356362646164373662383562613264663966326631353237366130 -34393439356263383732643665323431653738633236313539366535396664616261333232306535 -63306662346465303835616666333434393361306462653861323430366566353435333231353935 -34383264663930303662663462626535346130613033396435653934633933366464343166306165 -64623461323365623634346463386234386561306339613461613438663034333334643365343531 -32303637616336616463383566386139323639613731303263646162613262343531306665326261 -66393038653234376132646136613263383531656632373631326361313332613739386465343935 -37626331633063336232326333343037646432323265326131653665333863653337663961383737 -36663361663232373338623931393538393461646538646565323730393562353836623263343832 -38303333386363313634643930663832656262616537666531393536656664303539306563653265 -64666538333135656132643637346666353930356635393764333538396662316366353166376433 -33626232383666343030363263626266656538616562663735353534663164376434346631383762 -31376561376430333036393131356564663737633064616361353038633839656164633536613631 -66646665613132623062383465623738363330633039373135343333363039643332363331333365 -36306636373238396430336530633763613332336432363933303733346133653666373132393063 -30633437356363666235326263386566643062343534353238633062393565633838623839316634 -62323239376532383163376237366431313734366665646161626232616566323631383536656632 -36653535643537616230626633306630383934373135363538656339626432666563663638316363 -30316262336461303438643964366434366332336535343437666432663566323761306563623261 -30633965623530346165633936616366623536666230363130386633633061343730373365303833 -66646334646634366433626331626137386531323661386132316235613966663730336432333764 -66306532303566333834613537666639616663633466633633613832363164623536373738613265 -38323038343862323166663533613830666362353630323035336235393565663230623562356166 -64306331363234336433323364316232653934366662323465393961393862373738343063316434 -36343035396536363136323734623132373763366636633939616339323965306564303031663331 -63306463623732373462313035623532646334623532363666633461613066323933393433376463 -62626563666565663438393332646435333939653439306234363930303637373965643366656131 -31383834666565623861356531663164646165313638353237643831343337313362306232393737 -36653062323561346661326133326635643363336465616636316666613335623235346161376136 -36666264633232653638626138643934616366663938336562353333393265373137383833356234 -32303638646436393865656336653664313136653831336636386664333965383461663166356363 -30383139323134303035626438626632613562663164393934663636636338336134626530356134 -33643930643532376532303466396264386166646166316166366661383263666563333764643365 -38633438306538316338623631616337303933373432646664313736613035626365356433323737 -31323364616464633830643133383661366161613137356431663330633032386136326334343264 -61633333356230326236353330316264383738303033323930666562393932343235313932666133 -32623636643563623166383231396433303735303534356334623330323933666636366365626266 -38653038306135326431343832336331623564633364663033653766623832383630643964643032 -35633431663062353339333266633835366430646563356434373537393937313932346432623633 -64373632343264353066633436626531636232653038613263653038323830616164303361393732 -34643233633731373637336137383763303736353237316134393835663032393861353934633038 -30626531356333346336373535313433623035333466343066346265326336643162323133656339 -37323561326137653939303839343837393763653465363462356161363963353865386539623333 -35383637356666633731396638643966303063313430393038393234346433646566326632363637 -65306466613230353261616366323634313837373030623563613562333833653263346230376439 -35643836346335373261326365336531353733636236373466353332383737613639633034323161 -66393432653336636362313962616237316232663038343665343065313030313937343834356436 -34326266343364616366343039303332353161373263313730373839643361326333616464306133 -64643863633336363762306131303431636366613038623562653035626537353466643231356561 -37393035656533666638336637373932346662346436313561313964316139613763616335316435 -33656230356365373365633830653835376639373365623663346635396361333338376139666232 -33626662616662626363636564306530613034663039653636663838326162616263343562393661 -64353134363737623139633734306430353265323835373833373261363031383163343938373862 -30363735633531376230376161643037663762316466396134626462346133626264353064333039 -66333531613735313333376336313565376632346565373134386433663935626363336635356337 -61633264363635303833613462346263636433383634326330393236663835626432326336396133 -36396462323365633338663935343733346365356233653436613962356366383365326262663236 -34316233626130336635333933646463663461653364313338343534633630663733336261363431 -37343664333633383536633464326466653432353733343933616264316364666661396631336135 -64306637623234643735643430323262626539383439373363356139643362663939336665376139 -35613864303837363635353564393532336162393566313339633866316266363261623266633032 -61343365393762386465356164646531313865633633313866313162393431393132613131643462 -38646131363036313964333930663234396139613362326331333538376364323461353839366562 -62313066663830313862326162326166356537653135313036326239353032636634656433316530 -63336532663935616633373261653666333662643561313235353466303632623364336165623334 -63346334303762326363643838336362616466333631376135643466306638313038353765353034 -61613033623132653930623634376537643230323330343534646365356339333938396565336533 -33303730666433646465623231306233353130626237353236373836333438666565626566326531 -30373637353237393934343064616663663762343135313865386331326266386639353430306130 -39353534663362323665616166373733623639333164656633363537613437616635363639316232 -37373365336531323639663935313836313338653030396133356365336437373963313231636332 -65663433646665383836643362383739653663636338346137636263386366386234306130303264 -30393266376138646465613436613736373662643365663330313230346139613465383136333463 -38626661643165356364626164663164366534316462376633653231626233393934303333313963 -39643362633761353731643239663334646266613536383661626462633062653231616236326332 -32393634643030656535633139336132343639313939313436393865336361633430376166313230 -63383435663766646537363136373138316166333031663736616461316134343461356438366361 -37326663343434323563613231633530316364643164646464386361656632633539353135303432 -34386162376235326631653764613866323432366166663966356534346463306231656665346333 -35356633356262303236386633316539363536653438633334623161343136623161313463626633 -61373637303630633233383430346534613336363739653332376461383531653832333264356163 -32346562636662323066643932326436326333323537323932343033653862356163353730353438 -31313531306462636131626136613135646231343633323065623363643661303336313463373130 -30636630623734636536366631653031326162383034623233623463326434366635383836613361 -61356463336335646662353735333662633231396331336336636235663839353163616234363733 -32373438393730656461383537353038653739326335313732636639656263643033346635316465 -63306437613863643932396361346335303331366535393863613663313133393730333039306233 -63376563366636313435623664323632383139653932643461383536313734343430613736393734 -38313061623163313931616564623366353266333237643639366166313564336437376664303938 -30306233633437376233353237393331313734633063666165323637363938353239653539613439 -36346232626466396431386664396535663162336166313438363265353232363365633034383331 -36393164386235613134663566666539323539313735383636303631336337386366643561346331 -65353962366336653139356433366465616637386333636439333365396563363663656231346333 -63366636336131656237396234353837303035323637343265303566333761353431613135356635 -31313664316635636564346531323638633266356634323164393563383935343738346632333237 -35656464356338356538366664636265306165653334316363336435666262636634326636383934 -36313136373038326363366263616438306561653565656435643063613537643732643332363037 -63633962333637326434363936346633313634363961613063303664323761313533646638666139 -64616436366638353166656133323131633461363663616336353730336639653463383033323061 -30646237653463313261643237343933663032346133336339393965626166623066373735623836 -30653331656635373838633062333638333037316439323663323838616530663530623434653964 -37616362373331633030396261333038373162336536373731396363646334333665396630376263 -37656634373138636633386163393234613434376265393065306333353661326266636633323634 -62633031363965346337363031663263313538393064363761366336356462383737313633353236 -35613261653563663663663832373664383262306232373430323934376330376166363738343962 -61323863336664383266313264613563636464363566356637396261353039626166623331626234 -39353762353536646338613066656533303332666664353863343838356464616437623934343263 -31313838326531356432353563326334643665663735366233666534343733323865636562326530 -63333166303936643736623066653832346339343133346632343164373630616538633936633631 -36376663343934666133343535646662623038666633616130323163346533393765653337353832 -36616563393930343065666361376635326464333435303736386661396263346331636131386336 -64326665643536363563343964623536306238376535656330323061663431653532633434386634 -33346133656630636565613065323634616333396363346534303163393337613830366662303731 -61633530393463633635346136656366333030623038616439363631383466303962333238373661 -35386332613264303739343931336366653431393134303833323464383439656661303163636464 -61363462363064393364633061336262353261336662363462636462336462636535366662333534 -63363666626137636633356631653862626639346634373238353636666236623964373231383264 -31666563353034386365636264346464326237663235353136346339393436383035663034313630 -37333963373135643430653761643662353334646439313262393635656662353439616334356338 -65313166643934623065353164633965303166653830306165333837346262393563616335343764 -39313033373339626534613838343239323661613530323666356665353431356439646231613638 -63323862353230373562393039656361376434366237653365373937336332313762333561386432 -61343435356633396465353133333066333563313330396234626165393364653031353939633731 -37623439336262373838393533626162333937623133396365373034613962623161393231303562 -65626133623833383465396632366137396135363434306337353038333633653264616437633635 -66396435663931653534643239613636333862613263613434396261323238333461623661613437 -64633331393461333831633162623333623663376165343530326262613362653730663463313039 -33316638623664663837383837306163663461373636643032303933366338303633613830356665 -34363165663232386237643464646163663136396232626138333165653162303339616362396230 -37383766313039643438346136623864326334653938393039633961373339376665633536336437 -39383033393635613034333634373834386266626534363833313534393134303138363162316533 -33653333373962643965336465326635653732306338656631356564363961366462636230373030 -63393837356631366638663964326530666536643932343861616665633331373230336530356138 -39303738386166336334633433353339613366643436313064653333626130313361656237623163 -35663263633136373765343330343338306636663534383730353235636434656138643466383261 -62373661616137613164363665353535633637613263646361313337336533363665626462383633 -61383731303132393138663639396433343530336266633939653366633438626139666161653638 -62623866393533346136343339363334666333613666613031613135626235633564353463366664 -30393130356664343434633132313537383063663130646464346263636133303034316266303739 -30656661303231303434333562656237633233616539333239303266373363613034626263613531 -35393937333761633232386333353134613362396138353030613934353935356637623630356533 -30626431366234383834383866353436326333386564353537663136623761623736313861366336 -31336331373537313739353933303261336238613630636462353031653133333139306363326566 -32373264306338353638393965343933656162373438373366333338623434313032373538623835 -63316434306262643532616232646430316635306535316635326564316664353063343331653963 -61306530396630323031386534653062636533613931613632306637343364623464386137623330 -39396166306333346665323139356135643662363564633631383362303636616336613732383763 -35353861343565383739336535623962666239663963626162373861343738663364386439353133 -62666232333533376563383536363239366135306134616439643738306331643539383034663363 -37366366643838666338396537373232623232326263616165616639353939323463663638643132 -61353038646233646231393961663863373466306461373832363435613635383836363633393039 -64346134633837333332366135363736323234336235626630653965353039663964383535373931 -63303262346661373535376161393136656436303235386333663033656164363636346632616433 -31353932643266343361626431383835623761653633656131373134633163343137363536336661 -34316633386263306432333338313462393031383832333533656436336230666363316133396162 -65663861616538306333373032626539663535373161383462366164373764343437323562626136 -38653336663263306533376466323132623261386166666435353438663763316665653039623532 -38323730626666353636663830373765383138303330386663663737623531346630363936393966 -37663839623464393136303934306438376362313233643838373939323938666635626630633035 -31333466393833393361393965353636616661353166323937313032663139386431333163663035 -62373265306132643465363765376663623430656264613839336234343766613833323235353333 -66656639366130656534316639306638366465336661643263666337323030666263623036306362 -64316634353139666434396261653161646339663263663131386339346631653932653834626562 -62386665616131386138633839353262353230316264383130656330313333326538636261393863 -37633665613631343130313163376337363963653134626131643531353565666537613636373663 -63333633313561363438653035303563303532613736373634613362313663386563656339656634 -64616666346532376537336130353233623832336237376663663837643134636361616533666530 -63373065663833363734356130613230613739633134643766373935396531373965383862656330 -32306639356365383332643462336331383731643864636264633234616132386538396533613432 -32646638656233333661626335306361646435306234653436323361643866633235313962313637 -61333637663463643066333562373535363439636666643538626133623432643932666662653233 -33306137613735626135373430393033373132356666633337303134323231323235326434323639 -63326362306136333065393734396339336665313035663637303533393834373664623864386234 -31313062316334333130336138326132636366356266653531333435386231653063646531353933 -37326533663431376461383632643266663531626235393131663464373439396666343236313262 -35316165313962383632623262366164386130323065646436343236623230636664306539613031 -37363564343438376637386366376139613332623765663166373731316262303630326234383063 -35303330333364303366363135376262323365633561336264626333323564396132346362626164 -30623637333263366164373465353562356561376238353332353461623939633035643562356266 -64666131376335663832373136646266633363386139363864363939386534636461313237666661 -31383063366362306466633039363730376130373661366331643836356533303062323030396330 -35623431663561653264383531626136653363336339366332363431323635393561363763613134 -37643733633138396432623031666333616136643735646235346632306461313136653837326135 -36643935303264303532396332356561643063373263303536626433623264393432343933363237 -65616237656131356537366337316437363831303064326436393761623734303238336334653131 -38363437373264373636653531346665666363616233643563336133316439643663336263613964 -66613835336638386631386565343233313435356434393637326339623933306134343332316132 -64326434393134643866323935663331336539396636303666623364363133613861303366313736 -61623465646336643161313839326333316632653365626231616264616633623336633463663232 -65313465313965316139316531623863373235633362633731636633393534663662623663623533 -65653762623938343833653639373730363932366330373237653830316438356666333636663938 -66353139333162376439306530653839306436393832333030336632643830376663653132633633 -36373965646666613436383931643662383263633066356666666362306430373636336438626231 -37653338336462616333353937626363663765346664623862616162353865633463393263626537 -32333336383633383237613731346465613635633633383065643038333536616331333966373232 -66663231343266393865663165383937633439373064383636323137363566646133616332656566 -35343335376465653939653933393161396265396136363936656433316566613336613537623365 -37393364326337633362303662656333613934663362323331343135666136376365663765346439 -35303465303163333732343737383135303635613865346331376537336566623561643837333433 -36633930376330623737633836376239663333616134356530623264303337666432326332646433 -31633034303166616134353736613838383231666363623563316430326461393462333564626335 -62646337643066313563343466303231643334666437383135393432663538623464313735663431 -63336166323839656531633862326534353136303264616266373431363036643335616562363438 -63643464356662333065666663643464623139353833353536323466663462313630366235303065 -34623433613736646465616466633232656362356137366634393735623031343531633231306334 -33393137343637343734613133366239306135383931353637313561376161666562396237386436 -61386637376563346633303032626361353462323963366233613566643434666532383965626661 -66663165336164313431653363653939653262326537623630643237636163613066323434653633 -38613939316463663833643062303933383165393939333233643139666462363037613032306135 -32643266333938653962366231363364616339656137646432666466653363636265643364656363 -32313966356238356266356339636465376133653861306233343635303135303735623037383339 -37626335333030643932306164316535353933346462666337353366633966346363366337623133 -65343766653261353365643039333164663231323031393233623062366432373430396563663264 -37313962363831316137663064313631646433353033336537636132623663393637336438366463 -36393565633936346134643465306639633737363431656161376533633434636663656535613037 -61643330383366663266626436326466646234333831386632633566663831336437646563333635 -65616339626561353065626462633530633461643764373866376264636337636431366638623839 -31366338653632333037353233623962303866303334353033343739636637616239626237343764 -39356464396239383235396132316665366238373833303266343535636164623862656139613064 -33393264363634636231653235613133656138663763326263386334303537333733653132346533 -61383739663963643365393638616233323138616131376461323233643262656633636435303566 -32656438303466306361653366656464303335663661656437373031356365336334373961386264 -32396230326431376137356534336566643137356361316232333939343362323766393232373639 -35363465356235323331333265303535623630666236376230633364643237653762386630323836 -38363136373331623964623964373163363930313138393030353636643930633335323761383764 -37316135393466323139643738366537396133636465393565613765633938306164633263653032 -35353931643438633436306464316230333437373532356261613565643164656330643862386635 -36616237653834653134646439636266643131613761373833346338623439383861636330383133 -34616630313465303535613032626536303762623331653435333633303262326464306330393832 -30623265346438656137383937306366646530613564306230353939626366653536653738323139 -63363332626532346462313635353366333235323837353961323862343334353232313464626236 -30633336316465666637626239373730383965653737663639336261306264343530643364663561 -64666265613762313032633837333433643537666562653534643364346637356363653732306561 -39623538623763653136353464663164356232623333363033646666396232666261323233653661 -65393536653237383863653134356134653533316631623231616539653861363538376362663066 -61646261656336363931303935353764313562653736633431633263656261623039613737373432 -31373165386161373038643831333937333366636230326133616430346131386663653964313866 -37626234396631646639626436326466666561303734346134653764353234376136656662366539 -39376161616162653337353235643236323832653835356235363634346365346462346162306333 -61326534393264666163383466616166626463626666616438653765346638383763636338376463 -35616466306230383233366266653064343962393731393434363435333466616462376633336338 -61643061613963666636336366663562346366616135326462383864326562346534353032343662 -37363861653866363630373565346266623037663233326432316562356661333538666332313465 -33333930343965313030363262653862626461393162653135666666336262663634653333313434 -37373030356665616238363438613739366337383961666662363364343535393033666336636465 -39333431353939366439393761343039626663386164653330663135313839356535393362376135 -66353531353461333539633135363832393235333535333066373461346363343863323239626335 -65313638623638313437303865653736626133653239643232306437663237313432346633616565 -37303539333830663235393862396665313164623263353932313036333362643361383732346631 -33336330656565616331 +65663265653134663864356333373331393339353033383265373261663332383037656133303432 +6662356330323730333132353231333537376535626338330a623266393537623365613335303763 +61346461616565326637376233306336336666393763663466663739353765656533306463366265 +6137366133353734380a386564313734303265303937383066363235393964383737646435626432 +31386533653165653836303462363033383463313161366364663434346361343965383534623563 +35646366316335376434313333323439353563383766393466373931363164336464643161336662 +64616536383431396131653763373762663334323835333532343237356631663333303438396539 +36333039333933323438356336626535383763373766633363656233613661363036323533623261 +66623363303930323961393439633561333163383161646636373435386361353736646665373735 +61333137336131663161663735373765333964616539643139333761613233303436396265386639 +30383831643532323630313732656261393834373935623261373237303435323134333463383831 +61373933333737313736303739363362343235373434393839356462643235663366663336373036 +63383036383434326237303731653363303666363666356564636337336364383336373361373631 +62663130613139393431653265353033343932346566303635353132636365306531383532303763 +30376163363163323232616361363166393661333933333031346232303737636563323063393939 +39646362353461326138633135303235326339643763613831663638643331653137333737346233 +31346638653066643937383230306432336232666534373864393930633864376530623530363866 +62653837323137353830666264653263376336633166363238366164376662333731353137666633 +37643938313634323231386139643130653265646235653939316264303539323639396334353339 +63616261626664643330356139313633613866376139613734313930353731653861336162643333 +62316130313838393439366236396465623639626337363438323235653736323966396664653066 +61396336646532646639326335343462646236653835316631346461636161373032393735303166 +31633031643332383362333838386232616135626361306539333234646137383764363532333030 +33613133623838353861346636323739343765663261373163373639623664653564396635646434 +31653330393763336431613139393434323037303338623234613039323161373965373131376363 +61323863366461316330666637666264386463656533323130383032316564643630616630333966 +35656565666234643435643238366564323131333062663638313330383236393937653834373935 +61333936383535343332376435303139313761336466633434343636643738313739633665363732 +39393266613937306464383531353633306332313336646363363139333334646639386564333961 +31363537333965303534303431386532653139663166313433643461636437363031316230303762 +37333933633036346630313633366465303234303139663131393735626339343964326264626333 +63313533376239616163386338396665633863653831633130663736343035653937356639313030 +61383234653435633139613532316261663030316332643965353339653036353536376562366636 +33623239646435376131633131643337613139383765363961636262386464376362326339633862 +62393831626133383735373832653634326162303438313163663565663339643164336430356339 +66313833623731376164643065353032656436656664366336323862303039613433353963643733 +39303566663032393162396464636264373334636132303935616134323236393830633639376133 +61383666646139383565393064653134353664653137386437303530393736623935633761373166 +36663064356161313166326534376231633431333966343536386635396536306638356132646563 +30663635646362646631356139393135663763613336383338343534616138643066643134363538 +63383061366364383633383465396237613239656237646662323036363163336437343362656534 +61316334643132636461303239636537326133306464306662656564346633666135373536666135 +39326335663765613635353534653162383130393239303735343461333036613730366632306435 +34646163346165343964393034323036313031623235663938316662633463353839396261386432 +33343330323464663061313433356634376561323963373266663133623361613833383134383033 +62346335646136653937653261623535393563616139333930323739373433663364333765353031 +61646232343863383665366137366565393166623861383330653361346162626462633765636664 +32616262356438656136313537323538393337366164306538633365616530363061373034633038 +31633266653931623935303033333863383039613966666564363465663966663032303663633233 +32356664373833353435666339323539633763613063663939373233663237393834623664643533 +65306536373437343730346536656336363965313966373937363164366631363766633361373439 +61306637326238313664633039303839343864623834333265336238616638303363303338313334 +36643162653862643561303236333530363462373936366331306535303331636439333635383965 +31366339626434363762323331623434383735643031346164306163376663346538323037376531 +61356565353334663136323534633365383235323432363835666538326264306564623834626663 +38666533613664323736616630303062306134636166663461313439333139396266653738303333 +35306465366131653564633338656165376638356663366265373165323236343639636466613138 +37316463366637633066633566316132366565313861316538663938386464613765336136356631 +32643661363132396537616531623165623038643239393139646139303737366438353738366233 +61623561303732356336396539326232303530353439323039333033643764316662666465353239 +66613437316661616536303634326165666435333739333765366532613163646361613730323937 +34623964666264343363363562363833336463313931376636636631363537373966363731393865 +36303231636431626165356230323739653065633163396134646464383636613462626364613836 +37663833316232613437623532323539323033306633373730336638366365646566333235373436 +37663530636532366661396139653166373538643739613934343430643530626466313634626362 +39623963633066363831323030656536343663663934333132393338336263366264336437316635 +38663232646361633835353833333937643137383339643764343530623934346639396237353535 +65613339616230396132626333616338343735363635653438653862663363376663343230323938 +34613830303332633231386437383866306663356430376133653335613163306362343737363932 +35653565306135343935366431323966353033643231663131626434346462393431616661353831 +34653662333330356265303263303238623361656166396336633230373861636637633931626161 +31613266303365376431333262633738646532376535643461376539373438383631343061666132 +33643533343464646132623233306230303939643735323364353563373861313632643334623166 +33643633623930613939636231633264656663623666646261616164343031353933643563633434 +34643762336235366539646162653634643063643336366463653734363538306162643834623632 +31616664643062353165646666633461633032636330396665373866646135313664623033666333 +39393838666336643563373634326339323030353565356234326462313666303430323136393638 +34633635613335653430393439653566616136373263323236386632373634393330376239356162 +66353666376161613534333063353263623531623536616364303262326638343163313965383131 +62333964616563396432666433303831313663633132636636646563326630633737373034393966 +30363037343530316138323137373733656465363439643763363035393939656332323930363937 +35356330376139333862333939393861303934353535353461336635613962333462313333373335 +61663930353261353132376438643165333838633034336564333462336664663830653530386134 +35333130613263623565323738393765393439353033613039616136393632333039316431656334 +63366138643263633835316362633133373639346132613661346264663063303731396532613864 +39636537386664343363313764626461393463353236646234653735666433383064336466373630 +38373731616363633434613934623965666437663762646331346264323761343037316165316564 +62323739323663323339376233353135363939626164396430373131373734353232313262343731 +30346466643932396634666530326637663430326365393461366539313461386337313161393264 +31346465366630323765613435353431616266656162316465373863633435383430353830663563 +62363066636630303834363861663530383537333762326465646537623764303034666238323530 +37343666356330643231666264383363336263383638366431363961643931356633393934613734 +65313462373433396330393761633863346330626266613736646232356339623032346665363833 +61633035393334306266333134393131393135383235383634333531343135376238663665353365 +36663730353966643133353134393333393537373635366162613033373036316166353462353162 +36623930336363386334306462666532613130663336643334653635633638643634623465333765 +32313730313866333235656266393131316135306232366637316164333539333737353039343363 +32396138373139613932313430353664303633393035663634376531323838336666366362373665 +37353231643064623239616261343466333139343733666562643364316337656437623534616139 +38316163383430303839313239343366383437636539363439613562346164306436323232303238 +32303134313739363061623465303231633730613363306566326231623032333663396533613537 +31306631353331616131356139633937643836623463316161313464633365616439323731623536 +34366637313962626262373163323464343737633263653266303533666530323436386631373336 +36346265623537363332613238633631356635323532353933333032333434623635323535663339 +36316338306365363430313031666132396232306261633566383962666335316166376664643734 +39623430663235353461653939653230363032316464323064326639353630363863323361373537 +32323432316239363236343432363830653336653764353661323930373130363035646131313437 +36643466626337363037653938656362643066316338393733323432623031616238613336653432 +66343434323031363638636333323664636437303665613337323332666137303431373036616465 +32623231323137366561376634353564316161393936633834383334383064613739333361373861 +33376661316136316639353339663638333966643831366465663136353639323163613133393835 +39353961336130313035656261363664363566363061323035356162386662356363646639393066 +38316663393335323032363965396165383761623239643338626164653664653165393261633831 +64666433386234326163363737663262306662306234383338626134336562656263323631303363 +32626562653632356338363030366537316235343863363134626535666363616530393534356237 +32383736623533666632396161623366643030383538393037623636366266333665373333346636 +64323132646130633335393965663861303566313231623932353362616438636235336330363433 +33346362346264383538343931323765353763663830396264353135663834623766643136626635 +66666362333561666138633237386366353962303634323434633464633935663531643636616261 +64356663353037356462343431656538663332336665386464333831656539303732346465333362 +32373732653566343030623337303030373432346539323364326266633539396532353933336566 +64623664333938373531386662313166303133336164343937383363363337356365336266613737 +65386332393233643536656664316336373961326335383561333836306130616664303665323334 +31656134383334363134366362666438346438646635613930653731613061303339316166316635 +37666262623863376330353862666461316237613561663733323839306133623434336533313739 +30323764353936623737656364666363336139616338353562623838623036356664356131393239 +33303966643363323264393163303237333566303266396138653161316466386561653037376261 +65383135663362373931333266363137366438336465623236623161393231343333353031336164 +64346162323262666264646564396462353334656636616134386137353463613335303839373030 +30343537663035613730333365353033373433653434316134386266393865383935623963393165 +66353039386338333331333830666461366230326562366466646531363435333338613937653162 +35383235636663613733666537663238396161633737336438353134376538346638626239313062 +34323933316537653736386238616263333832323035376330633533656534363639393664656261 +36343765303734363863353365636431656434633934313135313463633461633434356461323261 +38663262363535666435313837663436316635386463303163666562343561336633666462376262 +34353239623939336137326537393337313531313535343661373735393739313334303131636261 +32326564656266316334316435363233336339616635346130333536376166633239303535323139 +64613636353362636665646239626436313238346539393663396135356237346338613665316663 +62336531666531633238326537643331346235643634363536303964356333343234333163326133 +64643232666436383730626663386565653931643937636139643762663435636536303261386436 +34333631396365646538373866653765356334636262613666663137613166643364643535376164 +63613532626366613735323234383563326538356531376130616161386132313630616261653030 +61623639383232626565366138373165353165313330333765373066373138616231363262653736 +32313633373464343163616338666234313165666164623164643337393033313264363734616430 +34353037353537623137353565666637303236386464323364353464633630616462336266623834 +62383238623834636630306233653765653935373233653231366433616164396135663536393838 +34306335336537306238376636313233316634653531356366623731356561306564656161373866 +39353766363062323233623433613065386635646566316438623162396531613966643935343362 +32666537633437646335343236646238376664356632663563633331303431613032666632316461 +63303135366565373665366231643861643361313837653936383265386231616439303339383130 +32623764656465343530383561353938386162623365646138646238353331666531363166653032 +63383836616533376261313239306335336361333533633961653563393434303334633538366431 +62363466616336346362333365393363316435343230353136633733386134613738386666303865 +32393337336432633530376235306639366534656466343235366431376661306661353861383361 +66666432373435366531373131313030313537383461353966343833386462393233636662663061 +32353236326334343166363161326535333937376434326462303437386339326435363163663262 +31323436373266666136613737373534326430393633373431666635363330333135346563303831 +37393735373333373532333938643064666439353134383163653331346163353930333534373130 +63306565326430653235656164306166326361646337653037326630656562306162353130323635 +36666664346235333831373631636634656161616632353962646532633339313535366663313061 +33393334323963393731383761666531386631643231373431336664626664656130353562393234 +36383063326336336563393164346237633637343564326330616532386631333364396239363664 +38343533333262303562356565316333363063313435383232366263656337333865363263626665 +38616231383530653833636139643564613864373561396531353662336162643136386666333637 +38653037346637386562633038613462666635633631663237653634336234633736653163653663 +65656139373463666638303263643933336361323930333839353965363061316163666265346665 +66393165383063373531636165623239613232306136646361346566393132346363636530353466 +35386130363763303835313261343565326132653632376337356565656230333032323331353564 +63643466616332316662626135333531633163373833636633333235633461643361636132303638 +66303831393761623638323534666664326561316631623339323130626439666630666663366438 +39316363343236323461386561643031363765636264383039653036633334346633363061333066 +33356261323063393762656665323439643535626433663330356163306361393235396132323738 +64353437353463376666383439373736316231613638633433636161303662356364313834353463 +66353864336465653763373666363631313461666366336130326361326265303930353731613163 +38373063653837383539646535383437336239666132666536643265343363386138383131363438 +63356632316538396638303061363636396466373338366637306131613633306463326664376664 +38616233653362363636636462656265323138353130316234323465323165623834636163333731 +32336664653836303236313161616365643365306137343364306437373837666530633230313561 +31366664313865333836303330383862636637653539316464313466353537633631346563336339 +35623838666632313838653261366463303532386162663062353264666538666464353733663561 +64653831393036313631656638383064373163313532653330643366613239383236333863303834 +39393666613339383763363339333238306331363133636639356436316562653465383330356466 +63623661373762313565656536336136386362666638613161383837306262633863653363303137 +32653838343063626337393733613235643938616434643232376265326138323438363630333532 +32303964666537396563613831363534386236323231373538323566643063633335386664633366 +33303737633133613832626235376130353666643831346131343966373737633730633963393464 +37626632383330363365383663363161303336326166646163393432393630326664306332363131 +66376436303033306566396665386464333835303935333235326661313264313337653466336133 +30636461346362346537343538633639646164643336366661356130346335393764376466633262 +34343833313165633063346662643365346534363434333730376338623336653264333130313032 +65353639396431666161663764663031663063303038316531313737333865333162633765313762 +30613763363738373966636435393337346135383064333039313731323939663963623765336231 +65333431353233373835653864623363653330646238326337353865313534663938356665393535 +34303732336637643235363833316265656130353134353430333133373462343465336634323235 +36633264666137373130376462336665303238373465396633393235346131336532633338363839 +30666234396663343065376236383131383832343035656166633965626636363933376462663065 +31633230333764386666363365656538653031363530386663653733393037643264383339316434 +63366131613434316461323831323363623764663233396466623731343365323366313936626161 +65373336356363383939353966393237323965303036303066303932666130656364336362366238 +62616231306136343966663565656535356130663337616164623365323537366634636666346366 +33326234353438616562306432313232316331613732336230316334393065306565366539376236 +61623233366637623762653833303335346235343033633331313435373663356666363030346465 +31616265346331346532653361323937613739323838353965643539373937373539323937396337 +36383865303735646135306631616139376563646331613936643864366464393464376639343663 +65643536363031373439663334363165336337303165336333303738653734653434316466396538 +33616130646238643565346465316435333138353834303762666638656362613964613635376466 +36326337353539373464323262336136366465373537396663383663626535383232663235303963 +32323661303734653331363061656362616664333037643762653030656439333738646631316332 +31356530623831643761333966613235653631353666306362336231393836323261393036366237 +39353564323433633734343062663131363661393065326531656238383331643764633634616264 +30636364333464353931326163393638626330373566333633653038343330373638626630353462 +65376535663361653461373465326462396538653732666538616238363037666534646163616236 +65633234636136396564393530656165313132333265633261613733373031656436383138646462 +35626662636465316533613864636465396232316462336437363430613439346132346239666365 +61633831663632643235363162396130656631303332303763326239636663303234366666383666 +63626361383165333166643833666131346135323264393239643530303338303635303165363765 +31393965353661376432343865303335373433393262656533393935373233633463383164363330 +38633033353631396635393537656437343463373731616138343265396366663264663466633833 +35366435666166303333313631616661323765363565383838326433353130656263306538373861 +66323936623165333630373132656261636464326263306633623466343131333739383363346139 +33363431393632343365383830383233373932366365393935656338323566363731626264633432 +63366537623736636533666565363331376130323434653034626662323862303764383965326264 +37653030326361643964616662313763383034353530633037626466323462376632313366346632 +64633930653464356362336164656466623462646535333563393630393437643564323439656433 +61343963303434306533326137623730393462633037313135326137656437343433363731383363 +36336232336464346561353162303731623339303565333964646462353534303437663563626531 +31356465303933616133633335316339653330333263303261306637333762376631316264616430 +65653431393231306134326436636138636538386336653333393262336363366430653034303137 +63343334663263323965663862323566396339643062613732303737356136373038623661653133 +38373630643935313033613132666538373636313362623034626231643562376263313135633631 +39643063386236383438666631623263653137333935356466613862303638663731373632623430 +31653263386135623430396239626638306533663466333736383032353262383336333131643335 +65336336653733386264646637313937313738643563623330666635653938306230316330663364 +63343232336430303230666165353064636537323766303138356637643934326432353266666135 +34366336306637646562613330353936656136643766616365646262613232326666323063383762 +38333838353065656439383065643631663633356531353463336361366131356132366437636237 +34313635343934383032633937623831623332313764346162363965333062643038343937623932 +30623637336331373562353432313265326664666432376233633331653332353366646665363937 +31646565333064343463323330643266633561386438626434623538323163366533633861313130 +30626136633739303862316630353465663638353730366262343739373436336535373036313732 +34663962393335323566626438363562316638313636313932393736653233636534303236383930 +39663462656161643235303531353634303965626366626261356332376237333565633538336639 +34333030366264323562616637383938333866313163663339643537323138623939363134393330 +63636635346638323538636332393130316135333533656535303732346139333866313335616531 +65653433613239646338343365643530633734333731353738353165316130643439383837636665 +31663039333333386365626466333933313032313434633333396133376330613330396636636134 +61376434346330333364666232613731303466356436303163343933336364643837343264613965 +30376130313737343332653865393963303635373337663131333038383334656266393138333830 +37643737666661316434303433643432613236356562346332636233643430303030333966653933 +37316662663937373237633963313936353765666638333639323734326236396236323030636334 +30356232306566303538303338326430353438316332653236363365646361376338333736313533 +38323637626563353261613761653730333464326630356333396565373265386235306233386233 +62636630303961363830326539376138323937636632663334323362333630386231386563326639 +37386332396433333061343736393165633836386338313234303266316130383966623063343833 +33633765316534366130336639386337316530313639393335313333353965653264396330643063 +64646664623963383866353566393739643665316430303263313438376665666336343266323633 +63333732366463376132346361636466333261326661346562346564393330376536333034656332 +31316638653335623235646433386463313261333331343838613236376333386132343564373033 +31326231363166646336353966323537343962373036303564613830626530323966303836306638 +35643734356638353334656539356363346331663364623130343661323466303334653133323434 +39633332613933346137323966353662623435643766653566663261303262343261666365623865 +63633261666264393263383831643631656139366634656239363062386235653130633432633962 +37343232646536363262376265383530623235613865616533373634353236623632653865366237 +39313833666330636335333463643164353564356664346631386635376564333463313237353433 +62363238333762363333306334663866313763616530323530396235623863313431646433613732 +34396639633464363539383137636363316466613833626234663166386634306631383832373361 +64626232346230643937333938323865373661633861326563636436653833323564656362343830 +38643731386561306639323661313131616437636335353738616231323530633238383564653764 +36643431663166666539363035623937393831376632346436373134356531303836626439373336 +33366330333538333165366132393964353435306363353862386465366666326234346139636330 +36353761616464353631303539333965396362313663333535353263383030356435386234633639 +37323662613635353161636332643538613362303163646136356530646264326436386635386262 +39356364616665313831373633353662303464396635333561613762666435336638643162383332 +64663563613239633966646439653336363230666566323063393931326335623661613937333462 +30643961393833346435333433316565316333393361663261616339343731356665616633646636 +62636566396234376162373865323363323431306538306436396533303461383837343932323136 +35623066396165616430386133353938633639663737613630333338613235306539316261663361 +65353430366435663665316338613533326334393737383465346662363932656364626235616335 +62613239613436343661646538343963633766653161363134316262316338626630383662396162 +32643964343739646439636165663132653264623030303837383030343130313761643862353935 +34613465376462303631363634353961386137323734666563623034386637383064323564393065 +34313166663535373434623738306636363230663663646632373839373932326363643334626439 +32346236376639316562306334643162336338336434633366373038396166353561366231356236 +38383034363339643162303237396138626561623236613435303136623635363032393764633965 +30343436643538393233393538353330323563633661623163336262313233326362303334306161 +63323166323064386137616562643936323864376333656131613865306561353437316333373936 +64623137386631306261363438323639363639643634653863623635303131623634633833626361 +61356431366464646633623865633464366539356430353739373239343064626533393462393033 +32623136323763643737643861613731393739643631373738653832353036316266633534653536 +34623463323639623136386137623935343934353566326664373837373538326134393863393631 +61613238643463396663643363616666633164613336303339663735383630353263396437316235 +63333639623137616137313938373139373832366433646531343636646266303239326561393165 +38333533366631316566316461303930666133396565313334326666376638386462306535366434 +66363063343234376365333536393536326130653262343630353265386665323763653330633336 +39616562616434336431353333653461303465373431386463303433653136356561363666653463 +62393863633930323337393161643630643232316162343730626666653763326330666461383934 +64386462356665393766616537643630636265626634393833653266363933376362613733636537 +63303365333236306665346664666330393633623436326462396536313331383735643237613562 +38373464663836366632623338666331306537396662346665663765343865636139396339353161 +35643431613163613431363630646537393664353834313163386161626364333933373332373264 +66646631373239633032386131306235326463643833656234336332643732646663363837616637 +66653338626566663637386333356533326339613561326539336631313866613865323661333634 +34343564316233653863336464323963383938656562316664373065663361656130373638343938 +64303063643534653731303831656130383261343562653365336234313236363837373462333537 +38636262666637393038613562306562323133623431383030626436663735333330313861313939 +34323936396562636238333863373963323534326262643732656338333837316639356430386562 +63363665616162383737343537323366656239386265656230393535623164323638373030376133 +62653330633361643339346336643261626534626339353062373762373364326332653466613034 +61316633323836303465313233366565396561393132393762613264646365323333636230656337 +31663462343931633764316566636136666164353836343938613164356665336236346232333835 +32613364366466363732633830366136323234363262363930633834366364623332643831373530 +63353433313231653930666332623164623937346439666138326139313238373538366432646364 +35643661386433333166363663633563383534306366363962366364356139376461326336356136 +66333563646533613039643338333539326562326330656634613266323764623863363466316138 +35383233623637653364376565613136646464383363366163373862396436373534646636623233 +38626533353738386533643530383061356463656436316237393131333338343938303361323331 +66366231666439323662636266303634653737666330356661323065326639396462656238313534 +63323839376531666339663831626330393163353365313762356563356562313534653238396463 +66343639613236346364653131663066636434636665616132396264633934366630306463666130 +61303834386432633763333237343337633238663736616465613235666531656337646464333532 +31303763346562646262656463376634353563386330643231623830353763666138646638363937 +37373465386264383737313232363263333330626234393237306439303066306563323532393539 +35346338643664393333323830616466373362663261313838323833393662316437626364643739 +66396662383565323533373730313665363832333537303734343638616337626261646633313866 +66353732343865633131336336656130303231316336373865396663356266386133633534353766 +65303135643866373961636135646136656136303234313337373766393964313430623032353431 +39376139356664666562643033323865323966343263343234663437643632376133623735393730 +36336262333138333962326663353836613532633365356230303837383731363131343139376563 +37346138363138393062343666623262383062643234626362623738383965373166343230663339 +62336331616663623665343239633466373839386566336631373139643732393734633562343933 +31343564383739626139323764663536366230373034626464363933313137313636623836353437 +35653232333939646233313462666165303537363136653038626234343138396136343339643464 +66356433396238326538386137373638663932636662633965353935653162616333386539366635 +30633465396264653237643135363663346562646132663030326234626131643465623638356536 +66386335376537653434336463623338613835306532323230333135343464343435383033626531 +38323465363634356162336437333637336433643865386662396130663036636634643738396566 +39366463363339646335346364336233313931363065643133373937386265656432313165366534 +38346335656231336232613464333337323163316334373732333363386134393432303939306565 +62656139626536363866346430373363346235346665666231633939376638663533353833343362 +35396339306266363130313966393333646630623537346234383835343866306564356434656664 +61386435306433373062333966643164323439666433326436353630646339393734306263633537 +31323966323634666333633030396432383335663333643134353231383734373961306134376431 +31613634633836313666656663643364356431363065626130323135383766613538393535336266 +37366263393333366432663131636231326631373732643566636334663931616561663630346338 +30646533383465316134633137633333396362653663383230636137623736313935613238386264 +38653063646466653464646334393233653732316537643333393138353330323563626661383831 +32363932343032303131626661353666623839376137306633613130373732326434323334323239 +32623139663432626666646162353731613763616133613833333036373731323064386436663031 +62666166356538653135316635666631613335336331656262633239636665626264306465356637 +64376364363632636137656561326539373038353161306430383137356132313138343231333932 +38333636663339643438643338656530333036363162623536396633346665386230646631346663 +63346338653539303236633438623366376237613463393835326337346135613961343861646465 +30623237373438613835626336663031653234363338666661346436366166333966343635396239 +65626362336564376366353739313465323034346165313439656333363230613032616531323439 +30656431336432386363356430383665366166306237626136353430386266323333663663396262 +62323634343261633737323430306566646130663264316262393061666635333261633039323132 +64623265343634306130616565633439303131343065343861653764396266643632646662326466 +39663262353062663462393864616633303035306234643934383034646331613935383562386433 +63623366303564366339376165656233366235343762303833623266313734653465303138363832 +64323434663035633932343738306163396434373539316630666230656333353736326165343663 +35326536366264386237633263393639613731666137363066316239316336363031333335303733 +39653434633563376338333735353631623433396531326334393366376135323035653930376263 +39666466336465663936613333646466633134333165356261333839346632386265336535383836 +66333137333032616565636166616635326633343362366539386138346361306663333164383265 +63663430396139303532643838663165643430646138633866613337393136306361323661326430 +33303464363033353139643439373066613832623936303764313266356632353537383833353464 +62393834306165653139653464613935646166353161623437613965643564346134306238396564 +37626461363833643637656566626163633266376663616530613231343539336135626332326631 +39643734336230393530623339396235613265333731323438636435363936633939333836393538 +63323232373561356236343938363733653866323337613034646233343837373737313530386338 +39656565323066633561646266663337616230623461366131663638303564643630323739353734 +39386664326461373932656564646134323134636639313161393061346430306233633637346533 +35333631383735343236653533653936646632363935663237343833316432343465653463333662 +30623266323964646132656538373334656564366462633561663936633364346432323765323530 +61376632363130326336656462616331353135333636666432333931333362616535373633653037 +65623665313238626437613837643866303539626234336165353236383663663638373763353139 +32333032626564363461626162313133313734353035616331333061353761646633613135363061 +61663463356466623864373735366564346635616236306139383230633535393863663035626332 +34306339316464383933393465313964323933353033623262353436643163393365623035396331 +30333965363839323364643539626435376430613637313062653864656433336561383565366339 +61326538653735383561313033356366386563323766656163616433313935623539323638366262 +63633338323738663339363766353637363834306366313637323764363036306261366134653263 +61316261346639336263376238323034356634646330333862646534363961323165623663656431 +37313661616362616533303435353532646334623864346434353466626265356333393030383234 +36363130356332346434323234626164613138633034663132313739623231333464643363363162 +61396437316132366663633030376636383934356165303033353536383333633530656335666665 +30373661373539623766636230663965376533343934336532353761313334383136316434653931 +65376666356464643561323562313462323161303737356430306536303764653434326633393163 +61396663633036623238663832383634393163306635613733303737353235393365613738656133 +35366630316566323635326262613236363234393334613835643833343831633739343862346232 +30323039353266326331333735306131363563336230373063353235653231373235643536313838 +31313839633230346565656333386638313434383732383861636335343065393262616637663238 +61353861373865333766363361666433316538613665633262333364303962343437653235626266 +61616431653939626162663031623063376239316133393563353532363339613461396537353232 +35303236633664613863373031366436356133636537393534643931336139663039643737313836 +32323463653836626164643861366439336462643538303330373832343165643261353361313931 +64366232643962363035393634303438303665343030623030366633323631643466353934663664 +31643166646438643664663334643364343631356231643532636538303530326136623666623336 +33303131343832626538386563333435656266666466363432663032626535313338383835353633 +61356533633463313564323831323436303333396134386464613563393133353736613565356437 +61613531656330343634646336653062323965386365316536303835386561356136656565346532 +33383132656535306530613566656339616238393363313263303333653664613830313161363037 +37613263663630333466333834363261636139633234393365363462306632363162313462353639 +39633834356537346634393137306134323338393665666166643661613431313339393336353563 +65393333393138653937316131626635653365653265346161323038376638336235323065643463 +64616538376662613230393135356536333539663834656666323338626137626233386264343830 +38336136663062663866623036633237666435336461386364376133616530306664306632653836 +35653464616636633933343261633730633337343731623131343064353934303761356563333562 +37323739316132336434386636613363326462323934633365643331303134303837353839373939 +34613036323038616339343235326266623563616337633865396266623139626233303338323737 +34663063626637626665306530613066666561393736366137643265366631613861643334343931 +35653438636365336133323037303662333337666466393563646664393137636164653064653761 +61643635353666653839396238353435373565643862303266653030373730343238363339346132 +33636232376664306263313232373639393131623435616539643665396462373232363032626565 +64366431393061363333343830313133343531336263363764653062383337323638383639313761 +61636661613732343432343839616463346236363164313063646662626436306231343163643733 +35613237376165663462326337353164346562653337616164663132366433636365643635643466 +39343035633132653130353061633139353432356630623663343665393765386563386430623061 +31653061613439363732393439666230643363383037316232393865383035323034623530346437 +35316433346433383532333964333030353466323734393761383266346630323362633362323963 +31333436376332663362353939653361316436303163376165633763303232383534626137336131 +35666331653631316338363634353639383239313931396530656536613335393234663433386430 +33663962306534346236343339343333613362323534326135633135306261326630316332376633 +65376366643262633031346266376165633431623737363931313232316631356334663964626632 +61646632626238333139313439346439326430353039643331663839346564396335643661383633 +31313936626561353133636565383564656363393461343538616633326434373531643835613537 +63613366336265373032663165613362316266643832646238376130343135393364353466343037 +34633938383563306636356161363831333531333866616264366336313232313737656665353032 +31666338386330656136323930383366623266383961303163373639316634386136366432303938 +36666537643539366535313563366136666339323264306333383761333431343331353430623330 +66656635353237633631396232633864613535333337613733626163363234306532353731323138 +38303337303566306464306435393833383330373662656337646130633462303566613865356662 +65646331343063303465383237313036303333363831373063353938336531623033316161653832 +39343162633661326462323238313433383130316539353234666463633430383461393562646234 +63366639323761306665613566656134316463636437363764316365666162363265366632373336 +65363863626566303834376538623232323331353864633536653566636662346362353233303234 +30636265323931363437356163653763656232313066366363633335333632653763663438336663 +36383764646133316335616439663931303865653663366365376565353336313162336661623937 +33613430313337633934373965366131373930386562393039376663643934333138333437316365 +34323836613037366436353662383637303534356164633266313235333465393839386463383831 +31393063663237376134346162353032623835303931616232616266343838326666643137356661 +31613435393536386164383765303666663163633664393331613061383362613231663039616664 +36643365346566626564616234303362663636366663656435333935346435363064303635663934 +36613130633237356433653035623865653036636663323136613333396536363264333666336338 +31396339313930336537376561663936353230363038316663666137393064323135346631393838 +63326564376233323336333536376339306230353630633562313639326238616138626630313564 +65613335636135386333366364303631393765346261323634633635323864393238346231346530 +65323965396231666662323330613361303866323562373636653965316330663063383034353466 +61323463623866333333623863616536313430333238396537306263313334633930643231656461 +63323565623661633536336335333239613765633237616339363036633639356434393230333463 +34643766333231343765333262666339323931376363373131313837383733626462393433383639 +37376439393034323138396137363230366466633031313962363964303931363139383335616263 +36303563376564663566663962356466346435623666386538313065616164353133346432643163 +39343162313034626332653635336666623963633334623739353164373135366335376666396237 +39393863653930313932616430323361633432613164646135343731643661346365373262363533 +38386666353866626231306662373938653435626532653633363234393838363039373532623466 +61353632313639616265623561393962646662396436356530613962376665346261363138653735 +66646539643461373137303632383837613463376164373665663637316231646234613064373635 +31326261366462323038373761666139613532643362616432383836613637616235363930323963 +62343761626163396566353236323535306432633232363236363931326465386362653831303066 +64306365356330346539663265356432336564623665366562313637386163306166646665363531 +31643235373034613335613837356663666437363134656630653062313131643736393834393662 +38386532663266626663646636616136346232363635323830373332656633346261393564653162 +33613537313734303362643466343530393933363230386563663265343635303635656262653931 +37653638326161626332366232323336316132313963343563303431373139323937613231316330 +32393938376464303031323966643462646536653537363731613166306564613731653530333231 +64326534613364646233376163666166343633333838363865376630353131303938383161616661 +61343962353236343033646434316365653261353366353263333662376239396138343537663165 +63646336386633363264393164336463356261383166383264633739303337386365613463663030 +61303131646434633237353962626238356636323339363938303531623933343764663436316538 +38383735613839633733323730306136643661653266396635666337393966646561633637363661 +63623763356235663134656635663666613435353837393733313735636562313431623966313435 +31636534643931323039366134623034616661623564313338656162323164323938303537623065 +36373665313735633665613661323834336365363664356661346633383939633066313061396663 +64656231633736666138373861353336343361656161326662306235323634616136663838346131 +61663363656130316165353265323431313064336561333639323832666564346532653437326263 +34653761376137366338346239623765386661613931363434306362333361393331373165393662 +62386364323431633830363061316631386465346261613733663363313030313734376636623835 +37303439373939383166613731646135626235666234626331633364366239353262316630376165 +62303061383034326433386238616638343836396438363263376632383366653662663930666165 +30306432346432666636623165643230643430613565333636376631626531326662333063663235 +34626463393338616637383531303036636463323038376266323938656233393933353535383637 +63656263656436633061336161316661353734313663653637333864303638643536356130396265 +32336564636463363930653135353130666235613134376632333061323135613439643762313762 +36613461323763306634306339343336323139303632343537383730386664363161356538396335 +35633734393363383563626261393634363637623037646535616630343838663230376538663662 +39353434343730663336616339366135326132653163366437393562656334313162376434656536 +37333966333339643964666433633164363662336365633537353763643439333433633130386233 +63313233633736653834353932323963653536656664323639373663663235353233653337356235 +64646437326361356238666130626264356236656637386661656161663139316431386336303234 +32343965656235346133613665343236336161353030643566356139363166663363343265653439 +36356531336531333632643532313461313863636562656633626634393936663234396432336365 +61363833353335373932353335646636313564663833656132323631383531326334356633663662 +37396639336535633138646134363030353436393336336238373436656665393135373666343633 +66653738393661613461623265633762353662393165616162613062346334613766383864613232 +33376238393662303065356662323237323038653637323962303730353638663438643130313938 +63343535323762386164326137373535643366663133363939663466633861626631653932633263 +63366536343332643432306337613337613265663063356631663430306265343134623561393530 +36376362663462323330313961376533393063613032626337333831346265653536633639313262 +31666533643333643363396462353737623661663333303465656232323734353731663635366534 +37353134663037313530316366366263653066626231343665316334386465373965363635383430 +30313836383934306333626337333938616533643165373639373834626134313737383238363830 +32356165636639396130373562623637623838326339633236363334306539616264626562363661 +34326636646364343534656362313136616639326364373537383665336363333131646233393564 +34353865313338363632643939656430366466343032663034366534373831366535363664343233 +62633662376365623038633865643534353239313063383039396637323934326136373639383335 +63643232313362323737326663623930373331653566333361383736383966623435653736316239 +64613730653139316264393432626561633939383931346232623362383136623037396336316436 +62343665393364643030643233643231313763636137363836303539373564663834353162316562 +61306261633163636361316536306236396536646635356465363665373634633734336265353033 +36646562373737666131353335313033623632636437346236303736363137303131613265363266 +66633864323031396331613330633533383436323930396164303933666133316639656233633664 +32333663313261393462653436616530383661383931386662303563303865613365623039393864 +30303661393937306366663234643632346535386638383239333433323262323337306131316538 +61353761653031633733356535653363323933323339633331613736643833346263623139326436 +62343265303935303133373961316230633964336339623135313962373534653536366438393961 +36373636626536356531346532306636313037666564386137326539373536356466613865636139 +32383137333235663939353261383838643264623565633761363039623963366333393936323665 +61656533393365373763323537636264343333396430613562343263353630323832363539303061 +39643863373961616231666439616531346534393362336230626234626536653864343265653031 +39373533643366653436376137326537326433393166646634306539656662663430656130353337 +39393334303532383838393461613537643938346332616439626163353634636462356235633562 +61336137656531636636386130376361636137636134336534333166613464393663653563393465 +63616435646661383430346335363337316663643236373832653639353939303661326437623165 +37626436343935383466353533373630313538323562393633336638663838336234343533346461 +32643937376135366133643138663363353239666463333562366235326232383464323436653133 +64643765323934393833663633656534633566396666626433383837353234653061356133626366 +36623937356237643762343865333163643762613563316166393965323536396633656133303336 +61336435626163663639613934656165393732353762616331333032393561623335383631313062 +37386534373637346637383039663533316333626533333638333435333465333834353731643034 +62383335636463393565396435393334663638363637333561336432636362346465356336316538 +65393536616362383766663765343463363636323534633734663738663035663161376431326465 +33663466383637333061366139396634316531323465376561306637303562623031363366633063 +62366564336334623066376138373835653638323566313061336332356136373537646633646439 +31353764643832333361323565666535323239313962326463396265373361336164343430363831 +63313961616134383765663534303238336533616538616238386235353635336365306261646334 +32363666643632636665383333653263663565326238333266366138663564343437363363643266 +31316333313464353934616565383435393136383466356435316138373437393531633964636564 +66363834373662353962313835653533636236623263383063663838633365393936323933646536 +34656261353964613930623861623239336235393162386230316239323832333237633834353261 +31653966303465353764393031636465643331343163663439353539323562376238326532646139 +63656134653361303933363364646238326365663331626335346634353963366662656232383861 +33623766623261323666636435623336343831356261393230623736323662336237653561616134 +66366438626564663434616263386238313432316234393834626262613961373865356231333161 +39343636326661373265376436313833306163663934623034303136636136303034346332646434 +34633765333631653935626566653638356363343932386533313531623164386566353634646161 +33623138623161653963663530373966303734313939376565373130383231393935366462373132 +38656265646235356237623963646233656161666634366231656434393338616538613539363437 +36363266393430396233623463633038623537333434373239306330366565343937656562646538 +61323536363635383639353530623136343365353639663961343263663834326363383439346631 +62653536386630656363393238366366356631633535333534636565366136333862313131363365 +33633130613931313937323862306534393334616239653463303663616465383734653932363238 +62623861633665363633306562333862663238386565363564666137343866383835313631383139 +38313837366632316462376633343031323330633031353562646638393438333861363931346262 +65303033356637663332623438366634613663623561323334633563633366333735316238663964 +35626162343766643834633133376133646262343934653835633231396563656564346536656364 +38623866303463396664323637363036663866623738666466613463616565623165313461653231 +38623365666432376637383632376630626266376230653330323932616334323564303964336630 +38613064616231343537633264636137363339666237373739343833666231663230303636346564 +65383863386166366133336464643737633336313462393165396539343135306333353666373337 +35303732346363393766303437656436623464376431363332323461623736373164623737616232 +61343766653833336630326332313363626239626536633736643632323437346561646538313830 +61646662333866373934656165653933306266356662366563306265323930333166383634396262 +31663330643663656536363435336565323330613365613237336339373765343037326531376634 +31353933626534323764633131386164393434303264613238626161373730643537306138363266 +65333963393435303463623137613631303363353761383863303936613162643561663137353535 +38326437323462316630383265336232336365633430383639613766626332363831326537383064 +39353761343761333032393764313766663337383864386462366164303834636236333832663533 +32646237613761656439623434323261643962643635346335633238353565313036353464326661 +64663234313165336639646161343230323133353631383165396262393234303332313136666430 +33343732366235626666373830393266326132303436623134623930646661383130323362636337 +62326436346336633230356537333734373362353364623236653732653736383963653136623563 +62333432313563363439386132303232363839653861366632633031343733366132306564383039 +33623036316665336234303434376239316231313065643061386533633435626633626265633965 +35633533383034653562356438376530316336353336396134643261383733333565626332663661 +63653563373138363734323733333436613134623963323964346239343436323633623766633333 +61323962646166366432616137653639623532333563323536303164656664646161333930666664 +31346433323064376165383137633431623566646664396232653965623235376638383438306237 +32313031656364333531343733636637326531386230653435636266633231343237333432316334 +33383836353035383166646462633364633964623162616639333633303536356664373065656438 +30643436626230366634363839386131636630373439623666356538353733376466303332643764 +64333264376130396634333363386132643839323366323135643131316136383132356638323563 +36353063393231396636383131616334663661646537646635646639306637626464623932386162 +36326666376430373561363639343735346166343365353032653030653438393836336439383831 +64343564316139363233303930626138393536633735653464353338383738636235396131633030 +61306562633634313038323239623339326233363135656135353136323039343930663130633762 +32313362373835373465353266636637313861613539633362643735306539316133656564326439 +35616333646437656532383664613133333732626531356664663964643832363139653335633230 +32636439393032373162623163666331336166323335663738663463363736623132313333353333 +30386538633138666461633064303536346530616435666431343437333833343833333566656263 +62333266613965633761613435373639376137376531343766646639396463393834393433313932 +35356436616162366338643665386562623435663864653731633161623936356462346133383338 +30323433366164336664326461656132303233666162313465343737346337643039626535363637 +35313866303639663833363364623564613862626165356239396232643962346563333435316230 +33613264336664363934653239633439376361376234393239383565376536306261313237663162 +31653162623936643630633635373064326333313834396130383330633436613562306361303166 +64353637303439303463643134653464666238343264356332336436656532313632636131353535 +36393161376233663338333166626532636637373536323233653161613230616262366235623665 +34363865386265616134616139636664306633623030653330643366383133303265643938653734 +39353465636462623737623462653733613330303437343865383130356163396662316634396137 +63336563353332646435356166653561343436613164376364333964636465313739653638343064 +34373634316231396565633033393838386335613665633662376362313032633935323238356332 +36633065356462363163326132626661396263376635333236663234303433306133653739663437 +64353733373737643832393534333135343031303131653231323062663032383261643832313539 +39343066646432346232326661373637386265663263333937306139633165373530663938303135 +34326538323131353035663239363365666639623861666335663162343863646337323662393465 +39363538646364353234616539326139623037643566323038316330356161396235363239383766 +30663836393139356632333366316237643163623961303635343530376334613733626661326463 +39636631383335616361343661346465666335356461643431346363363335646631313530313266 +61613331373962353861343163656338653066306562323662303465313834366465366563366431 +35623935623032666362373962353233623830306534363031633330343365653037373661663961 +35326633366638356562663565353461646364396263666537333362373661343063323338376635 +36653963303461656236653733353730623832376532653736336364306365623733663936346338 +32623464656233626237353564636336356331663866306336393866356534323434356463613530 +61336237346531633161663730333533343961393131353066646432613237333036623662643032 +32303165366338626439646438613135643437353238613134396134396162313264383134623734 +34393461366336366634373863643737326337366438333732333531333032386665373132316565 +32643862663437336337336431323363336366386239613834303530366532383732643631333836 +32626439343433623737353666333737646132623064633030346365383930326630653863643162 +65656531326132636539613866653834363963626435343435366535643135386366323033666435 +64366238353865336237393832353537613066656662303930376231643064333263313833393937 +62643362303036356433633237363839386638613062326262346563323734663863376334623933 +34656266623532633137396534626664336661336436313434623637323438393061343437633961 +34333538663835643565383763663439363034316661303063636534336664316366316131343030 +62316263646238613062333165353464306138653833646632353633373564383832613465346262 +61623361633438396362333933643766306136353534363365356262633238346535366265343232 +35373833313939306234656236353233326235643966633930363263613764363835333435633764 +30356336643537333136333636626162626366333937343831386230393630363533346336653731 +61663162653863343562393531333438363130333966366635326665313966356238333264353338 +37346334623337616431333661373937393432363831336131313032646664653066336230303733 +32333664636261356635306365666331303164336364313935353161663632613035356661323435 +39343466633730643938623566623830646138616232343130323438353061356530383933306661 +63646138363832323334346534346463633161663236373763343366336336353038383839613166 +33613333393938666461353332333364393461663939623030633033346161636332343630326132 +38386438313864646536616630393237663930376634663535363538633766323563613832356335 +65376165666230653138666239656434633535373530313766393066313438303563383439313663 +32393965333964303638336134656236376332383439383338376633353365616239363137353161 +36306337356237396338346337303237643238613963353262636436326266363437386364396338 +31613937386664383932343332653337663139623561376363303436646436383532393832333861 +37343732346535663134316631303264346662326139333132373364643364323139323836376464 +63346137646439363437376130376263646363626637313265346466363732353262623030633030 +39386131633433303637353537636234666535613238346431316331303836316661363934626230 +66343637623931636263353737386662383166333834366135336235663762383834663663363034 +38363261636538333436633462313738623331376564356631343436353364373735353731626134 +66333432633839653764653966333836393235373039343161353031613639376634373237303266 +61633634643733326535373665623435663734373436313061393062653039353633323865613931 +31393433663366323839633531646664373933316634636430356531336662306232666435633566 +34643230383231653134366562303438663361636438633663623462343061623633376163636335 +66663431323031643731336439316164316364326135336161336633333364356531633830346365 +36363635353539396435646130366339623462363030636264303937353735333331393565313834 +35363833633262616562313139373933353332323133396237356363323532373162663638303466 +62333032323331353232353139383666353632333138363237373365313164646162333539343832 +63336232313566393136383863613765313663376631323736386134623963643131316337383365 +66353334306430616562306161376239353361366239323738386361363633353862373365316437 +39313031333932333766636134393262613839346331663138643931363861653533333533373263 +31633565623738303537396363333432636233623030336334663031663438363633636232663335 +36353932386332343535633136613636643638356462366238393762353366376264303533346133 +64663730333763336235646463653137373739636230643932346165663663303031323331303936 +63306538303261386262343064623665313031666433346238336232326432366637393264616631 +32303130643631336362653033366165393630306165646166663337316333393066626632356164 +37303266363132356337646131383863363133353335646238646233376338383430646132626636 +34376336323533373161663561346632336333653337323164363034376464353134653339346465 +61303136656661386661636563656438323035383565393563626534313536366461656331366363 +37303835333031333732393435316461353433633532366236633734643636643163656531346435 +31326635656437383763363865636438383133356438316136323336623439323034343736333738 +31323637326663613264643033333464623934613138343536363863303565326661636563313435 +65643761306434356534386562353564636262643532633633393233656636343561306463333836 +38316666653138313634616339323836343961316639343835356331366533666634363465366238 +37366330336531343165363032656465343830363536336566306235323639313936613838316231 +64643662656563343432393535333632323832623538643662636534363835643566656230313238 +35303538386362306430373366313731623464633737383433666233343638313439323537626163 +31346331373561616137633837626338353063666132626236303262393337663261646530666336 +33663231316432663138633439363935396264616330386336613765346131396638646434653531 +65323136373965643966373264333437616432613666323162313838333739633933623761613463 +65353134613231373730326636306365623765326466363833663765363834373465356461333537 +36346336383332666365336433313634303839383833323562626364316137333266666438313661 +61343965343365326539336235643763353231323532653032616263656134626462313730396532 +38313162313933666233346164393733313338646339323031383733643266613366643566363961 +62383235393036623338336465336236363234386366663166363136393963383163373934643862 +61663031626639303434326532366261666534626331383232646265333633643865383437353838 +65313930353931363132613138373930346637373639366232626434393734303535303937376564 +36636137613431313432663563386230623966643763366635636437366431616363383364383930 +37666434373765616231333962333431313731376435333061383038363732373265303664363363 +39636534663564636565353239636364336537633334646539393333633263386363333965636430 +36626166356335303734383765346662373333316636333935636662636432346433616235323738 +39363464666334336131383733633935616437396235663132333231346636323130663162356361 +66323564383132393831383163316535356336386464366264313435346437386131316166646262 +31663639613462373137353731623137643863663363393438626464303365356435373132646265 +65386231643034623134333366306261376266316131376663383864333662366364346465396332 +37386166376630373765376261663738313662656639623938346230613733613565383033363831 +32386535333335323562373536343333363833346132616136313135393531643362306565643135 +33353930336365393234363838356136363330366633393339343964613431343833616431376538 +37616662613234356634643634616439663763313238396130643234313638656633633030373164 +36326564663630353232343766303730393039356664353338376331376665346334653835306533 +63396333323465346235366235613166663939316433643562616264326137303834323437653062 +32373535363062313838306131353934323039386235623233396163386434643235346434336131 +61386639666362613137356538373964356137386663656633303237396331653537353630393162 +37393239316661663966636538353438386265356634666431646363343461333138653031333431 +35303336353335306136653463636234663063313631623938363966646662663831373432636434 +66393861313731383739376363656237363034636134316162343266323130306133363563303935 +31366639626339633361336362666435616130336538633531333739383561613538633734613436 +36333736653133343034323831653833623465346166656233656266323631313738366563616165 +38633133303433376365316261316535303130343739613830646534616338376437356130396632 +64623636373834626435 diff --git a/lmn-client.yml b/lmn-client.yml index 5584d6e..4a2fab7 100644 --- a/lmn-client.yml +++ b/lmn-client.yml @@ -49,6 +49,7 @@ - lmn_network - role: up2date_debian tags: upgrade + - lmn_encrypt - lmn_sssd - lmn_mount - lmn_kde @@ -63,7 +64,7 @@ - role: lmn_localhome when: localhome - role: lmn_localuser - when: localuser + when: localuser|bool - role: lmn_exam when: exam_mode - role: lmn_wlan @@ -80,15 +81,17 @@ loop_var: rolename when: custom_roles is defined - - name: Final tasks - ansible.builtin.include_role: - name: "{{ role }}" - loop_control: - loop_var: role - loop: - - lmn_security - - lmn_finish - - lmn_tmpfixes + - name: Import role security + ansible.builtin.import_role: + name: lmn_security + + - name: Import role finish + ansible.builtin.import_role: + name: lmn_finish + + - name: Import role tmpfixes + ansible.builtin.import_role: + name: lmn_tmpfixes - name: Apply roles that must run serial diff --git a/lmn-vault b/lmn-vault deleted file mode 100644 index 01cc8c1..0000000 --- a/lmn-vault +++ /dev/null @@ -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 diff --git a/misc/preseed.cfg b/misc/preseed.cfg index 09c6cfe..2cbe370 100644 --- a/misc/preseed.cfg +++ b/misc/preseed.cfg @@ -50,13 +50,11 @@ d-i apt-setup/contrib boolean true d-i mirror/country string manual d-i mirror/http/hostname string deb.debian.org d-i mirror/http/directory string /debian -#d-i mirror/http/proxy string http://10.167.0.253:3142/ -#d-i mirror/http/proxy string http://192.168.1.17:3142/ -#d-i mirror/http/proxy string http://aptcache.steinbeisschule-reutlingen.de:3142/ -d-i mirror/http/proxy string http://aptcache.pn.steinbeis.schule:3142/ +#d-i mirror/http/proxy string http://aptcache.pn.steinbeis.schule:3142/ +d-i mirror/http/proxy string # 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: #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 ; \ echo "$vaultpw" > /target/dev/shm/vaultpw ; \ in-target ansible-pull --verbose --purge --extra-vars="run_in_installer=true" \ - -l localhost \ - -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C fvs $playbook ; \ + --vault-password-file /dev/shm/vaultpw -l localhost \ + -i inventory-sample.yml --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main $playbook ; \ fi -## --vault-password-file /dev/shm/vaultpw -l localhost \ # ## When installing in combination with ansible-pull, ## export your ansible playbook like: diff --git a/misc/vm/Netzlaufwerke neu verbinden.lnk b/misc/vm/Netzlaufwerke neu verbinden.lnk new file mode 100755 index 0000000..e2fe26b Binary files /dev/null and b/misc/vm/Netzlaufwerke neu verbinden.lnk differ diff --git a/misc/vm/injector.ps1 b/misc/vm/injector.ps1 new file mode 100644 index 0000000..4c785cf --- /dev/null +++ b/misc/vm/injector.ps1 @@ -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 diff --git a/misc/vm/vm-prepare-sys.ps1 b/misc/vm/vm-prepare-sys.ps1 new file mode 100644 index 0000000..ad8f16f --- /dev/null +++ b/misc/vm/vm-prepare-sys.ps1 @@ -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" + } +} diff --git a/misc/vm/vm-prepare-sys.xml b/misc/vm/vm-prepare-sys.xml new file mode 100755 index 0000000..b00a30e Binary files /dev/null and b/misc/vm/vm-prepare-sys.xml differ diff --git a/misc/vm/vm-prepare-user.ps1 b/misc/vm/vm-prepare-user.ps1 new file mode 100644 index 0000000..15b540a --- /dev/null +++ b/misc/vm/vm-prepare-user.ps1 @@ -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 +} diff --git a/misc/vm/vm-prepare-user.xml b/misc/vm/vm-prepare-user.xml new file mode 100755 index 0000000..f3f8854 Binary files /dev/null and b/misc/vm/vm-prepare-user.xml differ diff --git a/misc/vm/vm-update-user.ps1 b/misc/vm/vm-update-user.ps1 new file mode 100644 index 0000000..c3036d5 --- /dev/null +++ b/misc/vm/vm-update-user.ps1 @@ -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 diff --git a/misc/vm/vm-update-user.xml b/misc/vm/vm-update-user.xml new file mode 100755 index 0000000..b6500e8 Binary files /dev/null and b/misc/vm/vm-update-user.xml differ diff --git a/roles/custom/fvs/files/lmn-codeblocks.sh b/roles/custom/fvs/files/lmn-codeblocks.sh new file mode 100644 index 0000000..27f24b3 --- /dev/null +++ b/roles/custom/fvs/files/lmn-codeblocks.sh @@ -0,0 +1,15 @@ +if [[ "$UID" -gt 10000 ]] && [[ ! -f ~/.config/codeblocks/default.conf ]] ; then + mkdir -p ~/.config/codeblocks + cat < ~/.config/codeblocks/default.conf + + + + + + + + + + +EOF +fi diff --git a/roles/custom/fvs/files/lmn-patch-dolphin.sh b/roles/custom/fvs/files/lmn-patch-dolphin.sh index 60707c8..ca7efc6 100755 --- a/roles/custom/fvs/files/lmn-patch-dolphin.sh +++ b/roles/custom/fvs/files/lmn-patch-dolphin.sh @@ -16,11 +16,16 @@ fi id="$(grep ID "$file" | sed -E "s|^.+ID>([[:digit:]]+)/([[:digit:]]+) -+ Nextcloud -+ -+ -+ -+ -+ -+ $IDENTITY/${NUM3} -+ true -+ -+ + Network diff --git a/roles/custom/fvs/files/lmn-sync b/roles/custom/fvs/files/lmn-sync index 16668f8..6ae5e17 100644 --- a/roles/custom/fvs/files/lmn-sync +++ b/roles/custom/fvs/files/lmn-sync @@ -12,7 +12,7 @@ fi #rsync -rlptD --chown=pgmadmin:root --chmod=F755,D755 rsync://server:/local-program/ /usr/local/lmn RSYNC_COMMAND=$(rsync -ai --delete --exclude=mimeinfo.cache \ - --chown=root:root --chmod=F644,D755 "rsync://server:/desktopstarter" \ + --chown=root:root --chmod=F644,D755 "rsync://fileserver:/desktopstarter" \ /usr/local/share/applications/ | sed '/ \.\//d') if [[ $? -eq 0 ]] && [[ -n "${RSYNC_COMMAND}" ]]; then echo "${RSYNC_COMMAND}" diff --git a/roles/custom/fvs/files/policies.json b/roles/custom/fvs/files/policies.json index 1fd5fb0..b1c20cc 100644 --- a/roles/custom/fvs/files/policies.json +++ b/roles/custom/fvs/files/policies.json @@ -3,9 +3,9 @@ "Proxy": { "Mode": "autoDetect" }, - "OverrideFirstRunPage": "https://www.steinbeisschule-reutlingen.de", + "OverrideFirstRunPage": "https://www.steinbeis.schule", "Homepage": { - "URL": "https://www.steinbeisschule-reutlingen.de", + "URL": "https://www.steinbeis.schule", "Locked": false, "StartPage": "previous-session" }, @@ -15,7 +15,7 @@ "toplevel_name": "FvS-Reutlingen" }, { - "url": "https://www.steinbeisschule-reutlingen.de", + "url": "https://www.steinbeis.schule", "name": "FvS-Homepage" }, { @@ -27,7 +27,7 @@ "name": "FvS-eMail" }, { - "url": "https://dw.steinbeis.schule", + "url": "https://info.steinbeis.schule", "name": "FvS-Hilfesystem" }, { @@ -35,15 +35,23 @@ "name": "FvS-Moodle" }, { - "url": "https://nc.steinbeis.schule", - "name": "FvS-Nextcloud" + "url": "https://cloud.steinbeis.schule", + "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", "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" }, { diff --git a/roles/custom/fvs/tasks/main.yml b/roles/custom/fvs/tasks/main.yml index 738b4fe..2248651 100644 --- a/roles/custom/fvs/tasks/main.yml +++ b/roles/custom/fvs/tasks/main.yml @@ -29,7 +29,6 @@ - elpa-magit - emacs - filezilla - - freeplane - git - git-cola - gitg @@ -46,6 +45,7 @@ - libasound2-dev - libdbus-glib-1-2 ## needed for zotero - libnotify-bin ## needed for pwroff script + - libsqlite3-dev - libwayland-dev - libxcursor-dev - libxi-dev @@ -62,10 +62,13 @@ - okular-extra-backends ## needed for CHM files - pdf-presenter-console - php-cli + - php-sqlite3 - pipx - planner - pulseview + - python3-legacy-cgi - python3-paho-mqtt + - python3-pgzero - python3-websockets - qpdfview - shellcheck @@ -82,7 +85,7 @@ - unison-gtk - w3m - wireshark - - zulucrypt-gui + # - zulucrypt-gui ## no longer in trixie autoremove: true state: latest environment: @@ -155,6 +158,11 @@ dest: /etc/profile.d/ 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 ansible.builtin.copy: @@ -162,6 +170,16 @@ dest: /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/fvs-config.js 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 ansible.builtin.blockinfile: @@ -170,13 +188,22 @@ mode: '0644' block: | [KDE] - SingleClick=false + #SingleClick=false [KDE Action Restrictions][$i] action/start_new_session=false - #action/switch_user=false + action/switch_user=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 ansible.builtin.copy: dest: /etc/xdg/ksmserverrc @@ -220,7 +247,7 @@ ansible.builtin.blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml marker: // {mark} ANSIBLE MANAGED BLOCK - insertbefore: '\s+//Footer' + insertbefore: '^}$' block: | Text { id: hostname @@ -249,5 +276,12 @@ KERNEL=="mmcblk[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", GROUP="domain users" +- name: 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 ansible.builtin.include_tasks: sync.yml diff --git a/roles/lmn_encrypt/defaults/main.yml b/roles/lmn_encrypt/defaults/main.yml new file mode 100644 index 0000000..b9b7837 --- /dev/null +++ b/roles/lmn_encrypt/defaults/main.yml @@ -0,0 +1,3 @@ +--- +encrypt_passphrase_initial: Muster! +encrypt_tpm2: false diff --git a/roles/lmn_encrypt/handlers/main.yml b/roles/lmn_encrypt/handlers/main.yml new file mode 100644 index 0000000..0ef929f --- /dev/null +++ b/roles/lmn_encrypt/handlers/main.yml @@ -0,0 +1,5 @@ +- name: Run update-grub + ansible.builtin.command: update-grub + +- name: Run update-dracut + ansible.builtin.command: dracut -f diff --git a/roles/lmn_encrypt/tasks/main.yml b/roles/lmn_encrypt/tasks/main.yml new file mode 100644 index 0000000..6c81e7b --- /dev/null +++ b/roles/lmn_encrypt/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- name: Find device with LUKS holder + vars: + partitions: "{{ item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') }}" + ansible.builtin.set_fact: + encrypt_device: "/dev/disk/by-id/{{ partitions[0].value.links.ids[0] }}" + when: + - item.value.partitions is defined + - item.value.partitions | dict2items | length > 0 + - item.value.partitions | dict2items | selectattr('value.holders', 'search', 'luks|crypt') | length > 0 + loop: "{{ ansible_devices | dict2items }}" + +- name: Get luks slots + ansible.builtin.command: + cmd: "systemd-cryptenroll {{ encrypt_device }}" + register: encrypt_slots_result + changed_when: false + when: encrypt_device is defined + +- name: Change Password of Luks password slot + ansible.builtin.command: + cmd: > + systemd-run -P --wait + -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase_initial }} + -p SetCredential=cryptenroll.new-passphrase:{{ encrypt_passphrase }} + systemd-cryptenroll --password {{ encrypt_device }} --wipe-slot=password + no_log: true + when: + - encrypt_device is defined + - encrypt_passphrase is defined + - encrypt_slots_result.stdout_lines | length == 2 + - encrypt_slots_result.stdout_lines[1].startswith(' 0') + +- name: TPM Device Check + ansible.builtin.stat: + path: /dev/tpm0 + register: tpm_device + when: encrypt_device is defined + +- name: Include TPM2 role + ansible.builtin.include_tasks: + file: tpm2.yml + when: + - encrypt_device is defined + - encrypt_tpm2 + - tpm_device.stat.exists diff --git a/roles/lmn_encrypt/tasks/tpm2.yml b/roles/lmn_encrypt/tasks/tpm2.yml new file mode 100644 index 0000000..432ce2f --- /dev/null +++ b/roles/lmn_encrypt/tasks/tpm2.yml @@ -0,0 +1,42 @@ +--- +- name: Install tpm2-tools and dracut + ansible.builtin.apt: + name: + - tpm2-tools + - dracut + +- name: Enable tpm2-tss crypt module on dracut + ansible.builtin.copy: + dest: /etc/dracut.conf.d/crypt.conf + content: add_dracutmodules+=" tpm2-tss crypt " + mode: '0644' + notify: Run update-dracut + +- name: Comment out root device in crypttab + ansible.builtin.lineinfile: + dest: /etc/crypttab + regexp: '^([^#].*)' + line: '#\1' + backrefs: true + +- name: Insert luks support to GRUB_CMDLINE_LINUX + ansible.builtin.lineinfile: + dest: /etc/default/grub + regexp: '^(GRUB_CMDLINE_LINUX=).*' + line: '\1"rd.auto rd.luks=1"' + backrefs: true + notify: Run update-grub + +- name: Insert TPM2 to Luks slot + ansible.builtin.command: + cmd: > + systemd-run -P --wait + -p SetCredential=cryptenroll.passphrase:{{ encrypt_passphrase | default(encrypt_passphrase_initial) }} + systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="" {{ encrypt_device }} --wipe-slot=tpm2 + no_log: true + when: "'tpm2' not in encrypt_slots_result.stdout" + +# - name: Update TPM2 Luks slot +# ansible.builtin.command: +# cmd: systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 --unlock-tpm2-device=auto {{ encrypt_device }} --wipe-slot=tpm2 +# when: not grub_config.changed diff --git a/roles/lmn_exam/defaults/main.yml b/roles/lmn_exam/defaults/main.yml index da8c198..fc97945 100644 --- a/roles/lmn_exam/defaults/main.yml +++ b/roles/lmn_exam/defaults/main.yml @@ -1,2 +1,3 @@ --- exam_mode: true +exam_teacherpc_last_digit: 80 diff --git a/roles/lmn_exam/files/pam-exec.sh b/roles/lmn_exam/files/pam-exec.sh index 4f54861..f905cfc 100644 --- a/roles/lmn_exam/files/pam-exec.sh +++ b/roles/lmn_exam/files/pam-exec.sh @@ -5,10 +5,16 @@ if [[ "${PAM_USER}" =~ -exam$ ]]; then systemctl start firewalld.service + if [[ -f /usr/local/sbin/no-way-out-nftable ]]; then + /usr/local/sbin/no-way-out-nftable || true + fi if systemctl is-enabled --quiet libvirtd.service; then systemctl restart libvirtd.service fi elif ! (users | grep -q -- "-exam"); then + if /usr/sbin/nft list tables | /usr/bin/grep -q filtermacvtap; then + /usr/sbin/nft delete table netdev filtermacvtap || true + fi systemctl stop firewalld.service if systemctl is-enabled --quiet libvirtd.service; then systemctl restart libvirtd.service diff --git a/roles/lmn_exam/tasks/main.yml b/roles/lmn_exam/tasks/main.yml index 0e3bc4e..1d0893e 100644 --- a/roles/lmn_exam/tasks/main.yml +++ b/roles/lmn_exam/tasks/main.yml @@ -50,6 +50,38 @@ - pam-exec.sh - rmexam +- name: Append teacherPC to exam_destination_allowed_ipv4 addresses + ansible.builtin.set_fact: + exam_destination_allowed_ipv4: "{{ exam_destination_allowed_ipv4 + (exam_teacherpc_ips | default([ ansible_default_ipv4.address.rsplit('.', 1)[0] ~ '.' ~ exam_teacherpc_last_digit ])) }}" + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + - exam_teacherpc_ips is defined or exam_teacherpc_last_digit | default('') | string | length > 0 + +- name: Install no-way-out-policy + ansible.builtin.template: + src: no-way-out.xml.j2 + dest: "/etc/firewalld/policies/no-way-out-{{ item }}.xml" + mode: '0644' + vars: + zones: + - HOST + - "{{ 'libvirt' if vm_support | default(false) else '' }}" + loop: "{{ zones | reject('match','^$') }}" + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + +- name: Install no-way-out nf-table for macvtap device + ansible.builtin.template: + src: no-way-out-nftable.j2 + dest: "/usr/local/sbin/no-way-out-nftable" + mode: '0755' + when: + - exam_destination_allowed_ipv4 is defined + - exam_destination_allowed_ipv4 | length > 0 + - vm_support is defined and vm_support + - name: Enable login script via pam_exec.so ansible.builtin.lineinfile: dest: /etc/pam.d/common-session diff --git a/roles/lmn_exam/templates/no-way-out-nftable.j2 b/roles/lmn_exam/templates/no-way-out-nftable.j2 new file mode 100644 index 0000000..93305a9 --- /dev/null +++ b/roles/lmn_exam/templates/no-way-out-nftable.j2 @@ -0,0 +1,43 @@ +#!/usr/bin/bash + +set -eu + +interfaces=$(/usr/bin/ip link | /usr/bin/sed -En 's/.*(macvtap-.*)@.*/\1/p') +gateway=$(/usr/bin/ip route list default | /usr/bin/head -1 | /usr/bin/cut -f 3 -d " ") + +filterchain="" +for interface in ${interfaces}; do + filterchain=$(cat <<- EOF +${filterchain} + + chain filterin_${interface} { + type filter hook ingress device ${interface} priority filter; policy drop; + ip saddr \$allowed_ipv4 accept + ip saddr ${gateway} accept + ip saddr 255.255.255.255 accept + ether type arp accept + } + + chain filterout_${interface} { + type filter hook egress device ${interface} priority filter; policy drop; + ip daddr \$allowed_ipv4 accept + ip daddr ${gateway} accept + ip daddr 255.255.255.255 accept + ether type arp accept + } +EOF +) +done + + + +nft_table=$(cat <<- EOF +define allowed_ipv4 = { {{ exam_destination_allowed_ipv4 | join(",") }} } + +table netdev filtermacvtap { +${filterchain} +} +EOF +) + +echo "$nft_table" | /usr/sbin/nft -f - diff --git a/roles/lmn_exam/templates/no-way-out.xml.j2 b/roles/lmn_exam/templates/no-way-out.xml.j2 new file mode 100644 index 0000000..7cf782f --- /dev/null +++ b/roles/lmn_exam/templates/no-way-out.xml.j2 @@ -0,0 +1,10 @@ + +{% for address in exam_destination_allowed_ipv4 %} + + + + +{% endfor %} + + + diff --git a/roles/lmn_finish/handlers/main.yml b/roles/lmn_finish/handlers/main.yml new file mode 100644 index 0000000..bae24ff --- /dev/null +++ b/roles/lmn_finish/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: Reboot client + ansible.builtin.command: + cmd: "shutdown -r -t 60" diff --git a/roles/lmn_finish/tasks/main.yaml b/roles/lmn_finish/tasks/main.yaml index 5f3a787..d7ec865 100644 --- a/roles/lmn_finish/tasks/main.yaml +++ b/roles/lmn_finish/tasks/main.yaml @@ -6,6 +6,8 @@ - "{{ extra_pkgs }}" - "{{ extra_pkgs1 }}" - "{{ extra_pkgs2 }}" + tags: + - baseinstall - name: Add backports for {{ ansible_distribution_release }} ansible.builtin.apt_repository: @@ -14,7 +16,7 @@ main non-free-firmware state: present 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 ansible.builtin.apt: @@ -25,6 +27,19 @@ - "{{ extra_pkgs_bpo }}" - "{{ extra_pkgs_bpo1 }}" - "{{ extra_pkgs_bpo2 }}" + when: extra_pkgs_bpo | length > 0 or extra_pkgs_bpo1 | length > 0 or extra_pkgs_bpo2 | length > 0 + + +- name: Check if former ansible-stamp exists + ansible.builtin.stat: + path: /var/local/ansible-stamps + register: stamp_exists + +- name: Trigger Reboot if no former ansible-run is found + ansible.builtin.debug: + msg: "First Ansible-Run on Client - Reboot handler started" + changed_when: not stamp_exists.stat.exists + notify: "Reboot client" - name: Timestamp successfull run and send up-to-date report ansible.builtin.shell: diff --git a/roles/lmn_kde/defaults/main.yml b/roles/lmn_kde/defaults/main.yml index 779142b..065c5ba 100644 --- a/roles/lmn_kde/defaults/main.yml +++ b/roles/lmn_kde/defaults/main.yml @@ -3,9 +3,10 @@ kde_desktop_pkg: - akonadi-backend-sqlite - arduino - bluefish - - calligra + # - calligra - codeblocks - dia + - filius - flameshot - freecad - fritzing @@ -14,8 +15,9 @@ kde_desktop_pkg: - inkscape - kde-full - keepassxc + - kicad + - kicad-doc-de - librecad - - mu-editor - openboard - qtcreator - spyder @@ -34,3 +36,5 @@ kde_desktop_pkg: - xdg-desktop-portal-kde - xdg-desktop-portal-wlr # share screen in browser - xournalpp + +kde_desktop_pkg_bpo: [ ] diff --git a/roles/lmn_kde/tasks/main.yml b/roles/lmn_kde/tasks/main.yml index 052606b..0b76358 100644 --- a/roles/lmn_kde/tasks/main.yml +++ b/roles/lmn_kde/tasks/main.yml @@ -8,19 +8,14 @@ repo: deb http://deb.debian.org/debian/ {{ ansible_distribution_release }}-backports main non-free-firmware state: present update_cache: true + when: kde_desktop_pkg_bpo | length > 0 - name: Install extra packages from backports ansible.builtin.apt: - name: - - filius - - kicad - - kicad-doc-de - - libreoffice - - libreoffice-l10n-de - - libreoffice-qt5 - state: latest # noqa package-latest + name: "{{ kde_desktop_pkg_bpo }}" autoremove: true default_release: "{{ ansible_distribution_release }}-backports" + when: kde_desktop_pkg_bpo | length > 0 - name: Create akonadi config dir diff --git a/roles/lmn_localhome/tasks/main.yml b/roles/lmn_localhome/tasks/main.yml index 3122720..a06998b 100644 --- a/roles/lmn_localhome/tasks/main.yml +++ b/roles/lmn_localhome/tasks/main.yml @@ -9,7 +9,7 @@ ansible.builtin.blockinfile: path: /usr/share/sddm/themes/debian-breeze/Main.qml marker: // {mark} ANSIBLE MANAGED BLOCK localhome - insertbefore: '\s+//Footer' + insertbefore: '^}$' block: | Text { id: localhome @@ -33,7 +33,6 @@ dest: /etc/profile.d/lmn-logout.sh mode: '0755' content: | - [[ "${UID}" -gt 10000 ]] && ! findmnt "/lmn/media/${USER}/home" > /dev/null && exit 0 {% if localhome_logout_missing_serverhome %} [[ "${UID}" -gt 10000 ]] && ! findmnt /srv/samba/schools/default-school > /dev/null && exit 0 {% endif %} diff --git a/roles/lmn_misc/files/bootorder.sh b/roles/lmn_misc/files/bootorder.sh index a0fb6cd..e3ef2a9 100644 --- a/roles/lmn_misc/files/bootorder.sh +++ b/roles/lmn_misc/files/bootorder.sh @@ -5,11 +5,11 @@ set -eu cur="$(efibootmgr | grep -Ei 'BootOrder:' | \ - sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')" -pxeip4="$(efibootmgr | grep -Ei "IP.*4" | \ - sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" + sed -E 's/^BootOrder: ([[:xdigit:]]{4}),.+$/\1/')" +pxeip4="$(efibootmgr | grep -Ei "IP.{0,5}4" | \ + sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)" debian="$(efibootmgr | grep -Ei "debian" | \ - sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/')" + sed -E 's/^Boot([[:xdigit:]]{4}).+$/\1/' | paste -sd, -)" if [[ "$cur" != "$pxeip4" ]] && [[ -n "$pxeip4" ]] && [[ -n "$debian" ]] ; then efibootmgr -o $pxeip4,$debian diff --git a/roles/lmn_misc/tasks/main.yml b/roles/lmn_misc/tasks/main.yml index 22134c5..23dce2b 100644 --- a/roles/lmn_misc/tasks/main.yml +++ b/roles/lmn_misc/tasks/main.yml @@ -98,7 +98,7 @@ export superusers password_pbkdf2 root {{ grub_pwd }} notify: Run update-grub - when: grub_pwd|default(false) + when: grub_pwd | bool | default(false) - name: Allow booting grub menu entries ansible.builtin.lineinfile: @@ -167,6 +167,8 @@ src: reporter.j2 dest: /usr/local/sbin/reporter mode: '0755' + tags: + - baseinstall - name: Provide services and timers for reporter ansible.builtin.copy: @@ -177,12 +179,16 @@ - reporter.service - reporter.timer when: misc_reporter + tags: + - baseinstall - name: Enable reporter.timer ansible.builtin.systemd: name: reporter.timer enabled: true when: misc_reporter + tags: + - baseinstall # Prepare CloneScreen on Presenter PCs diff --git a/roles/lmn_network/tasks/main.yml b/roles/lmn_network/tasks/main.yml index 7a39349..571c107 100644 --- a/roles/lmn_network/tasks/main.yml +++ b/roles/lmn_network/tasks/main.yml @@ -5,14 +5,14 @@ mode: '0644' content: > {{ apt_conf }} - when: apt_conf|default(false) + when: apt_conf | bool | default(false) - name: Set NTP server ansible.builtin.lineinfile: path: /etc/systemd/timesyncd.conf insertafter: '^#NTP=' line: NTP={{ ntp_serv }} - when: ntp_serv|default(false) + when: ntp_serv | bool | default(false) - name: Add proposed-updates repository ansible.builtin.apt_repository: diff --git a/roles/lmn_printer/tasks/main.yml b/roles/lmn_printer/tasks/main.yml index 960b1fa..996cb2e 100644 --- a/roles/lmn_printer/tasks/main.yml +++ b/roles/lmn_printer/tasks/main.yml @@ -37,7 +37,7 @@ line: "SystemGroup root lpadmin {{ printer_admin_group }}" regexp: '^SystemGroup' state: present - when: printer_admin_group | length + when: printer_admin_group | length > 0 - name: Disable cups-browsed ansible.builtin.systemd: diff --git a/roles/lmn_security/tasks/main.yml b/roles/lmn_security/tasks/main.yml index 62e2754..6c9edcf 100644 --- a/roles/lmn_security/tasks/main.yml +++ b/roles/lmn_security/tasks/main.yml @@ -5,6 +5,8 @@ key: "{{ item }}" loop: "{{ keys2deploy }}" when: keys2deploy is defined + tags: + - baseinstall - name: Allow sudo without password for ansible ansible.builtin.lineinfile: @@ -14,12 +16,16 @@ owner: root group: root mode: '0700' + tags: + - baseinstall - name: Disable ansible user login ansible.builtin.user: name: ansible password_lock: true when: security_defaultuser_login_disable + tags: + - baseinstall - name: Limit SSH access to user ansible ansible.builtin.blockinfile: diff --git a/roles/lmn_sssd/defaults/main.yml b/roles/lmn_sssd/defaults/main.yml new file mode 100644 index 0000000..e7664ac --- /dev/null +++ b/roles/lmn_sssd/defaults/main.yml @@ -0,0 +1,2 @@ +--- +sssd_domjoin_user: global-admin diff --git a/roles/lmn_sssd/handlers/main.yml b/roles/lmn_sssd/handlers/main.yml index 6fdda36..cddc361 100644 --- a/roles/lmn_sssd/handlers/main.yml +++ b/roles/lmn_sssd/handlers/main.yml @@ -1,6 +1,5 @@ - name: Restart sssd - ansible.builtin.service: + ansible.builtin.systemd: name: sssd state: restarted enabled: true - listen: "Restart sssd" diff --git a/roles/lmn_sssd/tasks/main.yml b/roles/lmn_sssd/tasks/main.yml index ed44ce5..c816d13 100644 --- a/roles/lmn_sssd/tasks/main.yml +++ b/roles/lmn_sssd/tasks/main.yml @@ -10,15 +10,27 @@ ansible.builtin.template: src: sssd.conf.j2 dest: /etc/sssd/sssd.conf - mode: '0600' + mode: '0640' notify: Restart sssd - ## Either one of the variables is defined: +- name: Check if the machine account password and the join are still valid + ansible.builtin.shell: + cmd: adcli testjoin -D {{ domain | upper }} + register: adcli_test_result + failed_when: false + changed_when: false + + # If domjoin not valid: - name: Join the domain ansible.builtin.shell: cmd: > - echo "{{ ansible_cmdline.adpw | default('') + adpw.user_input | default('') }}" | - adcli join --stdin-password -U global-admin {{ domain | upper }} - when: > - ansible_cmdline.adpw | default('') | length > 0 or - adpw.user_input | default('') | length > 0 + echo "{{ ad_passwd }}" | adcli join --stdin-password -U {{ ad_user }} {{ domain | upper }} + no_log: true + vars: + ad_user: "{{ 'global-admin' if (adpw.user_input | default(ansible_cmdline.adpw) | default('') | length > 0) else sssd_domjoin_user }}" + ad_passwd: "{{ adpw.user_input | default('') if adpw.user_input | default ('') | length > 0 else ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') }}" + throttle: 1 + when: + - adpw.user_input | default('') | length > 0 or + ansible_cmdline.adpw | default(sssd_domjoin_passwd) | default('') | length > 0 + - adcli_test_result.rc != 0 diff --git a/roles/lmn_sssd/templates/sssd.conf.j2 b/roles/lmn_sssd/templates/sssd.conf.j2 index fc3bf48..1591f1d 100644 --- a/roles/lmn_sssd/templates/sssd.conf.j2 +++ b/roles/lmn_sssd/templates/sssd.conf.j2 @@ -9,7 +9,9 @@ ad_domain = {{ domain }} id_provider = ad access_provider = ad use_fully_qualified_names = False +{% if localhome is defined and localhome %} cache_credentials = True +{% endif %} krb5_store_password_if_offline = True default_shell = /usr/bin/bash # default: # ldap_id_mapping = True @@ -17,6 +19,7 @@ ad_gpo_access_control = disabled ad_gpo_ignore_unreadable = True ad_maximum_machine_account_password_age = 0 ignore_group_members = True +krb5_renew_interval = 1h {% if localhome is defined and localhome %} override_homedir = /home/%u {% endif %} diff --git a/roles/lmn_tmpfixes/tasks/main.yml b/roles/lmn_tmpfixes/tasks/main.yml index 8e90138..23e0bf8 100644 --- a/roles/lmn_tmpfixes/tasks/main.yml +++ b/roles/lmn_tmpfixes/tasks/main.yml @@ -8,3 +8,27 @@ - bookworm.yml - cleanup.yml when: ansible_distribution_release == "bookworm" + +- name: Set chromium gl-flags fixing AMD graphic issues + ansible.builtin.copy: + dest: /etc/chromium.d/fvs + content: | + export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --use-gl=desktop" + when: ansible_board_vendor == "LENOVO" and + (ansible_board_name == "312D" or ansible_board_name == "312A") + +- name: Fix 8086:4909 external graphics card + ansible.builtin.replace: + dest: "/etc/default/grub" + regexp: 'GRUB_CMDLINE_LINUX=""$' + replace: 'GRUB_CMDLINE_LINUX="i915.force_probe=4909"' + notify: Run update-grub + when: ansible_board_vendor == "LENOVO" and ansible_board_name == "32CB" + +- name: Remove calligra + ansible.builtin.apt: + name: + - calligra + state: absent + purge: true + autoremove: true diff --git a/roles/lmn_vm/files/lmn-vm b/roles/lmn_vm/files/lmn-vm index 7d4011e..006b84c 100644 --- a/roles/lmn_vm/files/lmn-vm +++ b/roles/lmn_vm/files/lmn-vm @@ -3,6 +3,11 @@ %role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync %examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-sync +# vm-delete: Delete VM-Images +%role-teacher ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete +%role-student ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete +%examusers ALL=(lmnsynci) NOPASSWD: /usr/local/bin/vm-delete + # vm-aria2: Start/Stop aria2 as systemd-service for VM-Images lmnsynci ALL=(root) NOPASSWD: /usr/local/bin/vm-aria2 diff --git a/roles/lmn_vm/files/vm-delete b/roles/lmn_vm/files/vm-delete new file mode 100755 index 0000000..84a8aba --- /dev/null +++ b/roles/lmn_vm/files/vm-delete @@ -0,0 +1,45 @@ +#!/bin/bash + +set -eu + +directory="/lmn/vm" + +if [ ! -d "$directory" ]; then + echo "No VM directory found." + exit 1 +fi + +qcow2_files=("$directory"/*.qcow2) + +if [ "${#qcow2_files[@]}" -eq 0 ]; then + echo "Keine QCOW2-Dateien gefunden." + exit 0 +fi + +echo "Gefundene QCOW2-Dateien:" +echo "-------------------------------------------------------------" +printf "%-50s %10s\n" "Datei" "Größe (MB)" +echo "-------------------------------------------------------------" + +for file in "${qcow2_files[@]}"; do + size=$(du -m "$file" | cut -f1) # Größe in MB + printf "%-50s %10d\n" "$file" "$size" +done + +echo "-------------------------------------------------------------" + +for file in "${qcow2_files[@]}"; do + read -rp "Möchtest du die Datei $file löschen? (j/n) " confirmation + if [[ "$confirmation" == "j" || "$confirmation" == "J" ]]; then + link_count=$(stat -c %h "$file") + rm "$file" + echo "$file wurde gelöscht." + if [ "$link_count" -gt 1 ]; then + echo "Achtung: $file hat noch $((link_count - 1)) weitere Hardlinks." + echo "Diese liegen evtl. unter:" + echo "- /var/tmp/${UID}/vm/ (temporäre VMs, werden automatisch beim Neustart gelöscht)" + echo "- /var/vm/${UID}/ (persistente VMs)" + fi + echo + fi +done diff --git a/roles/lmn_vm/files/vm-link-images b/roles/lmn_vm/files/vm-link-images index e4c8618..0eccd04 100755 --- a/roles/lmn_vm/files/vm-link-images +++ b/roles/lmn_vm/files/vm-link-images @@ -19,8 +19,9 @@ done shift "$((OPTIND -1))" # link system-VM-Images to User VM Directory -for i in *.qcow2; do - [[ -f "${VM_DIR}/${i}" ]] || ln "${i}" "${VM_DIR}/${i}" +for filename in "$@"; do + filename="$(basename ${filename})" + [[ -f "${VM_DIR}/${filename}" ]] || ln "${filename}" "${VM_DIR}/${filename}" done # allow lmnsynci to remove old vm images diff --git a/roles/lmn_vm/files/vm-netboot b/roles/lmn_vm/files/vm-netboot index c21024f..92ca621 100755 --- a/roles/lmn_vm/files/vm-netboot +++ b/roles/lmn_vm/files/vm-netboot @@ -7,10 +7,10 @@ set -eu ## Imporant for all virsh libvirt calls: export XDG_CONFIG_HOME="/var/tmp/vm/${UID}" -menu=(standard "CLI Standard Debian GNU/Linux NFS" - standard-ram "CLI Standard Debian GNU/Linux RAM" - kde-desktop "KDE Plasma Desktop Debian GNU/Linux NFS" - gnome-desktop "Gnome Desktop Debian GNU/Linux NFS") +menu=(standard-edu "CLI Standard Debian GNU/Linux NFS" + standard-edu-ram "CLI Standard Debian GNU/Linux RAM" + kde-edu "KDE Plasma Desktop Debian GNU/Linux NFS" + gnome-edu "Gnome Desktop Debian GNU/Linux NFS") img=$(dialog --clear --backtitle "Virtual Machine Chooser" \ --title "Choose the Virtual Machine to Start" \ --menu "Start VM:" 12 70 6 "${menu[@]}" 2>&1 >/dev/tty) @@ -22,6 +22,8 @@ mac="$(ip link | grep -A1 -m1 "macvtap-" | \ sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")" tapdev="$(ip link | grep -A1 -m1 "macvtap-" | sed -nE "s%^[1-9]:\s(\S+)@.*%\1%p")" +livebox=$(host livebox | sed -E "s/.+ ([0-9.]+)$/\1/") + if [[ $# -eq 0 ]] ; then mem=$(sed -En "s/^MemAvailable:\s+([0-9]+)\s+kB/\1/p" /proc/meminfo) cpu=$(sed -En "0,/^cpu cores/s/^cpu cores\s+:\s+([0-9]+)/\1/p" /proc/cpuinfo) @@ -31,8 +33,8 @@ else arg=("$@") fi -kernel="http://livebox/d-i/n-live/${img%-ram}/live/vmlinuz" -initrd="http://livebox/d-i/n-live/${img%-ram}/live/initrd.img" +kernel="http://${livebox}/d-i/n-live/${img%-ram}/live/vmlinuz" +initrd="http://${livebox}/d-i/n-live/${img%-ram}/live/initrd.img" kargs=(boot=live components splash locales=de_DE.UTF-8 keyboard-layouts=de swap=true live-config.timezone=Europe/Berlin) @@ -42,10 +44,10 @@ case "$img" in kargs+=(console=ttyS0) ;;& *-ram) - kargs+=("fetch=http://10.190.1.2/d-i/n-live/${img%-ram}/live/filesystem.squashfs") + kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs rd.live.ram=1") ;; *) - kargs+=(netboot=nfs "nfsroot=10.190.1.2:/srv/nfs/debian-live/${img%-ram}") + kargs+=("root=live:nfs4:${livebox}:/images/${img%-ram}/live/filesystem.squashfs") ;; esac diff --git a/roles/lmn_vm/files/vm-run b/roles/lmn_vm/files/vm-run index a957a49..af0bd67 100755 --- a/roles/lmn_vm/files/vm-run +++ b/roles/lmn_vm/files/vm-run @@ -90,17 +90,21 @@ create_clone() { local VM_NAME="$1" if ! [[ -f "${VM_SYSDIR}/${VM_NAME}.qcow2" || -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then - echo "qcow2 File does not exists." >&2 - exit 1 + echo "qcow2 File does not exists." >&2 + exit 1 fi # Create User-VM-Dir and link system VM-Images [[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}" - if [[ "${PERSISTENT}" -eq 1 ]]; then - sudo /usr/local/bin/vm-link-images -p - else - sudo /usr/local/bin/vm-link-images - fi + IMAGE="${VM_NAME}.qcow2" + while [[ -n ${IMAGE} ]]; do + if [[ "${PERSISTENT}" -eq 1 ]]; then + sudo /usr/local/bin/vm-link-images -p "${IMAGE}" + else + sudo /usr/local/bin/vm-link-images "${IMAGE}" + fi + IMAGE="$(qemu-img info -U "${VM_DIR}/${IMAGE}" | grep "^backing file:" | cut -d ' ' -f 3)" + done # Create backing file cd "${VM_DIR}" @@ -130,18 +134,30 @@ create_printerlist() { } create_mountlist() { - if id | grep -q teachers; then - NETHOME=/srv/samba/schools/default-school/teachers/$USER - else - NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") - fi - NETHOME="${NETHOME#/srv/samba/schools}" - cat << EOF > "/lmn/media/${USER}/.mounts.csv" + NETHOMEPART="${NETHOME#/srv/samba/schools}" + cat << EOF > "${VMINFO_DIR}/.mounts.csv" Drive;Remotepath -H;\\\\10.190.1.1${NETHOME//\//\\} -T;\\\\10.190.1.1\default-school\share +H;\\\\server.pn.steinbeis.schule${NETHOMEPART//\//\\} +T;\\\\server.pn.steinbeis.schule\\default-school\\share EOF - echo "${USER}" > "/lmn/media/${USER}/.user" + echo "${USER}" > "/${VMINFO_DIR}/.user" +} + +start_virtiofs_service() { + local target_name=$1 + local shared_dir=$2 + local drive_letter=$3 + local socket="/run/user/${UID}/virtiofs-${VM_NAME}-${target_name,,}.sock" + + systemd-run --user /usr/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() { @@ -151,9 +167,17 @@ start_virtiofsd() { [[ "$GUEST_GID" == 0 ]] && GUEST_GID=1010 fi # END temporary fix - socket="/run/user/$(id -u $USER)/virtiofs-${VM_NAME}.sock" - systemd-run --user /usr/local/bin/virtiofsd --uid-map=:${GUEST_UID}:${UID}:1: --gid-map=:${GUEST_GID}:$(id -g):1: \ - --socket-path "$socket" --shared-dir "/lmn/media/${USER}" --syslog + + # start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y" + # start_virtiofs_service "default-school" "/srv/samba/schools/default-school" "Y" + + # Home@PC / VM-Data + # if the environment variable VMLEGACY is set, /lmn/media/USER is forced + if [[ "${HOME}" != "${NETHOME}" && ! -v VMLEGACY ]]; then + start_virtiofs_service "Home_Linux" "${HOME}" "Y" + else + start_virtiofs_service "VM-Data" "/lmn/media/${USER}" "Y" + fi } ask_really_persistent() { @@ -216,7 +240,7 @@ while true; do shift ;; -o | --options ) - LIBVIRTOPTS=$2 + LIBVIRTOPTS="${LIBVIRTOPTS} $2" shift 2 ;; --no-viewer ) @@ -267,6 +291,7 @@ while true; do type="ethernet,mac=${mac},target.dev=${interface},xpath1.set=./target/@managed=no,model.type=virtio" LIBVIRTOPTS="${LIBVIRTOPTS} --network type=$type" done + LIBVIRTOPTS="${LIBVIRTOPTS} --check mac_in_use=off" shift ;; --os ) @@ -315,18 +340,38 @@ if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then check_images fi if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then - create_clone "${VM_NAME}" + create_clone "${VM_NAME}" fi # delete the old vm virsh --connect=qemu:///session undefine --nvram "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist" #trap exit_script SIGHUP SIGINT SIGTERM + for dir in teachers examusers staff parents; do + if [[ -d "/srv/samba/schools/default-school/${dir}/${USER}" ]]; then + NETHOME="/srv/samba/schools/default-school/${dir}/${USER}" + break + fi + done + if [[ -z "${NETHOME+x}" ]]; then + NETHOME=(/srv/samba/schools/default-school/students/*/"$USER") + fi + + if [[ "${HOME}" != "${NETHOME}" ]]; then + VMINFO_DIR="${HOME}" + else + VMINFO_DIR="/lmn/media/${USER}" + fi create_printerlist create_mountlist # start virtiofsd-service [[ "${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="${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 \ --disk "${VM_DIR}/${VM_NAME}-clone.qcow2",driver.discard=unmap,target.bus=scsi,cache=writeback \ --network=bridge=virbr0,model.type=virtio \ - --filesystem driver.type=virtiofs,accessmode=passthrough,target.dir=virtiofs,xpath1.set=./source/@socket="/run/user/${UID}/virtiofs-${VM_NAME}.sock" \ --controller type=scsi,model=virtio-scsi \ --check path_in_use=off \ --connect="${QEMU}" \ diff --git a/roles/lmn_vm/files/vm-vminfo b/roles/lmn_vm/files/vm-vminfo new file mode 100755 index 0000000..559d47f --- /dev/null +++ b/roles/lmn_vm/files/vm-vminfo @@ -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() + + diff --git a/roles/lmn_vm/tasks/main.yml b/roles/lmn_vm/tasks/main.yml index a39325a..e2c312b 100644 --- a/roles/lmn_vm/tasks/main.yml +++ b/roles/lmn_vm/tasks/main.yml @@ -18,7 +18,9 @@ - mktorrent - libvirt-daemon-system - virt-manager + - virt-viewer - dialog # for vm-netboot menu + - python3-impacket # - name: allow all users to use VMs # lineinfile: @@ -27,32 +29,6 @@ # insertafter: '#auth_unix_rw = "polkit"' # notify: reload libvirtd -- name: Configure pam_mount for VM bind mounts - ansible.builtin.blockinfile: - dest: /etc/security/pam_mount.conf.xml - marker: "" - block: | - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - rootansibleDebian-gdmsddm{% if localuser %}{{ localuser }}{% endif %} - - insertafter: "" - - name: Use umount script for proper cleanup ansible.builtin.blockinfile: dest: /etc/security/pam_mount.conf.xml @@ -142,6 +118,7 @@ group: root mode: '0755' loop: + - vm-delete - vm-create - vm-rebase - vm-run @@ -149,6 +126,7 @@ - vm-sync - vm-link-images - vm-virtiofsd + - vm-vminfo - virtiofsd - vm-aria2 - uploadseed @@ -236,3 +214,26 @@ src: vm-netboot dest: /usr/local/bin/ mode: '0755' + +- name: Provide vminfo service + ansible.builtin.copy: + content: | + [Unit] + Description=Create .vminfo.json for VMs + [Service] + Type=simple + ExecStart=/usr/bin/bash -c 'umask 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' diff --git a/roles/lmn_vpn/files/10-lmn-mount.sh b/roles/lmn_vpn/files/10-lmn-mount.sh index 6f42725..cabbc58 100755 --- a/roles/lmn_vpn/files/10-lmn-mount.sh +++ b/roles/lmn_vpn/files/10-lmn-mount.sh @@ -13,30 +13,32 @@ if [[ "$CONNECTION_ID" = "VPN-Schule" ]]; then # Exit if server is already mounted findmnt /srv/samba/schools/default-school > /dev/null && exit 0 - if ! klist -s -c "${KRB5CCNAME}"; then - #echo "try to renew KRB5-Ticket" >&2 - #sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}" - echo "KRB5-Ticket is expired. Sleep 3 seconds and hope it will be renewed after." >&2 - sleep 3 - fi + counter=1 + while ! klist -s -c "${KRB5CCNAME}"; do + (( counter > 30 )) && exit 0 + echo "KRB5-Ticket is expired. Sleep 1 seconds and hope it will be renewed after." >&2 + # if (( counter == 10 )); then + # echo "try to renew KRB5-Ticket" >&2 + # sudo -u "${USERNAME}" kinit -R -c "${KRB5CCNAME}" + # fi + sleep 1 + ((counter++)) + done echo "prepare mountpoints" >&2 umask 0002 mkdir -p /srv/samba/schools/default-school chmod 777 /srv/samba/schools/default-school - mkdir -p "/lmn/media/${USERNAME}/share" - + mount -t cifs //server/default-school/ /srv/samba/schools/default-school \ -o "sec=krb5i,cruid=${USERID},user=${USERNAME},uid=${USERID},gid=${GROUPID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10" echo "after mount" >&2 - mount --bind /srv/samba/schools/default-school/share "/lmn/media/${USERNAME}/share" SUDO_USER=$USERNAME /usr/local/bin/install-printers.sh elif [[ "$NM_DISPATCHER_ACTION" = "pre-down" ]]; then # FIXME: Only umount server when Wireguard-Connection was the only connection to server. # Dirty fix (works only in fvs-IP-Range) if ! (ip r s | grep "10.190." | grep -v wg0); then - echo "Try to umount server shares" - umount "/lmn/media/${USERNAME}/share" + echo "Try to umount server" umount /srv/samba/schools/default-school fi fi diff --git a/roles/lmn_vpn/files/mountserver b/roles/lmn_vpn/files/mountserver index 71c61cc..708a26e 100644 --- a/roles/lmn_vpn/files/mountserver +++ b/roles/lmn_vpn/files/mountserver @@ -3,7 +3,6 @@ set -eu exit_script() { echo "unmounting media - terminated by trap!" >> "/tmp/${SUDO_UID}-exit-mount.log" - findmnt "/lmn/media/${SUDO_USER}/share" && umount "/lmn/media/${SUDO_USER}/share" findmnt "/srv/samba/schools/default-school" && umount "/srv/samba/schools/default-school" trap - SIGHUP SIGINT SIGTERM # clear the trap kill -- -$$ # Sends SIGTERM to child/sub processes @@ -14,11 +13,9 @@ findmnt /srv/samba/schools/default-school > /dev/null && exit 0 umask 0002 mkdir -p /srv/samba/schools/default-school chmod 777 /srv/samba/schools/default-school -mkdir -p "/lmn/media/${SUDO_USER}/share" mount -t cifs //server/default-school/ /srv/samba/schools/default-school \ -o "sec=krb5i,cruid=${SUDO_UID},user=${SUDO_USER},uid=${SUDO_UID},gid=${SUDO_GID},file_mode=0700,dir_mode=0700,mfsymlinks,nobrl,actimeo=600,cache=loose,echo_interval=10" -mount --bind /srv/samba/schools/default-school/share "/lmn/media/${SUDO_USER}/share" echo "Einbindung erfolgreich!" echo "Dieses Fenster bitte nicht schließen!" diff --git a/roles/lmn_vpn/tasks/wg_config.yml b/roles/lmn_vpn/tasks/wg_config.yml index d1bf9ce..1e42049 100644 --- a/roles/lmn_vpn/tasks/wg_config.yml +++ b/roles/lmn_vpn/tasks/wg_config.yml @@ -5,7 +5,7 @@ - wireguard - 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 register: result changed_when: false @@ -17,10 +17,12 @@ * server not reachable * no matching ssh-key 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 - 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: - name: Set facts wg_clientname ansible.builtin.set_fact: diff --git a/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml index 74bc7c4..79932f0 100644 --- a/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml +++ b/roles/lmn_wlan/tasks/eap-tls_check-certificate.yaml @@ -27,7 +27,7 @@ when: cert_client_active.stat.exists - 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 register: radius_reachable changed_when: false @@ -40,12 +40,13 @@ - "* server not reachable" - "* no matching ssh-key" 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 ansible.builtin.include_tasks: eap-tls_issue-certificate.yaml 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 (cert_serial.stdout | replace('serial=','') | int(base=16) ) in ( radius_crl.revoked_certificates | map(attribute='serial_number') | list ) or diff --git a/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml index a3258df..9e897bb 100644 --- a/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml +++ b/roles/lmn_wlan/tasks/eap-tls_issue-certificate.yaml @@ -105,6 +105,7 @@ ansible.builtin.systemd: name: iwd.service enabled: false + failed_when: false - name: Remove deprecated NetworkManager config ansible.builtin.blockinfile: diff --git a/roles/lmn_wlan/tasks/main.yaml b/roles/lmn_wlan/tasks/main.yaml index 1fb7ec2..d5adcea 100644 --- a/roles/lmn_wlan/tasks/main.yaml +++ b/roles/lmn_wlan/tasks/main.yaml @@ -3,7 +3,6 @@ - name: Install packages related to wifi ansible.builtin.apt: name: - - systemd-resolved - firmware-realtek # for our wifi sticks - name: Provide service to enable WiFi on boot