diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py
index 6e8d0bb0..55e449bc 100644
--- a/confluent_server/confluent/config/attributes.py
+++ b/confluent_server/confluent/config/attributes.py
@@ -156,6 +156,12 @@ node = {
                         'indicates candidate managers, either for '
                         'high availability or load balancing purposes.')
     },
+    'discovery.passwordrules': {
+        'description':  'Any specified rules shall be configured on the BMC '
+                        'upon discovery.  "expiration=no,loginfailures=no" '
+                        'would disable password expiration and login failures '
+                        'triggering a lockout.'
+    },
     'discovery.policy': {
         'description':  'Policy to use for auto-configuration of discovered '
                         'and identified nodes. Valid values are "manual", '
diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py
index 756021c6..a1431ad9 100644
--- a/confluent_server/confluent/config/configmanager.py
+++ b/confluent_server/confluent/config/configmanager.py
@@ -94,7 +94,9 @@ _hasquorum = True
 _attraliases = {
     'bmc': 'hardwaremanagement.manager',
     'bmcuser': 'secret.hardwaremanagementuser',
+    'switchuser': 'secret.hardwaremanagementuser',
     'bmcpass': 'secret.hardwaremanagementpassword',
+    'switchpass': 'secret.hardwaremanagementpassword',
 }
 
 def _mkpath(pathname):
diff --git a/confluent_server/confluent/discovery/handlers/bmc.py b/confluent_server/confluent/discovery/handlers/bmc.py
index 4f26a88a..5f053716 100644
--- a/confluent_server/confluent/discovery/handlers/bmc.py
+++ b/confluent_server/confluent/discovery/handlers/bmc.py
@@ -45,7 +45,7 @@ class NodeHandler(generic.NodeHandler):
     def config(self, nodename, reset=False):
         self._bmcconfig(nodename, reset)
 
-    def _bmcconfig(self, nodename, reset=False):
+    def _bmcconfig(self, nodename, reset=False, customconfig=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.
@@ -74,6 +74,8 @@ class NodeHandler(generic.NodeHandler):
                 ic = self._get_ipmicmd(user, passwd)
             else:
                 raise
+        if customconfig:
+            customconfig(ic)
         currusers = ic.get_users()
         lanchan = ic.get_network_channel()
         userdata = ic.xraw_command(netfn=6, command=0x44, data=(lanchan,
diff --git a/confluent_server/confluent/discovery/handlers/xcc.py b/confluent_server/confluent/discovery/handlers/xcc.py
index ad222489..7cbafd5e 100644
--- a/confluent_server/confluent/discovery/handlers/xcc.py
+++ b/confluent_server/confluent/discovery/handlers/xcc.py
@@ -13,11 +13,13 @@
 # limitations under the License.
 
 import confluent.discovery.handlers.imm as immhandler
+import confluent.util as util
 import pyghmi.exceptions as pygexc
 import pyghmi.ipmi.oem.lenovo.imm as imm
 
 
 
+
 class NodeHandler(immhandler.NodeHandler):
     devname = 'XCC'
 
@@ -41,16 +43,45 @@ class NodeHandler(immhandler.NodeHandler):
         #if ipmicmd:
         #    ipmicmd.ipmi_session.logout()
 
+    def validate_cert(self, certificate):
+        # broadly speaking, merely checks consistency moment to moment,
+        # but if https_cert gets stricter, this check means something
+        fprint = util.get_fingerprint(self.https_cert)
+        return util.cert_matches(fprint, certificate)
+
+    def set_password_policy(self, ic):
+        ruleset = {'USER_GlobalMinPassChgInt': '0'}
+        for rule in self.ruleset.split(','):
+            if '=' not in rule:
+                continue
+            name, value = rule.split('=')
+            if value.lower() in ('no', 'none', 'disable', 'disabled'):
+                value = '0'
+            if name.lower() in ('expiry', 'expiration'):
+                ruleset['USER_GlobalPassExpPeriod'] = value
+                if int(value) < 5:
+                    ruleset['USER_GlobalPassExpWarningPeriod'] = value
+            if name.lower() in ('lockout', 'loginfailures'):
+                if value.lower() in ('no', 'none', 'disable', 'disabled'):
+                    value = '0'
+                ruleset['USER_GlobalMaxLoginFailures'] = value
+        ic.register_key_handler(self.validate_cert)
+        ic.oem_init()
+        ic._oem.immhandler.wc.grab_json_response('/api/dataset', ruleset)
+
     def config(self, nodename, reset=False):
         # 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.
-        ic = self._bmcconfig(nodename)
+        dpp = self.configmanager.get_node_attributes(
+            nodename, 'discovery.passwordrules')
+        self.ruleset = dpp.get(nodename, {}).get(
+            'discovery.passwordrules', {}).get('value', '')
+        ic = self._bmcconfig(nodename, customconfig=self.set_password_policy)
         ff = self.info.get('attributes', {}).get('enclosure-form-factor', '')
         if ff not in ('dense-computing', [u'dense-computing']):
             return
         # Ok, we can get the enclosure uuid now..
-        ic.oem_init()
         enclosureuuid = ic._oem.immhandler.get_property(
             '/v2/ibmc/smm/chassis/uuid')
         enclosureuuid = ic._oem.immhandler.get_property(
diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py
index 05c77050..1cd70e23 100644
--- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py
+++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py
@@ -25,6 +25,7 @@ import eventlet.green.threading as threading
 import eventlet.greenpool as greenpool
 import eventlet.queue as queue
 import eventlet.support.greendns
+from fnmatch import fnmatch
 import pyghmi.constants as pygconstants
 import pyghmi.exceptions as pygexc
 console = eventlet.import_patched('pyghmi.ipmi.console')
@@ -32,6 +33,37 @@ ipmicommand = eventlet.import_patched('pyghmi.ipmi.command')
 import socket
 import ssl
 
+pci_cache = {}
+
+def get_dns_txt(qstring):
+    return eventlet.support.greendns.resolver.query(
+        qstring, 'TXT')[0].strings[0].replace('i=', '')
+
+def get_pci_text_from_ids(subdevice, subvendor, device, vendor):
+    fqpi = '{0}.{1}.{2}.{3}'.format(subdevice, subvendor, device, vendor)
+    if fqpi in pci_cache:
+        return pci_cache[fqpi]
+    vendorstr = None
+    try:
+        vendorstr = get_dns_txt('{0}.pci.id.ucw.cz'.format(subvendor))
+    except Exception:
+        try:
+            vendorstr = get_dns_txt('{0}.pci.id.ucw.cz'.format(vendor))
+        except Exception:
+            pass
+    devstr = None
+    try:
+        devstr = get_dns_txt(fqpi + '.pci.id.ucw.cz')
+    except Exception:
+        try:
+            devstr = get_dns_txt('{0}.{1}.pci.id.ucw.cz'.format(
+                device, vendor))
+        except Exception:
+            pass
+    if vendorstr and devstr:
+        pci_cache[fqpi] = vendorstr, devstr
+    return vendorstr, devstr
+
 
 # There is something not right with the RLocks used in pyghmi when
 # eventlet comes into play.  It seems like sometimes on acquire,
@@ -841,7 +873,7 @@ class IpmiHandler(object):
                         sanitize_invdata(invdata[1])
                         newinf = {'present': True, 'information': invdata[1]}
                     newinf['name'] = invdata[0]
-                    invitems.append(newinf)
+                    self.add_invitem(invitems, newinf)
             else:
                 self.make_inventory_map()
                 compname = self.invmap.get(component, None)
@@ -855,7 +887,7 @@ class IpmiHandler(object):
                     sanitize_invdata(invdata)
                     newinf = {'present': True, 'information': invdata}
                 newinf['name'] = compname
-                invitems.append(newinf)
+                self.add_invitem(invitems, newinf)
         except ssl.SSLEOFError:
             errorneeded = msg.ConfluentNodeError(
                 self.node, 'Unable to communicate with the https server on '
@@ -872,6 +904,21 @@ class IpmiHandler(object):
         if errorneeded:
             self.output.put(errorneeded)
 
+    def add_invitem(self, invitems, newinf):
+        if fnmatch(newinf['name'], 'Adapter ??:??:??') or fnmatch(
+                newinf['name'], 'PCIeGen? x*'):
+            myinf = newinf.get('information', {})
+            sdid = myinf.get('PCI Subsystem Device ID', None)
+            svid = myinf.get('PCI Subsystem Vendor ID', None)
+            did = myinf.get('PCI Device ID', None)
+            vid = myinf.get('PCI Vendor ID', None)
+            vstr, dstr = get_pci_text_from_ids(sdid, svid, did, vid)
+            if vstr:
+                newinf['information']['PCI Vendor'] = vstr
+            if dstr:
+                newinf['name'] = dstr
+        invitems.append(newinf)
+
     def handle_sensors(self):
         if self.element[-1] == '':
             self.element = self.element[:-1]