From 6ca653e4200f18926a34bb82323931cc71f52e8a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 21 May 2018 16:21:28 +0200 Subject: T652: first SNMP version using XML interface definition --- interface-definitions/snmp.xml | 539 +++++++++++++++++++++++++++++++++++++++++ src/conf_mode/snmp.py | 234 ++++++++++++++++++ 2 files changed, 773 insertions(+) create mode 100644 interface-definitions/snmp.xml create mode 100755 src/conf_mode/snmp.py diff --git a/interface-definitions/snmp.xml b/interface-definitions/snmp.xml new file mode 100644 index 000000000..bcd5295ee --- /dev/null +++ b/interface-definitions/snmp.xml @@ -0,0 +1,539 @@ + + + + + + + + Simple Network Management Protocol (SNMP) + 980 + + + + + Community name [REQUIRED] + + ^[^%]+$ + + Community string may not contain '%' + + + + + Authorization type (rw or ro) (default: 'ro') + + (ro|rw) + + Authorization type must be either 'rw' or 'ro' + + + + + IP address of SNMP client allowed to contact system + + + + + + + + + + Subnet of SNMP client(s) allowed to contact system + + ipv4net + IP address and prefix length + + + ipv6net + IPv6 address and prefix length + + + + + + + + + + + + Contact information + + .{1,255} + + Contact information is limited to 255 characters or less + + + + + Description information + + .{1,255} + + Description is limited to 255 characters or less + + + + + IP address to listen for incoming SNMP requests + + + + + + + + + Port for SNMP service (default: '161') + + 1-65535 + Numeric IP port + + + + + Port number must be in range 1 to 65535 + + + + + + + Location information + + .{1,255} + + Location is limited to 255 characters or less + + + + + Register a subtree for SMUX-based processing + + oid + Object Identifier + + + + + + + SNMP trap source address + + + + + + + + + Address of trap target + + + + + + + + + Community used when sending trap information + + + + + Destination port used for trap notification + + 1-65535 + Numeric IP port + + + + + Port number must be in range 1 to 65535 + + + + + + + Simple Network Management Protocol (SNMP) v3 + + + + + Specifies the EngineID that uniquely identify an agent (e.g. 0xff42) + + ^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$ + + ID must contain an even number (from 2 to 36) of hex digits + + + + + Specifies the group with name groupname + + + + + Define group access permission (default: 'ro') + + ro + read only + + + rw + read write + + + (ro|rw) + + Authorization type must be either 'rw' or 'ro' + + + + + Defines security level + + (auth|priv) + + + + + + + Defines the name of view + + service snmp v3 view + + + + + + + + Defines SNMP target for inform or traps for IP + + ipv4 + IP address of trap target + + + ipv6 + IPv6 address of trap target + + + + + + + + + + Defines the privacy + + + + + Defines the encrypted key for authentication + + ^0x[0-9a-f]*$ + + Key must start from '0x' and contain hex digits + + + + + Defines the clear text key for authentication + + ^.{8,}$ + + Key must contain 8 or more characters + + + + + Defines the protocol used for authentication (default: 'md5') + + md5 + Message Digest 5 + + + sha + Secure Hash Algorithm + + + (md5|sha) + + + + + + + + Specifies the EngineID that uniquely identify an agent (e.g. 0xff42) + + ^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$ + + ID must contain from 2 to 36 hex digits + + + + + Specifies TCP/UDP port of destination SNMP traps/informs (default: '162') + + 1-65535 + Numeric IP port + + + + + Port number must be in range 1 to 65535 + + + + + Defines the privacy + + + + + Defines the encrypted key for privacy protocol + + ^0x[0-9a-f]*$ + + Key must start from '0x' and contain hex digits + + + + + Defines the clear text key for privacy protocol + + ^.{8,}$ + + Key must contain 8 or more characters + + + + + Defines the protocol for privacy (default: 'des') + + des + Data Encryption Standard + + + aes + Advanced Encryption Standard + + + (des|aes) + + + + + + + + Defines protocol for notification between TCP and UDP + + tcp + Use Transmission Control Protocol for notifications + + + udp + Use User Datagram Protocol for notifications + + + (tcp|udp) + + + + + + Specifies the type of notification between inform and trap (default: 'inform') + + inform + Use INFORM + + + trap + Use TRAP + + + (inform|trap) + + + + + + Defines username for authentication + + service snmp v3 user + + + + + + + + Specifies that the snmpd uses encryption + + + + + Defines the server certificate fingerprint or key-file name + + + + + Defines the port for TSM (default: '10161') + + 1-65535 + Numeric IP port + + + + + Port number must be in range 1 to 65535 + + + + + + + Specifies the user with name username + + ^[^\(\)\|\-]+$ + + Illegal characters in name + + + + + Specifies the auth + + + + + Defines the encrypted key for authentication + + ^0x[0-9a-f]*$ + + Key must start from '0x' and contain hex digits + + + + + Defines the clear text key for authentication + + ^.{8,}$ + + Key must contain 8 or more characters + + + + + Defines the protocol used for authentication (default: 'md5') + + md5 + Message Digest 5 + + + sha + Secure Hash Algorithm + + + (md5|sha) + + + + + + + + Specifies the EngineID that uniquely identify an agent (e.g. 0xff42) + + ^(0x){0,1}([0-9a-f][0-9a-f]){1,18}$ + + ID must contain from 2 to 36 hex digits + + + + + Specifies group for user name + + service snmp v3 group + + + + + + Define users access permission (default: 'ro') + + ro + read only + + + rw + read write + + + (ro|rw) + + Authorization type must be either 'rw' or 'ro' + + + + + Defines the privacy + + + + + Defines the encrypted key for privacy protocol + + ^0x[0-9a-f]*$ + + Key must start from '0x' and contain hex digits + + + + + Defines the clear text key for privacy protocol + + ^.{8,}$ + + Key must contain 8 or more characters + + + + + Defines the protocol for privacy (default: 'des') + + des + Data Encryption Standard + + + aes + Advanced Encryption Standard + + + (des|aes) + + + + + + Specifies finger print or file name of TSM certificate + + + + + + + + + + + + + diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py new file mode 100755 index 000000000..d32a9a343 --- /dev/null +++ b/src/conf_mode/snmp.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# + +import sys +import os + +import jinja2 + +from vyos.config import Config +from vyos import ConfigError + +import vyos.version + +config_file_client = r'/etc/snmp/snmp.conf' +config_file_daemon = r'/etc/snmp/snmpd.conf' + +# SNMPS template - be careful if you edit the template. +client_config_tmpl = """ +### Autogenerated by snmp.py ### +{% if trap_source -%} +clientaddr {{ trap_source }} +{% endif %} + +""" + +# SNMPS template - be careful if you edit the template. +daemon_config_tmpl = """ +### Autogenerated by snmp.py ### +# non configurable defaults +sysObjectID 1.3.6.1.4.1.44641 +sysServices 14 +# maybe needed by lldpd +master agentx +agentXPerms 0755 0755 +# add hook to read IF-MIB::ifAlias from sysfs +pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias +# ospfd +smuxpeer .1.3.6.1.4.1.3317.1.2.2 +# bgpd +smuxpeer .1.3.6.1.4.1.3317.1.2.5 +# ripd +smuxpeer .1.3.6.1.4.1.3317.1.2.3 +# mribd +smuxpeer .1.3.6.1.4.1.3317.1.2.9 +# mribd +smuxpeer .1.3.6.1.2.1.83 +# pimd +smuxpeer .1.3.6.1.4.1.3317.1.2.8 +# pimd +smuxpeer .1.3.6.1.2.1.157 +smuxsocket localhost + +# linkUp/Down configure the Event MIB tables to monitor +# the ifTable for network interfaces being taken up or down +# for making internal queries to retrieve any necessary information +# create an internal snmpv3 user of the form 'vyattaxxxxxxxxxxxxxxxx' +## TODO!!!! +iquerySecName vyatta3392514e4189da84 + +# Modified from the default linkUpDownNotification +# to include more OIDs and poll more frequently +notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus +notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus +monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2 +monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2 + +######################## +# configurable section # +######################## + +# Version +sysDescr VyOS {{ version }} + +{% if description -%} +# Description +SysDescr {{ description }} +{% endif %} + +# Listen +agentaddress unix:/run/snmpd.socket{% for ip in listen_on %},udp:{{ ip.addr }}:{{ ip.port }}{% endfor %} + + +# SNMP communities +{% if communities -%} +{% for c in communities %} +{% if c.network -%} +{% for network in c.network %} +{{ c.authorization }}community {{ c.name }} {{ network }} +{% endfor %} +{% else %} +{{ c.authorization }}community {{ c.name }} +{% endif %} +{% endfor %} +{% endif %} + +{% if contact -%} +# system contact information +SysContact {{ contact }} +{% endif %} + +{% if location -%} +# system location information +SysLocation {{ location }} +{% endif %} + +{% if smux_peers -%} +# additional smux peers +{% for sp in smux_peers %} +smuxpeer {{ sp }} +{% endfor %} +{% endif %} + +""" + +default_config_data = { + 'listen_on': [], + 'location' : '', + 'description' : '', + 'contact' : '', + 'communities': [], + 'trap_source': '', + 'smux_peers': [] +} + +def get_config(): + snmp = default_config_data + conf = Config() + if not conf.exists('service snmp'): + return None + else: + conf.set_level('service snmp') + + version_data = vyos.version.get_version_data() + snmp.setdefault('version', version_data['version']) + + if conf.exists('community'): + for name in conf.list_nodes('community'): + community = { + 'name': name, + 'authorization': 'ro', + 'network': [] + } + + if conf.exists('community {0} authorization'.format(name)): + community['authorization'] = conf.return_value('community {0} authorization'.format(name)) + + if conf.exists('community {0} network'.format(name)): + community['network'] = conf.return_values('community {0} network'.format(name)) + + snmp['communities'].append(community) + + if conf.exists('contact'): + snmp['contact'] = conf.return_value('contact') + + if conf.exists('description'): + snmp['description'] = conf.return_value('description') + + if conf.exists('listen-address'): + for addr in conf.list_nodes('listen-address'): + listen = { + 'addr': addr, + 'port': '161' + } + + if conf.exists('listen-address {0} port'.format(addr)): + listen['port'] = conf.return_value('listen-address {0} port'.format(addr)) + + snmp['listen_on'].append(listen) + + if conf.exists('location'): + snmp['location'] = conf.return_value('location') + + if conf.exists('smux-peer'): + snmp['smux_peers'] = conf.return_values('smux-peer') + + if conf.exists('trap-source'): + snmp['trap_source'] = conf.return_value('trap-source') + + return snmp + +def verify(snmp): + return None + +def generate(snmp): + if snmp is None: + return None + + tmpl = jinja2.Template(client_config_tmpl, trim_blocks=True) + config_text = tmpl.render(snmp) + with open(config_file_client, 'w') as f: + f.write(config_text) + + tmpl = jinja2.Template(daemon_config_tmpl, trim_blocks=True) + config_text = tmpl.render(snmp) + with open(config_file_daemon, 'w') as f: + f.write(config_text) + + return None + +def apply(snmp): + if snmp is not None: + os.system("sudo systemctl restart snmpd.service") + else: + # SNMP is removed in the commit + os.system("sudo systemctl stop snmpd.service") + os.unlink(config_file_client) + os.unlink(config_file_daemon) + + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + sys.exit(1) -- cgit v1.2.3