Esempio n. 1
0
    def walk(self, oid):
        """Walk over children of a given OID

        This is roughly equivalent to snmpwalk.  It will automatically try to
        be a snmpbulkwalk if possible.

        :param oid: The SNMP object identifier
        """
        # SNMP is a complicated mess of things.  Will endeavor to shield caller
        # from as much as possible, assuming reasonable defaults when possible.
        # there may come a time where we add more parameters to override the
        # automatic behavior (e.g. DES is weak, so it's likely to be
        # overriden, but some devices only support DES)
        tp = _get_transport(self.server)
        ctx = snmp.ContextData(self.context)
        resolvemib = False
        if '::' in oid:
            resolvemib = True
            mib, field = oid.split('::')
            obj = snmp.ObjectType(snmp.ObjectIdentity(mib, field))
        else:
            obj = snmp.ObjectType(snmp.ObjectIdentity(oid))

        walking = snmp.bulkCmd(self.eng,
                               self.authdata,
                               tp,
                               ctx,
                               0,
                               10,
                               obj,
                               lexicographicMode=False,
                               lookupMib=resolvemib)
        try:
            for rsp in walking:
                errstr, errnum, erridx, answers = rsp
                if errstr:
                    errstr = str(errstr)
                    finerr = errstr + ' while trying to connect to ' \
                                      '{0}'.format(self.server)
                    if errstr in ('Unknown USM user', 'unknownUserName',
                                  'wrongDigest', 'Wrong SNMP PDU digest'):
                        raise exc.TargetEndpointBadCredentials(finerr)
                    # need to do bad credential versus timeout
                    raise exc.TargetEndpointUnreachable(finerr)
                elif errnum:
                    raise exc.ConfluentException(errnum.prettyPrint() +
                                                 ' while trying to connect to '
                                                 '{0}'.format(self.server))
                for ans in answers:
                    if not obj[0].isPrefixOf(ans[0]):
                        # PySNMP returns leftovers in a bulk command
                        # filter out such leftovers
                        break
                    yield ans
        except snmperr.WrongValueError:
            raise exc.TargetEndpointBadCredentials('Invalid SNMPv3 password')
Esempio n. 2
0
def cnos_login(node, configmanager, creds):
    wc = webclient.SecureHTTPConnection(
        node,
        port=443,
        verifycallback=util.TLSCertVerifier(
            configmanager, node, 'pubkeys.tls_hardwaremanager').verify_cert)
    wc.set_basic_credentials(
        creds[node]['secret.hardwaremanagementuser']['value'],
        creds[node]['secret.hardwaremanagementpassword']['value'])
    wc.request('GET', '/nos/api/login/')
    rsp = wc.getresponse()
    body = rsp.read()
    if rsp.status == 401:  # CNOS gives 401 on first attempt...
        wc.request('GET', '/nos/api/login/')
        rsp = wc.getresponse()
        body = rsp.read()
    if rsp.status >= 200 and rsp.status < 300:
        return wc
    raise exc.TargetEndpointBadCredentials('Unable to authenticate')
