Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 15 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,30 +183,7 @@ This is intended to reduce the amount of polling required by clients to keep up
However the specification is deliberately left open-ended; only the message bodies are specified, but not the protocol by which they are carried nor the method by which clients subscribe.
It is assumed that implementations will provide a suitable mechanism, such as a call to allow clients to subscribe to webhooks, or details of an event bus to connect to and receive the messages.

### Security

The TAMS specification stipulates authentication methods that a client should support in order to identify themselves and provide credentials to the server, using standard HTTP approaches.
The authorisation model (the rules by which authenticated requests are allowed or denied) is not part of the TAMS specification, and is up to individual implementers and organisations depending on their exact rules, needs and threat model.

It is assumed that implementations will apply other IT and cloud infrastructure security best practices, notably including the use of TLS (e.g. HTTPS connections) within and between their systems.

## Mock TAMS Service

This repo contains some automation to run a mock version of the API using [Stoplight Prism](https://stoplight.io/open-source/prism).
To run the mock server using Docker, try something like the command below (or run `make mock-server-up`):

```shell
docker run --rm --init --name mock-tams -v "$(pwd)":/data:ro -p 4010:4010 stoplight/prism mock /data/TimeAddressableMediaStore.yaml -h 0.0.0.0
```

A mock API server will start at <http://localhost:4010>

## Proposals, Decisions and Architecture Changes

This repository uses [(M)ADR documents](https://adr.github.io/madr/) to propose significant changes, facilitate discussions and decision making, and to store a record of options that were considered.
These documents may be found in the [docs/adr](./docs/adr/) directory, and are managed as described by the [ADR Readme](./docs/adr/README.md).

## API Versioning
### API Versioning

The API is versioned using a major and minor version number.
A breaking change - such as removal of a feature, or renaming of properties in such a way that would break compatibility (including fixing a typo) - results in a major version increment and the minor version is reset to 0.
Expand All @@ -226,7 +203,20 @@ Otherwise, the version will not change.

It is possible to see what the version would be if a release was made at the current commit by running `make next-version` in the top directory of this repository.

### Making a release
### Security

The TAMS specification stipulates authentication methods that a client should support in order to identify themselves and provide credentials to the server, using standard HTTP approaches.
The authorisation model (the rules by which authenticated requests are allowed or denied) is not part of the TAMS specification, and is up to individual implementers and organisations depending on their exact rules, needs and threat model.
However some principles and suggestions are discussed in [AppNote0016: Authorisation in TAMS workflows](./docs/appnotes/0016-authorisation-in-tams-workflows.md).

It is assumed that implementations will apply other IT and cloud infrastructure security best practices, notably including the use of TLS (e.g. HTTPS connections) within and between their systems.

## Proposals, Decisions and Architecture Changes

This repository uses [(M)ADR documents](https://adr.github.io/madr/) to propose significant changes, facilitate discussions and decision making, and to store a record of options that were considered.
These documents may be found in the [docs/adr](./docs/adr/) directory, and are managed as described by the [ADR Readme](./docs/adr/README.md).

## Making a release

Run the `release` workflow under the `Actions` tab on this repository on GitHub against the `main` branch.
This workflow requires approval.
Expand Down
9 changes: 5 additions & 4 deletions api/TimeAddressableMediaStore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2239,7 +2239,7 @@ paths:
"400":
$ref: '#/components/responses/trait_resource_info_head_400'
"404":
description: The requested Media Object does not exist.
description: The requested Media Object does not exist. 404 MUST be returned if the ID has been assigned via the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage), but not yet registered against a Flow Segment.
get:
summary: Media Object Information
description: |
Expand Down Expand Up @@ -2338,7 +2338,7 @@ paths:
"400":
description: Bad request. Invalid query options.
"404":
description: The requested Media Object does not exist.
description: The requested Media Object does not exist. 404 MUST be returned if the ID has been assigned via the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage), but not yet registered against a Flow Segment.
/objects/{objectId}/instances:
post:
summary: Register a Media Object instance
Expand Down Expand Up @@ -2389,7 +2389,7 @@ paths:
"403":
description: Forbidden. You do not have permission to modify this Media Object.
"404":
description: The Media Object does not exist.
description: The Media Object does not exist. 404 MUST be returned if the ID has been assigned via the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage), but not yet registered against a Flow Segment.
delete:
summary: Delete a Media Object instance
description: |
Expand Down Expand Up @@ -2428,7 +2428,8 @@ paths:
"403":
description: Forbidden. You do not have permission to modify this Media Object.
"404":
description: The requested Object ID in the path is invalid.
description: The requested Object ID in the path is invalid. 404 MUST be returned if the ID has been assigned via the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage), but not yet registered against a Flow Segment.

