Beispiel #1
0
def loadConfig(filename):
    """Load and parse .yaml configuration file

    Args:
        filename (str): Path to system configuration file

    Returns:
        dict: representing configuration information

    Raises:
        BdsError: if unable to get configuration information
    """
    try:
        with open(filename) as stream:
            config = yaml.load(stream)
            return config['bdsSnmpAdapter']

    except Exception as exc:
        raise error.BdsError(
            'Failed to read configuration file %s: %s' % (filename, exc))
Beispiel #2
0
 def willRaise():
     raise error.BdsError()
    def __init__(self, args, queue):
        configDict = loadConfig(args.config)

        self.moduleLogger = set_logging(configDict, __class__.__name__)

        self.moduleLogger.info(f'original configDict: {configDict}')

        self._queue = queue

        # temp lines for graylog client end #
        # configDict['usmUserDataMatrix'] = [ usmUserTuple.strip().split(',')
        # for usmUserTuple in configDict['usmUserTuples'].split(';') if len(usmUserTuple) > 0 ]
        # self.moduleLogger.debug('configDict['usmUserDataMatrix']: {}'.format(configDict['usmUserDataMatrix']))
        # configDict['usmUsers'] = []
        self.moduleLogger.info(f'modified configDict: {configDict}')

        self._snmpEngine = snmp_config.getSnmpEngine(
            engineId=configDict['snmp'].get('engineId'))

        engineBoots = snmp_config.setSnmpEngineBoots(
            self._snmpEngine, configDict.get('stateDir', '.'))

        self._targets = snmp_config.setTrapTypeForTag(self._snmpEngine, self.TARGETS_TAG)

        authEntries = {}

        for snmpVersion, snmpConfigEntries in configDict['snmp'].get(
                'versions', {}).items():

            snmpVersion = str(snmpVersion)

            if snmpVersion in ('1', '2c'):

                for security, snmpConfig in snmpConfigEntries.items():

                    community = snmpConfig['community']

                    authLevel = snmp_config.setCommunity(
                        self._snmpEngine, security, community, version=snmpVersion, tag=self.TARGETS_TAG)

                    self.moduleLogger.info(
                        f'Configuring SNMPv{snmpVersion} security name '
                        f'{security}, community name {community}')

                    authEntries[security] = snmpVersion, authLevel

            elif snmpVersion == '3':

                for security, usmCreds in snmpConfigEntries.get('usmUsers', {}).items():

                    authLevel = snmp_config.setUsmUser(
                        self._snmpEngine, security,
                        usmCreds.get('user'),
                        usmCreds.get('authKey'), usmCreds.get('authProtocol'),
                        usmCreds.get('privKey'), usmCreds.get('privProtocol'))

                    self.moduleLogger.info(
                        f'Configuring SNMPv3 USM security {security}, user '
                        f'{usmCreds.get("user")}, '
                        f'auth {usmCreds.get("authKey")}/{usmCreds.get("authProtocol")}, '
                        f'priv {usmCreds.get("privKey")}/{usmCreds.get("privProtocol")}')

                    authEntries[security] = snmpVersion, authLevel

            else:
                raise error.BdsError(f'Unknown SNMP version {snmpVersion}')

            self._birthday = time.time()

        snmpTrapTargets = configDict['notificator'].get('snmpTrapTargets', {}).items()

        for targetId, (targetName, targetConfig) in enumerate(snmpTrapTargets):

            bind_address = targetConfig.get('bind-address', '0.0.0.0'), 0

            security = targetConfig['security-name']

            transportDomain = snmp_config.setSnmpTransport(
                self._snmpEngine, iface=bind_address, iface_num=targetId)

            transportAddress = (targetConfig['address'],
                                int(targetConfig.get('port', 162)))

            snmp_config.setTrapTargetAddress(
                self._snmpEngine, security, transportDomain, transportAddress,
                tag=self.TARGETS_TAG)

            snmpVersion, authLevel = authEntries[security]

            snmp_config.setTrapVersion(
                self._snmpEngine, security, authLevel, snmpVersion)

            self.moduleLogger.info(
                f'Configuring target #{targetId}, transport domain '
                f'{transportDomain}, destination {transportAddress}, '
                f'bind address {bind_address} using security name {security}')

        self._configureMibObjects(configDict)

        self._ntfOrg = ntforg.NotificationOriginator()

        self._trapCounter = 0

        self.moduleLogger.info(
            f'Running SNMP engine ID {self._snmpEngine}, boots {engineBoots}')
    def __init__(self, args, mibController):
        self.mibController = mibController

        configDict = loadConfig(args.config)

        self.moduleLogger = set_logging(configDict, __class__.__name__)

        self.moduleLogger.debug(f'configDict:{configDict}')

        self.snmpEngine = snmp_config.getSnmpEngine(
            engineId=configDict['snmp'].get('engineId'))

        engineBoots = snmp_config.setSnmpEngineBoots(
            self.snmpEngine, configDict.get('stateDir', '.'))

        self.listeningAddress = configDict['responder']['listeningIP']
        self.listeningPort = configDict['responder']['listeningPort']
        self.birthday = time.time()

        self.moduleLogger.info(
            f'Running SNMP engine ID {self.snmpEngine.snmpEngineID.prettyPrint()}, '
            f'boots {engineBoots}')

        # UDP over IPv4
        try:
            snmp_config.setSnmpTransport(
                self.snmpEngine, (self.listeningAddress, self.listeningPort))

        except Exception as exc:
            self.moduleLogger.error(f'SNMP transport error: {exc}')
            raise

        self.moduleLogger.info(
            f'SnmpEngine UDPv4 listening on {self.listeningAddress} '
            f'{self.listeningPort}')

        for snmpVersion, snmpConfigEntries in configDict['snmp'].get(
                'versions', {}).items():

            snmpVersion = str(snmpVersion)

            if snmpVersion in ('1', '2c'):

                for security, snmpConfig in snmpConfigEntries.items():
                    community = snmpConfig['community']

                    snmp_config.setCommunity(
                        self.snmpEngine, security, community, version=snmpVersion)

                    self.moduleLogger.info(
                        f'Configuring SNMPv{snmpVersion} security name '
                        f'{security}, community name {community}')

            elif snmpVersion == '3':

                for security, usmCreds in snmpConfigEntries.get('usmUsers', {}).items():
                    snmp_config.setUsmUser(
                        self.snmpEngine, security,
                        usmCreds.get('user'),
                        usmCreds.get('authKey'), usmCreds.get('authProtocol'),
                        usmCreds.get('privKey'), usmCreds.get('privProtocol'))

                    self.moduleLogger.info(
                        f'Configuring SNMPv3 USM security {security}, user '
                        f'{usmCreds.get("user")}, '
                        f'auth {usmCreds.get("authKey")}/{usmCreds.get("authProtocol")}, '
                        f'priv {usmCreds.get("privKey")}/{usmCreds.get("privProtocol")}')

            else:
                raise error.BdsError('Unknown SNMP version {snmpVersion}')

        snmpContext = snmp_config.setMibController(
            self.snmpEngine, mibController)

        self.moduleLogger.info(
            f'Configuring SNMP context name "{snmpContext}"')

        cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.NextCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.BulkCommandResponder(self.snmpEngine, snmpContext)

        self.snmpEngine.transportDispatcher.jobStarted(1)