Esempio n. 3
0
 def _bmcconfig(self, nodename, reset=False, customconfig=None, vc=None):
     # TODO(jjohnson2): set ip parameters, user/pass, alert cfg maybe
     # In general, try to use https automation, to make it consistent
     # between hypothetical secure path and today.
     creds = self.configmanager.get_node_attributes(nodename, [
         'secret.hardwaremanagementuser',
         'secret.hardwaremanagementpassword'
     ],
                                                    decrypt=True)
     user = creds.get(nodename, {}).get('secret.hardwaremanagementuser',
                                        {}).get('value', None)
     passwd = creds.get(nodename,
                        {}).get('secret.hardwaremanagementpassword',
                                {}).get('value', None)
     try:
         ic = self._get_ipmicmd()
         passwd = self.DEFAULT_PASS
     except pygexc.IpmiException as pi:
         havecustomcreds = False
         if user is not None and user != self.DEFAULT_USER:
             havecustomcreds = True
         else:
             user = self.DEFAULT_USER
         if passwd is not None and passwd != self.DEFAULT_PASS:
             havecustomcreds = True
         else:
             passwd = self.DEFAULT_PASS
         if havecustomcreds:
             ic = self._get_ipmicmd(user, passwd)
         else:
             raise
     if vc:
         ic.register_key_handler(vc)
     currusers = ic.get_users()
     lanchan = ic.get_network_channel()
     userdata = ic.xraw_command(netfn=6, command=0x44, data=(lanchan, 1))
     userdata = bytearray(userdata['data'])
     maxusers = userdata[0] & 0b111111
     enabledusers = userdata[1] & 0b111111
     lockedusers = userdata[2] & 0b111111
     cfg = self.configmanager
     cd = cfg.get_node_attributes(nodename, [
         'secret.hardwaremanagementuser',
         'secret.hardwaremanagementpassword', 'hardwaremanagement.manager'
     ], True)
     cd = cd.get(nodename, {})
     if ('secret.hardwaremanagementuser' not in cd
             or 'secret.hardwaremanagementpassword' not in cd):
         raise exc.TargetEndpointBadCredentials(
             'secret.hardwaremanagementuser and/or '
             'secret.hardwaremanagementpassword was not configured')
     newuser = cd['secret.hardwaremanagementuser']['value']
     newpass = cd['secret.hardwaremanagementpassword']['value']
     for uid in currusers:
         if currusers[uid]['name'] == newuser:
             # Use existing account that has been created
             newuserslot = uid
             if newpass != passwd:  # don't mess with existing if no change
                 ic.set_user_password(newuserslot, password=newpass)
                 ic = self._get_ipmicmd(user, passwd)
                 if vc:
                     ic.register_key_handler(vc)
             break
     else:
         newuserslot = lockedusers + 1
         if newuserslot < 2:
             newuserslot = 2
         if newpass != passwd:  # don't mess with existing if no change
             ic.set_user_password(newuserslot, password=newpass)
         ic.set_user_name(newuserslot, newuser)
         if havecustomcreds:
             ic = self._get_ipmicmd(user, passwd)
             if vc:
                 ic.register_key_handler(vc)
         #We are remote operating on the account we are
         #using, no need to try to set user access
         #ic.set_user_access(newuserslot, lanchan,
         #                   privilege_level='administrator')
     # Now to zap others
     for uid in currusers:
         if uid != newuserslot:
             if uid <= lockedusers:  # we cannot delete, settle for disable
                 ic.disable_user(uid, 'disable')
             else:
                 # lead with the most critical thing, removing user access
                 ic.set_user_access(uid,
                                    channel=None,
                                    callback=False,
                                    link_auth=False,
                                    ipmi_msg=False,
                                    privilege_level='no_access')
                 # next, try to disable the password
                 ic.set_user_password(uid, mode='disable', password=None)
                 # ok, now we can be less paranoid
                 try:
                     ic.user_delete(uid)
                 except pygexc.IpmiException as ie:
                     if ie.ipmicode != 0xd5:  # some response to the 0xff
                         # name...
                         # the user will remain, but that is life
                         raise
     if customconfig:
         customconfig(ic)
     if ('hardwaremanagement.manager' in cd
             and cd['hardwaremanagement.manager']['value']
             and not cd['hardwaremanagement.manager']['value'].startswith(
                 'fe80::')):
         newip = cd['hardwaremanagement.manager']['value']
         newipinfo = getaddrinfo(newip, 0)[0]
         # This getaddrinfo is repeated in get_nic_config, could be
         # optimized, albeit with a more convoluted api..
         newip = newipinfo[-1][0]
         if ':' in newip:
             raise exc.NotImplementedException('IPv6 remote config TODO')
         netconfig = netutil.get_nic_config(cfg, nodename, ip=newip)
         plen = netconfig['prefix']
         newip = '{0}/{1}'.format(newip, plen)
         currcfg = ic.get_net_configuration()
         if currcfg['ipv4_address'] != newip:
             # do not change the ipv4_config if the current config looks
             # like it is already accurate
             ic.set_net_configuration(
                 ipv4_address=newip,
                 ipv4_configuration='static',
                 ipv4_gateway=netconfig['ipv4_gateway'])
     elif self.ipaddr.startswith('fe80::'):
         cfg.set_node_attributes(
             {nodename: {
                 'hardwaremanagement.manager': self.ipaddr
             }})
     else:
         raise exc.TargetEndpointUnreachable(
             'hardwaremanagement.manager must be set to desired address')
     if reset:
         ic.reset_bmc()
     return ic