diff options
Diffstat (limited to 'src/conf_mode/snmp.py')
-rwxr-xr-x | src/conf_mode/snmp.py | 225 |
1 files changed, 37 insertions, 188 deletions
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index ac94afb1a..4a69e8742 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -15,18 +15,20 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import jinja2 - -import vyos.version -import vyos.validate from binascii import hexlify from time import sleep from stat import S_IRWXU, S_IXGRP, S_IXOTH, S_IROTH, S_IRGRP from sys import exit +from jinja2 import FileSystemLoader, Environment from vyos.config import Config +from vyos.defaults import directories as vyos_data_dir +from vyos.validate import is_ipv4, is_addr_assigned +from vyos.version import get_version_data from vyos import ConfigError +from vyos.util import call + config_file_client = r'/etc/snmp/snmp.conf' config_file_daemon = r'/etc/snmp/snmpd.conf' @@ -43,171 +45,10 @@ OIDs = { 'none': '.1.3.6.1.6.3.10.1.2.1' } -# SNMP template (/etc/snmp/snmp.conf) - be careful if you edit the template. -client_config_tmpl = """ -### Autogenerated by snmp.py ### -{% if trap_source -%} -clientaddr {{ trap_source }} -{% endif %} - -""" - -# SNMP template (/usr/share/snmp/snmpd.conf) - be careful if you edit the template. -access_config_tmpl = """ -### Autogenerated by snmp.py ### -{%- for u in v3_users %} -{{ u.mode }}user {{ u.name }} -{%- endfor %} - -rwuser {{ vyos_user }} - -""" - -# SNMP template (/var/lib/snmp/snmpd.conf) - be careful if you edit the template. -user_config_tmpl = """ -### Autogenerated by snmp.py ### -# user -{%- for u in v3_users %} -{%- if u.authOID == 'none' %} -createUser {{ u.name }} -{%- elif u.authPassword %} -createUser {{ u.name }} {{ u.authProtocol | upper }} "{{ u.authPassword }}" {{ u.privProtocol | upper }} {{ u.privPassword }} -{%- else %} -usmUser 1 3 {{ v3_engineid }} "{{ u.name }}" "{{ u.name }}" NULL {{ u.authOID }} {{ u.authMasterKey }} {{ u.privOID }} {{ u.privMasterKey }} 0x -{%- endif %} -{%- endfor %} - -createUser {{ vyos_user }} MD5 "{{ vyos_user_pass }}" DES -{%- if v3_engineid %} -oldEngineID {{ v3_engineid }} -{%- endif %} -""" - -# SNMP template (/etc/snmp/snmpd.conf) - 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 -master agentx -agentXPerms 0777 0777 -pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias -smuxpeer .1.3.6.1.2.1.83 -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 -iquerySecName {{ vyos_user }} - -# 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 # -######################## - -# Default system description is VyOS version -sysDescr VyOS {{ version }} - -{% if description %} -# Description -SysDescr {{ description }} -{%- endif %} - -# Listen -agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},udp:161,udp6:161{% endif %} - -# SNMP communities -{%- for c in communities %} - -{%- if c.network_v4 %} -{%- for network in c.network_v4 %} -{{ c.authorization }}community {{ c.name }} {{ network }} -{%- endfor %} -{%- elif not c.has_source %} -{{ c.authorization }}community {{ c.name }} -{%- endif %} - -{%- if c.network_v6 %} -{%- for network in c.network_v6 %} -{{ c.authorization }}community6 {{ c.name }} {{ network }} -{%- endfor %} -{%- elif not c.has_source %} -{{ c.authorization }}community6 {{ c.name }} -{%- endif %} - -{%- endfor %} - -{% 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 %} - -{% if trap_targets -%} -# if there is a problem - tell someone! -{%- for t in trap_targets %} -trap2sink {{ t.target }}{% if t.port -%}:{{ t.port }}{% endif %} {{ t.community }} -{%- endfor %} -{%- endif %} - -{%- if v3_enabled %} -# -# SNMPv3 stuff goes here -# -# views -{%- for v in v3_views %} -{%- for oid in v.oids %} -view {{ v.name }} included .{{ oid.oid }} -{%- endfor %} -{%- endfor %} - -# access -# context sec.model sec.level match read write notif -{%- for g in v3_groups %} -access {{ g.name }} "" usm {{ g.seclevel }} exact {{ g.view }} {% if g.mode == 'ro' %}none{% else %}{{ g.view }}{% endif %} none -{%- endfor %} - -# trap-target -{%- for t in v3_traps %} -trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ v3_engineid }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }} -{%- endfor %} - -# group -{%- for u in v3_users %} -group {{ u.group }} usm {{ u.name }} -{% endfor %} -{%- endif %} - -{% if script_ext %} -# extension scripts -{%- for ext in script_ext|sort(attribute='name') %} -extend {{ ext.name }} {{ ext.script }} -{%- endfor %} -{% endif %} -""" - default_config_data = { 'listen_on': [], 'listen_address': [], + 'ipv6_enabled': 'True', 'communities': [], 'smux_peers': [], 'location' : '', @@ -237,9 +78,12 @@ def get_config(): if not conf.exists('service snmp'): return None else: + if conf.exists('system ipv6 disable'): + snmp['ipv6_enabled'] = False + conf.set_level('service snmp') - version_data = vyos.version.get_version_data() + version_data = get_version_data() snmp['version'] = version_data['version'] # create an internal snmpv3 user of the form 'vyosxxxxxxxxxxxxxxxx' @@ -263,7 +107,7 @@ def get_config(): # Subnet of SNMP client(s) allowed to contact system if conf.exists('community {0} network'.format(name)): for addr in conf.return_values('community {0} network'.format(name)): - if vyos.validate.is_ipv4(addr): + if is_ipv4(addr): community['network_v4'].append(addr) else: community['network_v6'].append(addr) @@ -271,7 +115,7 @@ def get_config(): # IP address of SNMP client allowed to contact system if conf.exists('community {0} client'.format(name)): for addr in conf.return_values('community {0} client'.format(name)): - if vyos.validate.is_ipv4(addr): + if is_ipv4(addr): community['network_v4'].append(addr) else: community['network_v6'].append(addr) @@ -554,16 +398,16 @@ def verify(snmp): addr = listen[0] port = listen[1] - if vyos.validate.is_ipv4(addr): + if is_ipv4(addr): # example: udp:127.0.0.1:161 listen = 'udp:' + addr + ':' + port - else: + elif snmp['ipv6_enabled']: # example: udp6:[::1]:161 listen = 'udp6:' + '[' + addr + ']' + ':' + port # We only wan't to configure addresses that exist on the system. # Hint the user if they don't exist - if vyos.validate.is_addr_assigned(addr): + if is_addr_assigned(addr): snmp['listen_on'].append(listen) else: print('WARNING: SNMP listen address {0} not configured!'.format(addr)) @@ -665,35 +509,40 @@ def generate(snmp): # # As we are manipulating the snmpd user database we have to stop it first! # This is even save if service is going to be removed - os.system("systemctl stop snmpd.service") - rmfile(config_file_client) - rmfile(config_file_daemon) - rmfile(config_file_access) - rmfile(config_file_user) + call('systemctl stop snmpd.service') + config_files = [config_file_client, config_file_daemon, config_file_access, + config_file_user] + for file in config_files: + rmfile(file) if snmp is None: return None + # Prepare Jinja2 template loader from files + tmpl_path = os.path.join(vyos_data_dir['data'], 'templates', 'snmp') + fs_loader = FileSystemLoader(tmpl_path) + env = Environment(loader=fs_loader) + # Write client config file - tmpl = jinja2.Template(client_config_tmpl) + tmpl = env.get_template('etc.snmp.conf.tmpl') config_text = tmpl.render(snmp) with open(config_file_client, 'w') as f: f.write(config_text) # Write server config file - tmpl = jinja2.Template(daemon_config_tmpl) + tmpl = env.get_template('etc.snmpd.conf.tmpl') config_text = tmpl.render(snmp) with open(config_file_daemon, 'w') as f: f.write(config_text) # Write access rights config file - tmpl = jinja2.Template(access_config_tmpl) + tmpl = env.get_template('usr.snmpd.conf.tmpl') config_text = tmpl.render(snmp) with open(config_file_access, 'w') as f: f.write(config_text) # Write access rights config file - tmpl = jinja2.Template(user_config_tmpl) + tmpl = env.get_template('var.snmpd.conf.tmpl') config_text = tmpl.render(snmp) with open(config_file_user, 'w') as f: f.write(config_text) @@ -705,7 +554,7 @@ def apply(snmp): return None # start SNMP daemon - os.system("systemctl restart snmpd.service") + call("systemctl restart snmpd.service") # Passwords are not available immediately in the configuration file, # after daemon startup - we wait until they have been processed by @@ -746,15 +595,15 @@ def apply(snmp): # Now update the running configuration # - # Currently when executing os.system() the environment does not + # Currently when executing call() the environment does not # have the vyos_libexec_dir variable set, see Phabricator T685. - os.system('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['auth_pw'])) - os.system('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['priv_pw'])) - os.system('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user'])) - os.system('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" privacy plaintext-key > /dev/null'.format(cfg['user'])) + call('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['auth_pw'])) + call('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['priv_pw'])) + call('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user'])) + call('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" privacy plaintext-key > /dev/null'.format(cfg['user'])) # Enable AgentX in FRR - os.system('vtysh -c "configure terminal" -c "agentx" >/dev/null') + call('vtysh -c "configure terminal" -c "agentx" >/dev/null') return None |