Beispiel #5
0
    def add(self, mibName, mibSymbol, *indices, value=None,
            valueFormat=None, code=None):
        """Add SNMP MIB managed object instance to the OID DB

        Args:
            mibName (str): MIB name e.g. SNMPv2-MIB. This MIB must be in MIB
                search path.
            mibSymbol (str): MIB symbol name
            indices (vararg): one or more objects representing indices.
                Should be `0` for scalars.
            value: put this value into MIB managed object. This is what SNMP
                manager will get in response. The `None` sentinel refreshes
                existing object.
            valueFormat (string): 'hexValue' to indicate hex `value` initializer.
                Optional.
            code (string): compile and use this Python code snippet for getting a
                value at run time. Optional.

        Examples:

          add('SNMPv2-MIB', 'sysDescr', 0, value='hello world')
          add('SNMPv2-MIB', 'sysDescr', 0, value='10101010', valueFormat='binValue')
          add('SNMPv2-MIB', 'sysDescr', 0, code='print("hello world")')

        """
        if value is None:
            objectIdentity = rfc1902.ObjectIdentity(
                mibName, mibSymbol, *indices).resolveWithMib(self._mibViewController)

            try:
                oidDbItem = self._oids[objectIdentity.getOid()]

            except KeyError:
                raise error.BdsError(
                    'Initial value for managed %s::%s object must be '
                    'provided' % (mibName, mibSymbol))

        else:
            obj = rfc1902.ObjectType(
                rfc1902.ObjectIdentity(mibName, mibSymbol, *indices), value)

            objectIdentity, objectSyntax = obj.resolveWithMib(self._mibViewController)

            try:
                representation = {valueFormat if valueFormat else 'value': value}
                objectSyntax = objectSyntax.clone(**representation)

                if code:
                    code = compile(code, '<%s::%s>' % (mibName, mibSymbol), 'exec')

                oidDbItem = OidDbItem(
                    oid=objectIdentity.getOid(),
                    name=objectIdentity.getMibSymbol()[1],
                    value=objectSyntax,
                    code=code
                )

            except Exception as exc:
                raise error.BdsError(
                    'Error setting managed object %s (%s) of type %s to value '
                    '"%s"' % ('::'.join(objectIdentity.getMibSymbol()),
                              objectIdentity.getOid(), objectSyntax, value))

        self.moduleLogger.debug(
            f'{"updating" if oidDbItem.oid in self._oids else "adding"} '
            f'{oidDbItem.oid} {"<code>" if code else oidDbItem.value.prettyPrint()}')

        # put new OID online immediately
        self._oids[oidDbItem.oid] = oidDbItem

        self._dirty = True

        now = time.time()

        mibObject = mibName, mibSymbol

        # We update two DBs for some time while use only one, eventually
        # we drop the older DB and use the newer one. This effectively
        # expires DB entries that do not get updated for some time.
        self._mibObjects[mibObject][oidDbItem.oid] = oidDbItem
        self._candidateMibObjects[mibObject][oidDbItem.oid] = oidDbItem

        if self._expireBy < now:

            # put candidate objects online
            (self._mibObjects[mibObject],
             self._candidateMibObjects[mibObject]) = (
                self._candidateMibObjects[mibObject],
                self._mibObjects[mibObject])

            # prepare new candidate objects dict - drop everything it has,
            # most importantly, entries that have not been updated
            # N.B. this only works for tablular SNMP objects
            self._candidateMibObjects[mibObject].clear()

            # stale entries expire in two runs of `.add`
            self._expireBy = now + self.EXPIRE_PERIOD / 2

            # drop all online OIDs
            self._oids.clear()

            # put recently updated OIDs online
            for oidItems in self._mibObjects.values():
                self._oids.update(oidItems)
