A nyilvános kulcsok titkossága kulcsfontosságú a titkosításban: bár bárki hozzáférhet a nyilvános kulcshoz, csak a privát kulcs birtokosa képes visszafejteni az azt titkosított adatokat. A tanúsítvány aláírási kérelem (Certificate Signing Request, CSR) tartalmazza azokat az információkat, amelyeket a végső aláírt tanúsítványba kell beépíteni, beleértve a nyilvános kulcsot, a kulcshoz kapcsolódó adatokat, a tanúsítvány érvényességi körét (például mely szerverek számára érvényes), valamint az érintett szervezet és földrajzi hely adatokat. A tanúsítvány aláírási kérelem egyfajta kérvényszerű bejegyzés, amely az összes olyan adatot tartalmaz, amire az aláíró félnek szüksége van ahhoz, hogy a döntését meghozza és engedélyezze a végleges aláírt tanúsítvány kibocsátását.

A tanúsítvány aláírási kérelmet a hitelesítő hatóság (Certificate Authority, CA) használja a végleges, aláírt tanúsítvány létrehozására. Maga a CSR nem kerül aláírásra; helyette az OpenSSL generál egy új aláírt tanúsítvány fájlt. A webszerverek ezt az új aláírt tanúsítványt és a hozzá tartozó privát kulcsot használják a TLS kapcsolat létrehozásához a böngésző és a szerver között.

Vegyünk egy példát: Bob szeretné meglátogatni Alice éttermének weboldalát. Bob a böngészőjében beírja az étterem nevét, majd a böngésző elvégzi a DNS feloldást és a TCP kézfogást, mielőtt megkezdi a TLS kapcsolat létrehozását. A böngésző először elküldi a Client Hello üzenetet, amely tájékoztatja Alice-ot, hogy milyen TLS verziókat és titkosítási algoritmusokat támogat a böngésző. Alice étterme válaszként Server Hello üzenetet küld, amely tartalmazza az aláírt tanúsítványt, egy véletlenszerű karakterláncot és a támogatott titkosítási algoritmusokat.

Most, hogy Bob böngészője rendelkezik Alice aláírt tanúsítványával, ellenőrzi a tanúsítványt az abban szereplő hitelesítő hatósággal. Mivel Bob böngészője is megbízik ebben a hitelesítő hatóságban, generál egy második véletlenszerű karakterláncot, az úgynevezett premaster secret-et, majd titkosítja ezt Alice nyilvános kulcsával, és visszaküldi a szervernek. A szerver a privát kulcsát használja a premaster secret visszafejtésére. Mivel azt Alice nyilvános kulcsával titkosították, csak Alice tudja visszafejteni azt. Egy bonyolult matematikai algoritmus segítségével mind Bob böngészője, mind Alice étterme egy azonos szimmetrikus kulcsot generál, amelyet az előzőleg elküldött véletlenszerű karakterlánc és a premaster secret alapján használnak.

Miután a kapcsolat létrejött, a böngésző és a szerver minden további adatot ezen a szimmetrikus kulcson keresztül titkosítanak, mivel a szimmetrikus titkosítás gyorsabb, mint az aszimmetrikus. Ez biztosítja, hogy senki más ne tudja meg, mit rendel Bob Alice éttermében.

A TLS kapcsolat egyirányú hitelesítést alkalmaz: csak a szerver (jelen esetben Alice étterme) küldi el az aláírt tanúsítványt. Mi történik azonban akkor, ha Alice éttermének szüksége van arra, hogy azonosítsa a látogatókat? Ebben az esetben Bob-nak is el kell küldenie egy aláírt tanúsítványt, amelyet Alice érvényesíthet, így létrejöhet egy kölcsönös TLS (mTLS) kapcsolat. A mTLS olyan helyzetekben alkalmazható, amikor mindkét félnek szüksége van egymás hitelesítésére, ellentétben a hagyományos esetekkel, ahol csak a kliens (például egy böngésző) ellenőrzi a szervert. A mTLS kapcsolat során mind a kliens, mind a szerver tanúsítványokat cserélnek, és mindkét tanúsítványt ellenőrzik a hitelesítő hatóság által, mielőtt bármilyen titkosított adatot cserélnének.

