From f6c44922f82329beebd212a9281d2e25b19eabe7 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 26 Mar 2020 14:10:17 -0400 Subject: [PATCH] Add support for forced password change ThinkAgile CP storage BMC firmware now requires a password change be navigated prior to operation. --- .../confluent/discovery/handlers/cpstorage.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/confluent_server/confluent/discovery/handlers/cpstorage.py b/confluent_server/confluent/discovery/handlers/cpstorage.py index 4aaee102..4284a8c6 100644 --- a/confluent_server/confluent/discovery/handlers/cpstorage.py +++ b/confluent_server/confluent/discovery/handlers/cpstorage.py @@ -13,9 +13,58 @@ # limitations under the License. import confluent.discovery.handlers.bmc as bmchandler +import eventlet +import confluent.util as util +try: + from urllib import urlencode +except ImportError: + from urllib.parse import urlencode +webclient = eventlet.import_patched('pyghmi.util.webclient') class NodeHandler(bmchandler.NodeHandler): DEFAULT_USER = 'admin' DEFAULT_PASS = 'admin' devname = 'BMC' maxmacs = 2 + + 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 get_webclient(self, user, passwd, newuser, newpass): + wc = webclient.SecureHTTPConnection(self.ipaddr, 443, + verifycallback=self.validate_cert) + wc.connect() + authdata = urlencode({'username': user, 'password': passwd, + 'weblogsign': 1}) + res = wc.grab_json_response_with_status('/api/session', authdata) + if res[1] == 200: + if res[0].get('force_password', 1) == 0: + # Need to handle password change + passchange = { + 'Password': newpass, + 'RetypePassword': newpass, + 'param': 4, + 'username': 'admin', + 'privilege': 4, + } + passchange = urlencode(passchange) + rsp = wc.grab_json_response_with_status('/api/reset-pass', + passchange) + rsp = wc.grab_json_response_with_status('/api/session', + method='DELETE') + + def config(self, nodename, reset=False): + self.nodename = nodename + creds = self.configmanager.get_node_attributes( + self.nodename, ['secret.hardwaremanagementuser', + 'secret.hardwaremanagementpassword'], + decrypt=True) + user, passwd, isdefault = self.get_node_credentials( + nodename, creds, 'admin', 'admin') + if not isdefault: + self.get_webclient(self.DEFAULT_USER, self.DEFAULT_PASS, user, + passwd) + self._bmcconfig(nodename, False)