Epic: Capture Ownership on Newly Created Entities
Story: Create EF migrations in EdFi_Admin to enable storage of ownership-based claims information
As an API host I want to manage ownership tokens for API clients so that I can authorize access to Ed-Fi ODS API resources based on ownership.
The schema of the EdFi_Admin database must be updated to support the creation of ownership tokens, the association of a single (stable) token to an API client, and the assignment of one or more ownership tokens to an API client.
Tasks:
- Create EF migration in EdFi_Admin (in the Migrations subfolder of the EdFi.Ods.Admin.Models project) to support storing information needed for the ownership-based security model:
- Create an OwnershipToken entity/table.
- Add an OwnershipTokenId (short/smallint) property as the primary key.
- Add a Description (string/nvarchar with a maximum length of 50) property to hold a descriptive name worthy of display in a management UI.
- Modify the ApiClient entity/table, as follows:
- Add an optional CreatorOwnershipTokenId property (short/smallint) as a foreign key reference to the OwnershipToken entity/table.
- Create an ApiClientOwnershipToken entity/table.
- Add an ApiClientOwnershipTokenId (int IDENTITY) property/column as the primary key.
- Add OwnershipTokenId (short/smallint) and ApiClientId (int) properties as foreign key references to their respective tables.
- Create a unique constraint/index on ApiClientId and OwnershipTokenId properties/columns.
- Create an OwnershipToken entity/table.
- Create EF migration in EdFi_Admin (in the Migrations subfolder of the EdFi.Ods.Admin.Models project) to enhance the AccessTokenIsValid stored procedure to return ownership-based claims information.
- Stored procedure must also return:
- the CreatorOwnershipTokenId associated with the API client (for "stamping" newly created resources)
- the collection of the API client's current OwnershipTokens (for authorizing access to existing resources)
- Stored procedure content must be added as embedded resources in the Sql subfolder, and are then executed in the up/down migrations using a helper function. Review any of the existing migrations that modify this stored procedure as a precedence for implementation.
- Stored procedure must also return:
- Phase 1 - Capture Ownership on Newly Created Entities
- Add support for ownership-based claims information
- Create EF migration in EdFi_Admin to support ownership-based security model:
- Create OwnershipToken entity/table with OwnershipTokenId (short) as the primary key, and a Description (string with maxlength of 50).
- Add optional OwnershipTokenId foreign key reference to the ApiClient entity/table.
- Create the ApiClientOwnershipToken entity/table with ApiClientOwnershipTokenId (int IDENTITY), with foreign key references to OwnershipTokenId (short) and ApiClientId (int).
- Create EF migration in EdFi_Admin to enhance the AccessTokenIsValid stored procedure to support ownership-based claims
- Stored procedure must also return the OwnershipTokenId associated with the API client (for "stamping" newly created resources)
- Stored procedure must also return the collection of the API client's current OwnershipTokens (for authorizing access to existing resources)
- Enhance OAuthTokenValidator class to populate the ownership-based claims into the ApiClientDetails class
- Add CreatorOwnershipTokenId to the ApiClientDetails class and populate.
- Add OwnedOwnershipTokenIds collection to the ApiClientDetails class, and populate from stored procedure results.
- Enhance the ApiKeyContext class to hold the ownership-based claims values for authorization decisions:
- Add CreatorOwnershipTokenId to the ApiClientDetails class and populate.
- Add OwnedOwnershipTokenIds collection to the ApiClientDetails class, and populate from stored procedure results.
- Enhance the OAuthAuthenticationProvider's Authenticate method to copy the CreatorOwnershipTokenId and OwnedOwnershipTokenIds from the ApiClientDetails to the ApiKeyContext
- Create EF migration in EdFi_Admin to support ownership-based security model:
- Add ODS support for capturing resource ownership
- Create a script for adding boilerplate ownership column to each aggregate root table
- Suggestion is to use a SELECT statement using INFORMATION_SCHEMA tables to generate a resultset that contains
ALTER TABLE edfi.Staff ADD CreatedByOwnershipTokenId smallint NULL
statements.
- Suggestion is to use a SELECT statement using INFORMATION_SCHEMA tables to generate a resultset that contains
- Ed-Fi TODO: Implement MetaEd generator to add CreatedByOwnershipTokenId via feature toggle (a la "Change Queries")
- Create a script for adding boilerplate ownership column to each aggregate root table
- Add core API support for capturing ownership on new resources
- Add CreatedByOwnershipTokenId property to the AggregateRootWIthCompositeKey class
- Create an ICreateEntity decorator (OwnershipInitializationCreateEntityDecorator) to assign the CreatedByOwnershipTokenId upon entity creation.
- Inject the IApiKeyContextProvider into the decorator
- Assign the CreatedByOwnershipTokenId from the API key context (OwnershipTokenId) before calling decorated Create method.
- Implement API Feature for Resource Ownership
- NOTE: Create as a new project, a la EdFi.Ods.ChangeQueries.
- Implement ResourceOwnershipNHibernateConfigurationActivity (INHibernateBeforeBindMappingActivity) to add ORM mapping of the CreatedByOwnershipTokenId property in all aggregate roots (a la ChangeQueryMappingNHibernateConfigurationActivity)
- Register all necessary components with the container (ResourceOwnershipInstaller)
- ResourceOwnershipNHibernateConfigurationActivity
- Implement ResourceOwnershipFeature (a la ChangeQueriesFeature)
- Add support for ownership-based claims information
- Phase 2 - Define and Make Metadata Available for Applying Multiple Authorization Strategies
- Add database support for defining necessary authorization metadata for applying multiple authorization strategies
- Create an EF migration (from entity changes) that renames existing columns and tables as follows:
- Rename the ResourceClaimAuthorizationMetadatas table to ResourceClaimActionAuthorizations.
- Rename the primary key column of the ResourceClaimActionAuthorizations table from ResourceClaimAuthorizationStrategyId to ResourceClaimActionAuthorizationId
- Create unique constraint/index on the ResourceClaim_ResourceClaimId and Action_ActionId columns.
- Ensure that all related artifacts (i.e. FK constraint names) are named correctly to prevent future EF migration failures.
- Create and preserve a single commit inclusive of the changes to entities and the associated migrations (do not squash the commit).
- Create an EF migration (from entity changes) that renames existing columns and tables as follows:
- Rename the ClaimSetResourceClaims table to ClaimSetResourceClaimActionAuthorizations.
- Rename the primary key of that table from ClaimSetResourceClaimId to ClaimSetResourceClaimActionAuthorizationId.
- Create unique constraint/index on the ClaimSet_ClaimSetId, ResourceClaim_ResourceClaimId and Action_ActionId columns.
- Ensure that all related artifacts (i.e. FK constraint names) are named correctly to prevent future EF migration failures.
- Create and preserve a single commit inclusive of the changes to entities and the associated migrations (do not squash the commit).
- Create an EF migration (from entity changes) that drops existing FKs and Indexes and moves the AuthorizationStrategyId FKs to new child tables (ResourceClaimActionAuthorizationStrategies and ClaimSetResourceClaimActionAuthorizationStrategyOverrides).
- Create primary key columns as ResourceClaimActionAuthorizationStrategyId and ClaimSetResourceClaimActionAuthorizationStrategyOverrideId, respectively.
- Create unique constraint/index on the FK columns of new child tables, as follows (respectively):
- ResourceClaimActionAuthorization_ResourceClaimActionAuthorizationIdId, and AuthorizationStrategy_AuthorizationStrategyId columns.
- ClaimSetResourceClaimActionAuthorization_ClaimSetResourceClaimActionAuthorizationIdId, and AuthorizationStrategy_AuthorizationStrategyId columns.
- Up migration must also move existing inline authorization strategy assignments to the child tables.
- Down migration must inline the data (using all defined authorization strategies, as they are not constrained) back to the parent table.
- Create an EF migration (from entity changes) that renames existing columns and tables as follows:
- Modify API authorization components to surface multiple authorization strategies
- Adjust any artifacts that currently reference authorization strategy names (or overrides) in the singular as type
string
toIReadOnlyList<string>
(except for EF security model components which should useList<string>
):- ~\Ed-Fi-ODS\Application\EdFi.Ods.Common\Security\Claims\EdFiResourceClaimValue.cs
- ~\Ed-Fi-ODS\Application\EdFi.Ods.Common\Security\Claims\IResourceAuthorizationMetadataProvider.cs
- ~\Ed-Fi-ODS\Application\EdFi.Ods.Security\Authorization\EdFiAuthorizationProvider.cs
- ~\Ed-Fi-ODS\Application\EdFi.Ods.Security\AuthorizationStrategies\ResourceAuthorizationMetadataProvider.cs
- ~\Ed-Fi-ODS\Application\EdFi.Ods.Security\Claims\ClaimsIdentityProvider.cs
- Adjust any artifacts that currently reference authorization strategy names (or overrides) in the singular as type
- Add database support for defining necessary authorization metadata for applying multiple authorization strategies
- Phase 3 - Authorize Access Based on Resource Ownership
- Implement a filter configurator for ownership based authorization
- OwnershipBasedAuthorizationStrategyFilterConfigurator class should implement the
INHibernateFilterConfigurator
interface using theNamespaceBasedAuthorizationStrategyFilterConfigurator
as a reference. - When defining the
criteriaApplicator
action, consider making use of theApplyPropertyFilters
extension method (ofICriteria
).
- OwnershipBasedAuthorizationStrategyFilterConfigurator class should implement the
- Implement an authorization strategy for ownership-based authorization
- OwnershipBasedAuthorizationStrategy class should implement the IEdFiAuthorizationStrategy using the NamespaceBasedAuthorizationStrategy as a reference.
- Named parameter value (CreatedByOwnershipTokenId) should be assigned from the client's claims (OwnershipTokenIds as an array of objects)
- Implement a filter configurator for ownership based authorization