A mTLS használata a hálózati támadásokkal szemben védelmet nyújthat, mivel megakadályozza, hogy bárki jogosulatlanul adatokat küldjön a hálózati szolgáltatásokhoz, beleértve a naplózási infrastruktúrát is. Ezért a mTLS fontos része a nulla bizalom alapú rendszereknek, mivel lehetővé teszi a hozzáférést csak azoknak, akik képesek igazolni a hitelesítő adataikat, mielőtt hozzáférnének a belső vagy érzékeny alkalmazásokhoz. A mTLS tehát hozzájárul a támadókatól való védelemhez, még akkor is, ha azok megszerezték a felhasználónév-jelszó kombinációkat.

Fontos megérteni, hogy a mTLS kifejezetten belső hálózatokban és nulla bizalom alapú környezetekben alkalmazható. Nyilvános weboldalak vagy szolgáltatások esetén nem ajánlott a mTLS használata, mivel ez azt jelentené, hogy minden potenciális ügyfélnek rendelkeznie kell egy megbízható tanúsítvánnyal ahhoz, hogy hozzáférhessen a szolgáltatáshoz.

A tanúsítvány hitelesítő hatóság (CA) létrehozása a következő lépés, amelyet ebben a könyvben bemutatunk. Először saját gyökér és köztes CA-kat hozunk létre. A köztes CA-t fogjuk használni a tanúsítvány aláírási kérelmek aláírására a könyv minden további fejezetéhez. A gyakorlatban ügyelni kell arra, hogy a CA-kat rendkívül biztonságos rendszerekben tároljuk, amelyek kizárólag köztes CA-k létrehozására használatosak. A gyökér CA-kat légmentesen elzárva és fizikailag védve kell tárolni. A gyakorlati környezetben ezek az intézkedések elhagyhatók.

A CA-k létrehozásához szükséges fájlrendszert a következő módon készíthetjük el egy Ubuntu gépen:

bash
$ cd ~
$ mkdir -p ~/tls/{configs,keys,csr,caroot,caintermediate,certs}

A CA fájlokat tartsuk meg a munkaállomásunkon, és ne töröljük őket a fejezet végén, mivel szükség lesz rájuk az eszközök tanúsítványainak létrehozásakor.

Hogyan működik a Logstash HTTP kimenet és API interakciók?

A Logstash, mint nyílt forráskódú adatfeldolgozó eszköz, képes összegyűjteni, feldolgozni és továbbítani adatokat különböző rendszerek és szolgáltatások között. Az egyik legfontosabb funkciója az HTTP kimenet konfigurálása, amely lehetővé teszi adataink küldését más API-k felé. Ez különösen akkor hasznos, amikor az adatokat nem tudjuk más módon átvinni a kívánt rendszerbe, vagy ha egy harmadik fél által használt API-t kell kezelni.

A Logstash egyik alapvető képessége az adatkezelés és a különböző külső rendszerekkel való kommunikáció. Az API-k használata lehetővé teszi az adatok dinamikus lekérését, például időjárás-információk, fenyegetettségi intelligencia vagy felhőalapú naplózási eszközök adatainak megszerzését. Az HTTP Poller bővítmény segítségével a Logstash képes kapcsolatba lépni a webes API-kkal, és lekérni az adatokat, majd feldolgozni őket a rendszerben.

A különböző HTTP kimeneti konfigurációk rendkívül sokoldalúak, és lehetőséget biztosítanak arra, hogy a Logstash segítségével adatokat küldjünk harmadik féltől származó rendszerekbe, mint például a Splunk. A Splunk egy népszerű adatbázis és SIEM (Security Information and Event Management) eszköz, amely saját, zárt protokollokat használ az adatok küldésére, de képes HTTPS-en keresztül adatokat fogadni is. Ha adatokat kell migrálni más rendszerekből a Splunkba, a Logstash HTTP kimenetét használhatjuk közvetítőként.

Amikor adatokat küldünk egy API-n keresztül, a kimenetben szereplő fejléceket is megadhatjuk. Például a fenti példában a -H opcióval egyedi fejlécet adtunk hozzá az HTTP kéréshez, amely tartalmazza a szkennelés célpontját. Ez lehetővé teszi, hogy nyomon követhessük minden egyes szkennelésünket. A Logstash-ban a küldött fájl tartalmát a standard kimenetre jeleníthetjük meg, és az adatokat továbbíthatjuk az Elasticsearch rendszerbe, ahol azok később kereshetőek lesznek.

A Kibana segítségével könnyen lekérdezhetjük az adatokat, például a type:nmap* lekérdezéssel. A Logstash konfigurációs fájlokban a metadata => true beállítás lehetővé teszi, hogy a metainformációkat is megjeleníthessük a kimeneten, még akkor is, ha azok nem jelennek meg közvetlenül a Kibana felületén.

