├── requirements.txt ├── pytest.ini ├── requirements-test.txt ├── setup.cfg ├── .gitignore ├── .travis.yml ├── protobix ├── __init__.py ├── datacontainer.py ├── zabbixagentconfig.py ├── senderprotocol.py └── sampleprobe.py ├── tests ├── __init__.py ├── zabbix │ ├── zabbix_server.conf │ ├── zabbix_server_sqlite3.sql │ └── zabbix_server_mysql.sql ├── tls_ca │ ├── protobix.crl │ ├── rogue-protobix.crl │ ├── protobix-ca.cert.pem │ ├── protobix-client.cert.pem │ ├── rogue-zabbix-server.cert.pem │ ├── protobix-zabbix-server.cert.pem │ ├── protobix-client.revoked.cert.pem │ ├── rogue-protobix-client.revoked.cert.pem │ ├── protobix-client.not-yet-valid.cert.pem │ ├── rogue-protobix-client.not-yet-valid.cert.pem │ ├── rogue-protobix-ca.cert.pem │ ├── rogue-protobix-client.cert.pem │ ├── protobix-client.key.pem │ ├── protobix-zabbix-server.key.pem │ ├── protobix-client.not-yet-valid.key.pem │ ├── protobix-client.revoked.key.pem │ ├── rogue-protobix-client.key.pem │ ├── rogue-zabbix-server.key.pem │ ├── rogue-protobix-client.revoked.key.pem │ └── rogue-protobix-client.not-yet-valid.key.pem ├── docker-tests.sh ├── test_memory_leak.py ├── test_datacontainer.py ├── test_senderprotocol.py ├── test_zabbixagentconfig.py └── test_sampleprobe.py ├── setup.py └── README.md /requirements.txt: -------------------------------------------------------------------------------- 1 | configobj 2 | simplejson 3 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts='-k-_need_backend' 3 | -------------------------------------------------------------------------------- /requirements-test.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pytest-cov 3 | mock 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .coverage 2 | .cache 3 | *.pyc 4 | *.swp 5 | /__pycache__/ 6 | /.eggs/ 7 | MANIFEST 8 | dist/ 9 | *.egg-info 10 | *.xdb 11 | *.db 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.4" 5 | - "3.5" 6 | # comand to install requirements 7 | install: pip install -r requirements.txt -r requirements-test.txt 8 | # command to run tests 9 | script: python setup.py test 10 | -------------------------------------------------------------------------------- /protobix/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Protobix is a simple module which implement Zabbix Sender protocol 3 | It provides a sample probe you can extend to monitor any software with Zabbix 4 | """ 5 | from .datacontainer import DataContainer 6 | from .senderprotocol import SenderProtocol 7 | from .sampleprobe import SampleProbe 8 | from .zabbixagentconfig import ZabbixAgentConfig 9 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import pytest 5 | try: 6 | import coverage 7 | coverage_options = ['--cov', 'protobix', '--cov-report', 'term-missing'] 8 | except ImportError: 9 | coverage_options = [] 10 | try: 11 | import pylint 12 | pylint_options = ['--pylint '] 13 | except ImportError: 14 | pylint_options = [] 15 | 16 | pytest_options = ['-v', '-k-_need_backend'] 17 | pytest_options += coverage_options 18 | pytest_options += pylint_options 19 | 20 | pytest.main(pytest_options) 21 | -------------------------------------------------------------------------------- /tests/zabbix/zabbix_server.conf: -------------------------------------------------------------------------------- 1 | LogType=console 2 | DebugLevel = 3 3 | 4 | PidFile=/tmp/zabbix_server.pid 5 | 6 | DBName=tests/zabbix/zabbix.db 7 | 8 | StartPollers=0 9 | StartIPMIPollers=0 10 | StartPollersUnreachable=1 11 | StartTrappers=1 12 | StartPingers=0 13 | StartDiscoverers=0 14 | StartHTTPPollers=0 15 | StartTimers=1 16 | StartEscalators=1 17 | StartJavaPollers=0 18 | StartVMwareCollectors=0 19 | StartSNMPTrapper=0 20 | StartDBSyncers=4 21 | StartProxyPollers=0 22 | 23 | ListenIP=127.0.0.1 24 | 25 | Timeout=3 26 | TrapperTimeout=300 27 | 28 | TLSCAFile=tests/tls_ca/rogue-protobix-ca.cert.pem 29 | TLSCRLFile=tests/tls_ca/rogue-protobix.crl 30 | TLSCertFile=tests/tls_ca/rogue-zabbix-server.cert.pem 31 | TLSKeyFile=tests/tls_ca/rogue-zabbix-server.key.pem 32 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix.crl: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICijB0AgEBMA0GCSqGSIb3DQEBDQUAMAAXDTE2MDgxNTAwMDAwMFoXDTE2MDkx 3 | MzIzNTk1OVowMDAuAgEFFw0xNjA4MTUxNDA5MzBaMBowGAYDVR0YBBEYDzIwMTYw 4 | ODE1MTQwOTAwWqAOMAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQENBQADggIBAFj5 5 | wF7laMNp/W2VLead+cOoqpm/pXHiSjhmoby94idshAP628lSVvLaq7Be3Ix/fWs8 6 | e2euXaIq9anHjRRZaCneVU02WLHivwkpkiQ2a9sRBNHH70c1RQtMH3gQnGjYk6eR 7 | 2Sq5qEoqb6i5JcO6L5pCBu/rcbsqcy/bWDBjqLJl8355o4d8YhiaP15JsmfJy2ab 8 | OtZ+93rRd9HfNUtNjaBO+KO5DoXtmFwAFmu+sxKjyHlIMS2/fqZbR9NFd3c6J1JO 9 | CG2f5/kulizsSrHP2lO1lpgQd97By8zJzWqCPOXiu/sM7LixB3jIouqvfLXgkq2b 10 | PCO+8CoqFP5tX5VWuW02d5DR3lL4uGyl5++imhityDNX2U4n0mQylgpETdCFIR2h 11 | y24R0j9o9Vqmobip20R9hUvGzpIOfsDocOFflH2Di2YydWw+V0nDeawBR+1veib4 12 | l3ueS+M+5dfmaw4CBK+n0wAoJdSnc2NdzTfb+bTXkMUhWlFUqNTX8CARPAG0U+Rq 13 | 3P4JjtpPG3+1U5nxxaW/xXRT6xQViZOLRfYP/LDZcTEcPqoyS5jHxU9DCrbA3/BI 14 | jevZpklM2Uzg/TjEGWSD9XmU9N+In1t9EC3Ed82Bj868c37KxA/6/PYbYxoiDSb6 15 | vukgA2k0yhPtlxnOgh6uHk28f3eM6Q2Fb0QRd1UT 16 | -----END X509 CRL----- 17 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from setuptools import setup 5 | 6 | setup( 7 | name = 'protobix', 8 | packages = ['protobix'], 9 | version = '1.0.2', 10 | install_requires = [ 11 | 'configobj', 12 | 'simplejson' 13 | ], 14 | tests_require = [ 15 | 'mock', 16 | 'pytest', 17 | ], 18 | test_suite='tests', 19 | description = 'Implementation of Zabbix Sender protocol', 20 | long_description = ( 'This module implements Zabbix Sender Protocol.\n' 21 | 'It allows to build list of items and send ' 22 | 'them as trapper.\n' 23 | 'It currently supports items update as well as ' 24 | 'Low Level Discovery.' ), 25 | author = 'Jean Baptiste Favre', 26 | author_email = 'jean-baptiste.favre@blablacar.com', 27 | license = 'GPL-3+', 28 | url='https://github.com/jbfavre/python-protobix/', 29 | download_url = 'https://github.com/jbfavre/python-protobix/archive/1.0.2.tar.gz', 30 | keywords = ['monitoring','zabbix','trappers'], 31 | classifiers = [], 32 | ) 33 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix.crl: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIDMjCCARoCAQEwDQYJKoZIhvcNAQENBQAwgaUxCzAJBgNVBAYTAkZSMRYwFAYD 3 | VQQIEw1JbGUgZGUgRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczERMA8GA1UEChMIcHJv 4 | dG9iaXgxEzARBgNVBAsTCm1vbml0b3JpbmcxIjAgBgNVBAMTGXJvZ3VlLXByb3Rv 5 | Yml4LmRvbWFpbi50bGQxIjAgBgkqhkiG9w0BCQEWE3Byb3RvYml4QGRvbWFpbi50 6 | bGQXDTE2MDgxNTAwMDAwMFoXDTE2MDkxMzIzNTk1OVowMDAuAgEEFw0xNjA4MTUx 7 | NDA5MzhaMBowGAYDVR0YBBEYDzIwMTYwODE1MTQwOTAwWqAOMAwwCgYDVR0UBAMC 8 | AQEwDQYJKoZIhvcNAQENBQADggIBAK3gR/qI96K6nx9C3eRF55rtcIe+9SQ9kvCY 9 | GYZqa0iDBJRH+H17C4rEAzCwqf6FCQ/DFhlAnT8oNr0nL2tIFlye76nDbi6qiM/m 10 | EDAv63Oaq8mV1/W1PNWhIPmiwWRsoAYjKnq3gk1xmvSN69yIEDxt7hj/mxTmegF+ 11 | pxY96Jj9M1GsCxjsYYpc0jY5JnNAoM+AVjXSpG9CJIVxQbk6HtY9N1ybkPhZdZuM 12 | +5VoD61lpmBdyDFD2n9n71b/22yi6kHkCu84cB+Zf9IrjXXjSZUlOQk3NHkpbz2R 13 | 5rACoANVqlRjZ8+fITqMmO1ZeumondNJcjkumt+taArMhDTVfiFgwNo4D9ZUkADm 14 | bhBWpkyLHDk6+DyFdHq517ZNr3kaORMgJikgi1+S1PzVYu8Or4Wuc6IUYM4aeuyL 15 | Lz0EZVM6ssxK50Vy+t3t5H+KEXu4BS2GGYSQ7kkGTOCU+OC8lhSAA+Hc81yB7OVc 16 | 9PU63ye2swMewHP2R1VriooXyCqSNvgz/TNDwcwaSpN3uoVuTGWVHegRP7D3IQHp 17 | jySjDnKa5oua0HDCkZAhjdUTLvidqvv/u5S8CWS+Maj+IciLSfINOelRVHKMDXIE 18 | MZaA7FlIFTx50+nWnXO21A4JfURfDiB/mYe1gS8FFJ8cExsLQ29lYJ2pkLoPX85b 19 | FpoB3hHU 20 | -----END X509 CRL----- 21 | -------------------------------------------------------------------------------- /tests/docker-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION=$(sed 's/\..*//' /etc/debian_version) 4 | case ${VERSION} in 5 | 7) echo 'Debian Wheezy' 6 | packages_list='python2.7 python-setuptools python-configobj python-simplejson python-pytest python-mock adduser' 7 | test_suite_list='python' 8 | ;; 9 | 8) echo 'Debian Jessie' 10 | packages_list='python2.7 python3 python-setuptools python3-setuptools python-configobj python-simplejson python3-configobj python3-simplejson python-pytest python-pytest-cov python-mock python3-pytest python3-pytest-cov python3-mock' 11 | test_suite_list='python python3' 12 | ;; 13 | *) echo 'Debian stretch/sid' 14 | packages_list='python2.7 python3 python-setuptools python3-setuptools python-configobj python-simplejson python3-configobj python3-simplejson python-pytest python-pytest-cov python-mock python3-pytest python3-pytest-cov python3-mock' 15 | test_suite_list='python python3' 16 | ;; 17 | esac 18 | 19 | function cleanup() { 20 | cd /home/python-protobix 21 | find . -name '*.pyc' -exec rm {} \; 2>/dev/null 22 | find . -name '__pycache__' -exec rm -r {} \; 2>/dev/null 23 | } 24 | 25 | # Update package list 26 | apt-get update 27 | 28 | # Install dependencies for both python 2.7 & python 3 29 | apt-get -qq -y install ${packages_list} 30 | 31 | # Create an unprivileged user 32 | addgroup -gid 1000 protobix 33 | adduser --system -uid 1000 -gid 1000 --home /home/python-protobix \ 34 | --shell /bin/bash --no-create-home --disabled-password \ 35 | protobix 36 | 37 | 38 | for test_suite in ${test_suite_list} 39 | do 40 | # Clean existing cache files 41 | cleanup 42 | # Run test suite 43 | su - protobix -s /bin/bash -c "cd /home/python-protobix;${test_suite} setup.py test" 44 | done 45 | 46 | # Clean existing cache files 47 | cleanup 48 | -------------------------------------------------------------------------------- /tests/zabbix/zabbix_server_sqlite3.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO `hosts` VALUES (10105,NULL,'protobix.host1',0,0,'',0,0,0,-1,2,'','',0,0,0,0,NULL,0,0,0,0,0,'','',0,0,0,'','protobix.host1',0,NULL,'',1,1,'','','',''),(10106,NULL,'protobix.host2',0,0,'',0,0,0,-1,2,'','',0,0,0,0,NULL,0,0,0,0,0,'','',0,0,0,'','protobix.host2',0,NULL,'',1,7,'','','protobix','70726f746f62697870726f746f62697870726f746f62697870726f746f626978'); 2 | 3 | INSERT INTO `items` VALUES (23663,2,'','',10105,'my.protobix.item.int','my.protobix.item.int',0,1,1,0,3,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23664,2,'','',10105,'my.protobix.item.string','my.protobix.item.string',0,1,0,0,4,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23667,2,'','',10105,'my.protobix.lld_item1','my.protobix.lld_item1',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'30',0,0,0,'',0),(23670,2,'','',10105,'my.protobix.lld_item2','my.protobix.lld_item2',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'1',0,0,0,'',0),(23665,2,'','',10106,'my.protobix.item.int','my.protobix.item.int',0,1,1,0,3,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23666,2,'','',10106,'my.protobix.item.string','my.protobix.item.string',0,1,0,0,4,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23669,2,'','',10106,'my.protobix.lld_item1','my.protobix.lld_item1',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'1',0,0,0,'',0),(23668,2,'','',10106,'my.protobix.lld_item2','my.protobix.lld_item2',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'30',0,0,0,'',0); 4 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-ca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIE7TCCAtWgAwIBAgIBATANBgkqhkiG9w0BAQ0FADAAMB4XDTE2MDgxNTEzNDEw 3 | MFoXDTI2MDgxNTEzNDEwMFowADCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC 4 | ggIBAMZ7j4THkcGV2l0J18R5vmcotUOX2m0ZrYd85O+bub9qjCCbvIf+iUywhCZW 5 | emX2leEa27/8kPQp3NG0rJuOUOaon4SJDgHexykAMJ3Y6qHF9A/2J3kWH+hlhxYw 6 | ODhqDCURMWM9DkMi4+sb0jdGPqtSuTzySpeE3perx2bhuX1yn5wjLsbcNahej4vv 7 | PgKbe9rPZefkWLR8mzQ8iCrRskg14BKfGS+X694F6WdcJ6zytN8Pjqa+Vyxs4p/R 8 | 5B9jk9QsVQWybJd6n3k0lJCOVI9FBIpQF0wDk9pcjljhzoJh02a4kFQTMPwZuLNj 9 | gnaxc4vyMdijWzPwW6U5f1eWnV1iuCu2P7Y7y7DYnql5FZK9dcGSQU+X7xQXjRPQ 10 | Up07i5v+3KFI6bW0fq5jMTCY+SJZXmqM8Sq5JZxOT/ZsFFCZomHRODsyOYHrTt1l 11 | ZXbz7X/aDErzQMiNKgTVh12TterCoMoXmFwPcPOQzLfG1rMhNCL1NaCh19AEjEeB 12 | lXHv0iQvjXbQ8i0IBRLD3gTLFPB+BjWda8+25QH9qjgh30hhk0aGb0sQAGcsBBiT 13 | RZg64rkTPE66TwCtBOkJKuO7Sn8IJVJg14t3hzClzV7Uu+5daD14JQ4+MoBjYqaq 14 | ZCePvVJvqEyOJlf8L0WajTERFLj+wfIc2nxTIF+454uYuxnlAgMBAAGjcjBwMA8G 15 | A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKZzBzWCQhtveZaVHIt4QV/MMfOUMAsG 16 | A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgENBBEWD3hj 17 | YSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQ0FAAOCAgEACI3yQOe04cXdqhBwS5s/ 18 | GcK7iv2il0b9rDQHSyPlhNdfydTD24qV0WbPzA2IAOgdO+sYebUD8TgB2AVfuzmu 19 | NmeSFESWpjAX88bpsWbhlfAO97FSLW0dhApCEXdXMDgDLa6B04Vn4ybECLYKZfWA 20 | XmcacJqbX12MDJqJ2WST9RwNO/eQ61iR8DHtuyh3lFiAy+F36GZmviMJ146PaNqF 21 | W2ChoiOYDVHeWY5StSptDTeGYrBuwgGODsmsX+umPF0dU9V00Ods95I5tSsE3jNg 22 | +OCYibHwZ4ojfAUUp72sVfP6zZ4EWo50pH+GXy5uiF6ScqJ0F/af7NSaEzHocyPi 23 | QrR8CtbVDShNqO1IPHWeQfozGf6Ht1p90HaPOFm5hk53mH/oK9YDuG9ftm9a0WFg 24 | DR479TqGWpYDkP1hu0XKkv1desWRA/7I/X3RyyvMXDycdD4ykwJVqWBMy5X0dlKr 25 | YbftZYvoJJMJSey61/4WrO1xN0JFyLRVkA/7Chz7Sp3wlNu826ZR9QbCyC2lMfmr 26 | 8MMEQkEb8BAPVOfkfA2nbb9P1dzkknBsgnT5zbBRQBvHWgj7X/kwqodlSEB35/2u 27 | HQQJm6fyjctAvnBnkJOqtWIoJEnECMLY+Frlu6xBlqT1gcE39t5tHeBls2BDF8y+ 28 | HWXDA9jZ29CS94f/CK8Tweg= 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-zabbix-server.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFkDCCA3igAwIBAgIBBjANBgkqhkiG9w0BAQ0FADCBpTELMAkGA1UEBhMCRlIx 3 | FjAUBgNVBAgTDUlsZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQK 4 | Ewhwcm90b2JpeDETMBEGA1UECxMKbW9uaXRvcmluZzEiMCAGA1UEAxMZcm9ndWUt 5 | cHJvdG9iaXguZG9tYWluLnRsZDEiMCAGCSqGSIb3DQEJARYTcHJvdG9iaXhAZG9t 6 | YWluLnRsZDAeFw0xNjA4MTUxNDUyMDBaFw0xNzA4MTUxNDUyMDBaMAAwggIiMA0G 7 | CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvVcxZ1cyVmRGpnFtidsfGbXfVrfFL 8 | AWyH0AyxGYFASLLO6IKxp2SuE5wTDXZCIwPGQdcQz7Oi4p/iU76Zg9t3sxu9YrXd 9 | SiN7W+oUkMkz2NtMfiaxO39KXGcqGgobYnY8uFVwvlfqCCInlUH84Wxx7CLgU7Hu 10 | DZaI9mFdJLEX4PhDsVVVEVh7CbCkBllXLNa1DILVCeq4XtJzWTDtlnkWrCAEc1R6 11 | Zs2/GwT7HrADzJzRdCX2DsJmFvMv4ZMhcznrCi+qar1gYLkWG3NrF/Fw3f4JRFJD 12 | Hqv2Rno5fBzk/C6iWRRhjkTEoRD1g6zJoTt4A718vaftx439NnZ3CfXyGPPM1b72 13 | JsI8nBbZ2eIeMBvSz39BBsED3/HzKAqo+kX8rvpIJX00S4htQ3N27MxRAmzJpJpS 14 | UBDTr6wwQuGYiUzbnIy0l4+h5RrrFLED3/xp+bubNMN5JtYkH0jmuqNc+hpUVUEj 15 | 61l2GZVv1SJt8UziJLqfhofP8FfT6Q6GS8mgMslN2fJCgYTp7xaruxSwqsF17bRX 16 | MedAyN5BvJT9QSC9mmxl0/c5tX9VJ1AtCCikdzfaFapwiB98cI0SVE5kaDHdu5od 17 | YRD1fsok1i/3Pw8eVaWjdw31HTgUTL6ImV1vNbBa+bNiFq45+uC3+Xz7KojEXEIh 18 | iYTzifokYgDzUwIDAQABo28wbTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQCqZsl 19 | Q7lnj71Bqyo4EIIKX9Bc4TALBgNVHQ8EBAMCBeAwEQYJYIZIAYb4QgEBBAQDAgZA 20 | MB4GCWCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQENBQAD 21 | ggIBADxorUCx2QThNE339ZUmCRrULVjLxTDaDPqN5ASg6M1hXNt8mSa2/hI6wpEJ 22 | fzwf1+s8qYyxo6fsDqxoW+SulM3S6hwJUW+n7+SkeUozJqIm7QPc8SoIyr+Y9P49 23 | N6EqhJFKM8Hi4HmHWVI/OeHu1JJ5EZ0GLc6zk03YdFEnezvsKes1D1iyAZ+ycGl7 24 | KfqH+5lMgfE2U6/5DzMOGgu8Ldcz3yxrgiRH0t1T0b1TKoQ1x9ZgUsU2/Ub+Gbv5 25 | oSmEEGEf9RjsYZb2zLlEAril16tTN8chiaT6WYjiofy1vwWULN4PHNVV6ubfoC35 26 | VFJIZgOv7TVRkytFvPV/Th8HjcSWaW7KINGnod3N/mwvLKUrbd6YMrezx40Liaj8 27 | tVln5tY/iTzQzpwq1pT57VsRU3pzeed1v7j8go2iN9cQtX09thwWR1tWHY1V84z/ 28 | 8Dz56x9gOBB+yStyfhTc3Q+aYRM2XqL6Snpbg0+u56ACHnXIsvmXl0OR6djTXPU+ 29 | I6GXOXBG+81C14Fw/JrbZMeTFJpLI+4WjDa9dROyvOZIWNYmzoBuYckeFTvV1a2v 30 | HxRzzLNlMI3kU8JFWn+vjpGbtDywQzCW59VqEjGkC/ZjA87+Lpdxce+zQADcmeiP 31 | cdeqWcazdU6PityffJAuhiedv6ALrHEmDmDESWMyLMCRM3QQ 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-zabbix-server.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFkTCCA3mgAwIBAgIBCDANBgkqhkiG9w0BAQ0FADAAMCAXDTE2MDgxNTE0NDYw 3 | MFoYDzk5OTkxMjMxMjM1OTU5WjCBpDELMAkGA1UEBhMCRlIxFjAUBgNVBAgTDUls 4 | ZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQKEwhwcm90b2JpeDET 5 | MBEGA1UECxMKbW9uaXRvcmluZzEhMB8GA1UEAxMYemFiYml4LXNlcnZlci5kb21h 6 | aW4udGxkMSIwIAYJKoZIhvcNAQkBFhNwcm90b2JpeEBkb21haW4udGxkMIICIjAN 7 | BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxyd8AYBaNrgWJiI6zupB76jDiMFH 8 | iWy1dGz8niYzO+2MiCtBd5ddohJzzbICXzoH/h0EqrIPh/iv6mpXqYC5fkpNBt0d 9 | o1mIzh1UcbCxFiEYhVhghvdhuR4dFrkwvZs5ckdGYtYkPm2rLJkTs2yZztrnPKF7 10 | fYLaKbToZhca8ntliQ64CbJ6n6uQxCmQ2JntsMaiqbfkNATx45VD6HK9IFp+Lv1a 11 | JyL314b9ArtTuv4O0H6E+T8LHFXsfjwyCHo5EulmfLipCMuc+4GZeHOtuuKhhTZb 12 | kctGSMeAL/2Ku4GZhy+U89N6unXUmo7LI01MTChFN8vziqo2qd7r4wpQ+1VnIeTm 13 | CRV7ZRtuLCR7pZ9fQOKKw1/rqSnOICRlCaytud9QJh8rLF8IB+LD7roFLMM3ves4 14 | W+cGMGNFbYW0f7Sy1ghAe1WZDXNWI31GhM69SlFWxNVKQEqI1QnIucKAueKYUGaE 15 | VGwNFMtsk+KLqsjOTJeBmd9TbCQWKqNkJj6b+T6fGYz+hhthAaHZstzLMuuDaibs 16 | +Xpc/1xA7mbV8qMNdelG7tdBY7KAyrurdtDKLB3ZjvcxEG8WcU464YcUcj4968TB 17 | Qt8rYDxHxInC5wz0qclfmCn5SJcazvxhhyh3+fdHAgwlXiAOKmmtS9UdijR2jKcz 18 | H/uJtN4myMfRyfMCAwEAAaNvMG0wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUA0S6 19 | R+gF5lHrI4giq3bXzhrpJk4wCwYDVR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIG 20 | QDAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBDQUA 21 | A4ICAQCfvCcW6df+pPwzpPnYoBpqRwJHHaOffUieDbqkoaWZ9TpQvTnCCFCyir6i 22 | ChnZ7bmJ6GnymT3cGInuV3670LdHQiWQXzm9yboYZhOtBAIxdBpCrSrnudRbnB8T 23 | BkWnCnUatgfouoddaU2aCiQl7+Qtcfj5iCRLJZ7J3C2qVP6TWIh/WL/GhZ0csp5m 24 | E/o/jNg8VNi+kSX/meThh/ClXmaIDtBxbtofRmpdjPA84LoLy5jygHNRC8CRmtT2 25 | HddLHUhiaAVy/7f78D0uwChkR7q7aTKuZnGqOtXKvVeVWadMUhpUH1/tnnbaUOM/ 26 | CHpHc7aY6QFvyQk6EhR3frLjmUgrPdCF6q5gn5MnvLRQxexPGYVo5SUytCgIiqz7 27 | iKjlZGeKg2b9+lsgLOjBVD+aTVZ+Bu16aCHXRHKY/EgO1QTfZL/Ow9J74yTV9Zpf 28 | 75yHzNwjRzabx06Y1hawq0WQ+oPpTic+2Kk10kW6csG2BuSRA3KXl9n1UOE0rEdW 29 | x3jv9Lzfbx8lX80qx6eoRkrr/g7QHIWEST7tSlh/Np7p+glDYW4Uq9yzQQoI4T7R 30 | vvwUXf3UyGMbqZmEpqJK8wN50Fd5+HI3SxDtdcGl77S5Rlwy7VKkC63XsKE4k21m 31 | wdg2tSx4/fOCrCm2r0H+SfGg4zw5Oh3Bcw6vYeVKvxcR3TIOpQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.revoked.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFmzCCA4OgAwIBAgIBBTANBgkqhkiG9w0BAQ0FADAAMCAXDTE2MDgxNTE0MDIw 3 | MFoYDzk5OTkxMjMxMjM1OTU5WjCBrjELMAkGA1UEBhMCRlIxFjAUBgNVBAgTDUls 4 | ZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQKEwhwcm90b2JpeDET 5 | MBEGA1UECxMKbW9uaXRvcmluZzErMCkGA1UEAxMicmV2b2tlZC1wcm90b2JpeC1j 6 | bGllbnQuZG9tYWluLnRsZDEiMCAGCSqGSIb3DQEJARYTcHJvdG9iaXhAZG9tYWlu 7 | LnRsZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMMRyuHgYjWsCWvf 8 | sMl+N0Sl6H9jNI2+Zp7br3g+/GZ4fnZhgI7WNLulh1MHzAVHGUaopTTt6e5kDnfV 9 | NxkOjFllp84Iv5+qT62DJDuDxTU+ShBzMyBqw/6K98DOc+esvuj9Bt2NBsNmHyl0 10 | VQHdHLql/jXKjUGPOvUZMa0q6DCZXCxAhs4drWnIO78TATaDoo30vHMtcGKodjwF 11 | Rd1e9/+RaaZx6xwntSsztGIexHEHEbHxksYDTmDuv8m+A8PD+/8B0NUBfSgGQIrQ 12 | v4VBrvsAuetAJJy1mkI2noFFSqYjNRN9jnngV170mcBabfMXKTETdW9j23SCE64p 13 | 6Z7aIAmdOFdVxfJxe4eLz+EqiL2F0/ljyjMp+22HzcSl4e4Ti4DjsoHhaE+hq2ZY 14 | rJekpPk0BejKjBVHmHu+y35ImzwWO9G1FXvo4sJnLt+IauNKlpPTyglFzl8ndcMF 15 | X1apXZiPpWFeuwVoIdzLawVrp0Fgwjkwr9HFdb92BeSpNB4g3Tg4ovEz8u3ZkILx 16 | IzsLOvAvdrBgnUQvQzXQtsDLasfhYkFZqd/BwjKk9Sf9YJRwf7gXPzNNRZcWrtkU 17 | yyil4BrkYEIb2yujXKslkJsWc/6TTLd7As/XHXOG2ylxUBEtfspnKRXk7rum1NJq 18 | oeh1ZDBiOYHPfTFiqCBXIPQ0LF49AgMBAAGjbzBtMAwGA1UdEwEB/wQCMAAwHQYD 19 | VR0OBBYEFFxnk5tddvAM0xlLUb5BTa1QrclfMAsGA1UdDwQEAwIEsDARBglghkgB 20 | hvhCAQEEBAMCBaAwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkq 21 | hkiG9w0BAQ0FAAOCAgEAvGmll3rPPkMPr+MOSYGWino+41PS2o/JkZIaBo6xESBq 22 | fBkflPydXyUqevK2Wae7mToGvrdHEI/BgDKZaWto7KUXgF3d7JtsMGD8x/BJ9r7b 23 | DKdWJ5kBIfk+6gJGCCXMN6wbkgvNaa95k2NO38/6DIHQKQwFX0sg9qqVgr2w3o94 24 | SpDodFwzsxDaTwNJMahxMvSwI1rAhtrrZ9O2PLatwqt+aS7B69xszHE+m/wc5kXR 25 | RhZ/wZLxdyBcOh1XVN3nhSSj9IcDjbqUqkcV8ScBtCtKj4UAxFfYb3Ht2ufps2Tp 26 | wIUdgFCPMo+ODClHlqQcm6eMss7LMxfHsQaJNCjEXLKst/aqp3duFC9+dthf6d+n 27 | LaIWQ+sIe20V+HNKKS3/7AwdnZ3ZIpov9nUVPLjA9GN2xkiUzL1zau8zva/+eC0C 28 | s5YgVKf1eSs3Cz/e29VDxiU/FHD2slPcn4pMlXCQhPnsNDIUwr4lIauFenuqmj82 29 | vvdWn+qxgQnpYvSuM4cR3lqshSFbypj0CT1sbOFH5omDmnXNnQnSm2dJLGgQXVKw 30 | +4jgTAO8goV8iRIIqjtoWg1Scl7otTAj5z5ePdnwgsLD55p3Jg2YazyB3K9hnhxJ 31 | R5uPGoh18/vf8LAsn9FCaoRl2+0m7qsf2k3P6Cd6dYfgMezzQQbOl3VcGWl7Jq4= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.revoked.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.not-yet-valid.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFoTCCA4mgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAAMCAXDTI2MDgxNTE0MDcw 3 | MFoYDzk5OTkxMjMxMjM1OTU5WjCBtDELMAkGA1UEBhMCRlIxFjAUBgNVBAgTDUls 4 | ZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQKEwhwcm90b2JpeDET 5 | MBEGA1UECxMKbW9uaXRvcmluZzExMC8GA1UEAxMobm90LXlldC12YWxpZC1wcm90 6 | b2JpeC1jbGllbnQuZG9tYWluLnRsZDEiMCAGCSqGSIb3DQEJARYTcHJvdG9iaXhA 7 | ZG9tYWluLnRsZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJzeNPZs 8 | 6ZIKGL+uqLPLtUz4KuBGdxKO0//0PP4pyAOisXGJfHBYYekCdcr5w6laY7P7PE9N 9 | WUKot4L8smphIR1w/BKdRvlEANZYSnj+v93wMezzKskZvwzfzy7j8wBIwQq2p/4X 10 | Gu2/1l9QsE68k1agrtGDHA9svhAaEQs1uVLpvksm3Mnt5JM8ox/eZx8s/MP5TTvi 11 | nx9nvzCHImix6ssACgoBFrOpW9AmwOSNmiSiASzpxEmMEOJSLNeQqvHtrJA1xRUi 12 | G1zfqdk5VnC743iPi+hbNeJgwOVwgIr/frHsqj2YpcbzKC7lbT+tzl69btBfhrzg 13 | 0I9PRYQERvCYXIy6V80DNVfa9ddk8hU0EJHrUALdeTvhvE0uxha39G8lh0v7WsjF 14 | HUIXKJ+z15poAGmlOEivO3oWfIo3zdNt4gdM8SRiUjqv7U1lsF9v15V5jfhW2wxz 15 | J3OFmUTjNrqorNFLbK+eoIbeTkLndWpkECAWXY7VjVuS62aMqAdE13g38JPAy375 16 | 8krGAJMbsH7bnDDuuyGNyyYcQvma1aTyL84Hfb1Fqx4dHPfgCQLcoto99sOhxZd3 17 | PKGXWR+juyjsCEIGCTdBFYUK5oJargZEZj0Eay11AXOpkY7WkkHAjSn8EG+/FVXT 18 | pRJJyEzPp8+XISi4VBqwcuXEcyXiQzkkl51/AgMBAAGjbzBtMAwGA1UdEwEB/wQC 19 | MAAwHQYDVR0OBBYEFJmUxouCg17QRn+IRqPPF4iQeRUMMAsGA1UdDwQEAwIEsDAR 20 | BglghkgBhvhCAQEEBAMCBaAwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0 21 | ZTANBgkqhkiG9w0BAQ0FAAOCAgEADbRtEhneKdAfp81m3EEHGDNVUD3z8Cgh0rwY 22 | KwNJWsJOyZbK5IwRaRCYxJjfxF3dwUvcpabsI8bbVw+sZzTmACLXxY1Tyhx0wKgS 23 | Afpxo2YGgNPYwG0E5+RP09Mo5yRJq4ed81rkdjSf4xgBWYYWcPTLV72VYld3Rc3Q 24 | d+exWRDl03F6A96KaPZJvx7NXG7bjynSVLqWCH1846uLHSzs1VicwegKgqWq9Nwt 25 | qV4Poqdq5XujQpbDu1J1Bvy3TN9NploM+TP8sFJmZWThamyXnrw8Qs6H441tAX71 26 | sjaUDxXdeg9Gx5ZMupCKFAkKs0YfvpAebIyYEqid2q4Qqj0lMliKWi/L1DbioVRI 27 | 9OdH6txJ8jsUv0ucTOh6vNjvsUvyfW7TK2/u0GpFagrcLlodfy6kI4s6KUxLjLlc 28 | S05/WJ93Ya6PV0XotJEr8avWJOyOgARcbPq+t4MOKPZyIXdp6pVVi97yJB6SD771 29 | HxiREDSn7E3gxMVQueL0DU8R93l++8YGvh2ZU9EkUl6s1ZMNT+NiA19kOsVUkRmQ 30 | 6/kcHkecsYhjLhPZnM9s0hMpI4QAwFLgkurOYKkuAd7HTVyBLUr3VFJrU78lKc5E 31 | eJYqOILu1nrMH9OAaBKiU0Y/MRwmHXuPXb+3DH8slUHbgOOAl+HQasX5JVhqIGDw 32 | 7KwXAGM= 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.not-yet-valid.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | 7KwXAGM= 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-ca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGOzCCBCOgAwIBAgIBATANBgkqhkiG9w0BAQ0FADCBpTELMAkGA1UEBhMCRlIx 3 | FjAUBgNVBAgTDUlsZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQK 4 | Ewhwcm90b2JpeDETMBEGA1UECxMKbW9uaXRvcmluZzEiMCAGA1UEAxMZcm9ndWUt 5 | cHJvdG9iaXguZG9tYWluLnRsZDEiMCAGCSqGSIb3DQEJARYTcHJvdG9iaXhAZG9t 6 | YWluLnRsZDAgFw0xNjA4MTUxMzQ1MDBaGA85OTk5MTIzMTIzNTk1OVowgaUxCzAJ 7 | BgNVBAYTAkZSMRYwFAYDVQQIEw1JbGUgZGUgRnJhbmNlMQ4wDAYDVQQHEwVQYXJp 8 | czERMA8GA1UEChMIcHJvdG9iaXgxEzARBgNVBAsTCm1vbml0b3JpbmcxIjAgBgNV 9 | BAMTGXJvZ3VlLXByb3RvYml4LmRvbWFpbi50bGQxIjAgBgkqhkiG9w0BCQEWE3By 10 | b3RvYml4QGRvbWFpbi50bGQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 11 | AQDEpZlXhgiSDb+aKoQuaEmfmdFRTfAScpIuZfuoXdO7S38aJNrQGDcsp1fqVwYw 12 | cZAZjfHT/gp8Sl+5TWymCnvkgsLxDexd3KXFaPnDgGcZ/erKtPZPG2MsJBiNf6oC 13 | 6hwtd/VnXnt+NdcUY4rkjE0Jz1Z6VOYVFxg0Uam4naThE1RqLjlqLKV9MtwcpA5P 14 | QlxMvpVlu8nxJHhBqOyJh1lQRzznW2d5BEiVJtZKMWfJ+zOqA99WhUp363J1TZ8Y 15 | RpoqYpiqnfLVYKbwJ44QveBL1KGDVlecvWHHmdnmpoRwqZIumlJJmjFtvxvVWr2m 16 | OoxnODnDuIHTbqx/h3Jb6egDyVYN/4qEV2FmiBf94cq00krba5ZVP92vS2ByuYOh 17 | yXA0wvWBp8y4QIWzkVkRu0W3cjNeSY2L7cSJFNMtP+CAS4i8istM0e4mfeye45c0 18 | T+tK8st9Rs3yK0blVlr63sMlukjjV+6d8TK+rIQfxx3UN0L6L/hEkv/gJW/apAI7 19 | vU5YpG2m7M2q9fqCTivVeLrrEMc+x5xmJMkgDo63mss1J77A0v/tydaOxcB49M+m 20 | ku50zagWnwpXIWXzb6LPJToLgTE4xBCyh3LQ7RG64TSvnDkZP11UAvVa6dim5JeV 21 | KihuIQjKF9SidsTgQrQf32Hg2majZZsch8Kbo4vXATt7ewIDAQABo3IwcDAPBgNV 22 | HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQcrZ3C9dkmLsSBFK09gY6cz7DK/jALBgNV 23 | HQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMB4GCWCGSAGG+EIBDQQRFg94Y2Eg 24 | Y2VydGlmaWNhdGUwDQYJKoZIhvcNAQENBQADggIBAA1iJwTCc4a/yUAChqGDIVxl 25 | 9jMxP2LnJEohjWFUxvg6608i1jOMT7ujJftdAY/J0c/83jEHMPs5U96LK8GRZWjS 26 | 2Jqakbrr+4G9v3hMdUKYHdnfDOee7dlfb+NnUM//i8Zn9X72AKF8PJY0ZGdU+Oyl 27 | vkxF52yfvvf/CDXxU0tSbI8PWtygeqFMSE5LWNeEU8Zb8AcPfHAIqYhrny3kn+F7 28 | 3+4ZI72gWzKpmCyoySBeH9QItigS0OtYK/lGADv02mwVw5up0SMfPSuP5quukO3+ 29 | QnpVKATtOS/oGFYeyZAkFYAdEqcb7AyhZMgE0Y0dWstlHXl14nbI01qQSXUCIKzt 30 | r6BxFoFQncq7zYCinVqj2DBzck59mLQr091nbp5fFSMGpS+avYH4Dgds2YA/lf0k 31 | zFsn/lMJHk40ACMH8taRtDH9y6r1/r7FXM9vkm55b0QtstQNBrIueXJcwtciiCfh 32 | Hoip42S6e1WRYonTEsOtrcLyyUip5d5P3PiHSExpZOY8XZb30ahop5a+D9RtCxBj 33 | PpZt8B7Bij3GD4/wnBZdYS9DZCGBju5NXs0cIJrYBPe9lV3jCgs4Rl7mdhJhHjfF 34 | mzFyhzHsM+c+urT++ADtFZdTSYxfVlvajFr+74aY3YCk4hTJAU87BYMZ31FZW1yG 35 | cnDtHkC0XIFB+wfQAFib 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGPzCCBCegAwIBAgIBAzANBgkqhkiG9w0BAQ0FADCBpTELMAkGA1UEBhMCRlIx 3 | FjAUBgNVBAgTDUlsZSBkZSBGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMREwDwYDVQQK 4 | Ewhwcm90b2JpeDETMBEGA1UECxMKbW9uaXRvcmluZzEiMCAGA1UEAxMZcm9ndWUt 5 | cHJvdG9iaXguZG9tYWluLnRsZDEiMCAGCSqGSIb3DQEJARYTcHJvdG9iaXhAZG9t 6 | YWluLnRsZDAgFw0xNjA4MTUxNDAwMDBaGA85OTk5MTIzMTIzNTk1OVowgawxCzAJ 7 | BgNVBAYTAkZSMRYwFAYDVQQIEw1JbGUgZGUgRnJhbmNlMQ4wDAYDVQQHEwVQYXJp 8 | czERMA8GA1UEChMIcHJvdG9iaXgxEzARBgNVBAsTCm1vbml0b3JpbmcxKTAnBgNV 9 | BAMTIHJvZ3VlLXByb3RvYml4LWNsaWVudC5kb21haW4udGxkMSIwIAYJKoZIhvcN 10 | AQkBFhNwcm90b2JpeEBkb21haW4udGxkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A 11 | MIICCgKCAgEAvNSI6aQA+RJ6iT0ktw3cbsaA5GZmuiDP2psuycB56K7Lbeu0saic 12 | pnnvnA1l4zQMUs+6G5UFzsEIyyAR61LDgAeWGOXhNs8Vu14hd1fpLLGA2Z5OmNAw 13 | IKVVYoSAyWzVGunfaS7jRdhfVqWg7J2JcyLdKtSfMYY9gxxI0+rZ9shsNMhE3dzj 14 | qjXaMri6se4V4YBxEvfTn7GQe6y6ujOaXzIcmE9cXYstfZkB2VyZjX77OcxOjwKL 15 | XGYfhYpFwZSnhfnM8UihgyVJlOraguKNO9VYFPdH30A7iFL3XBQ8EsKOpE+tpm9j 16 | ohQHdSmrCpS6Q+uEt+0Dn/Jld/ilD6MGb6M9OT0sOA5sueNM2Bdi49yPpv2AxLUV 17 | q0G+BlE9Ele6GzSYxjmKO1+yitbO6LQC8ZzhUBSROdG1SzM003lO1WXof+kuVhwT 18 | O3kqG/hkhfls9UnMTuN5nKBb0gxNDu+/tKz469AIkjMNDeTsXiNQXsjpTRD1RK1C 19 | /rj2VhFUF64en047AMAylERSlxQNgpMWtX8EUW2NY7g8SKVjLFdhKTSvgcRaQ8Ln 20 | f/bwQJn+1a198e9iHMwBppiHtLivFtidZUpKg8HC+9hml7Y0dfMDmuyGx4okOdsA 21 | ewgHGO7cJi62i5781LsjVxT9JKJVwZLPX6OagHomWRx43yAjLpCcV2ECAwEAAaNv 22 | MG0wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUBeBFsxcM1+wZTCzrJeij+p1Cu6cw 23 | CwYDVR0PBAQDAgSwMBEGCWCGSAGG+EIBAQQEAwIFoDAeBglghkgBhvhCAQ0EERYP 24 | eGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBDQUAA4ICAQDDLk2klXywAOUtYETZ 25 | cg7V0WfwVXj1x+/3iXFOFVfkR/tdI2d8Ee1Bh8QHMBZKgUnDMh83I5FLQHDS1Gav 26 | DDx0TjKY/wc0niM0LX0j2nsJZhAhqMGmHGJT7mkLP2FXkFt/6+orLDUMrcMXYrJO 27 | +7a93v/62LJH5ehHgcDDjpnpavkq6f1nalzvgl79D1zm6RdFiFBZggllvjDGzQRz 28 | ruaBB7o+oGYAeD2J/vYr2XH5YeUDHaD063pjTcZGME5ee++GJGIdgqBxiEgjfw7S 29 | 1EjiBDidoE75L6FrSlSVlo6s9Oh6SCtvFFMk740/R+PbLDLxpa1iIzed0JlI3/TW 30 | lT+YNv/3/uO/8wn3LJQyST9xriHYsokrjcN4jKj/IUYwQbi8jiPoHbp/ByqpC5IJ 31 | tQtR9eWFEZyaKkIOODgMWnt3mkUhHTDd7/HXd+diR6ppYeirQ6JKxFH8h9ieIzQj 32 | XdTaBWDp5SzINOfzuGRnAKCl4i4tu+8W8LFcSarFC/tfk2O8HJvNT3H2HmTQv8Jk 33 | wTmSGN1Xkde78XOlUQ6cqNUz+1B3SXYeKDODi+zQ5q5d67yMvY7SO5s8hiMpKi/l 34 | tEWgtsUO5+hm5/qdiOGo3EIhgbQ82QSwc+aHFsQ0CFuUrKDCqQVQqL5GJUS3YSk3 35 | AqeEq3Ob0843eCR9FlrATdTWug== 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDxQJYWkBPpOUXO 3 | dHc/xPhCKPZBF1mYzoFvqzJYpOr/xEqSmZAxM+WeqC77RbpkcI2SEw7AIFALJD2q 4 | LBqp68AkFQHxvWA1xGKF9IUhNdN3Q7pzxWuxTvMd6S+/oUmsj94nvChrNozQaIRA 5 | SLCt0tRJUbBHZm7dyJTf6DpkKtxA62mq4WY/TXbbAQDsTUJewlFTvRtxW+vW1acg 6 | vlO8rcz7mLJx6cpMYHrjc6GqK3WcskTo3sBBLrLd0U+cH6QwVNA4JxQqjAtNToQH 7 | LEEvZg+8svWCrmf1S47CpzW6xKMT2vOUsRzPhFSStNK5blxG92kMyOsUNdG3rGT5 8 | 3CG7v/fthaTHEB1whbTcDspwQRpT+hBFy7RkT0LIPMx9WupbFvh86vz3TPF5di/V 9 | EgLt76fAuuaUzvfE/Duu7irFYwQgF1s37AsuDyxekBka7LArbYHso+isOcl2MDAN 10 | 6sgr1N3+IqQI0QyAtoh28RYxx5AMwF9kVxPMiG0MFivAgzAhuSF5J6aFWrgiCZW6 11 | OQekmkNxY8f+nO8JSOFgp90Bfwk1HuXrQv+QTquletwrs0bsNBRQLYC/iNoN3EhY 12 | 5Fx2mdGRov3RlOlb7obiPPpI80thc8r47CC6JErtAuVFLgSpZp0PZnNtZCMIthc3 13 | yEIr+NbTzitiNkoKo/ZWQNlsmixI6QIDAQABAoICAQC1ALIax4pIxxGarkLx80QX 14 | z0fC2lP8k6MFNzqUy1cNAia5CsHmSHuUp7ZoC46m4NM2r1m3yAaF9XDWhjSTHC+S 15 | YriMuHrAnFEXE7f2jL3Vk1kGly4PX56D6HpMmiP+dgpFYaQpnEnV6zSeTmtQXweq 16 | 4sERMMcpWt5nh4KXuJh7lKQ48teV0vbDpWMd53FOSxhdbVpzmHW/P5kete15eCR8 17 | 97maQb/nwdMxZ4X5eJXLNO0Ckm1H+lN0nR/PkOXM5TU7jAZTTbMFE013XDqj5z0T 18 | ZGlS3KtenIvFe1KSiAmaUgHCo4dsImqZj1UyjpxpGiMU1oGZLi/kUFGKLSCaDpNh 19 | iprbCp2Dt5Gd2t8q/wjAMh6FCIT/SY6p1uORdzFeFzt1ylqGt9gYum4b1CoHvoVS 20 | 0R4FlMcXBhG5fKErt27FjkQc5T9efI8sWcvi2BVI9WwItOIwvoEnAC4DbsxPiDfH 21 | ESPIlcc1OZJql/P7kkcCYjzwlCdjQLRneT1dnwNAnEyDJ12ZsaPlAJ5ca2WBxLcz 22 | qhEshswPqZE70xlvjuSg3Gd8ggHQUZ1FkBwx2oNpy7GdJpAu2aNh492812r1KuBY 23 | dY/crdnshIeumq7OVTqEHsu9YnCjn1a71wNEOjauc4f1fedzUw9KeFc3WqhXH17s 24 | cNUXR/ltAuUbRCa9gjPP6QKCAQEA+/1txN3oqbglC17yxbedaTTiNu09gzKjMIEb 25 | 6irjhOeFfWuEBIv+e50tzRBZrLid5J900t1OV5aM7HucdcHHtJXx0J1gNanHYOWs 26 | TSLvcrZAXmFdkeJaKJLv1b8Z4dgmx1if/0agtkNrs2Zmf0M9+psfBxqNxBLLyOf1 27 | mTTg0YkcRcY5sAXWT5oaY+Jor9HeBxIL9eErMmBsjMg/j5b2uZ7BY7zg0jriDjfR 28 | OpqgnY563ajhJYc6SAW8CUME3cYGmEg6imqngZyAQD68rsSTDSA/LEClnu4KSek9 29 | 59nmq6MQic5EW6oD7BVHpeLadzMCLLirH7L6AxfoqOd3f+tUjwKCAQEA9Rdp7Q+e 30 | kxRwOWe7V/uz6pyv7Dw+vml9ee85m3evQWEhNzt0lR0zqI6PTtSB3pceo2rGYMV2 31 | 4Gky4kvkcDVq8lBCMftWRND79HX03aySUcIyUmeSIKaYEjVwUZO8glP+URXmM++d 32 | as4zfsDs+iCyBsxoyzBnuGPUf9iZJiRy4Nd/sXEqAYgJf4H0hYd2fKfobbXnMtVQ 33 | HE826bUKCD+rdwJfGvH+ncjZmLiLSybfrymk1CcFFUSAN75y+Cb9BIq6q7Nm7Lix 34 | KfMPqUwoBeDhfctpHIdcwUl1o4yQEgkaVSWpZ4GNZmIPkXz9AVV9Yz6bXtw/tbHf 35 | d7d2XXIZiun3BwKCAQEAr48Z2c1s2kmD7Y8h/qP1FCYW8IOKloxB63oX06Y7yw1u 36 | EDpGyNAr5T1VeofIojAhOPXq8znh6d3mop9gGx59nw/UYC40qE53rMd2qmsLfdUB 37 | tX+KLCgR/jCYzUcNpi3snnfdSIGRWEpSj7No94MGfEF0dYOHfzJFLdyFXE7dzr4C 38 | p436BOucKutHNY24t720PSLSmGRerwNEvTSKK+TWUe4L+AvQakdB1PwIVhcCjaKF 39 | cUbGTVoQPbtZDO7XRhc/4vp3ZpX1y7QYGipbVDt54+wydwc3HCnlmybXzV8feTbr 40 | P8coEuC5SNJuj2EkKWWtPzENb9FGo78Vhg91TvbKewKCAQEAiXYxVeFdyhY7fybb 41 | 31Pvq9VnofKEKl2WH4552+V7qQqmC4lQMNXpBE+4trjfgg12BKe9TcdSjjjSbjOs 42 | kvaS3gb/qXLTBtPDjG+f/7hrdGmbubYXMjLdtdC9BzP6FYqwZ6AFtflda+rs3Nmt 43 | z/gIgWGiINwsQDHVnELKWqc0u0CCgO38ZlF7KkWj9ERuwymVZfsRCeS0Ary3Cssc 44 | LlYvgBcXalBxwuNEj7Bph6Ps7xxHMyoTYsNBuoIZj26mmCaK3gRH5NsNmn6VuRla 45 | lTl0nw44DOUqs8nUrf8HSuZKG5l88u2pddPn8WyNpnLhWYlisQiMvwZdVJLUU0LM 46 | aqogfwKCAQA7+FUz+7120zI+czUc4msJsupnisjLfPSiYa5QQdPxKmCb1OOjZZBA 47 | Jv9RQmqcDGE5FOzgzlnoCeOBMUffBTPD9v7k7CVb/eLcPcMRT+du2qBhMS5BryIC 48 | jh5jSV5myFIyTMedc8Ny/FbhvXN068YO0O0z3cqc221r2p+ohRTTVs8+s7lfQGy7 49 | hva9pvPcKZDEB9E05R9R/ufHUSEQKyXJ/WjAXj3s4QzCSKeA56VN/KJj7XQYIbbg 50 | zMtloBORmlM0SyPzhbmOXBXDaYkNUsUHYvb0yIP6pa0e8tCXQObUMq8zAa+YsgGI 51 | 528/TmS/nAabaRR7CmTWbWPZCAm+WceQ 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-zabbix-server.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | apUB6koN/AfEs4VPX5zZYN5TMGbw 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.not-yet-valid.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | unr0Ue8OU29Fsqx79EruoLDkBhH5coU= 52 | -----END PRIVATE KEY----- -------------------------------------------------------------------------------- /tests/tls_ca/protobix-client.revoked.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | qc2oYarze7enr9buPV97fDXFoNbJDw== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | xrKD1f6RIzCF5aaIBhxni7licwVzYb4= 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-zabbix-server.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | qOBu23PguNn0BA0m117q50/6kenW+lCRqw== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.revoked.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | L4rb44/zvk7onAdLlZq314JgOsWLWBo= 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/tls_ca/rogue-protobix-client.not-yet-valid.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | v5vxFGOZecOoetur6gMjwywglStAcT4x 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/zabbix/zabbix_server_mysql.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.6.30, for debian-linux-gnu (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: zabbix 4 | -- ------------------------------------------------------ 5 | -- Server version 5.5.5-10.1.16-MariaDB-1~jessie 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Dumping data for table `hosts` 20 | -- 21 | -- WHERE: hostid in (10105,10106) 22 | 23 | LOCK TABLES `hosts` WRITE; 24 | /*!40000 ALTER TABLE `hosts` DISABLE KEYS */; 25 | INSERT INTO `hosts` VALUES (10105,NULL,'protobix.host1',0,0,'',0,0,0,-1,2,'','',0,0,0,0,NULL,0,0,0,0,0,'','',0,0,0,'','protobix.host1',0,NULL,'',1,1,'','','',''),(10106,NULL,'protobix.host2',0,0,'',0,0,0,-1,2,'','',0,0,0,0,NULL,0,0,0,0,0,'','',0,0,0,'','protobix.host2',0,NULL,'',1,7,'','','protobix','70726f746f62697870726f746f62697870726f746f62697870726f746f626978'); 26 | /*!40000 ALTER TABLE `hosts` ENABLE KEYS */; 27 | UNLOCK TABLES; 28 | 29 | -- 30 | -- Dumping data for table `items` 31 | -- 32 | -- WHERE: hostid in (10105,10106) 33 | 34 | LOCK TABLES `items` WRITE; 35 | /*!40000 ALTER TABLE `items` DISABLE KEYS */; 36 | INSERT INTO `items` VALUES (23663,2,'','',10105,'my.protobix.item.int','my.protobix.item.int',0,1,1,0,3,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23664,2,'','',10105,'my.protobix.item.string','my.protobix.item.string',0,1,0,0,4,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23667,2,'','',10105,'my.protobix.lld_item1','my.protobix.lld_item1',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'30',0,0,0,'',0),(23670,2,'','',10105,'my.protobix.lld_item2','my.protobix.lld_item2',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'1',0,0,0,'',0),(23665,2,'','',10106,'my.protobix.item.int','my.protobix.item.int',0,1,1,0,3,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23666,2,'','',10106,'my.protobix.item.string','my.protobix.item.string',0,1,0,0,4,'','',0,0,'',0,'','','1','',0,'',NULL,NULL,'','','',0,0,'','','','',0,0,NULL,'','',0,'30',0,0,0,'',0),(23669,2,'','',10106,'my.protobix.lld_item1','my.protobix.lld_item1',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'1',0,0,0,'',0),(23668,2,'','',10106,'my.protobix.lld_item2','my.protobix.lld_item2',0,90,0,0,4,'','',0,0,'',0,'','','','',0,'',NULL,NULL,'','','',0,0,'','','','',0,1,NULL,'','',0,'30',0,0,0,'',0); 37 | /*!40000 ALTER TABLE `items` ENABLE KEYS */; 38 | UNLOCK TABLES; 39 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 40 | 41 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 42 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 43 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 44 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 45 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 46 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 47 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 48 | 49 | -- Dump completed on 2016-08-14 9:57:36 50 | -------------------------------------------------------------------------------- /tests/test_memory_leak.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test long running process & detect memory leak 3 | """ 4 | import configobj 5 | import pytest 6 | import mock 7 | import unittest 8 | 9 | import resource 10 | import sys 11 | import os 12 | 13 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 14 | import protobix 15 | 16 | PAYLOAD = { 17 | "items": { 18 | "protobix.host1": { 19 | "my.protobix.item.int": 0, 20 | "my.protobix.item.string": 1 21 | }, 22 | "protobix.host2": { 23 | "my.protobix.item.int": 0, 24 | "my.protobix.item.string": 1 25 | }, 26 | "protobix.host3": { 27 | "my.protobix.item.int": 0, 28 | "my.protobix.item.string": 1 29 | }, 30 | "protobix.host4": { 31 | "my.protobix.item.int": 0, 32 | "my.protobix.item.string": 1 33 | }, 34 | "protobix.host5": { 35 | "my.protobix.item.int": 0, 36 | "my.protobix.item.string": 1 37 | }, 38 | "protobix.host6": { 39 | "my.protobix.item.int": 0, 40 | "my.protobix.item.string": 1 41 | }, 42 | "protobix.host7": { 43 | "my.protobix.item.int": 0, 44 | "my.protobix.item.string": 1 45 | }, 46 | "protobix.host8": { 47 | "my.protobix.item.int": 0, 48 | "my.protobix.item.string": 1 49 | } 50 | }, 51 | "lld": { 52 | 'protobix.host1': { 53 | 'my.protobix.lld_item1': [ 54 | { '{#PBX_LLD_KEY11}': 0, 55 | '{#PBX_LLD_KEY12}': 'lld string' }, 56 | { '{#PBX_LLD_KEY11}': 1, 57 | '{#PBX_LLD_KEY12}': 'another lld string' } 58 | ], 59 | 'my.protobix.lld_item2': [ 60 | { '{#PBX_LLD_KEY21}': 10, 61 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 62 | { '{#PBX_LLD_KEY21}': 2, 63 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 64 | ] 65 | 66 | }, 67 | 'protobix.host2': { 68 | 'my.protobix.lld_item1': [ 69 | { '{#PBX_LLD_KEY11}': 0, 70 | '{#PBX_LLD_KEY12}': 'lld string' }, 71 | { '{#PBX_LLD_KEY11}': 1, 72 | '{#PBX_LLD_KEY12}': 'another lld string' } 73 | ], 74 | 'my.protobix.lld_item2': [ 75 | { '{#PBX_LLD_KEY21}': 10, 76 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 77 | { '{#PBX_LLD_KEY21}': 2, 78 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 79 | ] 80 | } 81 | } 82 | } 83 | 84 | def long_run(data_type, debug_level): 85 | """ 86 | Generic long running process simulator 87 | Used by tests below 88 | """ 89 | zbx_container = protobix.DataContainer() 90 | zbx_container.debug_level = debug_level 91 | run=1 92 | max_run=1000 93 | while run <= max_run: 94 | zbx_container.data_type = data_type 95 | zbx_container.add(PAYLOAD[data_type]) 96 | try: 97 | zbx_container.send() 98 | except: 99 | pass 100 | if run % (max_run/10) == 0 or run <=1: 101 | usage=resource.getrusage(resource.RUSAGE_SELF) 102 | display_memory = usage[2]*resource.getpagesize()/1000000.0 103 | if run == 1: 104 | initial_memory = usage[2] 105 | display_initial_memory = usage[2]*resource.getpagesize()/1000000.0 106 | final_memory = usage[2] 107 | print ('Run %i: ru_maxrss=%f mb - initial=%f mb' % ( 108 | run, (display_memory), display_initial_memory 109 | )) 110 | run += 1 111 | return initial_memory, final_memory 112 | 113 | memory_leak_matrix = ( 114 | ('items', 2), 115 | ('items', 4), 116 | ('lld', 2), 117 | ('lld', 4) 118 | ) 119 | 120 | @pytest.mark.parametrize(('data_type','debug_level'), memory_leak_matrix) 121 | def test_long_run_for_memory_leak(data_type, debug_level): 122 | """ 123 | Simulate long running process with and without debug 124 | and control memory usage 125 | """ 126 | initial_memory, final_memory = long_run(data_type, debug_level) 127 | assert initial_memory == final_memory 128 | -------------------------------------------------------------------------------- /protobix/datacontainer.py: -------------------------------------------------------------------------------- 1 | import logging 2 | try: import simplejson as json 3 | except ImportError: import json # pragma: no cover 4 | 5 | from .zabbixagentconfig import ZabbixAgentConfig 6 | from .senderprotocol import SenderProtocol 7 | 8 | # For both 2.0 & >2.2 Zabbix version 9 | # ? 1.8: Processed 0 Failed 1 Total 1 Seconds spent 0.000057 10 | # 2.0: Processed 0 Failed 1 Total 1 Seconds spent 0.000057 11 | # 2.2: processed: 50; failed: 1000; total: 1050; seconds spent: 0.09957 12 | # 2.4: processed: 50; failed: 1000; total: 1050; seconds spent: 0.09957 13 | ZBX_DBG_SEND_RESULT = "Send result [%s-%s-%s] for key [%s] item [%s]. Server's response is %s" 14 | ZBX_TRAPPER_MAX_VALUE = 250 15 | 16 | class DataContainer(SenderProtocol): 17 | 18 | _items_list = [] 19 | _result = [] 20 | _logger = None 21 | _config = None 22 | socket = None 23 | 24 | def __init__(self, 25 | config=None, 26 | logger=None): 27 | 28 | # Loads config from zabbix_agentd file 29 | # If no file, it uses the default _config as configuration 30 | self._config = config 31 | if config is None: 32 | self._config = ZabbixAgentConfig() 33 | if logger: 34 | self.logger = logger 35 | self._items_list = [] 36 | 37 | def add_item(self, host, key, value, clock=None, state=0): 38 | """ 39 | Add a single item into DataContainer 40 | 41 | :host: hostname to which item will be linked to 42 | :key: item key as defined in Zabbix 43 | :value: item value 44 | :clock: timestemp as integer. If not provided self.clock()) will be used 45 | """ 46 | if clock is None: 47 | clock = self.clock 48 | if self._config.data_type == "items": 49 | item = {"host": host, "key": key, 50 | "value": value, "clock": clock, "state": state} 51 | elif self._config.data_type == "lld": 52 | item = {"host": host, "key": key, "clock": clock, "state": state, 53 | "value": json.dumps({"data": value})} 54 | else: 55 | if self.logger: # pragma: no cover 56 | self.logger.error("Setup data_type before adding data") 57 | raise ValueError('Setup data_type before adding data') 58 | self._items_list.append(item) 59 | 60 | def add(self, data): 61 | """ 62 | Add a list of item into the container 63 | 64 | :data: dict of items & value per hostname 65 | """ 66 | for host in data: 67 | for key in data[host]: 68 | if not data[host][key] == []: 69 | self.add_item(host, key, data[host][key]) 70 | 71 | def send(self): 72 | """ 73 | Entrypoint to send data to Zabbix 74 | If debug is enabled, items are sent one by one 75 | If debug isn't enable, we send items in bulk 76 | Returns a list of results (1 if no debug, as many as items in other case) 77 | """ 78 | if self.logger: # pragma: no cover 79 | self.logger.info("Starting to send %d items" % len(self._items_list)) 80 | try: 81 | # Zabbix trapper send a maximum of 250 items in bulk 82 | # We have to respect that, in case of enforcement on zabbix server side 83 | # Special case if debug is enabled: we need to send items one by one 84 | max_value = ZBX_TRAPPER_MAX_VALUE 85 | if self.debug_level >= 4: 86 | max_value = 1 87 | if self.logger: # pragma: no cover 88 | self.logger.debug("Bulk limit is %d items" % max_value) 89 | else: 90 | if self.logger: # pragma: no cover 91 | self.logger.info("Bulk limit is %d items" % max_value) 92 | # Initialize offsets & counters 93 | max_offset = len(self._items_list) 94 | run = 0 95 | start_offset = 0 96 | stop_offset = min(start_offset + max_value, max_offset) 97 | server_success = server_failure = processed = failed = total = time = 0 98 | while start_offset < stop_offset: 99 | run += 1 100 | if self.logger: # pragma: no cover 101 | self.logger.debug( 102 | 'run %d: start_offset is %d, stop_offset is %d' % 103 | (run, start_offset, stop_offset) 104 | ) 105 | 106 | # Extract items to be send from global item's list' 107 | _items_to_send = self.items_list[start_offset:stop_offset] 108 | 109 | # Send extracted items 110 | run_response, run_processed, run_failed, run_total, run_time = self._send_common(_items_to_send) 111 | 112 | # Update counters 113 | if run_response == 'success': 114 | server_success += 1 115 | elif run_response == 'failed': 116 | server_failure += 1 117 | processed += run_processed 118 | failed += run_failed 119 | total += run_total 120 | time += run_time 121 | if self.logger: # pragma: no cover 122 | self.logger.info("%d items sent during run %d" % (run_total, run)) 123 | self.logger.debug( 124 | 'run %d: processed is %d, failed is %d, total is %d' % 125 | (run, run_processed, run_failed, run_total) 126 | ) 127 | 128 | # Compute next run's offsets 129 | start_offset = stop_offset 130 | stop_offset = min(start_offset + max_value, max_offset) 131 | 132 | # Reset socket, which is likely to be closed by server 133 | self._socket_reset() 134 | except: 135 | self._reset() 136 | self._socket_reset() 137 | raise 138 | if self.logger: # pragma: no cover 139 | self.logger.info('All %d items have been sent in %d runs' % (total, run)) 140 | self.logger.debug( 141 | 'Total run is %d; item processed: %d, failed: %d, total: %d, during %f seconds' % 142 | (run, processed, failed, total, time) 143 | ) 144 | # Everything has been sent. 145 | # Reset DataContainer & return results_list 146 | self._reset() 147 | return server_success, server_failure, processed, failed, total, time 148 | 149 | def _send_common(self, item): 150 | """ 151 | Common part of sending operations 152 | Calls SenderProtocol._send_to_zabbix 153 | Returns result as provided by _handle_response 154 | 155 | :item: either a list or a single item depending on debug_level 156 | """ 157 | total = len(item) 158 | processed = failed = time = 0 159 | if self._config.dryrun is True: 160 | total = len(item) 161 | processed = failed = time = 0 162 | response = 'dryrun' 163 | else: 164 | self._send_to_zabbix(item) 165 | response, processed, failed, total, time = self._read_from_zabbix() 166 | 167 | output_key = '(bulk)' 168 | output_item = '(bulk)' 169 | if self.debug_level >= 4: 170 | output_key = item[0]['key'] 171 | output_item = item[0]['value'] 172 | if self.logger: # pragma: no cover 173 | self.logger.info( 174 | "" + 175 | ZBX_DBG_SEND_RESULT % ( 176 | processed, 177 | failed, 178 | total, 179 | output_key, 180 | output_item, 181 | response 182 | ) 183 | ) 184 | return response, processed, failed, total, time 185 | 186 | def _reset(self): 187 | """ 188 | Reset main DataContainer properties 189 | """ 190 | # Reset DataContainer to default values 191 | # So that it can be reused 192 | if self.logger: # pragma: no cover 193 | self.logger.info("Reset DataContainer") 194 | self._items_list = [] 195 | self._config.data_type = None 196 | 197 | @property 198 | def logger(self): 199 | """ 200 | Returns logger instance 201 | """ 202 | return self._logger 203 | 204 | @logger.setter 205 | def logger(self, value): 206 | """ 207 | Set logger instance for the class 208 | """ 209 | if isinstance(value, logging.Logger): 210 | self._logger = value 211 | else: 212 | if self._logger: # pragma: no cover 213 | self._logger.error("logger requires a logging instance") 214 | raise ValueError('logger requires a logging instance') 215 | 216 | # ZabbixAgentConfig getter & setter 217 | # Avoid using private property _config from outside 218 | @property 219 | def dryrun(self): 220 | """ 221 | Returns dryrun 222 | """ 223 | return self._config.dryrun 224 | 225 | @dryrun.setter 226 | def dryrun(self, value): 227 | """ 228 | Set dryrun 229 | """ 230 | self._config.dryrun = value 231 | 232 | @dryrun.setter 233 | def data_type(self, value): 234 | """ 235 | Set data_type 236 | """ 237 | self._config.data_type = value 238 | -------------------------------------------------------------------------------- /tests/test_datacontainer.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for protobix.SenderProtocol 3 | """ 4 | import configobj 5 | import pytest 6 | import mock 7 | import unittest 8 | import time 9 | try: import simplejson as json 10 | except ImportError: import json 11 | import socket 12 | 13 | import sys 14 | import os 15 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 16 | import protobix 17 | 18 | DATA = { 19 | 'items': { 20 | "protobix.host1": { 21 | "my.protobix.item.int": 0, 22 | "my.protobix.item.string": "item string" 23 | }, 24 | "protobix.host2": { 25 | "my.protobix.item.int": 0, 26 | "my.protobix.item.string": "item string" 27 | } 28 | }, 29 | 'lld': { 30 | 'protobix.host1': { 31 | 'my.protobix.lld_item1': [ 32 | { '{#PBX_LLD_KEY11}': 0, 33 | '{#PBX_LLD_KEY12}': 'lld string' }, 34 | { '{#PBX_LLD_KEY11}': 1, 35 | '{#PBX_LLD_KEY12}': 'another lld string' } 36 | ], 37 | 'my.protobix.lld_item2': [ 38 | { '{#PBX_LLD_KEY21}': 10, 39 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 40 | { '{#PBX_LLD_KEY21}': 2, 41 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 42 | ] 43 | 44 | }, 45 | 'protobix.host2': { 46 | 'my.protobix.lld_item1': [ 47 | { '{#PBX_LLD_KEY11}': 0, 48 | '{#PBX_LLD_KEY12}': 'lld string' }, 49 | { '{#PBX_LLD_KEY11}': 1, 50 | '{#PBX_LLD_KEY12}': 'another lld string' } 51 | ], 52 | 'my.protobix.lld_item2': [ 53 | { '{#PBX_LLD_KEY21}': 10, 54 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 55 | { '{#PBX_LLD_KEY21}': 2, 56 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 57 | ] 58 | } 59 | } 60 | } 61 | 62 | pytest_params = ( 63 | 'items', 64 | 'lld' 65 | ) 66 | def test_invalid_logger(): 67 | """ 68 | Adding data before assigning data_type should raise an Exception 69 | """ 70 | with pytest.raises(ValueError) as err: 71 | zbx_datacontainer = protobix.DataContainer(logger='invalid') 72 | assert str(err.value) == 'logger requires a logging instance' 73 | 74 | @pytest.mark.parametrize('data_type', pytest_params) 75 | def test_items_add_before_set_data_type(data_type): 76 | """ 77 | Adding data before assigning data_type should raise an Exception 78 | """ 79 | zbx_datacontainer = protobix.DataContainer() 80 | assert zbx_datacontainer.items_list == [] 81 | with pytest.raises(ValueError): 82 | zbx_datacontainer.add(DATA[data_type]) 83 | assert zbx_datacontainer.items_list == [] 84 | zbx_datacontainer.data_type = data_type 85 | zbx_datacontainer.add(DATA) 86 | assert len(zbx_datacontainer.items_list) == 4 87 | 88 | @pytest.mark.parametrize('data_type', pytest_params) 89 | def test_debug_no_dryrun_yes(data_type): 90 | """ 91 | debug_level to False 92 | dryrun to True 93 | """ 94 | zbx_datacontainer = protobix.DataContainer() 95 | zbx_datacontainer.data_type = data_type 96 | zbx_datacontainer.dryrun = True 97 | assert zbx_datacontainer.items_list == [] 98 | zbx_datacontainer.add(DATA[data_type]) 99 | assert len(zbx_datacontainer.items_list) == 4 100 | 101 | assert zbx_datacontainer.dryrun is True 102 | assert zbx_datacontainer.debug_level < 4 103 | 104 | ''' Send data to zabbix ''' 105 | srv_success, srv_failure, processed, failed, total, time = zbx_datacontainer.send() 106 | assert srv_success == 0 107 | assert srv_failure == 0 108 | assert processed == 0 109 | assert failed == 0 110 | assert total == 4 111 | assert zbx_datacontainer.items_list == [] 112 | 113 | @pytest.mark.parametrize('data_type', pytest_params) 114 | def test_debug_yes_dryrun_yes(data_type): 115 | """ 116 | debug_level to True 117 | dryrun to True 118 | """ 119 | zbx_datacontainer = protobix.DataContainer() 120 | zbx_datacontainer.data_type = data_type 121 | zbx_datacontainer.dryrun = True 122 | zbx_datacontainer.debug_level = 4 123 | 124 | assert zbx_datacontainer.items_list == [] 125 | zbx_datacontainer.add(DATA[data_type]) 126 | 127 | assert len(zbx_datacontainer.items_list) == 4 128 | 129 | ''' Send data to zabbix ''' 130 | srv_success, srv_failure, processed, failed, total, time = zbx_datacontainer.send() 131 | assert srv_success == 0 132 | assert srv_failure == 0 133 | assert processed == 0 134 | assert failed == 0 135 | assert total == 4 136 | assert zbx_datacontainer.items_list == [] 137 | 138 | @pytest.mark.parametrize('data_type', pytest_params) 139 | def test_debug_no_dryrun_no(data_type): 140 | """ 141 | debug_level to False 142 | dryrun to False 143 | """ 144 | zbx_datacontainer = protobix.DataContainer() 145 | # Force a Zabbix port so that test fails even if backend is present 146 | zbx_datacontainer.server_port = 10060 147 | zbx_datacontainer.data_type = data_type 148 | assert zbx_datacontainer.items_list == [] 149 | zbx_datacontainer.add(DATA[data_type]) 150 | assert len(zbx_datacontainer.items_list) == 4 151 | 152 | assert zbx_datacontainer.dryrun is False 153 | assert zbx_datacontainer.debug_level < 4 154 | 155 | ''' Send data to zabbix ''' 156 | with pytest.raises(socket.error): 157 | results_list = zbx_datacontainer.send() 158 | 159 | @pytest.mark.parametrize('data_type', pytest_params) 160 | def test_debug_yes_dryrun_no(data_type): 161 | """ 162 | debug_level to True 163 | dryrun to False 164 | """ 165 | zbx_datacontainer = protobix.DataContainer() 166 | zbx_datacontainer.debug_level = 4 167 | # Force a Zabbix port so that test fails even if backend is present 168 | zbx_datacontainer.server_port = 10060 169 | zbx_datacontainer.data_type = data_type 170 | assert zbx_datacontainer.items_list == [] 171 | zbx_datacontainer.add(DATA[data_type]) 172 | assert len(zbx_datacontainer.items_list) == 4 173 | 174 | assert zbx_datacontainer.dryrun is False 175 | assert zbx_datacontainer.debug_level >= 4 176 | 177 | ''' Send data to zabbix ''' 178 | with pytest.raises(socket.error): 179 | results_list = zbx_datacontainer.send() 180 | 181 | @pytest.mark.parametrize('data_type', pytest_params) 182 | def test_server_connection_fails(data_type): 183 | """ 184 | Connection to Zabbix Server fails 185 | """ 186 | zbx_datacontainer = protobix.DataContainer() 187 | zbx_datacontainer.server_port = 10060 188 | zbx_datacontainer.data_type = data_type 189 | assert zbx_datacontainer.items_list == [] 190 | assert zbx_datacontainer.server_port == 10060 191 | zbx_datacontainer.add(DATA[data_type]) 192 | with pytest.raises(IOError): 193 | zbx_datacontainer.send() 194 | assert zbx_datacontainer.items_list == [] 195 | 196 | @pytest.mark.parametrize('data_type', pytest_params) 197 | def test_need_backend_debug_no_dryrun_no(data_type): 198 | """ 199 | debug_level to False 200 | dryrun to False 201 | """ 202 | zbx_datacontainer = protobix.DataContainer() 203 | zbx_datacontainer.data_type = data_type 204 | assert zbx_datacontainer.items_list == [] 205 | zbx_datacontainer.add(DATA[data_type]) 206 | assert len(zbx_datacontainer.items_list) == 4 207 | 208 | assert zbx_datacontainer.dryrun is False 209 | assert zbx_datacontainer.debug_level < 4 210 | 211 | ''' Send data to zabbix ''' 212 | srv_success, srv_failure, processed, failed, total, time = zbx_datacontainer.send() 213 | assert srv_success == 1 214 | assert srv_failure == 0 215 | assert processed == 4 216 | assert failed == 0 217 | assert total == 4 218 | assert zbx_datacontainer.items_list == [] 219 | 220 | @pytest.mark.parametrize('data_type', pytest_params) 221 | def test_need_backend_debug_yes_dryrun_no(data_type): 222 | """ 223 | debug_level to True 224 | dryrun to False 225 | """ 226 | zbx_datacontainer = protobix.DataContainer() 227 | zbx_datacontainer.debug_level = 4 228 | zbx_datacontainer.data_type = data_type 229 | assert zbx_datacontainer.items_list == [] 230 | zbx_datacontainer.add(DATA[data_type]) 231 | assert len(zbx_datacontainer.items_list) == 4 232 | 233 | assert zbx_datacontainer.dryrun is False 234 | assert zbx_datacontainer.debug_level >= 4 235 | 236 | ''' Send data to zabbix ''' 237 | srv_success, srv_failure, processed, failed, total, time = zbx_datacontainer.send() 238 | assert srv_success == 4 239 | assert srv_failure == 0 240 | assert processed == 4 241 | assert failed == 0 242 | assert total == 4 243 | assert zbx_datacontainer.items_list == [] 244 | 245 | 246 | @pytest.mark.parametrize('data_type', pytest_params) 247 | def test_need_backend_debug_yes_dryrun_no(data_type): 248 | """ 249 | debug_level to True 250 | dryrun to False 251 | """ 252 | zbx_datacontainer = protobix.DataContainer() 253 | zbx_datacontainer.debug_level = 4 254 | zbx_datacontainer.data_type = data_type 255 | assert zbx_datacontainer.items_list == [] 256 | zbx_datacontainer.add(DATA[data_type]) 257 | assert len(zbx_datacontainer.items_list) == 4 258 | 259 | assert zbx_datacontainer.dryrun is False 260 | assert zbx_datacontainer.debug_level >= 4 261 | 262 | ''' Send data to zabbix ''' 263 | srv_success, srv_failure, processed, failed, total, time = zbx_datacontainer.send() 264 | assert srv_success == 4 265 | assert srv_failure == 0 266 | assert processed == 4 267 | assert failed == 0 268 | assert total == 4 269 | assert zbx_datacontainer.items_list == [] 270 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-protobix 2 | 3 | * `dev` Branch: [![Build Status](https://travis-ci.org/jbfavre/python-protobix.svg?branch=dev)](https://travis-ci.org/jbfavre/python-protobix) 4 | * `upstream` Branch (default): [![Build Status](https://travis-ci.org/jbfavre/python-protobix.svg?branch=upstream)](https://travis-ci.org/jbfavre/python-protobix) 5 | 6 | `python-protobix` is a very simple python module which implements [Zabbix Sender protocol 2.0](https://www.zabbix.org/wiki/Docs/protocols/zabbix_sender/2.0). 7 | It allows to build a list of Zabbix items and send them as `trappers`. 8 | 9 | Currently `python-protobix` supports "classics" `items` as well as [`Low Level Discovery`](https://www.zabbix.com/documentation/2.4/manual/discovery/low_level_discovery) ones. 10 | 11 | Please note that `python-protobix` is developped and tested on Debian GNU/Linux only. 12 | I can't enforce compatibility with other distributions, though it should work on any distribution providing Python 2.7 or Python 3.x. 13 | 14 | Any feedback on this is, of course, welcomed. 15 | 16 | ## Test 17 | 18 | To install all required dependencies and launch test suite 19 | 20 | python setup.py test 21 | 22 | By default, all tests named like `*need_backend*` are disabled, since they need a working Zabbix Server. 23 | 24 | If you want to run theses tests as well, you will need: 25 | * a working Zabbix Server 3.x configuration file like the one in `tests/zabbix/zabbix_server.conf` 26 | * SQL statements in `tests/zabbix/zabbix_server_mysql.sql` with all informations to create testing hosts & items 27 | 28 | You can then start Zabbix Server with `zabbix_server -c tests/zabbix/zabbix_server.conf -f` and launch test suite with 29 | 30 | py.test --cov protobix --cov-report term-missing 31 | 32 | ### Using a docker container 33 | 34 | You can also use docker to run test suite on any Linux distribution of your choice. 35 | You can use provided script `docker-tests.sh` as entrypoint example: 36 | 37 | docker run --volume=$(pwd):/home/python-protobix --entrypoint=/home/python-protobix/tests/docker-tests.sh -ti debian:jessie 38 | 39 | Currently, entrypoint `docker-tests.sh` only supports Debian GNU/Linux. 40 | 41 | __Please note that this docker entrypoint does not provide a way to execute test that need a backend__. 42 | 43 | ## Installation 44 | 45 | With `pip` (stable version): 46 | 47 | pip install protobix 48 | 49 | With `pip` (test version): 50 | 51 | pip install -i https://testpypi.python.org/simple/ protobix 52 | 53 | Python is available as Debian package for Debian GNU/Linux sid and testing. 54 | 55 | ## Usage 56 | 57 | Once module is installed, you can use it either extending `protobix.SampleProbe` or directly using `protobix.Datacontainer`. 58 | 59 | ### Extend `protobix.SampleProbe` 60 | 61 | `python-protobix` provides a convenient sample probe you can extend to fit your own needs. 62 | 63 | Using `protobix.SampleProbe` allows you to concentrate on getting metrics or Low Level Discovery items without taking care of anything related to `protobix` itself. 64 | This is the recommanded way of using `python-protobix`. 65 | 66 | `protobix.SampleProbe` provides a `run` method which take care of everything related to `protobix`. 67 | 68 | Some probes are available from my Github repository [`python-zabbix`](https://github.com/jbfavre/python-zabbix) 69 | 70 | ```python 71 | #!/usr/bin/env python 72 | # -*- coding: utf-8 -*- 73 | ''' Copyright (c) 2013 Jean Baptiste Favre. 74 | Sample Python class which extends protobix.SampleProbe 75 | ''' 76 | import protobix 77 | import argparse 78 | import socket 79 | import sys 80 | 81 | class ExampleProbe(protobix.SampleProbe): 82 | 83 | __version__ = '1.0.2' 84 | # discovery_key is *not* the one declared in Zabbix Agent configuration 85 | # it's the one declared in Zabbix template's "Discovery rules" 86 | discovery_key = "example.probe.llddiscovery" 87 | 88 | def _parse_probe_args(self, parser): 89 | # Parse the script arguments 90 | # parser is an instance of argparse.parser created by SampleProbe._parse_args method 91 | # you *must* return parser to SampleProbe so that your own options are taken into account 92 | example_probe_options = parser.add_argument_group('ExampleProbe configuration') 93 | example_probe_options.add_argument( 94 | "-o", "--option", default="default_value", 95 | help="WTF do this option" 96 | ) 97 | return parser 98 | 99 | def _init_probe(self): 100 | # Whatever you need to initiliaze your probe 101 | # Can be establishing a connection 102 | # Or reading a configuration file 103 | # If you have nothing special to do 104 | # Just do not override this method 105 | # Or use: 106 | pass 107 | 108 | def _get_discovery(self): 109 | # Whatever you need to do to discover LLD items 110 | # this method is mandatory 111 | # If not declared, calling the probe ith --discovery option will resut in a NotimplementedError 112 | # If you get discovery infos for only one node you should return data as follow 113 | return { self.hostname: data } 114 | # If you get discovery infos for many hosts, then you should build data dict by yourself 115 | # and return result as follow 116 | return data 117 | 118 | def _get_metrics(self): 119 | # Whatever you need to do to collect metrics 120 | # this method is mandatory 121 | # If not declared, calling the probe with --update-items option will resut in a NotimplementedError 122 | # If you get metrics for only one node you should return data as follow 123 | return { self.hostname: data } 124 | # If you get metrics for many hosts, then you should build data dict by your self 125 | # and return result as follow 126 | return data 127 | 128 | if __name__ == '__main__': 129 | ret = RedisServer().run() 130 | print ret 131 | sys.exit(ret) 132 | ``` 133 | 134 | Declare your newly created probe as `Zabbix Agent` user parameters: 135 | 136 | UserParameter=example.probe.check,/usr/local/bin/example_probe.py --update-items 137 | UserParameter=example.probe.discovery,/usr/local/bin/example_probe.py --discovery 138 | 139 | You're done. 140 | 141 | The `protobix.SampleProbe` exit code will be sent to Zabbix. 142 | You'll be able to setup triggers if needed. 143 | 144 | __Exit codes mapping__: 145 | * 0: everything went well 146 | * 1: probe failed at step 1 (probe initialization) 147 | * 2: probe failed at step 2 (probe data collection) 148 | * 3: probe failed at step 3 (add data to DataContainer) 149 | * 4: probe failed at step 4 (send data to Zabbix) 150 | 151 | ### Use `protobix.Datacontainer` 152 | 153 | If you don't want or can't use `protobix.SampleProbe`, you can also directly use `protobix.Datacontainer`. 154 | 155 | __How to send items updates__ 156 | 157 | ```python 158 | #!/usr/bin/env python 159 | 160 | ''' import module ''' 161 | import protobix 162 | 163 | DATA = { 164 | "protobix.host1": { 165 | "my.protobix.item.int": 0, 166 | "my.protobix.item.string": "item string" 167 | }, 168 | "protobix.host2": { 169 | "my.protobix.item.int": 0, 170 | "my.protobix.item.string": "item string" 171 | } 172 | } 173 | 174 | zbx_datacontainer = protobix.DataContainer() 175 | zbx_datacontainer.data_type = 'items' 176 | zbx_datacontainer.add(DATA) 177 | zbx_datacontainer.send() 178 | ``` 179 | 180 | __How to send Low Level Discovery__ 181 | 182 | ```python 183 | #!/usr/bin/env python 184 | 185 | ''' import module ''' 186 | import protobix 187 | 188 | DATA = { 189 | 'protobix.host1': { 190 | 'my.protobix.lld_item1': [ 191 | { '{#PBX_LLD_KEY11}': 0, 192 | '{#PBX_LLD_KEY12}': 'lld string' }, 193 | { '{#PBX_LLD_KEY11}': 1, 194 | '{#PBX_LLD_KEY12}': 'another lld string' } 195 | ], 196 | 'my.protobix.lld_item2': [ 197 | { '{#PBX_LLD_KEY21}': 10, 198 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 199 | { '{#PBX_LLD_KEY21}': 2, 200 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 201 | ] 202 | }, 203 | 'protobix.host2': { 204 | 'my.protobix.lld_item1': [ 205 | { '{#PBX_LLD_KEY11}': 0, 206 | '{#PBX_LLD_KEY12}': 'lld string' }, 207 | { '{#PBX_LLD_KEY11}': 1, 208 | '{#PBX_LLD_KEY12}': 'another lld string' } 209 | ], 210 | 'my.protobix.lld_item2': [ 211 | { '{#PBX_LLD_KEY21}': 10, 212 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 213 | { '{#PBX_LLD_KEY21}': 2, 214 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 215 | ] 216 | } 217 | } 218 | 219 | zbx_datacontainer = protobix.DataContainer() 220 | zbx_datacontainer.data_type = 'lld' 221 | zbx_datacontainer.add(DATA) 222 | zbx_datacontainer.send() 223 | ``` 224 | 225 | ## Advanced configuration 226 | 227 | `python-protobix` behaviour can be altered in many ways using options. 228 | All configuration options are stored in a `protobix.ZabbixAgentConfig` instance. 229 | 230 | __Protobix specific configuration options__ 231 | 232 | | Option name | Default value | ZabbixAgentConfig property | Command-line option (SampleProbe) | 233 | |--------------|---------------|----------------------------|-----------------------------------| 234 | | `data_type` | `None` | `data_type` | `--update-items` or `--discovery` | 235 | | `dryrun` | `False` | `dryrun` | `-d` or `--dryrun` | 236 | 237 | __Zabbix Agent configuration options__ 238 | 239 | | Option name | Default value | ZabbixAgentConfig property | Command-line option (SampleProbe) | 240 | |------------------------|--------------------------|----------------------------|-----------------------------------| 241 | | `ServerActive` | `127.0.0.1` | `server_active` | `-z` or `--zabbix-server` | 242 | | `ServerPort` | `10051` | `server_port` | `-p` or `--port` | 243 | | `LogType` | `file` | `log_type` | none | 244 | | `LogFile` | `/tmp/zabbix_agentd.log` | `log_file` | none | 245 | | `DebugLevel` | `3` | `debug_level` | `-v` (from none to `-vvvvv`) | 246 | | `Timeout` | `3` | `timeout` | none | 247 | | `Hostname` | `socket.getfqdn()` | `hostname` | none | 248 | | `TLSConnect` | `unencrypted` | `tls_connect` | `--tls-connect` | 249 | | `TLSCAFile` | `None` | `tls_ca_file` | `--tls-ca-file` | 250 | | `TLSCertFile` | `None` | `tls_cert_file` | `--tls-cert-file` | 251 | | `TLSCRLFile` | `None` | `tls_crl_file` | `--tls-crl-file` | 252 | | `TLSKeyFile` | `None` | `tls_key_file` | `--tls-key-file` | 253 | | `TLSServerCertIssuer` | `None` | `tls_server_cert_issuer` | `--tls-server-cert-issuer` | 254 | | `TLSServerCertSubject` | `None` | `tls_server_cert_subject` | `--tls-server-cert-subject` | 255 | 256 | ## How to contribute 257 | 258 | You can contribute to `protobix`: 259 | * fork this repository 260 | * write tests and documentation (tests __must__ pass for both Python 2.7 & 3.x) 261 | * implement the feature you need 262 | * open a pull request against __`upstream`__ branch 263 | -------------------------------------------------------------------------------- /tests/test_senderprotocol.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for protobix.SenderProtocol 3 | """ 4 | import configobj 5 | import pytest 6 | import mock 7 | import unittest 8 | import time 9 | try: import simplejson as json 10 | except ImportError: import json 11 | import socket 12 | 13 | import sys 14 | import os 15 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 16 | import protobix 17 | 18 | try: import simplejson as json 19 | except ImportError: import json 20 | import struct 21 | if sys.version_info < (3,): 22 | def b(x): 23 | return x 24 | else: 25 | import codecs 26 | def b(x): 27 | return codecs.utf_8_encode(x)[0] 28 | 29 | # Zabbix force TLSv1.2 protocol 30 | # in src/libs/zbxcrypto/tls.c function zbx_tls_init_child 31 | HAVE_DECENT_SSL = False 32 | if sys.version_info > (2,7,9): 33 | import ssl 34 | HAVE_DECENT_SSL = True 35 | 36 | def test_default_params(): 37 | """ 38 | Default configuration 39 | """ 40 | zbx_senderprotocol = protobix.SenderProtocol() 41 | 42 | assert zbx_senderprotocol.server_active == '127.0.0.1' 43 | assert zbx_senderprotocol.server_port == 10051 44 | assert zbx_senderprotocol._config.dryrun is False 45 | assert zbx_senderprotocol.items_list == [] 46 | 47 | def test_server_active_custom(): 48 | """ 49 | Test setting zbx_server with custom value 50 | """ 51 | zbx_senderprotocol = protobix.SenderProtocol() 52 | assert zbx_senderprotocol.server_active == '127.0.0.1' 53 | zbx_senderprotocol.server_active = 'myserver.domain.tld' 54 | assert zbx_senderprotocol.server_active == 'myserver.domain.tld' 55 | 56 | def test_server_port_custom(): 57 | """ 58 | Test setting server_port with custom value 59 | """ 60 | zbx_senderprotocol = protobix.SenderProtocol() 61 | assert zbx_senderprotocol.server_port == 10051 62 | zbx_senderprotocol.server_port = 10052 63 | assert zbx_senderprotocol.server_port == 10052 64 | 65 | def test_server_port_invalid_greater_than_32767(): 66 | """ 67 | Test setting server_port with invalid value 68 | """ 69 | zbx_senderprotocol = protobix.SenderProtocol() 70 | with pytest.raises(ValueError) as err: 71 | zbx_senderprotocol.server_port = 40000 72 | assert str(err.value) == 'ServerPort must be between 1024 and 32767' 73 | assert zbx_senderprotocol.server_port == 10051 74 | 75 | def test_server_port_invalid_lower_than_1024(): 76 | """ 77 | Test setting server_port with invalid value 78 | """ 79 | zbx_senderprotocol = protobix.SenderProtocol() 80 | with pytest.raises(ValueError) as err: 81 | zbx_senderprotocol.server_port = 1000 82 | assert str(err.value) == 'ServerPort must be between 1024 and 32767' 83 | assert zbx_senderprotocol.server_port == 10051 84 | 85 | def test_debug_custom(): 86 | """ 87 | Test setting server_port with custom value 88 | """ 89 | zbx_senderprotocol = protobix.SenderProtocol() 90 | assert zbx_senderprotocol.debug_level == 3 91 | zbx_senderprotocol.debug_level = 4 92 | assert zbx_senderprotocol.debug_level == 4 93 | 94 | def test_debug_invalid_lower_than_0(): 95 | """ 96 | Test setting server_port with invalid value 97 | """ 98 | zbx_senderprotocol = protobix.SenderProtocol() 99 | with pytest.raises(ValueError) as err: 100 | zbx_senderprotocol.debug_level = -1 101 | assert str(err.value) == 'DebugLevel must be between 0 and 5, -1 provided' 102 | assert zbx_senderprotocol.debug_level == 3 103 | 104 | def test_debug_invalid_greater_than_5(): 105 | """ 106 | Test setting server_port with invalid value 107 | """ 108 | zbx_senderprotocol = protobix.SenderProtocol() 109 | with pytest.raises(ValueError) as err: 110 | zbx_senderprotocol.debug_level = 10 111 | assert str(err.value) == 'DebugLevel must be between 0 and 5, 10 provided' 112 | assert zbx_senderprotocol.debug_level == 3 113 | 114 | def test_dryrun_custom(): 115 | """ 116 | Test setting dryrun with custom value 117 | """ 118 | zbx_senderprotocol = protobix.SenderProtocol() 119 | assert zbx_senderprotocol._config.dryrun is False 120 | zbx_senderprotocol._config.dryrun = True 121 | assert zbx_senderprotocol._config.dryrun is True 122 | zbx_senderprotocol._config.dryrun = False 123 | assert zbx_senderprotocol._config.dryrun is False 124 | 125 | def test_dryrun_invalid(): 126 | """ 127 | Test setting dryrun with invalid value 128 | """ 129 | zbx_senderprotocol = protobix.SenderProtocol() 130 | assert zbx_senderprotocol._config.dryrun is False 131 | with pytest.raises(ValueError) as err: 132 | zbx_senderprotocol._config.dryrun = 'invalid' 133 | assert str(err.value) == 'dryrun parameter requires boolean' 134 | assert zbx_senderprotocol._config.dryrun is False 135 | 136 | def test_clock_integer(): 137 | """ 138 | Test clock method 139 | """ 140 | zbx_senderprotocol = protobix.SenderProtocol() 141 | assert isinstance(zbx_senderprotocol.clock, int) is True 142 | 143 | def test_clock_accurate(): 144 | """ 145 | Test clock method 146 | """ 147 | zbx_senderprotocol = protobix.SenderProtocol() 148 | assert zbx_senderprotocol.clock == int(time.time()) 149 | 150 | @mock.patch('socket.socket', return_value=mock.MagicMock(name='socket', spec=socket.socket)) 151 | def test_send_to_zabbix(mock_socket): 152 | """ 153 | Test sending data to Zabbix Server 154 | """ 155 | item = { 'host': 'myhostname', 'key': 'my.item.key', 156 | 'value': 1, 'clock': int(time.time())} 157 | payload = json.dumps({ 158 | "data": [item], 159 | "request": "sender data", 160 | "clock": int(time.time()) 161 | }) 162 | packet = b('ZBXD\1') + struct.pack('= 2.2 176 | 'processed: 1; failed: 2; total: 3; seconds spent: 0.123456', 177 | ) 178 | @pytest.mark.parametrize('zabbix_answer', zabbix_answer_params) 179 | def test_handle_response(zabbix_answer): 180 | """ 181 | Test Zabbix Server/Proxy answer 182 | """ 183 | payload='{"response":"success","info":"'+zabbix_answer+'"}' 184 | zbx_datacontainer = protobix.DataContainer() 185 | srv_response, processed, failed, total, time = zbx_datacontainer._handle_response(payload) 186 | assert srv_response == 'success' 187 | assert processed == 1 188 | assert failed == 2 189 | assert total == 3 190 | assert time == 0.123456 191 | 192 | zabbix_answer_params= ( 193 | # Zabbix Sender protocol <= 2.0 194 | 'Invalid content', 195 | # Zabbix Sender protocol >= 2.2 196 | 'invalid content', 197 | ) 198 | @pytest.mark.parametrize('zabbix_answer', zabbix_answer_params) 199 | def test_handle_response_with_invalid_content(zabbix_answer): 200 | """ 201 | Test Zabbix Server/Proxy answer 202 | """ 203 | payload='{"response":"success","info":"'+zabbix_answer+'"}' 204 | zbx_datacontainer = protobix.DataContainer() 205 | with pytest.raises(IndexError): 206 | zbx_datacontainer._handle_response(payload) 207 | 208 | @mock.patch('socket.socket', return_value=mock.MagicMock(name='socket', spec=socket.socket)) 209 | def test_read_from_zabbix_valid_content(mock_socket): 210 | """ 211 | Test sending data to Zabbix Server 212 | """ 213 | answer_payload = '{"info": "processed: 0; failed: 1; total: 1; seconds spent: 0.000441", "response": "success"}' 214 | answer_packet = b('ZBXD\1') + struct.pack('= 1024 and value <= 32767: 175 | self.config['ServerPort'] = value 176 | else: 177 | raise ValueError('ServerPort must be between 1024 and 32767') 178 | 179 | @property 180 | def log_type(self): 181 | if 'LogType' in self.config: 182 | return self.config['LogType'] 183 | 184 | @log_type.setter 185 | def log_type(self, value): 186 | if value and value in ['file', 'system', 'console']: 187 | self.config['LogType'] = value 188 | 189 | @property 190 | def log_file(self): 191 | return self.config['LogFile'] 192 | 193 | @log_file.setter 194 | def log_file(self, value): 195 | self.config['LogFile'] = value 196 | 197 | @property 198 | def debug_level(self): 199 | return self.config['DebugLevel'] 200 | 201 | @debug_level.setter 202 | def debug_level(self, value): 203 | # Must be between 0 and 5 204 | # https://www.zabbix.com/documentation/3.0/manual/appendix/config/zabbix_agentd 205 | if isinstance(value, int) and value >= 0 and value <= 5: 206 | self.config['DebugLevel'] = value 207 | else: 208 | raise ValueError('DebugLevel must be between 0 and 5, ' + str(value) + ' provided') 209 | 210 | @property 211 | def timeout(self): 212 | return self.config['Timeout'] 213 | 214 | @timeout.setter 215 | def timeout(self, value): 216 | # Must be between 1 and 30 217 | # https://www.zabbix.com/documentation/3.0/manual/appendix/config/zabbix_agentd 218 | if isinstance(value, int) and value > 0 and value <= 30: 219 | self.config['Timeout'] = value 220 | else: 221 | raise ValueError('Timeout must be between 1 and 30') 222 | 223 | @property 224 | def hostname(self): 225 | return self.config['Hostname'] 226 | 227 | @hostname.setter 228 | def hostname(self, value): 229 | if value: 230 | self.config['Hostname'] = value 231 | 232 | @property 233 | def tls_connect(self): 234 | return self.config['TLSConnect'] 235 | 236 | @tls_connect.setter 237 | def tls_connect(self, value): 238 | if value in ['unencrypted', 'psk', 'cert']: 239 | self.config['TLSConnect'] = value 240 | else: 241 | raise ValueError('TLSConnect must be one of [unencrypted,psk,cert]') 242 | 243 | @property 244 | def tls_ca_file(self): 245 | return self.config['TLSCAFile'] 246 | 247 | @tls_ca_file.setter 248 | def tls_ca_file(self, value): 249 | if value: 250 | self.config['TLSCAFile'] = value 251 | 252 | @property 253 | def tls_cert_file(self): 254 | return self.config['TLSCertFile'] 255 | 256 | @tls_cert_file.setter 257 | def tls_cert_file(self, value): 258 | if value: 259 | self.config['TLSCertFile'] = value 260 | 261 | @property 262 | def tls_crl_file(self): 263 | return self.config['TLSCRLFile'] 264 | 265 | @tls_crl_file.setter 266 | def tls_crl_file(self, value): 267 | if value: 268 | self.config['TLSCRLFile'] = value 269 | 270 | @property 271 | def tls_key_file(self): 272 | return self.config['TLSKeyFile'] 273 | 274 | @tls_key_file.setter 275 | def tls_key_file(self, value): 276 | if value: 277 | self.config['TLSKeyFile'] = value 278 | 279 | @property 280 | def tls_server_cert_issuer(self): 281 | return self.config['TLSServerCertIssuer'] 282 | 283 | @tls_server_cert_issuer.setter 284 | def tls_server_cert_issuer(self, value): 285 | if value: 286 | self.config['TLSServerCertIssuer'] = value 287 | 288 | @property 289 | def tls_server_cert_subject(self): 290 | return self.config['TLSServerCertSubject'] 291 | 292 | @tls_server_cert_subject.setter 293 | def tls_server_cert_subject(self, value): 294 | if value: 295 | self.config['TLSServerCertSubject'] = value 296 | 297 | @property 298 | def tls_psk_identity(self): 299 | return self.config['TLSPSKIdentity'] 300 | 301 | @tls_psk_identity.setter 302 | def tls_psk_identity(self, value): 303 | if value: 304 | self.config['TLSPSKIdentity'] = value 305 | 306 | @property 307 | def tls_psk_file(self): 308 | return self.config['TLSPSKFile'] 309 | 310 | @tls_psk_file.setter 311 | def tls_psk_file(self, value): 312 | if value: 313 | self.config['TLSPSKFile'] = value 314 | 315 | @property 316 | def dryrun(self): 317 | return self.config['dryrun'] 318 | 319 | @dryrun.setter 320 | def dryrun(self, value): 321 | if value in [True, False]: 322 | self.config['dryrun'] = value 323 | else: 324 | raise ValueError('dryrun parameter requires boolean') 325 | 326 | @property 327 | def data_type(self): 328 | return self.config['data_type'] 329 | 330 | @data_type.setter 331 | def data_type(self, value): 332 | if value in ['lld', 'items', None]: 333 | self.config['data_type'] = value 334 | else: 335 | raise ValueError('data_type requires either "items" or "lld"') 336 | -------------------------------------------------------------------------------- /protobix/senderprotocol.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import sys 3 | import time 4 | import re 5 | 6 | import socket 7 | try: import simplejson as json 8 | except ImportError: import json # pragma: no cover 9 | 10 | from .zabbixagentconfig import ZabbixAgentConfig 11 | 12 | if sys.version_info < (3,): # pragma: no cover 13 | def b(x): 14 | return x 15 | else: # pragma: no cover 16 | import codecs 17 | def b(x): 18 | return codecs.utf_8_encode(x)[0] 19 | 20 | HAVE_DECENT_SSL = False 21 | if sys.version_info > (2,7,9): 22 | import ssl 23 | # Zabbix force TLSv1.2 protocol 24 | # in src/libs/zbxcrypto/tls.c function zbx_tls_init_child 25 | ZBX_TLS_PROTOCOL=ssl.PROTOCOL_TLSv1_2 26 | HAVE_DECENT_SSL = True 27 | 28 | ZBX_HDR = "ZBXD\1" 29 | ZBX_HDR_SIZE = 13 30 | ZBX_RESP_REGEX = r'[Pp]rocessed:? (\d+);? [Ff]ailed:? (\d+);? ' + \ 31 | r'[Tt]otal:? (\d+);? [Ss]econds spent:? (\d+\.\d+)' 32 | 33 | class SenderProtocol(object): 34 | 35 | REQUEST = "sender data" 36 | _logger = None 37 | 38 | def __init__(self, logger=None): 39 | self._config = ZabbixAgentConfig() 40 | self._items_list = [] 41 | self.socket = None 42 | if logger: # pragma: no cover 43 | self._logger = logger 44 | 45 | @property 46 | def server_active(self): 47 | return self._config.server_active 48 | 49 | @server_active.setter 50 | def server_active(self, value): 51 | if self._logger: # pragma: no cover 52 | self._logger.debug( 53 | "Replacing server_active '%s' with '%s'" % 54 | (self._config.server_active, value) 55 | ) 56 | self._config.server_active = value 57 | 58 | @property 59 | def server_port(self): 60 | return self._config.server_port 61 | 62 | @server_port.setter 63 | def server_port(self, value): 64 | if self._logger: # pragma: no cover 65 | self._logger.debug( 66 | "Replacing server_port '%s' with '%s'" % 67 | (self._config.server_port, value) 68 | ) 69 | self._config.server_port = value 70 | 71 | @property 72 | def debug_level(self): 73 | return self._config.debug_level 74 | 75 | @debug_level.setter 76 | def debug_level(self, value): 77 | if self._logger: # pragma: no cover 78 | self._logger.debug( 79 | "Replacing debug_level '%s' with '%s'" % 80 | (self._config.debug_level, value) 81 | ) 82 | self._config.debug_level = value 83 | 84 | @property 85 | def items_list(self): 86 | return self._items_list 87 | 88 | @property 89 | def clock(self): 90 | return int(time.time()) 91 | 92 | def _send_to_zabbix(self, item): 93 | if self._logger: # pragma: no cover 94 | self._logger.info( 95 | "Send data to Zabbix Server" 96 | ) 97 | 98 | # Format data to be sent 99 | if self._logger: # pragma: no cover 100 | self._logger.debug( 101 | "Building packet to be sent to Zabbix Server" 102 | ) 103 | payload = json.dumps({"data": item, 104 | "request": self.REQUEST, 105 | "clock": self.clock }) 106 | if self._logger: # pragma: no cover 107 | self._logger.debug('About to send: ' + str(payload)) 108 | data_length = len(payload) 109 | data_header = struct.pack('= 4096: 128 | _buffer = self._socket().recv(4096) 129 | zbx_srv_resp_data += _buffer 130 | recv_length = len(_buffer) 131 | 132 | _buffer = None 133 | recv_length = None 134 | # Check that we have a valid Zabbix header mark 135 | if self._logger: # pragma: no cover 136 | self._logger.debug( 137 | "Checking Zabbix headers" 138 | ) 139 | assert zbx_srv_resp_data[:5] == b(ZBX_HDR) 140 | 141 | # Extract response body length from packet 142 | zbx_srv_resp_body_len = struct.unpack('= 3: # pragma: no cover 160 | zbx_srv_resp_body = zbx_srv_resp_body.decode() 161 | # Analyze Zabbix answer 162 | response, processed, failed, total, time = self._handle_response(zbx_srv_resp_body) 163 | 164 | # Return Zabbix Server answer as JSON 165 | return response, processed, failed, total, time 166 | 167 | def _handle_response(self, zbx_answer): 168 | """ 169 | Analyze Zabbix Server response 170 | Returns a list with number of: 171 | * processed items 172 | * failed items 173 | * total items 174 | * time spent 175 | 176 | :zbx_answer: Zabbix server response as string 177 | """ 178 | zbx_answer = json.loads(zbx_answer) 179 | if self._logger: # pragma: no cover 180 | self._logger.info( 181 | "Anaylizing Zabbix Server's answer" 182 | ) 183 | if zbx_answer: 184 | self._logger.debug("Zabbix Server response is: [%s]" % zbx_answer) 185 | 186 | # Default items number in length of th storage list 187 | nb_item = len(self._items_list) 188 | if self._config.debug_level >= 4: 189 | # If debug enabled, force it to 1 190 | nb_item = 1 191 | 192 | # If dryrun is disabled, we can process answer 193 | response = zbx_answer.get('response') 194 | result = re.findall(ZBX_RESP_REGEX, zbx_answer.get('info')) 195 | processed, failed, total, time = result[0] 196 | 197 | return response, int(processed), int(failed), int(total), float(time) 198 | 199 | def _socket_reset(self): 200 | if self.socket: 201 | if self._logger: # pragma: no cover 202 | self._logger.info( 203 | "Reset socket" 204 | ) 205 | self.socket.close() 206 | self.socket = None 207 | 208 | def _socket(self): 209 | # If socket already exists, use it 210 | if self.socket is not None: 211 | if self._logger: # pragma: no cover 212 | self._logger.debug( 213 | "Using existing socket" 214 | ) 215 | return self.socket 216 | 217 | # If not, we have to create it 218 | if self._logger: # pragma: no cover 219 | self._logger.debug( 220 | "Setting socket options" 221 | ) 222 | socket.setdefaulttimeout(self._config.timeout) 223 | # Connect to Zabbix server or proxy with provided config options 224 | if self._logger: # pragma: no cover 225 | self._logger.info( 226 | "Creating new socket" 227 | ) 228 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 229 | 230 | # TLS is enabled, let's set it up 231 | if self._config.tls_connect != 'unencrypted' and HAVE_DECENT_SSL is True: 232 | if self._logger: # pragma: no cover 233 | self._logger.info( 234 | 'Configuring TLS to %s' % str(self._config.tls_connect) 235 | ) 236 | # Setup TLS context & Wrap socket 237 | self.socket = self._init_tls() 238 | if self._logger: # pragma: no cover 239 | self._logger.info( 240 | 'Network socket initialized with TLS support' 241 | ) 242 | 243 | if self._logger and isinstance(self.socket, socket.socket): # pragma: no cover 244 | self._logger.info( 245 | 'Network socket initialized with no TLS' 246 | ) 247 | # Connect to Zabbix Server 248 | self.socket.connect( 249 | (self._config.server_active, self._config.server_port) 250 | ) 251 | #if isinstance(self.socket, ssl.SSLSocket): 252 | # server_cert = self.socket.getpeercert() 253 | # if self._config.tls_server_cert_issuer: 254 | # print(server_cert['issuer']) 255 | # assert server_cert['issuer'] == self._config.tls_server_cert_issuer 256 | # self._logger.info( 257 | # 'Server certificate issuer is %s' % 258 | # server_cert['issuer'] 259 | # ) 260 | # if self._config.tls_server_cert_subject: 261 | # print(server_cert['subject']) 262 | # assert server_cert['subject'] == self._config.tls_server_cert_subject 263 | # self._logger.info( 264 | # 'Server certificate subject is %s' % 265 | # server_cert['subject'] 266 | # ) 267 | 268 | return self.socket 269 | 270 | """ 271 | Manage TLS context & Wrap socket 272 | Returns ssl.SSLSocket if TLS enabled 273 | socket.socket if TLS disabled 274 | """ 275 | def _init_tls(self): 276 | # Create a SSLContext and configure it 277 | if self._logger: # pragma: no cover 278 | self._logger.info( 279 | "Initialize TLS context" 280 | ) 281 | ssl_context = ssl.SSLContext(ZBX_TLS_PROTOCOL) 282 | if self._logger: # pragma: no cover 283 | self._logger.debug( 284 | 'Setting TLS verify_mode to ssl.CERT_REQUIRED' 285 | ) 286 | ssl_context.verify_mode = ssl.CERT_REQUIRED 287 | 288 | # Avoid CRIME and related attacks 289 | if self._logger: # pragma: no cover 290 | self._logger.debug( 291 | 'Setting TLS option ssl.OP_NO_COMPRESSION' 292 | ) 293 | ssl_context.options |= ssl.OP_NO_COMPRESSION 294 | ssl_context.verify_flags = ssl.VERIFY_X509_STRICT 295 | 296 | # If tls_connect is cert, we must provide client cert file & key 297 | if self._config.tls_connect == 'cert': 298 | if self._logger: # pragma: no cover 299 | self._logger.debug( 300 | "Using provided TLSCertFile %s" % self._config.tls_cert_file 301 | ) 302 | self._logger.debug( 303 | "Using provided TLSKeyFile %s" % self._config.tls_key_file 304 | ) 305 | ssl_context.load_cert_chain( 306 | self._config.tls_cert_file, 307 | self._config.tls_key_file 308 | ) 309 | elif self._config.tls_connect == 'psk': 310 | raise NotImplementedError 311 | 312 | # If provided, use CA file & enforce server certificate chek 313 | if self._config.tls_ca_file: 314 | if self._logger: # pragma: no cover 315 | self._logger.debug( 316 | "Using provided TLSCAFile %s" % self._config.tls_ca_file 317 | ) 318 | ssl_context.load_default_certs(ssl.Purpose.SERVER_AUTH) 319 | ssl_context.load_verify_locations( 320 | cafile=self._config.tls_ca_file 321 | ) 322 | 323 | # If provided, use CRL file & enforce server certificate check 324 | if self._config.tls_crl_file: 325 | if self._logger: # pragma: no cover 326 | self._logger.debug( 327 | "Using provided TLSCRLFile %s" % self._config.tls_crl_file 328 | ) 329 | ssl_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF 330 | ssl_context.load_verify_locations( 331 | cafile=self._config.tls_crl_file 332 | ) 333 | 334 | ## If provided enforce server cert issuer check 335 | #if self._config.tls_server_cert_issuer: 336 | # verify_issuer 337 | 338 | ## If provided enforce server cert subject check 339 | #if self._config.tls_server_cert_issuer: 340 | # verify_issuer 341 | 342 | # Once configuration is done, wrap network socket to TLS context 343 | tls_socket = ssl_context.wrap_socket( 344 | self.socket 345 | ) 346 | assert isinstance(tls_socket, ssl.SSLSocket) 347 | return tls_socket 348 | -------------------------------------------------------------------------------- /protobix/sampleprobe.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from argparse import RawTextHelpFormatter 3 | import socket 4 | import sys 5 | import traceback 6 | import logging 7 | from logging import handlers 8 | 9 | from .datacontainer import DataContainer 10 | from .zabbixagentconfig import ZabbixAgentConfig 11 | 12 | class SampleProbe(object): 13 | 14 | __version__ = '1.0.2' 15 | # Mapping between zabbix-agent Debug option & logging level 16 | LOG_LEVEL = [ 17 | logging.NOTSET, 18 | logging.CRITICAL, 19 | logging.ERROR, 20 | logging.INFO, 21 | logging.DEBUG, 22 | logging.DEBUG, 23 | ] 24 | logger = None 25 | probe_config = None 26 | hostname = None 27 | options = None 28 | 29 | def _parse_args(self, args): 30 | if self.logger: 31 | self.logger.info( 32 | "Read command line options" 33 | ) 34 | # Parse the script arguments 35 | parser = argparse.ArgumentParser( 36 | usage='%(prog)s [options]', 37 | formatter_class=RawTextHelpFormatter, 38 | epilog='Protobix - copyright 2016 - Jean Baptiste Favre (www.jbfavre.org)' 39 | ) 40 | # Probe operation mode 41 | probe_mode = parser.add_argument_group('Probe commands') 42 | probe_mode.add_argument( 43 | '--update-items', action='store_true', dest='update', 44 | help="Get & send items to Zabbix.\nThis is the default behaviour" 45 | ) 46 | probe_mode.add_argument( 47 | '--discovery', action='store_true', 48 | help="If specified, will perform Zabbix Low Level Discovery." 49 | ) 50 | # Common options 51 | common = parser.add_argument_group('Common options') 52 | common.add_argument( 53 | '-d', '--dryrun', action='store_true', 54 | help="Do not send anything to Zabbix. Usefull to debug with\n" 55 | "--verbose option" 56 | ) 57 | common.add_argument( 58 | '-v', action='count', dest='debug_level', 59 | help="Enable verbose mode. Is used to setup logging level.\n" 60 | "Specifying 4 or more 'v' (-vvvv) enables Debug. Items are then\n" 61 | "sent one after the other instead of bulk" 62 | ) 63 | # Protobix specific options 64 | protobix = parser.add_argument_group('Protobix specific options') 65 | protobix.add_argument( 66 | '-z', '--zabbix-server', dest='server_active', 67 | help="Hostname or IP address of Zabbix server. If a host is\n" 68 | "monitored by a proxy, proxy hostname or IP address\n" 69 | "should be used instead. When used together with\n" 70 | "--config, overrides the first entry of ServerActive\n" 71 | "parameter specified in agentd configuration file." 72 | ) 73 | protobix.add_argument( 74 | '-p', '--port', dest='server_port', 75 | help="Specify port number of Zabbix server trapper running on\n" 76 | "the server. Default is 10051. When used together with \n" 77 | "--config, overrides the port of first entry of\n" 78 | "ServerActive parameter specified in agentd configuration\n" 79 | "file." 80 | ) 81 | protobix.add_argument( 82 | '-c', '--config', dest='config_file', 83 | help="Use config-file. Zabbix sender reads server details from\n" 84 | "the agentd configuration file. By default Protobix reads\n" 85 | "`/etc/zabbix/zabbix_agentd.conf`.\n" 86 | "Absolute path should be specified." 87 | ) 88 | protobix.add_argument( 89 | '--tls-connect', choices=['unencrypted', 'psk', 'cert'], 90 | help="How to connect to server or proxy. Values:\n" 91 | "unencrypted connect without encryption\n" 92 | "psk connect using TLS and a pre-shared key\n" 93 | "cert connect using TLS and a certificate." 94 | ) 95 | protobix.add_argument( 96 | '--tls-ca-file', 97 | help="Full pathname of a file containing the top-level CA(s)\n" 98 | "certificates for peer certificate verification." 99 | ) 100 | protobix.add_argument( 101 | '--tls-cert-file', 102 | help="Full pathname of a file containing the certificate or\n" 103 | "certificate chain." 104 | ) 105 | protobix.add_argument( 106 | '--tls-key-file', 107 | help="Full pathname of a file containing the private key." 108 | ) 109 | protobix.add_argument( 110 | '--tls-crl-file', 111 | help="Full pathname of a file containing revoked certificates." 112 | ) 113 | protobix.add_argument( 114 | '--tls-server-cert-issuer', 115 | help="Allowed server certificate issuer." 116 | ) 117 | protobix.add_argument( 118 | '--tls-server-cert-subject', 119 | help="Allowed server certificate subject." 120 | ) 121 | # TLS PSK is not implemented in Python 122 | # https://bugs.python.org/issue19084 123 | # Following options are not implemented 124 | protobix.add_argument( 125 | '--tls-psk-identity', 126 | help="PSK-identity string." 127 | ) 128 | protobix.add_argument( 129 | '--tls-psk-file', 130 | help="Full pathname of a file containing the pre-shared key." 131 | ) 132 | # Probe specific options 133 | parser = self._parse_probe_args(parser) 134 | # Analyze provided command line options 135 | options = parser.parse_args(args) 136 | 137 | # Check that we don't have both '--update' & '--discovery' options 138 | options.probe_mode = 'update' 139 | if options.update is True and options.discovery is True: 140 | raise ValueError( 141 | 'You can\' use both --update-items & --discovery options' 142 | ) 143 | elif options.discovery is True: 144 | options.probe_mode = 'discovery' 145 | 146 | return options 147 | 148 | def _init_logging(self): 149 | logger = logging.getLogger(self.__class__.__name__) 150 | logger.handlers = [] 151 | logger.setLevel(logging.NOTSET) 152 | self.logger = logger 153 | 154 | def _setup_logging(self, log_type, debug_level, log_file): 155 | if self.logger: 156 | self.logger.info( 157 | "Initialize logging" 158 | ) 159 | # Enable log like Zabbix Agent does 160 | # Though, when we have a tty, it's convenient to use console to log 161 | common_log_format = '[%(name)s:%(levelname)s] %(message)s' 162 | if log_type == 'console' or sys.stdout.isatty(): 163 | console_handler = logging.StreamHandler() 164 | console_formatter = logging.Formatter( 165 | fmt=common_log_format, 166 | datefmt='%Y%m%d:%H%M%S' 167 | ) 168 | console_handler.setFormatter(console_formatter) 169 | self.logger.addHandler(console_handler) 170 | if log_type == 'file': 171 | file_handler = logging.FileHandler(log_file) 172 | # Use same date format as Zabbix: when logging into 173 | # zabbix_agentd log file, it's easier to read & parse 174 | log_formatter = logging.Formatter( 175 | fmt='%(process)d:%(asctime)s.%(msecs)03d ' + common_log_format, 176 | datefmt='%Y%m%d:%H%M%S' 177 | ) 178 | file_handler.setFormatter(log_formatter) 179 | self.logger.addHandler(file_handler) 180 | if log_type == 'system': 181 | # TODO: manage syslog address as command line option 182 | syslog_handler = logging.handlers.SysLogHandler( 183 | address=('localhost', 514), 184 | facility=logging.handlers.SysLogHandler.LOG_DAEMON 185 | ) 186 | # Use same date format as Zabbix does: when logging into 187 | # zabbix_agentd log file, it's easier to read & parse 188 | log_formatter = logging.Formatter( 189 | fmt='%(process)d:%(asctime)s.%(msecs)03d ' + common_log_format, 190 | datefmt='%Y%m%d:%H%M%S' 191 | ) 192 | syslog_handler.setFormatter(log_formatter) 193 | self.logger.addHandler(syslog_handler) 194 | self.logger.setLevel( 195 | self.LOG_LEVEL[debug_level] 196 | ) 197 | 198 | def _init_config(self): 199 | if self.logger: 200 | self.logger.info( 201 | "Get configuration" 202 | ) 203 | # Get config from ZabbixAgentConfig 204 | zbx_config = ZabbixAgentConfig(self.options.config_file) 205 | 206 | # And override it with provided command line options 207 | if self.options.server_active: 208 | zbx_config.server_active = self.options.server_active 209 | 210 | if self.options.server_port: 211 | zbx_config.server_port = int(self.options.server_port) 212 | 213 | # tls_connect 'cert' needed options 214 | if self.options.tls_cert_file: 215 | zbx_config.tls_cert_file = self.options.tls_cert_file 216 | 217 | if self.options.tls_key_file: 218 | zbx_config.tls_key_file = self.options.tls_key_file 219 | 220 | if self.options.tls_ca_file: 221 | zbx_config.tls_ca_file = self.options.tls_ca_file 222 | 223 | if self.options.tls_crl_file: 224 | zbx_config.tls_crl_file = self.options.tls_crl_file 225 | 226 | # tls_connect 'psk' needed options 227 | if self.options.tls_psk_file: 228 | zbx_config.tls_psk_file = self.options.tls_psk_file 229 | 230 | if self.options.tls_psk_identity: 231 | zbx_config.tls_psk_identity = self.options.tls_psk_identity 232 | 233 | if self.options.tls_server_cert_issuer: 234 | zbx_config.tls_server_cert_issuer = self.options.tls_server_cert_issuer 235 | 236 | if self.options.tls_server_cert_subject: 237 | zbx_config.tls_server_cert_subject = self.options.tls_server_cert_subject 238 | 239 | # Set tls_connect last because it'll check above options 240 | # to ensure a coherent config set 241 | if self.options.tls_connect: 242 | zbx_config.tls_connect = self.options.tls_connect 243 | 244 | if self.options.debug_level: 245 | self.options.debug_level = min(4, self.options.debug_level) 246 | zbx_config.debug_level = self.options.debug_level 247 | 248 | zbx_config.dryrun = False 249 | if self.options.dryrun: 250 | zbx_config.dryrun = self.options.dryrun 251 | 252 | return zbx_config 253 | 254 | def _get_metrics(self): 255 | # mandatory method 256 | raise NotImplementedError 257 | 258 | def _get_discovery(self): 259 | # mandatory method 260 | raise NotImplementedError 261 | 262 | def _init_probe(self): 263 | # non mandatory method 264 | pass 265 | 266 | def _parse_probe_args(self, parser): 267 | # non mandatory method 268 | return parser 269 | 270 | def run(self, options=None): 271 | # Init logging with default values since we don't have real config yet 272 | self._init_logging() 273 | 274 | # Parse command line options 275 | args = sys.argv[1:] 276 | if isinstance(options, list): 277 | args = options 278 | self.options = self._parse_args(args) 279 | 280 | # Get configuration 281 | self.zbx_config = self._init_config() 282 | 283 | # Update logger with configuration 284 | self._setup_logging( 285 | self.zbx_config.log_type, 286 | self.zbx_config.debug_level, 287 | self.zbx_config.log_file 288 | ) 289 | 290 | # Datacontainer init 291 | zbx_container = DataContainer( 292 | config = self.zbx_config, 293 | logger=self.logger 294 | ) 295 | # Get back hostname from ZabbixAgentConfig 296 | self.hostname = self.zbx_config.hostname 297 | 298 | # Step 1: read probe configuration 299 | # initialize any needed object or connection 300 | try: 301 | self._init_probe() 302 | except: 303 | if self.logger: 304 | self.logger.critical( 305 | "Step 1 - Read probe configuration failed" 306 | ) 307 | self.logger.debug(traceback.format_exc()) 308 | return 1 309 | 310 | # Step 2: get data 311 | try: 312 | data = {} 313 | if self.options.probe_mode == "update": 314 | zbx_container.data_type = 'items' 315 | data = self._get_metrics() 316 | elif self.options.probe_mode == "discovery": 317 | zbx_container.data_type = 'lld' 318 | data = self._get_discovery() 319 | except NotImplementedError as e: 320 | if self.logger: 321 | self.logger.critical( 322 | "Step 2 - Get Data failed [%s]" % str(e) 323 | ) 324 | self.logger.debug(traceback.format_exc()) 325 | raise 326 | except Exception as e: 327 | if self.logger: 328 | self.logger.critical( 329 | "Step 2 - Get Data failed [%s]" % str(e) 330 | ) 331 | self.logger.debug(traceback.format_exc()) 332 | return 2 333 | 334 | # Step 3: add data to container 335 | try: 336 | zbx_container.add(data) 337 | except Exception as e: 338 | if self.logger: 339 | self.logger.critical( 340 | "Step 3 - Format & add Data failed [%s]" % str(e) 341 | ) 342 | self.logger.debug(traceback.format_exc()) 343 | zbx_container._reset() 344 | return 3 345 | 346 | # Step 4: send data to Zabbix server 347 | try: 348 | zbx_container.send() 349 | except socket.error as e: 350 | if self.logger: 351 | self.logger.critical( 352 | "Step 4 - Sent to Zabbix Server [%s] failed [%s]" % ( 353 | self.zbx_config.server_active, 354 | str(e) 355 | ) 356 | ) 357 | self.logger.debug(traceback.format_exc()) 358 | return 4 359 | except Exception as e: 360 | if self.logger: 361 | self.logger.critical( 362 | "Step 4 - Unknown error [%s]" % str(e) 363 | ) 364 | self.logger.debug(traceback.format_exc()) 365 | return 4 366 | # Everything went fine. Let's return 0 and exit 367 | return 0 368 | -------------------------------------------------------------------------------- /tests/test_zabbixagentconfig.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for protobix.ZabbixAgentConfig 3 | """ 4 | import configobj 5 | import pytest 6 | import mock 7 | import unittest 8 | import logging 9 | 10 | import sys 11 | import os 12 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 13 | import protobix 14 | 15 | @mock.patch('configobj.ConfigObj') 16 | def test_config_file_default(mock_configobj): 17 | """ 18 | Default Zabbix Agent configuration from Zabbix 19 | """ 20 | mock_configobj.side_effect = [ 21 | { 22 | 'LogFile': '/tmp/zabbix_agentd.log', 23 | 'Server': '127.0.0.1', 24 | 'ServerActive': '127.0.0.1', 25 | 'Hostname': 'Zabbix server' 26 | } 27 | ] 28 | zbx_config = protobix.ZabbixAgentConfig( 29 | config_file='default_zabbix_agentd.conf' 30 | ) 31 | assert zbx_config.data_type is None 32 | assert zbx_config.dryrun is False 33 | assert zbx_config.server_active == '127.0.0.1' 34 | assert zbx_config.server_port == 10051 35 | assert zbx_config.log_type == 'file' 36 | assert zbx_config.log_file == '/tmp/zabbix_agentd.log' 37 | assert zbx_config.debug_level == 3 38 | assert zbx_config.timeout == 3 39 | assert zbx_config.hostname == 'Zabbix server' 40 | assert zbx_config.tls_connect == 'unencrypted' 41 | assert zbx_config.tls_ca_file is None 42 | assert zbx_config.tls_cert_file is None 43 | assert zbx_config.tls_crl_file is None 44 | assert zbx_config.tls_key_file is None 45 | assert zbx_config.tls_server_cert_issuer is None 46 | assert zbx_config.tls_server_cert_subject is None 47 | assert zbx_config.tls_psk_identity is None 48 | assert zbx_config.tls_psk_file is None 49 | 50 | @mock.patch('configobj.ConfigObj') 51 | def test_config_file_not_found(mock_configobj): 52 | """ 53 | Not found zabbix_agentd.conf 54 | hostname should fallback to socket.getfqdn 55 | """ 56 | mock_configobj.side_effect = [ 57 | {} 58 | ] 59 | with mock.patch('socket.getfqdn', return_value='myhostname'): 60 | zbx_config = protobix.ZabbixAgentConfig( 61 | config_file='not_found_config_file' 62 | ) 63 | assert zbx_config.data_type is None 64 | assert zbx_config.dryrun is False 65 | assert zbx_config.server_active == '127.0.0.1' 66 | assert zbx_config.server_port == 10051 67 | assert zbx_config.log_type == 'file' 68 | assert zbx_config.log_file == '/tmp/zabbix_agentd.log' 69 | assert zbx_config.debug_level == 3 70 | assert zbx_config.timeout == 3 71 | assert zbx_config.hostname == 'myhostname' 72 | assert zbx_config.tls_connect == 'unencrypted' 73 | assert zbx_config.tls_ca_file is None 74 | assert zbx_config.tls_cert_file is None 75 | assert zbx_config.tls_crl_file is None 76 | assert zbx_config.tls_key_file is None 77 | assert zbx_config.tls_server_cert_issuer is None 78 | assert zbx_config.tls_server_cert_subject is None 79 | assert zbx_config.tls_psk_identity is None 80 | assert zbx_config.tls_psk_file is None 81 | 82 | @mock.patch('configobj.ConfigObj') 83 | def test_server_active_custom(mock_configobj): 84 | """ 85 | Custom serverActive & serverPort 86 | """ 87 | mock_configobj.side_effect = [ 88 | { 89 | 'ServerActive': 'myzabbixserver:10052,10.0.0.2:10051', 90 | } 91 | ] 92 | zbx_config = protobix.ZabbixAgentConfig( 93 | 'zabbix_config_with_custom_serverActive' 94 | ) 95 | assert zbx_config.server_active == 'myzabbixserver' 96 | assert zbx_config.server_port == 10052 97 | 98 | @mock.patch('configobj.ConfigObj') 99 | def test_server_port_invalid_lower_than_1024(mock_configobj): 100 | """ 101 | Invalid serverPort. 102 | Should raise an ValueError with proper message 103 | """ 104 | mock_configobj.side_effect = [ 105 | { 106 | 'ServerActive': '127.0.0.1:1000', 107 | 'LogFile': '/tmp/zabbix_agentd.log', 108 | } 109 | ] 110 | with pytest.raises(ValueError) as err: 111 | protobix.ZabbixAgentConfig( 112 | 'zabbix_config_with_invalid_serverPort' 113 | ) 114 | assert str(err.value) == 'ServerPort must be between 1024 and 32767' 115 | 116 | @mock.patch('configobj.ConfigObj') 117 | def test_server_port_invalid_greater_than_32767(mock_configobj): 118 | """ 119 | Invalid serverPort. 120 | Should raise an ValueError with proper message 121 | """ 122 | mock_configobj.side_effect = [ 123 | { 124 | 'ServerActive': '127.0.0.1:40000', 125 | 'LogFile': '/tmp/zabbix_agentd.log', 126 | } 127 | ] 128 | with pytest.raises(ValueError) as err: 129 | protobix.ZabbixAgentConfig( 130 | 'zabbix_config_with_invalid_serverPort' 131 | ) 132 | assert str(err.value) == 'ServerPort must be between 1024 and 32767' 133 | 134 | @mock.patch('configobj.ConfigObj') 135 | def test_log_config_custom(mock_configobj): 136 | """ 137 | LogType set to 'file' 138 | LogFile set to '/tmp/zabbix_agentd.log' 139 | """ 140 | mock_configobj.side_effect = [ 141 | { 142 | 'LogType': 'file', 143 | 'LogFile': '/tmp/test_zabbix_agentd.log', 144 | } 145 | ] 146 | zbx_config = protobix.ZabbixAgentConfig( 147 | 'zabbix_config_with_logType_to_file_logFile_set' 148 | ) 149 | assert zbx_config.log_type == 'file' 150 | assert zbx_config.log_file == '/tmp/test_zabbix_agentd.log' 151 | 152 | @mock.patch('configobj.ConfigObj') 153 | def test_log_config_fallback_log_file(mock_configobj): 154 | """ 155 | LogType set to 'file' 156 | LogFile unset 157 | LogFile should default to '/tmp/zabbix_agentd.log' 158 | """ 159 | mock_configobj.side_effect = [ 160 | { 161 | 'LogType': 'file' 162 | } 163 | ] 164 | zbx_config = protobix.ZabbixAgentConfig( 165 | 'zabbix_config_with_logType_to_system_logFile_empty' 166 | ) 167 | assert zbx_config.log_type == 'file' 168 | assert zbx_config.log_file == '/tmp/zabbix_agentd.log' 169 | 170 | @mock.patch('configobj.ConfigObj') 171 | def test_log_config_use_syslog(mock_configobj): 172 | """ 173 | LogType set to 'system' 174 | LogFile should be None 175 | """ 176 | mock_configobj.side_effect = [ 177 | { 178 | 'LogType': 'system', 179 | 'LogFile': '/tmp/zabbix_agentd.log', 180 | } 181 | ] 182 | zbx_config = protobix.ZabbixAgentConfig( 183 | 'zabbix_config_with_logType_to_system' 184 | ) 185 | assert zbx_config.log_type == 'system' 186 | assert zbx_config.log_file is None 187 | 188 | @mock.patch('configobj.ConfigObj') 189 | def test_log_config_use_console(mock_configobj): 190 | """ 191 | LogType set to 'console' 192 | LogFile set 193 | LogFile should be None 194 | """ 195 | mock_configobj.side_effect = [ 196 | { 197 | 'LogType': 'console', 198 | 'LogFile': '/tmp/zabbix_agentd.log', 199 | } 200 | ] 201 | zbx_config = protobix.ZabbixAgentConfig( 202 | 'zabbix_config_with_logType_to_console' 203 | ) 204 | assert zbx_config.log_type == 'console' 205 | assert zbx_config.log_file is None 206 | 207 | @mock.patch('configobj.ConfigObj') 208 | def test_log_config_use_console_fallback_log_file(mock_configobj): 209 | """ 210 | LogType set to 'console' 211 | LogFile unset 212 | LogFile should be None 213 | """ 214 | mock_configobj.side_effect = [ 215 | { 216 | 'LogType': 'console', 217 | } 218 | ] 219 | zbx_config = protobix.ZabbixAgentConfig( 220 | 'zabbix_config_with_logType_to_console' 221 | ) 222 | assert zbx_config.log_type == 'console' 223 | assert zbx_config.log_file is None 224 | 225 | @mock.patch('configobj.ConfigObj') 226 | def test_log_config_invalid_log_type(mock_configobj): 227 | """ 228 | Invalid LogType 229 | Should raise an ValueError with proper message 230 | """ 231 | mock_configobj.side_effect = [ 232 | { 233 | 'LogType': 'invalid', 234 | } 235 | ] 236 | with pytest.raises(ValueError) as err: 237 | protobix.ZabbixAgentConfig('zabbix_config_with_invalid_logType') 238 | assert str(err.value) == 'LogType must be one of [file,system,console]' 239 | 240 | @mock.patch('configobj.ConfigObj') 241 | def test_log_config_zabbix_24_compatibility(mock_configobj): 242 | """ 243 | Missing LogType & LogFile set to '-' 244 | LogType should fallbackback to system 245 | LogFile should fallback to '/dev/log' 246 | This is for Zabbix 2.4.x retro compatibility 247 | """ 248 | mock_configobj.side_effect = [ 249 | { 250 | 'LogFile': '-', 251 | } 252 | ] 253 | zbx_config = protobix.ZabbixAgentConfig( 254 | 'zabbix_config_with_missing_logType' 255 | ) 256 | assert zbx_config.log_type == 'system' 257 | assert zbx_config.log_file is None 258 | 259 | @mock.patch('configobj.ConfigObj') 260 | def test_hostname_custom(mock_configobj): 261 | """ 262 | Custom hostname. 263 | Should *NOT* fallback to socket.getfqdn 264 | """ 265 | mock_configobj.side_effect = [ 266 | { 267 | 'LogFile': '/tmp/zabbix_agentd.log', 268 | 'Hostname': 'myhostname' 269 | } 270 | ] 271 | with mock.patch('socket.getfqdn', return_value='myhostname.domain.tld'): 272 | zbx_config = protobix.ZabbixAgentConfig( 273 | 'zabbix_config_with_custom_hostname' 274 | ) 275 | assert zbx_config.hostname == 'myhostname' 276 | 277 | @mock.patch('configobj.ConfigObj') 278 | def test_timeout_custom(mock_configobj): 279 | """ 280 | Custom Timeout. 281 | Should not fallbackback to 3 282 | """ 283 | mock_configobj.side_effect = [ 284 | { 285 | 'LogFile': '/tmp/zabbix_agentd.log', 286 | 'Timeout': 5, 287 | } 288 | ] 289 | zbx_config = protobix.ZabbixAgentConfig( 290 | 'zabbix_config_with_custom_timeout' 291 | ) 292 | assert zbx_config.timeout == 5 293 | 294 | @mock.patch('configobj.ConfigObj') 295 | def test_timeout_invalid_lower_than_0(mock_configobj): 296 | """ 297 | Invalid Timeout. 298 | Should raise an ValueError with proper message 299 | """ 300 | mock_configobj.side_effect = [ 301 | { 302 | 'LogFile': '/tmp/zabbix_agentd.log', 303 | 'Timeout': -2, 304 | } 305 | ] 306 | with pytest.raises(ValueError) as err: 307 | protobix.ZabbixAgentConfig('zabbix_config_with_invalid_timeout') 308 | assert str(err.value) == 'Timeout must be between 1 and 30' 309 | 310 | @mock.patch('configobj.ConfigObj') 311 | def test_timeout_invalid_greater_than_30(mock_configobj): 312 | """ 313 | Invalid Timeout. 314 | Should raise an ValueError with proper message 315 | """ 316 | mock_configobj.side_effect = [ 317 | { 318 | 'LogFile': '/tmp/zabbix_agentd.log', 319 | 'Timeout': 50, 320 | } 321 | ] 322 | with pytest.raises(ValueError) as err: 323 | protobix.ZabbixAgentConfig('zabbix_config_with_invalid_timeout') 324 | assert str(err.value) == 'Timeout must be between 1 and 30' 325 | 326 | @mock.patch('configobj.ConfigObj') 327 | def test_debug_level_custom(mock_configobj): 328 | """ 329 | Custom DebugLevel. 330 | Should not fallbackback to 3 331 | """ 332 | mock_configobj.side_effect = [ 333 | { 334 | 'LogFile': '/tmp/zabbix_agentd.log', 335 | 'DebugLevel': 4 336 | } 337 | ] 338 | zbx_config = protobix.ZabbixAgentConfig( 339 | 'zabbix_config_with_custom_debugLevel' 340 | ) 341 | assert zbx_config.debug_level == 4 342 | 343 | @mock.patch('configobj.ConfigObj') 344 | def test_debug_level_invalid_lower_than_0(mock_configobj): 345 | """ 346 | Invalid DebugLevel. 347 | Should raise an ValueError with proper message 348 | """ 349 | mock_configobj.side_effect = [ 350 | { 351 | 'LogFile': '/tmp/zabbix_agentd.log', 352 | 'DebugLevel': -1 353 | } 354 | ] 355 | with pytest.raises(ValueError) as err: 356 | protobix.ZabbixAgentConfig('zabbix_config_with_invalid_debugLevel') 357 | assert str(err.value) == 'DebugLevel must be between 0 and 5, -1 provided' 358 | 359 | @mock.patch('configobj.ConfigObj') 360 | def test_debug_level_invalid_greater_than_5(mock_configobj): 361 | """ 362 | Invalid DebugLevel. 363 | Should raise an ValueError with proper message 364 | """ 365 | mock_configobj.side_effect = [ 366 | { 367 | 'LogFile': '/tmp/zabbix_agentd.log', 368 | 'DebugLevel': 10 369 | } 370 | ] 371 | with pytest.raises(ValueError) as err: 372 | protobix.ZabbixAgentConfig('zabbix_config_with_invalid_debugLevel') 373 | assert str(err.value) == 'DebugLevel must be between 0 and 5, 10 provided' 374 | 375 | @mock.patch('configobj.ConfigObj') 376 | def test_tls_default_config(mock_configobj): 377 | """ 378 | Default TLS configuration 379 | """ 380 | mock_configobj.side_effect = [{}] 381 | zbx_config = protobix.ZabbixAgentConfig('TLS_default_configuration') 382 | assert zbx_config.tls_connect == 'unencrypted' 383 | assert zbx_config.tls_ca_file is None 384 | assert zbx_config.tls_cert_file is None 385 | assert zbx_config.tls_crl_file is None 386 | assert zbx_config.tls_key_file is None 387 | assert zbx_config.tls_server_cert_issuer is None 388 | assert zbx_config.tls_server_cert_subject is None 389 | 390 | @mock.patch('configobj.ConfigObj') 391 | def test_tls_connect_unencrypted_other_custom(mock_configobj): 392 | """ 393 | TLSConnect: 'unencrypted' 394 | All other TLS parameters should default to None 395 | """ 396 | mock_configobj.side_effect = [ 397 | { 398 | 'TLSConnect': 'unencrypted', 399 | 'TLSCAFile': '/tmp/tls_ca_file.crt', 400 | 'TLSCertFile': '/tmp/tls_cert_file.crt', 401 | 'TLSCRLFile': '/tmp/tls_crl_file.crt', 402 | 'TLSKeyFile': '/tmp/tls_ckey_file.crt', 403 | 'TLSServerCertIssuer': '/tmp/tls_server__cert_issuer.crt', 404 | 'TLSServerCertSubject': '/tmp/tls_server_cert_subject.crt', 405 | } 406 | ] 407 | zbx_config = protobix.ZabbixAgentConfig('TLSConnect_unencrypted') 408 | assert zbx_config.tls_connect == 'unencrypted' 409 | assert zbx_config.tls_ca_file is None 410 | assert zbx_config.tls_cert_file is None 411 | assert zbx_config.tls_crl_file is None 412 | assert zbx_config.tls_key_file is None 413 | assert zbx_config.tls_server_cert_issuer is None 414 | assert zbx_config.tls_server_cert_subject is None 415 | 416 | @mock.patch('configobj.ConfigObj') 417 | def test_tls_connect_cert_tls_cert_key_missing(mock_configobj): 418 | """ 419 | TLSConnect: 'cert' 420 | TLSCertFile unset 421 | TLSKeyFile unset 422 | Should raise a ValueError with appropriate message 423 | """ 424 | mock_configobj.side_effect = [ 425 | { 426 | 'TLSConnect': 'cert' 427 | } 428 | ] 429 | with pytest.raises(ValueError) as err: 430 | protobix.ZabbixAgentConfig('TLSConnect_cert_without_TLSCertFile_TLSKeyFile_TLSCAFile') 431 | assert str(err.value) == 'TLSConnect is cert. TLSCertFile, TLSKeyFile and TLSCAFile are mandatory' 432 | 433 | @mock.patch('configobj.ConfigObj') 434 | def test_tls_connect_cert_tls_cert_key_custom(mock_configobj): 435 | """ 436 | TLSConnect: 'cert' 437 | TLSCertFile set 438 | TLSKeyFile set 439 | """ 440 | mock_configobj.side_effect = [ 441 | { 442 | 'TLSConnect': 'cert', 443 | 'TLSCertFile': '/tmp/tls_cert_file.pem', 444 | 'TLSKeyFile': '/tmp/tls_key_file.pem', 445 | 'TLSCAFile': '/tmp/tls_ca_file.pem', 446 | } 447 | ] 448 | zbx_config = protobix.ZabbixAgentConfig('TLSConnect_TLSCertFile_TLSKeyFile') 449 | assert zbx_config.tls_connect == 'cert' 450 | assert zbx_config.tls_cert_file == '/tmp/tls_cert_file.pem' 451 | assert zbx_config.tls_key_file == '/tmp/tls_key_file.pem' 452 | assert zbx_config.tls_ca_file == '/tmp/tls_ca_file.pem' 453 | 454 | 455 | @mock.patch('configobj.ConfigObj') 456 | def test_tls_connect_cert_other_custom(mock_configobj): 457 | """ 458 | TLSConnect: 'cert' 459 | Other TLS params custom 460 | """ 461 | mock_configobj.side_effect = [ 462 | { 463 | 'TLSConnect': 'cert', 464 | 'TLSCAFile': '/tmp/tls_ca_file.crt', 465 | 'TLSCertFile': '/tmp/tls_cert_file.crt', 466 | 'TLSCRLFile': '/tmp/tls_crl_file.crt', 467 | 'TLSKeyFile': '/tmp/tls_key_file.crt', 468 | 'TLSServerCertIssuer': '/tmp/tls_server__cert_issuer.crt', 469 | 'TLSServerCertSubject': '/tmp/tls_server_cert_subject.crt', 470 | } 471 | ] 472 | zbx_config = protobix.ZabbixAgentConfig('TLSConnect_TLSCertFile_TLSKeyFile') 473 | assert zbx_config.tls_connect == 'cert' 474 | assert zbx_config.tls_ca_file == '/tmp/tls_ca_file.crt' 475 | assert zbx_config.tls_cert_file == '/tmp/tls_cert_file.crt' 476 | assert zbx_config.tls_crl_file == '/tmp/tls_crl_file.crt' 477 | assert zbx_config.tls_key_file == '/tmp/tls_key_file.crt' 478 | assert zbx_config.tls_server_cert_issuer == '/tmp/tls_server__cert_issuer.crt' 479 | assert zbx_config.tls_server_cert_subject == '/tmp/tls_server_cert_subject.crt' 480 | 481 | @mock.patch('configobj.ConfigObj') 482 | def test_tls_connect_invalid(mock_configobj): 483 | """ 484 | invalid TLSConnect 485 | Should raise a ValueError with appropriate message 486 | """ 487 | mock_configobj.side_effect = [ 488 | { 489 | 'TLSConnect': 'invalid', 490 | } 491 | ] 492 | with pytest.raises(ValueError) as err: 493 | protobix.ZabbixAgentConfig('TLSConnect_invalid') 494 | assert str(err.value) == 'TLSConnect must be one of [unencrypted,psk,cert]' 495 | 496 | @mock.patch('configobj.ConfigObj') 497 | def test_tls_connect_psk_tls_msk_identity_file_missing(mock_configobj): 498 | """ 499 | TLSConnect: 'psk' 500 | Should raise a NotImplementedError with appropriate message 501 | """ 502 | mock_configobj.side_effect = [ 503 | { 504 | 'TLSConnect': 'psk' 505 | } 506 | ] 507 | with pytest.raises(ValueError) as err: 508 | protobix.ZabbixAgentConfig('TLSConnect_psk') 509 | assert str(err.value) == 'TLSConnect is psk. TLSPSKIdentity and TLSPSKFile are mandatory' 510 | 511 | @mock.patch('configobj.ConfigObj') 512 | def test_tls_connect_psk(mock_configobj): 513 | """ 514 | TLSConnect: 'psk' 515 | Should raise a NotImplementedError with appropriate message 516 | """ 517 | mock_configobj.side_effect = [ 518 | { 519 | 'TLSConnect': 'psk', 520 | 'TLSPSKIdentity': 'TLS PSK Zabbix Identity', 521 | 'TLSPSKFile': '/tmp/psk.file', 522 | } 523 | ] 524 | zbx_config = protobix.ZabbixAgentConfig('TLSConnect_psk') 525 | assert zbx_config.tls_psk_identity == 'TLS PSK Zabbix Identity' 526 | assert zbx_config.tls_psk_file == '/tmp/psk.file' 527 | 528 | @mock.patch('configobj.ConfigObj') 529 | def test_data_type(mock_configobj): 530 | """ 531 | Test data_type. Default is None 532 | """ 533 | mock_configobj.side_effect = [{}] 534 | zbx_config = protobix.ZabbixAgentConfig('default_configuration') 535 | assert zbx_config.data_type is None 536 | zbx_config.data_type = 'items' 537 | assert zbx_config.data_type == 'items' 538 | zbx_config.data_type = 'lld' 539 | assert zbx_config.data_type == 'lld' 540 | 541 | @mock.patch('configobj.ConfigObj') 542 | def test_data_type_invalid(mock_configobj): 543 | """ 544 | Test data_type with invalid value 545 | """ 546 | mock_configobj.side_effect = [{}] 547 | zbx_config = protobix.ZabbixAgentConfig('default_configuration') 548 | assert zbx_config.data_type is None 549 | with pytest.raises(ValueError) as err: 550 | zbx_config.data_type = 'invalid' 551 | assert str(err.value) == 'data_type requires either "items" or "lld"' 552 | assert zbx_config.data_type is None 553 | 554 | @mock.patch('configobj.ConfigObj') 555 | def test_dryrun(mock_configobj): 556 | """ 557 | Test dryrun. Default is False 558 | """ 559 | mock_configobj.side_effect = [{}] 560 | zbx_config = protobix.ZabbixAgentConfig('default_configuration') 561 | assert zbx_config.dryrun is False 562 | zbx_config.dryrun = True 563 | assert zbx_config.dryrun is True 564 | 565 | @mock.patch('configobj.ConfigObj') 566 | def test_dryrun_invalid(mock_configobj): 567 | """ 568 | Test dryrun with invalid value 569 | """ 570 | mock_configobj.side_effect = [{}] 571 | zbx_config = protobix.ZabbixAgentConfig('default_configuration') 572 | assert zbx_config.dryrun is False 573 | with pytest.raises(ValueError) as err: 574 | zbx_config.dryrun = 'invalid' 575 | assert str(err.value) == 'dryrun parameter requires boolean' 576 | assert zbx_config.dryrun is False 577 | -------------------------------------------------------------------------------- /tests/test_sampleprobe.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test Protobix sampleprobe 3 | """ 4 | import configobj 5 | import pytest 6 | import mock 7 | import unittest 8 | import socket 9 | 10 | import resource 11 | import time 12 | import sys 13 | import os 14 | 15 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 16 | import protobix 17 | import logging 18 | import argparse 19 | 20 | # Zabbix force TLSv1.2 protocol 21 | # in src/libs/zbxcrypto/tls.c function zbx_tls_init_child 22 | HAVE_DECENT_SSL = False 23 | if sys.version_info > (2,7,9): 24 | import ssl 25 | HAVE_DECENT_SSL = True 26 | 27 | class ProtobixTestProbe(protobix.SampleProbe): 28 | __version__="1.0.2" 29 | 30 | def _get_metrics(self): 31 | return { 32 | "protobix.host1": { 33 | "my.protobix.item.int": 0, 34 | "my.protobix.item.string": "item string" 35 | }, 36 | "protobix.host2": { 37 | "my.protobix.item.int": 0, 38 | "my.protobix.item.string": "item string" 39 | } 40 | } 41 | 42 | def _get_discovery(self): 43 | return { 44 | 'protobix.host1': { 45 | 'my.protobix.lld_item1': [ 46 | { '{#PBX_LLD_KEY11}': 0, 47 | '{#PBX_LLD_KEY12}': 'lld string' }, 48 | { '{#PBX_LLD_KEY11}': 1, 49 | '{#PBX_LLD_KEY12}': 'another lld string' } 50 | ], 51 | 'my.protobix.lld_item2': [ 52 | { '{#PBX_LLD_KEY21}': 10, 53 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 54 | { '{#PBX_LLD_KEY21}': 2, 55 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 56 | ] 57 | }, 58 | 'protobix.host2': { 59 | 'my.protobix.lld_item1': [ 60 | { '{#PBX_LLD_KEY11}': 0, 61 | '{#PBX_LLD_KEY12}': 'lld string' }, 62 | { '{#PBX_LLD_KEY11}': 1, 63 | '{#PBX_LLD_KEY12}': 'another lld string' } 64 | ], 65 | 'my.protobix.lld_item2': [ 66 | { '{#PBX_LLD_KEY21}': 10, 67 | '{#PBX_LLD_KEY21}': 'yet an lld string' }, 68 | { '{#PBX_LLD_KEY21}': 2, 69 | '{#PBX_LLD_KEY21}': 'yet another lld string' } 70 | ] 71 | } 72 | } 73 | 74 | class ProtobixTLSTestProbe(ProtobixTestProbe): 75 | 76 | def run(self, options=None): 77 | # Init logging with default values since we don't have real config yet 78 | self._init_logging() 79 | # Parse command line options 80 | args = sys.argv[1:] 81 | if isinstance(options, list): 82 | args = options 83 | self.options = self._parse_args(args) 84 | 85 | # Get configuration 86 | self.zbx_config = self._init_config() 87 | 88 | # Update logger with configuration 89 | self._setup_logging( 90 | self.zbx_config.log_type, 91 | self.zbx_config.debug_level, 92 | self.zbx_config.log_file 93 | ) 94 | 95 | # Datacontainer init 96 | zbx_container = protobix.DataContainer( 97 | config = self.zbx_config, 98 | logger=self.logger 99 | ) 100 | # Get back hostname from ZabbixAgentConfig 101 | self.hostname = self.zbx_config.hostname 102 | 103 | # Step 1: read probe configuration 104 | # initialize any needed object or connection 105 | self._init_probe() 106 | 107 | # Step 2: get data 108 | data = {} 109 | if self.options.probe_mode == "update": 110 | zbx_container.data_type = 'items' 111 | data = self._get_metrics() 112 | elif self.options.probe_mode == "discovery": 113 | zbx_container.data_type = 'lld' 114 | data = self._get_discovery() 115 | 116 | # Step 3: add data to container 117 | zbx_container.add(data) 118 | 119 | # Step 4: send data to Zabbix server 120 | server_success, server_failure, processed, failed, total, time = zbx_container.send() 121 | return server_success, server_failure, processed, failed, total, time 122 | 123 | class ProtobixTestProbe2(protobix.SampleProbe): 124 | __version__="1.0.2" 125 | 126 | """ 127 | Check default configuration of the sample probe 128 | """ 129 | def test_default_configuration(): 130 | pbx_test_probe = ProtobixTestProbe() 131 | pbx_test_probe.options = pbx_test_probe._parse_args([]) 132 | assert pbx_test_probe.options.config_file is None 133 | assert pbx_test_probe.options.debug_level is None 134 | assert pbx_test_probe.options.discovery is False 135 | assert pbx_test_probe.options.dryrun is False 136 | assert pbx_test_probe.options.update is False 137 | assert pbx_test_probe.options.server_port is None 138 | assert pbx_test_probe.options.server_active is None 139 | 140 | """ 141 | Check --update-items argument 142 | """ 143 | def test_command_line_option_update_items(): 144 | pbx_test_probe = ProtobixTestProbe() 145 | pbx_test_probe.options = pbx_test_probe._parse_args(['--update-items']) 146 | pbx_config = pbx_test_probe._init_config() 147 | assert pbx_test_probe.options.discovery is False 148 | assert pbx_test_probe.options.update is True 149 | assert pbx_test_probe.options.probe_mode == 'update' 150 | 151 | """ 152 | Check --discovery argument 153 | """ 154 | def test_command_line_option_discovery(): 155 | pbx_test_probe = ProtobixTestProbe() 156 | pbx_test_probe.options = pbx_test_probe._parse_args(['--discovery']) 157 | pbx_config = pbx_test_probe._init_config() 158 | assert pbx_test_probe.options.discovery is True 159 | assert pbx_test_probe.options.update is False 160 | assert pbx_test_probe.options.probe_mode == 'discovery' 161 | 162 | """ 163 | Check exception when providing both --update-items & --discovery arguments 164 | """ 165 | def test_force_both_discovery_and_update(): 166 | pbx_test_probe = ProtobixTestProbe() 167 | with pytest.raises(ValueError): 168 | result = pbx_test_probe.run(['--discovery', '--update-items']) 169 | 170 | """ 171 | Check -v argument. Used to set logger log level 172 | """ 173 | def test_force_verbosity(): 174 | pbx_test_probe = ProtobixTestProbe() 175 | pbx_test_probe.options = pbx_test_probe._parse_args(['-vvvv']) 176 | pbx_config = pbx_test_probe._init_config() 177 | assert pbx_test_probe.options.debug_level == 4 178 | pbx_test_probe.options = pbx_test_probe._parse_args(['-vv']) 179 | pbx_config = pbx_test_probe._init_config() 180 | assert pbx_test_probe.options.debug_level == 2 181 | pbx_test_probe.options = pbx_test_probe._parse_args(['-vvvvvvvvv']) 182 | assert pbx_test_probe.options.debug_level == 9 183 | pbx_config = pbx_test_probe._init_config() 184 | assert pbx_config.debug_level == 4 185 | 186 | """ 187 | Check -d & --dryrun argument. 188 | """ 189 | def test_force_dryrun(): 190 | pbx_test_probe = ProtobixTestProbe() 191 | pbx_test_probe.options = pbx_test_probe._parse_args(['--dryrun']) 192 | pbx_config = pbx_test_probe._init_config() 193 | assert pbx_test_probe.options.dryrun is True 194 | pbx_test_probe.options = pbx_test_probe._parse_args(['-d']) 195 | pbx_config = pbx_test_probe._init_config() 196 | assert pbx_test_probe.options.dryrun is True 197 | 198 | """ 199 | Check -z & --zabbix-server argument. 200 | """ 201 | def test_command_line_option_zabbix_server(): 202 | pbx_test_probe = ProtobixTestProbe() 203 | pbx_test_probe.options = pbx_test_probe._parse_args(['--zabbix-server', '192.168.0.1']) 204 | pbx_config = pbx_test_probe._init_config() 205 | assert pbx_config.server_active == '192.168.0.1' 206 | pbx_test_probe.options = pbx_test_probe._parse_args(['-z', '192.168.0.2']) 207 | pbx_config = pbx_test_probe._init_config() 208 | assert pbx_config.server_active == '192.168.0.2' 209 | 210 | """ 211 | Check -p & --port argument. 212 | """ 213 | def test_command_line_option_port(): 214 | pbx_test_probe = ProtobixTestProbe() 215 | pbx_test_probe.options = pbx_test_probe._parse_args(['--port', '10052']) 216 | pbx_config = pbx_test_probe._init_config() 217 | assert pbx_config.server_port == 10052 218 | pbx_test_probe.options = pbx_test_probe._parse_args(['-p', '10060']) 219 | pbx_config = pbx_test_probe._init_config() 220 | assert pbx_config.server_port == 10060 221 | 222 | """ 223 | Check --tls-cert-file argument. 224 | """ 225 | def test_command_line_option_tls_cert_file(): 226 | pbx_test_probe = ProtobixTestProbe() 227 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-cert-file', '/tmp/test_file.crt']) 228 | pbx_config = pbx_test_probe._init_config() 229 | assert pbx_config.tls_cert_file == '/tmp/test_file.crt' 230 | 231 | """ 232 | Check --tls-key-file argument. 233 | """ 234 | def test_command_line_option_tls_key_file(): 235 | pbx_test_probe = ProtobixTestProbe() 236 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-key-file', '/tmp/test_file.key']) 237 | pbx_config = pbx_test_probe._init_config() 238 | assert pbx_config.tls_key_file == '/tmp/test_file.key' 239 | 240 | """ 241 | Check --tls-ca-file argument. 242 | """ 243 | def test_command_line_option_tls_ca_file(): 244 | pbx_test_probe = ProtobixTestProbe() 245 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-ca-file', '/tmp/test_ca_file.crt']) 246 | pbx_config = pbx_test_probe._init_config() 247 | assert pbx_config.tls_ca_file == '/tmp/test_ca_file.crt' 248 | 249 | """ 250 | Check --tls-crl-file argument. 251 | """ 252 | def test_command_line_option_tls_crl_file(): 253 | pbx_test_probe = ProtobixTestProbe() 254 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-crl-file', '/tmp/test_file.crl']) 255 | pbx_config = pbx_test_probe._init_config() 256 | assert pbx_config.tls_crl_file == '/tmp/test_file.crl' 257 | 258 | """ 259 | Check --tls-psk-file argument. 260 | """ 261 | def test_command_line_option_tls_psk_file(): 262 | pbx_test_probe = ProtobixTestProbe() 263 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-psk-file', '/tmp/test_file.psk']) 264 | pbx_config = pbx_test_probe._init_config() 265 | assert pbx_config.tls_psk_file == '/tmp/test_file.psk' 266 | 267 | """ 268 | Check --tls-psk-identity argument. 269 | """ 270 | def test_command_line_option_tls_psk_identity(): 271 | pbx_test_probe = ProtobixTestProbe() 272 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-psk-identity', 'Zabbix TLS/PSK identity']) 273 | pbx_config = pbx_test_probe._init_config() 274 | assert pbx_config.tls_psk_identity == 'Zabbix TLS/PSK identity' 275 | 276 | """ 277 | Check --tls-server-cert-issuer argument. 278 | """ 279 | def test_command_line_option_tls_server_cert_issuer(): 280 | pbx_test_probe = ProtobixTestProbe() 281 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-server-cert-issuer', 'Zabbix TLS cert issuer']) 282 | pbx_config = pbx_test_probe._init_config() 283 | assert pbx_config.tls_server_cert_issuer == 'Zabbix TLS cert issuer' 284 | 285 | """ 286 | Check --tls-server-cert-subject argument. 287 | """ 288 | def test_command_line_option_tls_server_cert_subject(): 289 | pbx_test_probe = ProtobixTestProbe() 290 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-server-cert-subject', 'Zabbix TLS cert subject']) 291 | pbx_config = pbx_test_probe._init_config() 292 | assert pbx_config.tls_server_cert_subject == 'Zabbix TLS cert subject' 293 | 294 | """ 295 | Check --tls-connect argument. 296 | """ 297 | def test_command_line_option_tls_connect(): 298 | pbx_test_probe = ProtobixTestProbe() 299 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-connect', 'cert']) 300 | pbx_config = pbx_test_probe._init_config() 301 | assert pbx_config.tls_connect == 'cert' 302 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-connect', 'psk']) 303 | pbx_config = pbx_test_probe._init_config() 304 | assert pbx_config.tls_connect == 'psk' 305 | pbx_test_probe.options = pbx_test_probe._parse_args(['--tls-connect', 'unencrypted']) 306 | pbx_config = pbx_test_probe._init_config() 307 | assert pbx_config.tls_connect == 'unencrypted' 308 | 309 | """ 310 | Check logger configuration in console mode 311 | """ 312 | def test_log_console(): 313 | pbx_test_probe = ProtobixTestProbe() 314 | pbx_test_probe._init_logging() 315 | assert isinstance(pbx_test_probe.logger, logging.Logger) 316 | pbx_test_probe._setup_logging('console', 4, '/tmp/log_file') 317 | assert len(pbx_test_probe.logger.handlers) == 1 318 | assert pbx_test_probe.logger.level == logging.DEBUG 319 | assert isinstance(pbx_test_probe.logger.handlers[0], logging.StreamHandler) 320 | 321 | """ 322 | Check logger configuration in file mode & debug 323 | """ 324 | def test_log_file(): 325 | pbx_test_probe = ProtobixTestProbe() 326 | pbx_test_probe._init_logging() 327 | assert isinstance(pbx_test_probe.logger, logging.Logger) 328 | pbx_test_probe._setup_logging('file', 4, '/tmp/log_file') 329 | assert len(pbx_test_probe.logger.handlers) == 1 330 | assert pbx_test_probe.logger.level == logging.DEBUG 331 | assert isinstance(pbx_test_probe.logger.handlers[0], logging.FileHandler) 332 | 333 | """ 334 | Check logger configuration in file mode with invalid file 335 | Here, invalid means that it doesn't exists, or we don't have 336 | permission to write into 337 | """ 338 | def test_log_file_invalid(): 339 | pbx_test_probe = ProtobixTestProbe() 340 | pbx_test_probe._init_logging() 341 | assert isinstance(pbx_test_probe.logger, logging.Logger) 342 | with pytest.raises(IOError): 343 | pbx_test_probe._setup_logging('file', 4, '/do_not_have_permission') 344 | assert pbx_test_probe.logger.level == logging.NOTSET 345 | assert len(pbx_test_probe.logger.handlers) == 0 346 | 347 | """ 348 | Check logger configuration in system (syslog) mode 349 | """ 350 | def test_log_syslog(): 351 | pbx_test_probe = ProtobixTestProbe() 352 | pbx_test_probe._init_logging() 353 | assert isinstance(pbx_test_probe.logger, logging.Logger) 354 | pbx_test_probe._setup_logging('system', 3, None) 355 | assert len(pbx_test_probe.logger.handlers) == 1 356 | assert pbx_test_probe.logger.level == logging.INFO 357 | assert isinstance(pbx_test_probe.logger.handlers[0], logging.handlers.SysLogHandler) 358 | 359 | """ 360 | Check a custom probe without _get_metrics method. 361 | """ 362 | def test_not_implemented_get_metrics(): 363 | pbx_test_probe = ProtobixTestProbe2() 364 | with pytest.raises(NotImplementedError): 365 | pbx_test_probe.run([]) 366 | 367 | """ 368 | Check a custom probe without _get_discovery method. 369 | """ 370 | def test_not_implemented_get_discovery(): 371 | pbx_test_probe = ProtobixTestProbe2() 372 | with pytest.raises(NotImplementedError): 373 | pbx_test_probe.run(['--discovery']) 374 | 375 | """ 376 | Check that sample probe correctly catches exception from _init_probe 377 | """ 378 | def test_init_probe_exception(): 379 | pbx_test_probe = ProtobixTestProbe2() 380 | with mock.patch('protobix.SampleProbe._init_probe') as mock_init_probe: 381 | mock_init_probe.side_effect = Exception('Something went wrong') 382 | result = pbx_test_probe.run([]) 383 | assert result == 1 384 | 385 | """ 386 | Check that sample probe correctly catches exception from _get_metrics 387 | """ 388 | def test_get_metrics_exception(): 389 | pbx_test_probe = ProtobixTestProbe2() 390 | with mock.patch('protobix.SampleProbe._get_metrics') as mock_get_metrics: 391 | mock_get_metrics.side_effect = Exception('Something went wrong in _get_metrics') 392 | result = pbx_test_probe.run([]) 393 | assert result == 2 394 | 395 | """ 396 | Check that sample probe correctly catches exception from _get_discovery 397 | """ 398 | def test_get_discovery_exception(): 399 | pbx_test_probe = ProtobixTestProbe2() 400 | with mock.patch('protobix.SampleProbe._get_discovery') as mock_get_discovery: 401 | mock_get_discovery.side_effect = Exception('Something went wrong in _get_discovery') 402 | result = pbx_test_probe.run(['--discovery']) 403 | assert result == 2 404 | 405 | """ 406 | Check that sample probe correctly catches exception from DataContainer add method 407 | """ 408 | def test_datacontainer_add_exception(): 409 | pbx_test_probe = ProtobixTestProbe() 410 | with mock.patch('protobix.DataContainer.add') as mock_datacontainer_add: 411 | mock_datacontainer_add.side_effect = Exception('Something went wrong in DataContainer.add') 412 | result = pbx_test_probe.run([]) 413 | assert result == 3 414 | 415 | """ 416 | Check that sample probe correctly catches exception from DataContainer send method 417 | """ 418 | def test_datacontainer_send_exception(): 419 | pbx_test_probe = ProtobixTestProbe() 420 | with mock.patch('protobix.DataContainer.send') as mock_datacontainer_send: 421 | mock_datacontainer_send.side_effect = Exception('Another something went wrong') 422 | result = pbx_test_probe.run([]) 423 | assert result == 4 424 | 425 | """ 426 | Check that sample probe correctly catches socket exception from DataContainer send method 427 | """ 428 | def test_datacontainer_send_socket_error(): 429 | pbx_test_probe = ProtobixTestProbe() 430 | with mock.patch('protobix.DataContainer.send') as mock_datacontainer_send: 431 | mock_datacontainer_send.side_effect = socket.error 432 | result = pbx_test_probe.run([]) 433 | assert result == 4 434 | 435 | """ 436 | Check return 0 when everything is fine 437 | """ 438 | def test_everything_runs_fine(): 439 | pbx_test_probe = ProtobixTestProbe() 440 | with mock.patch('protobix.DataContainer.send') as mock_datacontainer_send: 441 | mock_datacontainer_send.side_effect = None 442 | result = pbx_test_probe.run([]) 443 | assert result == 0 444 | 445 | if HAVE_DECENT_SSL is True: 446 | 447 | """ 448 | Check sending data with or without TLS with debug disabled 449 | """ 450 | pytest_matrix = ( 451 | ('items', False, False), 452 | ('lld', False, False), 453 | ('items', True, False), 454 | ('lld', True, False), 455 | ('items', False, True), 456 | ('lld', False, True), 457 | ('items', True, True), 458 | ('lld', True, True), 459 | ) 460 | @pytest.mark.parametrize('data_type,tls_enabled,tls_crl_enabled', pytest_matrix) 461 | def test_need_backend_tls_cert(data_type, tls_enabled, tls_crl_enabled): 462 | params = [] 463 | if tls_enabled: 464 | params = [ 465 | '--tls-connect', 'cert', 466 | '--tls-ca-file', 'tests/tls_ca/rogue-protobix-ca.cert.pem', 467 | '--tls-cert-file', 'tests/tls_ca/rogue-protobix-client.cert.pem', 468 | '--tls-key-file', 'tests/tls_ca/rogue-protobix-client.key.pem', 469 | ] 470 | if tls_crl_enabled: 471 | params.append('--tls-crl-file') 472 | params.append('tests/tls_ca/rogue-protobix.crl') 473 | params.append('--update' if data_type == 'items' else '--discovery') 474 | params.append('-vvv') 475 | pbx_test_probe = ProtobixTLSTestProbe() 476 | server_success, server_failure, processed, failed, total, time = pbx_test_probe.run(params) 477 | if tls_enabled is False: 478 | assert server_success == 1 479 | assert server_failure == 0 480 | assert processed == 4 481 | assert failed == 0 482 | assert total == 4 483 | else: 484 | # protobix.host1 does NOT have TLS enabled 485 | # therefore items sent on behalf of protobix.host1 must fail 486 | assert server_success == 1 487 | assert server_failure == 0 488 | assert processed == 2 489 | assert failed == 2 490 | assert total == 4 491 | 492 | """ 493 | Check sending data with or without TLS with debug enabled 494 | """ 495 | pytest_matrix = ( 496 | ('items', False, False), 497 | ('lld', False, False), 498 | ('items', True, False), 499 | ('lld', True, False), 500 | ('items', False, True), 501 | ('lld', False, True), 502 | ('items', True, True), 503 | ('lld', True, True), 504 | ) 505 | @pytest.mark.parametrize('data_type,tls_enabled,tls_crl_enabled', pytest_matrix) 506 | def test_need_backend_tls_cert_debug(data_type, tls_enabled, tls_crl_enabled): 507 | params = [] 508 | if tls_enabled: 509 | params = [ 510 | '--tls-connect', 'cert', 511 | '--tls-ca-file', 'tests/tls_ca/rogue-protobix-ca.cert.pem', 512 | '--tls-cert-file', 'tests/tls_ca/rogue-protobix-client.cert.pem', 513 | '--tls-key-file', 'tests/tls_ca/rogue-protobix-client.key.pem', 514 | ] 515 | if tls_crl_enabled: 516 | params.append('--tls-crl-file') 517 | params.append('tests/tls_ca/rogue-protobix.crl') 518 | params.append('--update' if data_type == 'items' else '--discovery') 519 | params.append('-vvvvv') 520 | pbx_test_probe = ProtobixTLSTestProbe() 521 | server_success, server_failure, processed, failed, total, time = pbx_test_probe.run(params) 522 | if tls_enabled is False: 523 | assert server_success == 4 524 | assert server_failure == 0 525 | assert processed == 4 526 | assert failed == 0 527 | assert total == 4 528 | else: 529 | # protobix.host1 does NOT have TLS enabled 530 | # therefore items sent on behalf of protobix.host1 must fail 531 | assert server_success == 4 532 | assert server_failure == 0 533 | assert processed == 2 534 | assert failed == 2 535 | assert total == 4 536 | 537 | """ 538 | Check sending data with or without TLS with debug disabled 539 | """ 540 | pytest_matrix = ( 541 | ('items', False, False), 542 | ('lld', False, False), 543 | ('items', True, False), 544 | ('lld', True, False), 545 | ('items', False, True), 546 | ('lld', False, True), 547 | ('items', True, True), 548 | ('lld', True, True), 549 | ) 550 | @pytest.mark.parametrize('data_type,tls_enabled,tls_crl_enabled', pytest_matrix) 551 | def test_need_backend_tls_cert_invalid(data_type, tls_enabled, tls_crl_enabled): 552 | params = [] 553 | if tls_enabled: 554 | params = [ 555 | '--tls-connect', 'cert', 556 | '--tls-ca-file', 'tests/tls_ca/protobix-ca.cert.pem', 557 | '--tls-cert-file', 'tests/tls_ca/protobix-client.cert.pem', 558 | '--tls-key-file', 'tests/tls_ca/protobix-client.key.pem', 559 | ] 560 | if tls_crl_enabled: 561 | params.append('--tls-crl-file') 562 | params.append('tests/tls_ca/protobix.crl') 563 | params.append('--update' if data_type == 'items' else '--discovery') 564 | params.append('-vvv') 565 | pbx_test_probe = ProtobixTLSTestProbe() 566 | if tls_enabled is True: 567 | with pytest.raises(ssl.SSLError) as err: 568 | pbx_test_probe.run(params) 569 | else: 570 | server_success, server_failure, processed, failed, total, time = pbx_test_probe.run(params) 571 | assert server_success == 1 572 | assert server_failure == 0 573 | assert processed == 4 574 | assert failed == 0 575 | assert total == 4 576 | 577 | """ 578 | Check sending data with or without TLS with debug enabled 579 | """ 580 | pytest_matrix = ( 581 | ('items', False, False), 582 | ('lld', False, False), 583 | ('items', True, False), 584 | ('lld', True, False), 585 | ('items', False, True), 586 | ('lld', False, True), 587 | ('items', True, True), 588 | ('lld', True, True), 589 | ) 590 | @pytest.mark.parametrize('data_type,tls_enabled,tls_crl_enabled', pytest_matrix) 591 | def test_need_backend_tls_cert_invalid_debug(data_type, tls_enabled, tls_crl_enabled): 592 | params = [] 593 | if tls_enabled: 594 | params = [ 595 | '--tls-connect', 'cert', 596 | '--tls-ca-file', 'tests/tls_ca/protobix-ca.cert.pem', 597 | '--tls-cert-file', 'tests/tls_ca/protobix-client.cert.pem', 598 | '--tls-key-file', 'tests/tls_ca/protobix-client.key.pem', 599 | ] 600 | if tls_crl_enabled: 601 | params.append('--tls-crl-file') 602 | params.append('tests/tls_ca/protobix.crl') 603 | params.append('--update' if data_type == 'items' else '--discovery') 604 | params.append('-vvvvv') 605 | pbx_test_probe = ProtobixTLSTestProbe() 606 | if tls_enabled is True: 607 | with pytest.raises(ssl.SSLError) as err: 608 | pbx_test_probe.run(params) 609 | else: 610 | server_success, server_failure, processed, failed, total, time = pbx_test_probe.run(params) 611 | assert server_success == 4 612 | assert server_failure == 0 613 | assert processed == 4 614 | assert failed == 0 615 | assert total == 4 616 | --------------------------------------------------------------------------------