diff --git a/README.md b/README.md index 9209cf4aca73434dbe4fed878d996a1102c59651..3a1724cb31ae86271dde8d3bbc1c38a6c0ef396f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/packagee-0.1.2-20230706.mkp "package-0.1.2-20230706.mkp" +[PACKAGE]: ../../raw/master/mkp/freeradius-0.1.1-20240430.mkp "freeradius-0.1.1-20240430.mkp" # Title A short description about the plugin diff --git a/mkp/freeradius-0.1.1-20240430.mkp b/mkp/freeradius-0.1.1-20240430.mkp new file mode 100644 index 0000000000000000000000000000000000000000..44e8693bc4abfbdc28de7507d078175fbda4c086 Binary files /dev/null and b/mkp/freeradius-0.1.1-20240430.mkp differ diff --git a/source/agent_based/freeradius.py b/source/agent_based/freeradius.py new file mode 100644 index 0000000000000000000000000000000000000000..74f54258b22fce33f316553aa5358832d03f53e9 --- /dev/null +++ b/source/agent_based/freeradius.py @@ -0,0 +1,467 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2024-04-29 +# File : freeradius.py (check plugin) + + +from _collections_abc import Mapping, Sequence +from json import loads as json_loads, JSONDecodeError +from time import localtime, mktime, strftime, strptime, time as now_tine + +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + Result, + Service, + State, + check_levels, + register, + render, + get_rate, + GetRateError, + get_value_store, +) +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( + CheckResult, + DiscoveryResult, + StringTable, +) + +_CMK_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%m %Z' +_FREERADIUS_TIME_FORMAT = "%b %d %Y %H:%M:%S %Z" + +# Authentication attributes +_FreeRADIUS_Total_Access_Requests = 'FreeRADIUS-Total-Access-Requests' +_FreeRADIUS_Total_Access_Accepts = 'FreeRADIUS-Total-Access-Accepts' +_FreeRADIUS_Total_Access_Rejects = 'FreeRADIUS-Total-Access-Rejects' +_FreeRADIUS_Total_Access_Challenges = 'FreeRADIUS-Total-Access-Challenges' +_FreeRADIUS_Total_Auth_Responses = 'FreeRADIUS-Total-Auth-Responses' +_FreeRADIUS_Total_Auth_Duplicate_Requests = 'FreeRADIUS-Total-Auth-Duplicate-Requests' +_FreeRADIUS_Total_Auth_Malformed_Requests = 'FreeRADIUS-Total-Auth-Malformed-Requests' +_FreeRADIUS_Total_Auth_Invalid_Requests = 'FreeRADIUS-Total-Auth-Invalid-Requests' +_FreeRADIUS_Total_Auth_Dropped_Requests = 'FreeRADIUS-Total-Auth-Dropped-Requests' +_FreeRADIUS_Total_Auth_Unknown_Types = 'FreeRADIUS-Total-Auth-Unknown-Types' +_FreeRADIUS_Total_Auth_Conflicts = 'FreeRADIUS-Total-Auth-Conflicts' +# Accounting attributes +_FreeRADIUS_Total_Accounting_Requests = 'FreeRADIUS-Total-Accounting-Requests' +_FreeRADIUS_Total_Accounting_Responses = 'FreeRADIUS-Total-Accounting-Responses' +_FreeRADIUS_Total_Acct_Duplicate_Requests = 'FreeRADIUS-Total-Acct_Duplicate-Requests' +_FreeRADIUS_Total_Acct_Malformed_Requests = 'FreeRADIUS-Total-Acct-Malformed-Requests' +_FreeRADIUS_Total_Acct_Invalid_Requests = 'FreeRADIUS-Total-Acct-Invalid-Requests' +_FreeRADIUS_Total_Acct_Dropped_Requests = 'FreeRADIUS-Total-Acct-Dropped-Requests' +_FreeRADIUS_Total_Acct_Unknown_Types = 'FreeRADIUS-Total-Acct-Unknown-Types' +_FreeRADIUS_Total_Acct_Conflicts = 'FreeRADIUS-Total-Acct-Conflicts' +# Internal Attributes +_FreeRADIUS_Stats_Start_Time = 'FreeRADIUS-Stats-Start-Time' +_FreeRADIUS_Stats_HUP_Time = 'FreeRADIUS-Stats-HUP-Time' +_FreeRADIUS_Queue_Len_Internal = 'FreeRADIUS-Queue-Len-Internal' +_FreeRADIUS_Queue_Len_Proxy = 'FreeRADIUS-Queue-Len-Proxy' +_FreeRADIUS_Queue_Len_Auth = 'FreeRADIUS-Queue-Len-Auth' +_FreeRADIUS_Queue_Len_Acct = 'FreeRADIUS-Queue-Len-Acct' +_FreeRADIUS_Queue_Len_Detail = 'FreeRADIUS-Queue-Len-Detail' +_FreeRADIUS_Queue_PPS_In = 'FreeRADIUS-Queue-PPS-In' +_FreeRADIUS_Queue_PPS_Out = 'FreeRADIUS-Queue-PPS-Out' +# Proxy-Authentication attributes +_FreeRADIUS_Total_Proxy_Access_Requests = 'FreeRADIUS-Total-Proxy-Access-Requests' +_FreeRADIUS_Total_Proxy_Access_Accepts = 'FreeRADIUS-Total-Proxy-Access-Accepts' +_FreeRADIUS_Total_Proxy_Access_Rejects = 'FreeRADIUS-Total-Proxy-Access-Rejects' +_FreeRADIUS_Total_Proxy_Access_Challenges = 'FreeRADIUS-Total-Proxy-Access-Challenges' +_FreeRADIUS_Total_Proxy_Auth_Responses = 'FreeRADIUS-Total-Proxy-Auth-Responses' +_FreeRADIUS_Total_Proxy_Auth_Duplicate_Requests = 'FreeRADIUS-Total-Proxy-Auth-Duplicate-Requests' +_FreeRADIUS_Total_Proxy_Auth_Malformed_Requests = 'FreeRADIUS-Total-Proxy-Auth-Malformed-Requests' +_FreeRADIUS_Total_Proxy_Auth_Invalid_Requests = 'FreeRADIUS-Total-Proxy-Auth-Invalid-Requests' +_FreeRADIUS_Total_Proxy_Auth_Dropped_Requests = 'FreeRADIUS-Total-Proxy-Auth-Dropped-Requests' +_FreeRADIUS_Total_Proxy_Auth_Unknown_Types = 'FreeRADIUS-Total-Proxy-Auth-Unknown-Types' +# Proxy-Accounting attributes +_FreeRADIUS_Total_Proxy_Accounting_Requests = 'FreeRADIUS-Total-Proxy-Accounting-Requests' +_FreeRADIUS_Total_Proxy_Accounting_Responses = 'FreeRADIUS-Total-Proxy-Accounting-Responses' +_FreeRADIUS_Total_Proxy_Acct_Duplicate_Requests = 'FreeRADIUS-Total-Proxy-Acct-Duplicate-Requests' +_FreeRADIUS_Total_Proxy_Acct_Malformed_Requests = 'FreeRADIUS-Total-Proxy-Acct-Malformed-Requests' +_FreeRADIUS_Total_Proxy_Acct_Invalid_Requests = 'FreeRADIUS-Total-Proxy-Acct-Invalid-Requests' +_FreeRADIUS_Total_Proxy_Acct_Dropped_Requests = 'FreeRADIUS-Total-Proxy-Acct-Dropped-Requests' +_FreeRADIUS_Total_Proxy_Acct_Unknown_Types = 'FreeRADIUS-Total-Proxy-Acct-Unknown-Types' + +_FreeRADIUS_Authentication = [ + _FreeRADIUS_Total_Access_Requests, + _FreeRADIUS_Total_Auth_Responses, + _FreeRADIUS_Total_Access_Accepts, + _FreeRADIUS_Total_Access_Rejects, + _FreeRADIUS_Total_Access_Challenges, + _FreeRADIUS_Total_Auth_Duplicate_Requests, + _FreeRADIUS_Total_Auth_Malformed_Requests, + _FreeRADIUS_Total_Auth_Invalid_Requests, + _FreeRADIUS_Total_Auth_Dropped_Requests, + _FreeRADIUS_Total_Auth_Unknown_Types, + _FreeRADIUS_Total_Auth_Conflicts, +] + +_FreeRADIUS_Accounting = [ + _FreeRADIUS_Total_Accounting_Requests, + _FreeRADIUS_Total_Accounting_Responses, + _FreeRADIUS_Total_Acct_Duplicate_Requests, + _FreeRADIUS_Total_Acct_Malformed_Requests, + _FreeRADIUS_Total_Acct_Invalid_Requests, + _FreeRADIUS_Total_Acct_Dropped_Requests, + _FreeRADIUS_Total_Acct_Unknown_Types, + _FreeRADIUS_Total_Acct_Conflicts +] + +_FreeRADIUS_Queue = [ + _FreeRADIUS_Queue_PPS_In, + _FreeRADIUS_Queue_PPS_Out, + _FreeRADIUS_Queue_Len_Acct, + _FreeRADIUS_Queue_Len_Auth, + _FreeRADIUS_Queue_Len_Detail, + _FreeRADIUS_Queue_Len_Internal, + _FreeRADIUS_Queue_Len_Proxy, +] + +_FreeRADIUS_Total_Proxy_Authentication = [ + _FreeRADIUS_Total_Proxy_Access_Requests, + _FreeRADIUS_Total_Proxy_Auth_Responses, + _FreeRADIUS_Total_Proxy_Access_Accepts, + _FreeRADIUS_Total_Proxy_Access_Challenges, + _FreeRADIUS_Total_Proxy_Access_Rejects, + _FreeRADIUS_Total_Proxy_Auth_Dropped_Requests, + _FreeRADIUS_Total_Proxy_Auth_Duplicate_Requests, + _FreeRADIUS_Total_Proxy_Auth_Invalid_Requests, + _FreeRADIUS_Total_Proxy_Auth_Malformed_Requests, + _FreeRADIUS_Total_Proxy_Auth_Unknown_Types, +] + +_FreeRADIUS_Total_Proxy_Accounting = [ + _FreeRADIUS_Total_Proxy_Accounting_Requests, + _FreeRADIUS_Total_Proxy_Accounting_Responses, + _FreeRADIUS_Total_Proxy_Acct_Dropped_Requests, + _FreeRADIUS_Total_Proxy_Acct_Duplicate_Requests, + _FreeRADIUS_Total_Proxy_Acct_Invalid_Requests, + _FreeRADIUS_Total_Proxy_Acct_Malformed_Requests, + _FreeRADIUS_Total_Proxy_Acct_Unknown_Types, +] + + +def _get_metric(rwa_attribute: str) -> str: + return rwa_attribute.lower().replace('-', '_') + + +def _rate_attributes(params: Mapping[str, any], section: Mapping[str, int], attributes: Sequence): + def _get_label(raw_attribute: str) -> str: + raw_attribute = raw_attribute.replace('FreeRADIUS-Total-Proxy-', '') + raw_attribute = raw_attribute.replace('FreeRADIUS-Total-', '') + raw_attribute = raw_attribute.replace('Access-', '') + raw_attribute = raw_attribute.replace('Auth-', '') + raw_attribute = raw_attribute.replace('Accounting-', '') + raw_attribute = raw_attribute.replace('Acct-', '') + raw_attribute = raw_attribute.replace('-', ' ') + raw_attribute = raw_attribute.replace(' Requests', '') + + return raw_attribute + + attribute_params = {attribute: params for attribute, params in params.get('attributes', [])} + now = now_tine() + value_store = get_value_store() + + for attribute, notice_only, upper, lower in attributes: + if (value := section.get(attribute)) is not None: + try: + value = get_rate(value_store, _get_metric(attribute), now, value, raise_overflow=True) + except GetRateError: + continue + yield from check_levels( + value=value, + label=_get_label(attribute), + render_func=lambda v: f'{v:.2f}/s', + metric_name=_get_metric(attribute), + notice_only=attribute_params.get(attribute, {}).get('info_line', notice_only), + levels_upper=attribute_params.get(attribute, {}).get('upper'), + levels_lower=attribute_params.get(attribute, {}).get('lower'), + ) + + +def _list_attributes(section: Mapping[str, int], attributes: Sequence[str] | None): + yield Result(state=State.OK, notice=f'\nAttributes:') + for key, value in section.items(): + if attributes is None or key in attributes: + yield Result(state=State.OK, notice=f'{key}:{value}') + + +def parse_freeradius(string_table: StringTable) -> Mapping[str, int] | None: + try: + return json_loads(string_table[0][0]) + except (JSONDecodeError, TypeError): + return + + +register.agent_section( + name="freeradius", + parse_function=parse_freeradius, +) + + +def discover_freeradius(section: Mapping[str, int]) -> DiscoveryResult: + yield Service() + + +def check_freeradius(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + if 'error' in section: + yield Result(state=State.CRIT, summary=section['error']) + return + if (start_time := section.get(_FreeRADIUS_Stats_Start_Time)) is None or ( + hup_time := section.get(_FreeRADIUS_Stats_HUP_Time)) is None: + yield Result( + state=State.WARN, + summary=f'Response attributes {_FreeRADIUS_Stats_Start_Time} and {_FreeRADIUS_Stats_Start_Time} not found.' + ) + return + + if isinstance(start_time, str): + # str to sec "Apr 29 2024 10:09:54 CEST" -> 1714378194.0 + start_time = mktime(strptime(start_time, _FREERADIUS_TIME_FORMAT)) + if isinstance(hup_time, str): + hup_time = mktime(strptime(hup_time, _FREERADIUS_TIME_FORMAT)) + + yield from check_levels( + value=now_tine() - start_time, + label='Uptime', + render_func=render.timespan, + metric_name='uptime', + ) + + yield from check_levels( + value=now_tine() - hup_time, + label='Reload', + render_func=render.timespan, + metric_name='reload', + ) + + yield Result( + state=State.OK, + notice=f'Service started at: {strftime(_CMK_TIME_FORMAT, localtime(start_time))}' + ) + if start_time != hup_time: + yield Result( + state=State.OK, + notice=f'Service restarted (HUP) at: {strftime(_CMK_TIME_FORMAT, localtime(hup_time))}' + ) + else: + yield Result(state=State.OK, notice='Service restarted (HUP) at: never') + + yield Result(state=State.OK, summary=f'# of status attributes: {len(section)}') + + if params.get('list_attributes'): + yield from _list_attributes(section, None) + + +register.check_plugin( + name='freeradius', + service_name='FreeRADIUS', + sections=['freeradius'], + discovery_function=discover_freeradius, + check_function=check_freeradius, + check_default_parameters={}, + check_ruleset_name='freeradius', +) + + +def discover_freeradius_queue(section: Mapping[str, int]) -> DiscoveryResult: + for attribute in _FreeRADIUS_Queue: + if attribute in section: + yield Service() + break + + +def check_freeradius_queue(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + def _get_label(raw_attribute: str) -> str: + raw_attribute = raw_attribute.replace('FreeRADIUS-Queue-', '') + raw_attribute = raw_attribute.replace('Len-', '') + raw_attribute = raw_attribute.replace('Acct', 'Accounting') + raw_attribute = raw_attribute.replace('Auth', 'Authentication') + raw_attribute = raw_attribute.replace('-', ' ') + return raw_attribute + + attribute_params = {attribute: params for attribute, params in params.get('attributes', [])} + attributes = [ + # attribute, notice_only + (_FreeRADIUS_Queue_PPS_In, False), + (_FreeRADIUS_Queue_PPS_Out, False), + (_FreeRADIUS_Queue_Len_Acct, True), + (_FreeRADIUS_Queue_Len_Auth, True), + (_FreeRADIUS_Queue_Len_Detail, True), + (_FreeRADIUS_Queue_Len_Internal, True), + (_FreeRADIUS_Queue_Len_Proxy, True), + ] + for attribute, notice_only in attributes: + if (value := section.get(attribute)) is not None: + yield from check_levels( + value=value, + label=_get_label(attribute), + render_func=lambda v: f'{v}', + metric_name=_get_metric(attribute), + notice_only=attribute_params.get(attribute, {}).get('info_line', notice_only), + levels_upper=attribute_params.get(attribute, {}).get('upper'), + levels_lower=attribute_params.get(attribute, {}).get('lower'), + ) + if params.get('list_attributes'): + yield from _list_attributes(section, _FreeRADIUS_Queue) + + +register.check_plugin( + name='freeradius_queue', + service_name='FreeRADIUS queue', + sections=['freeradius'], + discovery_function=discover_freeradius_queue, + check_function=check_freeradius_queue, + check_default_parameters={}, + check_ruleset_name='freeradius_queue', +) + + +def discover_freeradius_total_authentication(section: Mapping[str, int]) -> DiscoveryResult: + for attribute in _FreeRADIUS_Authentication: + if attribute in section: + yield Service() + break + + +def check_freeradius_total_authentication(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + attributes = [ + # attribute, notice_only + (_FreeRADIUS_Total_Access_Requests, False), + (_FreeRADIUS_Total_Auth_Responses, False), + (_FreeRADIUS_Total_Access_Accepts, True), + (_FreeRADIUS_Total_Access_Rejects, True), + (_FreeRADIUS_Total_Auth_Dropped_Requests, True), + (_FreeRADIUS_Total_Access_Challenges, True), + (_FreeRADIUS_Total_Auth_Duplicate_Requests, True), + (_FreeRADIUS_Total_Auth_Malformed_Requests, True), + (_FreeRADIUS_Total_Auth_Invalid_Requests, True), + (_FreeRADIUS_Total_Auth_Unknown_Types, True), + (_FreeRADIUS_Total_Auth_Conflicts, True), + ] + yield from _rate_attributes(params, section, attributes) + + if params.get('list_attributes'): + yield from _list_attributes(section, _FreeRADIUS_Authentication) + + +register.check_plugin( + name='freeradius_total_authentication', + service_name='FreeRADIUS authentication', + sections=['freeradius'], + discovery_function=discover_freeradius_total_authentication, + check_function=check_freeradius_total_authentication, + check_default_parameters={}, + check_ruleset_name='freeradius_total_authentication', +) + + +def discover_freeradius_total_accounting(section: Mapping[str, int]) -> DiscoveryResult: + for attribute in _FreeRADIUS_Accounting: + if attribute in section: + yield Service() + break + + +def check_freeradius_total_accounting(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + attributes = [ + # attribute, notice_only + (_FreeRADIUS_Total_Accounting_Requests, False), + (_FreeRADIUS_Total_Accounting_Responses, False), + (_FreeRADIUS_Total_Acct_Dropped_Requests, True), + (_FreeRADIUS_Total_Acct_Duplicate_Requests, True), + (_FreeRADIUS_Total_Acct_Malformed_Requests, True), + (_FreeRADIUS_Total_Acct_Invalid_Requests, True), + (_FreeRADIUS_Total_Acct_Unknown_Types, True), + (_FreeRADIUS_Total_Acct_Conflicts, True), + ] + yield from _rate_attributes(params, section, attributes) + + if params.get('list_attributes'): + yield from _list_attributes(section, _FreeRADIUS_Accounting) + + +register.check_plugin( + name='freeradius_total_accounting', + service_name='FreeRADIUS accounting', + sections=['freeradius'], + discovery_function=discover_freeradius_total_accounting, + check_function=check_freeradius_total_accounting, + check_default_parameters={}, + check_ruleset_name='freeradius_total_accounting', +) + + +def discover_freeradius_total_proxy_authentication(section: Mapping[str, int]) -> DiscoveryResult: + for attribute in _FreeRADIUS_Total_Proxy_Authentication: + if attribute in section: + yield Service() + break + + +def check_freeradius_total_proxy_authentication(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + attributes = [ + # attribute, notice_only + (_FreeRADIUS_Total_Proxy_Access_Requests, False), + (_FreeRADIUS_Total_Proxy_Auth_Responses, False), + (_FreeRADIUS_Total_Proxy_Access_Accepts, True), + (_FreeRADIUS_Total_Proxy_Access_Rejects, True), + (_FreeRADIUS_Total_Proxy_Access_Challenges, True), + (_FreeRADIUS_Total_Proxy_Auth_Duplicate_Requests, True), + (_FreeRADIUS_Total_Proxy_Auth_Malformed_Requests, True), + (_FreeRADIUS_Total_Proxy_Auth_Invalid_Requests, True), + (_FreeRADIUS_Total_Proxy_Auth_Dropped_Requests, True), + (_FreeRADIUS_Total_Proxy_Auth_Unknown_Types, True), + ] + yield from _rate_attributes(params, section, attributes) + + if params.get('list_attributes'): + yield from _list_attributes(section, _FreeRADIUS_Total_Proxy_Authentication) + + +register.check_plugin( + name='freeradius_total_proxy_authentication', + service_name='FreeRADIUS proxy authentication', + sections=['freeradius'], + discovery_function=discover_freeradius_total_proxy_authentication, + check_function=check_freeradius_total_proxy_authentication, + check_default_parameters={}, + check_ruleset_name='freeradius_total_proxy_authentication', +) + + +def discover_freeradius_total_proxy_accounting(section: Mapping[str, int]) -> DiscoveryResult: + for attribute in _FreeRADIUS_Total_Proxy_Accounting: + if attribute in section: + yield Service() + break + + +def check_freeradius_total_proxy_accounting(params: Mapping[str, any], section: Mapping[str, int]) -> CheckResult: + attribute = [ + # attribute, notice_only + (_FreeRADIUS_Total_Proxy_Accounting_Requests, False), + (_FreeRADIUS_Total_Proxy_Accounting_Responses, False), + (_FreeRADIUS_Total_Proxy_Acct_Duplicate_Requests, True), + (_FreeRADIUS_Total_Proxy_Acct_Malformed_Requests, True), + (_FreeRADIUS_Total_Proxy_Acct_Invalid_Requests, True), + (_FreeRADIUS_Total_Proxy_Acct_Dropped_Requests, True), + (_FreeRADIUS_Total_Proxy_Acct_Unknown_Types, True), + ] + yield from _rate_attributes(params, section, attribute) + + if params.get('list_attributes'): + yield from _list_attributes(section, _FreeRADIUS_Total_Proxy_Accounting) + + +register.check_plugin( + name='freeradius_total_proxy_accounting', + service_name='FreeRADIUS proxy accounting', + sections=['freeradius'], + discovery_function=discover_freeradius_total_proxy_accounting, + check_function=check_freeradius_total_proxy_accounting, + check_default_parameters={}, + check_ruleset_name='freeradius_total_proxy_accounting', +) diff --git a/source/agents/special/agent_freeradius b/source/agents/special/agent_freeradius new file mode 100755 index 0000000000000000000000000000000000000000..f39e8f8673ea5f7d55941e27f26a28f4a4b577ae --- /dev/null +++ b/source/agents/special/agent_freeradius @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# Copyright (C) 2022 Checkmk GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +import sys + +from cmk.special_agents.agent_freeradius import main + +if __name__ == "__main__": + sys.exit(main()) diff --git a/source/checkman/.gitkeep b/source/checkman/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/source/checkman/freeradius b/source/checkman/freeradius deleted file mode 100644 index 08ef898bcf6eb7a7979de60090d54f9719bbbc5b..0000000000000000000000000000000000000000 --- a/source/checkman/freeradius +++ /dev/null @@ -1,45 +0,0 @@ -title: Dummy check man page - used as template for new check manuals -agents: linux, windows, aix, solaris, hpux, vms, freebsd, snmp -catalog: see modules/catalog.py for possible values -license: GPL -distribution: check_mk -description: - Describe here: (1) what the check actually does, (2) under which - circumstances it goes warning/critical, (3) which devices are supported - by the check, (4) if the check requires a separated plugin or - tool or separate configuration on the target host. - -item: - Describe the syntax and meaning of the check's item here. Provide all - information one needs if coding a manual check with {checks +=} in {main.mk}. - Give an example. If the check uses {None} as sole item, - then leave out this section. - -examples: - # Give examples for configuration in {main.mk} here. If the check has - # configuration variable, then give example for them here. - - # set default levels to 40 and 60 percent: - foo_default_values = (40, 60) - - # another configuration variable here: - inventory_foo_filter = [ "superfoo", "superfoo2" ] - -perfdata: - Describe precisely the number and meaning of performance variables - the check sends. If it outputs no performance data, then leave out this - section. - -inventory: - Describe how the inventory for the check works. Which items - will it find? Describe the influence of check specific - configuration parameters to the inventory. - -[parameters] -foofirst(int): describe the first parameter here (if parameters are grouped - as tuple) -fooother(string): describe another parameter here. - -[configuration] -foo_default_levels(int, int): Describe global configuration variable of - foo here. Important: also tell the user how they are preset. diff --git a/source/checks/agent_freeradius b/source/checks/agent_freeradius new file mode 100644 index 0000000000000000000000000000000000000000..171e45eae252485163bb1279fb62951570120f41 --- /dev/null +++ b/source/checks/agent_freeradius @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2024-04-29 +# File : checks/agent_freeradius +# +# + +from collections.abc import Mapping, Sequence +from typing import Any + + +def agent_freeradius_arguments( + params: Mapping[str, Any], + hostname: str, + ipaddress: str | None, +) -> Sequence[object]: + args = [] + + if ipaddress is not None: + args.extend(['-H', ipaddress]) + else: + args.append('-H $HOSTADDRESS$') + + if (auth_port := params.get("auth_port")) is not None: + args.extend(['--auth-port', auth_port]) + + if (secret := params.get("secret")) is not None: + args.extend(["--secret", passwordstore_get_cmdline("%s", secret)]) + + if (timeout := params.get('timeout')) is not None: + args.extend(['--timeout', timeout]) + + # if (user_name := params.get("user_name")) is not None: + # args.extend([f'--username', user_name]) + # + # if (user_password := params.get("user_password")) is not None: + # args.extend(["--password", passwordstore_get_cmdline("%s", user_password)]) + + return args + + +special_agent_info["freeradius"] = agent_freeradius_arguments diff --git a/source/gui/metrics/freeradius.py b/source/gui/metrics/freeradius.py new file mode 100644 index 0000000000000000000000000000000000000000..11d96edbca1b5d0da1c7ff85735abc673c0a13ba --- /dev/null +++ b/source/gui/metrics/freeradius.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2024-04-29 +# File : freeradius.py (metrics) + +from cmk.gui.i18n import _ + +from cmk.gui.plugins.metrics.utils import ( + check_metrics, + graph_info, + metric_info, + perfometer_info, +) +# +_color_accepts = '24/a' +_color_challenges = '42/a' +_color_rejects = '32/a' +_color_requests = '16/a' +_color_responses = '35/b' +# +_color_conflicts = '25/a' +_color_dropped = '43/a' +_color_duplicate = '13/a' +_color_invalid = '33/a' +_color_malformed = '23/a' +_color_unknown = '53/a' +# queue +_color_authentication = '11/a' +_color_accounting = '21/a' +_color_detail = '31/a' +_color_internal = '41/a' +_color_proxy = '22/a' +_color_pps_in = '13/a' +_color_pps_out = '23/b' +# +# times +# +metric_info['reload'] = {'title': _('Reload'), 'unit': 's', 'color': '13/b', } +graph_info['freeradius.time'] = { + 'title': _('FreeRADIUS uptime'), + 'metrics': [ + ('reload', 'area'), + ('uptime', 'area'), + ], + 'optional_metrics': [ + 'uptime', + 'reload', + ], +} +# +# queue +# +_FreeRADIUS_Queue_Len_Internal = 'freeradius_queue_len_internal' +_FreeRADIUS_Queue_Len_Proxy = 'freeradius_queue_len_proxy' +_FreeRADIUS_Queue_Len_Auth = 'freeradius_queue_len_auth' +_FreeRADIUS_Queue_Len_Acct = 'freeradius_queue_len_acct' +_FreeRADIUS_Queue_Len_Detail = 'freeradius_queue_len_detail' +_FreeRADIUS_Queue_PPS_In = 'freeradius_queue_pps_in' +_FreeRADIUS_Queue_PPS_Out = 'freeradius_queue_pps_out' + +metric_info[_FreeRADIUS_Queue_Len_Auth] = { + 'title': _('Authentication'), 'unit': 'count', 'color': _color_authentication +} +metric_info[_FreeRADIUS_Queue_Len_Acct] = {'title': _('Accounting'), 'unit': 'count', 'color': _color_accounting} +metric_info[_FreeRADIUS_Queue_Len_Detail] = {'title': _('Detail'), 'unit': 'count', 'color': _color_detail} +metric_info[_FreeRADIUS_Queue_Len_Internal] = {'title': _('Internal'), 'unit': 'count', 'color': _color_internal} +metric_info[_FreeRADIUS_Queue_Len_Proxy] = {'title': _('Proxy'), 'unit': 'count', 'color': _color_proxy} +metric_info[_FreeRADIUS_Queue_PPS_In] = {'title': _('PPS in'), 'unit': 'count', 'color': _color_pps_in} +metric_info[_FreeRADIUS_Queue_PPS_Out] = {'title': _('PPS out'), 'unit': 'count', 'color': _color_pps_out} + +graph_info['freeradius.queue'] = { + 'title': _('FreeRADIUS queue length'), + 'metrics': [ + (_FreeRADIUS_Queue_Len_Acct, 'line'), + (_FreeRADIUS_Queue_Len_Auth, 'line'), + (_FreeRADIUS_Queue_Len_Detail, 'line'), + (_FreeRADIUS_Queue_Len_Internal, 'line'), + (_FreeRADIUS_Queue_Len_Proxy, 'line'), + ], + 'optional_metrics': [ + _FreeRADIUS_Queue_Len_Auth, + _FreeRADIUS_Queue_Len_Acct, + _FreeRADIUS_Queue_Len_Detail, + _FreeRADIUS_Queue_Len_Internal, + _FreeRADIUS_Queue_Len_Proxy, + ], +} + +graph_info['freeradius.pps'] = { + 'title': _('FreeRADIUS queue PPS'), + 'metrics': [ + (_FreeRADIUS_Queue_PPS_In, 'area'), + (_FreeRADIUS_Queue_PPS_Out, '-area'), + ], + 'optional_metrics': [ + _FreeRADIUS_Queue_PPS_In, + _FreeRADIUS_Queue_PPS_Out, + ], +} + +perfometer_info.append(('stacked', [ + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Queue_PPS_In, + "half_value": 100, + "exponent": 3, + }, + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Queue_PPS_Out, + "half_value": 100, + "exponent": 3, + } +])) +# +# authentication +# +_FreeRADIUS_Total_Access_Requests = 'freeradius_total_access_requests' +_FreeRADIUS_Total_Access_Accepts = 'freeradius_total_access_accepts' +_FreeRADIUS_Total_Access_Rejects = 'freeradius_total_access_rejects' +_FreeRADIUS_Total_Access_Challenges = 'freeradius_total_access_challenges' +_FreeRADIUS_Total_Auth_Responses = 'freeradius_total_auth_responses' +_FreeRADIUS_Total_Auth_Duplicate_Requests = 'freeradius_total_auth_duplicate_requests' +_FreeRADIUS_Total_Auth_Malformed_Requests = 'freeradius_total_auth_malformed_requests' +_FreeRADIUS_Total_Auth_Invalid_Requests = 'freeradius_total_auth_invalid_requests' +_FreeRADIUS_Total_Auth_Dropped_Requests = 'freeradius_total_auth_dropped_requests' +_FreeRADIUS_Total_Auth_Unknown_Types = 'freeradius_total_auth_unknown_types' +_FreeRADIUS_Total_Auth_Conflicts = 'freeradius_total_auth_conflicts' + +metric_info[_FreeRADIUS_Total_Access_Requests] = {'title': _('Requests'), 'unit': '1/s', 'color': _color_requests} +metric_info[_FreeRADIUS_Total_Access_Accepts] = {'title': _('Accepts'), 'unit': '1/s', 'color': _color_accepts} +metric_info[_FreeRADIUS_Total_Access_Rejects] = {'title': _('Rejects'), 'unit': '1/s', 'color': _color_rejects} +metric_info[_FreeRADIUS_Total_Access_Challenges] = {'title': _('Challenges'), 'unit': '1/s', 'color': _color_challenges} +metric_info[_FreeRADIUS_Total_Auth_Responses] = {'title': _('Responses'), 'unit': '1/s', 'color': _color_responses} +metric_info[_FreeRADIUS_Total_Auth_Duplicate_Requests] = { + 'title': _('Duplicate'), 'unit': '1/s', 'color': _color_duplicate +} +metric_info[_FreeRADIUS_Total_Auth_Malformed_Requests] = { + 'title': _('Malformed'), 'unit': '1/s', 'color': _color_malformed +} +metric_info[_FreeRADIUS_Total_Auth_Invalid_Requests] = {'title': _('Invalid'), 'unit': '1/s', 'color': _color_invalid} +metric_info[_FreeRADIUS_Total_Auth_Dropped_Requests] = {'title': _('Dropped'), 'unit': '1/s', 'color': _color_dropped} +metric_info[_FreeRADIUS_Total_Auth_Unknown_Types] = { + 'title': _('Unknown tyoes'), 'unit': '1/s', 'color': _color_unknown +} +metric_info[_FreeRADIUS_Total_Auth_Conflicts] = {'title': _('Conflicts'), 'unit': '1/s', 'color': _color_conflicts} + +graph_info['freeradius.authentication'] = { + 'title': _('FreeRADIUS Authentications'), + 'metrics': [ + (_FreeRADIUS_Total_Access_Accepts, 'line'), + (_FreeRADIUS_Total_Access_Challenges, 'line'), + (_FreeRADIUS_Total_Access_Rejects, 'line'), + (_FreeRADIUS_Total_Access_Requests, 'area'), + (_FreeRADIUS_Total_Auth_Responses, '-area'), + ], + 'optional_metrics': [ + _FreeRADIUS_Total_Access_Requests, + _FreeRADIUS_Total_Access_Accepts, + _FreeRADIUS_Total_Access_Rejects, + _FreeRADIUS_Total_Access_Challenges, + _FreeRADIUS_Total_Auth_Responses, + ], +} + +graph_info['freeradius.authentication.errors'] = { + 'title': _('FreeRADIUS Authentication Errors'), + 'metrics': [ + (_FreeRADIUS_Total_Auth_Conflicts, 'line'), + (_FreeRADIUS_Total_Auth_Dropped_Requests, 'line'), + (_FreeRADIUS_Total_Auth_Duplicate_Requests, 'line'), + (_FreeRADIUS_Total_Auth_Invalid_Requests, 'line'), + (_FreeRADIUS_Total_Auth_Malformed_Requests, 'line'), + (_FreeRADIUS_Total_Auth_Unknown_Types, 'line'), + ], + 'optional_metrics': [ + _FreeRADIUS_Total_Auth_Conflicts, + _FreeRADIUS_Total_Auth_Dropped_Requests, + _FreeRADIUS_Total_Auth_Duplicate_Requests, + _FreeRADIUS_Total_Auth_Invalid_Requests, + _FreeRADIUS_Total_Auth_Malformed_Requests, + _FreeRADIUS_Total_Auth_Unknown_Types, + ], +} + +perfometer_info.append(('stacked', [ + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Total_Access_Requests, + "half_value": 400, + "exponent": 3, + }, + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Total_Auth_Responses, + "half_value": 400, + "exponent": 3, + } +])) +# +# accounting +# +_FreeRADIUS_Total_Accounting_Requests = 'freeradius_total_accounting_requests' +_FreeRADIUS_Total_Accounting_Responses = 'freeradius_total_accounting_responses' +_FreeRADIUS_Total_Acct_Duplicate_Requests = 'freeradius_total_acct_duplicate_requests' +_FreeRADIUS_Total_Acct_Malformed_Requests = 'freeradius_total_acct_malformed_requests' +_FreeRADIUS_Total_Acct_Invalid_Requests = 'freeradius_total_acct_invalid_requests' +_FreeRADIUS_Total_Acct_Dropped_Requests = 'freeradius_total_acct_dropped_requests' +_FreeRADIUS_Total_Acct_Unknown_Types = 'freeradius_total_acct_unknown_types' +_FreeRADIUS_Total_Acct_Conflicts = 'freeradius_total_acct_conflicts' + +metric_info[_FreeRADIUS_Total_Accounting_Requests] = {'title': _('Requests'), 'unit': '1/s', 'color': _color_responses} +metric_info[_FreeRADIUS_Total_Accounting_Responses] = { + 'title': _('Responses'), 'unit': '1/s', 'color': _color_responses +} +metric_info[_FreeRADIUS_Total_Acct_Duplicate_Requests] = { + 'title': _('Duplicate'), 'unit': '1/s', 'color': _color_duplicate +} +metric_info[_FreeRADIUS_Total_Acct_Malformed_Requests] = { + 'title': _('Malformed'), 'unit': '1/s', 'color': _color_malformed +} +metric_info[_FreeRADIUS_Total_Acct_Invalid_Requests] = {'title': _('Invalid'), 'unit': '1/s', 'color': _color_invalid} +metric_info[_FreeRADIUS_Total_Acct_Dropped_Requests] = {'title': _('Dropped'), 'unit': '1/s', 'color': _color_dropped} +metric_info[_FreeRADIUS_Total_Acct_Unknown_Types] = {'title': _('Unknown type'), 'unit': '1/s', 'color': _color_unknown} +metric_info[_FreeRADIUS_Total_Acct_Conflicts] = {'title': _('Conflict'), 'unit': '1/s', 'color': _color_conflicts} + +graph_info['freeradius.accounting'] = { + 'title': _('FreeRADIUS Accounting'), + 'metrics': [ + (_FreeRADIUS_Total_Accounting_Requests, 'line'), + (_FreeRADIUS_Total_Accounting_Responses, '-line'), + ], + 'optional_metrics': [ + _FreeRADIUS_Total_Accounting_Requests, + _FreeRADIUS_Total_Accounting_Responses, + ], +} + +graph_info['freeradius.accounting.errors'] = { + 'title': _('FreeRADIUS Accounting Errors'), + 'metrics': [ + (_FreeRADIUS_Total_Acct_Conflicts, '-line'), + (_FreeRADIUS_Total_Acct_Dropped_Requests, 'line'), + (_FreeRADIUS_Total_Acct_Duplicate_Requests, 'line'), + (_FreeRADIUS_Total_Acct_Invalid_Requests, 'line'), + (_FreeRADIUS_Total_Acct_Malformed_Requests, 'line'), + (_FreeRADIUS_Total_Acct_Unknown_Types, 'line'), + ], + 'optional_metrics': [ + _FreeRADIUS_Total_Acct_Conflicts, + _FreeRADIUS_Total_Acct_Dropped_Requests, + _FreeRADIUS_Total_Acct_Duplicate_Requests, + _FreeRADIUS_Total_Acct_Invalid_Requests, + _FreeRADIUS_Total_Acct_Malformed_Requests, + _FreeRADIUS_Total_Acct_Unknown_Types + ], +} + +perfometer_info.append(('stacked', [ + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Total_Accounting_Requests, + "half_value": 400, + "exponent": 3, + }, + { + 'type': 'logarithmic', + 'metric': _FreeRADIUS_Total_Accounting_Responses, + "half_value": 400, + "exponent": 3, + } +])) +# +# Proxy-Authentication +# +_FreeRADIUS_Total_Proxy_Access_Requests = 'freeradius_total_proxy_access_requests' +_FreeRADIUS_Total_Proxy_Access_Accepts = 'freeradius_total_proxy_access_accepts' +_FreeRADIUS_Total_Proxy_Access_Rejects = 'freeradius_total_proxy_access_rejects' +_FreeRADIUS_Total_Proxy_Access_Challenges = 'freeradius_total_proxy_access_challenges' +_FreeRADIUS_Total_Proxy_Auth_Responses = 'freeradius_total_proxy_auth_responses' +_FreeRADIUS_Total_Proxy_Auth_Duplicate_Requests = 'freeradius_total_proxy_auth_duplicate_requests' +_FreeRADIUS_Total_Proxy_Auth_Malformed_Requests = 'freeradius_total_proxy_auth_malformed_requests' +_FreeRADIUS_Total_Proxy_Auth_Invalid_Requests = 'freeradius_total_proxy_auth_invalid_requests' +_FreeRADIUS_Total_Proxy_Auth_Dropped_Requests = 'freeradius_total_proxy_auth_dropped_requests' +_FreeRADIUS_Total_Proxy_Auth_Unknown_Types = 'freeradius_total_proxy_auth_unknown_types' + +check_metrics['check_mk-freeradius_total_proxy_authentication'] = { + _FreeRADIUS_Total_Proxy_Access_Requests: {'name': _FreeRADIUS_Total_Access_Requests}, + _FreeRADIUS_Total_Proxy_Access_Accepts: {'name': _FreeRADIUS_Total_Access_Accepts}, + _FreeRADIUS_Total_Proxy_Access_Rejects: {'name': _FreeRADIUS_Total_Access_Rejects}, + _FreeRADIUS_Total_Proxy_Access_Challenges: {'name': _FreeRADIUS_Total_Access_Challenges}, + _FreeRADIUS_Total_Proxy_Auth_Responses: {'name': _FreeRADIUS_Total_Auth_Responses}, + _FreeRADIUS_Total_Proxy_Auth_Duplicate_Requests: {'name': _FreeRADIUS_Total_Auth_Duplicate_Requests}, + _FreeRADIUS_Total_Proxy_Auth_Malformed_Requests: {'name': _FreeRADIUS_Total_Auth_Malformed_Requests}, + _FreeRADIUS_Total_Proxy_Auth_Invalid_Requests: {'name': _FreeRADIUS_Total_Auth_Invalid_Requests}, + _FreeRADIUS_Total_Proxy_Auth_Dropped_Requests: {'name': _FreeRADIUS_Total_Auth_Dropped_Requests}, + _FreeRADIUS_Total_Proxy_Auth_Unknown_Types: {'name': _FreeRADIUS_Total_Auth_Unknown_Types}, +} +# +# Proxy-Accounting +# +_FreeRADIUS_Total_Proxy_Accounting_Requests = 'freeradius_total_proxy_accounting_requests' +_FreeRADIUS_Total_Proxy_Accounting_Responses = 'freeradius_total_proxy_accounting_responses' +_FreeRADIUS_Total_Proxy_Acct_Duplicate_Requests = 'freeradius_total_proxy_acct_duplicate_requests' +_FreeRADIUS_Total_Proxy_Acct_Malformed_Requests = 'freeradius_total_proxy_acct_malformed_requests' +_FreeRADIUS_Total_Proxy_Acct_Invalid_Requests = 'freeradius_total_proxy_acct_invalid_requests' +_FreeRADIUS_Total_Proxy_Acct_Dropped_Requests = 'freeradius_total_proxy_acct_dropped_requests' +_FreeRADIUS_Total_Proxy_Acct_Unknown_Types = 'freeradius_total_proxy_acct_unknown_types' + +check_metrics['check_mk-freeradius_total_proxy_accounting'] = { + _FreeRADIUS_Total_Proxy_Accounting_Requests: {'name': _FreeRADIUS_Total_Accounting_Requests}, + _FreeRADIUS_Total_Proxy_Accounting_Responses: {'name': _FreeRADIUS_Total_Accounting_Responses}, + _FreeRADIUS_Total_Proxy_Acct_Duplicate_Requests: {'name': _FreeRADIUS_Total_Acct_Duplicate_Requests}, + _FreeRADIUS_Total_Proxy_Acct_Malformed_Requests: {'name': _FreeRADIUS_Total_Acct_Malformed_Requests}, + _FreeRADIUS_Total_Proxy_Acct_Invalid_Requests: {'name': _FreeRADIUS_Total_Acct_Invalid_Requests}, + _FreeRADIUS_Total_Proxy_Acct_Dropped_Requests: {'name': _FreeRADIUS_Total_Acct_Dropped_Requests}, + _FreeRADIUS_Total_Proxy_Acct_Unknown_Types: {'name': _FreeRADIUS_Total_Acct_Unknown_Types}, +} diff --git a/source/lib/python3/cmk/special_agents/agent_freeradius.py b/source/lib/python3/cmk/special_agents/agent_freeradius.py new file mode 100644 index 0000000000000000000000000000000000000000..cfdda6f76b9dd4e1ebace1204e263b8506dd5116 --- /dev/null +++ b/source/lib/python3/cmk/special_agents/agent_freeradius.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2024-04-29 +# File : agent_freeradius.py (special agent) + +# /etc/freeradius/3.0/radiusd.conf +# security { +# status_server = yes +# } + +# +# /etc/freeradius/3.0/sites-enabled/status +# +# server status { +# listen { +# type = status +# # ipaddr = 127.0.0.1 +# ipaddr = 0.0.0.0 +# port = 18121 +# } +# client cmkbuild { +# ipaddr = 192.168.10.99 +# secret = adminsecret +# } +# } +# + +import socket +import pyrad.client +from argparse import ( + Namespace, +) +from collections.abc import Mapping, Sequence +from json import dumps as json_dumps +from os import environ +from time import time_ns +from sys import ( + exit as sys_exit, + stdout as sys_stdout, +) + +from cmk.special_agents.utils.agent_common import ( + special_agent_main, +) +from cmk.special_agents.utils.argument_parsing import create_default_argument_parser + +no_radiuslib = False +try: + from pyrad.client import Client as radClient + from pyrad.dictionary import Dictionary as radDictionary + from pyrad.packet import AccessAccept, AccessReject, AccessRequest, StatusServer + from pyrad.client import Timeout as pyTimeout +except ModuleNotFoundError: + no_radiuslib = True + +VERSION = '0.1.1-20240430' + + +class Args(Namespace): + host: str + secret: str + username: str + password: str + auth_port: int + timeout: int + + +def write_section(message: Mapping[str, any]): + sys_stdout.write('\n<<<freeradius:sep(0)>>>\n') + sys_stdout.write(json_dumps(message)) + sys_stdout.write('\n<<<>>>\n') + + +def parse_arguments(argv: Sequence[str] | None) -> Args: + parser = create_default_argument_parser(__doc__) + parser.description = 'This is a special agent to collect stats data from FreeRADIS servers.' + parser.epilog = ( + f'(c) thl-cmk[at]outlook[dot], Version: {VERSION}, ' + f'For more information see: https://thl-cmk.hopto.org' + ) + + parser.add_argument( + '-H', '--host', required=True, + help='Host/IP-Address of RADIUS server to query (required)', + ) + parser.add_argument( + '--secret', required=True, + help='secret RADIUS key', + ) + parser.add_argument( + '--auth-port', type=int, default=18121, + help='RADIUS authentication port to use.', + ) + parser.add_argument( + '--timeout', type=int, default=1, + help='RADIUS server timeout', + ) + + return parser.parse_args(argv) + + +def agent_freeradius_main(args: Args) -> int: + if no_radiuslib: + write_section( + { + 'error': 'To use this special agent, you must install the Python ' + 'library “pyrad†in your CMK Python environment.' + } + ) + sys_exit(0) + + omd_root = environ["OMD_ROOT"] + path_to_dict = f'{omd_root}/local/lib/check_mk/special_agents' + # status request + status_srv = radClient( + server=args.host.strip(), # not sure where the leading spce comes from + authport=args.auth_port, + secret=args.secret.encode('utf-8'), + dict=radDictionary(f"{path_to_dict}/dictionary"), + retries=1, + timeout=args.timeout, + ) + status = status_srv.CreateAuthPacket( + code=StatusServer, + NAS_Identifier="checkmk", + ) + # https://freeradius.org/documentation/freeradius-server/3.2.4/howto/monitoring/statistics.html + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Authentication") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Accounting") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Proxy-Authentication") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Proxy-Accounting") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Internal") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Client") + # status.AddAttribute('FreeRADIUS-Stats-Client-IP-Address', "192.168.10.99") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Server") + # status.AddAttribute("FreeRADIUS-Stats-Server-IP-Address", "192.168.10.95") + # status.AddAttribute("FreeRADIUS-Stats-Server-Port", "1645") + # status.AddAttribute("FreeRADIUS-Statistics-Type", "Home-Server") + status.AddAttribute("FreeRADIUS-Statistics-Type", "All") + + status.add_message_authenticator() + try: + response = status_srv.SendPacket(status) + except pyrad.client.Timeout as e: + write_section({'error': f'Special agent request timeout, check configuration!. ({e})'}) + sys_exit() + except socket.gaierror as e: + write_section(({'error': f'Special agent network error, check Configuration. ({e})'})) + sys_exit() + + if response.code == AccessAccept: + attributes = { + attribute: response.get(attribute)[0] + for attribute in response.keys() if isinstance(attribute, str)} + write_section(attributes) + else: + write_section({'error': 'Response access reject, check configuration'}) + + return 0 + + +def main() -> int: + return special_agent_main(parse_arguments, agent_freeradius_main) diff --git a/source/lib/python3/cmk/special_agents/dictionary b/source/lib/python3/cmk/special_agents/dictionary new file mode 100755 index 0000000000000000000000000000000000000000..125de2fc6581f18a66137b2e1ebddc3d3a05c292 --- /dev/null +++ b/source/lib/python3/cmk/special_agents/dictionary @@ -0,0 +1,446 @@ +# +# Version $Id: dictionary,v 1.1.1.1 2002/10/11 12:25:39 wichert Exp $ +# +# for free radius dictionaries see: /usr/share/freeradius +# +# This file contains dictionary translations for parsing +# requests and generating responses. All transactions are +# composed of Attribute/Value Pairs. The value of each attribute +# is specified as one of 4 data types. Valid data types are: +# +# string - 0-253 octets +# ipaddr - 4 octets in network byte order +# integer - 32 bit value in big endian order (high byte first) +# date - 32 bit value in big endian order - seconds since +# 00:00:00 GMT, Jan. 1, 1970 +# +# FreeRADIUS includes extended data types which are not defined +# in RFC 2865 or RFC 2866. These data types are: +# +# abinary - Ascend's binary filter format. +# octets - raw octets, printed and input as hex strings. +# e.g.: 0x123456789abcdef +# +# +# Enumerated values are stored in the user file with dictionary +# VALUE translations for easy administration. +# +# Example: +# +# ATTRIBUTE VALUE +# --------------- ----- +# Framed-Protocol = PPP +# 7 = 1 (integer encoding) +# + +# +# Include compatibility dictionary for older users file. Move this +# directive to the end of the file if you want to see the old names +# in the logfiles too. +# +#$INCLUDE dictionary.compat # compability issues +#$INCLUDE dictionary.acc +#$INCLUDE dictionary.ascend +#$INCLUDE dictionary.bay +#$INCLUDE dictionary.cisco +#$INCLUDE dictionary.livingston +#$INCLUDE dictionary.microsoft +#$INCLUDE dictionary.quintum +#$INCLUDE dictionary.redback +#$INCLUDE dictionary.shasta +#$INCLUDE dictionary.shiva +#$INCLUDE dictionary.tunnel +#$INCLUDE dictionary.usr +#$INCLUDE dictionary.versanet +#$INCLUDE dictionary.erx +$INCLUDE dictionary.freeradius +#$INCLUDE dictionary.alcatel + +# +# Following are the proper new names. Use these. +# +ATTRIBUTE User-Name 1 string +ATTRIBUTE User-Password 2 string +ATTRIBUTE CHAP-Password 3 octets +ATTRIBUTE NAS-IP-Address 4 ipaddr +ATTRIBUTE NAS-Port 5 integer +ATTRIBUTE Service-Type 6 integer +ATTRIBUTE Framed-Protocol 7 integer +ATTRIBUTE Framed-IP-Address 8 ipaddr +ATTRIBUTE Framed-IP-Netmask 9 ipaddr +ATTRIBUTE Framed-Routing 10 integer +ATTRIBUTE Filter-Id 11 string +ATTRIBUTE Framed-MTU 12 integer +ATTRIBUTE Framed-Compression 13 integer +ATTRIBUTE Login-IP-Host 14 ipaddr +ATTRIBUTE Login-Service 15 integer +ATTRIBUTE Login-TCP-Port 16 integer +ATTRIBUTE Reply-Message 18 string +ATTRIBUTE Callback-Number 19 string +ATTRIBUTE Callback-Id 20 string +ATTRIBUTE Framed-Route 22 string +ATTRIBUTE Framed-IPX-Network 23 ipaddr +ATTRIBUTE State 24 octets +ATTRIBUTE Class 25 octets +ATTRIBUTE Vendor-Specific 26 octets +ATTRIBUTE Session-Timeout 27 integer +ATTRIBUTE Idle-Timeout 28 integer +ATTRIBUTE Termination-Action 29 integer +ATTRIBUTE Called-Station-Id 30 string +ATTRIBUTE Calling-Station-Id 31 string +ATTRIBUTE NAS-Identifier 32 string +ATTRIBUTE Proxy-State 33 octets +ATTRIBUTE Login-LAT-Service 34 string +ATTRIBUTE Login-LAT-Node 35 string +ATTRIBUTE Login-LAT-Group 36 octets +ATTRIBUTE Framed-AppleTalk-Link 37 integer +ATTRIBUTE Framed-AppleTalk-Network 38 integer +ATTRIBUTE Framed-AppleTalk-Zone 39 string + +ATTRIBUTE Acct-Status-Type 40 integer +ATTRIBUTE Acct-Delay-Time 41 integer +ATTRIBUTE Acct-Input-Octets 42 integer +ATTRIBUTE Acct-Output-Octets 43 integer +ATTRIBUTE Acct-Session-Id 44 string +ATTRIBUTE Acct-Authentic 45 integer +ATTRIBUTE Acct-Session-Time 46 integer +ATTRIBUTE Acct-Input-Packets 47 integer +ATTRIBUTE Acct-Output-Packets 48 integer +ATTRIBUTE Acct-Terminate-Cause 49 integer +ATTRIBUTE Acct-Multi-Session-Id 50 string +ATTRIBUTE Acct-Link-Count 51 integer +ATTRIBUTE Acct-Input-Gigawords 52 integer +ATTRIBUTE Acct-Output-Gigawords 53 integer +ATTRIBUTE Event-Timestamp 55 date + +ATTRIBUTE CHAP-Challenge 60 string +ATTRIBUTE NAS-Port-Type 61 integer +ATTRIBUTE Port-Limit 62 integer +ATTRIBUTE Login-LAT-Port 63 integer +ATTRIBUTE Tunnel-Type 64 integer +ATTRIBUTE Tunnel-Medium-Type 65 integer +ATTRIBUTE Tunnel-Client-Endpoint 66 string +ATTRIBUTE Tunnel-Server-Endpoint 67 string +ATTRIBUTE Acct-Tunnel-Connection 68 string +ATTRIBUTE Tunnel-Password 69 string + +ATTRIBUTE ARAP-Password 70 string +ATTRIBUTE ARAP-Features 71 string +ATTRIBUTE ARAP-Zone-Access 72 integer +ATTRIBUTE ARAP-Security 73 integer +ATTRIBUTE ARAP-Security-Data 74 string +ATTRIBUTE Password-Retry 75 integer +ATTRIBUTE Prompt 76 integer +ATTRIBUTE Connect-Info 77 string +ATTRIBUTE Configuration-Token 78 string +ATTRIBUTE EAP-Message 79 string +ATTRIBUTE Message-Authenticator 80 octets +ATTRIBUTE Tunnel-Private-Group-Id 81 string +ATTRIBUTE Tunnel-Assignment-Id 82 string +ATTRIBUTE Tunnel-Preference 83 integer +ATTRIBUTE ARAP-Challenge-Response 84 string # 10 octets +ATTRIBUTE Acct-Interim-Interval 85 integer +ATTRIBUTE NAS-Port-Id 87 string +ATTRIBUTE Framed-Pool 88 string +ATTRIBUTE NAS-IPv6-Address 95 octets # really IPv6 +ATTRIBUTE Framed-Interface-Id 96 octets # 8 octets +ATTRIBUTE Framed-IPv6-Prefix 97 ipv6prefix # stupid format +ATTRIBUTE Login-IPv6-Host 98 octets # really IPv6 +ATTRIBUTE Framed-IPv6-Route 99 string +ATTRIBUTE Framed-IPv6-Pool 100 string +ATTRIBUTE Delegated-IPv6-Prefix 123 ipv6prefix + + +ATTRIBUTE Digest-Response 206 string +ATTRIBUTE Digest-Attributes 207 octets # stupid format + +# +# Experimental Non Protocol Attributes used by Cistron-Radiusd +# + +# These attributes CAN go in the reply item list. +ATTRIBUTE Fall-Through 500 integer +ATTRIBUTE Exec-Program 502 string +ATTRIBUTE Exec-Program-Wait 503 string + +# These attributes CANNOT go in the reply item list. +ATTRIBUTE User-Category 1029 string +ATTRIBUTE Group-Name 1030 string +ATTRIBUTE Huntgroup-Name 1031 string +ATTRIBUTE Simultaneous-Use 1034 integer +ATTRIBUTE Strip-User-Name 1035 integer +ATTRIBUTE Hint 1040 string +ATTRIBUTE Pam-Auth 1041 string +ATTRIBUTE Login-Time 1042 string +ATTRIBUTE Stripped-User-Name 1043 string +ATTRIBUTE Current-Time 1044 string +ATTRIBUTE Realm 1045 string +ATTRIBUTE No-Such-Attribute 1046 string +ATTRIBUTE Packet-Type 1047 integer +ATTRIBUTE Proxy-To-Realm 1048 string +ATTRIBUTE Replicate-To-Realm 1049 string +ATTRIBUTE Acct-Session-Start-Time 1050 date +ATTRIBUTE Acct-Unique-Session-Id 1051 string +ATTRIBUTE Client-IP-Address 1052 ipaddr +ATTRIBUTE Ldap-UserDn 1053 string +ATTRIBUTE NS-MTA-MD5-Password 1054 string +ATTRIBUTE SQL-User-Name 1055 string +ATTRIBUTE LM-Password 1057 octets +ATTRIBUTE NT-Password 1058 octets +ATTRIBUTE SMB-Account-CTRL 1059 integer +ATTRIBUTE SMB-Account-CTRL-TEXT 1061 string +ATTRIBUTE User-Profile 1062 string +ATTRIBUTE Digest-Realm 1063 string +ATTRIBUTE Digest-Nonce 1064 string +ATTRIBUTE Digest-Method 1065 string +ATTRIBUTE Digest-URI 1066 string +ATTRIBUTE Digest-QOP 1067 string +ATTRIBUTE Digest-Algorithm 1068 string +ATTRIBUTE Digest-Body-Digest 1069 string +ATTRIBUTE Digest-CNonce 1070 string +ATTRIBUTE Digest-Nonce-Count 1071 string +ATTRIBUTE Digest-User-Name 1072 string +ATTRIBUTE Pool-Name 1073 string +ATTRIBUTE Ldap-Group 1074 string +ATTRIBUTE Module-Success-Message 1075 string +ATTRIBUTE Module-Failure-Message 1076 string +# X99-Fast 1077 integer + +# +# Non-Protocol Attributes +# These attributes are used internally by the server +# +ATTRIBUTE Auth-Type 1000 integer +ATTRIBUTE Menu 1001 string +ATTRIBUTE Termination-Menu 1002 string +ATTRIBUTE Prefix 1003 string +ATTRIBUTE Suffix 1004 string +ATTRIBUTE Group 1005 string +ATTRIBUTE Crypt-Password 1006 string +ATTRIBUTE Connect-Rate 1007 integer +ATTRIBUTE Add-Prefix 1008 string +ATTRIBUTE Add-Suffix 1009 string +ATTRIBUTE Expiration 1010 date +ATTRIBUTE Autz-Type 1011 integer + +# +# Integer Translations +# + +# User Types + +VALUE Service-Type Login-User 1 +VALUE Service-Type pdate 2 +VALUE Service-Type Callback-Login-User 3 +VALUE Service-Type Callback-Framed-User 4 +VALUE Service-Type Outbound-User 5 +VALUE Service-Type Administrative-User 6 +VALUE Service-Type NAS-Prompt-User 7 +VALUE Service-Type Authenticate-Only 8 +VALUE Service-Type Callback-NAS-Prompt 9 +VALUE Service-Type Call-Check 10 +VALUE Service-Type Callback-Administrative 11 + +# Framed Protocols + +VALUE Framed-Protocol PPP 1 +VALUE Framed-Protocol SLIP 2 +VALUE Framed-Protocol ARAP 3 +VALUE Framed-Protocol Gandalf-SLML 4 +VALUE Framed-Protocol Xylogics-IPX-SLIP 5 +VALUE Framed-Protocol X.75-Synchronous 6 + +# Framed Routing Values + +VALUE Framed-Routing None 0 +VALUE Framed-Routing Broadcast 1 +VALUE Framed-Routing Listen 2 +VALUE Framed-Routing Broadcast-Listen 3 + +# Framed Compression Types + +VALUE Framed-Compression None 0 +VALUE Framed-Compression Van-Jacobson-TCP-IP 1 +VALUE Framed-Compression IPX-Header-Compression 2 +VALUE Framed-Compression Stac-LZS 3 + +# Login Services + +VALUE Login-Service Telnet 0 +VALUE Login-Service Rlogin 1 +VALUE Login-Service TCP-Clear 2 +VALUE Login-Service PortMaster 3 +VALUE Login-Service LAT 4 +VALUE Login-Service X25-PAD 5 +VALUE Login-Service X25-T3POS 6 +VALUE Login-Service TCP-Clear-Quiet 8 + +# Login-TCP-Port (see /etc/services for more examples) + +VALUE Login-TCP-Port Telnet 23 +VALUE Login-TCP-Port Rlogin 513 +VALUE Login-TCP-Port Rsh 514 + +# Status Types + +VALUE Acct-Status-Type Start 1 +VALUE Acct-Status-Type Stop 2 +VALUE Acct-Status-Type Interim-Update 3 +VALUE Acct-Status-Type Alive 3 +VALUE Acct-Status-Type Accounting-On 7 +VALUE Acct-Status-Type Accounting-Off 8 +# RFC 2867 Additional Status-Type Values +VALUE Acct-Status-Type Tunnel-Start 9 +VALUE Acct-Status-Type Tunnel-Stop 10 +VALUE Acct-Status-Type Tunnel-Reject 11 +VALUE Acct-Status-Type Tunnel-Link-Start 12 +VALUE Acct-Status-Type Tunnel-Link-Stop 13 +VALUE Acct-Status-Type Tunnel-Link-Reject 14 + +# Authentication Types + +VALUE Acct-Authentic RADIUS 1 +VALUE Acct-Authentic Local 2 + +# Termination Options + +VALUE Termination-Action Default 0 +VALUE Termination-Action RADIUS-Request 1 + +# NAS Port Types + +VALUE NAS-Port-Type Async 0 +VALUE NAS-Port-Type Sync 1 +VALUE NAS-Port-Type ISDN 2 +VALUE NAS-Port-Type ISDN-V120 3 +VALUE NAS-Port-Type ISDN-V110 4 +VALUE NAS-Port-Type Virtual 5 +VALUE NAS-Port-Type PIAFS 6 +VALUE NAS-Port-Type HDLC-Clear-Channel 7 +VALUE NAS-Port-Type X.25 8 +VALUE NAS-Port-Type X.75 9 +VALUE NAS-Port-Type G.3-Fax 10 +VALUE NAS-Port-Type SDSL 11 +VALUE NAS-Port-Type ADSL-CAP 12 +VALUE NAS-Port-Type ADSL-DMT 13 +VALUE NAS-Port-Type IDSL 14 +VALUE NAS-Port-Type Ethernet 15 +VALUE NAS-Port-Type xDSL 16 +VALUE NAS-Port-Type Cable 17 +VALUE NAS-Port-Type Wireless-Other 18 +VALUE NAS-Port-Type Wireless-802.11 19 + +# Acct Terminate Causes, available in 3.3.2 and later + +VALUE Acct-Terminate-Cause User-Request 1 +VALUE Acct-Terminate-Cause Lost-Carrier 2 +VALUE Acct-Terminate-Cause Lost-Service 3 +VALUE Acct-Terminate-Cause Idle-Timeout 4 +VALUE Acct-Terminate-Cause Session-Timeout 5 +VALUE Acct-Terminate-Cause Admin-Reset 6 +VALUE Acct-Terminate-Cause Admin-Reboot 7 +VALUE Acct-Terminate-Cause Port-Error 8 +VALUE Acct-Terminate-Cause NAS-Error 9 +VALUE Acct-Terminate-Cause NAS-Request 10 +VALUE Acct-Terminate-Cause NAS-Reboot 11 +VALUE Acct-Terminate-Cause Port-Unneeded 12 +VALUE Acct-Terminate-Cause Port-Preempted 13 +VALUE Acct-Terminate-Cause Port-Suspended 14 +VALUE Acct-Terminate-Cause Service-Unavailable 15 +VALUE Acct-Terminate-Cause Callback 16 +VALUE Acct-Terminate-Cause User-Error 17 +VALUE Acct-Terminate-Cause Host-Request 18 + +#VALUE Tunnel-Type L2TP 3 +#VALUE Tunnel-Medium-Type IP 1 + +VALUE Prompt No-Echo 0 +VALUE Prompt Echo 1 + +# +# Non-Protocol Integer Translations +# + +VALUE Auth-Type Local 0 +VALUE Auth-Type System 1 +VALUE Auth-Type SecurID 2 +VALUE Auth-Type Crypt-Local 3 +VALUE Auth-Type Reject 4 +VALUE Auth-Type ActivCard 5 +VALUE Auth-Type EAP 6 +VALUE Auth-Type ARAP 7 + +# +# Cistron extensions +# +VALUE Auth-Type Ldap 252 +VALUE Auth-Type Pam 253 +VALUE Auth-Type Accept 254 + +VALUE Auth-Type PAP 1024 +VALUE Auth-Type CHAP 1025 +VALUE Auth-Type LDAP 1026 +VALUE Auth-Type PAM 1027 +VALUE Auth-Type MS-CHAP 1028 +VALUE Auth-Type Kerberos 1029 +VALUE Auth-Type CRAM 1030 +VALUE Auth-Type NS-MTA-MD5 1031 +VALUE Auth-Type CRAM 1032 +VALUE Auth-Type SMB 1033 + +# +# Authorization type, too. +# +VALUE Autz-Type Local 0 + +# +# Experimental Non-Protocol Integer Translations for Cistron-Radiusd +# +VALUE Fall-Through No 0 +VALUE Fall-Through Yes 1 + +VALUE Packet-Type Access-Request 1 +VALUE Packet-Type Access-Accept 2 +VALUE Packet-Type Access-Reject 3 +VALUE Packet-Type Accounting-Request 4 +VALUE Packet-Type Accounting-Response 5 +VALUE Packet-Type Accounting-Status 6 +VALUE Packet-Type Password-Request 7 +VALUE Packet-Type Password-Accept 8 +VALUE Packet-Type Password-Reject 9 +VALUE Packet-Type Accounting-Message 10 +VALUE Packet-Type Access-Challenge 11 +VALUE Packet-Type Status-Server 12 +VALUE Packet-Type Status-Client 13 + +# Tunnel Type +VALUE Tunnel-Type PPTP 1 +VALUE Tunnel-Type L2F 2 +VALUE Tunnel-Type L2TP 3 +VALUE Tunnel-Type ATMP 4 +VALUE Tunnel-Type VTP 5 +VALUE Tunnel-Type AH 6 +VALUE Tunnel-Type IP 7 +VALUE Tunnel-Type MIN-IP 8 +VALUE Tunnel-Type ESP 9 +VALUE Tunnel-Type GRE 10 +VALUE Tunnel-Type DVS 11 +VALUE Tunnel-Type IP-in-IP 12 + +# Tunnel Medium Type +VALUE Tunnel-Medium-Type IP 1 +VALUE Tunnel-Medium-Type IPv4 1 +VALUE Tunnel-Medium-Type IPv6 2 +VALUE Tunnel-Medium-Type NSAP 3 +VALUE Tunnel-Medium-Type HDLC 4 +VALUE Tunnel-Medium-Type BBN-1822 5 +VALUE Tunnel-Medium-Type IEEE-802 6 +VALUE Tunnel-Medium-Type E.163 7 +VALUE Tunnel-Medium-Type E.164 8 +VALUE Tunnel-Medium-Type F.69 9 +VALUE Tunnel-Medium-Type X.121 10 +VALUE Tunnel-Medium-Type IPX 11 +VALUE Tunnel-Medium-Type Appletalk 12 +VALUE Tunnel-Medium-Type DecNet-IV 13 +VALUE Tunnel-Medium-Type Banyan-Vines 14 +VALUE Tunnel-Medium-Type E.164-NSAP 15 diff --git a/source/lib/python3/cmk/special_agents/dictionary.freeradius b/source/lib/python3/cmk/special_agents/dictionary.freeradius new file mode 100755 index 0000000000000000000000000000000000000000..0c083ce60c31143a461ce43d23887e16bd2a09b5 --- /dev/null +++ b/source/lib/python3/cmk/special_agents/dictionary.freeradius @@ -0,0 +1,155 @@ +# -*- text -*- +# Copyright (C) 2019 The FreeRADIUS Server project and contributors +# This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 +# +# The FreeRADIUS Vendor-Specific dictionary. +# +# Version: $Id: 14fed7af4e18885cf59c7f5211feb58e66c04b77 $ +# + +VENDOR FreeRADIUS 11344 + +BEGIN-VENDOR FreeRADIUS + +ATTRIBUTE FreeRADIUS-Proxied-To 1 ipaddr +ATTRIBUTE FreeRADIUS-Acct-Session-Start-Time 2 date + +# +# This attribute is really a bitmask. +# +ATTRIBUTE FreeRADIUS-Statistics-Type 127 integer + +VALUE FreeRADIUS-Statistics-Type None 0 +VALUE FreeRADIUS-Statistics-Type Authentication 1 +VALUE FreeRADIUS-Statistics-Type Accounting 2 +VALUE FreeRADIUS-Statistics-Type Proxy-Authentication 4 +VALUE FreeRADIUS-Statistics-Type Proxy-Accounting 8 +VALUE FreeRADIUS-Statistics-Type Internal 0x10 +VALUE FreeRADIUS-Statistics-Type Client 0x20 +VALUE FreeRADIUS-Statistics-Type Server 0x40 +VALUE FreeRADIUS-Statistics-Type Home-Server 0x80 + +VALUE FreeRADIUS-Statistics-Type Auth-Acct 0x03 +VALUE FreeRADIUS-Statistics-Type Proxy-Auth-Acct 0x0c + +VALUE FreeRADIUS-Statistics-Type All 0x1f + +# +# Global authentication statistics for packets received by the server. +# +ATTRIBUTE FreeRADIUS-Total-Access-Requests 128 integer +ATTRIBUTE FreeRADIUS-Total-Access-Accepts 129 integer +ATTRIBUTE FreeRADIUS-Total-Access-Rejects 130 integer +ATTRIBUTE FreeRADIUS-Total-Access-Challenges 131 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Responses 132 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Duplicate-Requests 133 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Malformed-Requests 134 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Invalid-Requests 135 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Dropped-Requests 136 integer +ATTRIBUTE FreeRADIUS-Total-Auth-Unknown-Types 137 integer + +# +# Global statistics for auth packets sent by the server to all home servers +# +ATTRIBUTE FreeRADIUS-Total-Proxy-Access-Requests 138 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Access-Accepts 139 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Access-Rejects 140 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Access-Challenges 141 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Responses 142 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Duplicate-Requests 143 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Malformed-Requests 144 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Invalid-Requests 145 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Dropped-Requests 146 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Auth-Unknown-Types 147 integer + +# +# Global accounting statistics for packets received by the server. +# +ATTRIBUTE FreeRADIUS-Total-Accounting-Requests 148 integer +ATTRIBUTE FreeRADIUS-Total-Accounting-Responses 149 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Duplicate-Requests 150 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Malformed-Requests 151 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Invalid-Requests 152 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Dropped-Requests 153 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Unknown-Types 154 integer + +# +# Global statistics for acct packets sent by the server to all home servers +# +ATTRIBUTE FreeRADIUS-Total-Proxy-Accounting-Requests 155 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Accounting-Responses 156 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Acct-Duplicate-Requests 157 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Acct-Malformed-Requests 158 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Acct-Invalid-Requests 159 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Acct-Dropped-Requests 160 integer +ATTRIBUTE FreeRADIUS-Total-Proxy-Acct-Unknown-Types 161 integer + +# +# Internal queues. Different packet types are put into different queues. +# +ATTRIBUTE FreeRADIUS-Queue-Len-Internal 162 integer +ATTRIBUTE FreeRADIUS-Queue-Len-Proxy 163 integer +ATTRIBUTE FreeRADIUS-Queue-Len-Auth 164 integer +ATTRIBUTE FreeRADIUS-Queue-Len-Acct 165 integer +ATTRIBUTE FreeRADIUS-Queue-Len-Detail 166 integer + +ATTRIBUTE FreeRADIUS-Stats-Client-IP-Address 167 ipaddr +ATTRIBUTE FreeRADIUS-Stats-Client-Number 168 integer +ATTRIBUTE FreeRADIUS-Stats-Client-Netmask 169 integer + +ATTRIBUTE FreeRADIUS-Stats-Server-IP-Address 170 ipaddr +ATTRIBUTE FreeRADIUS-Stats-Server-Port 171 integer + +ATTRIBUTE FreeRADIUS-Stats-Server-Outstanding-Requests 172 integer +ATTRIBUTE FreeRADIUS-Stats-Server-State 173 integer + +VALUE FreeRADIUS-Stats-Server-State Alive 0 +VALUE FreeRADIUS-Stats-Server-State Zombie 1 +VALUE FreeRADIUS-Stats-Server-State Dead 2 +VALUE FreeRADIUS-Stats-Server-State Idle 3 + +# +# When a home server is marked "dead" or "alive" +# +ATTRIBUTE FreeRADIUS-Stats-Server-Time-Of-Death 174 date +ATTRIBUTE FreeRADIUS-Stats-Server-Time-Of-Life 175 date + +# +# When this server was started. If start == hup, it hasn't been +# hup'd yet. This is friendlier than having hup == 0 on start. +# +ATTRIBUTE FreeRADIUS-Stats-Start-Time 176 date +ATTRIBUTE FreeRADIUS-Stats-HUP-Time 177 date +# ATTRIBUTE FreeRADIUS-Stats-Start-Time 176 integer +# ATTRIBUTE FreeRADIUS-Stats-HUP-Time 177 integer + +# +# Exponential moving average of home server response time +# Window-1 is the average is calculated over "window" packets. +# Window-10 is the average is calculated over "10 * window" packets. +# +# Both Window-1 and Window-10 are times in microseconds +# (1/1000000 of a second). +# +ATTRIBUTE FreeRADIUS-Server-EMA-Window 178 integer +ATTRIBUTE FreeRADIUS-Server-EMA-USEC-Window-1 179 integer +ATTRIBUTE FreeRADIUS-Server-EMA-USEC-Window-10 180 integer + +ATTRIBUTE FreeRADIUS-Queue-PPS-In 181 integer +ATTRIBUTE FreeRADIUS-Queue-PPS-Out 182 integer +ATTRIBUTE FreeRADIUS-Queue-Use-Percentage 183 integer + +ATTRIBUTE FreeRADIUS-Stats-Last-Packet-Recv 184 date +ATTRIBUTE FreeRADIUS-Stats-Last-Packet-Sent 185 date + +ATTRIBUTE FreeRADIUS-Stats-Error 187 string + +ATTRIBUTE FreeRADIUS-Stats-Client-IPv6-Address 188 ipv6addr +ATTRIBUTE FreeRADIUS-Stats-Server-IPv6-Address 189 ipv6addr + +# 190 is reserved + +ATTRIBUTE FreeRADIUS-Total-Auth-Conflicts 191 integer +ATTRIBUTE FreeRADIUS-Total-Acct-Conflicts 192 integer + +END-VENDOR FreeRADIUS diff --git a/source/packages/freeradius b/source/packages/freeradius new file mode 100644 index 0000000000000000000000000000000000000000..beaf0bd1c76398c7aa536be2c51e9b714a55bb6f --- /dev/null +++ b/source/packages/freeradius @@ -0,0 +1,23 @@ +{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)', + 'description': 'FreeRADIUS special agent\n' + '\n' + 'You need to enable the status server on the FreeRADIUS server ' + 'and make it\n' + 'accessible from the CMK site.\n' + '\n' + 'NOTE: this plugin needs _pyrad_ to work.\n', + 'download_url': 'https://thl-cmk.hopto.org', + 'files': {'agent_based': ['freeradius.py'], + 'agents': ['special/agent_freeradius'], + 'checks': ['agent_freeradius'], + 'gui': ['metrics/freeradius.py'], + 'lib': ['python3/cmk/special_agents/agent_freeradius.py', + 'python3/cmk/special_agents/dictionary', + 'python3/cmk/special_agents/dictionary.freeradius'], + 'web': ['plugins/wato/agent_freeradiusi.py']}, + 'name': 'freeradius', + 'title': 'FreeRADIUS special agent', + 'version': '0.1.1-20240430', + 'version.min_required': '2.2.0b1', + 'version.packaged': '2.2.0p24', + 'version.usable_until': '2.3.0b1'} diff --git a/source/web/plugins/wato/agent_freeradiusi.py b/source/web/plugins/wato/agent_freeradiusi.py new file mode 100644 index 0000000000000000000000000000000000000000..0b144518a762154a1462d25cec9015cf951d599d --- /dev/null +++ b/source/web/plugins/wato/agent_freeradiusi.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2024-04-29 +# File : wato/agent_freeradius.py +# + + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.special_agents.common import RulespecGroupDatasourceProgramsApps +from cmk.gui.plugins.wato.utils import HostRulespec, IndividualOrStoredPassword, rulespec_registry +from cmk.gui.valuespec import ( + Dictionary, + Integer, + # TextInput, + Transform, + ValueSpec, +) + + +def _valuespec_special_agent_freeradius() -> ValueSpec: + return Transform( + Dictionary( + title=_('FreeRADIUS'), + help=_(''), + elements=[ + # ('server', + # TextInput( + # title=_('Server IP-address or name'), + # help=_( + # 'Hostname or IP-address to monitor. Default is the host name/IP-Address of the monitored host.' + # ), + # size=50, + # allow_empty=False, + # placeholder='i.e 192.168.10.10 or srvrad01.company.intern' + # )), + ('auth_port', + Integer( + title=_('Authentication port'), + help=_('The RADIUS port to use for authentication. Default is 18121.'), + size=5, + default_value=18121, + minvalue=1, + maxvalue=65535, + )), + ('secret', + IndividualOrStoredPassword( + title=_('Shared secret'), + help=_('The shared secret.'), + allow_empty=False, + )), + ('timeout', + Integer( + title=_('Request timeout'), + help=_('The timeout for the RADIUS request.'), + default_value=2, + minvalue=1, + maxvalue=30, + unit='s', + )), + # ('user_name', + # TextInput( + # title=_('Username'), + # help=_('The username to use in the request.'), + # size=50, + # placeholder='username to use in the request', + # allow_empty=False, + # )), + # ('user_password', + # IndividualOrStoredPassword( + # title=_('User password'), + # help=_('The user password.'), + # allow_empty=False + # )), + ], + required_keys=[ + 'secret', + ] + ), + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupDatasourceProgramsApps, + name="special_agents:freeradius", + valuespec=_valuespec_special_agent_freeradius, + ) +)