macOS shell vs process substitution permission

Fórumok

Van egy Linuxon teljesen jól működő script ami macOS alatt elesik. A gond az hogy a külső parancs (hívjuk mondjuk ssh-keygen-nek) kikapcsolhatatlanul ellenőrzi a file jogosultságokat és nem hajlandó tovább menni ha ott group vagy other access is van. A problémám az hogy ezt egy shell process substitution által generált pipe-ra mondja aminek nem tudom állítani a jogosultságait és magát a tartalmat nem írhatom ki normál állományban a diszkre.

Írtam egy rövid scriptet ami teszteli a különféle eseteket.

touch xxx
chmod 0600 xxx

echo 1
ls -l xxx
echo 2
ls -lL /dev/stdin < xxx
echo 3
ls -lL /dev/stdin < <(cat xxx)
echo 4
cat xxx | ls -lL /dev/stdin
echo 5
echo <(cat xxx) | ls -lL /dev/stdin
echo 6
ls -lL <(cat xxx)

Ez Linux alatt teljesen jól működik.

1
-rw------- 1 user1 users 0 okt   13 10.51 xxx
2
-rw------- 1 user1 users 0 okt   13 10.51 /dev/stdin
3
prw------- 1 user1 users 0 okt   13 10.51 /dev/stdin
4
prw------- 1 user1 users 0 okt   13 10.51 /dev/stdin
5
prw------- 1 user1 users 0 okt   13 10.51 /dev/stdin
6
prw------- 1 user1 users 0 okt   13 10.51 /dev/fd/63

macOS alatt azonban a jogosultságok rosszak, kivéve ha normál állomány a bemenet, de az nekem nem lehetőség.

1
-rw-------  1 macosusr  staff  0 Oct 13 09:53   xxx
2
-rw-------  1 macosusr  staff  0 Oct 13 09:53   /dev/stdin
3
prw-rw----  0 macosusr  staff  0 Oct 13 10:19   /dev/stdin
4
prw-rw----  0 macosusr  staff  0 Oct 13 10:19   /dev/stdin
5
prw-rw----  0 macosusr  staff  11 Oct 13 10:19  /dev/stdin
6
prw-rw----  0 macosusr  staff  0 Oct 13 10:19   /dev/fd/11

Egy named pipe-al meg tudom oldani, de az elég ronda és kezelni kell egyéb felmerülő corner case-eket is (file rendszer jogosultságok, név ütközés stb.)

Mivel én magam nem használok macOS-t ezért a verziót nem tudom, de elvileg a legfrissebb stabil verzió van fenn a klienseken illetve a legfrissebb Bash brew-ból telepítve. Esetleg nem tudja valaki hogy a eme technológiai csodát miképp lehet meggyőzni arról hogy ezt a működést fejezze abba? Lehetséges egyáltalán vagy marad a named pipe-os bohóckodás?

Hozzászólások

yes | ssh-keygen -t rsa -q -N "" -f >(cat) 2>1 | grep -o -- '-----B'

Nem volna rossz tudni, mi a valódi probléma, amit nem lehet temporális fájllal megoldani.

Hát sokrétű a probléma, macOS-en az ssh* alkalmazások nem hajlandóak semmit sem csinálni ha a vonatkozó fájlok nem 600 jogosultsággal rendelkeznek.

Mivel Árpád nem fáljba akarja rakni a kulcsát(merthogy az ssh-keygen csak fájlba hajlandó rakni a generált kulcsot - mellékszál, hogy az ssh meg csak billentyűzetről hajlandó bevenni a jelszót), hanem egy átmeneti változóba (ez mondjuk túlságosan szerintem nem biztonságos - lehetséges, hogy direkt van ez a korlátozás), ami tulajdonképp egy átmeneti fájl mégis shell szkriptben (wtf), ami macOS-en nem 600 jogosultságot kap alapból.

Árpád sosem írt még shell szkriptet ami cross-platform, így nem tudja, hogy mekkora ortó szopás és mély fosgödör az egész shell-szkriptesdi.

