From ea732dac3e6d27f2d6123ce96406da82b9a54aeb Mon Sep 17 00:00:00 2001 From: lo-simon Date: Thu, 4 Jan 2024 12:04:31 +0000 Subject: [PATCH] Add authorization support to IS-12 --- Development/nmos-cpp-node/main.cpp | 2 +- Development/nmos/control_protocol_ws_api.cpp | 8 ++++++-- Development/nmos/control_protocol_ws_api.h | 7 ++++--- Development/nmos/node_server.cpp | 2 +- Development/nmos/scope.h | 3 +++ 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Development/nmos-cpp-node/main.cpp b/Development/nmos-cpp-node/main.cpp index d70a45958..b08ba5ef8 100644 --- a/Development/nmos-cpp-node/main.cpp +++ b/Development/nmos-cpp-node/main.cpp @@ -118,7 +118,7 @@ int main(int argc, char* argv[]) #endif // only implement communication with Authorization server if IS-10/BCP-003-02 is required -// cf. preprocessor conditions in nmos::make_node_api, nmos::make_connection_api, nmos::make_events_api, nmos::make_channelmapping_api, make_events_ws_validate_handler +// cf. preprocessor conditions in nmos::make_node_api, nmos::make_connection_api, nmos::make_events_api, nmos::make_channelmapping_api, make_events_ws_validate_handler, make_control_protocol_ws_validate_handler nmos::experimental::authorization_state authorization_state; if (nmos::experimental::fields::server_authorization(node_model.settings)) { diff --git a/Development/nmos/control_protocol_ws_api.cpp b/Development/nmos/control_protocol_ws_api.cpp index b6bc3f476..890efe761 100644 --- a/Development/nmos/control_protocol_ws_api.cpp +++ b/Development/nmos/control_protocol_ws_api.cpp @@ -50,9 +50,9 @@ namespace nmos // IS-12 Control Protocol WebSocket API - web::websockets::experimental::listener::validate_handler make_control_protocol_ws_validate_handler(nmos::node_model& model, slog::base_gate& gate_) + web::websockets::experimental::listener::validate_handler make_control_protocol_ws_validate_handler(nmos::node_model& model, nmos::experimental::ws_validate_authorization_handler ws_validate_authorization, slog::base_gate& gate_) { - return [&model, &gate_](web::http::http_request req) + return [&model, ws_validate_authorization, &gate_](web::http::http_request req) { nmos::ws_api_gate gate(gate_, req.request_uri()); @@ -60,6 +60,10 @@ namespace nmos // Clients SHOULD use the "Authorization Request Header Field" method. // Clients MAY use a "URI Query Parameter". // See https://tools.ietf.org/html/rfc6750#section-2 + if (ws_validate_authorization) + { + if (!ws_validate_authorization(req, nmos::experimental::scopes::ncp)) { return false; } + } // For now just return true const auto& ws_ncp_path = req.request_uri().path(); diff --git a/Development/nmos/control_protocol_ws_api.h b/Development/nmos/control_protocol_ws_api.h index 1d8052cd8..1bf3c556a 100644 --- a/Development/nmos/control_protocol_ws_api.h +++ b/Development/nmos/control_protocol_ws_api.h @@ -3,6 +3,7 @@ #include "nmos/control_protocol_handlers.h" #include "nmos/websockets.h" +#include "nmos/ws_api_utils.h" namespace slog { @@ -13,15 +14,15 @@ namespace nmos { struct node_model; - web::websockets::experimental::listener::validate_handler make_control_protocol_ws_validate_handler(nmos::node_model& model, slog::base_gate& gate); + web::websockets::experimental::listener::validate_handler make_control_protocol_ws_validate_handler(nmos::node_model& model, nmos::experimental::ws_validate_authorization_handler ws_validate_authorization, slog::base_gate& gate); web::websockets::experimental::listener::open_handler make_control_protocol_ws_open_handler(nmos::node_model& model, nmos::websockets& websockets, slog::base_gate& gate); web::websockets::experimental::listener::close_handler make_control_protocol_ws_close_handler(nmos::node_model& model, nmos::websockets& websockets, slog::base_gate& gate); web::websockets::experimental::listener::message_handler make_control_protocol_ws_message_handler(nmos::node_model& model, nmos::websockets& websockets, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, nmos::get_control_protocol_method_handler get_control_protocol_method, nmos::control_protocol_property_changed_handler property_changed, slog::base_gate& gate); - inline web::websockets::experimental::listener::websocket_listener_handlers make_control_protocol_ws_api(nmos::node_model& model, nmos::websockets& websockets, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, nmos::get_control_protocol_method_handler get_control_protocol_method, nmos::control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + inline web::websockets::experimental::listener::websocket_listener_handlers make_control_protocol_ws_api(nmos::node_model& model, nmos::websockets& websockets, nmos::experimental::ws_validate_authorization_handler ws_validate_authorization, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, nmos::get_control_protocol_method_handler get_control_protocol_method, nmos::control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { return{ - nmos::make_control_protocol_ws_validate_handler(model, gate), + nmos::make_control_protocol_ws_validate_handler(model, ws_validate_authorization, gate), nmos::make_control_protocol_ws_open_handler(model, websockets, gate), nmos::make_control_protocol_ws_close_handler(model, websockets, gate), nmos::make_control_protocol_ws_message_handler(model, websockets, get_control_protocol_class, get_control_protocol_datatype, get_control_protocol_method, property_changed, gate) diff --git a/Development/nmos/node_server.cpp b/Development/nmos/node_server.cpp index 3cb4836d0..5cb290d50 100644 --- a/Development/nmos/node_server.cpp +++ b/Development/nmos/node_server.cpp @@ -78,7 +78,7 @@ namespace nmos { if (control_protocol_ws_port == events_ws_port) throw std::runtime_error("Same port used for events and control protocol websockets are not supported"); auto& control_protocol_ws_api = node_server.ws_handlers[{ {}, control_protocol_ws_port }]; - control_protocol_ws_api.first = nmos::make_control_protocol_ws_api(node_model, control_protocol_ws_api.second, node_implementation.get_control_protocol_class, node_implementation.get_control_protocol_datatype, node_implementation.get_control_protocol_method, node_implementation.control_protocol_property_changed, gate); + control_protocol_ws_api.first = nmos::make_control_protocol_ws_api(node_model, control_protocol_ws_api.second, node_implementation.ws_validate_authorization, node_implementation.get_control_protocol_class, node_implementation.get_control_protocol_datatype, node_implementation.get_control_protocol_method, node_implementation.control_protocol_property_changed, gate); } // Set up the listeners for each HTTP API port diff --git a/Development/nmos/scope.h b/Development/nmos/scope.h index 1f3999531..25d65004e 100644 --- a/Development/nmos/scope.h +++ b/Development/nmos/scope.h @@ -24,6 +24,8 @@ namespace nmos const scope events{ U("events") }; // IS-08 const scope channelmapping{ U("channelmapping") }; + // IS-12 + const scope ncp{ U("ncp") }; } inline utility::string_t make_scope(const scope& scope) @@ -40,6 +42,7 @@ namespace nmos if (scopes::netctrl.name == scope) { return scopes::netctrl; } if (scopes::events.name == scope) { return scopes::events; } if (scopes::channelmapping.name == scope) { return scopes::channelmapping; } + if (scopes::ncp.name == scope) { return scopes::ncp; } return{}; } }