633 lines
32 KiB
Markdown
633 lines
32 KiB
Markdown
# Dynamic Redfish Authorization
|
|
|
|
Author: Nan Zhou (nanzhoumails@gmail.com)
|
|
|
|
Created: 08/08/2022
|
|
|
|
## Problem Description
|
|
|
|
The Redfish authorization subsystem controls which authenticated users have
|
|
access to resources and the type of access that users have.
|
|
|
|
DMTF has already defined the authorization model and schemas. This design is to
|
|
enhance the current implementation in BMCWeb Redfish interface so that OpenBMC
|
|
systems exposes interfaces to change authorization behavior at runtime without
|
|
Redfish service restart.
|
|
|
|
## Background and References
|
|
|
|
### Redfish Authorization Model
|
|
|
|
The Redfish authorization model consists of the privilege model and the
|
|
operation-to-privilege mapping.
|
|
|
|
In the privilege model, there are fixed set of standard Redfish roles and each
|
|
of them is assigned a fixed array of standard privileges (e.g., `Login`,
|
|
`ConfigureManager`, etc). A service may define custom OEM roles (read-only). A
|
|
service may even allow custom client-defined roles to be created, modified, and
|
|
deleted via REST operations on `RoleCollection`.
|
|
|
|
The operation-to-privilege mapping is defined for every resource type and
|
|
applies to every resource the service implements for the applicable resource
|
|
type. It is used to determine whether the identity privileges of an
|
|
authenticated Redfish role are sufficient to complete the operation in the
|
|
request. The Redfish Forum provides a Privilege Registry definition in its
|
|
official registry collection as a base operation-to-privilege mapping. It also
|
|
allows mapping overrides (Property override, Subordinate override, and Resource
|
|
URI override) to customize mapping.
|
|
|
|
For example, a peer who is an `Operator` that has both `Login`,
|
|
`ConfigureComponents`, and `ConfigureSelf` privileges, is authorized to send a
|
|
`GET` request to the `ChassisCollection`, since the `GET` operation on this
|
|
resource only requires the `Login` privilege. On the other hand, the same peer
|
|
gets denied access if they send a POST request to `CertificateService`, as the
|
|
POST operation on certificates requires `ConfigureManager` privilege that the
|
|
peer is missing.
|
|
|
|
**Note**, in the Redfish spec, OEM roles can be added via POST to the
|
|
`RoleCollection` in the `AccountService`; `PrivilegesUsed`, `OEMPrivilegesUsed`,
|
|
and properties of `Mappings` are all read-only.
|
|
|
|
References:
|
|
|
|
1. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#privilege-model
|
|
2. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#redfish-service-operation-to-privilege-mapping
|
|
3. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#roles
|
|
4. https://redfish.dmtf.org/registries/v1/Redfish_1.3.0_PrivilegeRegistry.json
|
|
|
|
### Phosphor-user-manager
|
|
|
|
Phosphor-user-manager is an OpenBMC daemon that does user management.
|
|
|
|
It exposes DBus APIs to dynamically add users, manage users' attributes (e.g.,
|
|
group, privileges, status, and account policies). It has a hardcoded list of
|
|
user groups (SSH, IPMI, Redfish, Web) and a hardcoded list of privileges
|
|
("priv-admin", "priv-operator", "priv-user", "priv-noaccess"). These privileges
|
|
are implemented as Linux secondary groups.
|
|
|
|
It also integrates LDAP (supports either ActiveDirectory or OpenLDAP) for remote
|
|
user management, where BMC acts as a LDAP client and uses nslcd to automatically
|
|
convert Linux system calls to LDAP queries.
|
|
|
|
References:
|
|
|
|
1. https://github.com/openbmc/docs/blob/master/architecture/user-management.md
|
|
2. https://github.com/openbmc/phosphor-user-manager
|
|
3. https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/yaml/xyz/openbmc_project/User
|
|
4. https://linux.die.net/man/8/nslcd
|
|
5. https://linux.die.net/man/8/nscd
|
|
|
|
### BMCWeb
|
|
|
|
BMCWeb is an OpenBMC Daemon which implements the Redfish service (it implements
|
|
other management interfaces as well besides Redfish).
|
|
|
|
BMCWeb supports various "authentication" options, but under the hood, to verify
|
|
the user is who they claim they are, there are two main authentication methods:
|
|
|
|
1. PAM based: use Linux-PAM to do username/password style of authentication
|
|
2. TLS based: use the Public Key infrastructure to verify signature of peer's
|
|
certificates; then use identities (in X509 certificates, these are Common
|
|
Name or Subject Alternative Name) as user names.
|
|
|
|
After getting the peer's user name, BMCWeb sends DBus queries to
|
|
phosphor-user-manager to query the user's privileges and uses a hardcoded map to
|
|
convert the privileges to Redfish roles. The hardcoded map is listed below:
|
|
|
|
| Phosphor-user-manager privileges (implemented as groups) | BMCWeb Redfish Roles |
|
|
| -------------------------------------------------------- | -------------------- |
|
|
| priv-admin | Administrator |
|
|
| priv-operator | Operator |
|
|
| priv-user | ReadOnly |
|
|
| priv-noaccess | NoAccess |
|
|
|
|
To map Redfish role to their assigned Redfish privileges, BMCWeb implements the
|
|
following hardcoded map:
|
|
|
|
| BMCWeb Redfish Roles | Assigned Redfish Privileges |
|
|
| -------------------- | -------------------------------------------------------------------------------------- |
|
|
| Administrator | "Login", "ConfigureManager", "ConfigureUsers", "ConfigureSelf", "ConfigureComponents"} |
|
|
| Operator | "Login", "ConfigureSelf", "ConfigureComponents" |
|
|
| ReadOnly | "Login", "ConfigureSelf" |
|
|
| NoAccess | NA |
|
|
|
|
At compile time, BMCWeb assigns each operation of each entity a set of required
|
|
Redfish Privileges. An authorization action is performed when a BMCWeb route
|
|
callback is performed: check if the assigned Redfish Privileges is a superset of
|
|
the required Redfish Privileges.
|
|
|
|
In the following section, we refer a BMCWeb route as the handler of an operation
|
|
of an given resource URI, which is what the BMCWEB_ROUTE macro has defined.
|
|
|
|
References:
|
|
|
|
1. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/include/authentication.hpp
|
|
2. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/http/http_connection.hpp
|
|
3. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/redfish-core/lib/roles.hpp
|
|
|
|
### Gaps
|
|
|
|
As mentioned above, majority of the current Redfish authorization settings are
|
|
configured at compile time including:
|
|
|
|
1. the set of Phosphor-user-manager privileges
|
|
2. the mapping from Phosphor-user-manager privileges to Redfish roles
|
|
3. the set of Redfish roles
|
|
4. the mapping from Redfish roles to Redfish Privileges
|
|
5. the operation-to-privilege mapping
|
|
|
|
However, modern systems have use cases where Redfish roles, Redfish privileges,
|
|
and operation-to-privilege mapping need to change when the system keeps running.
|
|
E.g., a new micro-service is introduced and needs to talk to existing BMCs in
|
|
the fleet, we need to propagate a configuration so that this new peer gets a
|
|
proper Redfish role and is authorized to access certain resources without
|
|
rolling out a new BMC firmware.
|
|
|
|
Another gap is that current Redfish roles and operation-to-privilege mapping
|
|
lead to a very coarse-grained access control, and doesn't implement the
|
|
principle of least privilege. Though these configurations are defined by DMTF,
|
|
it is explicitly called out in the standard that implementation implement their
|
|
own OEM roles and privileges if "the standard privilege is overly broad".
|
|
|
|
For systems which have requirement where a given user only has access to the
|
|
resources it needs. For example, a micro-service responsible for remote power
|
|
control can only send GET to Chassis and ComputerSystems, and POST to
|
|
corresponding ResetActions. With the existing implementation, such micro-service
|
|
has at least ConfigureComponents Redfish privilege, which leads to being able to
|
|
patch an EthernetInterface resource.
|
|
|
|
## Requirements
|
|
|
|
BMC implements a dynamic Redfish authorization system:
|
|
|
|
1. Clients shall be able to add new OEM Redfish privileges without recompile
|
|
2. Clients shall be able to add new OEM Redfish roles and assign it with any
|
|
existing Redfish privileges without recompile
|
|
3. Clients shall be able to modify existing operation-to-privilege mappings
|
|
without recompile
|
|
4. Above changes on systems shall be atomic; that is, once changed, all new
|
|
queries will use the latest configurations
|
|
5. BMC shall perform sanity check on above modification; that is
|
|
- It rejects ill formatted modification
|
|
- It rejects modification of non-OEM privileges
|
|
- It rejects deletion of OEM Redfish roles if any user (either local or
|
|
remote) maps such roles
|
|
- It rejects deletion of OEM Redfish privileges if any OEM Redfish role is
|
|
assigned such privileges
|
|
6. BMC shall persist all the above modifications and recover from crash
|
|
7. Existing systems with the static authorization shall work as if this feature
|
|
is not introduced, including non-Redfish routes (e.g., KVM websocket)
|
|
8. Default OEM roles and Redfish privileges must be selectable on a per system
|
|
basis at compile time; default Redfish PrivilegeRegistry must be settable on
|
|
a per system basis at compile time
|
|
9. The total storage used by this feature shall be limited; this is
|
|
- The total rwfs disk usage increase is less than 100 KB on systems with the
|
|
dynamic authorization feature enabled
|
|
- The runtime memory usage increase is less than 1 MB on systems with the
|
|
dynamic authorization feature enabled
|
|
- The binary size increase of modified daemons is less than 100 KB on all
|
|
systems
|
|
10. BMC implements a complete privilege registry; that is
|
|
- It shall implement all overrides in the Redfish base Privilege registries
|
|
at compile time; it shall support configuring overrides at runtime but
|
|
implementation may begin with static configuring and reject runtime
|
|
modification
|
|
- BMC exposes PrivilegeRegistry which represents the current configuration
|
|
and reflects runtime changes
|
|
- Changes to resource entities shall be propagated to the current privilege
|
|
registries automatically
|
|
11. New Redfish resource can be implemented without modifying custom
|
|
PrivilegeRegistry
|
|
12. All the above shall be testable; CI must be capable of finding issues
|
|
|
|
## Proposed Design
|
|
|
|
### Mapping: Users, Redfish Roles, and Redfish Privileges
|
|
|
|
As mentioned in the background section, existing Redfish roles are stored as
|
|
Linux secondary groups with prefix "priv" (includes "priv-admin",
|
|
"priv-operator", and "priv-user"). And a Linux user is in one of these groups
|
|
representing that a user is a specific Redfish role. BMCWeb then uses a
|
|
hardcoded table to map Redfish role to Redfish privileges.
|
|
|
|
However, modeling roles only as static Linux secondary groups doesn't worked
|
|
well with OEM Redfish Roles where a Redfish role maps to a dynamic set of OEM
|
|
privileges: secondary group can't represent associations.
|
|
|
|
To solve this, we propose the following solution:
|
|
|
|
**Store Redfish Roles As Linux Users and Secondary Groups** We propose to store
|
|
Redfish Roles as both Linux users and secondary groups. Storing as secondary
|
|
groups is to associate users with Redfish roles. On the other hand, storing as
|
|
users is to associate Redfish roles with Redfish privileges. See below section
|
|
for these mappings.
|
|
|
|
Users for Redfish roles won't be any predefined groups (web, redfish, ipmi). We
|
|
can add extra attributes to distinguish them with real local and LDAP users.
|
|
Users for Redfish roles won't have SSH permission as well.
|
|
|
|
Redfish roles will have a fixed prefix "openbmc-rfr-". "rfr" refers to Redfish
|
|
role. OEM redfish roles will get prefix "openbmc-orfr-". "orfr" refers to OEM
|
|
Redfish role. For example, the base Redfish role "Administrator" will result in
|
|
a Linux secondary group "openbmc-rfr-administrator" and a local user
|
|
"openbmc-rfr-administrator". We can also make the vendor name ("openbmc")
|
|
configurable at compile time. Using acronym is to save characters since Linux
|
|
username has 31 characters limit.
|
|
|
|
**Store Redfish Privileges as Secondary Groups** Redfish privileges will be
|
|
stored as Linux secondary groups with a fixed prefix "openbmc-rfp". rfr" refers
|
|
to Redfish privilege. OEM privileges will have fixed prefix "openbmc-orfp".
|
|
"orfr" refers to OEM Redfish privilege.
|
|
|
|
**Username to Redfish Role Mapping** Mapping a username to Redfish role becomes
|
|
searching the group starting with "openbmc-rfr" that the user is in.
|
|
|
|
**Redfish Role to Redfish Privileges Mapping** Mapping a Redfish Role to Redfish
|
|
privileges becomes searching all the groups starting with "openbmc-rfp" or
|
|
"openbmc-orfp" of the user.
|
|
|
|
A user maps be in multiple linux secondary groups meaning they are assigned
|
|
certain privileges; for example, user "PowerService" is in "openbmc-orfr-power"
|
|
group meaning its Redfish role is "openbmc-orfr-power"; local user
|
|
"openbmc-orfr-power" is in secondary groups "openbmc-rfp-configureself" and
|
|
"openbmc-orfp-power" groups meaning "openbmc-orfr-power" is assigned to Redfish
|
|
privileges "ConfigureSelf" and "OemPrivPower".
|
|
|
|
The following diagram shows how assigned privileges of a power control service
|
|
with identity (username in PAM, or CN/SAN in TLS) "power-service" is resolved.
|
|
|
|
```
|
|
+-----------------+
|
|
| power service |
|
|
| |
|
|
+--------|--------+
|
|
|
|
|
|
|
|
+-----------------+
|
|
| authentication |
|
|
| (PAM or TLS) |
|
|
| BMCWeb |
|
|
+--------|--------+
|
|
|
|
|
|username:power-service
|
|
|
|
|
+-----------------+ +-----------------+ +----------------------------+
|
|
| BMCWeb |DBus: privileges | phosphor- | | Linux |
|
|
| ------------------------>| user-manager | |user: power-service |
|
|
| |<-----------------------| | |group: |
|
|
| | privileges: | <----------->| openbmc-orfr-power |
|
|
| | Login, ConfigureSelf | | | |
|
|
| | OemPrivPower | | |user: openbmc-orfr-power |
|
|
+-----------------+ +-----------------+ |group: |
|
|
| openbmc-rfp-configureself |
|
|
| openbmc-orfp-power |
|
|
| openbmc-rfp-login |
|
|
+----------------------------+
|
|
```
|
|
|
|
The above diagram works for LDAP users as well. A remote role or group can map
|
|
to base Redfish roles or OEM Redfish roles via RemoteRoleMapping: an LDAP group
|
|
maps to a single Redfish role stored as local users.
|
|
|
|
We propose to extend the existing phosphor-user-manager:
|
|
|
|
1. It returns AllPrivileges dynamically by looking up the current groups
|
|
2. Phosphor-user-manager provides DBus APIs to query privileges of a given user
|
|
|
|
The legacy groups (e.g., `priv-user`) still works as before. For example, a user
|
|
in both `priv-user` and `openbmc-orfp-power` will have the following Redfish
|
|
privileges: `Login`, `ConfigureSelf`, `OemPrivPower`.
|
|
|
|
### Creation/Deletion: Users, Redfish Roles, and Redfish Privileges
|
|
|
|
Base privileges and roles won't be allowed to change at runtime.
|
|
|
|
#### OEM Redfish Privileges
|
|
|
|
PATCH OEMPrivilegesUsed in PrivilegeRegistry creating/deleting OEM privileges to
|
|
create or delete OEM Privileges at runtime.
|
|
|
|
We propose to extend the existing phosphor-user-manager:
|
|
|
|
1. Phosphor-user-manager provides DBus APIs to create/delete OEM Redfish
|
|
privileges; under the hood, it stores privileges as Linux groups, as today
|
|
how base Redfish roles are stored
|
|
2. Phosphor-user-manager keeps a maximum number of Redfish privileges; we
|
|
propose 32 as the first iteration considering fast bit manipulation
|
|
3. Phosphor-user-manager performs validation:
|
|
- Names of OEM Redfish privileges are unique and valid; e.g., start with
|
|
"openbmc-orfp-"
|
|
- Reject deletion of a privilege that's currently in use (assigned to any
|
|
Redfish roles that have a user associated with)
|
|
|
|
Systems can also optionally add OEM Privileges at compile time via Yocto's
|
|
GROUPADD_PARAM in the useradd class.
|
|
|
|
#### OEM Redfish Roles
|
|
|
|
POST on the RoleCollection in the AccountService to create an OEM role, with
|
|
assigned Privileges in the AssignedPrivileges and OemPrivileges properties in
|
|
the Role resource.
|
|
|
|
DELETE on the specific Role in the RoleCollection to delete an OEM role.
|
|
Predefined roles are not allowed to be deleted.
|
|
|
|
We propose to extend the existing phosphor-user-manager:
|
|
|
|
1. Phosphor-user-manager provides DBus APIs to create Redfish role
|
|
2. Phosphor-user-manager keeps a maximum number of Redfish roles; we propose 32
|
|
as the first iteration considering fast bit manipulation
|
|
3. Phosphor-user-manager performs validation:
|
|
- Names of OEM Redfish roles are unique and valid; e.g., start with
|
|
"openbmc-orfr-"
|
|
- Reject deletion of a RedfishRole that's currently in use (associated with
|
|
users)
|
|
|
|
#### Users
|
|
|
|
POST on the ManagerAccountCollection to create a user, with a RoleId to the
|
|
assigned Redfish role.
|
|
|
|
DELETE on the specific user in the ManagerAccountCollection to delete a user.
|
|
|
|
Note: modification on ManagerAccountCollection need authorization as well. For
|
|
example, a user with only "ConfigureSelf" permission is not allowed to delete
|
|
other users.
|
|
|
|
#### Typical Workflow
|
|
|
|
In summary, a typical workflow to create a new local user with an new OEM
|
|
Redfish role which is assigned a new set of OEM Redfish Privileges is mapped out
|
|
below.
|
|
|
|
```
|
|
Root User BMCWeb Phosphor-User-Manager Linux
|
|
| PATCH PrivilegeRegistry | | |
|
|
|-------------------------->| DBus: createGroup | |
|
|
| Add OemAddPowerService |----------------------------->| groupadd |
|
|
Create | | |----------------------->|
|
|
OemPrivilege| | Okay |<-----------------------|
|
|
| Okay |<-----------------------------| Okay |
|
|
|<--------------------------| | |
|
|
| | | |
|
|
| | | |
|
|
| POST RoleCollection | | |
|
|
|-------------------------->| DBus: createUser | |
|
|
| |----------------------------->| useradd + groupadd |
|
|
Create | | |----------------------->|
|
|
OemRole | | Okay |<-----------------------|
|
|
| Okay |<-----------------------------| Okay |
|
|
|<--------------------------| | |
|
|
| | | |
|
|
| | | |
|
|
|POST | | |
|
|
| ManagerAccountCollection | | |
|
|
|-------------------------->| DBus: createUser | |
|
|
| |----------------------------->| useradd |
|
|
Create | | |----------------------->|
|
|
User | | |<-----------------------|
|
|
| |<-----------------------------| Okay |
|
|
|<--------------------------| Okay | |
|
|
| Okay | | |
|
|
Time | | | |
|
|
v v v v
|
|
```
|
|
|
|
### Non-Redfish Routes or OEM Resources
|
|
|
|
We still keep the current `privileges` C++ API to add explicit Redfish
|
|
privileges for non-redfish routes via `BMCWEB_ROUTE`.
|
|
|
|
### Redfish Routes
|
|
|
|
We propose to create a new macro `REDFISH_ROUTE` so existing `REDFISH_ROUTE`
|
|
stay unchanged for non-redfish routes.
|
|
|
|
For each `REDFISH_ROUTE`, instead of taking a privileges array (or reference to
|
|
a privileges array), this design proposes to create the following extra C++
|
|
APIs:
|
|
|
|
1. `entity`: it takes a string representing the Resource name (the same
|
|
definition as it in the PrivilegeRegistry); for example,
|
|
"/redfish/v1/Managers/${ManagerId}/EthernetInterfaces/" will provide a string
|
|
"EthernetInterfaceCollection" as the entity
|
|
2. `subordinateTo`: it takes an array of string representing what resource this
|
|
router is subordinate to (the same definition as it in the
|
|
PrivilegeRegistry); for example, a route with URL
|
|
"/redfish/v1/Managers/${ManagerId}/EthernetInterfaces/" will provide an array
|
|
of {"Manager", "EthernetInterfaceCollection"} as the value of
|
|
`subordinateTo`.
|
|
|
|
Any Redfish route must provide these attributes. Non Redfish route shall not
|
|
provide them, instead, they specify `privileges` directly. The values of these
|
|
attributes can be generated from the schema at compile time. To guarantee this
|
|
in C++ code, we can make them required parameters in constructors.
|
|
|
|
See below for how we propose to get required Redfish privileges for a given
|
|
method on a given resource by using the proposed `entity` & `subordinateTo`, the
|
|
existing `methods`, and the URL from the request.
|
|
|
|
See the alternatives section for how we can get rid of setting these attributes
|
|
at manually.
|
|
|
|
### Operation-to-Privilege Mapping Data Structure in Memory
|
|
|
|
BMCWeb keeps a JSON like data structure in memory to represent the whole
|
|
Operation-to-Privilege Mapping. For a given route with known entity name, HTTP
|
|
method, and resource URL, the required set of privileges can be retrieved
|
|
efficiently.
|
|
|
|
The operation to check if a user is authorized to perform a Redfish operation is
|
|
still the existing bit-wise `isSupersetOf` between the required privileges of a
|
|
given operation on a given resource and the assigned privileges of a role.
|
|
|
|
### Generate Operation-to-Privilege Mapping Data Structure at Compile Time
|
|
|
|
BMCWeb has requirements that it doesn't prefer to load a large file at service
|
|
start time since it slows down the service, and whatever services rely on it.
|
|
|
|
Thus, we propose to generate the data structure at compile time, it takes a
|
|
PrivilegeRegistry JSON, and generate necessary headers and sources files to hold
|
|
a variable that represent the whole Operation-to-Privilege Mapping. The input
|
|
JSON can change across systems.
|
|
|
|
This can be implemented as a customized Meson generator.
|
|
|
|
We will delete the current static privileges header, but the generated header
|
|
will increase the binary size. We shall limit the increase to <= 100KB. The size
|
|
of `Redfish_1.3.0_PrivilegeRegistry.json` is about 275 KB; the minified version
|
|
of it (no whitespace) is about 62 KB. When parsing this JSON and converting it
|
|
to C++ codes, we shall not increase the binary size a lot otherwise we can just
|
|
store the whole registry as a Nlohmann JSON object.
|
|
|
|
### Operation-to-Privilege Mapping Overrides
|
|
|
|
In routing codes, we can parse the Operation-to-Privilege Mapping Data Structure
|
|
and look for SubordinateOverrides and ResourceURIOverrides, combine them with
|
|
the attributes from route and request, and perform authorization.
|
|
|
|
Most part of the Authorization codes run before resource handlers. However,
|
|
PropertyOverrides for read operation can only be executed when response is ready
|
|
since we need to inspect the response attributes. PropertyOverrides for write
|
|
operator shall still run before the handler codes: the authorization code
|
|
inspect the request payload and corresponding properties, and look them up in
|
|
the Operation-to-Privilege Mapping in-memory Data Structure.
|
|
|
|
A example execution flow for a read operation is mapped out below.
|
|
|
|
```
|
|
+---------------+
|
|
| BMCWeb | Get
|
|
| routing | /redfish/v1/Managers/${ManagerId}/EthernetInterfaces/
|
|
+-------|-------+
|
|
| Known information:
|
|
| Request.URL
|
|
| Request.method
|
|
| Route.entity
|
|
| Route.subordinateTo
|
|
|
|
|
+-----------------------+ +--------------------------------------------------------------+
|
|
| Any | |Operation-to-Privilege Mapping in-memory Data Structure |
|
|
| ResourceURIOverrides? <------>| |
|
|
| | |{ |
|
|
+-----------|-----------+ | "Entity": "EthernetInterface", |
|
|
|Updated | "OperationMap": { |
|
|
|RequiredPrivileges | "Get": [{ |
|
|
+-----------------------+ | "Privilege": ["ConfigureComponents"] |
|
|
| Any | | }] |
|
|
| SubordinateOverrides? |<----->| }, |
|
|
| | | "SubordinateOverrides": [{ |
|
|
+-----------------------+ | "Targets": ["Manager", "EthernetInterfaceCollection"], |
|
|
|Updated | "OperationMap": { |
|
|
|RequiredPrivileges | "Get": [{ |
|
|
v | "Privilege": ["ConfigureManager"] |
|
|
+-----------------------+ | }] |
|
|
| Authorization | | } |
|
|
+-----------|-----------+ | }] |
|
|
|Okay |} |
|
|
|Got Response | |
|
|
| +--------------------------------------------------------------+
|
|
+-----------------------+ ^
|
|
| Any | |
|
|
| PropertyOverrides? |<----------------------+
|
|
+-----------|-----------+
|
|
|
|
|
|
|
|
v
|
|
Final Response
|
|
```
|
|
|
|
The implementation may start with implementing just the overrides specified in
|
|
DMTF's base PrivilegeRegistry at compile time and reject any PATCH on overrides
|
|
properties.
|
|
|
|
### PrivilegeRegistry Resource
|
|
|
|
BMCWeb will implement PrivilegeRegistry in a new route. The route will reflect
|
|
the current PrivilegeRegistry in used including dynamic changes.
|
|
|
|
With the proposed Dynamic Operation-to-Privilege Mapping Data Structure, and
|
|
DBus APIs that phosphor-user-manager provides, the implementation is trivial:
|
|
convert the JSON data structure into a JSON response.
|
|
|
|
### PATCH on PrivilegeRegistry
|
|
|
|
Though the Redfish spec declares PrivilegeRegistry to be read-only, this design
|
|
still proposes implementing PATCH on PrivilegeRegistry: users can PATCH any
|
|
attributes directly, e.g., patch the POST privilege array of OperationMap of
|
|
Entity EthernetInterface so that users with "OemEthernetManager" can also send
|
|
GET to EthernetInterface.
|
|
|
|
```
|
|
{
|
|
Entity": "EthernetInterface",
|
|
"OperationMap": {
|
|
"GET": [
|
|
{
|
|
"Privilege": [
|
|
"Login"
|
|
]
|
|
},
|
|
{
|
|
"Privilege": [
|
|
"OemEthernetManager"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
The implementation might reject modification on certain attributes when
|
|
corresponding implementation is not ready. E.g., it rejects modifying
|
|
SubordinateOverrides when the service doesn't have SubordinateOverrides
|
|
implemented.
|
|
|
|
Changes against the base PrivilegeRegistry will be rejected, e.g., deleting
|
|
ConfigureSelf from a OperationMap. This design is for OEMPrivileges and
|
|
OEMRoles.
|
|
|
|
### Persistent Data
|
|
|
|
OEM Redfish roles, Redfish privileges, and users are persisted by Linux. With a
|
|
maximum number of roles and privileges being set, the total persistent data will
|
|
be very small (around several KB).
|
|
|
|
To minimize size of persistent data, we propose that BMCWeb only stores the
|
|
serial of PATCH requests on the PrivilegeRegistry. This data can be stored in
|
|
the existing `bmcweb_persistent_data.json`. When restart from crash or reset,
|
|
BMCWeb will be able to execute the serial of PATCH requests to recover the
|
|
PrivilegeRegistry. A change on existing `bmcweb_persistent_data.json` is that
|
|
now BMCWeb will write changes to disk (commit) before it returns okay to
|
|
clients' PATCH on PrivilegeRegistry. Given that operations on PrivilegeRegistry
|
|
is much less often than other management and monitoring resources, writing a
|
|
small piece of data to disk is acceptable.
|
|
|
|
We can set a maximum number of PATCH requests that BMCWeb allows to limit the
|
|
disk usage. Most upstream systems also have several MB of read-write partition
|
|
configured. For example, `romulus` as of the design was written, 4194304 bytes
|
|
for rwfs. We propose to start with allowing 1000 requests.
|
|
|
|
Systems without enabling dynamic authorization feature won't have any new
|
|
persistent data added.
|
|
|
|
## Alternatives Considered
|
|
|
|
### Infer Entity and SubordinateTo from URL
|
|
|
|
We can infer the entity from the URL by building a Trie like data structure.
|
|
However, it's not a big deal to hardcode an entity for a route, since entity and
|
|
SubordinateTo never change at runtime.
|
|
|
|
## Impacts
|
|
|
|
1. New DBus interfaces on phosphor-user-manager
|
|
2. New persistent data managed by BMCWeb will be added on BMCs
|
|
3. Binary size will increase on BMCWeb
|
|
4. Existing systems with the static authorization shall work as if this feature
|
|
is not introduced
|
|
|
|
## Organizational
|
|
|
|
No new repository is required. Phosphor-user-manager and BMCWeb will be modified
|
|
to implement the design.
|
|
|
|
## Testing
|
|
|
|
Existing tests shall still pass as if this feature is not introduced. New Robot
|
|
Framework test can be added to test runtime modification of PrivilegeRegistry.
|
|
|
|
Test cases should include:
|
|
|
|
1. verify base Redfish roles, privileges, and base operation-to-privilege
|
|
respect the Redfish spec when no runtime modification is made
|
|
2. verify Redfish OemPrivilege can be added via PATCH to PrivilegeRegistry and
|
|
reflected in the PrivilegeRegistry resource
|
|
3. verify Redfish OemRole can be added via POST to ManagerAccountCollection with
|
|
assigned OemPrivilege and reflected in the ManagerAccountCollection
|
|
4. verify operation-to-privilege can be modified via PATCH on PrivilegeRegistry;
|
|
mapping of an action on a resource can be added with the above OemPrivilege,
|
|
and finally the user of that OemRole now can access the resource
|
|
5. verify the 3 dynamic overriding is working as expected; e.g., a new override
|
|
can be added to PrivilegeRegistry and should be reflected in new requests
|