def validate_engine_id(engine_id): # Validate engine_id, check octet string can be formed from it try: OctetString.fromHexString(engine_id) except ValueError: msg = "engine_id should be a set of octets in " \ "hexadecimal format." raise exception.InvalidInput(msg)
def validate_connectivity(ctxt, alert_source): # Fill optional parameters with default values if not set in input if not alert_source.get('port'): alert_source['port'] = constants.DEFAULT_SNMP_CONNECT_PORT if not alert_source.get('context_name'): alert_source['context_name'] = None if not alert_source.get('retry_num'): alert_source['retry_num'] = constants.DEFAULT_SNMP_RETRY_NUM if not alert_source.get('expiration'): alert_source['expiration'] = constants.DEFAULT_SNMP_EXPIRATION_TIME if CONF.snmp_validation_enabled is False: return alert_source storage_id = alert_source.get('storage_id') access_info = db.access_info_get(ctxt, storage_id) access_info = dict(access_info) if access_info.get('model') not in constants.SNMP_SUPPORTED_MODELS: return alert_source cmd_gen = cmdgen.CommandGenerator() version = alert_source.get('version') # Connect to alert source through snmp get to check the configuration try: target = cmdgen.UdpTransportTarget( (alert_source['host'], alert_source['port']), timeout=alert_source['expiration'], retries=alert_source['retry_num']) target.setLocalAddress((CONF.my_ip, 0)) if version.lower() == 'snmpv3': # Register engine observer to get engineId, # Code reference from: http://snmplabs.com/pysnmp/ observer_context = {} cmd_gen.snmpEngine.observer.registerObserver( lambda e, p, v, c: c.update(securityEngineId=v[ 'securityEngineId']), 'rfc3412.prepareDataElements:internal', cbCtx=observer_context) auth_key = None if alert_source['auth_key']: auth_key = encodeutils.to_utf8( cryptor.decode(alert_source['auth_key'])) privacy_key = None if alert_source['privacy_key']: privacy_key = encodeutils.to_utf8( cryptor.decode(alert_source['privacy_key'])) auth_protocol = None privacy_protocol = None if alert_source['auth_protocol']: auth_protocol = constants.AUTH_PROTOCOL_MAP.get( alert_source['auth_protocol'].lower()) if alert_source['privacy_protocol']: privacy_protocol = constants.PRIVACY_PROTOCOL_MAP.get( alert_source['privacy_protocol'].lower()) engine_id = alert_source.get('engine_id') if engine_id: engine_id = OctetString.fromHexString(engine_id) error_indication, __, __, __ = cmd_gen.getCmd( cmdgen.UsmUserData(alert_source['username'], authKey=auth_key, privKey=privacy_key, authProtocol=auth_protocol, privProtocol=privacy_protocol, securityEngineId=engine_id), target, constants.SNMP_QUERY_OID, ) if 'securityEngineId' in observer_context: engine_id = observer_context.get('securityEngineId') alert_source['engine_id'] = binascii.hexlify( engine_id.asOctets()).decode() else: community_string = encodeutils.to_utf8( cryptor.decode(alert_source['community_string'])) error_indication, __, __, __ = cmd_gen.getCmd( cmdgen.CommunityData( community_string, contextName=alert_source['context_name']), target, constants.SNMP_QUERY_OID, ) cmd_gen.snmpEngine.transportDispatcher.closeDispatcher() if not error_indication: return alert_source # Prepare exception with error_indication msg = six.text_type(error_indication) except Exception as e: msg = six.text_type(e) # Since validation occur error, raise exception LOG.error("Configuration validation failed with alert source for " "reason: %s." % msg) raise exception.SNMPConnectionFailed(msg)
def _input_check(self, alert_source): version = alert_source.get('version') if version.lower() == 'snmpv3': user_name = alert_source.get('username') security_level = alert_source.get('security_level') engine_id = alert_source.get('engine_id') # Validate engine_id, check octet string can be formed from it if engine_id: try: OctetString.fromHexString(engine_id) except (TypeError, ValueError): msg = "engine_id should be a set of octets in " \ "hexadecimal format." raise exception.InvalidInput(msg) if not user_name or not security_level: msg = "If snmp version is SNMPv3, then username, " \ "security_level are required." raise exception.InvalidInput(msg) if security_level == constants.SecurityLevel.AUTHNOPRIV\ or security_level == constants.SecurityLevel.AUTHPRIV: auth_protocol = alert_source.get('auth_protocol') auth_key = alert_source.get('auth_key') if not auth_protocol or not auth_key: msg = "If snmp version is SNMPv3 and security_level is " \ "authPriv or authNoPriv, auth_protocol and " \ "auth_key are required." raise exception.InvalidInput(msg) alert_source['auth_key'] = cryptor.encode( alert_source['auth_key']) if security_level == constants.SecurityLevel.AUTHPRIV: privacy_protocol = alert_source.get('privacy_protocol') privacy_key = alert_source.get('privacy_key') if not privacy_protocol or not privacy_key: msg = "If snmp version is SNMPv3 and security_level" \ " is authPriv, privacy_protocol and " \ "privacy_key are required." raise exception.InvalidInput(msg) alert_source['privacy_key'] = cryptor.encode( alert_source['privacy_key']) else: alert_source['privacy_key'] = None alert_source['privacy_protocol'] = None else: alert_source['auth_key'] = None alert_source['auth_protocol'] = None alert_source['privacy_key'] = None alert_source['privacy_protocol'] = None # Clear keys for other versions. alert_source['community_string'] = None else: community_string = alert_source.get('community_string') if not community_string: msg = "If snmp version is SNMPv1 or SNMPv2c, " \ "community_string is required." raise exception.InvalidInput(msg) alert_source['community_string'] = cryptor.encode( alert_source['community_string']) # Clear keys for SNMPv3 for k in SNMPv3_keys: alert_source[k] = None return alert_source