Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Zabbix + grafana – część 5 – Własne zapytania do API
Dalsza część opowieści
Na sam początek wróćmy do naszej hipotetycznej sytuacji z >poprzedniego artykułu. Musiałeś napisać zapytanie pokazujące maksymalną ilość zalogowanych użytkowników w wybranym przedziale czasu na dashboardzie – wyłącznie dla systemów Ubuntu (ustaliliśmy, że informacja ta znajduje się w inwentarzu hosta).
Utworzyłeś więc panel z następującym zapytaniem:
|
To zapytanie pozwoliło Ci stworzyć elegancką tabelę w Grafanie:

Po pewnym czasie zacząłeś jednak dostawać maile z informacją, że „w tabelce jest za dużo danych”. Wziąłeś się więc do roboty i zacząłeś sprawdzać, co może być problemem.
Po wielu godzinach analizy struktury bazy danych udało Ci się znaleźć kilka przyczyn:
- Podczas zapytania o hosty należy zadbać o to, by host był włączony oraz żeby faktycznie pytać o hosty (wiedziałeś, że w tabeli “hosts” trzymane są również wszystkie szablony?),
- Podczas zapytania o pozycje należy zadbać o to, by pozycja była włączona oraz żeby faktycznie pytać o pozycje (wiedziałeś, że w tabeli “items” trzymane są również reguły wykrywania niskopoziomowego?),
- Warto dodać jeszcze jedną regułę podczas zapytania o pozycje – żeby były w stanie Normalnym (ang. Normal) – chcemy pominąć wszystkie pozycje w stanie Niewspieranym (ang. Unsupported). Niestety ta informacja nie istnieje w tabeli items, tylko w tabeli items_rtdata, dlatego musisz uwzględnić ją w zapytaniu.
Po odkryciu tych dodatkowych założeń udało Ci się napisać następujące zapytanie:
|
Po uwzględnieniu wszystkich tych założeń udało się poprawnie wyświetlić dane (zauważ, że zniknął „wyłączony host”):

Udało się uratować sytuację – jesteś z siebie dumny, że wszystko zadziałało. Pozostaje jednak pewien niesmak, ponieważ osiągnięcie tego efektu wymagało kilku godzin analizowania struktury bazy danych, szczególnie w przypadku zadania, które na pierwszy rzut oka wydawało się dość trywialne.
Wstęp
Cała ta hipotetyczna sytuacja miała pokazać jedną z głównych wad bezpośrednich zapytań do bazy danych – konieczność znajomości jej struktury. Niestety, Zabbix nie udostępnia oficjalnych schematów bazy danych ani informacji o tym, jakie wartości mogą występować w poszczególnych kolumnach. Dodatkowo, przy bardziej skomplikowanych zapytaniach musimy dołączać kolejne tabele, co może skutkować wydłużonym czasem odpowiedzi i utrudnionym utrzymaniem takich zapytań w dłuższej perspektywie.
Dlatego w dzisiejszym artykule przyjrzymy się kolejnej metodzie wyciągania danych ze środowiska Zabbix – własnym zapytaniom do API. Miej na uwadze, że artykuł skupia się głównie na możliwościach pobierania danych do Grafany za pomocą API Zabbix. Nie będziemy tutaj szczegółowo omawiać samego API (solidną dawkę wiedzy powinieneś zacząć od >oficjalnej dokumentacji) ani struktury JSON – jako administrator Zabbixa zapewne nie raz miałeś już z nią do czynienia.
Zaczynamy!
Szybka powtórka
Architektura środowiska nie uległa znaczącym zmianom – wciąż bazujemy na tej samej konfiguracji. Zmianie podlega jedynie sposób komunikacji ze środowiskiem Zabbix, ponieważ tym razem wracamy do komunikacji za pomocą HTTP lub HTTPS:

