diff --git a/agent_based/inv_cisco_wlc_clients.py b/agent_based/inv_cisco_wlc_clients.py new file mode 100644 index 0000000000000000000000000000000000000000..22cdf26d7f546ef73dd8b9fde74526c0852034bc --- /dev/null +++ b/agent_based/inv_cisco_wlc_clients.py @@ -0,0 +1,359 @@ +# !/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 : 2016-04-08 +# +# writen by: Th.L thl-cmk[at]outlook[dot]com +# +# 22.08.2016 : removed index column +# 09.04.2017 : added wato enable/disable, remove columns +# 04.09.2018 : changes for CMK 1.5.x (inv_tree --> inv_tree_list) +# + +import re +import time +import binascii +from typing import List, NamedTuple + +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + OIDEnd, + OIDBytes, +) +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + register, + SNMPTree, + TableRow, + contains, +) +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( + StringTable, + InventoryResult, +) + +_enable_disable = { + 0: 'N/A', + 1: 'enabled', + 2: 'disabled', +} + +_isaclapplied = { + 0: 'n/a', + 1: 'true', + 2: 'false', + 3: 'notavailable', +} + +_associationmode = { + 0: 'n/a', + 1: 'unknown', + 2: 'wep', + 3: 'wpa', + 4: 'wpa2', +} + +_authmode = { + 0: 'none', + 1: 'psk', + 2: 'radius', + 3: 'cckm', + 4: 'wapipsk', + 5: 'wapicert', + 6: 'ftdot1x', + 7: 'ftpsk', + 8: 'pmfdot1x', + 9: 'pmfpsk', +} + +_reasoncode = { + 0: 'n/a', + 1: 'unspecified', + 2: 'previousauthnotvalid', + 3: 'deauthenticationleaving', + 4: 'disassociationduetoinactivity', + 5: 'disassociationapbusy', + 6: 'class2framefromnonauthstation', + 7: 'class2framefromnonassstation', + 8: 'disassociationstahasleft', + 9: 'stareqassociationwithoutauth', + 10: 'invalidinformationelement', + 11: 'groupcipherinvalid', + 12: 'unicastcipherinvalid', + 13: 'akmpinvalid', + 14: 'unsupportedrsnversion', + 15: 'invalidrsniecapabilities', + 16: 'ciphersuiterejected', + 17: 'missingreasoncode', + 18: 'maxassociatedclientsreached', + 19: 'maxassociatedclientsreachedonradio', + 20: 'maxassociatedclientsreachedonwlan', + 21: 'unspecifiedqosfailure', + 22: 'qospolicymismatch', + 23: 'insufficientbandwidth', + 24: 'invalidqosparams', +} + +_authentication = { + 0: 'n/a', + 1: 'unknown', + 2: 'central', + 3: 'local', +} + +_dataswitching = { + 0: 'n/a', + 1: 'unknown', + 2: 'central', + 3: 'local', +} + +_hreapapauth = { + 0: 'n/a', + 1: 'true', + 2: 'false', + 3: 'notapplicable', +} + +_nacstate = { + 0: 'n/a', + 1: 'quarantine', + 2: 'access', +} + +_protocol = { + 0: 'n/a', + 1: '802.11a', + 2: '802.11b', + 3: '802.11g', + 4: 'unknown', + 5: 'mobile', + 6: '802.11n 2,4Ghz', + 7: '802.11n 5GHz', + 8: 'ethernet', + 9: 'dot3', + 10: '802.11ac 5GHz' +} + +_userauthtype = { + 0: 'n/a', + 1: 'open', + 2: 'wepPsk', + 3: 'portal', + 4: 'simPeap', + 5: 'other', +} + +_wgbstatus = { + 0: 'n/a', + 1: 'wireless client', + 2: 'wireless client via WGB', + 3: 'WGB itself', +} + +_clientstatus = { + 0: 'n/a', + 1: 'idle', + 2: 'aaa Pending', + 3: 'authenticated', + 4: 'associated', + 5: 'powersave', + 6: 'disassociated', + 7: 'to be deleted', + 8: 'probing', + 9: 'excluded', +} + +_interfacetype = { + 0: 'n/a', + 1: '802.11bg', + 2: '802.11a', + 3: 'Ultra wideband', + 4: '802.11abgn', + 5: '802.11ac', + 6: '802.11b', + 7: '802.11g', + 8: '802.11n 2.4GHz', + 9: '802.11n 5GHz', + 10: 'unknown', +} + +_powersavemode = { + 0: 'n/a', + 1: 'active', + 2: 'powersave', +} + + +def _render_mac_address(bytestring): + return ':'.join(['%02s' % hex(ord(m))[2:] for m in bytestring]).replace(' ', '0').upper() + + +def parse_inv_cisco_wlc_clients(string_table: StringTable): + clients = [] + + for client in string_table: + macaddress, status, wlanprofilename, wgbstatus, wgbmacaddress, protocol, associationmode, \ + apmacaddress, iftype, ipaddress, nacstate, quarantinevlan, accessvlan, logintime, uptime, \ + powersavemode, currenttxrateset, datarateset, hreapapauth, ieee80211ucapable, posturestate, \ + aclname, aclapplied, redirecturl, aaaoverrideaclname, aaaoverrideaclapplied, username, \ + ssid, securitytagid, typekts, ipv6aclname, ipv6aclapplied, dataswitching, authentication, \ + channel, authmode, reasoncode, sessionid, aproammacaddress, mdnsprofile, mdnsadvcount, \ + policyname, aaarole, devicetype, userauthtype = client + + clients.append({ + 'macaddress': _render_mac_address(macaddress), + 'username': username, + 'status_columns': { + 'status': _clientstatus.get(int(status)), + 'wlanprofilename': wlanprofilename, + 'wgbstatus': _wgbstatus.get(int(wgbstatus)), + 'wgbmacaddress': wgbmacaddress, + 'protocol': _protocol.get(int(protocol)), + 'associationmode': _associationmode.get(int(associationmode)), + 'apmacaddress': _render_mac_address(apmacaddress), + 'iftype': _interfacetype.get(int(iftype)), + 'ipaddress': ipaddress, + 'nacstate': _nacstate.get(int(nacstate)), + 'quarantinevlan': quarantinevlan, + 'accessvlan': accessvlan, + 'logintime': logintime, + 'uptime': uptime, + 'powersavemode': _powersavemode.get(int(powersavemode)), + 'currenttxrateset': currenttxrateset, + 'datarateset': datarateset, + 'hreapapauth': _hreapapauth.get(int(hreapapauth)), + 'ieee80211ucapable': _enable_disable.get(int(ieee80211ucapable)), + 'posturestate': _enable_disable.get(int(posturestate)), + 'aclname': aclname, + 'aclapplied': _isaclapplied.get(int(aclapplied)), + 'redirecturl': redirecturl, + 'aaaoverrideaclname': aaaoverrideaclname, + 'aaaoverrideaclapplied': _isaclapplied.get(int(aaaoverrideaclapplied)), + 'ssid': ssid, + 'securitytagid': securitytagid, + 'typekts': _enable_disable.get(int(typekts)), + 'ipv6aclname': ipv6aclname, + 'ipv6aclapplied': _isaclapplied.get(int(ipv6aclapplied)), + 'dataswitching': _dataswitching.get(int(dataswitching)), + 'authentication': _authentication.get(int(authentication)), + 'channel': channel, + 'authmode': _authmode.get(int(authmode)), + 'reasoncode': _reasoncode.get(int(reasoncode)), + 'sessionid': sessionid, + 'aproammacaddress': _render_mac_address(aproammacaddress), + 'mdnsprofile': mdnsprofile, + 'mdnsadvcount': mdnsadvcount, + 'policyname': policyname, + 'aaarole': aaarole, + 'devicetype': devicetype, + 'userauthtype': _userauthtype.get(int(userauthtype)), + }, + }) + + return clients + + +def inventory_cisco_wlc_clients(params, section) -> InventoryResult: + removecolumns = [] + + if params: + removecolumns = params.get('removecolumns', removecolumns) + + path = ['networking', 'wlan', 'controller', 'clients'] + + for client in section: + key_columns = {'username': client['username']} # 'macaddress': client['macaddress'], + + for key in key_columns.keys(): + client.pop(key) + + status_columns = client['status_columns'] + + client.pop('status_columns') + + for entry in removecolumns: + try: + client.pop(entry) + except KeyError: + pass + + for entry in removecolumns: + try: + status_columns.pop(entry) + except KeyError: + pass + + yield TableRow( + path=path, + key_columns=key_columns, + inventory_columns=client, + status_columns=status_columns, + ) + + +register.snmp_section( + name='inv_cisco_wlc_clients', + parse_function=parse_inv_cisco_wlc_clients, + fetch= + SNMPTree( + base='.1.3.6.1.4.1.9.9.599.1.3.1.1', # CISCO-LWAPP-DOT11-CLIENT-MIB::cldcClientEntry + oids=[ + '1', # cldcClientMacAddress + '2', # cldcClientStatus + '3', # cldcClientWlanProfileName + '4', # cldcClientWgbStatus + '5', # cldcClientWgbMacAddress + '6', # cldcClientProtocol + '7', # cldcAssociationMode + '8', # cldcApMacAddress + '9', # cldcIfType + '10', # cldcClientIPAddress + '11', # cldcClientNacState + '12', # cldcClientQuarantineVLAN + '13', # cldcClientAccessVLAN + '14', # cldcClientLoginTime + '15', # cldcClientUpTime + '16', # cldcClientPowerSaveMode + '17', # cldcClientCurrentTxRateSet + '18', # cldcClientDataRateSet + '19', # cldcClientHreapApAuth + '20', # cldcClient80211uCapable + '21', # cldcClientPostureState + '22', # cldcClientAclName + '23', # cldcClientAclApplied + '24', # cldcClientRedirectUrl + '25', # cldcClientAaaOverrideAclName + '26', # cldcClientAaaOverrideAclApplied + '27', # cldcClientUsername + '28', # cldcClientSSID + '29', # cldcClientSecurityTagId + '30', # cldcClientTypeKTS + '31', # cldcClientIpv6AclName + '32', # cldcClientIpv6AclApplied + '33', # cldcClientDataSwitching + '34', # cldcClientAuthentication + '35', # cldcClientChannel + '36', # cldcClientAuthMode + '37', # cldcClientReasonCode + '38', # cldcClientSessionID + '39', # cldcClientApRoamMacAddress + '40', # cldcClientMdnsProfile + '41', # cldcClientMdnsAdvCount + '42', # cldcClientPolicyName + '43', # cldcClientAAARole + '44', # cldcClientDeviceType + '45', # cldcUserAuthType + ] + ), + detect=contains('.1.3.6.1.2.1.1.1.0', 'Cisco Controller'), # sysDescr +) + +register.inventory_plugin( + name='inv_cisco_wlc_clients', + inventory_function=inventory_cisco_wlc_clients, + inventory_default_parameters={}, + inventory_ruleset_name='inv_cisco_wlc_clients', +) diff --git a/inv_cisco_wlc_clients.mkp b/inv_cisco_wlc_clients.mkp index 4facc63014381ee7aa769545352a359b3f0f3342..c535701f48a4109b599a77e834c6213f5d3ac7a6 100644 Binary files a/inv_cisco_wlc_clients.mkp and b/inv_cisco_wlc_clients.mkp differ diff --git a/packages/inv_cisco_wlc_clients b/packages/inv_cisco_wlc_clients index d20a3f7af7ff9e11770d55f0af5a51463841b695..654f42d021e894600208a5419945df1c22bb6ca3 100644 --- a/packages/inv_cisco_wlc_clients +++ b/packages/inv_cisco_wlc_clients @@ -1,12 +1,21 @@ -{'author': u'Th.L. (thl-cmk[at]outlook[dot]com)', - 'description': u'SNMP inventory of Cisco WLC clients.\n\nVia WATO you can:\n - enable/disable this inventory\n - can add/remove some fields\n\nTested with Cisco WLC 5520/5505/2504.\n\n2020-03.15: added support for CMK1.6x\n', +{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)', + 'description': 'SNMP inventory of Cisco WLC clients.\n' + '\n' + 'Via WATO you can:\n' + ' - can add/remove some fields\n' + '\n' + 'Tested with Cisco WLC 5520/5505/2504.\n' + '\n' + '2020-03.15: added support for CMK1.6x\n' + '2021-07-12: rewritten for CMK 2.0\n', 'download_url': 'http://thl-cmk.hopto.org', - 'files': {'inventory': ['snmp_cisco_wlc_clients'], - 'web': ['plugins/views/inv_wlc_clients.py', - 'plugins/wato/inv_wlc_clients.py']}, + 'files': {'agent_based': ['inv_cisco_wlc_clients.py'], + 'web': ['plugins/views/inv_cisco_wlc_clients.py', + 'plugins/wato/inv_cisco_wlc_clients.py']}, 'name': 'inv_cisco_wlc_clients', 'num_files': 3, - 'title': u'inventory of cisco WLC clients', - 'version': '20200513.v0.2c', - 'version.min_required': '1.4.0p1', - 'version.packaged': '1.6.0p8'} \ No newline at end of file + 'title': 'inventory of cisco WLC clients', + 'version': '20210712.v0.3', + 'version.min_required': '2.0.0', + 'version.packaged': '2021.04.10', + 'version.usable_until': None} \ No newline at end of file diff --git a/web/plugins/views/inv_cisco_wlc_clients.py b/web/plugins/views/inv_cisco_wlc_clients.py new file mode 100644 index 0000000000000000000000000000000000000000..b8796ed2549127792d4371201252b3584a154266 --- /dev/null +++ b/web/plugins/views/inv_cisco_wlc_clients.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import cmk.gui.utils +from cmk.gui.plugins.views import ( + inventory_displayhints,) +from cmk.gui.i18n import _ + + +inventory_displayhints.update({ + '.networking.wlan.controller.clients:': {'title' : _('WLC clients'), + 'keyorder': ['username', 'uptime', 'ipaddress', 'apmacaddress', 'ssid', + 'channel', 'accessvlan', 'devicetype', 'protocol', 'status', + ], + 'view' : 'invwlcclients_of_host'}, + + '.networking.wlan.controller.clients:*.macaddress' : { 'title' : _('MAC Addresse'), }, + '.networking.wlan.controller.clients:*.status' : { 'title' : _('Status'), }, + '.networking.wlan.controller.clients:*.wlanprofilename' : { 'title' : _('WLAN profile name'), }, + '.networking.wlan.controller.clients:*.wgbstatus' : { 'title' : _('WGB status'), }, + '.networking.wlan.controller.clients:*.wgbmacaddress' : { 'title' : _('WGB MAC address'), }, + '.networking.wlan.controller.clients:*.protocol' : { 'title' : _('Protocol'), }, + '.networking.wlan.controller.clients:*.associationmode' : { 'title' : _('Association mode'), }, + '.networking.wlan.controller.clients:*.apmacaddress' : { 'title' : _('AP MAC address'), }, + '.networking.wlan.controller.clients:*.iftype' : { 'title' : _('Interface type'), }, + '.networking.wlan.controller.clients:*.ipaddress' : { 'title' : _('IP address'), }, + '.networking.wlan.controller.clients:*.nacstate' : { 'title' : _('NAC state'), }, + '.networking.wlan.controller.clients:*.quarantinevlan' : { 'title' : _('Quarantine VLAN'), }, + '.networking.wlan.controller.clients:*.accessvlan' : { 'title' : _('Access VLAN'), }, + '.networking.wlan.controller.clients:*.logintime' : { 'title' : _('Login time'), }, + '.networking.wlan.controller.clients:*.uptime' : { 'title' : _('Uptime'), }, + '.networking.wlan.controller.clients:*.powersavemode' : { 'title' : _('Power save mode'), }, + '.networking.wlan.controller.clients:*.currenttxrateset' : { 'title' : _('Current TX rate (MBit/s)'), }, + '.networking.wlan.controller.clients:*.datarateset' : { 'title' : _('Data rate set'), }, + '.networking.wlan.controller.clients:*.hreapapauth' : { 'title' : _('HREAP AP auth'), }, + '.networking.wlan.controller.clients:*.ieee80211ucapable' : { 'title' : _('802.11u capable'), }, + '.networking.wlan.controller.clients:*.posturestate' : { 'title' : _('Posture state'), }, + '.networking.wlan.controller.clients:*.aclname' : { 'title' : _('ACL name'), }, + '.networking.wlan.controller.clients:*.aclapplied' : { 'title' : _('ACL applied'), }, + '.networking.wlan.controller.clients:*.redirecturl' : { 'title' : _('Redirect URL'), }, + '.networking.wlan.controller.clients:*.aaaoverrideaclname' : { 'title' : _('AAA overide ACL name'), }, + '.networking.wlan.controller.clients:*.aaaoverrideaclapplied' : { 'title' : _('AAA overide ACL applied'), }, + '.networking.wlan.controller.clients:*.username' : { 'title' : _('Username'), }, + '.networking.wlan.controller.clients:*.ssid' : { 'title' : _('SSID'), }, + '.networking.wlan.controller.clients:*.securitytagid' : { 'title' : _('Security tag ID'), }, + '.networking.wlan.controller.clients:*.typekts' : { 'title' : _('NEC KTS SIP client'), }, + '.networking.wlan.controller.clients:*.ipv6aclname' : { 'title' : _('IPv6 ACL name'), }, + '.networking.wlan.controller.clients:*.ipv6aclapplied' : { 'title' : _('IPv6 ACL applied'), }, + '.networking.wlan.controller.clients:*.dataswitching' : { 'title' : _('Data switching'), }, + '.networking.wlan.controller.clients:*.authentication' : { 'title' : _('Authentication'), }, + '.networking.wlan.controller.clients:*.channel' : { 'title' : _('Channel'), }, + '.networking.wlan.controller.clients:*.authmode' : { 'title' : _('Auth mode'), }, + '.networking.wlan.controller.clients:*.reasoncode' : { 'title' : _('Reason code'), }, + '.networking.wlan.controller.clients:*.sessionid' : { 'title' : _('Session ID'), }, + '.networking.wlan.controller.clients:*.aproammacaddress' : { 'title' : _('AP roam MAC address'), }, + '.networking.wlan.controller.clients:*.mdnsprofile' : { 'title' : _('mDNS profile'), }, + '.networking.wlan.controller.clients:*.mdnsadvcount' : { 'title' : _('mDNS adv count'), }, + '.networking.wlan.controller.clients:*.policyname' : { 'title' : _('Policy name'), }, + '.networking.wlan.controller.clients:*.aaarole' : { 'title' : _('AAA role'), }, + '.networking.wlan.controller.clients:*.devicetype' : { 'title' : _('Device type'), }, + '.networking.wlan.controller.clients:*.userauthtype' : { 'title' : _('User auth type'), }, + +# '.networking.wlan.controller.clients:*.certificate_type' : { 'title' : _('Certificate type'), 'short' : _('Cert type'), 'filter' : visuals.FilterInvtableWLCCertType, 'paint' : 'wlc_cert_type' }, + +}) + + +from cmk.gui.plugins.views.inventory import declare_invtable_view + +declare_invtable_view('invwlcclients', '.networking.wlan.controller.clients:', _('WLC clients'), _('WLC clients')) diff --git a/web/plugins/wato/inv_cisco_wlc_clients.py b/web/plugins/wato/inv_cisco_wlc_clients.py new file mode 100644 index 0000000000000000000000000000000000000000..f56883dc12252782ea6853fe9a6c3ef3cd8aac12 --- /dev/null +++ b/web/plugins/wato/inv_cisco_wlc_clients.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato import ( + HostRulespec, + rulespec_registry, +) +from cmk.gui.valuespec import ( + Dictionary, + ListChoice, +) + +from cmk.gui.plugins.wato.inventory import ( + RulespecGroupInventory, +) + +removecolumns = [ + ('ieee80211ucapable', '802.11u capable'), + ('aaaoverrideaclapplied', 'AAA overide ACL applied'), + ('aaaoverrideaclname', 'AAA overide ACL name'), + ('aaarole', 'AAA role'), + ('accessvlan', 'Access VLAN'), + ('aclapplied', 'ACL applied'), + ('aclname', 'ACL name'), + # ('apmacaddress' ,'AP MAC address'), + ('aproammacaddress', 'AP roam MAC address'), + ('associationmode', 'Association mode'), + ('authentication', 'Authentication'), + ('authmode', 'Auth mode'), + # ('channel' ,'Channel'), + ('currenttxrateset', 'Current TX rate (MBit/s)'), + ('datarateset', 'Data rate set'), + ('dataswitching', 'Data switching'), + # ('devicetype' ,'Device type'), + ('hreapapauth', 'HREAP AP auth'), + ('iftype', 'Interface type'), + # ('ipaddress' ,'IP address'), + ('ipv6aclapplied', 'IPv6 ACL applied'), + ('ipv6aclname', 'IPv6 ACL name'), + ('logintime', 'Login time'), + ('macaddress', 'MAC Addresse'), + ('mdnsadvcount', 'mDNS adv count'), + ('mdnsprofile', 'mDNS profile'), + ('nacstate', 'NAC state'), + ('policyname', 'Policy name'), + ('posturestate', 'Posture state'), + ('powersavemode', 'Power save mode'), + # ('protocol' ,'Protocol'), + ('quarantinevlan', 'Quarantine VLAN'), + ('reasoncode', 'Reason code'), + ('redirecturl', 'Redirect URL'), + ('securitytagid', 'Security tag ID'), + ('sessionid', 'Session ID'), + # ('ssid' ,'SSID'), + # ('status' ,'Status'), + ('typekts', 'NEC KTS SIP client'), + # ('uptime' ,'Uptime'), + ('userauthtype', 'User auth type'), + # ('username' ,'Username'), + ('wgbmacaddress', 'WGB MAC address'), + ('wgbstatus', 'WGB status'), + ('wlanprofilename', 'WLAN profile name'), +] + + +def _valuespec_inv_cisco_wlc_clients(): + return Dictionary( + title=_('Cisco WLC Client inventory'), + elements=[ + ('removecolumns', + ListChoice( + title=_('list of columns to remove'), + help=_('information to remove from inventory'), + choices=removecolumns, + default_value=[ + ], + )), + ], + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupInventory, + match_type='dict', + name='inv_cisco_wlc_clients', + valuespec=_valuespec_inv_cisco_wlc_clients, + ))