Mutual TLS parsing change at runtime
Redfish AccountService[1] defines methods for selecting how to map a
certificate CommonName attribute to a user. These are intended to be a
patch parameter.
This commit implements the Redfish defined schemas; The parsing mode is
stored in the bmcweb persistent configuration file as an integer enum,
with Mapping to the Redfish schema.
To handle OEM specific parsing modes, an enum value of 100+ is defined
to allow the additional OEM parameters. Unfortunately, Redfish doesn't
have a way to represent these today, so those modes are currently not
selectable at runtime.
Now that things are runtime selectable, this obsoletes the option
mutual-tls-common-name-parsing, as it is not longer required at compile
time.
Tested:
GET /redfish/v1/AccountService
returns MultiFactorAuth/ClientCertificate/CertificateMappingAttribute
PATCH /redfish/v1/AccountService
```
{"MultiFactorAuth": {"ClientCertificate": {"CertificateMappingAttribute":"CommonName"}}}
```
Returns 200
[1] https://github.com/DMTF/Redfish-Publications/blob/5b217908b5378b24e4f390c063427d7a707cd308/csdl/AccountService_v1.xml#L1631
Change-Id: I67db0dfa5245a9da973320aab666d12dbd9229e4
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp
index 3bd256d..fff08d3 100644
--- a/include/persistent_data.hpp
+++ b/include/persistent_data.hpp
@@ -214,7 +214,8 @@
std::filesystem::perms::owner_write |
std::filesystem::perms::group_read;
std::filesystem::permissions(filename, permission);
- const auto& c = SessionStore::getInstance().getAuthMethodsConfig();
+ const AuthConfigMethods& c =
+ SessionStore::getInstance().getAuthMethodsConfig();
const auto& eventServiceConfig =
EventServiceStore::getInstance().getEventServiceConfig();
nlohmann::json::object_t data;
@@ -225,6 +226,8 @@
authConfig["SessionToken"] = c.sessionToken;
authConfig["BasicAuth"] = c.basic;
authConfig["TLS"] = c.tls;
+ authConfig["TLSCommonNameParseMode"] =
+ static_cast<int>(c.mTLSCommonNameParsingMode);
nlohmann::json& eventserviceConfig = data["eventservice_config"];
eventserviceConfig["ServiceEnabled"] = eventServiceConfig.enabled;
diff --git a/include/sessions.hpp b/include/sessions.hpp
index 5621fff..9c064ee 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -134,6 +134,49 @@
}
};
+enum class MTLSCommonNameParseMode
+{
+ Invalid = 0,
+ // This section approximately matches Redfish AccountService
+ // CertificateMappingAttribute, plus bmcweb defined OEM ones.
+ // Note, IDs in this enum must be maintained between versions, as they are
+ // persisted to disk
+ Whole = 1,
+ CommonName = 2,
+ UserPrincipalName = 3,
+
+ // Intentional gap for future DMTF-defined enums
+
+ // OEM parsing modes for various OEMs
+ Meta = 100,
+};
+
+inline MTLSCommonNameParseMode getMTLSCommonNameParseMode(std::string_view name)
+{
+ if (name == "CommonName")
+ {
+ return MTLSCommonNameParseMode::CommonName;
+ }
+ if (name == "Whole")
+ {
+ // Not yet supported
+ // return MTLSCommonNameParseMode::Whole;
+ }
+ if (name == "UserPrincipalName")
+ {
+ // Not yet supported
+ // return MTLSCommonNameParseMode::UserPrincipalName;
+ }
+ if constexpr (BMCWEB_META_TLS_COMMON_NAME_PARSING)
+ {
+ if (name == "Meta")
+ {
+ return MTLSCommonNameParseMode::Meta;
+ }
+ }
+ return MTLSCommonNameParseMode::Invalid;
+}
+
struct AuthConfigMethods
{
bool basic = BMCWEB_BASIC_AUTH;
@@ -142,35 +185,56 @@
bool cookie = BMCWEB_COOKIE_AUTH;
bool tls = BMCWEB_MUTUAL_TLS_AUTH;
+ MTLSCommonNameParseMode mTLSCommonNameParsingMode =
+ getMTLSCommonNameParseMode(
+ BMCWEB_MUTUAL_TLS_COMMON_NAME_PARSING_DEFAULT);
+
void fromJson(const nlohmann::json::object_t& j)
{
for (const auto& element : j)
{
const bool* value = element.second.get_ptr<const bool*>();
- if (value == nullptr)
+ if (value != nullptr)
{
- continue;
+ if (element.first == "XToken")
+ {
+ xtoken = *value;
+ }
+ else if (element.first == "Cookie")
+ {
+ cookie = *value;
+ }
+ else if (element.first == "SessionToken")
+ {
+ sessionToken = *value;
+ }
+ else if (element.first == "BasicAuth")
+ {
+ basic = *value;
+ }
+ else if (element.first == "TLS")
+ {
+ tls = *value;
+ }
}
-
- if (element.first == "XToken")
+ const uint64_t* intValue =
+ element.second.get_ptr<const uint64_t*>();
+ if (intValue != nullptr)
{
- xtoken = *value;
- }
- else if (element.first == "Cookie")
- {
- cookie = *value;
- }
- else if (element.first == "SessionToken")
- {
- sessionToken = *value;
- }
- else if (element.first == "BasicAuth")
- {
- basic = *value;
- }
- else if (element.first == "TLS")
- {
- tls = *value;
+ if (element.first == "MTLSCommonNameParseMode")
+ {
+ if (*intValue <= 2 || *intValue == 100)
+ {
+ mTLSCommonNameParsingMode =
+ static_cast<MTLSCommonNameParseMode>(*intValue);
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR(
+ "Json value of {} was out of range of the enum. Ignoring",
+ *intValue);
+ }
+ }
}
}
}