ps: valamint ideje lenne már végre kibaszni az összes shell-t a picsába és valami normális szkript-myelvet használni helyettük.

Árpád nagyon sok shell scriptet írt ami cross-platform és sajnos tisztában van vele hogy nem minden játék és mese ezen a területen. Eddig mindent meg lehetett valahogy oldani (ezt is egy named pipe-al ha másképp nem lehet, de szeretném elkerülni).

Az ssh-keygen nem csak kulcsot generál, csinál az minden egyebet is amiben szerepel SSH és kulcs, ami nem biztos hogy jó ötlet a fejlesztőktől de ez van. A probléma amit meg akarok oldani hogy az SSH CA egy környezeti változóban van és szeretném aláírni, most nincs előttem a kód, de valami ilyesmi van benne.

ssh-keygen -I john@doe.com -n user1,user2 -V +2d -s <(echo "$CA_KEY") mykey.pub

A felhasználók 1-2 naponta futtatják a scriptet ami új kulcsot generál nekik helyben és alá is írja. Hogy a CA_KEY ténylegesen honnan jön az itt most nem érdekes.

A cél hogy a CA kulcsa sose kerüljön ki diszkre, így ha elveszik az eszköz akkor csak egy rövid ideig érvényes SSH kulcs van rajta, nem kell végig rohanni az összes gépen és törölni az elveszett kulcsot illetve hozzáadni a user új kulcsát.

Igen, egy rosszindulatú felhasználó meg tudja szerezni a CA kulcsát, de annak a kezelése most még nem volt szempont, csak az eszköz elvesztése.

A kérdésem célja az volt hogy hátha van egy macOS beállítás ami módosít ezen a működésen, de ha nincs akkor marad a workaround. Ez a script amúgy is csak átmeneti megoldás. Elvileg, majd pár éve múlva meglátjuk...

> Hogy a CA_KEY ténylegesen honnan jön az itt most nem érdekes.

Gondolom, ez azt jelenti, hogy fájlból/adatbázisból jön.

Mindazontal az OpenSSH forrása elérhető, belefejleszthetsz egy ilyen opciót is.

Szerk: egyre kevésbé értem: a végfelhasználó önmagának hitelesíti az általa generált cert-et, de ez teljesen biztonságos, mert a felhasznó nem ért a shell-scripthez, és nem fog visszaélni vele.

A felhasználók alatt itt most egy szűk admin csoportot kell érteni és hidd el a jelenlegi helyzethez képest ez jobb, tudom hogy nem tökéletes, de apró lépésekben tudok csak haladni. A gond az hogy ha bármi mást raknék össze annak az üzemeltetését is még ugyanaz az admin csoport végezné, így ott is vissza lehet élni vele.

Az OpenSSH-t nem szeretném patchelni és utána a patchet karbantartani mert hogy nem fog bekerülni az upstreambe az biztos.

Sztem.itt a kalapács és a szög esete áll fenn, ezért érdemes lenne más oldalról megközelíteni a problémát.

Az SSH authorized_keys-ben van lehetőség beállítani, hogy meddig legyen érvényes a publikus kulcs. A kapcsoló neve expiry-time.

A generálás meg történhetne egy secret store-ban, ahol eleve van lehetőség az bejegyzések lejáratára és talán az automatikus törlésre is.

Ilyen funkcióval a HashiCorp Vaultban találkoztam, de biztos van itt más, aki tud esetleg szebb, jobb megoldást.

Így a kliens gépen nem kell kulcsot generálni hanem kérni kellene egyet a secret store-ból.

A publikus kulcsokat, meg lehetne teríteni Ansible-lel mondjuk lejárati dátummal.

Tehát a script csak kérne egy új kulcsot, és triggerelne egy Ansible playbook-ot egy másik gépen a publikus kulcs terítéséhez, már amennyiben ez külön szükséges és nem LDAP/AD-ból jönnek a kulcsok eleve. 