Dodatkowe założenia w tym przykładzie:
- Nazwy hostów w Zabbix są zgodne z tymi skonfigurowanymi w systemie operacyjnym,
- Oba hosty należą do grupy “Linux servers”,
- Host “zabbix-7-0” jest dodatkowo w grupie “Zabbix servers”,
- Istnieje już użytkownik “read-only” (opisany w >tym artykule) o nazwie grafana_api
Przygotowanie Zabbix do integracji
Ponieważ posiadamy już użytkownika grafana_api do pobierania danych, tym razem pokażemy drugą metodę autoryzacji do API – za pomocą tokenu API.
Aby go wygenerować, należy wejść w zakładkę Users – API tokens, a następnie kliknąć w prawym górnym rogu Create API token:

W nowym oknie konfiguracja wygląda następująco:
- Name – nazwa przydziału, np. grafana-12-1 API
- User – dla jakiego użytkownika tworzymy token, wybieramy wcześniej utworzonego usera grafana_api. Warto dodać informację o przeznaczeniu tokenu (np. kto go dodał, do czego jest wykorzystywany). Na potrzeby tego przykładu wpiszmy:
Własne zapytania API z środowiska Grafana (192.168.88.241) - Set expiration date and time – jeśli opcja jest aktywna, możemy określić datę wygaśnięcia tokenu. Autor mocno zaleca korzystanie z tej funkcji i wdrożenie polityki regularnej rotacji tokenów ze względów bezpieczeństwa. Ustawiona w tym przykładzie data (koniec marca 2026 roku) ma charakter wyłącznie przykładowy i powinna zostać dostosowana do zasad obowiązujących w danym środowisku.
- Enable – określa, czy token ma być aktywny (możemy go również wyłączyć po utworzeniu). Pozostawiamy tę opcję zaznaczoną.
Całość konfiguracji wygląda następująco:

Jeżeli wszystko wypełniliśmy poprawnie, w nowym oknie wyświetli się podsumowanie i co najważniejsze – wygenerowany token do API. W tym momencie pamiętaj o jego zapisaniu (np. poprzez skopiowanie do schowka za pomocą przycisku Copy to clipboard) – gdy zamkniesz okienko przyciskiem Close, nie będzie już możliwości ponownego podejrzenia tokenu.

Posiadając token API dla użytkownika grafana_api, możemy przejść do konfiguracji pluginu odpowiedzialnego za wysyłanie zapytań API w środowisku Grafana.
Konfiguracja pluginu Infinity
Kiedy mamy już utworzonego użytkownika read-only oraz zapewnioną możliwość połączenia z serwerem Zabbix z poziomu serwera grafana-12-1, możemy przejść do konfiguracji oficjalnego pluginu służący do wysyłania zapytań API o nazwie Infinity.
W tym celu wybieramy z menu Connections – Data sources, a następnie Add new data source:

W wyszukiwarce źródeł danych wpisujemy infinity i klikamy w odpowiedni wynik:

Ciekawostką jest to, że w tym momencie moglibyśmy już kliknąć przycisk Save & test i faktycznie korzystać z tak skonfigurowanego źródła danych. Byłoby ono bardzo uniwersalne i moglibyśmy wykorzystywać je do komunikacji z różnymi endpointami API. Wymagałoby to jednak konfiguracji podstawowych parametrów połączenia (w szczególności tokenu autoryzacyjnego) w każdym panelu osobno.
Dlatego skonfigurujemy to źródło danych w taki sposób, aby służyło wyłącznie do wysyłania zapytań API do środowiska Zabbix, a token autoryzacyjny był konfigurowany tylko raz – na poziomie źródła danych. Takie podejście ogranicza ekspozycję tokenu autoryzacyjnego, który pozostaje widoczny tylko na poziomie źródła danych, a nie w konfiguracji paneli.
Na początku uzupełnij pole Name – wybierz taką wartość, które jednoznacznie wskazuje na to źródło danych np. zabbix-API-7-0, a następnie przejdź w zakładkę Authentication:

Authentication
W zakładce Authentication dostępnych jest kilka metod uwierzytelniania. Ponieważ API Zabbixa korzysta z mechanizmu Bearer Token, wybieramy tę opcję i wklejamy wcześniej wygenerowany token.
Dodatkowo, w sekcji Allowed hosts wpiszmy pełny adres API Zabbix. Autor przypomina, że to URL, do którego łączymy się do Zabbixa, razem z endpointem API api_jsonrpc.php, w naszym przykładzie będzie to:
http://192.168.88.240/api_jsonrpc.php
Pamiętaj, aby po wpisaniu adresu kliknąć Add, tak aby pojawił się on na liście poniżej:

URL, Headers & Params
Przejdźmy teraz do sekcji URL, Headers & Params i omówmy poszczególne pola:
- Base URL – bazowy adres URL dla zapytań. Pole to można zostawić puste, jednak wtedy w każdym panelu trzeba będzie podawać pełny adres URL. Warto zdefiniować bazowy URL, aby uprościć późniejszą konfigurację. Przykładowo:
Jeżeli mamy API z dwoma endpointami:
http://api.test/v1 oraz
http://api.test/v2,
to “http://api.test/” to nasze bazowe URL, a w panelach podajemy, w zależności od potrzeb, tylko “v1” lub “v2”. Dzięki temu, gdy przeniesiemy rozwiązanie na inną nazwę DNS, wystarczy zmienić bazowe URL.
W naszym przykładzie istnieje tylko jeden endpoint, więc możemy wpisać pełny adres – http://192.168.88.240/api_jsonrpc.php. - Custom HTTP Headers – dodatkowe nagłówki HTTP dołączane do każdego zapytania. Oprócz nagłówków specyficznych dla Twojego środowiska, warto wspomnieć o jednym konkretnym nagłówku – Content-Type. API Zabbix akceptuje dane tylko w formacie JSON. Wartość tego nagłówka to jedna z trzech możliwości:
- application/json-rpc,
- application/json,
- application/jsonrequest.
W tym miejscu należy zadać sobie pytanie – “Czy istnieje ryzyko, że ktoś skonfiguruje zapytanie API w taki sposób, że payload nie będzie oznaczony jako JSON?” W dalszej części artykułu wskażemy, na co trzeba zwrócić uwagę by zawsze ten nagłówek był poprawny. Jeżeli jednak masz wątpliwości, możesz jawnie dodać nagłówek Content-Type z wartością application/json, co spowoduje jego nadpisanie w każdym zapytaniu.
W naszym przykładzie zakładamy poprawną konfigurację zapytań, dlatego pozostawiamy tę sekcję pustą.
- URL Query Param – dodatkowe parametry zapytania “doklejane” do URL (np. ?klucz=wartość). API Zabbix z nich nie korzysta, więc zostawiamy tę sekcję pustą.
- Ignore status code check – umożliwia przetwarzanie odpowiedzi nawet przy kodach HTTP innych niż 200. Ponieważ Zabbix zwraca poprawne dane wyłącznie przy kodzie 200, pozostawiamy tę opcję wyłączoną.
- Allow dangerous HTTP methods – pozwala włączyć metody takie jak PUT, PATCH czy DELETE (co może być niebezpieczne). Zabbix korzysta wyłącznie z metody POST, więc opcję zostawiamy odznaczoną.
- Encode query parameters with %20 – zamienia spacje w parametrach zapytania na kodowane %20, np. wartość “klucz api” zamieni na “klucz%20api”. Zabbix nie używa parametrów zapytania, więc zostawiamy odznaczone.
- Include cookies – umożliwia wykorzystanie ciasteczek do autoryzacji kolejnych zapytań (tutaj możemy wpisać nazwę tych ciasteczek, by plugin mógł je wykorzystać w innych zapytaniach). API Zabbix nie korzysta z ciasteczek, dlatego zostawiamy tę sekcję pustą.

