Record Level Ownership (Ed-Fi ODS / API)
Overview
Field implementations in the Ed-Fi ecosystem have come across the need for record-level ownership in the Ed-Fi ODS / API. These needs seem to stem from authorization use cases important in local contexts. As the Ed-Fi ODS / API primarily uses a relationship-based authorization strategy based on education organizations, there is sometimes a lack of the granularity necessary to meet all desired use cases.
Record level ownership has been proposed by the Arizona DOE as a general purpose solution to this situation. An initial proposed design was surfaced to the Technical Advisory Group for consideration (see February 2019 meeting notes and the attached deck). The proposal is framed as a set of optional elements to the Ed-Fi ODS / API (i.e. they could be turned off if not needed).
Ed-Fi Alliance also held a Record Level Ownership in the Ed-Fi ODS SIG to discuss this further. The following design recommendation is largely describes the work the SIG produced.
Overall Design
Each aggregate root entity in the ODS will be assigned with an ownership token indicating the access rights to that resource. EdFi_Admin database will be modified to hold ownership tokens for the API client. API logic will be modified to populate the new ownership token property on the aggregate root entity from the API client's key context. This could probably be done in the Create method of the CreateEntity<T> class. ODS / API authorization layer design will be expanded to support multiple authorization strategies for a give resource/action combination. This really is an authorization concern and while the flexibility of the general IoC-based architecture would allow the functionality to be configured in as additional C# classes driven by a feature configuration value, the most natural place for it to land is in the authorization code driven by authorization metadata. Authorization metadata in EdFi_Security database would need schema changes to support multiple authorization strategies. Authorization code would need to be updated to identify multiple matching authorization strategies for a request, and apply multiple sets of filter criteria to the queries. Sandbox and On-prem admin Apps and security visualization tool would need to be updated.
EdFi_Admin Database Changes
In order to authorize individual resource items in the API based on the concept of "ownership", each API client will need to have an associated "Ownership Token" that is captured with each resource the client creates. The API client's claims information will then need to include a list of "Ownership Tokens" that can be used to identify which resource items they currently "own", and the authorization process will filter results and access against this list against based on the target resource's "Ownership Token" value.
Initially, API clients would be created with an assigned/generated "Ownership Token", and with a single entry in their "Ownership Token" list containing that value. Subsequently, if the ownership of their data needs to be transferred to another API client, the "Ownership Token" value would be removed from their list and added to the new owning API client's list. Presumably, each "Ownership Token" should be associated with at most one API client at a time.
There was some discussion about what an "ownership token" would look like. However, the most important aspect to the concept is that it is distinctly not the API client Id as it can be transitioned between API clients. Additionally, since it will have to be added to every aggregate root table in the ODS database, we should consider the data type more carefully. It seems that rather than introducing a character-based column for this value, that a "smallint" value should more than suffice. Thus, the recommended design below uses "smallint".
While there are multiple ways to model this, the following is recommended for clarity of intent:
Create a new OwnershipTokens table, to capture the ownership tokens that are being used to create records in the ODS, as follows:
Column Name
Data Type
Allow Nulls
OwnershipTokenId smallint IDENTITY No A description column could also be added for display purposes for UI-based administration, perhaps being defaulted to the associated Application's name and a creation date/time (or similar).
Modify the ApiClients table, adding the following column (and associated foreign key constraint) to capture the ownership token associated with the API client for creation:
Column Name
Data Type
Allow Nulls
OwnershipToken_OwnershipTokenId smallint (FK) Yes Since this table represents the usage of a particular ownership token by an API client when creating resource items, a unique constraint should also be added to the column to prevent a token from being inadvertently being assigned to another API client.
Create a new ApiClientOwnershipTokens table, to capture the tokens currently "owned" by the API client (allowing the client to modify the associated resource items), as follows:
Column Name
Data Type
Allow Nulls
ApiClientOwnershipTokenId int IDENTITY No ApiClient_ApiClientId int (FK) No OwnershipToken_OwnershipTokenId smallint (FK) No If an "Ownership Token" should only be associated with 1 API client at a time, a unique constraint should be added to the OwnershipToken_OwnershipTokenId column.
EdFi_Ods Database Changes
Every aggregate root table in the ODS should have an additional "boilerplate" column added to capture the "Ownership Token" of the API client that created the record. The suggestion is to create these columns as CreatedByOwnershipTokenId of type smallint, and made nullable.
EdFi_Security Database Changes
The application of an "ownership-based" authorization strategy should be done in an additive fashion. To facilitate this, we will need to be able to define multiple authorization strategies for the default resource claim/action "tuples" (in the ResourceClaimAuthorizationMetadatas table), as well as for claim set-specific overrides (in the ClaimSetResourceClaims table). The current design of these tables are shown below.
Currently, the design is intended to capture a single Authorization Strategy and a single ValidationRuleSetName per ResourceClaim/Action pair, but it now needs to be modified to support capturing multiple authorization strategies.
The recommended approach is to modify the database by moving the AuthorizationStrategy_AuthorizationStrategyId column(s) to two new one-to-many child tables – ResourceClaimAuthorizationStrategies and ClaimSetResourceClaimAuthorizationStrategies.
The recommended database design changes are as follows:
- Rename the primary key column of the ResourceClaimAuthorizationMetadatas table from ResourceClaimAuthorizationStrategyId to ResourceClaimAuthorizationMetadataId.
Create a new ResourceClaimAuthorizationStrategies child table, as follows:
Column Name
Data Type
Allow Nulls
ResourceClaimAuthorizationStrategyId int IDENTITY No ResourceClaimAuthorizationMetadata_ResourceClaimAuthorizationMetadataId int (FK) No AuthorizationStrategy_AuthorizationStrategyId int (FK) No Add a unique constraint on the ResourceClaimAuthorizationMetadata_ResourceClaimAuthorizationMetadataId and AuthorizationStrategy_AuthorizationStrategyId columns.
Create a new ClaimSetResourceClaimAuthorizationStrategies child table, as follows:
Column Name
Data Type
Allow Nulls
ClaimSetResourceClaimAuthorizationStrategyId int IDENTITY No ClaimSetResourceClaim_ClaimSetResourceClaimId int (FK) No AuthorizationStrategyOverride_AuthorizationStrategyId int (FK) No Add a unique constraint on the ClaimSetResourceClaim_ClaimSetResourceClaimId and AuthorizationStrategyOverride_AuthorizationStrategyId columns.
Additional design changes to EdFi_Security that should be considered (for naming consistency) are as follows:
- Rename the ClaimSetResourceClaims table to ClaimSetResourceClaimAuthorizationMetadatas.
- Rename the primary key of that table from ClaimSetResourceClaimId to ClaimSetResourceClaimAuthorizationMetadataId.
- This would enforce data to conform to how it is used by the application.