Ez a terítésen bukik meg, több száz immutable/ephemeral virtuális gépről van szó. Az sem triviális hogy egy adott pillanatban lekérdezd hogy éppen hány gép is fut.

Ezzel a megoldással a szervereken elég csak egy statikus UserTrustedCA és a jövőben a kliens kulcsok aláírását ki lehet majd rakni egy külső service-re egy shell script helyett ami a user gépén fut. (Erre van is már kész megoldás, csak fejből nem vágom a nevét.) Ennek most azért nem lenne sok értelme mert a külső szervizt is ugyanazok üzemeltetnék akiknek az aláírt kulcs kell, így ott is vissza lehetne élni vele.

Több 100 gépnél az SSH kulcs dinamikusan jöhetne LDAP-ból és akkor nem kell" teríteni".

A generálás történhet másik gépen, vagy egy Vault jellegű szoftverban, ahogy fentebb írtam. Onnan a publikus kulcs mehet LDAP-ba vagy AD-ba.

Nem világos számomra, hogy az ephemeral/immutable gépeken hogy teríted jelenleg a publikus kulcsot.

Továbbra is azt érzem, hogy próbálod kötni az ebet a karóhoz, de én sem akarok senkit meggyőzni arról, hogy amit én mondok az a tuti csak úgy érzem nem igazán szeretnél a körön kívül gondolkodni.

A HashiCorp Vault jellegű szoftvert security team szokta szolgáltatásként nyújtani az üzememeltetésnél. Ha nincs külön ilyen team, akkor is le lehet fedni 2-3 kollégával, akik admin joggal és írásba foglalt felelősségi körrel rendelkeznek a rendszer felett. Az LDAP szintén ugyanez, mert GPDR szempontjából érzékeny adatok lehetnek benne. Tehát az én meglátásom elsőre, hogy kéne egy kis átszerveződéss hozzá és sokkal egyszerűbben megoldható lenne a szolgáltatás.

Ezek AWS instance-ok szétszórva több régió és account között, nem egyedi gépek. Egy sablonból indulnak el ahogy a terhelés kívánja. Az AWS lehetőséget ad arra hogy beállíts egy, azaz egy darab publikus kulcsot a sablonban. Ehelyett van most az hogy a gép konfigurációjában van a CA definiálva és minden admin kolléga, nem vagyunk sokan, saját kulcsot használ, nem egy közöset. Így eszköz elvesztése esetén nem kell megint végigtolni egy sablon módosítást minden gépen ami alsó hangon is egy hét.

AD, LDAP itt nem játszik, a gépeknek teljesen önjárónak kell lenniük, izolált környezetben is működniük kell a boot során kapott konfiggal.

A Vaultot ismerem, használtuk és várhatólag fogjuk is ismét használni - most más van helyette. Dedikált security team nincs, elvileg az infrahoz tartozik az is (kis cég, kis foci). Az átszerveződést meg már régóta javaslom, de nem az én szintemen dől el.

Aha, szóval ez AWS. Gyorsan utána olvastam. Hivatalosan valóban nem lehet, de létezik a nem hivatalos megoldás annyi hátránnyal, hogy létező vm-en kézzel kell frissíteni, hogy a beállítások működjenek. Tehát ez nem annyira jó megoldás.

A fenti megoldás itt van leírva egyébként: https://stackoverflow.com/a/41486527

Ugyanakkor inkább egy másik bevált módszer felé mennék. Egy korábbi cégemnél az volt a megoldás, hogy volt egy Linux jump szerver. Oda mindenki a saját kulcsával ment be, majd onnan érte el infrán a többi gépet. A jump node gyakorlatilag mindent tudott logolni, hogy melyik user mit csinált pontosan (összes parancsot!). Ha kompromitálódott volna az egyik kulcs– akkor a régi törlésre került a jump szerveren és a usernek új kulcs generálása után volt megint hozzáférése. Igaz ez on-prem megoldás volt, de megfelelő módon ide is átültethető lehet akár. Ja az SSH is le volt limitálva a jump node-on és egy scp se működött direktbe a jump szerverre. Ezzel csak arra próbálok utalni, hogy lehet szépen szabályozni ki mit tud megtenni a hálózaton. Mi a jump szerveren keresztül mentünk mint egy tunnel a többi gépre.

