Célgép-előkészítés

Egy célgép nem attól kész, hogy az átjáró eléri. Akkor kész, amikor az isg system check azt mondja — és ez a verdikt nem ennek az oldalnak az összefoglalója, hanem az a definíció, amit ez az oldal leír. Minden, ami itt következik, azért van, hogy egyetlen sor OK-ra álljon:

Ready to broker: <host>

Mint mér a „kész"

A készenléti sor hét alellenőrzés összegzése. Maga sosem tárcsáz semmit: mindegyik válasz egy olyan mérés, amit ugyanabban a futásban valamelyik szomszédos ellenőrzés már elvégzett. Bármelyik alellenőrzés nem teljesült állapota FAIL-re viszi a sort; ha ilyen nincs, bármelyik nem mért alellenőrzés WARN-t ad; OK csak akkor lesz, ha mind teljesült. A nem-teljesült és a nem-mért különböző verdikt, és sosem olvad össze.

# Alellenőrzés Akkor teljesül, ha Mi méri
1 human_access rule A ca.yaml valamelyik human_access engedélyszabálya megnevezi ezt a hosztot, hosts:-szal vagy illeszkedő host_labels: szelektorral Mindig — a ca.yaml statikus olvasása
2 host_cert Az átjáró saját kiadási nyilvántartása tart ehhez a hoszthoz olyan tanúsítványt, ami sem le nem járt, sem vissza nem lett vonva Mindig — az átjáró nyilvántartásának statikus olvasása
3 trusted_ca A célgép elfogadott egy olyan tanúsítványt, amit ez a CA írt alá --probe-hosts, futó isg serve mellett
4 break_glass A célgép break-glass kulcskészletéből felolvasott kulcsok közül legalább egyet elfogadott az isg-breakglass fiók --probe-keyset
5 break_glass_keyset Maga a kulcskészlet-fájl az, aminek lennie kell: restrict minden során, a várt mód és tulajdonos, és egy cert-authority sor, amelynek az ujjlenyomata megegyezik a breakglass_ca_fingerprint-tel --probe-keyset
6 reachable A DNS felold, a TCP 22 válaszol, és a célgép hosztkulcsa átmegy a szigorú ellenőrzésen A DNS-re és a TCP-re mindig; a hosztkulcs-verdikt --probe-hosts alatt mélyül el
7 level Mindig teljesül — a hoszt lockdown szintjét jelenti, és azt, hogy a szint honnan jött Mindig

A 7-es alellenőrzés nem egy küszöb, amit meg kell ugrani. A lockdown szint közvetlen bemenete a parancsonkénti policy-kapunak és a négy szem elvének, tehát a sor a saját bemeneteinek egyikét rejtené el, ha az értéket kihagyná.

Figyelj arra, ami a táblából következik: egy sima isg system check nem tud OK készenléti sort előállítani. A 3-as, a 4-es és az 5-ös alellenőrzés szondázási flagek mögött van, tehát azok nélkül a sor WARN, és minden nem mért alellenőrzés megnevezi azt a flaget, ami megmérné. Ez a szándékolt olvasat — a sor nem állítja egy hosztról, hogy kész, olyan bizonyíték alapján, amit nem gyűjtött be.

sshd-követelmények

Két direktíva, és ezek a bizalom két különböző iránya. Egyik sem helyettesíti a másikat.

TrustedUserCAKeys — a célgép elfogad minket. Ettől lesz elfogadható bejelentkezés az átjáró efemer munkamenet-tanúsítványa. Telepítsd a CA publikus kulcsát, és mutass rá az sshd-vel:

# az átjárón
isg ca pubkey > isg_ca.pub

# a célgépen
sudo install -m 644 isg_ca.pub /etc/ssh/ca/isg_ca.pub
printf '%s\n' 'TrustedUserCAKeys /etc/ssh/ca/isg_ca.pub' 'LogLevel VERBOSE' \
  | sudo tee /etc/ssh/sshd_config.d/50-isg-userca.conf
sudo sshd -t && sudo systemctl reload sshd