Network
W sekcji Network konfigurujemy ustawienia sieciowe:
- Timeout in seconds – czas oczekiwania na odpowiedź API. Przy pobieraniu dużych ilości danych wartość można zwiększyć. W naszym przykładzie pozostawiamy domyślną wartość 60 (sekund).
- Skip TLS Verify – wyłącza weryfikację certyfikatów TLS (zalecane wyłącznie w celach testowych!). W naszym przykładzie nie korzystamy z HTTPS, więc opcja pozostaje wyłączona.
- With CA Cert – umożliwia wskazanie lokalnego certyfikatu CA by plugin wiedział, że certyfikat na frontendzie Zabbix jest zaufany. W naszym przykładzie znowu zostawiamy puste.
- TLS Client Auth – pozwala skonfigurować uwierzytelnianie certyfikatem po stronie klienta, jeżeli twoje środowisko tego wymaga. Należy wtedy podać nazwę serwera oraz certyfikat publiczny i klucz prywatny klienta. W naszym przykładzie nie korzystamy z HTTPS, więc opcja pozostaje wyłączona
- Proxy Mode – konfiguracja serwera proxy:
– poprzez domyślną opcję – zmienne środowiskowe ustawione z poziomu systemu operacyjnego (HTTP_PROXY i HTTPS_PROXY),
– URL – należy wtedy podać adres serwera proxy oraz użytkownika i hasło do autoryzacji ręcznej,
– None – czyli brak proxy.
W naszym środowisku nie używamy proxy, więc ustawiamy zmieniamy wartość na None.

Security
W sekcji Security możemy określić, z jakich adresów URL wolno korzystać w ramach tego źródła danych (Allowed hosts). Zauważ jednak, że pole to jest dokładnie tym samym co pole w sekcji Authentication – zawsze zawiera te same dane. Jeżeli uzupełniłeś je wcześniej, to zobaczysz tutaj adres URL API naszego środowiska Zabbix.
Dodatkowe ustawienie (Query security) dotyczy zachowania pluginu w sytuacji, gdy w zapytaniu skonfigurowanym w panelu pojawią się wrażliwe dane. Co to znaczy “wrażliwe dane”? Przez wrażliwe dane rozumiany jest nagłówek Authorization (co nie jest wprost opisane w dokumentacji, ale wynika z analizy kodu źródłowego pluginu na czas pisania artykułu).
Jeżeli ustawimy ten nagłówek z poziomu panelu (a nie z poziomu źródła danych, tak jak powyżej), to możliwe zachowania:
- Deny – wysłanie zapytania zostanie zablokowane:

- Warn – zapytanie zostanie wysłane, ale pojawi się ostrzeżenie:

- Allow – pozwalamy na ustawianie tego nagłówka w zapytaniu bez żadnych błędów.
Ponieważ nagłówek autoryzacyjny został przez nas już skonfigurowany na poziomie źródła danych, ze względów bezpieczeństwa ustawiamy to pole na Deny.

Pozostałe ustawienia
Pozostałe opcje pozostawiamy puste, ale warto je krótko omówić:
- Health check – nazwa może wprowadzać w błąd, bo nie chodzi tu o sprawdzanie, czy API Zabbix „żyje”. Sekcja ta pozwala ustawić URL dla jakiegoś API jedynie w celu weryfikacji poprawności danych autoryzacyjnych. Dodatkowo funkcja ta działa wyłącznie w miejscu konfiguracji źródła danych (czyli podczas kliknięcia przycisku Save & test). Na moment pisania artykułu sprawdzanie działa jedynie dla metody HTTP GET. Ponieważ Zabbix korzysta z metody POST, autor zaleca pozostawienie tej sekcji pustej.
- Reference data – możemy dodać dodatkowe „statyczne dane” np. w formacie CSV lub JSON, do których później można łatwo odnieść się w zapytaniach podczas konfiguracji panelu. Jeżeli posiadasz statyczne dane, które musisz wykorzystać w wielu panelach, ta sekcja jest właśnie dla Ciebie.
- Global queries – pozwala skonfigurować dodatkowe zapytania, tak jak te definiowane w panelach, które następnie można wykorzystywać w wielu miejscach. Zamiast konfigurować całe zapytanie w każdym panelu, wystarczy wskazać zapytanie globalne. Autor jednak zaleca ostrożność przy korzystaniu z tej funkcjonalności, ponieważ według dokumentacji jest ona przestarzała (lub dokumentacja nie była aktualizowana od kilku lat – funkcja pozostaje „przestarzała” już ponad 4 lata).
Po wprowadzeniu wszystkich danych we wszystkich sekcjach klikamy Save & test.
Jeżeli konfiguracja została wykonana poprawnie, Grafana wyświetli komunikat potwierdzający udane połączenie:

Test połączenia i konfiguracja zapytania API
Aby zweryfikować, czy połączenie działa poprawnie, spróbujemy pobrać dane o naszym użytkowniku za pomocą API Zabbix. W tym celu otwieramy sekcję Explore, którą znajdziesz w menu po lewej stronie:

Upewnij się, że jako źródło danych wybrane jest wcześniej skonfigurowane połączenie „zabbix-API-7-0”. Po jego wyborze pojawi się dość rozbudowany kreator zapytań:
- Type – typ danych, na których będziemy pracować. Zabbix API bazuje na formacie JSON, więc zostawiamy domyślną opcję,
- Parser – parser, którego użyjemy do uzyskania interesujących danych. Na tą chwilę zostawimy domyślną wartość JSONata, ale w następnych artykułach przetestujemy także inne opcje.
- Source – skąd chcemy pobrać dane. Możemy np. statycznie wprowadzić dane (opcja Inline). Nas interesują dane z API Zabbix, więc zostawiamy domyślne URL.
- Format – sposób formatowania danych po przetworzeniu. Przy pracy z API Zabbix raczej nie ma potrzeby zmiany domyślnej wartości Table, więc pozostawiamy ją bez zmian.
- Method – Zabbix do wszystkich zapytań używa metody POST, więc pamiętaj, aby ustawić ją tutaj poprawnie.
- URL – adres, na który wysyłamy zapytania. Jeżeli w konfiguracji źródła danych ustawiłeś Base URL na pełny adres API Zabbix, pole to należy pozostawić puste. W przeciwnym wypadku trzeba podać cały adres URL.
Po wypełnieniu podstawowych parametrów zapytania, wypełnijmy teraz informacje o zapytaniu, klikając na przycisk Headers, Body, Request params:

Pojawi nam się dodatkowa sekcja, gdzie możemy ustawić tzw. “Payload”. Typ zapytania zostawiamy na Raw, natomiast Body Content Type zmieniamy na JSON. Zmiana ta spowoduje ustawienie nagłówka Content-Type na wartość application/json. Jeżeli nie wymusiłeś tego nagłówka podczas konfiguracji źródła danych, to inna wartość tego pola niż JSON spowoduje błąd:
error while performing the infinity query. unsuccessful HTTP response code status code : 412 Precondition Failed |
Autor jednak zachęca do ustawiania typu JSON, ponieważ wtedy zapytanie zostanie sformatowane, a plugin przeprowadzi wstępną walidację struktury JSON (podkreślając na czerwono sytuację, gdy zapytanie nie jest poprawnym JSON-em).
Przypomnijmy, że chcemy pobrać dane o użytkowniku. Wklejamy więc jako zawartość zapytania prosty JSON wyciągający wszystkie dane o użytkowniku (więcej informacji o metodzie user.get można przeczytać w >dokumentacji):
{ |
Zatrzymajmy się i przeanalizujmy nasze zapytanie API:
jsonrpc: "2.0" |
Określa wersję protokołu JSON-RPC, której używa Zabbix. W tym przypadku jest to wersja 2.0 – obowiązkowa dla wszystkich zapytań do API Zabbix.
method: "user.get" |
Nazwa metody, którą wywołujemy. user.get służy do pobierania informacji o użytkownikach w systemie Zabbix.
params: {} |
Parametry wywołania metody. W tym przykładzie pozostawiamy je puste, co oznacza, że API zwróci wszystkie dane o użytkownikach, do których ma dostęp użytkownik wykonujący zapytanie za pomocą tokenu.
W praktyce można tu dodać filtry, np. na konkretnego użytkownika, grupę użytkowników lub inne kryteria. Warto pamiętać, że jeśli zapytanie wykonuje zwykły użytkownik, API zwróci tylko dane dotyczące tego konkretnego użytkownika – nie zobaczy danych innych użytkowników.
id: 1 |
Identyfikator zapytania. Jest to wartość dowolna, ale musi być unikalna w danym zapytaniu, aby móc powiązać odpowiedź z konkretnym żądaniem. W odpowiedzi API zwróci to samo id, co pozwala upewnić się, że otrzymana odpowiedź odpowiada właśnie temu zapytaniu.
Wracając do konfiguracji naszego zapytania, nie dodajemy już żadnych dodatkowych nagłówków (a w szczególności nagłówka autoryzacyjnego – ponieważ został on dodany na poziomie źródła danych i będzie automatycznie dołączany do wszystkich zapytań) ani parametrów URL. Sekcja powinna wyglądać w następujący sposób:

W tym momencie, po kliknięciu Run Query powinien pojawić się mniej więcej taki wynik:

Dzięki temu wiemy, że połączenie działa. Wynik może wyglądać inaczej niż oczekiwaliśmy, ponieważ API zawsze zwraca trzy obiekty:
- jsonrpc -wersję protokołu JSON-RPC;
- id – identyfikator odpowiedniego żądania.
- result – dane zwrócone przez metodę.
Nas interesuje tylko wynik, dlatego chcemy wyświetlić dane, które znajdują się w obiekcie result. Aby wyświetlić tylko te dane, przechodzimy do sekcji Parsing options & Result fields i w polu Rows/Root wpisujemy ścieżkę JSON:
$.result |
Jeżeli nie znasz się na ścieżkach JSON (ang. JSON Path), jako administrator Zabbix powinieneś znać podstawy – w razie wątpliwości warto zajrzeć do >dokumentacji Zabbix oraz użyć narzędzi do sprawdzania ścieżki JSON, np. >Jsonpathfinder. Po wprowadzeniu powyższej ścieżki JSON oraz ponwnym kliknięciu Run query, powinniśmy zobaczyć już tabelkę z wszystkimi danymi o naszym użytkowniku:

Reszta konfiguracji nie będzie potrzebna w dalszych przykładach, więc omówimy ją krótko:
- Columns w sekcji Parsing to proste narzędzie do filtrowania wyników i przypisywania odpowiednich typów danych (np. Dane tekstowe lub liczba). Przykładowo przedstawiono wyciąganie tylko dwóch informacji – userid jako liczba, oraz username zmienione na Nazwa użytkownika jako tekst:

- Computed colums, Filter, Group by pozwala na dodanie kolumn, które mogą być wynikiem działania na danych z innych kolumn, lub też stosowania dodatkowych filtrów lub grupowania. Przykładowo – możemy od razu policzyć liczbę zwracanych użytkowników za pomocą naszego zapytania wpisując w polu Summarize funkcję count(userid):

- Pagination odpowiada za automatyczne dzielenie danych na strony w przypadku bardzo dużych odpowiedzi z API. W praktyce oznaczałoby to, że jeśli zapytanie zwracałoby ogromną liczbę wyników, API mogłoby poinformować, że trzeba pobrać dane w kilku partiach, wysyłając kolejne zapytania. Dobra wiadomość jest taka, że API Zabbix nie korzysta z paginacji – zawsze zwraca wszystkie dane, o które prosimy, więc nie musimy się tym martwić.
Podsumowanie
Pokazaliśmy, jak skonfigurować zapytania do API Zabbix za pomocą pluginu Infinity i jak w prosty sposób przetestować połączenie w Grafanie. Dzięki temu wiesz już, że pobieranie danych przez API może być wygodne i przejrzyste – bez konieczności wchodzenia w struktury bazy danych.
W kolejnym artykule zajmiemy się parserem UQL, pokazując jego możliwości w pracy z danymi z API Zabbix w Grafanie. To właśnie tam pokażemy, jak skonfigurować zapytania i zapoznać się z jego składnią, aby sprawnie przetwarzać dane z API Zabbix.
Jednocześnie zapraszamy na nasze nowe duże szkolenie Zabbix Expert z ponad 50% rabatem! Zapisy tutaj: https://zabbix.sekurak.pl
Jeżeli po przeczytaniu tego artykułu poczułeś satysfakcję podobną do tej przy łyknięciu dobrej kawy, możesz wesprzeć autora równie >dobrą kawką!
~ Albert Przybylski, zawodowo: Architekt ds. Monitoringu w firmie Aplitt, prywatnie: pełnoprawny fanatyk Zabbixa zasilany kawą