Továbbá, ha egyéni API-kat kell használnunk, vagy ha több adatforrást kell integrálnunk, akkor az HTTP Poller egy nagyszerű eszköz. Az HTTP Poller lehetőséget biztosít arra, hogy folyamatosan lekérdezzünk adatokat különböző forrásokból és integráljuk őket a Logstash-ba. A példában látható, hogyan hozhatunk létre egyszerű Python alapú web API-kat, amelyek adatokat szolgáltatnak a Logstash számára. Az ilyen API-kat célszerű HTTPS-en keresztül lekérdezni, hogy biztosítsuk az adatbiztonságot.

A Python alapú szkriptek lehetőséget adnak arra, hogy testreszabott adatokat készítsünk a saját rendszereink számára. A Flask könyvtár segítségével gyorsan létrehozhatunk egy webes szervert, amely különböző adatokat szolgáltat a rendszerünknek. Az ilyen típusú API-k rendkívül hasznosak lehetnek, ha specifikus adatokat kell lekérdezni, amelyek nem érhetők el más módon.

A Logstash képes folyamatosan lekérdezni az adatokat az API-któl, és a megfelelő ütemezés beállításával meghatározhatjuk, hogy mikor történjenek a lekérdezések. A példában látható, hogy a schedule => { every => "5s"} beállítással minden öt másodpercben új adatokat kérhetünk le. Ez különösen hasznos, ha valós idejű adatokat kell feldolgoznunk és továbbítanunk.

A beállítások és konfigurációk finomhangolása elengedhetetlen ahhoz, hogy a Logstash sikeresen integrálódjon más rendszerekkel. A megfelelő API-k beállítása és az adatforrások konfigurálása lehetővé teszi, hogy a Logstash-t egy robusztus adatfeldolgozó és adatátviteli eszközként használjuk.

Mindezek mellett fontos megérteni, hogy az adatok biztonsága mindig elsődleges kell, hogy legyen. Az SSL/TLS tanúsítványok megfelelő kezelése és a biztonságos API-k használata elengedhetetlen annak érdekében, hogy elkerüljük a lehetséges adatlopásokat vagy egyéb biztonsági problémákat. Emellett mindig figyeljünk arra, hogy az API-kat megfelelően konfiguráljuk, hogy azok a kívánt adatokat biztosítsák, és hogy a lekérdezett információk pontosak legyenek.

Hogyan működnek a Log

Hogyan dolgozzunk a strukturálatlan adatokkal a Logstash szűrőivel?

A Logstash számos szűrőt kínál az események átalakítására, és ezek közül sok, például a mutate, lehetőséget ad a mezők átnevezésére vagy értékek másolására. A különböző típusú szűrők, mint például a urldecode vagy az extractnumbers, speciális információk kinyerésére vagy feldolgozására szolgálnak. A cidr és translate szűrők segítségével gazdagíthatjuk az adatokat, míg a ruby szűrő lehetővé teszi, hogy Ruby kódot futtassunk a konfigurációban. Az egyes szűrők kombinálása gyakran hasznos, mivel lehetővé teszi, hogy logikákat csoportosítsunk egyes speciális feladatok számára, így más felhasználók könnyebben megérthetik, mit is csinálunk.

A Logstash rugalmasan kezeli a fehér karaktereket, így új sorokat, szóközöket vagy tabulátorokat használhatunk a konfigurációkban, hogy átláthatóbbá tegyük a beállításokat. Az egy soros beállítások segíthetnek abban, hogy világosan kiemeljük egy-egy szűrő logikáját, elkerülve a bonyolult, zárójelekből álló konfigurációkat.

A strukturálatlan adatkezelés egy különösen fontos aspektusa a Logstash használatának. Azok az adatok, amelyek nem sorokba és oszlopokba rendezettek, mint a JSON vagy YAML formátumok, komoly kihívások elé állíthatják az elemzőket. Gondoljunk például a syslog eseményekre, amelyek különböző formátumokban érkeznek, és mindegyik esetben egyedi kihívásokat rejtenek. Ha különböző formátumú adatokat kell feldolgoznunk, először célszerű standardizálni őket, így később könnyebben tudunk elemzést végezni rajtuk.

A következő szakaszban bemutatunk egy egyszerű példát, hogy hogyan alakíthatunk át egy syslog üzenetet JSON mezőkké, amelyeket adatbázisok vagy elemzők könnyedén felhasználhatnak. Ha az eredeti szöveges logokat megtartjuk, akkor minden egyes log formátumhoz külön parancssori eszközöket vagy adatbázis lekérdezéseket kellene futtatnunk, ami számottevően lassítaná az elemzést. A strukturált adatok esetében a különböző mezők összekorrellálása és aggregálása is egyszerűbbé válik.

