diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml new file mode 100644 index 0000000..ffada80 --- /dev/null +++ b/.github/workflows/build-pr.yml @@ -0,0 +1,30 @@ +name: Build Pull Request + +on: + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + container: + image: ghcr.io/dash-industry-forum/dashif-specs:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.github_token }} + + steps: + - uses: actions/checkout@v4 + - name: Build + env: + # Reset OPTS to empty to make sure we are not using + # interactive mode in CI + OPTS: + run: make -f /tools/Makefile spec SRC=Guidelines-Security.bs.md NAME=Guidelines-Security + + - name: Archive + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..f026418 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,56 @@ +name: Publish + +on: + push: + branches: + - master + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + packages: read + pages: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + container: + image: ghcr.io/dash-industry-forum/dashif-specs:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.github_token }} + + steps: + - uses: actions/checkout@v4 + - name: Build + env: + # Reset OPTS to empty to make sure we are not using + # interactive mode in CI + OPTS: + run: make -f /tools/Makefile spec SRC=Guidelines-Security.bs.md NAME=Guidelines-Security + + - name: Archive + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + + package: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/download-artifact@v4 + with: + name: dist + path: dist + - uses: actions/upload-pages-artifact@v3 + with: + path: dist + + publish: + runs-on: ubuntu-latest + needs: package + steps: + - name: Deploy to GitHub Pages + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index cd0df9c..2975b7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -Output \ No newline at end of file +Output +dist/ diff --git a/10-General.inc.md b/10-General.inc.md index 6a3900e..4089300 100644 --- a/10-General.inc.md +++ b/10-General.inc.md @@ -3,7 +3,7 @@ DASH-IF provides guidelines for using multiple [=DRM systems=] to access a DASH presentation by adding encryption signaling and [=DRM system configuration=] to DASH content encrypted in conformance to Common Encryption [[!CENC]]. In addition to content authoring guidelines, DASH-IF specifies interoperable workflows for DASH client interactions with [=DRM systems=], platform APIs and external services involved in content protection interactions.
- +
A [=DRM system=] cooperates with the device's [=media platform=] to enable playback of encrypted content while protecting the decrypted samples and [=content keys=] against potential attacks. The DASH-IF implementation guidelines focus on the signaling in the DASH presentation and the interactions of the DASH client with other components.
@@ -28,7 +28,7 @@ A license is a data structure in a [=DRM system=] specific format tha Different software architectural components are involved in playback of encrypted content. The exact nature depends on the specific implementation. A high-level reference architecture is described here.
- +
Reference architecture for encrypted content playback.
@@ -220,7 +220,7 @@ Note: This optimization might require support from platform APIs and/or [=DRM sy While it is common that `default_KID` identifies the actual [=content key=] used for encryption, a [=DRM system=] MAY make use of other keys in addition to the one signalled by the `default_KID` value but this SHALL be transparent to the client with only the `default_KID` being used in interactions between the DASH client and the [=DRM system=]. See [[#CPS-KeyHierarchy]].
- +
In a [[#CPS-KeyHierarchy|hierarchical key scenario]], `default_KID` references the [=root key=] and only the sample group descriptions reference the [=leaf keys=].
diff --git a/40-LicenseRequestModel.inc.md b/40-LicenseRequestModel.inc.md index 2628754..1743460 100644 --- a/40-LicenseRequestModel.inc.md +++ b/40-LicenseRequestModel.inc.md @@ -53,7 +53,7 @@ The above data sets are serialized and digitally signed to arrive at the final f [=Authorization tokens=] are issued by an authorization service, which is part of a solution's business logic. The authorization service has access to the project-specific context that it needs to make its decisions (e.g. the active session, user identification and database of purchases/entitlements). A single authorization service can be used to issue [=authorization tokens=] for multiple license servers, simplifying architecture in solutions where multiple license server vendors are used.
- +
Role of the authorization service in DRM workflow related communication.
@@ -68,7 +68,7 @@ To obtain an [=authorization token=], a DASH client needs to know the URL of the If no authorization service URL is provided by the MPD nor made available at runtime, a DASH client SHALL NOT attach an [=authorization token=] to a license request. Absence of this URL implies that authorization operations are performed in a manner transparent to the DASH client (see [[#CPS-lr-model-deployment]]).
- +
[=Authorization tokens=] are requested from all authorization services referenced by the selected adaptation sets.
@@ -197,7 +197,7 @@ Authorization services and license servers SHOULD indicate an inability to satis 1. Signals a suitable status code (4xx or 5xx). 1. Has a `Content-Type` of `application/problem+json`. -1. Contains a HTTP response body conforming to [[!rfc7807]]. +1. Contains a HTTP response body conforming to [[!rfc7807 obsolete]].
HTTP response from an authorization service, indicating a rejected [=authorization token=] request because the requested content is not a part of the user's subscriptions. @@ -265,7 +265,7 @@ The interoperable license request model is designed to allow for the use of diff The baseline architecture assumes that a separate authorization service exists, implementing the logic required to determine which users have the rights to access which content.
- +
The baseline architecture with an authorization service directly exposed to the DASH client.
@@ -274,7 +274,7 @@ While the baseline architecture offers several advantages, in some cases it may A common implementation for transparent authorization is to use a "license proxy", which acts as a license server but instead forwards the license request after authorization checks have passed. Alternatively, the license server itself may perform the authorization checks.
- +
A transparent authorization architecture performs the authorization checks at the license server, which is often hidden behind a proxy (indistinguishable from a license server to the DASH client).
diff --git a/60-ClientWorkflows.inc.md b/60-ClientWorkflows.inc.md index 4c57806..34fc61c 100644 --- a/60-ClientWorkflows.inc.md +++ b/60-ClientWorkflows.inc.md @@ -29,7 +29,7 @@ A typical [=DRM system=] might offer the following set of capabilities: A typical [=media platform=] API such as EME [[!encrypted-media]] will require the DASH client to query the platform by supplying a desired capability set. The [=media platform=] will inspect the desired capabilities, possibly displaying a permissions prompt to the user (if sensitive capabilities such as unique user identification are requested), after which it will return a supported capability set that indicates which of the desired capabilities are available.
- +
The DASH client presents a set of desired capabilities for each [=DRM system=] and receives a response with the supported subset.
@@ -128,7 +128,7 @@ When encrypted adaptation sets are initially selected for playback or when the s * This enables business logic to include DRM systems not signaled in the MPD. 1. Let default_kids be the set of all distinct `default_KID` values in adaptation_sets. -1. Let system_configurations be an empty map of `system ID -> map(default_kid -> configuration)`, representing the [=DRM system configuration=] of each `default_KID` for each [=DRM system=].
+1. Let system_configurations be an empty map of `system ID -> map(default_kid -> configuration)`, representing the [=DRM system configuration=] of each `default_KID` for each [=DRM system=].
1. For each system_id in candidate_system_ids: 1. Let configurations be a map of `default_kid -> configuration` where the keys are default_kids and the values are the [=DRM system configurations=] initialized with data from `ContentProtection` descriptors in the MPD (matching on `default_KID` and system_id). * If there is no matching `ContentProtection` descriptors in the MPD, the map still contains a partially initialized [=DRM system configuration=] for the `default_KID`. @@ -211,7 +211,7 @@ It is possible that not all of the encrypted adaptation sets selected for playba A DASH client can request a [=DRM system=] to enable decryption using any set of [=content keys=] (if it has the necessary [=DRM system configuration=]). However, this is only a request and playback can be countermanded at multiple stages of processing by different involved entities.
- +
The set of [=content keys=] made available for use can be far smaller than the set requested by a DASH client. Example workflow indicating potential instances of [=content keys=] being removed from scope.
@@ -262,7 +262,7 @@ DASH clients performing license requests SHOULD follow the [[#CPS-lr-model|DASH- [=DRM systems=] generally do not perform license requests on their own. Rather, when they determine that a [=license=] is required, they generate a document that serves as the license request body and expect the DASH client to deliver it to a license server for processing. The latter returns a suitable response that, if a [=license=] is granted, encapsulates the [=content keys=] in an encrypted form only readable to the DRM system.
- +
Simplified conceptual model of license request processing. Many details omitted.
@@ -276,7 +276,7 @@ The license request workflow defined here exists to enable the following goals t The proof of authorization is optional and the need to attach it to a license request is indicated by the presence of at least one `dashif:authzurl` in the [=DRM system configuration=]. The proof of authorization is a [[!jwt|JSON Web Token]] in compact encoding (the `aaa.bbb.ccc` form) returned as the HTTP response body when the DASH client performs a GET request to this URL. The token is attached to a license request in the HTTP `Authorization` header with the `Bearer` type. For details, see [[#CPS-lr-model]]. -Error responses from both the authorization service and the license server SHOULD be returned as [[rfc7807]] compatible responses with a 4xx or 5xx status code and `Content-Type: application/problem+json`. +Error responses from both the authorization service and the license server SHOULD be returned as [[rfc7807 obsolete]] compatible responses with a 4xx or 5xx status code and `Content-Type: application/problem+json`. DASH clients SHOULD implement retry behavior to recover from transient failures and expiration of [=authorization tokens=]. diff --git a/80-Misc.inc.md b/80-Misc.inc.md index ba0ed7a..133c4d5 100644 --- a/80-Misc.inc.md +++ b/80-Misc.inc.md @@ -16,7 +16,7 @@ Note: Changing the [=content keys=] does not increase the cryptographic security Using a key hierarchy allows a single [=content key=] to selectively unlock only a subset of a DASH presentation and apply license policy updates without the need to perform license requests at every program boundary. This mechanism is a specialization of periodic re-authorization for scenarios where license requests at program boundaries are not always desirable or possible.
- +
A key hierarchy establishes a [=DRM system=] specific relationship between a [=root key=] and a set of [=leaf keys=].
@@ -43,7 +43,7 @@ The mechanism by which a set of [=leaf keys=] is made available based on a reque When using a key hierarchy, the [=leaf keys=] are typically delivered in-band in the media segments, using `moof/pssh` boxes, together with additional/updated license policy constraints. The exact implementation is [=DRM system=] specific and transparent to a DASH client.
- +
Different rows indicate [=root key=] changes. Color alternations indicate [=leaf key=] changes. A key hierarchy enables per-program access control even in scenarios where a license request is only performed once per day. The single license request makes available all the [=leaf keys=] that the user is authorized to use during the next epoch.
diff --git a/Guidelines-Security.bs.md b/Guidelines-Security.bs.md index e5d7411..5246f29 100644 --- a/Guidelines-Security.bs.md +++ b/Guidelines-Security.bs.md @@ -1,40 +1,27 @@ -#include "01-Intro.inc.md" - -#include "10-General.inc.md" -#include "40-LicenseRequestModel.inc.md" -#include "60-ClientWorkflows.inc.md" -#include "80-Misc.inc.md" - - -
 Revision: 5.0
 
 Title: DASH-IF implementation guidelines: content protection and security
 Status: LS-COMMIT
 Shortname: dash-security
-URL: https://dashif-documents.azurewebsites.net/Guidelines-Security/master/Guidelines-Security.html
+URL: https://dashif.org/Guidelines-Security/
+Group: dashif
 Issue Tracking: GitHub https://github.com/Dash-Industry-Forum/Guidelines-Security/issues
-Repository: https://github.com/Dash-Industry-Forum/Guidelines-Security GitHub
-Editor: DASH Industry Forum
 
-Default Highlight: text
-
-Line Numbers: off
-Markup Shorthands: markdown yes
-Boilerplate: copyright off, abstract off
-Abstract: None
 
- -
-#include "References.json"
+
+path: 01-Intro.inc.md
 
- -
-
+
+path: 10-General.inc.md
 
- -
-
+
+path: 40-LicenseRequestModel.inc.md
+
+
+path: 60-ClientWorkflows.inc.md
+
+
+path: 80-Misc.inc.md
 
diff --git a/References.json b/biblio.json similarity index 100% rename from References.json rename to biblio.json diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8154bab --- /dev/null +++ b/build.bat @@ -0,0 +1,22 @@ +@echo off +set IMG=dashif/specs-builder:latest + +rem Check if OPTS is defined, if not, set default value +if "%OPTS%"=="" ( + set OPTS=-ti +) + +rem Collect command-line arguments +set TARGETS=%* + +rem If no arguments are provided, use "spec" +if "%TARGETS%"=="" ( + set TARGETS=spec +) + +rem Add parameters to TARGETS +set TARGETS=%TARGETS% SRC=Guidelines-Security.bs.md NAME=Guidelines-Security + +echo Running with targets: '%TARGETS%' +docker run --rm %OPTS% -v "%cd%:/data" -p 8000:8000 %IMG% %TARGETS% + diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..74c5a7c --- /dev/null +++ b/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Here is the command that can be used to debug or develop with the +# local resources. +# +# docker run --rm -ti -v `pwd`:/data -v `pwd`/build-tools/tools:/tools -v `pwd`/data/boilerplate/dashif:/usr/local/lib/python3.12/dist-packages/bikeshed/spec-data/boilerplate/dashif dashif-specs:latest +# + +# Run the docker container and pass all the arguments +IMG=dashif/specs-builder:latest + +# Allow to overwrite additional options from the outside. +# We use tty and interactive by default since this makes it easier +# to deal with watch mode and Ctrl-C etc but we can not use this +# for instance in CI mode +if [ -z ${OPTS+x} ]; then + OPTS=-ti +fi + +TARGETS="${@}" +if [ -z "${TARGETS}" ]; then + TARGETS="spec" +fi +# Add parameters +TARGETS="${TARGETS} SRC=Guidelines-Security.bs.md NAME=Guidelines-Security" + +echo "Run with targets: '${TARGETS}'" +docker run --rm ${OPTS} -v `pwd`:/data -p 8000:8000 \ + ${IMG} ${TARGETS} diff --git a/setup.bat b/setup.bat new file mode 100644 index 0000000..6e61ec6 --- /dev/null +++ b/setup.bat @@ -0,0 +1,2 @@ +@echo off +docker pull dashif/specs-builder:latest \ No newline at end of file diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..ab0bfc7 --- /dev/null +++ b/setup.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# Pull the latest build image +IMG=dashif/specs-builder:latest +docker pull ${IMG}