1# Dynamic Redfish Authorization
2
3Author: Nan Zhou (nanzhoumails@gmail.com)
4
5Created: 08/08/2022
6
7## Problem Description
8
9The Redfish authorization subsystem controls which authenticated users have
10access to resources and the type of access that users have.
11
12DMTF has already defined the authorization model and schemas. This design is to
13enhance the current implementation in BMCWeb Redfish interface so that OpenBMC
14systems exposes interfaces to change authorization behavior at runtime without
15Redfish service restart.
16
17## Background and References
18
19### Redfish Authorization Model
20
21The Redfish authorization model consists of the privilege model and the
22operation-to-privilege mapping.
23
24In the privilege model, there are fixed set of standard Redfish roles and each
25of them is assigned a fixed array of standard privileges (e.g., `Login`,
26`ConfigureManager`, etc). A service may define custom OEM roles (read-only). A
27service may even allow custom client-defined roles to be created, modified, and
28deleted via REST operations on `RoleCollection`.
29
30The operation-to-privilege mapping is defined for every resource type and
31applies to every resource the service implements for the applicable resource
32type. It is used to determine whether the identity privileges of an
33authenticated Redfish role are sufficient to complete the operation in the
34request. The Redfish Forum provides a Privilege Registry definition in its
35official registry collection as a base operation-to-privilege mapping. It also
36allows mapping overrides (Property override, Subordinate override, and Resource
37URI override) to customize mapping.
38
39For example, a peer who is an `Operator` that has both `Login`,
40`ConfigureComponents`, and `ConfigureSelf` privileges, is authorized to send a
41`GET` request to the `ChassisCollection`, since the `GET` operation on this
42resource only requires the `Login` privilege. On the other hand, the same peer
43gets denied access if they send a POST request to `CertificateService`, as the
44POST operation on certificates requires `ConfigureManager` privilege that the
45peer is missing.
46
47**Note**, in the Redfish spec, OEM roles can be added via POST to the
48`RoleCollection` in the `AccountService`; `PrivilegesUsed`, `OEMPrivilegesUsed`,
49and properties of `Mappings` are all read-only.
50
51References:
52
531. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#privilege-model
542. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#redfish-service-operation-to-privilege-mapping
553. https://redfish.dmtf.org/schemas/DSP0266_1.15.1.html#roles
564. https://redfish.dmtf.org/registries/v1/Redfish_1.3.0_PrivilegeRegistry.json
57
58### Phosphor-user-manager
59
60Phosphor-user-manager is an OpenBMC daemon that does user management.
61
62It exposes DBus APIs to dynamically add users, manage users' attributes (e.g.,
63group, privileges, status, and account policies). It has a hardcoded list of
64user groups (SSH, IPMI, Redfish, Web) and a hardcoded list of privileges
65("priv-admin", "priv-operator", "priv-user", "priv-noaccess"). These privileges
66are implemented as Linux secondary groups.
67
68It also integrates LDAP (supports either ActiveDirectory or OpenLDAP) for remote
69user management, where BMC acts as a LDAP client and uses nslcd to automatically
70convert Linux system calls to LDAP queries.
71
72References:
73
741. https://github.com/openbmc/docs/blob/master/architecture/user-management.md
752. https://github.com/openbmc/phosphor-user-manager
763. https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/yaml/xyz/openbmc_project/User
774. https://linux.die.net/man/8/nslcd
785. https://linux.die.net/man/8/nscd
79
80### BMCWeb
81
82BMCWeb is an OpenBMC Daemon which implements the Redfish service (it implements
83other management interfaces as well besides Redfish).
84
85BMCWeb supports various "authentication" options, but under the hood, to verify
86the user is who they claim they are, there are two main authentication methods:
87
881. PAM based: use Linux-PAM to do username/password style of authentication
892. TLS based: use the Public Key infrastructure to verify signature of peer's
90   certificates; then use identities (in X509 certificates, these are Common
91   Name or Subject Alternative Name) as user names.
92
93After getting the peer's user name, BMCWeb sends DBus queries to
94phosphor-user-manager to query the user's privileges and uses a hardcoded map to
95convert the privileges to Redfish roles. The hardcoded map is listed below:
96
97| Phosphor-user-manager privileges (implemented as groups) | BMCWeb Redfish Roles |
98| -------------------------------------------------------- | -------------------- |
99| priv-admin                                               | Administrator        |
100| priv-operator                                            | Operator             |
101| priv-user                                                | ReadOnly             |
102| priv-noaccess                                            | NoAccess             |
103
104To map Redfish role to their assigned Redfish privileges, BMCWeb implements the
105following hardcoded map:
106
107| BMCWeb Redfish Roles | Assigned Redfish Privileges                                                            |
108| -------------------- | -------------------------------------------------------------------------------------- |
109| Administrator        | "Login", "ConfigureManager", "ConfigureUsers", "ConfigureSelf", "ConfigureComponents"} |
110| Operator             | "Login", "ConfigureSelf", "ConfigureComponents"                                        |
111| ReadOnly             | "Login", "ConfigureSelf"                                                               |
112| NoAccess             | NA                                                                                     |
113
114At compile time, BMCWeb assigns each operation of each entity a set of required
115Redfish Privileges. An authorization action is performed when a BMCWeb route
116callback is performed: check if the assigned Redfish Privileges is a superset of
117the required Redfish Privileges.
118
119In the following section, we refer a BMCWeb route as the handler of an operation
120of an given resource URI, which is what the BMCWEB_ROUTE macro has defined.
121
122References:
123
1241. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/include/authentication.hpp
1252. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/http/http_connection.hpp
1263. https://github.com/openbmc/bmcweb/blob/d9f6c621036162e9071ce3c3a333b4544c6db870/redfish-core/lib/roles.hpp
127
128### Gaps
129
130As mentioned above, majority of the current Redfish authorization settings are
131configured at compile time including:
132
1331. the set of Phosphor-user-manager privileges
1342. the mapping from Phosphor-user-manager privileges to Redfish roles
1353. the set of Redfish roles
1364. the mapping from Redfish roles to Redfish Privileges
1375. the operation-to-privilege mapping
138
139However, modern systems have use cases where Redfish roles, Redfish privileges,
140and operation-to-privilege mapping need to change when the system keeps running.
141E.g., a new micro-service is introduced and needs to talk to existing BMCs in
142the fleet, we need to propagate a configuration so that this new peer gets a
143proper Redfish role and is authorized to access certain resources without
144rolling out a new BMC firmware.
145
146Another gap is that current Redfish roles and operation-to-privilege mapping
147lead to a very coarse-grained access control, and doesn't implement the
148principle of least privilege. Though these configurations are defined by DMTF,
149it is explicitly called out in the standard that implementation implement their
150own OEM roles and privileges if "the standard privilege is overly broad".
151
152For systems which have requirement where a given user only has access to the
153resources it needs. For example, a micro-service responsible for remote power
154control can only send GET to Chassis and ComputerSystems, and POST to
155corresponding ResetActions. With the existing implementation, such micro-service
156has at least ConfigureComponents Redfish privilege, which leads to being able to
157patch an EthernetInterface resource.
158
159## Requirements
160
161BMC implements a dynamic Redfish authorization system:
162
1631. Clients shall be able to add new OEM Redfish privileges without recompile
1642. Clients shall be able to add new OEM Redfish roles and assign it with any
165   existing Redfish privileges without recompile
1663. Clients shall be able to modify existing operation-to-privilege mappings
167   without recompile
1684. Above changes on systems shall be atomic; that is, once changed, all new
169   queries will use the latest configurations
1705. BMC shall perform sanity check on above modification; that is
171   - It rejects ill formatted modification
172   - It rejects modification of non-OEM privileges
173   - It rejects deletion of OEM Redfish roles if any user (either local or
174     remote) maps such roles
175   - It rejects deletion of OEM Redfish privileges if any OEM Redfish role is
176     assigned such privileges
1776. BMC shall persist all the above modifications and recover from crash
1787. Existing systems with the static authorization shall work as if this feature
179   is not introduced, including non-Redfish routes (e.g., KVM websocket)
1808. Default OEM roles and Redfish privileges must be selectable on a per system
181   basis at compile time; default Redfish PrivilegeRegistry must be settable on
182   a per system basis at compile time
1839. The total storage used by this feature shall be limited; this is
184   - The total rwfs disk usage increase is less than 100 KB on systems with the
185     dynamic authorization feature enabled
186   - The runtime memory usage increase is less than 1 MB on systems with the
187     dynamic authorization feature enabled
188   - The binary size increase of modified daemons is less than 100 KB on all
189     systems
19010. BMC implements a complete privilege registry; that is
191    - It shall implement all overrides in the Redfish base Privilege registries
192      at compile time; it shall support configuring overrides at runtime but
193      implementation may begin with static configuring and reject runtime
194      modification
195    - BMC exposes PrivilegeRegistry which represents the current configuration
196      and reflects runtime changes
197    - Changes to resource entities shall be propagated to the current privilege
198      registries automatically
19911. New Redfish resource can be implemented without modifying custom
200    PrivilegeRegistry
20112. All the above shall be testable; CI must be capable of finding issues
202
203## Proposed Design
204
205### Mapping: Users, Redfish Roles, and Redfish Privileges
206
207As mentioned in the background section, existing Redfish roles are stored as
208Linux secondary groups with prefix "priv" (includes "priv-admin",
209"priv-operator", and "priv-user"). And a Linux user is in one of these groups
210representing that a user is a specific Redfish role. BMCWeb then uses a
211hardcoded table to map Redfish role to Redfish privileges.
212
213However, modeling roles only as static Linux secondary groups doesn't worked
214well with OEM Redfish Roles where a Redfish role maps to a dynamic set of OEM
215privileges: secondary group can't represent associations.
216
217To solve this, we propose the following solution:
218
219**Store Redfish Roles As Linux Users and Secondary Groups** We propose to store
220Redfish Roles as both Linux users and secondary groups. Storing as secondary
221groups is to associate users with Redfish roles. On the other hand, storing as
222users is to associate Redfish roles with Redfish privileges. See below section
223for these mappings.
224
225Users for Redfish roles won't be any predefined groups (web, redfish, ipmi). We
226can add extra attributes to distinguish them with real local and LDAP users.
227Users for Redfish roles won't have SSH permission as well.
228
229Redfish roles will have a fixed prefix "openbmc-rfr-". "rfr" refers to Redfish
230role. OEM redfish roles will get prefix "openbmc-orfr-". "orfr" refers to OEM
231Redfish role. For example, the base Redfish role "Administrator" will result in
232a Linux secondary group "openbmc-rfr-administrator" and a local user
233"openbmc-rfr-administrator". We can also make the vendor name ("openbmc")
234configurable at compile time. Using acronym is to save characters since Linux
235username has 31 characters limit.
236
237**Store Redfish Privileges as Secondary Groups** Redfish privileges will be
238stored as Linux secondary groups with a fixed prefix "openbmc-rfp". rfr" refers
239to Redfish privilege. OEM privileges will have fixed prefix "openbmc-orfp".
240"orfr" refers to OEM Redfish privilege.
241
242**Username to Redfish Role Mapping** Mapping a username to Redfish role becomes
243searching the group starting with "openbmc-rfr" that the user is in.
244
245**Redfish Role to Redfish Privileges Mapping** Mapping a Redfish Role to Redfish
246privileges becomes searching all the groups starting with "openbmc-rfp" or
247"openbmc-orfp" of the user.
248
249A user maps be in multiple linux secondary groups meaning they are assigned
250certain privileges; for example, user "PowerService" is in "openbmc-orfr-power"
251group meaning its Redfish role is "openbmc-orfr-power"; local user
252"openbmc-orfr-power" is in secondary groups "openbmc-rfp-configureself" and
253"openbmc-orfp-power" groups meaning "openbmc-orfr-power" is assigned to Redfish
254privileges "ConfigureSelf" and "OemPrivPower".
255
256The following diagram shows how assigned privileges of a power control service
257with identity (username in PAM, or CN/SAN in TLS) "power-service" is resolved.
258
259```
260 +-----------------+
261 |  power service  |
262 |                 |
263 +--------|--------+
264          |
265          |
266 +-----------------+
267 |  authentication |
268 |   (PAM or TLS)  |
269 |      BMCWeb     |
270 +--------|--------+
271          |
272          |username:power-service
273          |
274 +-----------------+                        +-----------------+            +----------------------------+
275 |      BMCWeb     |DBus: privileges        |  phosphor-      |            |     Linux                  |
276 |                 ------------------------>|   user-manager  |            |user: power-service         |
277 |                 |<-----------------------|                 |            |group:                      |
278 |                 | privileges:            |                 <----------->|  openbmc-orfr-power        |
279 |                 |  Login, ConfigureSelf  |                 |            |                            |
280 |                 |  OemPrivPower          |                 |            |user: openbmc-orfr-power    |
281 +-----------------+                        +-----------------+            |group:                      |
282                                                                           |  openbmc-rfp-configureself |
283                                                                           |  openbmc-orfp-power        |
284                                                                           |  openbmc-rfp-login         |
285                                                                           +----------------------------+
286```
287
288The above diagram works for LDAP users as well. A remote role or group can map
289to base Redfish roles or OEM Redfish roles via RemoteRoleMapping: an LDAP group
290maps to a single Redfish role stored as local users.
291
292We propose to extend the existing phosphor-user-manager:
293
2941. It returns AllPrivileges dynamically by looking up the current groups
2952. Phosphor-user-manager provides DBus APIs to query privileges of a given user
296
297The legacy groups (e.g., `priv-user`) still works as before. For example, a user
298in both `priv-user` and `openbmc-orfp-power` will have the following Redfish
299privileges: `Login`, `ConfigureSelf`, `OemPrivPower`.
300
301### Creation/Deletion: Users, Redfish Roles, and Redfish Privileges
302
303Base privileges and roles won't be allowed to change at runtime.
304
305#### OEM Redfish Privileges
306
307PATCH OEMPrivilegesUsed in PrivilegeRegistry creating/deleting OEM privileges to
308create or delete OEM Privileges at runtime.
309
310We propose to extend the existing phosphor-user-manager:
311
3121. Phosphor-user-manager provides DBus APIs to create/delete OEM Redfish
313   privileges; under the hood, it stores privileges as Linux groups, as today
314   how base Redfish roles are stored
3152. Phosphor-user-manager keeps a maximum number of Redfish privileges; we
316   propose 32 as the first iteration considering fast bit manipulation
3173. Phosphor-user-manager performs validation:
318   - Names of OEM Redfish privileges are unique and valid; e.g., start with
319     "openbmc-orfp-"
320   - Reject deletion of a privilege that's currently in use (assigned to any
321     Redfish roles that have a user associated with)
322
323Systems can also optionally add OEM Privileges at compile time via Yocto's
324GROUPADD_PARAM in the useradd class.
325
326#### OEM Redfish Roles
327
328POST on the RoleCollection in the AccountService to create an OEM role, with
329assigned Privileges in the AssignedPrivileges and OemPrivileges properties in
330the Role resource.
331
332DELETE on the specific Role in the RoleCollection to delete an OEM role.
333Predefined roles are not allowed to be deleted.
334
335We propose to extend the existing phosphor-user-manager:
336
3371. Phosphor-user-manager provides DBus APIs to create Redfish role
3382. Phosphor-user-manager keeps a maximum number of Redfish roles; we propose 32
339   as the first iteration considering fast bit manipulation
3403. Phosphor-user-manager performs validation:
341   - Names of OEM Redfish roles are unique and valid; e.g., start with
342     "openbmc-orfr-"
343   - Reject deletion of a RedfishRole that's currently in use (associated with
344     users)
345
346#### Users
347
348POST on the ManagerAccountCollection to create a user, with a RoleId to the
349assigned Redfish role.
350
351DELETE on the specific user in the ManagerAccountCollection to delete a user.
352
353Note: modification on ManagerAccountCollection need authorization as well. For
354example, a user with only "ConfigureSelf" permission is not allowed to delete
355other users.
356
357#### Typical Workflow
358
359In summary, a typical workflow to create a new local user with an new OEM
360Redfish role which is assigned a new set of OEM Redfish Privileges is mapped out
361below.
362
363```
364         Root User                    BMCWeb                  Phosphor-User-Manager             Linux
365              |   PATCH PrivilegeRegistry |                              |                        |
366              |-------------------------->|   DBus: createGroup          |                        |
367              |   Add OemAddPowerService  |----------------------------->|     groupadd           |
368  Create      |                           |                              |----------------------->|
369  OemPrivilege|                           |            Okay              |<-----------------------|
370              |           Okay            |<-----------------------------|        Okay            |
371              |<--------------------------|                              |                        |
372              |                           |                              |                        |
373              |                           |                              |                        |
374              | POST RoleCollection       |                              |                        |
375              |-------------------------->|  DBus: createUser            |                        |
376              |                           |----------------------------->|  useradd + groupadd    |
377  Create      |                           |                              |----------------------->|
378  OemRole     |                           |            Okay              |<-----------------------|
379              |          Okay             |<-----------------------------|         Okay           |
380              |<--------------------------|                              |                        |
381              |                           |                              |                        |
382              |                           |                              |                        |
383              |POST                       |                              |                        |
384              | ManagerAccountCollection  |                              |                        |
385              |-------------------------->| DBus: createUser             |                        |
386              |                           |----------------------------->|       useradd          |
387  Create      |                           |                              |----------------------->|
388  User        |                           |                              |<-----------------------|
389              |                           |<-----------------------------|        Okay            |
390              |<--------------------------|            Okay              |                        |
391              |           Okay            |                              |                        |
392  Time        |                           |                              |                        |
393              v                           v                              v                        v
394```
395
396### Non-Redfish Routes or OEM Resources
397
398We still keep the current `privileges` C++ API to add explicit Redfish
399privileges for non-redfish routes via `BMCWEB_ROUTE`.
400
401### Redfish Routes
402
403We propose to create a new macro `REDFISH_ROUTE` so existing `REDFISH_ROUTE`
404stay unchanged for non-redfish routes.
405
406For each `REDFISH_ROUTE`, instead of taking a privileges array (or reference to
407a privileges array), this design proposes to create the following extra C++
408APIs:
409
4101. `entity`: it takes a string representing the Resource name (the same
411   definition as it in the PrivilegeRegistry); for example,
412   "/redfish/v1/Managers/${ManagerId}/EthernetInterfaces/" will provide a string
413   "EthernetInterfaceCollection" as the entity
4142. `subordinateTo`: it takes an array of string representing what resource this
415   router is subordinate to (the same definition as it in the
416   PrivilegeRegistry); for example, a route with URL
417   "/redfish/v1/Managers/${ManagerId}/EthernetInterfaces/" will provide an array
418   of {"Manager", "EthernetInterfaceCollection"} as the value of
419   `subordinateTo`.
420
421Any Redfish route must provide these attributes. Non Redfish route shall not
422provide them, instead, they specify `privileges` directly. The values of these
423attributes can be generated from the schema at compile time. To guarantee this
424in C++ code, we can make them required parameters in constructors.
425
426See below for how we propose to get required Redfish privileges for a given
427method on a given resource by using the proposed `entity` & `subordinateTo`, the
428existing `methods`, and the URL from the request.
429
430See the alternatives section for how we can get rid of setting these attributes
431at manually.
432
433### Operation-to-Privilege Mapping Data Structure in Memory
434
435BMCWeb keeps a JSON like data structure in memory to represent the whole
436Operation-to-Privilege Mapping. For a given route with known entity name, HTTP
437method, and resource URL, the required set of privileges can be retrieved
438efficiently.
439
440The operation to check if a user is authorized to perform a Redfish operation is
441still the existing bit-wise `isSupersetOf` between the required privileges of a
442given operation on a given resource and the assigned privileges of a role.
443
444### Generate Operation-to-Privilege Mapping Data Structure at Compile Time
445
446BMCWeb has requirements that it doesn't prefer to load a large file at service
447start time since it slows down the service, and whatever services rely on it.
448
449Thus, we propose to generate the data structure at compile time, it takes a
450PrivilegeRegistry JSON, and generate necessary headers and sources files to hold
451a variable that represent the whole Operation-to-Privilege Mapping. The input
452JSON can change across systems.
453
454This can be implemented as a customized Meson generator.
455
456We will delete the current static privileges header, but the generated header
457will increase the binary size. We shall limit the increase to <= 100KB. The size
458of `Redfish_1.3.0_PrivilegeRegistry.json` is about 275 KB; the minified version
459of it (no whitespace) is about 62 KB. When parsing this JSON and converting it
460to C++ codes, we shall not increase the binary size a lot otherwise we can just
461store the whole registry as a Nlohmann JSON object.
462
463### Operation-to-Privilege Mapping Overrides
464
465In routing codes, we can parse the Operation-to-Privilege Mapping Data Structure
466and look for SubordinateOverrides and ResourceURIOverrides, combine them with
467the attributes from route and request, and perform authorization.
468
469Most part of the Authorization codes run before resource handlers. However,
470PropertyOverrides for read operation can only be executed when response is ready
471since we need to inspect the response attributes. PropertyOverrides for write
472operator shall still run before the handler codes: the authorization code
473inspect the request payload and corresponding properties, and look them up in
474the Operation-to-Privilege Mapping in-memory Data Structure.
475
476A example execution flow for a read operation is mapped out below.
477
478```
479    +---------------+
480    |   BMCWeb      | Get
481    |    routing    | /redfish/v1/Managers/${ManagerId}/EthernetInterfaces/
482    +-------|-------+
483            | Known information:
484            |  Request.URL
485            |  Request.method
486            |  Route.entity
487            |  Route.subordinateTo
488            |
489+-----------------------+       +--------------------------------------------------------------+
490| Any                   |       |Operation-to-Privilege Mapping in-memory Data Structure       |
491| ResourceURIOverrides? <------>|                                                              |
492|                       |       |{                                                             |
493+-----------|-----------+       |   "Entity": "EthernetInterface",                             |
494            |Updated            |   "OperationMap": {                                          |
495            |RequiredPrivileges |      "Get": [{                                               |
496+-----------------------+       |         "Privilege": ["ConfigureComponents"]                 |
497| Any                   |       |      }]                                                      |
498| SubordinateOverrides? |<----->|   },                                                         |
499|                       |       |   "SubordinateOverrides": [{                                 |
500+-----------------------+       |      "Targets": ["Manager", "EthernetInterfaceCollection"],  |
501            |Updated            |      "OperationMap": {                                       |
502            |RequiredPrivileges |         "Get": [{                                            |
503            v                   |            "Privilege": ["ConfigureManager"]                 |
504+-----------------------+       |         }]                                                   |
505| Authorization         |       |      }                                                       |
506+-----------|-----------+       |   }]                                                         |
507            |Okay               |}                                                             |
508            |Got Response       |                                                              |
509            |                   +--------------------------------------------------------------+
510+-----------------------+                       ^
511| Any                   |                       |
512| PropertyOverrides?    |<----------------------+
513+-----------|-----------+
514            |
515            |
516            v
517        Final Response
518```
519
520The implementation may start with implementing just the overrides specified in
521DMTF's base PrivilegeRegistry at compile time and reject any PATCH on overrides
522properties.
523
524### PrivilegeRegistry Resource
525
526BMCWeb will implement PrivilegeRegistry in a new route. The route will reflect
527the current PrivilegeRegistry in used including dynamic changes.
528
529With the proposed Dynamic Operation-to-Privilege Mapping Data Structure, and
530DBus APIs that phosphor-user-manager provides, the implementation is trivial:
531convert the JSON data structure into a JSON response.
532
533### PATCH on PrivilegeRegistry
534
535Though the Redfish spec declares PrivilegeRegistry to be read-only, this design
536still proposes implementing PATCH on PrivilegeRegistry: users can PATCH any
537attributes directly, e.g., patch the POST privilege array of OperationMap of
538Entity EthernetInterface so that users with "OemEthernetManager" can also send
539GET to EthernetInterface.
540
541```
542{
543    Entity": "EthernetInterface",
544    "OperationMap": {
545        "GET": [
546            {
547                "Privilege": [
548                    "Login"
549                ]
550            },
551            {
552                "Privilege": [
553                    "OemEthernetManager"
554                ]
555            }
556        ]
557    }
558}
559```
560
561The implementation might reject modification on certain attributes when
562corresponding implementation is not ready. E.g., it rejects modifying
563SubordinateOverrides when the service doesn't have SubordinateOverrides
564implemented.
565
566Changes against the base PrivilegeRegistry will be rejected, e.g., deleting
567ConfigureSelf from a OperationMap. This design is for OEMPrivileges and
568OEMRoles.
569
570### Persistent Data
571
572OEM Redfish roles, Redfish privileges, and users are persisted by Linux. With a
573maximum number of roles and privileges being set, the total persistent data will
574be very small (around several KB).
575
576To minimize size of persistent data, we propose that BMCWeb only stores the
577serial of PATCH requests on the PrivilegeRegistry. This data can be stored in
578the existing `bmcweb_persistent_data.json`. When restart from crash or reset,
579BMCWeb will be able to execute the serial of PATCH requests to recover the
580PrivilegeRegistry. A change on existing `bmcweb_persistent_data.json` is that
581now BMCWeb will write changes to disk (commit) before it returns okay to
582clients' PATCH on PrivilegeRegistry. Given that operations on PrivilegeRegistry
583is much less often than other management and monitoring resources, writing a
584small piece of data to disk is acceptable.
585
586We can set a maximum number of PATCH requests that BMCWeb allows to limit the
587disk usage. Most upstream systems also have several MB of read-write partition
588configured. For example, `romulus` as of the design was written, 4194304 bytes
589for rwfs. We propose to start with allowing 1000 requests.
590
591Systems without enabling dynamic authorization feature won't have any new
592persistent data added.
593
594## Alternatives Considered
595
596### Infer Entity and SubordinateTo from URL
597
598We can infer the entity from the URL by building a Trie like data structure.
599However, it's not a big deal to hardcode an entity for a route, since entity and
600SubordinateTo never change at runtime.
601
602## Impacts
603
6041. New DBus interfaces on phosphor-user-manager
6052. New persistent data managed by BMCWeb will be added on BMCs
6063. Binary size will increase on BMCWeb
6074. Existing systems with the static authorization shall work as if this feature
608   is not introduced
609
610## Organizational
611
612No new repository is required. Phosphor-user-manager and BMCWeb will be modified
613to implement the design.
614
615## Testing
616
617Existing tests shall still pass as if this feature is not introduced. New Robot
618Framework test can be added to test runtime modification of PrivilegeRegistry.
619
620Test cases should include:
621
6221. verify base Redfish roles, privileges, and base operation-to-privilege
623   respect the Redfish spec when no runtime modification is made
6242. verify Redfish OemPrivilege can be added via PATCH to PrivilegeRegistry and
625   reflected in the PrivilegeRegistry resource
6263. verify Redfish OemRole can be added via POST to ManagerAccountCollection with
627   assigned OemPrivilege and reflected in the ManagerAccountCollection
6284. verify operation-to-privilege can be modified via PATCH on PrivilegeRegistry;
629   mapping of an action on a resource can be added with the above OemPrivilege,
630   and finally the user of that OemRole now can access the resource
6315. verify the 3 dynamic overriding is working as expected; e.g., a new override
632   can be added to PrivilegeRegistry and should be reflected in new requests
633