/flow-delete-requests:
head:
summary: List Flow Delete Requests
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ For more information on how we use application notes, see [here](./appnotes/READ
| [0013](./appnotes/0013-setting-flow-bit-rate-properties.md) | Setting Flow bit rate properties |
| [0014](./appnotes/0014-referencing-tams-content-in-other-systems.md) | Referencing TAMS content in other systems |
| [0015](./appnotes/0015-using-tams-in-opentimelineio.md) | Using TAMS in OpenTimelineIO |
| [0016](./appnotes/0016-authorisation-in-tams-workflows.md) | Authorisation in TAMS workflows |
| [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems |
| [0018](./appnotes/0018-managing-multiple-object-instances.md) | Managing Multiple Object Instances |

Expand Down Expand Up @@ -68,6 +69,7 @@ For more information on how we use ADRs, see [here](./adr/README.md).
| [0031](./adr/0031-flow-image-support.md) | Add new flow type to support still images |
| [0032](./adr/0032-specifying-storage-backend.md) | Specifying storage backend when requesting storage allocation |
| [0034](./adr/0034-storage-allow-object_ids.md) | Add object_ids option to Flow Storage request |
| [0035](./adr/0035-fine-grained-auth.md) | Fine-grained Authorisation in TAMS Workflows |
| [0036](./adr/0036-specifying-partial-segment-usage.md) | Specifying partial segment usage |
| [0037](./adr/0037-improve-webhooks.md) | Proposal for improvements to the Webhooks endpoints |
| [0038](./adr/0038-improved-storage-management.md) | Improved Storage Management |
Expand Down
178 changes: 178 additions & 0 deletions docs/adr/0035-fine-grained-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
status: "accepted"
---
# Fine-grained Authorisation in TAMS Workflows

## Context and Problem Statement

TAMS provides multiple methods for authentication, as described in [ADR0028](./0028-authentication-methods.md).
The most commonly used method to implement authentication is Bearer tokens acquired using OAuth2 flows.
OAuth2 allows for auth tokens to claim [scopes](https://oauth.net/2/scope/) as a means to restrict the permissions of clients and requests.
This has been used in TAMS implementations to provide coarse grained authorisation.

Emerging TAMS use cases are making use of TAMS' media re-use capabilities over increasingly large numbers of users, teams, and organisations.
As the number of clients accessing content in a TAMS store grows, the need for finer-grained control of that content becomes more acute.

This ADR presents the decisions and considerations that informed the initial approach to fine-grained auth in TAMS.

## Decision Drivers

* Be prescriptive enough to enable interoperability of service and client implementations
* Be permissive enough to facilitate integration with existing workflows and systems
* Acknowledge that organisations will have different threat models, and interoperability should be equally possible in more open and more restrictive environments
* As far as practical, maintain sensible parallels between coarse and fine-grained approaches
* Enable authorization at a sufficiently fine-grained level for practical use cases
* Must be possible to implement the design efficiently

## Considered Options

* Option 1a: Granularity of auth - Source
* Option 1b: Granularity of auth - Flow
* Option 1c: Granularity of auth - Segment
* Option 1d: Granularity of auth - Object
* Option 2a: Level of prescriptiveness - General principles
* Option 2b: Level of prescriptiveness - Auth logic
* Option 2c: Level of prescriptiveness - Specific API requests/pseudocode/scopes
* Option 2d: Level of prescriptiveness - Mandate the use of the proposed approach
* Option 3a: Supported architectures - Deep integration
* Option 3b: Supported architectures - Auth proxy
* Option 4a: Auth attributes - Single Tag with a list value
* Option 4b: Auth attributes - Specific parameters

## Decision Outcome

Chosen options:

* Option 1b: Granularity of auth - Flow
* Option 2b: Level of prescriptiveness - Auth logic
* Option 3b: Supported architectures - Auth proxy
* Option 4a: Auth attributes - Single Tag with a list value

This combination of options provides a good balance of well defined behaviour and flexibility.
It facilitates both interoperability and integration with existing auth systems and workflows.
The choice of Option 3b does not preclude the solution developed being implemented as described in Option 3a.
The choice of Option 4a allows for us to experiment with, and refine our approach to fine-grained auth.
Once our approach is mature, we may wish to consider implementing Option 1c in [ADR0040](./0040-tag-usability-enhancements.md) to provide a more efficient solution.

### Implementation

Implemented by <https://github.com/bbc/tams/pull/115>.

## Pros and Cons of the Options

### Option 1a: Granularity of auth - Source

Define permissions at the Source level.
Permissions are then propagated down to Flows, Segments, and Objects.

* Good, because it can be implemented with minimal changes to the API specification
* Good, because it requires the least additional data to be stored in/alongside the API
* Bad, because it provides limited control over different representations of media
* Prevents cost control (e.g. allow access to proxies, but not hi-res)
* Prevents management of access to specific storage backends

### Option 1b: Granularity of auth - Flow

Define permissions at the Source and Flow levels.
Permissions are then propagated down to Segments, and Objects.
However the default approach should be to define permissions on Sources (since permissions are likely to apply to all renditions of a piece of content), with the option to use Flows where restricting specific variants is required.

* Good, because it can be implemented with minimal changes to the API specification
* Good, because it requires a manageable amount of additional data to be stored in/alongside the API
* Good, because it provides control over different representations of media
* Neutral, because access can only be provided to entire flows
* Time-scoped access requires new flows to be created, potentially via zero-copy mechanism

### Option 1c: Granularity of auth - Segment

Define permissions at the Source, Flow, and Segment levels.
Permissions are then propagated down to Objects.

* Good, because it can be implemented with minimal changes to the API specification
* Good, because it provides control over different representations of media
* Good, because it enables direct control of access to segments of flow timelines
* Note that segments may contain multiple video frames/audio samples etc
* Allowing direct sub-segment access control would require significant further modification
* Bad, because it requires significant amounts of additional data to be stored in/alongside the API

### Option 1d: Granularity of auth - Object

Define permissions at the Source, Flow, Segment, and Object levels.

* Good, because it can be implemented with minimal changes to the API specification
* Good, because it provides control over different representations of media
* Good, because it maps the right to access content onto the content itself, regardless of how it is re-used
* Neutral, because it enables direct control of access to segments of flow timelines
* Allowing direct sub-segment access control would require significant modification
* Bad, because it requires significant amounts of additional data to be stored in/alongside the API
* Bad, because it may make re-use of media very complicated

### Option 2a: Level of prescriptiveness - General principles

State some general principles implementations may follow, and technologies they may use.
Leave the definition of auth logic etc up to individual implementations.

* Good, because it provides high levels of flexibility in implementations
* Bad, because it makes interoperability around fine-grained auth difficult
* Bad, because it requires implementers to derive all auth logic from scratch, including a few known non-trivial aspects

### Option 2b: Level of prescriptiveness - Auth logic

Define principles, and high-level auth logic.
Leave specific algorithms, and the requests that permissions evaluation systems may make to the API up to the individual implementations.

* Good, because it facilitates interoperability around fine-grained auth
* Good, because implementers don't have to derive auth logic from scratch
* Neutral, because it provides medium levels of flexibility to implementations

### Option 2c: Level of prescriptiveness - Specific API requests/pseudocode/scopes

Define all auth logic, algorithms that evaluate that auth logic, and API requests permission evaluation systems will make.

* Good, because it facilitates interoperability around fine-grained auth
* Good, because implementers don't have to derive auth logic, or algorithms from scratch
* Bad, because it provides low levels of flexibility to implementations
* This may conflict with existing auth systems, and workflows in deployments and organisational structures and models

### Option 2d: Level of prescriptiveness - Mandate the use of the proposed approach

Make the proposed approach to fine-grained auth mandatory.

* Good, because it ensures full interoperability around fine-grained auth
* Bad, because the approach may conflict with existing auth systems, and workflows in deployments and organisational structures and models
* Bad, because such conflicts being a mandatory part of the specification may prevent/impede use of TAMS by some organisations

### Option 3a: Supported architectures - Deep integration

Assume all TAMS services that support fine-grained auth will implement it with deep integration into the API implementation where policy decisions are made by the store implementation as part of processing a request, with full access to any backing databases etc.

* Good, because its the most efficient option to implement
* Bad, because it provides low levels of flexibility when integrating with existing auth systems, and workflows in deployments

### Option 3b: Supported architectures - Auth proxy

Assume fine-grained auth may be implemented using the Auth Proxy pattern where an HTTP reverse proxy can receive incoming requests, amend them as needed and forward them onto a store (which may have no fine-grained authorisation model).
The proxy can use the contents of the original request, the amended request(s) and the response(s) to make a decision on what to return to the user without modifying the underlying store.

* Good, because it provides high levels of flexibility when integrating with existing auth systems, and workflows in deployments
* Neutral, because its an acceptably efficient option to implement

### Option 4a: Auth attributes - Single Tag with a list value

Use the tag list support (added with [ADR0040](./0040-tag-usability-enhancements.md)) to provide/query attributes as part of an Attribute-Based Access Control (ABAC) system.

* Good, because it requires little/no changes to the API specification beyond ADR0040
* Good, because it makes use of tags for this purpose intuitive
* Good, because it requires very few API calls when carrying out evaluation of permissions on endpoints

### Option 4b: Auth attributes - Specific parameters

Define new parameters throughout the API specification for the purpose of storing auth-specific attributes.

* Good, because it allows for an optimal number API calls when carrying out evaluation of permissions on endpoints
* Neutral, because it results in increased integration of auth mechanisms into the core specification
* Bad, because it requires significant changes to the API specification for a feature that has not been widely tested

## More Information

Information on TAMS' approach to authentication may be found in [ADR0028](./0028-authentication-methods.md).
14 changes: 14 additions & 0 deletions docs/appnotes/0003-tag-names.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ The type is a `boolean`.
It is used to indictate the Flow should be excluded from HLS manifest generation.
Defaults to `false` if the tag is not set.

### auth_classes

Status: **Experimental**

Suggested as a way to build lightweight Attribute-based Access Control in [AppNote0016: Authorisation in TAMS workflows](./0016-authorisation-in-tams-workflows.md).
A comma seperated list of auth classes used to derive permissions on the Flow.

## Known Source Tags

### hls_exclude
Expand All @@ -206,3 +213,10 @@ Used in the TAMS demonstration at NAB 2025.
The type is a `boolean`.
It is used to indictate the Source should be excluded from HLS manifest generation.
Defaults to `false` if the tag is not set.

### auth_classes

Status: **Experimental**

Suggested as a way to build lightweight Attribute-based Access Control in [AppNote0016: Authorisation in TAMS workflows](./0016-authorisation-in-tams-workflows.md).
A comma seperated list of auth classes used to derive permissions on the Source.
Loading
Loading