Iniciando rápido com a API do Zabbix usando Python 3

Isaque Profeta
Zabbix Brasil
Published in
9 min readAug 9, 2020

Passo a passo com preparação de dependências em um Ubuntu 18.04, primeiros testes de acesso e dicas de uso.

Pyhton + PIP

Começando com o básico, instale o Python versão 3 (Linguagem) e o PIP para a versão 3 (Instalador de bibliotecas prontas da linguagem)

sudo apt update && sudo apt install python3 python3-pip

Por via das dúvidas, confirme que o Python do seu sistema operacional é a versão 3 testando no terminal (senão você pode precisar usar “python3” ao invés de “python”):

~$ python -V
Python 3.6.9
~$ pip -V
pip 20.1.1 from /home/isaque/.local/lib/python3.6/site-packages/pip (python 3.6)

pyZabbix

A API do Zabbix tem alguns requisitos de autenticação e usa o formato JSON para organizar os dados recebidos/enviados pela API, para iniciar então instale a biblioteca pronta do lukecyca/pyzabbix (Cuidado para não confundir com outra biblioteca existente chamada py-zabbix)

pip install pyzabbix

Estrutura de projeto

Usando a pyzabbix vamos escrever nosso primeiro código. Crie uma pasta chamada apizabbix na sua home para guardar o projeto e crie 2 arquivos para configurações, um para guardar as credenciais de acesso e outro para transformar o diretório em um modulo do Python

touch apizabbix.py
touch consulta.py
code .

Agora falando dos código de consulta vamos precisar de mais 2 arquivos, sendo um para autenticação e criação de sessões, e outro para a primeira pesquisa:

touch apizabbix.py
touch consulta_001.py
code .

Em seguida abra a pasta no seu editor favorito (vou usar o Visual Studio Code neste tutorial):

code .
VSCode com arquivos iniciais criados
VSCode com arquivos iniciais criados

Primeiramente, o arquivo __init__.py fica vazio (ele apenas define nosso projeto como módulo do Pyhton para facilitar o processo de “import”), já dentro do arquivo config.ini adicione a URL completa de acesso ao frontend, junto ao usuário e senha de acesso ao Zabbix conforme abaixo, pois vamos evitar usar os dados de acesso diretamente no arquivo .py aproveitando um módulo chamado “configparser”:

[zabbix]
server=http://127.0.1.1:8080/zabbix
user=Admin
password=zabbix

Arquivo de criação de sessões para pesquisa

Agora dentro do arquivo apizabbix.py vamos primeiro chamar a biblioteca do pyzabbix que instalamos, e logo depois o módulo de configuração do “configparser”:

from pyzabbix import ZabbixAPI
import configparser

Depois disso vamos preparar uma função que vai ser chamada por outros arquivos de script apenas para logar dentro do Zabbix e executar as consultas, e logo em seguida vamos preparar tudo para o “configparser” buscar os dados no arquivo config.ini:

def connect():
config = configparser.ConfigParser()
config.read("config.ini")

user = config.get('zabbix', 'user')
password = config.get('zabbix', 'password')
server = config.get('zabbix', 'server')

Ainda dentro dessa função vamos adicionar a criação do objeto de conexão e fazer o login na ferramenta (caso esteja usando HTTPS com certificado auto assinado, você pode ignorar os certificados removendo o comentário da segunda linha):

    zapi = ZabbixAPI(server)
# zapi.session.verify = False
zapi.login(user, password)

Vamos agora fechar a função usando um “return”:

    return zapi

E o arquivo final de chamada para o Zabbix vai ficar da seguinte forma:

A primeira consulta

Agora dentro do arquivo consulta_001.py onde criaremos o primeiro exemplo de consulta, vamos primeiro chamar a nossa função de acesso à API do Zabbix e iniciar uma nova conexão:

import apizabbixapi = apizabbix.connect()

Pronto! A partir de agora basta mergulhar de cabeça na documentação oficial e começar as pesquisas a partir desse ponto.

Nesse primeiro exemplo vamos ver uma pesquisa simples de todos os “Grupos de Hosts”, que pela documentação é o hostgroup.get então na nossa biblioteca pyzabbix vai ser uma função/metodo do objeto api, ficando então no formato api.hostgroup.get() (com os parênteses no final).

