Permit assignment the IPMI management channel via JSON
phosphor-ipmi-host hard codes Channel 1 as the LAN NIC responsible for
managing and updating IPMI, Redfish, and web server access
permissions. Systems that do not have an lan-802.3 channel type
configured for IPMI Channel 1 have no way of assigning permissions
that flow to phosphor-user-manager. The inability to update
permissions within phosphor-user-manaager ultimaltely flows to Redfish
and HTTPS access.
The changes in this commit provide flexibility in assigning the IPMI
channel used to propagate permission changes to
phosphor-user-manager. A new boolean keyword, is_managment_nic, is
added. This entry is added to the JSON file, channel_config.json by
default, to announce which lan-802.3 IPMI channel is to be used to
assign IPMI permissions used by phosphor-user-manager. Only one
channel can have this ability. If the keyword is missing in the JSON
file, the code falls back to using Channel 1.
Tested:
Fully testing this change requires using code that dynamically
disables Channel 1. The SUT only has a single NIC, which is not
assigned to Channel 1.
Fully reprogrammed SPI to enter a pristine state.
Created a new user, channel 3, id 2, privilege=4
Confirmed LAN "ipmitool raw 6 1" succeeds
Confirmed Web access to new user account
Confirmed Redfish acess to new user account
Confirmed BMC console "ipmitool raw 6 1" succeeds
Used BMC console ipmitool to change user permissions from 4 to
15 (i.e. no access)
Confirmed LAN "ipmitool raw 6 1" succeeds
Confirmed Web access to new user account fails
Confirmed Redfish acess to new user account fails
Confirmed BMC console "ipmitool raw 6 1" fails
Used BMC console ipmitool to change user permissions from 15 to
4 (i.e. admin)
All of the prior tests work as expected.
Change-Id: I5f6941fefc4f80742e404de1f22ba10cbedf5d5d
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/user_channel/channel_mgmt.cpp b/user_channel/channel_mgmt.cpp
index b8e0b85..b682ccb 100644
--- a/user_channel/channel_mgmt.cpp
+++ b/user_channel/channel_mgmt.cpp
@@ -17,6 +17,7 @@
#include "channel_mgmt.hpp"
#include "apphandler.hpp"
+#include "user_layer.hpp"
#include <sys/stat.h>
#include <unistd.h>
@@ -67,6 +68,7 @@
static constexpr const char* protocolTypeString = "protocol_type";
static constexpr const char* sessionSupportedString = "session_supported";
static constexpr const char* isIpmiString = "is_ipmi";
+static constexpr const char* isManagementNIC = "is_management_nic";
static constexpr const char* authTypeSupportedString = "auth_type_supported";
static constexpr const char* accessModeString = "access_mode";
static constexpr const char* userAuthDisabledString = "user_auth_disabled";
@@ -852,6 +854,7 @@
channelData[chNum].chID = chNum;
channelData[chNum].isChValid = false;
channelData[chNum].activeSessCount = 0;
+ channelData[chNum].isManagementNIC = false;
channelData[chNum].chInfo.mediumType = defaultMediumType;
channelData[chNum].chInfo.protocolType = defaultProtocolType;
@@ -860,6 +863,34 @@
channelData[chNum].chInfo.authTypeSupported = defaultAuthType;
}
+uint8_t ChannelConfig::getManagementNICID()
+{
+ static bool idFound = false;
+ static uint8_t id = 0;
+
+ if (idFound)
+ {
+ return id;
+ }
+
+ for (uint8_t chIdx = 0; chIdx < maxIpmiChannels; chIdx++)
+ {
+ if (channelData[chIdx].isManagementNIC)
+ {
+ id = chIdx;
+ idFound = true;
+ break;
+ }
+ }
+
+ if (!idFound)
+ {
+ id = static_cast<uint8_t>(EChannelID::chanLan1);
+ idFound = true;
+ }
+ return id;
+}
+
int ChannelConfig::loadChannelConfig()
{
boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
@@ -904,6 +935,12 @@
chData.activeSessCount = jsonChData.value(activeSessionsString, 0);
chData.maxTransferSize =
jsonChData.value(maxTransferSizeString, smallChannelSize);
+ if (jsonChData.count(isManagementNIC) != 0)
+ {
+ chData.isManagementNIC =
+ jsonChData[isManagementNIC].get<bool>();
+ }
+
std::string medTypeStr =
jsonChInfo[mediumTypeString].get<std::string>();
chData.chInfo.mediumType =
diff --git a/user_channel/channel_mgmt.hpp b/user_channel/channel_mgmt.hpp
index 0c31338..0f35816 100644
--- a/user_channel/channel_mgmt.hpp
+++ b/user_channel/channel_mgmt.hpp
@@ -64,6 +64,7 @@
ChannelInfo chInfo;
ChannelAccessData chAccess;
size_t maxTransferSize;
+ bool isManagementNIC;
};
class ChannelConfig;
@@ -235,6 +236,14 @@
*/
int writeChannelVolatileData();
+ /** @brief Returns the IPMI channel ID authorized to push IPMI privilege
+ * changes to phosphor-user-manager. Any channel access changes made on
+ * any other channel are ignored.
+ *
+ * @return IPMI channel ID as defined in channel_config.json
+ */
+ uint8_t getManagementNICID();
+
private:
uint32_t signalFlag = 0;
std::unique_ptr<boost::interprocess::named_recursive_mutex> channelMutex{
diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp
index 04eb2f9..a1aba71 100644
--- a/user_channel/user_mgmt.cpp
+++ b/user_channel/user_mgmt.cpp
@@ -17,6 +17,7 @@
#include "apphandler.hpp"
#include "channel_layer.hpp"
+#include "channel_mgmt.hpp"
#include <security/pam_appl.h>
#include <sys/stat.h>
@@ -509,11 +510,15 @@
uint8_t UserAccess::getUsrMgmtSyncIndex()
{
- // TODO: Need to get LAN1 channel number dynamically,
- // which has to be in sync with system user privilege
- // level(Phosphor-user-manager). Note: For time being chanLan1 is marked as
- // sync index to the user-manager privilege..
- return static_cast<uint8_t>(EChannelID::chanLan1);
+ // Identify the IPMI channel used to assign system user privilege levels
+ // in phosphor-user-manager. The default value is IPMI Channel 1. To
+ // assign a different channel add:
+ // "is_management_nic" : true
+ // into the channel_config.json file describing the assignment of the IPMI
+ // channels. It is only necessary to add the string above to ONE record in
+ // the channel_config.json file. All other records will be automatically
+ // assigned a "false" value.
+ return getChannelConfigObject().getManagementNICID();
}
CommandPrivilege UserAccess::convertToIPMIPrivilege(const std::string& value)