|
@@ -0,0 +1,188 @@
|
|
|
|
|
+import json
|
|
|
|
|
+import urllib.request
|
|
|
|
|
+
|
|
|
|
|
+ZABBIX_URL = 'http://192.168.130.170:8081/api_jsonrpc.php'
|
|
|
|
|
+ZABBIX_USER = 'Admin'
|
|
|
|
|
+ZABBIX_PASS = 'zabbix'
|
|
|
|
|
+DISCORD_WEBHOOK = 'https://discord.com/api/webhooks/1504740323576774739/2-MNclIGcYSxtLrQ-jzIXWl6miW3dOFTvB6KZsTQIX1FFis6JFoszATegAJoosJD7CMT'
|
|
|
|
|
+EMAIL_USER = 'lanfr144@gmail.com'
|
|
|
|
|
+EMAIL_PASS = '321iaSTB'
|
|
|
|
|
+
|
|
|
|
|
+def zabbix_request(method, params, auth=None):
|
|
|
|
|
+ payload = {
|
|
|
|
|
+ 'jsonrpc': '2.0',
|
|
|
|
|
+ 'method': method,
|
|
|
|
|
+ 'params': params,
|
|
|
|
|
+ 'id': 1
|
|
|
|
|
+ }
|
|
|
|
|
+ if auth:
|
|
|
|
|
+ payload['auth'] = auth
|
|
|
|
|
+
|
|
|
|
|
+ req = urllib.request.Request(ZABBIX_URL, data=json.dumps(payload).encode('utf-8'), headers={'Content-Type': 'application/json-rpc'})
|
|
|
|
|
+ with urllib.request.urlopen(req) as response:
|
|
|
|
|
+ res = json.loads(response.read().decode('utf-8'))
|
|
|
|
|
+ if 'error' in res:
|
|
|
|
|
+ print(f"Error in {method}: {res['error']}")
|
|
|
|
|
+ return None
|
|
|
|
|
+ return res['result']
|
|
|
|
|
+
|
|
|
|
|
+def main():
|
|
|
|
|
+ # 1. Login
|
|
|
|
|
+ auth_token = zabbix_request('user.login', {'username': ZABBIX_USER, 'password': ZABBIX_PASS})
|
|
|
|
|
+ if not auth_token:
|
|
|
|
|
+ print("Login failed")
|
|
|
|
|
+ return
|
|
|
|
|
+ print("Zabbix Auth Token:", auth_token)
|
|
|
|
|
+
|
|
|
|
|
+ # 2. Configure Email Media Type
|
|
|
|
|
+ # Find existing Email media type (type 0 = Email)
|
|
|
|
|
+ email_mt = zabbix_request('mediatype.get', {'filter': {'type': '0'}}, auth_token)
|
|
|
|
|
+ email_params = {
|
|
|
|
|
+ 'type': '0',
|
|
|
|
|
+ 'name': 'Email',
|
|
|
|
|
+ 'smtp_server': 'smtp.gmail.com',
|
|
|
|
|
+ 'smtp_port': '587',
|
|
|
|
|
+ 'smtp_helo': 'gmail.com',
|
|
|
|
|
+ 'smtp_email': EMAIL_USER,
|
|
|
|
|
+ 'smtp_security': '1', # STARTTLS
|
|
|
|
|
+ 'smtp_verify_peer': '0',
|
|
|
|
|
+ 'smtp_verify_host': '0',
|
|
|
|
|
+ 'smtp_authentication': '1',
|
|
|
|
|
+ 'username': EMAIL_USER,
|
|
|
|
|
+ 'passwd': EMAIL_PASS,
|
|
|
|
|
+ 'content_type': '1' # HTML
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if email_mt:
|
|
|
|
|
+ email_params['mediatypeid'] = email_mt[0]['mediatypeid']
|
|
|
|
|
+ zabbix_request('mediatype.update', email_params, auth_token)
|
|
|
|
|
+ print("Updated Email Media Type")
|
|
|
|
|
+ email_id = email_mt[0]['mediatypeid']
|
|
|
|
|
+ else:
|
|
|
|
|
+ res = zabbix_request('mediatype.create', email_params, auth_token)
|
|
|
|
|
+ email_id = res['mediatypeids'][0]
|
|
|
|
|
+ print("Created Email Media Type")
|
|
|
|
|
+
|
|
|
|
|
+ # 3. Configure Discord Media Type (type 4 = Webhook)
|
|
|
|
|
+ discord_script = """
|
|
|
|
|
+ var req = new HttpRequest();
|
|
|
|
|
+ req.addHeader('Content-Type: application/json');
|
|
|
|
|
+ var webhook = params.URL;
|
|
|
|
|
+ var payload = JSON.stringify({
|
|
|
|
|
+ "content": params.Subject + "\\n" + params.Message
|
|
|
|
|
+ });
|
|
|
|
|
+ var resp = req.post(webhook, payload);
|
|
|
|
|
+ if (req.getStatus() != 204 && req.getStatus() != 200) {
|
|
|
|
|
+ throw 'Failed with status ' + req.getStatus();
|
|
|
|
|
+ }
|
|
|
|
|
+ return 'OK';
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ discord_mt = zabbix_request('mediatype.get', {'filter': {'name': 'Discord Webhook'}}, auth_token)
|
|
|
|
|
+ discord_params = {
|
|
|
|
|
+ 'name': 'Discord Webhook',
|
|
|
|
|
+ 'type': '4',
|
|
|
|
|
+ 'parameters': [
|
|
|
|
|
+ {'name': 'URL', 'value': DISCORD_WEBHOOK},
|
|
|
|
|
+ {'name': 'Subject', 'value': '{ALERT.SUBJECT}'},
|
|
|
|
|
+ {'name': 'Message', 'value': '{ALERT.MESSAGE}'}
|
|
|
|
|
+ ],
|
|
|
|
|
+ 'script': discord_script,
|
|
|
|
|
+ 'process_tags': '0'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if discord_mt:
|
|
|
|
|
+ discord_params['mediatypeid'] = discord_mt[0]['mediatypeid']
|
|
|
|
|
+ zabbix_request('mediatype.update', discord_params, auth_token)
|
|
|
|
|
+ print("Updated Discord Media Type")
|
|
|
|
|
+ discord_id = discord_mt[0]['mediatypeid']
|
|
|
|
|
+ else:
|
|
|
|
|
+ res = zabbix_request('mediatype.create', discord_params, auth_token)
|
|
|
|
|
+ discord_id = res['mediatypeids'][0]
|
|
|
|
|
+ print("Created Discord Media Type")
|
|
|
|
|
+
|
|
|
|
|
+ # 4. Update Admin User Media
|
|
|
|
|
+ users = zabbix_request('user.get', {'filter': {'username': 'Admin'}, 'selectMedias': 'extend'}, auth_token)
|
|
|
|
|
+ if users:
|
|
|
|
|
+ admin_id = users[0]['userid']
|
|
|
|
|
+ medias = [
|
|
|
|
|
+ {'mediatypeid': email_id, 'sendto': [EMAIL_USER], 'active': 0, 'severity': 63, 'period': '1-7,00:00-24:00'},
|
|
|
|
|
+ {'mediatypeid': discord_id, 'sendto': ['Discord'], 'active': 0, 'severity': 63, 'period': '1-7,00:00-24:00'}
|
|
|
|
|
+ ]
|
|
|
|
|
+ zabbix_request('user.update', {'userid': admin_id, 'medias': medias}, auth_token)
|
|
|
|
|
+ print("Updated Admin user media")
|
|
|
|
|
+
|
|
|
|
|
+ # 5. Create Web Scenario & Trigger for "> 5 seconds"
|
|
|
|
|
+ hosts = zabbix_request('host.get', {'filter': {'host': 'Zabbix server'}}, auth_token)
|
|
|
|
|
+ if hosts:
|
|
|
|
|
+ host_id = hosts[0]['hostid']
|
|
|
|
|
+ # Create web scenario
|
|
|
|
|
+ httptests = zabbix_request('httptest.get', {'filter': {'name': 'Food App Performance'}}, auth_token)
|
|
|
|
|
+ if not httptests:
|
|
|
|
|
+ zabbix_request('httptest.create', {
|
|
|
|
|
+ 'name': 'Food App Performance',
|
|
|
|
|
+ 'hostid': host_id,
|
|
|
|
|
+ 'delay': '30s',
|
|
|
|
|
+ 'steps': [
|
|
|
|
|
+ {
|
|
|
|
|
+ 'name': 'Homepage',
|
|
|
|
|
+ 'url': 'http://172.18.0.3:8501', # Using docker internal IP or host IP
|
|
|
|
|
+ 'status_codes': '200',
|
|
|
|
|
+ 'no': 1
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }, auth_token)
|
|
|
|
|
+ print("Created HTTP Test for Food App")
|
|
|
|
|
+
|
|
|
|
|
+ # Create Trigger > 5s
|
|
|
|
|
+ triggers = zabbix_request('trigger.get', {'filter': {'description': 'Food App is too slow (> 5s)'}}, auth_token)
|
|
|
|
|
+ if not triggers:
|
|
|
|
|
+ zabbix_request('trigger.create', {
|
|
|
|
|
+ 'description': 'Food App is too slow (> 5s)',
|
|
|
|
|
+ 'expression': f'last(/Zabbix server/web.test.time[Food App Performance,Homepage,resp])>5',
|
|
|
|
|
+ 'priority': 4 # High
|
|
|
|
|
+ }, auth_token)
|
|
|
|
|
+ print("Created Trigger for slow performance")
|
|
|
|
|
+
|
|
|
|
|
+ triggers_down = zabbix_request('trigger.get', {'filter': {'description': 'Food App is DOWN'}}, auth_token)
|
|
|
|
|
+ if not triggers_down:
|
|
|
|
|
+ zabbix_request('trigger.create', {
|
|
|
|
|
+ 'description': 'Food App is DOWN',
|
|
|
|
|
+ 'expression': f'last(/Zabbix server/web.test.fail[Food App Performance])<>0',
|
|
|
|
|
+ 'priority': 5 # Disaster
|
|
|
|
|
+ }, auth_token)
|
|
|
|
|
+ print("Created Trigger for downtime")
|
|
|
|
|
+
|
|
|
|
|
+ # 6. Action to send message
|
|
|
|
|
+ actions = zabbix_request('action.get', {'filter': {'name': 'Alert Discord and Email'}}, auth_token)
|
|
|
|
|
+ if not actions:
|
|
|
|
|
+ zabbix_request('action.create', {
|
|
|
|
|
+ 'name': 'Alert Discord and Email',
|
|
|
|
|
+ 'eventsource': 0,
|
|
|
|
|
+ 'status': 0,
|
|
|
|
|
+ 'esc_period': '1m',
|
|
|
|
|
+ 'filter': {
|
|
|
|
|
+ 'evaltype': 0,
|
|
|
|
|
+ 'conditions': [
|
|
|
|
|
+ {'conditiontype': 3, 'operator': 2, 'value': 'Food App'} # Trigger name contains "Food App"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ 'operations': [
|
|
|
|
|
+ {
|
|
|
|
|
+ 'operationtype': 0,
|
|
|
|
|
+ 'opmessage': {
|
|
|
|
|
+ 'default_msg': 1,
|
|
|
|
|
+ 'mediatypeid': 0 # all
|
|
|
|
|
+ },
|
|
|
|
|
+ 'opmessage_usr': [
|
|
|
|
|
+ {'userid': admin_id}
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }, auth_token)
|
|
|
|
|
+ print("Created Action for Alerts")
|
|
|
|
|
+
|
|
|
|
|
+ print("Zabbix Configuration Complete.")
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
|
+ main()
|