Vamos agora adicionar então essa consulta ao nosso arquivo de consulta_001 e vamos imprimir em tela os resultados (note que eu usei o “pprint” para mostrar de forma mais organizada o resultado do JSON de resposta)

hostgroups = api.hostgroup.get()
pprint(hostgroups)

Logo depois de imprimir o resultado lembre sempre de fechar a sessão da API para não lotar sua tabela de sessões no Zabbix:

api.user.logout()

Arquivo completo para referência:

Execute o script acima entrando na pasta via terminal e use o comando (use o Crtl+Shift+` para chamar o terminal integrado se estiver usando o VSCode):

python consulta_001.py
Buscando todos os grupos do zabbix via API

Usando referências da documentação

Usando a biblioteca pyzabbix e olhando a documentação da API se for necessário utlizar parâmetros de filtro e seleção, temos primeiro que “traduzir” do JSON para o Python. Então vamos criar um segundo exemplo copiando o nosso consulta_001.py:

cp consulta_001.py consulta_002.py

Nesse próximo exemplo vamos usar um filtro no hostgroup.get para remover da pesquisa os grupos que são de templates (Nesse caso a regra é todos os grupos em que o nome não começa com o grupo pai Templates), e para fazer isso precisamos de algumas opções especiais que muita gente não acha porque não encontra a página de comentários e referência da API.

Nesse caso vamos precisar da opção “excludeSearch” que conforme a documentação “retorna os resultados que não batem com os critérios do parâmetro ‘search’ ”, então vamos ver como ficaria o JSON editando um pouco o exemplo de “hostgroup.get” da documentação oficial para o nosso exemplo:

{
"jsonrpc": "2.0",
"method": "hostgroup.get",
"params": {
"output": "extend",
"excludeSearch": true,
"search": {
"name": [
"Templates/"
]
}
},
"auth": "6f38cddc44cfbb6c1bd186f9a220b5a0",
"id": 1
}

Como usamos a programação com a biblioteca pyzabbix, podemos ignorar tudo que não está dentro do “params” e estender as opções da nossa busca da seguinte forma (note as diferenças entre o JSON e os parâmetros de função do Python, cuidado ao “copiar e colar”):

hostgroups = api.hostgroup.get(
output='extend',
excludeSearch=True,
search={
'name': 'Templates'
}
)

Agora para finalizar vamos fazer um exercício de loop (laço de repetição) nessa lista e fazer também um acesso a uma propriedade específica em um dicionário, e então vamos imprimir apenas os nomes dos grupos, usando um “for” e o nosso logout da API:

for hostgroup in hostgroups:
print(
hostgroup['name']
)
api.user.logout()

Observação para quem chegou do Zabbix e não conhece Python: uma lista é um array, que são todos os resultados entre colchetes “[]” separados por virgula e um dicionário é cada resultado entre chaves “{}” cheio de campos no formato {“chave”; “valor”}, o loop do “for” vai percorrer a lista e o print vai imprimir apenas o valor da chave ‘name’ em cada um dos resultados da lista nesse caso .

Arquivo completo para referência:

Execute o script acima entrando na pasta via terminal e use o comando (use o Crtl+Shift+` para chamar o terminal integrado se estiver usando o VSCode):

python consulta_002.py

Correlação entre dados da API usando select* e filtros de campos

Nesse exemplo, você vai fazer a correlação de informações entre entidades no Zabbix quando o método da API possuir a opção de “select*” como por exemplo no “hostgroup.get na documentação, e vai fazer também filtro dos campos pesquisados com o “output”:

Opções de select* dentro da API do hostgroup.get

Primeiro copie o consulta_001.py para o nosso terceiro exemplo:

cp consulta_001.py consulta_003.py

Adicione o “selectHosts” dentro do “hostgroup.get” para buscar os “hosts” dos grupos que estão sendo pesquisados:

hostgroups = api.hostgroup.get(
output='extend',
excludeSearch=True,
search={
'name': 'Templates'
},
selectHosts='extend'
)

Notou o “extend” acima? Essa opção trás todos os dados do host, o que pode ser desnecessário apenas gerando poluição de dados, confira isso rodando o comando no terminal.

python consulta_003.py

Para facilitar o trabalho, diminua o escopo com uma lista dos dados que você quer, como o exemplo abaixo, filtrando o “hostname(no campo “host”) e o “display name” (no campo “name”):