Ehhez a következő szűrőt alkalmazzuk a grok és dissect szűrőkkel. A grok egy rendkívül hasznos eszköz, amely a reguláris kifejezések segítségével képes strukturálatlan adatokat kinyerni és mezőkké alakítani. Az alábbi konfigurációt figyelembe véve, három különböző formátumban érkező syslog üzenetet feldolgozunk.

Grok minta használata

A grok szűrő a következő mintát alkalmazza, hogy a syslog üzeneteket megfelelő mezőkké alakítsa:

plaintext
grok {
id => "grok_syslog" match => { "[event][original]" => [ "(<%{POSINT:[log][syslog][priority]}>)?%{SYSLOGTIMESTAMP:syslog_timestamp} %{DATA:[host][name]} %{DATA:[process][name]}(\[%{POSINT:[process][pid]}\])? :%{GREEDYDATA:message}" ] } }

Ebben a konfigurációban a szűrő először a syslog üzenet prioritását ellenőrzi, majd a timestamp-ot és a hostname-t, végül a process nevet és a PID-t, ha létezik. Az utolsó lépésben a szűrő kinyeri a tényleges üzenetet, amely a GREEDYDATA minta segítségével kerül kinyerésre. A minta a syslog üzenet összes fontos elemét külön mezőkké alakítja, így az adatokat könnyen elemezhetjük és feldolgozhatjuk.

A grok és a dissect szűrők használata

A grok szűrőt leginkább akkor használjuk, amikor komplex szöveges adatokat szeretnénk mintázni és strukturálni. Azonban nem minden esetben van szükség ilyen bonyolult mintákra. A dissect szűrő például egy egyszerűbb, pozíció-alapú szintaxist alkalmaz, ami akkor hasznos, ha a szöveg struktúrája jól definiált és változó elemeket tartalmaz.

A szűrők kombinálása tehát a legjobb módja annak, hogy az adatokat könnyen feldolgozhatóvá és használhatóvá tegyük. A szűrők hatékonysága és sebessége kulcsfontosságú, mivel a rosszul megírt reguláris kifejezések jelentős teljesítményproblémákat okozhatnak. Éppen ezért, minden grok szűrőhöz célszerű ID-t rendelni, amely segít a hibák gyors azonosításában és javításában.

A rendszerben keletkező adatok gyakran nem rendezettek, és ha nem kezeljük őket megfelelően, az elemzési folyamat lelassulhat. Fontos megérteni, hogy a strukturálatlan adatok kezeléséhez nemcsak a megfelelő szűrők kiválasztására van szükség, hanem a szűrők megfelelő kombinációjának is el kell érni a kívánt eredményt.

Hogyan kezeljük a felhasználói adatokat Logstash konfigurációval?

A Logstash egy hatékony eszköz, amely képes különböző típusú adatokat gyűjteni, feldolgozni és átvinni különböző rendszerek között. Az egyik fontos feladat, amellyel gyakran szembesülnek a felhasználók, az adatok tisztítása és megfelelő formátumba történő átalakítása. Ebben a fejezetben a felhasználói adatok kezelésére, azok feldolgozására és a különböző szűrők alkalmazására koncentrálunk, különös figyelmet fordítva a mutációs szűrők használatára.

A Logstash konfigurációk általában több szűrőt tartalmaznak, amelyek meghatározzák, hogyan dolgozzon fel egy-egy adatot. Az egyik alapvető feladat az, hogy az adatokat egy adott formátumban alakítsuk át, hogy később könnyen használhatóak legyenek, például az eseményekből származó felhasználói adatokat. Képzelj el egy helyzetet, amikor a bejövő adatokban a felhasználói nevet tartalmazó mező úgy néz ki, hogy "StLouisOffice\James". Ebben az esetben a cél az, hogy az "StLouisOffice" domain nevet és a "James" felhasználói nevet külön mezőkben tároljuk.

A mutate szűrő alkalmazása

A mutate szűrő a Logstash egyik leggyakrabban használt szűrője. Ennek segítségével végezhetünk különböző módosításokat az adatainkon, például mezők átalakítását, törlését, másolását vagy összefűzését. Az alábbi konfiguráció példáját követve a bejövő "UserName" mezőt dolgozhatjuk fel:

javascript
filter {
if [winlog][event_data][UserName] =~ /.\\./ { mutate { copy => { "[winlog][event_data][UserName]" => "[utemp]" } } mutate {
gsub => [ "[utemp]", "[\\]", "/" ]
split => [
"[utemp]", "/" ] add_field => { "[user][domain]" => "%{[utemp][0]}" "[user][name]" => "%{[utemp][1]}" } remove_field => [ "[utemp]" ] } } else { mutate { copy => { "[winlog][event_data][UserName]" => "[user][name]" } } } mutate { lowercase => [ "[user][domain]", "[user][name]" ] } }

A fenti konfiguráció részletezése során láthatjuk, hogy a mutate szűrő első lépésként ellenőrzi, hogy a felhasználónév tartalmaz-e visszaperiódust (backslash). Ha igen, a következő lépésben a gsub szűrő segítségével az összes visszaperiódust előre perjellel ("/") helyettesíti. Ezt követően a split művelet végzi el a felhasználónév két részre bontását, a domain és a felhasználói név külön mezőkben kerülnek tárolásra. Miután a szükséges mezők kinyerésre kerültek, eltávolítjuk az ideiglenes mezőt, amely a feldolgozott adatokat tartalmazza.

Ha a felhasználónév nem tartalmaz visszaperiódust, akkor az egész nevet közvetlenül a user.name mezőbe másoljuk. A végső lépés pedig egy lowercase művelet, amely biztosítja, hogy a domain és a felhasználói név kisbetűs formátumban jelenjen meg.

A mutate szűrő műveleti sorrendje

Fontos megjegyezni, hogy a mutate szűrőnél figyelembe kell venni a műveletek sorrendjét, mivel a Logstash konfigurációk top-to-bottom (felülről lefelé) működnek. A különböző műveletek eltérően reagálhatnak, ha nem vagyunk tisztában azok sorrendjével. A Logstash hivatalos dokumentációja tartalmaz egy részletes magyarázatot a műveletek sorrendjéről, amely segíthet a szűrő működésének jobb megértésében.

További bővítési lehetőségek

Miután a fenti szűrők segítségével sikeresen feldolgoztuk a felhasználói adatokat, érdemes átgondolni, hogy más mezőket is hasonló módon dolgozhatunk fel. A mutate szűrő minden olyan funkcióval rendelkezik, amely lehetővé teszi több mező egyszerre történő módosítását, legyen szó másolásról, karakterek cseréjéről, mezők bontásáról vagy törléséről. A gsub szűrő különösen hasznos, ha több mezőt vagy karakterláncot kell egyszerre módosítani.

A gsub szűrő az egyetlen, amely három argumentumot használ egy művelet végrehajtásához. Például egy olyan konfigurációban, ahol több mezőt is egyszerre kell módosítani, a következő szintaxis alkalmazható:

javascript
filter { gsub => [ "[field_one]", "[\\]", "/", "[field_two]", "\|", ";" ] }

Ez a megoldás egyszerre hajt végre több karaktercserét két mezőben.

Ruby szkriptek alkalmazása Logstash-ben

A Logstash nemcsak beépített szűrők alkalmazásával képes adatokat feldolgozni, hanem Ruby szkriptek segítségével is finomhangolhatjuk a logikai folyamatokat. A Ruby szűrők lehetőséget adnak arra, hogy komplex adatfeldolgozást végezzünk, amely nem lenne könnyen elérhető a hagyományos Logstash szűrőkkel. A Ruby nyelvben használt event.get, event.set, és event.remove API-k lehetővé teszik a mezők közvetlen kezelését.

Például, ha szeretnénk egy mezőt hozzáadni, amely tartalmazza a Logstash szerver nevét, akkor a következő Ruby konfigurációs blokk használható:

swift
filter {
ruby { id => "ruby_add_agentforwarder" init => ' require "socket" @@hostname = Socket.gethostname ' code => ' event.set("[agent][forwarder]", @@hostname) ' } }

A fenti példában a Socket.gethostname Ruby függvényt használjuk a szerver nevét tartalmazó változó létrehozásához, amelyet később a event.set segítségével hozzáadunk az eseményhez.

Végső gondolatok

A Logstash szűrők és a Ruby szkriptek használata lehetővé teszi a fejlettebb és testre szabott adatfeldolgozást. Bár a konfigurációk komplexek lehetnek, a lehetőségek széles tárháza áll rendelkezésre a különböző adatok formázásához és átalakításához. Az ilyen típusú testreszabás nemcsak az egyszerűbb feladatok elvégzésére alkalmas, hanem összetett adatok elemzésére és feldolgozására is.