Skip to content

Commit 1e71793

Browse files
committed
Update to include IS-10
1 parent 5f9d604 commit 1e71793

9 files changed

+123
-9
lines changed

Documents/Architecture.md

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Architecture of nmos-cpp
22

3-
The [nmos](../Development/nmos/) module fundamentally provides three things.
3+
The [nmos](../Development/nmos/) module fundamentally provides three things.
44

5-
1. A C++ data model for the AMWA IS-04 and IS-05 NMOS resources which represent the logical functionality of a Node, or equally, for the resources of many Nodes held by a Registry.
6-
2. An implementation of each of the REST APIs defined by the AMWA IS-04 and IS-05 NMOS specifications, in terms of the data model.
7-
3. An implementation of the Node and Registry "active behaviours" defined by the specifications.
5+
1. A C++ data model for the AMWA IS-04, IS-05 and IS-08 NMOS resources which represent the logical functionality of a Node, or equally, for the resources of many Nodes held by a Registry.
6+
2. An implementation of each of the REST APIs defined by the AMWA IS-04, IS-05, IS-08, IS-09 and IS-10 NMOS specifications, in terms of the data model.
7+
3. An implementation of the Node and Registry "active behaviours" defined by the specifications.
88

99
The module also provides the concept of a server which combines the REST APIs and behaviours into a single object for simplicity.
1010

@@ -14,12 +14,13 @@ The module also provides the concept of a server which combines the REST APIs an
1414
1515
The top-level data structures for an NMOS Node and Registry are ``nmos::node_model`` and ``nmos::registry_model`` respectively.
1616

17-
A ``node_model`` has three member variables which are containers, of IS-04 resources, IS-05 resources and IS-07 resources, respectively:
17+
A ``node_model`` has four member variables which are containers, of IS-04 resources, IS-05 resources, IS-07 resources and IS-08 resources, respectively:
1818

1919
```C++
2020
nmos::resources node_resources;
2121
nmos::resources connection_resources;
2222
nmos::resources events_resources;
23+
nmos::resources channelmapping_resources;
2324
```
2425

2526
A ``registry_model`` has two containers, this time for the Registry's own Node API "self" resource, and for the resources that have been registered with the Registration API:
@@ -118,9 +119,11 @@ for (;;)
118119
> [nmos/events_api.cpp](../Development/nmos/events_api.cpp),
119120
> [nmos/registration_api.cpp](../Development/nmos/registration_api.cpp),
120121
> [nmos/query_api.cpp](../Development/nmos/query_api.cpp),
121-
> [nmos/system_api.cpp](../Development/nmos/system_api.cpp)
122+
> [nmos/system_api.cpp](../Development/nmos/system_api.cpp),
123+
> [nmos/channelmapping_api.cpp](../Development/nmos/channelmapping_api.cpp)
124+
> [nmos/authorization_redirect_api.cpp](../Development/nmos/authorization_redirect_api.cpp)
122125
123-
The ``nmos`` module also provides the implementation of each of the REST APIs defined by AMWA IS-04, IS-05, IS-07 and IS-09.
126+
The ``nmos`` module also provides the implementation of each of the REST APIs defined by AMWA IS-04, IS-05, IS-07, IS-08, IS-09 and IS-10.
124127

125128
The C++ REST SDK provides a general purpose HTTP listener, that accepts requests at a particular base URL and passes them to a user-specified request handler for processing.
126129
Therefore the ``nmos`` module implements each API as a request handler which reads and/or writes the relevant parts of the NMOS data model, and provides a convenience function, ``nmos::support_api``, for associating the API request handler with the HTTP listener.
@@ -167,7 +170,7 @@ The required Node behaviour includes:
167170

168171
The state machine implemented by the ``nmos::node_behaviour_thread`` is shown below:
169172

170-
![NMOS Node Behaviour](images/node-behaviour.png)
173+
![NMOS Node Behaviour](images/node-behaviour.png)
171174

172175
<details>
173176
<summary>More details...</summary>
@@ -211,7 +214,7 @@ The diagram below shows a sequence of events within and between an **nmos-cpp**
211214
Resource events initiated in a resource-scheduling thread in the Node are propagated via the Registration API to the Registry model.
212215
Events in the Registry model are sent in WebSocket messages to each Client with a matching Query API subscription.
213216

214-
![Sequence Diagram](images/node-registry-sequence.png)
217+
![Sequence Diagram](images/node-registry-sequence.png)
215218

