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..9f3180a 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,649 +1,690 @@ $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 +36383632636466643664323334306638653933393963626438303039393037353833643533356562 +6362363133383636613263656665666434646436633465620a646131383062333233656233663331 +65613730663137373964383161373535323637353561313535376563626137633732333634643031 +3937633236623534350a373337656262373732643839666162393734313463663736313333616530 +35363633616336343464303937353437666238613232393233333166653439336363303738323338 +32626135363537333965353034666636333639663133383465326330646432343737376630643434 +63323835393338613834393734653832373131643836643137626639613236356638613966383334 +62666564316139336165353531356661353864303031316266636430653862333735386662326531 +37393963643034326338313737653332343832633136316337343032623166643663363633393339 +36366362646238646536333739636631366239306331626630623830653066323065363961623861 +31383665353830333536656639383837636537393232303235386139623061636239376561653238 +35653236353931626134333831343363396533666535326236626137633936633737613233653133 +63336132316564323834366366306462666137656138306563333430653233366332653535396333 +64613237333062353535353262626339336361313433626663333435626266353366633132346564 +66626464653530396533376533653161373064353530313433613431366139366434663436396462 +35613734346165616665393237313835393366643065643762363662366661336433653331333938 +30323166396435666531393038616334623662613632376239666139373137646230636261353861 +65326532383430313733316466633336653363356630363362313734326130613837366235333537 +30393436653538336337393130396661656338623030616662663433643432383237633538393264 +61363265613531316461646631616164613738653533363463653039373761663533646536626466 +31663264623261613435303266663430643838663165333364646137626134396365333464643836 +33656632306334353030303233363331663831393839303135393333333966643661353635643430 +38383634636331373033356138343137643935346237343431373534396434366239363262356139 +31663537353738313661393235363763616561613161613063613961323762313565306666646365 +61376234363538326564313035663337313737303038326332626365303263656538613664303362 +65396561376334646338313936303334346537646364336131636136333163373133343366613135 +32336336636237353536343061663235643065303432356161656539653063316562333766663938 +35616463633430376431613236316233333837343830633465306663616634306565333531363064 +66646130366333653365393537323563326635303133316630356531636562353336343864643532 +37653762316139653132343433356665323730393064393662623566323832616431303738666465 +38643636623065343033336463346536336434643134313236646266643739383134653062376138 +36316664353536613032663737383732666536316364653565393263663462373832386531303234 +31623063343336393332616239613863623339623535303665363537323534343333666335613532 +35396430396138656536626537646232336132643537383831393463323365353861633066383635 +36393337386233326334656231663961613862323432316430303662666236626363373534333265 +64646639633961366434353339306539353632643365303231386438356232643231613866316336 +61616234383364363562303038383833363363316362373431383031616330353662366538376364 +33663763356565306164633662346339363931653339663232383462373530656130373331383863 +37623935346339386334653530323530323363353539646332303837333162323664373436393462 +33663231386263633563383164343331623938636639356461366362326433306165383566313538 +33376537363363613035306332386633316665336662666137636537383332653830616639393762 +66346133313664366239336437363366386530653763663833306365376233363132373166326333 +66616338306432383563386332316365393466396634633137383065613862363062373831343435 +30366633646535343162383332613163613139616364323037373838393864336338616531356563 +37393765396461666438343035623962346433373731323736316463616437663933383765316366 +35313432356137333063666564336539356237386466353638333838313966663834613537316465 +63383337663262616335646362616362363539346331626337323261366431323134313438336366 +38393662343437646531386461383536623331393263333238313763663161393661396361346633 +36646130373235326438386133353461363037373932363335613263383765623166643633373462 +66653164653333326265386161363334643138626465323035393562353066626138326566353736 +36336563666131653139356663376562646538353462326635313239653038373339336163623463 +30363661663661356633663132396564323936346661366262626634613230343363353565306635 +65623066396164666638343739363066393139333436346263666237376361393033313561393237 +34353835316638323632366134363538303039393462373037633736666337326164306437656331 +37346463633366366531343037666236636662313161343063656137303234386431353361343137 +38363339623037323330386237643733626639333866376265323634313637646135303531633036 +66663265313632663335373265303431636665363939663366306338393435623939626239323931 +62326566316661306637643961376536396338383437396639343362323438646633643932306431 +36386331383333613434326334393930363639626238653738613133306265393436306330313237 +30323163666235663265643331333763366239313638366538396531356638393135376630653433 +32626463393130363764336135393664393734623861303630666263353562663466353463393261 +63386230626261643434633661303062363136626538376639323466393138306335333366653964 +31373466636633376266356534313435353636336138343130393036376133323661346135313764 +38363464636437323839633239323637303162653738363238633562663132303735383432613938 +61633263613634666162343038333233343061646438653835316363393562366533376137303036 +66353033323938643333303337633239646230323336643630343137336233613536333134363364 +36616135333136393631656661313136633063333662346365333865386331306335636662616136 +62636139303533366161306433313739323838663432303735303964653737376130643735666532 +64636563356233356261323137316433376362666636313464366563303836663762393664653139 +38376434653565333231383336613134393732383930613637336136316361323839363732323264 +31653339326131393235353634303365363531313836333463323233326463383866373663623261 +66306239356166316263656631376362663633636561636433633039626561616532653365306632 +63346436323434353038306533383061623739363733656336323363386333346565396633393734 +66363862353765653734376235383634393830376134366430323831613430643065363439613265 +32623166313337633634626435316633326335343634306235336134613961383663356330393539 +37333136613464373764323364656635393166616539383438356263626239363863636139663462 +38636130316135396230343863313636383531336530643065326233343730333938353563623432 +65393566613637653562376461373265636432653363323064396464366434396462646630356234 +63373530623636343438633966333132343533623137373762666634653461653364356637313739 +30343134633163396335316435333637333064633961346239643437656261356238353234646238 +38373366336565616134346133376365653634306331306464383935623764336265333465343536 +30303732653930663464336530663261656334363263663434613237326339373834636663393435 +34646265366163366562633561646132323739316161623431346532373731386365636135653737 +61643130373938373832383831306436356363336230353763613965356139356432633235323539 +39396364383436346463636461303337363532326162343136653564623435636331636261383937 +35313761393464383431356165646264343639653539646535383731313332373466383764626436 +31616362643637396239373435363461323732613762303836653839646633646336323364623661 +32643266623839623833353562613233346164366530656165363366623361663439313131306430 +34643161366137336339333466656630643530313665353061313462623838336137396131623631 +61393336323139646431313661656139356133373261333965313765323830616233316234393364 +31616263643034373731303630663536373238316361643463313262633234623432326637326335 +32303038636434376162616535333831666436643437396331636230393933343065323562353634 +65626434363132396336373465316439626262666134656263313838656365326136353066346632 +65333437333438616236646239386434633239656436366533376564343666386137646631343137 +31663736316364346131323339333364316137326663343036333633633530663837316538626636 +61316632303539616161333032323362633133393739626466316535383161646438386231663764 +61336137356439383761343336383030666561316336613466303466346666326662343563623631 +34313238303638623330386333633437646536356665316130633933383937366437646430666663 +33666232363734353966646539336231653531396665393330313934333136346162396230636239 +36386261353031383932666361386632636464386438643336326466306136323164356266333465 +61643364613933353937396663616265313134643530623530643461626632373039366465323636 +35303739383230336633663138313237376465333366366434646662323838623231626331306534 +35336434313332366532666131613333383861303937613434323632663431383138356631656233 +66386537663037633831336330393861383262353034353634306130656130383863346564636261 +63356262383632616266646539376562306365336239666136623638663339636334316666633336 +35663963633263623533376563303564316432633938326335636465356561326534373136633036 +38323663616432313734633039326536653162383863316664333764646638333064323964346262 +33366161626538303261646235646263636665303334323733633336666664366135613763383733 +34666437666439323136353633663062376133653065326136663164346462626630343939343534 +66353534346661323566373139643461633564303330626635333331663864613938653566623832 +35383334663339306235626131626336333935613830376438396466333566313939343233323538 +37373731356437393437326364323765323430626661336539363962306532333739366139373932 +39326239663765323932326431666333346634306532386562663165323063633239326363373537 +63633338393533303237383236616436373833356564306331356562653133376264666137363062 +66353761663031393332643934373231326136623933636431366135616363616136353136396461 +38333830616565373232666464313331353336396631353461366335343766326661346637333464 +34373566646536376532393033343135663332363365646330653261303162666339653937376666 +64353635383436363535343233313737313138393932333133373135393930623764353963313364 +39363237383835633865336333663935316234336437343337366235383833373139656161383434 +65336362306365643039336561346531393332373330643335396131366138653239303635653330 +34346366326465623965616661653530643734656330666433643839373939653732666563333364 +35626163636162353064393662643832333363653063663135313034653561666132643066363064 +64306366363131643534663763393533393839336262646665373633333837353334323861396133 +38646233393336343330343366666362393434386163353130306137326433316563313731393033 +64393131396335646364393533346462643466333532633333663739343738313433313662376331 +30633437663566666361306565663065326430306664326464316539326438373533303861343961 +38313538626232633839633361396237333430626234633630633130386337386231346331393837 +37616263613330306637316131623936323464613130646237653762663265313432356433333834 +64663461363132623534363331396638653064383061393432393830333830353033633333303465 +36623930396630633066356233323133393964663530663930643339663538386462643336343934 +34313262346533653337393535633836396631626663343132613735653338613630636333336535 +34646662636663643966316563633862386665373864356466343133333138373432316462646137 +31376365376364323238303764616163656663313331343138646530316439386635626634346361 +66336334626166373665303332333130613438393061373634383535373763363839626433633364 +38613832303234623265616639333835343935313739373464613731656537626438313636383637 +61323931303262303131363233313436643365346130663534343237346337313537373932646639 +34346236313831363634656532303763326438373837613361393862626165366239363638643431 +30356664383562386537356330633063366437333634343462643866336134653934383332326431 +37353261656230336261373630306139643863633239616337643636303136303561653335653330 +32623663376635396130353566396530343133373636613633613062323032323938663466343661 +62383063383135363136343061663932303035666337316137666463303633656230636236303434 +31666238383236383936633765383864313430396161363665313035386234386466303366363463 +32323935306637363832383265633534393831636436393234643335343037643030623834313166 +37396635333930636339313730376338353038313733363030633863663631393764303433343035 +62363863633830313565643236326165666231373436316239386633356133393832623966333464 +34663831643566663038666363393933396539363264346639333736383862323532616130613366 +64633163336335643739373662653937343133333636356264643565363563626266353264323166 +65386165336138333965626337383733663839653038653066616532613237616661633536316365 +34663737643864633763353863343230333762323962353230373264356439653835333835613863 +65613038373363323030393963316539326139333566373735303437346561666635623065363030 +62656465653066383763393165663661333065303832316664653065353433656236306239656264 +64303136393134396231366536666532313966353930396165343334313435343330633535646261 +37323461663133356164323866656337663938616462626166336532636236643431666232323535 +34626137633061323534356662306536366536373761666635393464323533666561663537616531 +30663930656633386331313230366263363330636136613462366235313164303766626265613962 +33646232313039636634623465313766373630363566383964313435666437376666386332356439 +62643134383934333839316630333731316261636534373263386636343531333231393432373866 +64663666353664363763306536626130636463303864663339313437333930333632636232656333 +33396531353732656634323861366530346530363038323231346131623534633330656138633163 +64366462653038636637616333616339633439333336626661643465306531316434326533376231 +61313232363732386462353634303633323734343930333434343237613431613234396561303366 +31363130386365303765316366303930633134343930663634643731376439333036366439613961 +35633366656536623163306565633738353733386163643561366438646634356236396434376436 +66333739663366653136343661326232393964636538653137313166353032383031313734363436 +31653836316331363431306163653735653364346536396336626131656461616132613235616463 +66616539633066633966346433336336616664393366353738663430376536323031326436653035 +37616635656530346364313134323030663861653364616234613838343665346161336263396262 +34643665396638346638386465643161303938306164623864353935363330393135636633613761 +66316464343266636134633838306534383363633733373439336566666665343464373665316630 +36343562346339303863653338373764353262323437633666306138326332313630323766316636 +30316366316532646532626664393434656665393131663730643565323337353930663963643934 +33303462363066663337656530353330303738393934633966633031663833303466343039366134 +64353537623366636238633766313233366464393862346164353563623663626166326264376134 +38313837346532323161343831396163373264633333313631353835613535613436333839363031 +30363230656237396337623262383762323263373530353665656164613661366335306631333138 +38623837633737303161653232333338386636656432613332303966646663386665313465626465 +37373530393164653338313931326565343861643261613735326264626637353065643038333037 +31393230613538346163356234613734623833316433316332326338626130386263663264323733 +35666431326563646363656537656233323961623461333932333135346633383562333135636437 +37303932323237633465363162376361376135323663386634626236363165626536633031343361 +35313566386336346363376336366630633363343639663937656539616332366133643534393464 +39356331646631366234393462646163323661346564613563353137663362366265306565356134 +37663363363938646135376166363434336461646230343964656431373330613530336663356563 +65666461613837333064336339636330663165343461303135666239643635393834326664326231 +31343531383539613635373134366534313061363238326363353637353235646662306461326661 +30373535616266616165346537346564373135623365663730333436383330666435386461656238 +32333633316663633139623136363334656234303338633133613736356461633230343733313664 +62353538636239303639663263623836383266393931313964376230346161613034643237636364 +62643532353532313965356465633163623234306164363339636366343663306262383164613032 +34616138663161623631383837656136353666636562356237383034306165303566343133346463 +65383534316634666630666631333730306333336339316638333639316632663132613064356531 +66623434323239383930656530656432333237626532336135633963316431313666393236633333 +30313336323263653636646561663863373933306332303831383835343232613333666564633165 +64663766333962646230323232323934363164623931353331343163653362366131646531623739 +62303338646137376666363539663935376339623034303662623366373739626135363433646538 +65356563373364356535623232376536366235356165323938626436303334393832663031376664 +34306262313366313536393637396333333237396565333033316265656265316564313835313165 +30613039643061636330653264343230343739626138623861336262363037636135326430653561 +34396236643133643234663963373038393961656134363330666430666431373062663762336339 +31373465306534653362323662616234653439646665333462363933353062316637343432613265 +38663330373133303962623139313532313463393237323161653261656530383330643964623261 +30336532366265393638323737356363383436363065613735636431626539333935363134396666 +35616139383139306631376136356337656135363765643862356433393662306136663761396666 +34353061303337306336373565356138376233646337643632613861326565326131643434383561 +35373161636639646335663533316536383664656666353133633230643262373933323365396635 +65393339333032613761366465363632323833643664616662663131373863613837393363633936 +35353935323032646665613362666636323139363930386262663739653330323561653666383634 +35633339366436363637383132306431646665613835333339626534323136313564383163623133 +31666133383763636336326535636632653366353961653531383134333933373732333736326135 +33396538386538336633646131643034323039653232643462613638376636613037666364643834 +37346237653838393663323430343535346564656233353634613661356563623066316634643531 +34363936393964663765656233383466316535343932633238633137363730633633623365393231 +33626165303066343534303663396365333635613733383461373661656531613833636461633330 +65313937633764316663313530666563656235303536383739666136373162323936313737613034 +32623962303738366239666537643435633438353730613739666561353834643063643434323134 +65313761643966333633633965386536306364346232383131626534356165363061393065653736 +66316239623062306633383764383537646165363336653934373562316562323261623638613431 +65316333373131663031623366666438376566396564653764376564393633303363346431303031 +39666639323861653833346663363964633063653333313337373935303064636365366130386438 +62326230353866316133306664303832646132356364616337633366303964636136653130303762 +35393431386639333230656232633766346535386463653865323237313361373538646566663633 +34626130626636343032386335333230303235616564343830326165613764323437626335663031 +30376364323931383935666634346434613139646634343538363639393562363131353235396566 +32626233373136326132306230303431663039623263303265383061336639316333633063333363 +65623836616433353039396366393061623461663430633763303363636637663366623137396138 +35393564376364633331373561383734613063366130373862636136636230373166366131323561 +35376239373438653838333035393330353562626339656534663364313161333465386236393339 +39626435396563353765623734353839363936306661393766383538333037333530326534663464 +62663061663938393531626663373033353436393764323334386130663262303466626562643961 +34373830636234383737346464623566353863383964363430616332336163383161633730653734 +65646636646166383763386135333938363635356238373666333265306662373266303335353266 +31373561373837336662343765323333613635313235666561626362636235363730643165633266 +35333137333564666238356261336531636534366531343831636662666136626136346263393435 +34646165396165303465633437646133313633633862633434666565376633333837383233343530 +34346366613065333866353538643962303434316466383230623161393066383837633231323033 +37636566356263663362663633303532323133646532633737386539386332653362343066323434 +65663631643039626166376564656136646238303533623737626431343763393137313738623537 +38633563623663383635343239303832613533363634396363363833313761313331376364616466 +65363331663437633461353932313831643431616433303563336535393133626664633235353132 +30393362393133396139613261323263333435376635646562626535333335353262643833353133 +64383065306437373963386337623333643236353239666336656238326137373866643738613862 +66626265363763313862303163313963346639323366316137396663636137393936636266373033 +35323235373934366431646632306137643834646437636336393932376433613466643737653762 +32666461663131616332666161336436643862623965303038316664333539346437633433306266 +33653031643839356536643734393461313666646133643037633634666437336133366430626333 +30643737366165663031393434396166333364643733366330373164656534633733313831623634 +39666336393432633034626537313832306330373430343565626464653661613564333865363033 +63383834613331376536326662393261636365623034383738383833626561366164306437636535 +63323765373638626537356366663433316331623236653335646438636237616534346462366438 +35383061633337363166373030343137313738393265643630653135323266343639303861666434 +37643139363834393331353265646563653532353263313363613466613562306537386134303034 +38663830323636666639336665633838613238386661663063373138383133306634616432386235 +66666130326339666166336234386364363631646466363165326234353733373132646665613038 +34636234306435646635343237613534643864303036383662373763663636393939353330356434 +37666163623439623938326365383939613238383234656231326631383731666333316539306364 +64343665633339363232306161323533663262306436613435343130383037343638326538363164 +39306230306364363466353939613639303735646362356463323466626637643030623134316263 +65623163326130326266613832643534353132356431316261643235363135353465653930363666 +61336338626538333833346637373739666630303330633733303165643866626231633165336434 +38346664636666666236396265386662623238346135343561373136363863663438663637666161 +31353838353561326135353135656462656265353631366631373932633431623638333636396138 +35616261353964613964383035393436636638396130363938636335313066333165313830633764 +61663362646130643365363737353037323838656532643132343435333536663131326162643931 +66653133363762386262633931303765366130383663656566646331313665383266653164323136 +30393266336235376230306134663065346633666636366439306338346631653761353561383663 +63656165353033356266353737373964666231623434366639373935333032346563623139623530 +65336265386461376230656363346435663666323236393665646330663534393336393865356334 +36353433613737396431386236643165306361333939353033303762313935336235393639353037 +31326234623234386366636533343436646337643134393566313864376436313531653465656666 +64333833396239616266393839343862343766666630316531313435656539336233633636373366 +33313562346338386266623134363332306564633334353531303039376232636138383436373431 +62393231313239663334343131633161393937303835316533346135623235636333363463343131 +38323933346531356661393536383637373331346333363132333037306363646336373262386164 +38393965333330303938666635653063336331323236646163343431353031333338653934336533 +38373762343464303731373366313265333639616135316138643438303166373237306539353736 +66303738363862666465636463656134343965653334333266623666633239663466376566306235 +30363435626638396433616336306661333930333932613764363331626438336263323966316364 +61343065356162616163646336313939333236663038653733623834336435666634373236646264 +31663730323664366130623161333432663230353863383635353638383036333631613330313663 +38383730663466333862626439633833656462616238613134363533326236316132333466643838 +31383031636539323732363335396230383137343766616462623736303731333164326232626435 +34336638656566383631376634633938303437643865363537353938653032653765663939316233 +37363363353435323533646335663233386531313938363536363563336539383333316539666230 +36303236306636313539653937633033306236386431386562396264643866356337323664393436 +31356364653165376638396534643662663965366432363762306533366333373630666439306330 +63616236343235306530346465366431356133616464653664353232306164366131356266643731 +30653563353432373461633736376238343039396139613934343037633532613663633761653831 +65366535393333616362326665626162653130633863396362356230363232396533383232636532 +63346534626535623330666161636535303332626236333763303330313663656466613238313864 +32643739633163656539656134613734393032386334343532323834616365353933653034303638 +65366666633239323439383563646433366436626337323766386434366533376235656135313138 +62303864333730376132643034653564383466313466383530393064656630626539363163666661 +61323063613135396437393437383834313734363139373665656330363933373739313330396539 +37396331386130326330303935353032663839343964646462353839393038353261363033356164 +35666532633136343262613038333435353230363665643661656562333339666336303539346561 +65643830383164396665646564663631383931363439353239333563623239313564663066633537 +63306164613131353434353536633939363439623062303631353564323739623031343638353531 +39306462623632363963653030336663323838366136616166393139326562643939343431663133 +36353139353636363936316633373766626661333165643965643631396263343535306537613764 +39333164333130666135336630646433666236396362346265376363613864353063636363333361 +39306234656264643538333562333135383162313437616334353366636664366435636233366537 +65343036363664366138383333343833636633643962623934306163376363336261666165313838 +39393039386131346266323462396364396363333465336461663936356433646565373636343263 +37303530613537393638643936656131643365353731333064353037623962613765316637393961 +30313965326536303234646461616132363063396238363732636537633734313238343931376436 +64636339626438346464623165303832626163373636373135636464353530396564393033663538 +64656532336131626464616530343232363363633236323962653332303565383337303766353139 +34663337383961373637663132363739343162346432653430393131396637383332373164616265 +34346637376665343365663232366534373730343464303630626233303630346262323961643663 +39663964646465346537613438633534663164636437663431646330346161336131323131313437 +39373931363934343534663037353533343065666238613966666534363834626130383862336139 +38383263666463613639393634383463646330353332313665333336356631623837353166616536 +33656264623663336436363462323566363732373364623664373430653436333232643732323936 +33636239323032353831626662643866333465313432623863666164393632303539313135653365 +35613564636534323065666135353762623034643665616638396563356638376134653337616539 +61316239626163323161616334373231396435653134363638383061653866646633666637313533 +64616136626431356630383134656534373335613961623564363663313962626239653234643730 +37616632613065383136613263643364343065636132313964663563626339636631623235333232 +65646139613662646632356132373634393834326366633662663133333266316466643432666538 +35643930653734646637616233656133663731383162383538343662346266343830653162633661 +35636332636239613132303630616465376465623763333130336631656432666166333736663038 +31626637393839653964353864653630353564353964653639343938333436336132643934353338 +66336539333037373738396634653032663466633966616264626263333365623761323438366135 +64346138373866656462393064366334386433613530613331623437616539326331316366303864 +62356261666365306361613065666366373938356433313231363739393933313634363938633461 +66326632616135656463633932336464366139353536396336353763633661626461386331303034 +64633337646136613536373431383261623637393361653336626638626436613133663135396232 +61363463333830623366333331613435643831616530373630353730633331633439613161366639 +39623035353739326338613634396632323932303265393932343761636637343938373936333961 +62393332396363346362333266613931373339356333386530383363323765653238363334336334 +66393433353732333031363765366665343966326533383762666263356164656531666663616261 +30313030353539643636323434313166633730646439383337383665613730616661333638356165 +32353632363536656236313531656562336434636637646632616565366461323465303464323234 +34636238656635656334646664333939633431353831643836636537326363336536336366333966 +61343237623963323333326130633337373834313639623664376230373332343130343930366334 +37303462653730316464663132313462376434373933336461303136623937646437646263643263 +39376139316535343465663163613562646365643738636231626332323862633736613264383733 +31373961336262666661316536393964623036373030663939353662646137336664303337613233 +35633639323264373732306561333366613161643839616436343963613066636265383235396530 +62346637346666616164363035623933653536363038313261636664663836656530626561363233 +30356138356131616664363131393462356338666634633331373364653335393664346536336365 +65333564333636643638373734393633343933373433356334656234326232366465313439663630 +61633135363539653564613839613333613661623439336230376232386233306164326663386561 +39383562653763383736356231636463616137323932353162366564613230343966306239663539 +39326537393333613935303238313662336434393964386535343761613736323066303562363965 +65363933333462653832383765366630353662333039376439353436383931316237376635616566 +33323038346661323264663630636363666538383962373935353232393037623334626532636234 +64356564376633343637326334303966313934373234636563663932353430333836356238363433 +39366533383936343164313730323831313730386231363461353561346263663138623431616534 +63336463396337363162356637633533373164616438626238373939346464343037336161626539 +63366435363965383065396661646234326337363865666365306137333639393966663963306239 +37353663306239633466373939363437353234343038326464363235393637353161323964633262 +37623164396137323239616130646335353134626631323037313130376434373261333336616538 +31373031333364366334663531613065613762306163613766323339313239393061653333623830 +61363431313734373731336638643239663835666636386665663562646531386632663234303831 +37346663353363333332643264643263613035393633613436313731613932653436353033643266 +63366136383736316136353761393834386432313865393438613464346439386564383935383361 +62393439363431336135333833613935613039376639643261303739616237656564313235396366 +33353439383637356166326664663465613061343838363461666563326537626661303839313332 +39663430643130363232643039666362343238326163663132396530633261356663393064386466 +33343633666231633734616666356364653939363961663361313732646361623737343837306463 +37613339656434393633373262623062356564396239316137333863316133363232376663356261 +63346130343738633264633461373839383830393361346566316463613034306265666534356566 +65376562396432343738623931366339333062306166626537313434623735396561373962373233 +66343137653132393237333762643732353333316266323234623539363430346462653163373766 +39373139666239393133373563346564613963373937613331306532346130353962353536366261 +61373762636533356135633230626164616364313565316166633234656437386262373230313534 +31633863346664636435366235363938633163613239643961373130393866613761383133346632 +64663465666535316565643637306438326631366437383134383661353037316232353137316661 +35653536336462613637316331313033643034656166333633653632313736306234646236353935 +62353534303030316631636637623838383238663765323137626230346438613231363261323035 +62326635386134313037363838343065346362393266303363313462343933383938373433656530 +64633332333665643037313039393361623638333162353862663135363937336132663738653434 +66366539623034616632616466393064383537616430353533353938663339373765623436333464 +61623866623662373866653863303033636566393034346262343930313631306365666530333636 +65373532323333373664633239373465313233613465316136376339363761353436636463386435 +37366139383536613862616266643933393666363137633863663039316366636435313666376163 +64316533313930343564313066646630643035316437303733643735653233623532393032323734 +31363261653963303131323232323033316165616534636536303162346533333933313465303461 +35313230373033643063366431323630303062646263396166303761616632353061396366363034 +37653839646334633133366662653766386432613834353237613239393536346562663162333364 +34326463306565303438356566653766323865303563386434646533616534346133663737383832 +30643562636563633930326231313265313062656462666563663662356530383635613261396563 +63666162363363663565393134333732303837613362303439666364663535316665333762316232 +35313339343962613734326134313432653732316665333536343533303631323937353435653961 +39646563343234376263366532396133313831303031393331303736636465666233633531303762 +62326332376463656463643533643665323765656466346135653635656433343031313766643531 +30393837366266626164323538393761343935333262343462383530663862353439313061353261 +34626531316362353163363035356562366130363931363166306639306135653638636235623037 +34306231613466376164363832366662623266653831336536383535623637626136313331613938 +63333234623330393562626564333163653961333561633838663236313335653037376361376230 +36326433353839666530383534383833353938303761366163616437316565643931633561343738 +31363731646463656562653930363531306362343265383131336531643563313361646462363266 +39303764323638646239336166303532666331396334376331363863626262356339656533386662 +32626230646164623237363836303032393964396431666139356562626366366239366139626164 +35636663663165366436633263663233633766363564333830653161373832396661366534646136 +66323131323536323830616633383965393363386332353262623466316565353336623964393039 +30363035333463653061343031396466623261383335653039393861613839666535373139343038 +61316161366361613038373431316164353434316466346538323762386434633566323266663531 +39386664643631353831626538663834656262306662346335366136376263356665396661663561 +65333130323333316666623362313263666466623339393263646264333966613539326437353263 +34623630396638383232316630323165363530313466393836373361386161663665323664323465 +38646530323938653961306233393130636239326139613735666133663264303931376465353661 +64366135666431366365383032666465313465636131396338646532383638383737643537396464 +31643139623066326161333438363932336564343637313637303262353737303732356239666661 +31616438656338623030656461626635306135626239616461623462366238616532363434613435 +63336663396130323531663538646531393335656461393135636331343332613864613037306534 +65343539613762313066306366393133643137383739633939316632363737383438643331313730 +62653439326465343834343637373361646638356634333764653136353161663733326135373331 +66346434326336303561616362663936666538636634306365666239353434333464636234393166 +66356134653764313863383161326632636539343765323239663434353031393761363832323432 +39663836386532303430636133653164336366313264366132643065643663366265663230303433 +36643762333630336364313962363137643563376437346638643839323233323261613566333736 +36386663663134656430303932353265633339396438613564363330396364373138353363363937 +38313933313039643034373835366437316633386638313735313932643837366363303263396161 +31393361636536303465653130383738306433363130653630643261353232666137383330636366 +31623533333631393432303563336330333564653963663032356464653030383164643533373039 +32616566393664373739306333333730653434303837613161333963666564313737616538653335 +36653762623935363433636562616132313834376166313564353735353965613263633132616665 +63333662326237613936623966323663646633653233343733396637373062336236616331303536 +63643862623465376539643736363965666565663630373964623735336539626335386464356366 +65356166366661306235393334313739626330396137343261663232663330623039303838623861 +31653062316465653961623532363433663936343666623939653036373531323561333461396539 +65343333633436346135383666356135396539316139623166653862356363323830366466626265 +62653063353735623765356264386338313637386234666231333466616539633837383662343636 +63323661666235306636383335353966313331386261376161636538316637386334313161626432 +32363032306561613333363731383366373736363434343139663366373336323638643761663432 +31363762636330653635623861363835326438323434326264326238343666373735643035646662 +39623830343231353565653933363233653136356431383537333232623633633363316433386364 +65363038346634363233613762303535666532636363316461616165373763633538636264353530 +30396632303065633133356237646331323139306437366461363734393536326636663132656233 +36613861353964373164656335633338356238353134343532623966633532666637643562663161 +36333438623631626139366565303830643930646264646163353538643265643938653739356638 +35653466353739636432343465653162666531383932383962323564386633613434306138336662 +64346633313038646333353063343131326335643032616265343564393438373436643237383264 +63643431613762313766393466343361653535386538346636626364636633333463616137636163 +61613330613934346331623264616536313766363666386566386661326531666639613363623238 +35353235393964663934313032643136376630333638653533393633316333326631363637343834 +38636663303634333236663036303433333632323739623039373461323834396139363635666337 +36636633613139353665666334386130663864653264393163366239616461633261373935336432 +31356434653634613166343365643535313436373037663737353436353061616663356564316436 +61663431666364336133646161326361343434313038643263393739346439656138646332306334 +62333539326634623264393063343830373266393966393032653637353362663332356332373433 +64633962376432396335346662626436383039376533326338363733343032643065373639326331 +62646464316465613731376131646430396336383761383038633061353761363838653763333530 +39333664333333626630386432343732393733393762323535353031656437326239633038666464 +61353739393039666438623763633233616562613230616436353561323335623565623064333061 +34653330323365643361343436613864626234393339353337373364353363616562306438356561 +65616631623838636633363532353238346563353039633363313732376564363638623432666133 +36656563383237333961363661636135616366303537623038613730343834383935393863393966 +38303438646534393836626135396437623136653934356430366361336663666433393762623530 +31663831356637366233663933323965643761396430393033316461663166636465323033633163 +63323163353963323731646532653962666231393864376337616533396131316530383233396266 +36346666343232343162663635346663623466313264366533333837306433336562393332376235 +64613263666536356235393362376533356439633735613639323161636439393932316534393433 +37366465353236343636626639363962393730666334636366323431376266613736643165613031 +33383038643965663265356266396532383466383030303964366336646564656537303164616561 +35333261323763316634656437363931393039303237633261363831313037303836326530383434 +30323762633630323932663031626266616137373530666330373130376535613636393831336230 +66373032663930376534346263633036316363646639326239363164396163646662353337333232 +32343262383833666462383937663335616365646439366461353134663133626334336136376661 +30656363666661653064326466336364386262373862373234636361666366363863383735646439 +36666234633337383338333934353464613932393630663966643933666534326632663732666364 +30333466393765353737636133316637626139343465366635343336363665343566356339393630 +36303165376162373562396636323430386663653335633535363334383536393031336362653232 +30356664353832333333393631316131653766633266313931646236386132376363356330323637 +62383231393564353135613137353730356335373734346333326666346236313831643034393535 +65346439386335373764643433646636303065623964353364653531663630653535663761363166 +64633139386139383736373665626434616235383163623438346562396638363064383663396538 +37633436663934646361623763383832643839636166326265643866643731613137326535346663 +39366331373464343463323033616332323433303662363832313030336430383738336430643730 +63333033323235613061346234393433613665646335633232366538643862643663356666376164 +34373462323033663833383763343337313631376433626138613534343736343535313133373732 +62356664323362333039666464626164383132653965613065356334656666313236623563353135 +64346236343237366136376534343431656330333736333162356636336561333366336165303261 +33633130313137323330396135346366656564343465303165353861323535663333656435633635 +39363938396235386331303066396137616231383234653962613166663631313539333138653165 +31653062323139626532636636353438636165643434383866393231373665313437663732633539 +33353865653530333132333136326230636536343261663833363932316338366563336538396561 +64383562343736313335313632393664343262326436643833363836613333393736303362356235 +32306531383434643862356439633066663436616162303931623163316232323234363130363762 +37376265376236333961653666653530646162373137373833333235313862376664333165343365 +35643831373231663535383431326265346330626139343930376230656636316664336663303764 +36396335333262633339623235623930646265626565626438613364656363373263643033303336 +30383233323531393035363632326231393930363237333835613533666337613034343938386666 +33633035323965643034376138353134623132303264323033623438643661396635323135646339 +65303334313465643138613163386434323331646465313532343264333434343162623136663738 +30626231616333323065646535636331663961363462306638363465643738336230353732303262 +66363133343839623039643931653831323439343839323632616438336530636262613032653562 +30313039393130393766656265663331373930353865623237313032376334616232313038616137 +63623538363366386335313566353338323563623338633162323536616436616431363739643966 +37333533306538643066383064643161633761363531643563656439643265333361313365656635 +33393539323333653339333339323639376337393235663438313438353338636462373935313037 +34613832623161333262333561326235626362336266343863623864653064366331653737646336 +34613432306362613032313736646134313630346438393431313135313831373438623761633534 +63323737623532303230623363653564346337366563353933653037373937306166643131643531 +33333832366362316161306136646236653339653931653436316364353631366131396563313138 +62633731343335316265356164383966396533373666363730356431383931393065306565306631 +36376539333162626634333936323362313134336335363561383064663765663062393530373466 +36626431353834393931356363313132376364373066343861646234366533336464353534333363 +62356232333931313939633139306633376130393933356137333866383539616536366166643430 +61626166383732356333383031663133363238323934636534346633303334303361653936656566 +63396235313037663730653833356465623766343232636462623266353466383235656530333538 +39373539363863643735303637363333623133353766303431613664613861643036656535353133 +35343734633934313035663233353331373664303365336536323832323037643566383363623163 +31313534373261363030386666396433316262326466363539383034626136663864343339656233 +66653762646534633762336662346337313061316331613937336534373639306331613965656231 +38393133366161366662336635613534336236613364623938323761343462363163373436356330 +61636233623935346565353961663738306565383062363838336563623063356231653766616563 +64323439353430643566323431623538623531623239656666386237393637306638623066346537 +66313366316239346334376635313033626661653362363263626261353937616162363939316135 +61353432303864383635333664656134643936656137366563663365353131623532666262643531 +39353434376434383032366330623165313138346334623835383864376361386265356665393933 +33303236393034623661373334353037373531636337333931313534373163323363346235663834 +61326437653836613264643236366234643534383330336366323735393665376463366436306266 +34383331356130613264623631333132653365626166383762393335613165626465313063333934 +35323337353131306438333333643033393164353733326364616237613465663535326563323437 +31623662343762323533653363626362383866323333303363616139316630613338336537393037 +61616537643138346430376563366666626333636237653836346237313636323830613165376334 +32656338353430366231626366386263383631383931663339363038643036353966353739653832 +38376432643866356161636361343836646463306533303131333330626661303266363132303735 +37336263323063636433386536626437666431346461616436353239353836373835623963393836 +62656637663465333232386563623733303063363765393537653063313163343136313366376135 +30623134396132316433336364393163313432353433363166383635353130616333303339653234 +38666339316534333933316335383362626138363935663135346636663839633139353962376536 +31353633343738663331346165363866343033313565306530623337343434343365643261643061 +64306238363835636163363037346639363931323338636436376132316235323430643134646136 +39323030623536633230346331376136646539653330336335656264646439653736323332363233 +64643731613662623265616535633462353136383664356164323463666437626633306136643765 +66323430386330373938396566393831383631326161336235393539373030643838306264666663 +64393363373830353433386137653765333633336231336366636136373365386431613533333532 +37376533303730323738373265303930663961346236613832333961316336646364313637356136 +64623231653536326138386232373765363131303334626138373761343536383064323936303631 +38386432396139326464323032333261623365376136643665393864393831383939663933343137 +37343237326539303063643539666538643933363032613130303535383265663064333338653632 +37333038373933393762613462373462633637323437323034656164313433383333393064666664 +64333938363164653431613932613036613338333637366633643364643331663037356664303732 +30303061643337336530383430653565386133613137303937613036323037323262663439383839 +66393863646263653639613039386231343263636632343435666333303339663230306162613935 +35656530623761356563353166653635396432613835353834333332333763326465646132666662 +38663434636538623037376632313164633534396437646430343630343166336237613063386562 +31643439306539623131376564383936333239646537633961333566396533623934316639333132 +32356463336535623135316131663735343638353764653235393237623931636234333637333834 +30613662316437656366373833613231356435633131386332306637623732623332353930636636 +30313535623631616234623961336165316638303133376466333865306331333335643761313133 +65343564326438653338323234633665386661303833393137393137373765393630656337343665 +65306431316461313030653036623366316438346333633661313632316432623263346666623638 +61303534353161366261623263346336666361336331656234646263616139663835303136653531 +30643931336239626235323333643437623935643564326533393338363134346562393736613839 +64306536336433613634373633623031356335633030303434666230326434633162663130653131 +36653237366339326634313333393833336436393964343165653536653139373563623266323932 +64393164626334366231646635316363636432663838313565366430666362313031643132303830 +38653137633730303832356565373731656439333536633931373533376563313633333866333839 +31383139643030633632636236376534376334393833363066666161386262643734356539623762 +32613737386438633862343631653062663434656637373534613061623938373266373932336638 +37643938346331303035363232383032383838663962626331663437356434386663616463646664 +63376364666332333937323636663332383132386365306435333130303265613066363033313132 +36313637643966613331343033613036306339336365343737366638613638396430363734376463 +63623035346262373236366131393337626231373766313666303133666439656165653830656239 +30386362653834663431393163356266643830323065326330323561623939323131653263383463 +39383561393532393335356538633731653634613738303961613238366637623634343032623437 +34333738336139646338326361633663336139393566353732646632626162363735653031393364 +38343365346333356462636239613534316661383436353535313531396665336265623539613539 +30306638353133393632343535653030326364616562383136373331313033316438376133626462 +34396333356661643865636666666233643435363038376133383537623662663735373534623830 +66303037613130353236653633353836303333363134323966343537363965316333643165336164 +37393138653162323362636638386565366161316364653935393561323566376161393130633437 +39633166636666383866623039663530373766333362353263623537356265343432643666356439 +37633332313361656637646139353234386166646263663732383736316562396537396263646237 +39616266363037656534636433383838666331646163313539313833316239653532653566653861 +30643038633863393933646237323634626263616438656532616332393037306438333037646133 +62383164326461626163646238323734373364343263376362303135386538323161666663333861 +34616131383165663439303736346238353834303939303933623334326634663364343232613230 +35643464303838656531663737353462653233633064363464656537363064313365616536366531 +61353633363530373466313662666432636261626663303635353434366663303764373533396531 +66336136316162386333646539363630333864396339353164373962343036666563343338393161 +32303730326531643361376663353034396665646639313861323033303163626131333366333266 +38666565313965646538653338643133666232396261356264376636326139306631383034613232 +36646265326238333636633233366366303638356336353933623761643866313764376132373137 +64613931393566613335313730336630333236626564383836636130666164623934393866653266 +65616533373561616165623066633464343731666231343533653165336361373464373564346266 +36333566346433343335643030323338303635346365306166643866616238626237373932373639 +63316633383131323235663639333432376137653662373635373434373833383637356330383133 +34653333323366363466316362383034376561643635373538326530333736613439616233393232 +36356536313536306432633734323431393462356336323766373665306331306237343063616433 +34336631646133336139353930376333643762643833386232306466303131343834356361353337 +63613466633030343538303865393263346362303761623365633166623939333131333462316466 +63396537333163316264626663353737656364393136356663656538333963656536393136313364 +66383730386630346432386230666239313966373430643231613435336534303564663331363365 +39393737633539663834336336626664323363613431393936313333306164386439353565333366 +61333034646362326633303936333163383066643862643332363830383235373733656361346265 +30623237376461636136616132323334666362643832356132306631363235633333316563636363 +64316462656638396639623264343037383032316565306164383763373632383134363637656636 +66633964306132363266353533616338356339666662323765376239613063333665326561643237 +61653537346533333265393632656364353335316631356466633839666162326630626134376438 +62653632343734326236663362386131396530346536306633333665383364656531356438663131 +39336263363263366164336233333238613232323337626134663635306434336163663831343662 +66313631376461386566333966373136323138383534366131646662386362383336316163343166 +66373464313661383138366162656531366163643238323037383133393261326234316664323736 +35626139386361383533666531303965616237343666643730383564336335333661326565393139 +63653234376236663764656363653362346335383933313330633865346364356233646330306135 +62303633646231636634633661616562656464326435323736303037663864353331323364663935 +64373762383735653433393361376163313431366336313264643931636631363661633663353166 +64393663363532653834396262363636343162346532643538613235313662376135386332346265 +33356139343762626435373032326462396366393563376461386662326532326364336533363636 +33376462633030356633663365313261313636663936333831643966346363626630376338623530 +31346362316634616462643662356336316535623832636536383166616538306236666239636139 +62383065633934393937333966306662666238653434633437616533663964386234356533656264 +64633930316162643965313561613936366630333634336565383966386363333539636364343135 +39396333653337313933666664613839306238616263303761333864623832326334343931623234 +36313332306330396632333035643739343535633539633231636535653733306239666631343531 +33646563353766316330346531666539336530353739373930643662626436663835333261363739 +35303262393632643232636337353637653533333664353432396131623764373337393139646134 +33333362323435666334373738333734343837383237313735323837383933346566653836313536 +62376562396365653065373365643637326566326632663833396531623963313739393037613462 +36323433363264313436663232653338316364373333643330363562363332623739326235636161 +63333036653834346631303835383031623562316631316330366530393634313130343664656539 +66353965303433333966366561336137633463373432343864373237663230663031383964336630 +34643764323162313233393562616432646631393930333738343733613532303239623766626334 +33653062326535393531363830356363633537633838366137343731316262316330323762333766 +66316331306339666661363261643732616633323937666164303730383039356430373333313062 +64363866376266313737643763386165313931666335633932326136336437393234333932623062 +30666230653939313936646334633064336131623531316632333262623365313336363762356565 +35343533656561623134373034393365363833353138613737316136643464666564646263393133 +64623232313537323032616138653939623964376236616531353963653138393463633464613138 +39643461323331623537373830323865316538393535326232643736303931383035333535356632 +61306437663466313834383561653534363235353433643434323738346664346161643437343235 +62623666613863313963626165343831393636633364623137343634633530366264373431323265 +38356233353436356336646331343238306334313133623134346130336462636239626363363338 +66333863323937626537323539373161373837346262333761646133646637323538346661366532 +37653935663363373630303566366263353665633930323432393737646264616237366539613537 +61333931633464313134306163333661613765383037386161306538353364323837343933646337 +34663066646535396139316138653430613334303461343961616533623866633166316238653637 +30663430353433366136646635636637653737663332306130663031333363353930386464663264 +33363030656231356232373234333662613735353831353863613137643432333332656638386434 +62363634663264356431646662636330323234613634653733316362366165366262656237336538 +65666661396435616331616535623639313330366133633539313232396430653231313730346436 +66646230303339623936656139656162613433353239633539373963363132356139323862353735 +37326233383532623266356334333235336363353864336630616263373531613334353038326132 +36626136326238346538333136323433303632633436303166373734653532636531323732633763 +38626661393836653333653364633935343662653662393931313563323636643837383665343264 +31343339636465393461363936336333633335306531636363363431346138303431333661306338 +36646462333638353831376635633161613436613136366136613761343034653061383131633034 +39346462373661633338663039396663346338616136633965373265386132323230353333316539 +66633335366462373938653061393063353164343561343831376130666666626231643666643961 +63393162386434363733306461663230306138626537303430303033336663373965366437313230 +31333865663566393638373464383931343637626334656166313865313030646339323234316166 +62343735666665626234393931353536656661626636373436313236653636326161643339343466 +35363861663362653930356234353765666539316634366536386434393464323562383737303363 +64386339373961376437626235623933333263363031663139646163373636613530313538356363 +61303636396262633863373566666237313462363936323963366638636435313237386435333435 +39373538613337353161313266383663613938363435323934303838666365393464663162633935 +64373239393532623736623763353038333666316436393638326263313138353835333766373536 +34626130663766333830346439326232343437633765646239373039373061383961333733343533 +31643436393263383063343932626263653031633439633932666434333861386636633434633130 +62313130333565613063613138396465653430636131393839353364346362303563643031333964 +39326430653534356364333738646638393039626363636138343833666565376530666530373461 +65346439333830376664383636633061313538326335396331633139616635653733356136306135 +36366330373662346230633961306135326363353962326263643063343930626133386637626230 +62303061616538356162663133336365393263653133336661643666656336616463643962356338 +30393130626233326664653361303138353632323436613363363661636463346162346534366563 +32343139356136616537306466653966373165396664323838376537633136626535313536343064 +34343138626237646238353030653766633566306238656431616565373639356461373437356461 +33643435363366633263626330616136643265396539353432393166643436626361633837653364 +61663136316363333363626131373636656462356366376533653539653065343331343839326262 +35303234636335363637346131656364356234366463383666336530323362626333346232376331 +37363037616261663738323436333163333265633333323331643939663566366161633037323839 +30383530613531613439613337303238363339663765366430396538313066313663633739326161 +36376636303965623265656561333762666230643735316135626264616533346530653230663430 +32363538303238373139373439633233386262303336663863343539363965616331346635313463 +64653836313063383232323537383838316538343861613063316561353934633732646562613131 +37666237393732343032383532623432393536336338356464383863663439323362326262323461 +35616531633831366563623463626266656235623932336164346264666463393661333537613566 +36393064646132363536656165623031306239393539323566313735663032376132303837633238 +62333934356337613862396630356431353337393338373363323034363766643236623139643436 +61306163643761366430336639623865626230393165616134663862336439636630656638656431 +64313263366365613565643261396664366635303264356330643836653566636532306663393566 +30656130303665623630323536396333306563663435636332653364356663383362633063656338 +65656265383633303531386435396265323334616261633665373837613233383138373837383633 +64343836666162623162636365393561396638646631393534313533323437666432323932306130 +63643061613434616332343633636230653163626631333530633566636530326239376362383961 +63326335616430633635356534353731653832393730643161623534363862376433373164323461 +66383133633136626162646666363036633263396632303639326566376133343163393263323133 +66636264623466363066663637666262633839333765636538383330656539343637306134363135 +63626235383461623963663561336530626234366166383335303966333265363333383165363536 +61633733343966356265343264346432653565393165333538303562653962653366363132613034 +38633466333761343865333037383831363566663862666537656331643930343535623537663463 +64663936313533666630383566306234373938303534633234646462666432373961343032306366 +3262 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/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..3e1e756 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,6 +62,7 @@ - okular-extra-backends ## needed for CHM files - pdf-presenter-console - php-cli + - php-sqlite3 - pipx - planner - pulseview @@ -82,7 +83,7 @@ - unison-gtk - w3m - wireshark - - zulucrypt-gui + # - zulucrypt-gui ## no longer in trixie autoremove: true state: latest environment: @@ -155,6 +156,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 +168,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 +186,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 +245,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 +274,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..50a989f --- /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=7 {{ 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..07685bb 100644 --- a/roles/lmn_kde/defaults/main.yml +++ b/roles/lmn_kde/defaults/main.yml @@ -6,6 +6,7 @@ kde_desktop_pkg: - 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/tasks/main.yml b/roles/lmn_sssd/tasks/main.yml index ed44ce5..61e6441 100644 --- a/roles/lmn_sssd/tasks/main.yml +++ b/roles/lmn_sssd/tasks/main.yml @@ -13,12 +13,23 @@ mode: '0600' 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('') }}" + 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..3d8b79a 100644 --- a/roles/lmn_tmpfixes/tasks/main.yml +++ b/roles/lmn_tmpfixes/tasks/main.yml @@ -8,3 +8,19 @@ - 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" 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