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