hostgroups = api.hostgroup.get(
output='extend',
excludeSearch=True,
search={
'name': 'Templates'
},
selectHosts=[
'name',
'host'
]
)

Rode novamente o comando no terminal e veja o resultado:

python consulta_003.py
Resultado do selecHosts com filtro de dados recuperados

Termine trocando o “pprint” pelo “print” com uso do “for”, e perceba que é necessário fazer um novo loop dentro de cada grupo, uma vez que veio como resultado uma lista de vários dicionários de informações sendo um para cada host :

for hostgroup in hostgroups:
print('Grupo: ' + hostgroup['name'])

for host in hostgroup['hosts']:
print(' Host: ' + host['name'] + ': ' + host['host'])

Arquivo completo para referência:

Correlação entre dados da API usando Python

Em alguns casos não existe a opção de “select*” no método utilizado mas é necessário fazer uma integração entre ele e outra informação, nesse caso vamos buscar duas consultas em cascata e em seguida usar o Python para realizar a correlação entre elas.

Primeiro copie o consulta_001.py para o quarto exemplo:

cp consulta_001.py consulta_004.py

Vamos usar nesse exemplo duas chamadas na API para buscar os dados de todos os eventos de um grupo de hosts, então primeiro precisamos de dados sobre o grupo, para depois fazer o filtro dentro da opção “groupids” do método “event.get”.

Primeiro adicione o “output” para ver apenas o “id” de cada grupo achado e vamos trocar o “search” pelo “filter” que vai trazer só o grupo que tiver o nome exato da busca.(O “search” retorna qualquer coisa “parecida” com o pesquisado lembrando com o LIKE no SQL. Mais detalhes sobre o “search” na referência de comentários da API que já citei anteriormente):

hostgroups = api.hostgroup.get(
output=['id'],
filter={
'name': 'Linux servers'
}
)

Para quem está chegando no Python agora, o resultado do “hostgroups” vai vir parecido com o abaixo (você pode testar fazendo um print do mesmo):

[{'groupid': '2'}]

Então para acessar apenas o “id” 2, que vamos precisar na consulta abaixo, deve-se filtrar a primeira posição da lista com o “[0]” e em seguida o valor da chave ‘groupid’ dessa primeira posição com o “[‘groupid’]”, conforme abaixo:

hostgroups[0]['groupid']

Adicione agora a pesquisa de eventos, filtrando o “groupids” pelo id do grupos pesquisado por nome anteriormente, e escolha alguns campos de output:

events = api.event.get(
output=[
'clock',
'name',
'value',
'severity',
],
groupids=hostgroups[0]['groupid'],
)

Outros dois detalhes interessantes são:

  • Primeiro todos os horários da API vem em formato timestamp (número de segundos passados desde 1 de Janeiro de 1970) então deve-se fazer a conversão, o que não é muito difícil com a função “fromtimestamp” da biblioteca “datetime” do Python dentro de um loop para cada evento e em seguida transformando o formato usando o “strftime”.
from datetime import datetime
for event in events:
hora_evento = datetime.fromtimestamp(
int(event['clock'])
).strftime('%Y-%m-%d %H:%M:%S')
  • Em segundo lugar a severidade é um digito de 0 à 5 conforme o padrão do Zabbix na ordem, então podemos fazer uma lista das severidades na ordem correta e indexar as mesmas usando o número:
severidades = [
'Não classificada',
'Informação',
'Atenção',
'Média',
'Alta',
'Desastre'
]

for event in events:
severidade = severidades[(int(event['severity']))]

Note também nos dois casos que como todos os dados da API vem no formato de string então é necessário converter o tipo para inteiro para que o python use ele na indexação da lista, o que pode-se fazer usando a função “int()”.

Para fazer um print formatando uma mensagem final mais interessante, vou finalizar o tutorial deixando aqui um exemplo final desse código de eventos com a conversão do timestamp e do mapeamento de severidade:

Rodando o script no terminal:

python consulta_003.py
Resultado final de formatação dos eventos do grupo ‘Linux servers’

E é isso! Foco nos estudos e paciência nos testes é o segredo para fazer a combinação Python+Zabbix entregar relatórios e outros resultados que você precise.

--

--

Isaque Profeta
Zabbix Brasil

Security operations automation, monitoring tools specialist and Python/JavaScript enthusiast, but sometimes I can play with OKR and ITIL too.