From fc9d92da736f6a799e9c6d1de25ac552e82db914 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 30 Nov 2022 15:52:28 -0500 Subject: [PATCH] Add support for custom role names While IPMI has well defined roles and redfish has some well-defined starter roles, permit management of users for custom roles. Change-Id: Id6ff87a8ccbb12491adc37b460765d4eadf2c92d --- pyghmi/ipmi/command.py | 28 ++++++++++++++++++---------- pyghmi/ipmi/oem/generic.py | 5 +++++ pyghmi/ipmi/oem/lenovo/handler.py | 5 +++++ pyghmi/ipmi/oem/lenovo/imm.py | 13 +++++++++++++ pyghmi/redfish/command.py | 4 ++++ 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index 8202e54c..55029b9d 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -1698,6 +1698,7 @@ class Command(object): * administrator * proprietary * no_access + * custom. """ self.oem_init() if hasattr(self._oem, 'oem_user_access'): @@ -1726,6 +1727,8 @@ class Command(object): self.oem_init() self._oem.set_user_access( uid, channel, callback, link_auth, ipmi_msg, privilege_level) + if privilege_level.startswith('custom.'): + return True # unable to proceed with standard support data = [b, uid & 0b00111111, privilege_levels[privilege_level] & 0b00001111, 0] response = self.raw_command(netfn=0x06, command=0x43, data=data) @@ -1772,16 +1775,21 @@ class Command(object): r['access']['callback'] = (data[3] & 0b01000000) != 0 r['access']['link_auth'] = (data[3] & 0b00100000) != 0 r['access']['ipmi_msg'] = (data[3] & 0b00010000) != 0 - privilege_levels = { - 0: 'reserved', - 1: 'callback', - 2: 'user', - 3: 'operator', - 4: 'administrator', - 5: 'proprietary', - 0x0F: 'no_access' - } - r['access']['privilege_level'] = privilege_levels[data[3] & 0b00001111] + self.oem_init() + oempriv = self._oem.get_user_privilege_level(uid) + if oempriv: + r['access']['privilege_level'] = oempriv + else: + privilege_levels = { + 0: 'reserved', + 1: 'callback', + 2: 'user', + 3: 'operator', + 4: 'administrator', + 5: 'proprietary', + 0x0F: 'no_access' + } + r['access']['privilege_level'] = privilege_levels[data[3] & 0b00001111] return r def set_user_name(self, uid, name): diff --git a/pyghmi/ipmi/oem/generic.py b/pyghmi/ipmi/oem/generic.py index 4709f3a0..642cb275 100644 --- a/pyghmi/ipmi/oem/generic.py +++ b/pyghmi/ipmi/oem/generic.py @@ -329,6 +329,8 @@ class OEMHandler(object): def set_user_access(self, uid, channel, callback, link_auth, ipmi_msg, privilege_level): + if privilege_level.startswith('custom.'): + raise exc.UnsupportedFunctionality() return # Nothing to do def set_alert_ipv6_destination(self, ip, destination, channel): @@ -398,6 +400,9 @@ class OEMHandler(object): def get_user_expiration(self, uid): return None + + def get_user_privilege_level(self, uid): + return None def set_oem_extended_privilleges(self, uid): """Set user extended privillege as 'KVM & VMedia Allowed' diff --git a/pyghmi/ipmi/oem/lenovo/handler.py b/pyghmi/ipmi/oem/lenovo/handler.py index ddc58876..8b558f3b 100755 --- a/pyghmi/ipmi/oem/lenovo/handler.py +++ b/pyghmi/ipmi/oem/lenovo/handler.py @@ -1316,6 +1316,11 @@ class OEMHandler(generic.OEMHandler): return True return False + def get_user_privilege_level(self, uid): + if self.has_xcc: + return self.immhandler.get_user_privilege_level(uid) + return None + def set_user_access(self, uid, channel, callback, link_auth, ipmi_msg, privilege_level): if self.has_xcc: self.immhandler.set_user_access(uid, privilege_level) diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index 9ea28824..8f1158a2 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -883,6 +883,14 @@ class XCCClient(IMMClient): self.ipmicmd.ipmi_session.register_keepalive(self.keepalive, None) self.adp_referer = None + def get_user_privilege_level(self, uid): + uid = uid - 1 + accurl = '/redfish/v1/AccountService/Accounts/{0}'.format(uid) + accinfo, status = self.grab_redfish_response_with_status(accurl) + if status == 200: + return accinfo.get('RoleId', None) + return None + def set_user_access(self, uid, privilege_level): uid = uid - 1 role = None @@ -892,6 +900,8 @@ class XCCClient(IMMClient): role = 'Operator' elif privilege_level == 'user': role = 'ReadOnly' + elif privilege_level.startswith('custom.'): + role = privilege_level.replace('custom.', '') if role: self.grab_redfish_response_with_status( '/redfish/v1/AccountService/Accounts/{0}'.format(uid), @@ -2019,6 +2029,9 @@ class XCCClient(IMMClient): '/redfish/v1/UpdateService', {'HttpPushUriTargets': []}, method='PATCH') + def set_custom_user_privilege(self, uid, privilege): + return self.set_user_access(self, uid, privilege) + def update_firmware(self, filename, data=None, progress=None, bank=None): usd = self.grab_redfish_response_emptyonerror( '/redfish/v1/UpdateService') diff --git a/pyghmi/redfish/command.py b/pyghmi/redfish/command.py index ccb12f9b..ba05ef92 100644 --- a/pyghmi/redfish/command.py +++ b/pyghmi/redfish/command.py @@ -354,6 +354,8 @@ class Command(object): return True def set_user_access(self, uid, privilege_level='ReadOnly'): + if privilege_level.startswith('custom.'): + privilege_level = privilege_level.replace('custom.', '') accinfo = self._account_url_info_by_id(uid) if not accinfo: raise Exception("Unable to find indicated uid") @@ -375,6 +377,8 @@ class Command(object): accinfo = self._account_url_info_by_id(uid) if not accinfo: raise Exception("Unable to find indicated uid") + if privilege_level.startswith('custom.'): + privilege_level = privilege_level.replace('custom.', '') for role in self._validroles: if role.lower() == privilege_level.lower(): privilege_level = role