Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents
maxLevel2

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.

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)
    • Updated stored procedure SQL must be added as a .sql file as an Embedded Resource in the Sql subfolder. The up/down migrations 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.
  • Enhance OAuthTokenValidator class to populate the ApiClientDetails with the new ownership-based claims from the stored procedure results:
    • CreatorOwnershipTokenId   (short)
    • OwnershipTokenIds (List<short>)
  • Enhance the OAuthAuthenticationProvider's Authenticate method to copy the CreatorOwnershipTokenId and OwnershipTokenIds from the ApiClientDetails to new corresponding properties on the ApiKeyContext.

Story: Add 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:

...

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.

Original Notes (to be deleted):

  • 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
    • 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.
      • Ed-Fi TODO: Implement MetaEd generator to add CreatedByOwnershipTokenId via feature toggle (a la "Change Queries")
    • 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)
  • 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.
    • 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  to IReadOnlyList<string> (except for EF security model components which should use List<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
  • Phase 3 - Authorize Access Based on Resource Ownership
    • Implement a filter configurator for ownership based authorization
      • OwnershipBasedAuthorizationStrategyFilterConfigurator class should implement the INHibernateFilterConfigurator  interface using the NamespaceBasedAuthorizationStrategyFilterConfigurator as a reference.
      • When defining the criteriaApplicator  action, consider making use of the ApplyPropertyFilters  extension method (of ICriteria).
    • 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)Add an instance of the OwnershipBasedAuthorizationFeature instance to the feature list built in the constructor of the FeatureProvider class (in EdFi.Ods.Api.Startup).