A direktíva additív: a meglévő kulcsalapú bejelentkezések tovább működnek, és ezért biztonságos ezt a lépést mindenki más elé venni. Előbb nézd meg, van-e az sshd_config-ban Include /etc/ssh/sshd_config.d/*.conf sor — ha nincs, a direktíva a fő fájlba való. A reload előtt futtass sshd -t-t, minden alkalommal.

A LogLevel VERBOSE ugyanabból az okból kerül ugyanebbe a drop-inbe, amiért a lenti break-glass Match blokkban is ott van: ettől köti a célgép saját naplója a tanúsítványos bejelentkezést a kulcs ujjlenyomatához — és a drop-in az a hely, ami minden brókerezett bejelentkezést lefed, nem csak a vészfiókot.

A cert-only posztúra külön, opt-in lépés. Ha a tanúsítványos bejelentkezés ezen a gépen mérve működik, a PasswordAuthentication no ugyanebbe a drop-inbe felvehető, hogy a tanúsítvány legyen az egyetlen út befelé. Korábban ne: vele egy olyan gépen, ahol a TrustedUserCAKeys sor hibás, nem marad bejelentkezés. Az isg_target_host Ansible role pontosan ezért tartja az isg_target_host_cert_only kapcsoló mögött, alapból kikapcsolva.

HostCertificate — a célgép bizonyítja magát nekünk. Az átjáró alapértelmezett hosztkulcs-policyja strict, ami azt jelenti, hogy kizárólag a saját CA-ja által aláírt hoszttanúsítványt fogadja el: csupasz hosztkulcsot nem, és olyan kulcsot sem, amit korábban már látott. Adj ki egyet a célgép meglévő publikus hosztkulcsa fölé — a CA a privát felét sosem látja —, és telepítsd:

# az átjárón
isg ca host-cert issue --host <host> --key ./<host>_host_ed25519.pub

# a célgépen
sudo install -m 644 <host>-cert.pub /etc/ssh/ssh_host_ed25519_key-cert.pub
echo 'HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub' \
  | sudo tee /etc/ssh/sshd_config.d/60-isg-hostcert.conf
sudo sshd -t && sudo systemctl reload sshd

A célgépre másolandó fájl a pub/hosts/ alatti publikált tükör, nem az átjáró saját példánya a ca/ alatt. A reload (SIGHUP) elég: az sshd a konfig újraolvasásakor a HostCertificate-et is felveszi, a nyitott munkameneteket nem bántja, és az átjáró strict hosztkulcs-ellenőrzése közvetlenül utána átmegy — restart nem kell, és ugyanezért reloadol az isg_target_host role is.

A tanúsítvány principaljainak egyezniük kell azzal a névvel, amin az átjáró tárcsáz. A --principals alapértelmezése a --host, és a szigorú hosztkulcs-ellenőrzés a tanúsítvány principaljait a kapcsolathoz használt pontos hosztnévvel veti össze. A host.example.com-ra kiadott tanúsítvány elutasításra kerül, ha a leltár host-nak hívja a gépet. Sorold fel az összes aliast: --principals host,host.example.com.

Nincs karbantartandó principals-fájl. A mechanizmus maga a tanúsítvány principal-listája: az átjáró olyan tanúsítványt ír alá, amelynek az egyetlen principalja a munkamenet OS-felhasználója, és az sshd azért engedi be ezt a tanúsítványt bejelentkezésként arra a felhasználóra, mert a CA megbízható. Az ISG-ben semmi nem ír, nem követel meg és nem olvas AuthorizedPrincipalsFile-t.

Fiókok és csoportok

A célgépen Mihez kell Megjegyzés
Az --as által megnevezett OS-fiók Minden brókerezett munkamenethez Ez a tanúsítvány principalja. Nem kell hozzá authorized_keys bejegyzés és nem kell jelszó — a hitelesítő adat maga a tanúsítvány
Amilyen sudo jogai ennek a fióknak lenniük kell Jogosultság-emeléshez a munkamenetben Az emelés a célgépen történik, a célgép saját sudo-szabályai szerint. Az átjáró nem tart hozzá jelszót; a célgép promptja átvezetődik az operátor termináljára, és sem a bróker, sem a munkamenet-rögzítés nem kapja el a begépeltet. A jelszavas sudo-hoz a felhasználónak ismernie kell a fiók jelszavát — a gyakorlatban egy címtár-alapú fiókét, lásd lent
isg-breakglass A vészútvonalhoz Dedikált fiók, saját sshd Match blokkal, ami a /etc/ssh/breakglass_authorized_keys-t olvassa

Magának az átjárónak nincs szüksége fiókra a célgépen.

A break-glass blokk kicsi, önmagában zárt drop-in:

Match User isg-breakglass
    AuthorizedKeysFile /etc/ssh/breakglass_authorized_keys
    PubkeyAuthentication yes
    LogLevel VERBOSE
Match all

A záró Match all kötelező, nem díszítés: nélküle minden globális direktíva, ami a fő sshd_config-ban az Include után következik, ez alá a Match blokk alá esne. A LogLevel VERBOSE az, amitől a célgép saját naplója egy kulcs-ujjlenyomathoz köti a bejelentkezést. A kulcskészlet-fájltól 0644 mód és root:root tulajdonos várt — a fiók nem írhatja át azoknak a kulcsoknak a listáját, amelyek beengedik —, és minden sortól, a cert-authority sortól is, elvárt a restrict opció.

Nevesített helyi fiókok, emberenként egy

A célgépen a fiók neve nem megegyezés kérdése — ez az egyetlen név, amin a bejelentkezés állhat. Az átjáró-bejelentkezési fronton a munkamenet MINDIG annak a nevében nyílik, aki hitelesítette magát; nincs --as, amivel átirányítható lenne, és a célgépen principal-leképezés sincs: a role TrustedUserCAKeys-t telepít és AuthorizedPrincipalsFile-t nem, tehát az sshd a tanúsítványt annak a principalnak a bejelentkezéseként fogadja el, amit a tanúsítvány hordoz — és az a principal az adott ember saját felhasználóneve. Egy közös fióknak nem volna mihez illeszkednie: a tanúsítvány egy embert nevez meg, a gép egyetlen fiókot kínál mindenkinek, és a kapcsolat egyszerűen elutasításra fut.

Ezért mindenkinek, akinek el kell érnie egy célgépet, saját helyi fiókja van rajta. Az isg_target_host Ansible-role egyetlen listából hozza létre őket, ez az isg_target_host_users, és ezeknek a fiókoknak három tulajdonsága kimondott döntés, nem véletlen.

Shell, home és zárolt jelszó. A fiók azért van, hogy parancsot futtasson — pontosan azt brókerezi az ISG —, tehát bejelentkezési shellt kap (isg_target_host_users_shell, /bin/bash) és home-könyvtárat. A jelszó-mező zárolt: a hitelesítő adat a tanúsítvány, és egy jelszó nem válhat második belépési úttá. Egy direktíván múlik, hogy ez a kombináció működik, és érdemes a nevén tudni: UsePAM yes. PAM nélkül az sshd a zárolt shadow-mezőt letiltott fiókként olvassa, és elutasítja a bejelentkezést akkor is, ha a tanúsítvány és a bízott CA egyaránt rendben van. Mindkét disztribúció-család yes-szel szállít; a role nem állítja be, hanem megméri.

Nincs sudo. A role nem ír sudoers fájlt, és senkit nem vesz fel a wheel vagy a sudo csoportba. Egy általa kezelt fiók pontosan két csoportot visel: a saját elsődleges csoportját és a kezelt csoportot. A jogosultság-emelés a célgépen az marad, aminek a fenti táblázat mondja — a célgép saját sudo-szabályai, gépenként annak a döntése, akié a gép —, nem egy fiók-létrehozás mellékhatása. Az ellenőrzés mindkét irányt megméri: a csoport-listát id -Gn-nel, és azt, hogy a fiók mit futtathat valójában, sudo -l -U-val.

A kezelt csoport a hatókör — és egy már létező fiókot a role soha nem fogad örökbe. Minden fiók, amit a role létrehoz, egyetlen csoport tagja (isg_target_host_users_group, isg-testers), és ez a csoport maga a role hatóköre: a listán álló név fiókká lesz, a csoport listáról lekerült tagja a home-jával együtt eltávolítódik, a csoporton kívüli fiókot pedig a role sem nem olvassa, sem nem érinti. Épp ez utóbbi az, ami az automatizálás saját admin-fiókját kívül tartja.

Ugyanez rendezi azt is, mi történik, ha egy listás nevet a gépen már visel egy fiók, ami nem tagja a kezelt csoportnak. A role elutasítja a futást, és megnevezi az ütközést. Az örökbefogadás ártalmatlannak látszana — a fiók egyszerűen belépne a csoportba —, de ezzel a role hatókörébe is kerülne, ahol egy későbbi, teljesen ártalmatlan névlista-szűkítés a home-jával együtt törli. A hiba hónapokkal az azt kiváltó változás után érkezne — ezért a válasz megállás és nem figyelmeztetés: vagy vedd le a nevet a listáról, vagy nevezd át előbb kézzel a meglévő fiókot.

Egy üres isg_target_host_users listának is kimondott jelentése van. Nem azt jelenti, hogy „a fiókokhoz nem nyúlunk"; azt jelenti, hogy a kezelt csoport üres, tehát a mostani tagjai eltávolítódnak. Nincs olyan állapot, amiben a role csendben semmit nem kezel.

Címtár-alapú fiókok és a jelszavas sudo

Egy zárolt jelszavú helyi fiók a belépéshez elég — a hitelesítő adat a tanúsítvány —, de jelszavas sudo-ra nem jó: a célgép a fiók jelszavát kéri, és azt senki nem ismeri. Az emeléshez olyan fiók kell, amelynek a jelszava a felhasználónál már megvan. Nagyvállalatnál ez a címtár-fiók: a célgép ugyanahhoz a címtárhoz csatlakozik, amely ellen az ISG hitelesít (SSSD, vagy a platform AD-integrációja), a sudo a felhasználó saját címtár-jelszavát kéri, és a célgép ellenőrzi — ugyanazt a jelszót, amellyel a felhasználó az ISG-be belépett, újra begépelve. Az átjáró a belépéskori jelszót nem használja újra és nem tárolja; egyszeri bejelentkezésnél (SSO) nem is látja.

Az isg_target_directory Ansible-role pontosan ezt állítja be egy célgépen: SSSD-t ldaps-en, kötelező tanúsítvány-ellenőrzéssel, saját, csak olvasó bind-fiókkal (isg_cfg_ldap_target_bind_dn — külön a brókerekétől és az IdP-étől, így mindegyik a többitől függetlenül forgatható), első belépéskor létrehozott home-könyvtárral, és egyetlen sudoers drop-innal, amely egy címtár-csoportot nevez meg (isg_target_directory_sudo_group). Hogy ki emelhet, azt tehát a címtár dönti el, csoporttagsággal. Bekapcsolt role mellett az előző szakasz nevesített helyi fiókjai azon a gépen nem használatosak: egy azonos nevű helyi fiók eltakarná a címtárbelit, és a role ellenőrzése egy ilyen ütközésen megáll. Akkor is megáll, ha a felhasználó valamelyik csoport-azonosítójának nincs neve a címtárban — jellemzően az elsődleges csoportnak (gidNumber) nincs posixGroup párja —, mert az id ilyenkor a célgépen hibát ad.

A két kapu, sorrendben. Minden parancssorról ELŐSZÖR az ISG dönt — a policy-szabályok, a jóváhagyási követelmények, a gép szintje és a human_access —, és az ISG a sudo mögé is belát, arra a programra, amit futtatna: egy reboot-ra illeszkedő szabály a sudo reboot-ra is illeszkedik. A célgépre csak az ISG által átengedett parancs jut el, és csak ekkor alkalmazza a célgép sudo-ja a saját szabályait és kéri a jelszót. A célgép szűkítheti, amit az ISG engedett; amit az ISG megtagadott, azt nem bővítheti. A tényleges jog a kettő metszete.

Ahol a célgép az egyetlen kontroll. Az interaktív root-shelleket (sudo su, sudo -i, sudo -s, sudo bash) az ISG feltétel nélkül tiltja. Más a helyzet egy olyan programmal, amely maga is tud shellt indítani (sudo vim, majd :!sh): azon belül az ISG már nem látja egyenként a parancsokat. Ez ellen a célgép sudoers-e a kontroll — NOEXEC, vagy az ilyen programok meg sem engedése. A munkamenet-felvétel a kimenetet ekkor is rögzíti; megelőzni a célgép dolga.

Hálózat

Egy irány, egy port.

Honnan Hova Port Mikor
Átjáró Célgép TCP 22 Minden munkamenetnél, minden szondázásnál

A célgépről soha semmi nem kapcsolódik vissza az átjáróhoz. Nincs telepítendő ügynök, nincs visszahívás, és nincs második port.

A szondák egy üzemeltetési tulajdonságát érdemes betervezni: egyetlen --probe-hosts futás minden célgép 9 kapcsolatos PerSourcePenalties keretéből 4-et elhasznál, és a célgép ezt az átjáró forráscíme ellen könyveli, nem egy operátor ellen. Két gyors egymásutánban futtatott kör az, ami kiváltja a célgép kizárását — a kizárás pedig hamis FAIL-t termel, ami újrapróbálkozásra hív, ami megint kiváltja. Az átjáró pontosan ezért kényszerít ki minimális időközt a flottaszintű szondafutások közé, és a másodikat elutasítja, megmondva, hány másodpercet kell várni. Ne próbáld újra azért, hogy megerősítsd a hibát; várd ki.

Ezt az időközt minden átjáró magának kényszeríti ki, tehát egy olyan célgép, amelyik egynél többel néz szembe, a rátát annyiszorosan látja, ahányan vannak. Ez szándékos — az időköz a terhelést határolja, nem a helyességet védi, és a szondaútra tett közös írás lenne az ára annak, hogy az átjárók között összehangoljuk —, de azt jelenti, hogy a fenti keretet az egész flottára kell méretezni, nem egyetlen átjáróra.

Ellenőrzés

A statikus fele, amihez semmi nem kell az átjárón kívül:

isg system check

Minden konfigurációs fájlt validál, és jelenti a készenléti sort a leltár minden hosztjára, plusz minden olyan hosztra, amelyikhez van kiadott tanúsítvány — az átjárók saját front-tanúsítványai kivételével: az átjáró nem brókerelt célgép, hacsak a leltár nem sorolja fel, és ugyanez a szabály adja a lenti --probe-hosts próbák célhalmazát is. A --verbose megmutatja az egyes sorok mögötti alellenőrzéseket, és soronként a kikötést — azt, amit nem mért.

Az élő fele, amihez futó isg serve kell:

isg system check --probe-hosts --probe-keyset --verbose

A --probe-hosts a daemon nélkül nem hajlandó lefutni, és ezt ki is mondja ahelyett, hogy kapcsolatokat nyitna termelési hosztokra, amik aztán minden célgép sshd-naplójában megjelennének anélkül, hogy bármilyen ISG-auditbejegyzés megmagyarázná őket. (A --probe-without-audit ezt felülbírálja egy sürgős méréshez, és a kimenetben kimondja, mit adott fel.) Minden szonda külön auditálódik: REACHABILITY_PROBE, BYPASS_PROBE, HUMAN_CERT_PROBE, BREAK_GLASS_AUTH_METHOD_PROBE, és — a kulcskészlet felolvasására, ami valódi bejelentkezés, nem preauth-lezárás — BREAK_GLASS_KEYSET_READ.

Magának a leltárnak a nézete:

isg servers show
isg servers level <host>

Mit bizonyít egy zöld sor, és mit nem

A Ready to broker: <host> OK állapota azt jelenti: van hozzáférési szabály, ami lefedi ezt a hosztot, létezik hozzá élő hoszttanúsítvány, a célgép elfogadott egy tanúsítványt ettől a CA-tól, a vészútvonal a helyén van és a kulcskészlete sértetlen, a hoszt válaszol a TCP 22-n megbízható hosztkulccsal, és a lockdown szint feloldódott.

Nem bizonyítja, hogy a sudo működik-e az isg-breakglass-nak, ha egyszer bejelentkezett, és nem bizonyítja, hogy bármelyik operátor birtokolja-e egy elfogadott break-glass kulcs privát felét — a szonda mindig csak egy publikus kulcsot ajánl fel, és a választ figyeli. Bármelyik megerősítéséhez valódi break-glass bejelentkezés kell, valódi kulcsot tartó embertől. Azt sem bizonyítja, hogy egy adott személy kapcsolódhat: a készenlét hoszt-szintű kérdés, azt pedig, hogy egy adott principal jogosult-e, a hozzáférési kapuk döntik el kérésenként.

Ami el szokott csúszni

Minden itt szereplő állapotot ténylegesen megnevez valamelyik ellenőrzés. Az idézett szöveg az, amit az ellenőrzés kiír.

A hoszttanúsítvány sosem lett telepítve, vagy az sshd nélküle indult. Az elérhetőség-ellenőrzés ezt jelenti: target offers a plain host key, not a certificate — sshd may have started without the host cert (fail-open); strict-mode connect would be rejected. Ez a fail-open eset: az sshd feljött, a port válaszol, és egy szigorú kapcsolódás elutasításra kerülne. Egy sima isg system check elkapja, bármilyen szondázási flag nélkül.

A tanúsítvány lejárt. host cert expired a 2-es alellenőrzésen, és a hoszt szigorú módban elérhetetlenné válik. A hoszttanúsítvány-sor 30 nappal előbb figyelmeztet, tehát ezt az állapotot mindig megelőzi egy figyelmeztetés, amire volt ideje reagálni valakinek.

A tanúsítványt visszavonták. host cert revoked. A visszavonás átjáró-oldali: a célgép konfigurációja érintetlen marad, és a sorszámot minden tárcsázásnál megnézi, elavulni képes gyorsítótár nélkül.

A TrustedUserCAKeys el lett távolítva, vagy rossz fájlra mutat. A 3-as alellenőrzés ezt jelenti: certificate rejected (cert_rejected). Ez kizárólag --probe-hosts alatt látszik — az átjárón semmi nem látja a célgép sshd-jének konfigurációját, tehát egy tényleges felajánlás kell a célgép felé ahhoz, hogy kiderüljön.

A hosztot egyetlen hozzáférési szabály sem fedi le. no human_access rule names this host. Egy hoszt lehet elérhető, tanúsított és tökéletesen egészséges, és mégis olyan, amihez senki nem tud kapcsolódni, mert egyetlen engedélyszabály sem említi. Nincs hoszt-helyettesítő karakter, ami elkapná — használj host_labels szelektort.

Két hoszt osztozik egy hosztkulcson. A hoszttanúsítvány-sor ezt jelzi: duplicate host key shared with <other host>. A szokásos ok egy golden image vagy egy klónozott VM-pillanatkép, ami egyetlen /etc/ssh/ssh_host_*_key-t szállított minden gépre, a következmény pedig az, hogy bármelyik hoszt fel tudja mutatni a másik identitását a szigorú ellenőrzésnek. A kiadás pontosan ezért tagadja meg a második tanúsítványt egy már tanúsított kulcs fölé; a javítás a klón hosztkulcsainak újragenerálása (ssh-keygen -A) és az újrakiadás.

A break-glass kulcskészlet elcsúszott. A kulcskészlet-sor minden leletet jelent, nem áll meg az elsőnél: unexpected keyset mode/owner: … (want 0644 root:root), N of M key(s) missing the restrict option, no cert-authority line in the keyset — the break-glass CA is not trusted on this host, vagy — az, amelyik bukik, nem figyelmeztet — keyset trusts an unexpected break-glass CA. Az a hoszt, amelyiknek a vészajtaja nem a miénk, nem kész a brókerezésre.

A break-glass fiók hiányzik. isg-breakglass account does not exist on this host, vagy break-glass keyset is missing or unreadable (/etc/ssh/breakglass_authorized_keys).

A Match blokk már nincs érvényben. break-glass Match block NOT in effect — no offered key was accepted by isg-breakglass: a kulcskészlet-fájl fel lett olvasva, minden benne lévő kulcs fel lett ajánlva, és a célgép egyiket sem fogadta el. Vagy a Match blokk nem oda irányítja azt a fiókot, vagy az sshd nem ezt a fájlt olvassa hozzá.

Bármihez, ami nincs ezen a listán, a Troubleshooting tünet szerint katalogizálja az üzeneteket.