Az utóbbi megoldásnak van egy olyan előnye, hogy az adminnak nem kell tudnia a privát kulcsot a rendszerekhez direktbe. Ha meg rosszat csinál valamelyik admin, akkor minden naplózva van és bizonyítható. Erre lehet beállítani log figyelést és riasztást küldeni valahova.

Admin gép -> SSH saját kulcs -> jump szerver –> SSH előredefiniált kulcs a sablonban.  -> cél vm

Saját SSH kulccsal közvetlen nem éri el a cél vm-et. Ha pedig kimásolja a cél vm privát kulcsát, akkor pedig a tűzfal és az ssh is tudja blokkolni, tehát sokra nem megy a kulccsal. Szóval innen már lehet csavarni a dolgot minden irányba. 

Egyébként egy harmadik oldakról megvizsgálható az is, hogy miért és mennyire kell a kollégákat korlátozni, leszámítva a juniorokat, akiknek bele kell tanulniuk a rendeszerbe. Nekik nem kell hozzáférést adni mindenhez az első napon és kell egy mentor mellé, aki segít neki betanulni. Lehet egy kicsit jobb szervezéssel hatékonyabb lehetne az egész.

A security fontos dolog és addig spórol rajta a cég, még egyszer valaki be nem megy hozzájuk és el nem visz értékes adatokat. Ezt célszerű felfelé prezentálni, hogy melyik olcsóbb. Ha meglopnak vagy védekezek ellene amennyire lehet. Pénzügyi szempontból az első a nyerő (spórolás), majd után mindenki kereshet másik munkát legrosszabb esetben. A cégnek viszont a védekezés éri meg hosszabb távon, mert ad egy biztonság érzetet. Az árát be kell építeni a termék/szolgáltatás árába.

A security felépítése nem kis munka, főleg ha jól akarjá csinálni. Ezt üzemeltetéssel együtt nelet csinálni. Az egy seggel 2 lovat esete sajnos.

Köszönöm az ötletetelést. Felidézik a régi SCB supportos napokat. A hálózati konfig miatt nem lehet egy jump szervert használni és ahogy lejjebb írtam van aws-ssm-agent is. Próbálkoztunk vele, de végül el lett vetve.

A több kulcsot az SSH CA megközelítés megoldja. A szerveren csak egy (publikus) kulcs van, de minden felhasználó sajátot használ, így az ő szemszögükből olyan mintha sok kulcs lenne a szerveren az authorized_keys állományban (miközben az üres). A szép benne hogy a módosításhoz nem kell a szervereken végig menni, elég csak aláírni egy új kulcsot és rögtön érvényes lesz és mivel rövid ideig használható, ezért törlés esetén sem kell semmit csinálni.

A külön security csapattal egyet értek, az ha rendesen csinálják akkor teljes embert kíván. Több scenariot is felvázoltam már a managementnek hogy milyen károkat tud egy rosszindulatú felhasználó okozni, de nem igazán volt rá semmilyen reakció. Ennél többet én nem tehetek ezen a szinten, saját zsebből nem fogok egy shadow security teamet felvenni és fizetni.

Van az is, de a tapasztalatok alapján néha szimplán nem működik (kb ezer gépből mindig van 1-2 ahol fut az aws-ssm-agent, de nem működik a start-session) illetve ami problémásabb hogy szükség van arra hogy akkor is elérjük a gépet mielőtt az aws-ssm-agent elindulna.

Emellett van pár nem AWS gép is (tényleg nem sok, de lehet hogy több is lesz) és azokhoz is ugyanezt az SSH tanúsítvány alapú autentikációt használjuk.