216219
## Servers
217220

@@ -273,3 +276,102 @@ A logging statement at run-time:
273276
- terminates the application if its severity level is fatal
274277

275278
</details>
279+
280+
## Authorization
281+
282+
This is based on the ``OAuth 2.0`` recommendation, it is used for protecting the NMOS APIs, which allows NMOS Node and NMOS Registry to give limited access to the third-party application. Third-party applications including Broadcast Controller, which queries Registry via the AMWA IS-04 for the NMOS Nodes information and issues the IS-05 connection to the Nodes. NMOS Nodes also act as the third-party for the Registry to perform the AMWA IS-04 node registration.
283+
284+
### General idea of how it works
285+
286+
A client such as Broadcast Controller provides credentials to the Authorization Server. The required access token(s) is then granted to the Controller for accessing the protected APIs on the Resource(s) Server, such as the NMOS Node. The Resource Server will verify the access token for the level of the access right. If all goes well, the protected API is accessible.
287+
288+
The access token is time-limited, it must be refreshed before it expired. It is recommended to attempt a refresh at least 15 seconds before the expiry or the half-life of the access token.
289+
290+
To speed up the token validation process, the Resource(s) Server periodically fetches the Authorization Server's public keys, typically once every hour. The public keys allow the Resource(s) Server to perform local token validation without bombarding the Authorization Server on every API access validation.
291+
292+
A similar idea is also applied to how NMOS Node performs node registration. Registry obtains the public keys from the Authorization Server, and the Node obtains the registration access token from the Authorization Server. The Node embeds the token into the registration request for node registration, and registry heartbeat.
293+
294+
### Authorization Server Metadata
295+
296+
Clients, such as NMOS Broadcast Controller, Registry and Node locate the Authorization API endpoints via the DNS-SD Authorization Server discovery. The Authorization Server has a well-known endpoint for returning the server metadata. Details are shown in the client registration sequence diagram.
297+
298+
### Client Registration
299+
300+
Clients must be registered to the Authorization Server before using the ``OAuth 2.0`` protocol. In the event of successful registration, the Authorization Server will return the client_id for the public client and client_id and client_secret for the confidential client. It is, however, important that the public client which is using the Authorization Code Flow must register one or more redirect URLs for security purposes, which allows Authorization Server to ensure any authorization request is genuine and only the valid redirect URLs are used for returning the authorization code. While using Client Credentials Flow, Private Key JWT can be used for client authentication with extra security.
301+
302+
See the client registration sequence diagram below on how an NMOS Node is registered to the Authorization Server.
303+
304+
![Client-Registration](images/Authorization-Client-Registration.png)
305+
306+
### Access Token
307+
308+
There are a number of ways to request the access token, it is based on the type of authorization grant. The grant type depends on the location and the nature of the client involved in obtaining the access token. A number of grant types are defined in ``OAuth 2.0``. NMOS is focused on using the following types, the ``Authorization Code Grant`` and the ``Client Credentials Grant``.
309+
310+
#### Authorization Code Grant
311+
312+
This is the most recommended type, it should be used if the client has a web browser, such as the Broadcast Controller. An Authorization code is returned by the Authorization Server via the client's redirect URI. The client can then exchange it for a time-limited access token, and renew it with the refresh token.
313+
314+
For public clients, there is a potential security risk with an attacker hijacking the Authorization code. To prevent that ``Proof Key for Code Exchange`` (PKCE) is used to further secure the Authorization Code Flow.
315+
316+
Step 1. create a high entropy cryptographic random string, ``code_verifier``.
317+
318+
Step 2. convert the ``code_verifier`` to ``code_challenge`` with the following logic:
319+
320+
```
321+
code_challenge=BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
322+
```
323+
324+
Step 3. includes the ``code_challege`` and the hashing method used to generate the ``code_challenge`` in the authorization code request.
325+
326+
Step 4. send the ``code_verifier`` and the ``authorization code`` for exchanging the token. The Authorization Server uses the ``code_verifier`` to recreate the matching ``code_challenge`` to verify the client.
327+
328+
![Authorization-Code-Flow](images/Authorization-Code-Flow.png)
329+
330+
#### Client Credentials Grant
331+
332+
This type of authorization is used by clients to obtain the access token without user authorization, such as a hardware NMOS Node which has no web browser supported. To gain extra security the ``Private Key JWT`` is used by the NMOS Node as a form of client authentication by the Authorization Server before handing out the token.
333+
334+
![Client-Credentials-Flow](images/Authorization-Client-Credentials-Flow.png)
335+
336+
### Authorization Server Public Keys
337+
338+
The public keys are used by the Resource(s) Server for validating the access token before giving access right to it's protected APIs. The client must periodically poll the Authorization Server's ``public keys``, typically once every hour. In the event, that the Authorization Server is no longer available, the last fetched public keys will be kept in use until the Authorization Server connection is restored.
339+
340+
The token validation is done by re-generating the matching token signature by signing the token header and the token payload.
341+
342+
![Public-Keys](images/Authorization-Public-Keys.png)
343+
344+
### Authorization behaviour
345+
346+
> [nmos/authorization_behaviour.cpp](../../Development/nmos/authorization_behaviour.cpp)
347+
348+
The required Authorization behaviour includes:
349+
350+
- discovery of the Authorization Server
351+
- fetch Authorization Server metadata for Authorization Server endpoints and supported features
352+
- Authorization client registration
353+
- fetch Authorization Server public keys
354+
- fetch Bearer token for accessing protected endpoints
355+
356+
The state machine implemented by the ```nmos::experimental::authorization_behaviour_thread``` is shown below:
357+
358+
![Authorization-behaviour](images/Authorization-behaviour.png)
359+
360+
### Missing public keys to validate the access token
361+
362+
> [nmos/authorization_handlers.cpp](../../Development/nmos/authorization_handlers.cpp)
363+
> [nmos/authorization_behaviour.cpp](../../Development/nmos/authorization_behaviour.cpp)
364+
365+
If no matching public key is available to validate the incoming access token. The validation handler will trigger the authorization token issuer thread to fetch and cache the public keys from this token's issuer, which will then be possible to validate any token issued by this issuer.
366+
367+
The state machine implemented by the ```nmos::experimental::validate_authorization_handler``` and the ```nmos::experimental::authorization_token_issuer_thread``` are shown below:
368+
369+
![missing-public-keys](images/Authorization-Missing-Public-Keys.png)
370+
371+
In addition, if the Authorization behaviour thread is excluded, the NMOS Node/Registry can easily be configured as a headless ``OAuth 2.0`` enabled device. Where the access token will be fed in externally via the ```nmos::experimental::get_authorization_bearer_token_handler``` callback and the access token validation will be happening on the ```nmos::experimental::validate_authorization_token_handler``` callback.
372+
373+
### OAuth 2.0 Node Registration Example
374+
375+
Following is an overview of how an ``OAuth 2.0`` NMOS Node registers to an ``OAuth 2.0`` enabled NMOS Registry.
376+
377+
![Node-Registration](images/Authorization-Node-Registration.png)

