...
Table of Contents | ||
---|---|---|
|
Epic: Capture ownership of newly created resources
This epic covers all the stories needed to capture resource ownership on each resource stored in the Ed-Fi ODS by the API. It can be implemented independently from the use of this information to perform ownership-based authorization of API requests.
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.
Description
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.
The current state of the EdFi_Admin is such that certain changes will likely fail due to previous migration(s) having renamed some columns, but having failed to rename certain artifacts (such as FK constraints or indices using the columns). These affected artifacts have retained their original names which are derived from the previous column names, but the new migrations will fail to delete them correctly. This work to modify the model to reflect actual usage, and proper data constraints is probably actually going to be the trickiest work of the entire feature.
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.
Story: Make ownership-based authorization claims available to the Ed-Fi ODS API
As an API developer, I want to access the ownership-based claims so that I can perform appropriate authorization.
Description
In order to make the claims available to the API authorization logic, data must flow from the EdFi_Admin database to the API through the AccessTokenIsValid stored procedure, into the ApiClientDetails class, and finally into the ApiKeyContext. Primarily, this story involves the enhancement of existing artifacts to carry this additional information through to the ApiKeyContext so that it is available for authorization decisions.
Tasks
- 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 be modified to 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 Updated stored procedure content SQL must be added as embedded resources in a .sql file as an Embedded Resource in the Sql subfolder, and are then executed in the . The up/down migrations using will then use a helper function to execute these files. Review any of the existing migrations that modify this stored procedure as a precedence for implementation.
- 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)
- Stored procedure must be modified to also return:
- Add CreatorOwnershipTokenId to the ApiClientDetails class and populate.
- Add OwnedOwnershipTokenIds collection to the ApiClientDetails class, and populate from stored procedure results.
- CreatorOwnershipTokenId (
short
) - OwnershipTokenIds (
List<short>
)
Story: Add
...
- 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")
...
- 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.
...
- 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 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
...
- 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
).
...
CreatedByOwnershipTokenId columns to all aggregate root tables
As an API developer I want to have a column in each aggregate root table in the ODS database for storing the creator's ownership token so that I have a basis for performing ownership-based authorization on subsequent requests.
Description
Each aggregate root table in the ODS will need a new CreatedByOwnershipTokenId column (smallint) added. Suggestion for initial implementation is to run the following query in SQL Server Management Studio:
Code Block | ||
---|---|---|
| ||
select 'ALTER TABLE ' + c.TABLE_SCHEMA +'.' + c.TABLE_NAME + ' ADD CreatedByOwnershipTokenId smallint NOT NULL;'
from INFORMATION_SCHEMA.COLUMNS c
where c.COLUMN_NAME = 'Id'
and c.TABLE_SCHEMA NOT IN ('dbo', 'auth', 'interop')
order by c.TABLE_SCHEMA, c.TABLE_NAME
|
Copy the result from the grid into a new text file and incorporate into the database script execution appropriately.
NOTE: In the future, this will be produced by a MetaEd plugin similar to how Change Queries is handled.
Story: Identify and capture resource ownership during entity creation
As an API host, I want to be able to turn on the "Ownership-Based Authorization" functionality as an optional feature of the API so that I can capture ownership of new resources and perform subsequent ownership-based authorizations.
Description
This story adds all the components actually needed in order to identify the owner (from the current API client), assign the ownership token id to the corresponding aggregate root entity, and map the property to the ODS table.
Optional features in the Ed-Fi ODS API are now developed as "Features". All new classes described in the tasks below should be added to a new project named EdFi.Ods.Features.OwnershipBasedAuthorization. Review the recently added EdFi.Ods.ChangeQueries for a basis for code organization with the project.
Tasks
- Add a new CreatedByOwnershipTokenId property (short) to the AggregateRootWithCompositeKey class.
- Add a new IHasCreator interface (containing just the CreatedByOwnershipTokenId property) in the EdFi.Ods.Common project (alongside IHasIdentifier)
- Add a generic constraint (of IHasCreator) on the TEntity generic types defined on the ICreateEntity, CreateEntity and CreateEntityAuthorizationDecorator interfaces and implementations.
- Provide an INHibernateBeforeBindMappingActivity implementation (OwnershipBasedAuthorizationNHibernateConfigurationActivity) that adds the necessary run-time ORM mapping of the CreatedByOwnershipTokenId property in all aggregate roots. Use the ChangeQueryMappingNHibernateConfigurationActivity as a reference implementation.
- Create an ICreateEntity decorator (OwnershipInitializationCreateEntityDecorator, with a generic constraint of IHasCreator on the generic type argument TEntity) to assign the CreatedByOwnershipTokenId upon entity creation.
- Inject the IApiKeyContextProvider into the decorator (along with the decorated ICreateEntity instance). (NOTE: Following this pattern and registering the decorator first will result in Castle Windsor automatically injecting the decorated instance into the decorator.)
- Assign the CreatedByOwnershipTokenId property from the current API key context (CreatorOwnershipTokenId property) before calling decorated instance's Create method.
- Implement API Feature for Ownership-Based Authorizations
- Create a OwnershipBasedAuthorizationInstaller class (using ChangeQueriesInstaller as a referenced) to register all new components with the Castle Windsor container.
- Create a OwnershipBasedAuthorizationFeature class (using ChangeQueriesFeature as a reference implementation) to allow for configuration-based activation of the feature and invoke the installer.
- Add an instance of the OwnershipBasedAuthorizationFeature instance to the feature list built in the constructor of the FeatureProvider class (in EdFi.Ods.Api.Startup).