Beispiel #6
0
def setUsmUser(snmpEngine, security, user, authKey=None, authProtocol=None,
               privKey=None, privProtocol=None):
    """Configure SNMP v3 USM user credentials and VACM access.

    Args:
        snmpEngine (object): pysnmp `SnmpEngine` class instance
        security (str): SNMP security name. Used in SNMP engine configuration
            primarily as an ID for the given SNMP v3 authentication information.
        user (str): SNMP v3 USM user name
        authKey (str): SNMP v3 USM authentication key. Must be 8+ characters long,
            unless no SNMP message authentication is in use. Defaults to `None`.
        authProtocol (str): Authentication protocol to use. Known values are:
            'MD5', 'SHA', 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'NONE'. Defaults
            to 'NONE'.
        privKey (str): SNMP v3 USM privacy key. Must be 8+ characters long,
            unless no SNMP payload encryption is in use. Defaults to `None`.
        privProtocol (str): SNMP message encryption protocol to use. Known values are:
            'DES', '3DES', 'AES', 'AES128', 'AES192', 'AES192BLMT', 'AES256',
            'AES256BLMT', 'NONE'. Defaults to 'NONE'.

    Returns:
        str: effective SNMP authentication and privacy level. Known values are:
            'noAuthNoPriv', 'authNoPriv', 'authPriv'.
    """
    if not authKey:
        authProtocol = 'NONE'

    elif not authProtocol:
        authProtocol = 'MD5'

    if not privKey:
        privProtocol = 'NONE'

    elif not privProtocol:
        privProtocol = 'DES'

    authProtocol = AUTH_PROTOCOLS[authProtocol.upper()]
    privProtocol = PRIV_PROTOCOLS[privProtocol.upper()]

    if (authProtocol == config.usmNoAuthProtocol and
            privProtocol != config.usmNoPrivProtocol):
        raise error.BdsError('SNMP privacy implies enabled authentication')

    elif (authProtocol == config.usmNoAuthProtocol and
            privProtocol == config.usmNoPrivProtocol):
        authLevel = 'noAuthNoPriv'

    elif privProtocol != config.usmNoPrivProtocol:
        authLevel = 'authPriv'

    else:
        authLevel = 'authNoPriv'

    config.addV3User(
        snmpEngine,
        user,
        authProtocol,
        authKey,
        privProtocol,
        privKey,
        securityName=security)

    config.addVacmUser(
        snmpEngine, 3, security, authLevel,
        (1, 3, 6), (1, 3, 6), (1, 3, 6))

    return authLevel