Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

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 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.


  • 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)
  • No labels