summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/persistent_data_middleware.hpp7
-rw-r--r--include/sessions.hpp61
-rw-r--r--include/token_authorization_middleware.hpp17
-rw-r--r--redfish-core/lib/account_service.hpp109
-rw-r--r--static/redfish/v1/$metadata/index.xml4
-rw-r--r--static/redfish/v1/JsonSchemas/OemAccountService/index.json102
-rw-r--r--static/redfish/v1/schema/OemAccountService_v1.xml71
7 files changed, 359 insertions, 12 deletions
diff --git a/include/persistent_data_middleware.hpp b/include/persistent_data_middleware.hpp
index c368ab21dc..348079ba61 100644
--- a/include/persistent_data_middleware.hpp
+++ b/include/persistent_data_middleware.hpp
@@ -100,6 +100,12 @@ class Middleware
systemUuid = *jSystemUuid;
}
}
+ else if (item.key() == "auth_config")
+ {
+ SessionStore::getInstance()
+ .getAuthMethodsConfig()
+ .fromJson(item.value());
+ }
else if (item.key() == "sessions")
{
for (const auto& elem : item.value())
@@ -163,6 +169,7 @@ class Middleware
nlohmann::json data{
{"sessions", SessionStore::getInstance().authTokens},
+ {"auth_config", SessionStore::getInstance().getAuthMethodsConfig()},
{"system_uuid", systemUuid},
{"revision", jsonRevision}};
persistentFile << data;
diff --git a/include/sessions.hpp b/include/sessions.hpp
index df65d6155d..749349476c 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -339,6 +339,43 @@ struct UserSession
}
};
+struct AuthConfigMethods
+{
+ bool xtoken = true;
+ bool cookie = true;
+ bool sessionToken = true;
+ bool basic = true;
+
+ void fromJson(const nlohmann::json& j)
+ {
+ for (const auto& element : j.items())
+ {
+ const bool* value = element.value().get_ptr<const bool*>();
+ if (value == nullptr)
+ {
+ continue;
+ }
+
+ if (element.key() == "XToken")
+ {
+ xtoken = *value;
+ }
+ else if (element.key() == "Cookie")
+ {
+ cookie = *value;
+ }
+ else if (element.key() == "SessionToken")
+ {
+ sessionToken = *value;
+ }
+ else if (element.key() == "BasicAuth")
+ {
+ basic = *value;
+ }
+ }
+ }
+};
+
class Middleware;
class SessionStore
@@ -445,6 +482,17 @@ class SessionStore
return ret;
}
+ void updateAuthMethodsConfig(const AuthConfigMethods& config)
+ {
+ authMethodsConfig = config;
+ needWrite = true;
+ }
+
+ AuthConfigMethods& getAuthMethodsConfig()
+ {
+ return authMethodsConfig;
+ }
+
bool needsWrite()
{
return needWrite;
@@ -501,6 +549,7 @@ class SessionStore
std::random_device rd;
bool needWrite{false};
std::chrono::minutes timeoutInMinutes;
+ AuthConfigMethods authMethodsConfig;
};
} // namespace persistent_data
@@ -526,4 +575,16 @@ struct adl_serializer<std::shared_ptr<crow::persistent_data::UserSession>>
}
}
};
+
+template <> struct adl_serializer<crow::persistent_data::AuthConfigMethods>
+{
+ static void to_json(nlohmann::json& j,
+ const crow::persistent_data::AuthConfigMethods& c)
+ {
+ j = nlohmann::json{{"XToken", c.xtoken},
+ {"Cookie", c.cookie},
+ {"SessionToken", c.sessionToken},
+ {"BasicAuth", c.basic}};
+ }
+};
} // namespace nlohmann
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp
index 0a440501e1..7e4e3bb22f 100644
--- a/include/token_authorization_middleware.hpp
+++ b/include/token_authorization_middleware.hpp
@@ -31,8 +31,15 @@ class Middleware
return;
}
- req.session = performXtokenAuth(req);
- if (req.session == nullptr)
+ const crow::persistent_data::AuthConfigMethods& authMethodsConfig =
+ crow::persistent_data::SessionStore::getInstance()
+ .getAuthMethodsConfig();
+
+ if (req.session == nullptr && authMethodsConfig.xtoken)
+ {
+ req.session = performXtokenAuth(req);
+ }
+ if (req.session == nullptr && authMethodsConfig.cookie)
{
req.session = performCookieAuth(req);
}
@@ -42,11 +49,13 @@ class Middleware
if (!authHeader.empty())
{
// Reject any kind of auth other than basic or token
- if (boost::starts_with(authHeader, "Token "))
+ if (boost::starts_with(authHeader, "Token ") &&
+ authMethodsConfig.sessionToken)
{
req.session = performTokenAuth(authHeader);
}
- else if (boost::starts_with(authHeader, "Basic "))
+ else if (boost::starts_with(authHeader, "Basic ") &&
+ authMethodsConfig.basic)
{
req.session = performBasicAuth(authHeader);
}
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 59e2d1cd67..bc8ce771d6 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -553,7 +553,8 @@ inline void getLDAPConfigData(const std::string& ldapType,
class AccountService : public Node
{
public:
- AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/")
+ AccountService(CrowApp& app) :
+ Node(app, "/redfish/v1/AccountService/"), app(app)
{
entityPrivileges = {
{boost::beast::http::verb::get,
@@ -887,6 +888,65 @@ class AccountService : public Node
ldapEnableInterface, "Enabled", std::variant<bool>(serviceEnabled));
}
+ void handleAuthMethodsPatch(nlohmann::json& input,
+ const std::shared_ptr<AsyncResp>& asyncResp)
+ {
+ std::optional<bool> basicAuth;
+ std::optional<bool> cookie;
+ std::optional<bool> sessionToken;
+ std::optional<bool> xToken;
+
+ if (!json_util::readJson(input, asyncResp->res, "BasicAuth", basicAuth,
+ "Cookie", cookie, "SessionToken", sessionToken,
+ "XToken", xToken))
+ {
+ BMCWEB_LOG_ERROR << "Cannot read values from AuthMethod tag";
+ return;
+ }
+
+ // Make a copy of methods configuration
+ crow::persistent_data::AuthConfigMethods authMethodsConfig =
+ crow::persistent_data::SessionStore::getInstance()
+ .getAuthMethodsConfig();
+
+ if (basicAuth)
+ {
+ authMethodsConfig.basic = *basicAuth;
+ }
+
+ if (cookie)
+ {
+ authMethodsConfig.cookie = *cookie;
+ }
+
+ if (sessionToken)
+ {
+ authMethodsConfig.sessionToken = *sessionToken;
+ }
+
+ if (xToken)
+ {
+ authMethodsConfig.xtoken = *xToken;
+ }
+
+ if (!authMethodsConfig.basic && !authMethodsConfig.cookie &&
+ !authMethodsConfig.sessionToken && !authMethodsConfig.xtoken)
+ {
+ // Do not allow user to disable everything
+ messages::actionNotSupported(asyncResp->res,
+ "of disabling all available methods");
+ return;
+ }
+
+ crow::persistent_data::SessionStore::getInstance()
+ .updateAuthMethodsConfig(authMethodsConfig);
+ // Save configuration immediately
+ app.template getMiddleware<crow::persistent_data::Middleware>()
+ .writeData();
+
+ messages::success(asyncResp->res);
+ }
+
/**
* @brief Get the required values from the given JSON, validates the
* value and create the LDAP config object.
@@ -1063,6 +1123,10 @@ class AccountService : public Node
void doGet(crow::Response& res, const crow::Request& req,
const std::vector<std::string>& params) override
{
+ const crow::persistent_data::AuthConfigMethods& authMethodsConfig =
+ crow::persistent_data::SessionStore::getInstance()
+ .getAuthMethodsConfig();
+
auto asyncResp = std::make_shared<AsyncResp>(res);
res.jsonValue = {
{"@odata.context", "/redfish/v1/"
@@ -1078,6 +1142,16 @@ class AccountService : public Node
{"Accounts",
{{"@odata.id", "/redfish/v1/AccountService/Accounts"}}},
{"Roles", {{"@odata.id", "/redfish/v1/AccountService/Roles"}}},
+ {"Oem",
+ {{"OpenBMC",
+ {{"@odata.type", "#OemAccountService.v1_0_0.AccountService"},
+ {"AuthMethods",
+ {
+ {"BasicAuth", authMethodsConfig.basic},
+ {"SessionToken", authMethodsConfig.sessionToken},
+ {"XToken", authMethodsConfig.xtoken},
+ {"Cookie", authMethodsConfig.cookie},
+ }}}}}},
{"LDAP",
{{"Certificates",
{{"@odata.id",
@@ -1155,13 +1229,14 @@ class AccountService : public Node
std::optional<uint16_t> maxPasswordLength;
std::optional<nlohmann::json> ldapObject;
std::optional<nlohmann::json> activeDirectoryObject;
-
- if (!json_util::readJson(req, res, "AccountLockoutDuration",
- unlockTimeout, "AccountLockoutThreshold",
- lockoutThreshold, "MaxPasswordLength",
- maxPasswordLength, "MinPasswordLength",
- minPasswordLength, "LDAP", ldapObject,
- "ActiveDirectory", activeDirectoryObject))
+ std::optional<nlohmann::json> oemObject;
+
+ if (!json_util::readJson(
+ req, res, "AccountLockoutDuration", unlockTimeout,
+ "AccountLockoutThreshold", lockoutThreshold,
+ "MaxPasswordLength", maxPasswordLength, "MinPasswordLength",
+ minPasswordLength, "LDAP", ldapObject, "ActiveDirectory",
+ activeDirectoryObject, "Oem", oemObject))
{
return;
}
@@ -1181,6 +1256,22 @@ class AccountService : public Node
handleLDAPPatch(*ldapObject, asyncResp, req, params, "LDAP");
}
+ if (std::optional<nlohmann::json> oemOpenBMCObject;
+ oemObject &&
+ json_util::readJson(*oemObject, res, "OpenBMC", oemOpenBMCObject))
+ {
+ if (std::optional<nlohmann::json> authMethodsObject;
+ oemOpenBMCObject &&
+ json_util::readJson(*oemOpenBMCObject, res, "AuthMethods",
+ authMethodsObject))
+ {
+ if (authMethodsObject)
+ {
+ handleAuthMethodsPatch(*authMethodsObject, asyncResp);
+ }
+ }
+ }
+
if (activeDirectoryObject)
{
handleLDAPPatch(*activeDirectoryObject, asyncResp, req, params,
@@ -1221,6 +1312,8 @@ class AccountService : public Node
std::variant<uint16_t>(*lockoutThreshold));
}
}
+
+ CrowApp& app;
};
class AccountsCollection : public Node
diff --git a/static/redfish/v1/$metadata/index.xml b/static/redfish/v1/$metadata/index.xml
index 73833652d7..4804e48024 100644
--- a/static/redfish/v1/$metadata/index.xml
+++ b/static/redfish/v1/$metadata/index.xml
@@ -1045,6 +1045,10 @@
<edmx:Include Namespace="NetworkPort.v1_2_2"/>
<edmx:Include Namespace="NetworkPort.v1_2_3"/>
</edmx:Reference>
+ <edmx:Reference Uri="/redfish/v1/schema/OemAccountService_v1.xml">
+ <edmx:Include Namespace="OemAccountService"/>
+ <edmx:Include Namespace="OemAccountService.v1_0_0"/>
+ </edmx:Reference>
<edmx:Reference Uri="/redfish/v1/schema/NetworkPortCollection_v1.xml">
<edmx:Include Namespace="NetworkPortCollection"/>
</edmx:Reference>
diff --git a/static/redfish/v1/JsonSchemas/OemAccountService/index.json b/static/redfish/v1/JsonSchemas/OemAccountService/index.json
new file mode 100644
index 0000000000..528317086c
--- /dev/null
+++ b/static/redfish/v1/JsonSchemas/OemAccountService/index.json
@@ -0,0 +1,102 @@
+{
+ "$id": "http://redfish.dmtf.org/schemas/v1/OemAccountService.v1_0_0.json",
+ "$schema": "http://redfish.dmtf.org/schemas/v1/redfish-schema-v1.json",
+ "copyright": "Copyright 2014-2019 DMTF. For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright",
+ "definitions": {
+ "AccountService": {
+ "additionalProperties": false,
+ "description": "OEM Extension for AccountService",
+ "longDescription": "OEM Extension for AccountService providing info about TLS Auth.",
+ "patternProperties": {
+ "^([a-zA-Z_][a-zA-Z0-9_]*)?@(odata|Redfish|Message)\\.[a-zA-Z_][a-zA-Z0-9_]*$": {
+ "description": "This property shall specify a valid odata or Redfish property.",
+ "type": [
+ "array",
+ "boolean",
+ "integer",
+ "number",
+ "null",
+ "object",
+ "string"
+ ]
+ }
+ },
+ "properties": {
+ "AuthMethods": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/AuthMethodsConfig"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Authorization Methods configuration.",
+ "longDescription": "Configuration describing which auth methods are enabled."
+ }
+ },
+ "type": "object"
+ },
+ "AuthMethodsConfig": {
+ "additionalProperties": false,
+ "description": "Authorization Methods configuration.",
+ "longDescription": "Configuration describing which auth methods are enabled.",
+ "patternProperties": {
+ "^([a-zA-Z_][a-zA-Z0-9_]*)?@(odata|Redfish|Message)\\.[a-zA-Z_][a-zA-Z0-9_]*$": {
+ "description": "This property shall specify a valid odata or Redfish property.",
+ "type": [
+ "array",
+ "boolean",
+ "integer",
+ "number",
+ "null",
+ "object",
+ "string"
+ ]
+ }
+ },
+ "properties": {
+ "BasicAuth": {
+ "description": "Indicates whether BasicAuth authorization is enabled.",
+ "longDescription": "The value of this property shall be a boolean indicating whether BasicAuth authorization is enabled.",
+ "readonly": false,
+ "type": [
+ "boolean",
+ "null"
+ ]
+ },
+ "Cookie": {
+ "description": "Indicates whether Cookie authorization is enabled.",
+ "longDescription": "The value of this property shall be a boolean indicating whether Cookie authorization is enabled.",
+ "readonly": false,
+ "type": [
+ "boolean",
+ "null"
+ ]
+ },
+ "SessionToken": {
+ "description": "Indicates whether SessionToken authorization is enabled.",
+ "longDescription": "The value of this property shall be a boolean indicating whether SessionToken authorization is enabled.",
+ "readonly": false,
+ "type": [
+ "boolean",
+ "null"
+ ]
+ },
+ "XToken": {
+ "description": "Indicates whether XToken authorization is enabled.",
+ "longDescription": "The value of this property shall be a boolean indicating whether XToken authorization is enabled.",
+ "readonly": false,
+ "type": [
+ "boolean",
+ "null"
+ ]
+ }
+ },
+ "type": "object"
+ }
+ },
+ "owningEntity": "OpenBMC",
+ "release": "1.0",
+ "title": "#OemAccountService.v1_0_0"
+} \ No newline at end of file
diff --git a/static/redfish/v1/schema/OemAccountService_v1.xml b/static/redfish/v1/schema/OemAccountService_v1.xml
new file mode 100644
index 0000000000..626097b3c8
--- /dev/null
+++ b/static/redfish/v1/schema/OemAccountService_v1.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+
+ <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
+ <edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
+ </edmx:Reference>
+ <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Measures.V1.xml">
+ <edmx:Include Namespace="Org.OData.Measures.V1" Alias="Measures"/>
+ </edmx:Reference>
+ <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/RedfishExtensions_v1.xml">
+ <edmx:Include Namespace="RedfishExtensions.v1_0_0" Alias="Redfish"/>
+ </edmx:Reference>
+ <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/Resource_v1.xml">
+ <edmx:Include Namespace="Resource"/>
+ <edmx:Include Namespace="Resource.v1_0_0"/>
+ </edmx:Reference>
+
+ <edmx:DataServices>
+
+ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="OemAccountService">
+ <Annotation Term="Redfish.OwningEntity" String="OpenBMC"/>
+ </Schema>
+
+ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="OemAccountService.v1_0_0">
+ <Annotation Term="Redfish.OwningEntity" String="OpenBMC"/>
+ <Annotation Term="Redfish.Release" String="1.0"/>
+
+ <ComplexType Name="AuthMethodsConfig">
+ <Annotation Term="OData.AdditionalProperties" Bool="false"/>
+ <Annotation Term="OData.Description" String="Authorization Methods configuration."/>
+ <Annotation Term="OData.LongDescription" String="Configuration describing which auth methods are enabled."/>
+
+ <Property Name="BasicAuth" Type="Edm.Boolean">
+ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/>
+ <Annotation Term="OData.Description" String="Indicates whether BasicAuth authorization is enabled."/>
+ <Annotation Term="OData.LongDescription" String="The value of this property shall be a boolean indicating whether BasicAuth authorization is enabled."/>
+ </Property>
+
+ <Property Name="Cookie" Type="Edm.Boolean">
+ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/>
+ <Annotation Term="OData.Description" String="Indicates whether Cookie authorization is enabled."/>
+ <Annotation Term="OData.LongDescription" String="The value of this property shall be a boolean indicating whether Cookie authorization is enabled."/>
+ </Property>
+
+ <Property Name="SessionToken" Type="Edm.Boolean">
+ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/>
+ <Annotation Term="OData.Description" String="Indicates whether SessionToken authorization is enabled."/>
+ <Annotation Term="OData.LongDescription" String="The value of this property shall be a boolean indicating whether SessionToken authorization is enabled."/>
+ </Property>
+
+ <Property Name="XToken" Type="Edm.Boolean">
+ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/>
+ <Annotation Term="OData.Description" String="Indicates whether XToken authorization is enabled."/>
+ <Annotation Term="OData.LongDescription" String="The value of this property shall be a boolean indicating whether XToken authorization is enabled."/>
+ </Property>
+ </ComplexType>
+
+ <!--Base entity type for array members-->
+ <EntityType Name="AccountService" BaseType="Resource.OemObject" Abstract="true">
+ <Annotation Term="OData.Description" String="OEM Extension for AccountService"/>
+ <Annotation Term="OData.LongDescription" String="OEM Extension for AccountService providing info about TLS Auth."/>
+
+ <Property Name="AuthMethods" Type="OemAccountService.v1_0_0.AuthMethodsConfig">
+ <Annotation Term="OData.Description" String="Authorization Methods configuration."/>
+ <Annotation Term="OData.LongDescription" String="Configuration describing which auth methods are enabled."/>
+ </Property>
+ </EntityType>
+ </Schema>
+
+ </edmx:DataServices>
+</edmx:Edmx>