Documents/Dependencies.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ More details are given below.
1414
- For JSON Schema validation, the [Modern C++ JSON schema validator](https://github.com/pboettch/json-schema-validator) library, which is implemented on top of [JSON for Modern C++](https://github.com/nlohmann/json)
1515
- For DNS Service Discovery (DNS-SD), the [Bonjour SDK](https://developer.apple.com/bonjour/) on Windows, and on Linux either [Avahi](https://www.avahi.org/) or Apple's [mDNSResponder](https://opensource.apple.com/tarballs/mDNSResponder/) (another name for Bonjour)
1616
- The [Catch](https://github.com/philsquared/Catch) automated test framework, for unit testing
17+
- The [C++ JSON Web Token validator](https://github.com/Thalhammer/jwt-cpp) header only library
1718

1819
## Preparation
1920

@@ -309,6 +310,17 @@ Notes:
309310
A copy of the single header version (v1.10.0) is included in the [third_party/catch](../Development/third_party/catch) directory.
310311
No installation is necessary.
311312
313+
### C++ JSON Web Token validator
314+
315+
If using Conan, this section can be skipped.
316+
<details>
317+
<summary>If not using Conan...</summary>
318+
319+
A copy of the source code necessary to use this library is included in the [third_party/jwt-cpp](../Development/third_party/jwt-cpp) directory.
320+
No installation is necessary.
321+
322+
</details>
323+
312324
# What Next?
313325
314326
These [instructions](Getting-Started.md) explain how to build nmos-cpp itself, run the test suite, and try out the registry and node applications.
386 KB
Loading
402 KB
Loading
431 KB
Loading
378 KB
Loading
393 KB
Loading
363 KB
Loading
105 KB
Loading

0 commit comments

Comments
 (0)