From 92d412908ef3a86ec583ab88b7ad5f789590a697 Mon Sep 17 00:00:00 2001 From: Nirenjan Krishnan Date: Mon, 28 Oct 2019 14:36:56 -0700 Subject: [PATCH 1/9] Add Docker to Host communication Design document (cherry picked from commit 0a6da10630e09c4d626ace1486a529f8b98a65b3) --- doc/mgmt/Docker to Host communication.md | 173 +++++++++++++++++++++ doc/mgmt/images/docker-to-host-service.svg | 1 + 2 files changed, 174 insertions(+) create mode 100644 doc/mgmt/Docker to Host communication.md create mode 100644 doc/mgmt/images/docker-to-host-service.svg diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md new file mode 100644 index 00000000000..e96850bac02 --- /dev/null +++ b/doc/mgmt/Docker to Host communication.md @@ -0,0 +1,173 @@ +# Feature Name +Docker to Host communication + +# High Level Design Document +#### Rev 0.1 + +# Table of Contents + * [List of Tables](#list-of-tables) + * [Revision](#revision) + * [About This Manual](#about-this-manual) + * [Scope](#scope) + * [Definition/Abbreviation](#definitionabbreviation) + +# List of Tables +[Table 1: Abbreviations](#table-1-abbreviations) + +# Revision +| Rev | Date | Author | Change Description | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.1 | 10/28/2019 | Nirenjan Krishnan | Initial version | + +# About this Manual +This document provides general information about the Docker to Host +communication feature in SONiC. + +# Scope +This document describes the high level design of Docker to Host communication. +This describes the infrastructure provided by the feature, and example usage, +however, it does not describe the individual host-specific features. + +# Definition/Abbreviation + +### Table 1: Abbreviations +| **Term** | **Meaning** | +|--------------------------|-------------------------------------| +| XYZ | Term description | + +# 1 Feature Overview + +The management framework runs within a Docker container, and performs actions +translating the user CLIs or REST requests to actions. Most of these actions +perform some operation on the Redis database, but some of them require +operations to be done on the host, i.e., outside the container. This document +describes the host server, and translib API that are used to communicate between +the Docker container and the host. + + +## 1.1 Requirements + +### 1.1.1 Functional Requirements + +* The SONiC Management Framework and Telemetry containers must be able to issue + requests to the host, and return the responses from the host. +* The individual applications that need access to the host must be able to + create a host module and easily issue requests and get responses back from the + host. +* The host communication API shall be available in Translib, and shall provide + both synchronous and asynchronous communication methods. + +### 1.1.2 Configuration and Management Requirements + +N/A + +### 1.1.3 Scalability Requirements + +N/A + +### 1.1.4 Warm Boot Requirements + +N/A + +## 1.2 Design Overview +### 1.2.1 Basic Approach + +The code will extend the existing Translib modules to provide a D-Bus based +query API to issue requests to the host. The host service will be a Python based +application which listens on known D-Bus endpoints. + +The individual app modules can extend the host service by providing a small +Python snippet that will register against their application endpoint. + +### 1.2.2 Container + +SONiC Management Framework, gNMI Telemetry containers + +### 1.2.3 SAI Overview + +N/A + +# 2 Functionality +## 2.1 Target Deployment Use Cases + +All deployments + +## 2.2 Functional Description + +This feature enables applications such as image management, ZTP, etc. to issue +requests to the host to perform actions such as image install, ZTP +enable/disable, etc. + +# 3 Design +## 3.1 Overview + +The feature extends the SONiC management framework to add a D-Bus service on the +host. This service will register against a known endpoint, and will service +requests to the endpoint. Application modules will add snippets to the host +service, which will automatically register their endpoints, and the app module +in the container can use the APIs provided in Translib to send the request to +the host, and either wait for the response (if the request was synchronous), or +receive a channel and wait for the request to return the response on the +channel (asynchronous request). + +## 3.2 DB Changes +### 3.2.1 CONFIG DB +N/A +### 3.2.2 APP DB +N/A +### 3.2.3 STATE DB +N/A +### 3.2.4 ASIC DB +N/A +### 3.2.5 COUNTER DB +N/A + +## 3.3 Switch State Service Design +### 3.3.1 Orchestration Agent +N/A +### 3.3.2 Other Process +N/A +## 3.4 SyncD +N/A +## 3.5 SAI +N/A + +## 3.6 User Interface +### 3.6.1 Data Models +N/A +### 3.6.2 CLI +#### 3.6.2.1 Configuration Commands +N/A +#### 3.6.2.2 Show Commands +N/A +#### 3.6.2.3 Debug Commands +N/A +#### 3.6.2.4 IS-CLI Compliance +N/A +### 3.6.3 REST API Support +N/A + +# 4 Flow Diagrams + +![](images/docker-to-host-service.svg) + +# 5 Error Handling + +The `hostQuery` and `hostQueryAsync` APIs return a standard Go `error` object, +which can be used to handle any errors that are returned by the D-Bus +infrastructure. + +# 6 Serviceability and Debug +N/A + +# 7 Warm Boot Support +N/A + +# 8 Scalability +N/A + +# 9 Unit Test +List unit test cases added for this feature including warm boot. + +# 10 Internal Design Information +N/A diff --git a/doc/mgmt/images/docker-to-host-service.svg b/doc/mgmt/images/docker-to-host-service.svg new file mode 100644 index 00000000000..1c59f585130 --- /dev/null +++ b/doc/mgmt/images/docker-to-host-service.svg @@ -0,0 +1 @@ +RESTServer/TelemetryserverHostServiceHostQuery(response)HostQueryAsync(response)WaitonChannel \ No newline at end of file From 8e58aef2e882a76ac480690e15fea25c79f37bc6 Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Mon, 16 Dec 2019 21:26:36 -0500 Subject: [PATCH 2/9] Add information on logging and security requirements. Signed-off-by: Mike Lazar (cherry picked from commit e3fe0cf591a5dafc65c6268e1c21078b6ee6021d) --- doc/mgmt/Docker to Host communication.md | 31 +++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index e96850bac02..30517957819 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -18,6 +18,9 @@ Docker to Host communication | Rev | Date | Author | Change Description | |:---:|:-----------:|:------------------:|-----------------------------------| | 0.1 | 10/28/2019 | Nirenjan Krishnan | Initial version | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.2 | 12/16/2019 | Mike Lazar | Add details about architecture | + # About this Manual This document provides general information about the Docker to Host @@ -31,9 +34,9 @@ however, it does not describe the individual host-specific features. # Definition/Abbreviation ### Table 1: Abbreviations -| **Term** | **Meaning** | -|--------------------------|-------------------------------------| -| XYZ | Term description | +| **Term** | **Meaning** | +|--------------------------|---------------------------------------------------| +| D-Bus | Desktop Bus: https://en.wikipedia.org/wiki/D-Bus | # 1 Feature Overview @@ -56,6 +59,9 @@ the Docker container and the host. host. * The host communication API shall be available in Translib, and shall provide both synchronous and asynchronous communication methods. +* It shall be possible to configure the identity of the Linux user accounts who have access to a D-Bus socket. +* It shall be possible to configure containers in such a way that only certain containers (e.g. SONiC Mgmt.) + have access to the D-Bus socket. ### 1.1.2 Configuration and Management Requirements @@ -110,6 +116,25 @@ the host, and either wait for the response (if the request was synchronous), or receive a channel and wait for the request to return the response on the channel (asynchronous request). +The architecture of a D-Bus host service in a SONiC environment is illustrated in the diagram below: +![](images/docker-to-host-services-architecture.jpg) + +Note. The Linux D-Bus implementation uses Unix domain sockets for client to D-Bus service communications. +All containers that use D-Bus services will bind mount +(-v /var/run/dbus:/var/run/dbus:rw) the host directory where D-Bus service sockets are created. +This ensures that only the desired containers access the D-Bus host services. + +D-Bus provides a reliable communication channel between client (SONiC management container) and service (native host OS) – all actions are acknowledged and can provide return values. It should be noted that acknowledgements are important for operations such as “image upgrade” or “config-save”. In addition, D-Bus methods can return values of many types – not just ACKs. For instance, they can return strings, useful to return the output of a command. + +### 3.1.1 Security of D-Bus Communications +In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files. +This allows finer grain access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users. + +### 3.1.2 Command Logging + +It is possible to track and log the user name and the command that the user has requested. +The log record is created in the system log. + ## 3.2 DB Changes ### 3.2.1 CONFIG DB N/A From 44c5da4797e8eb8ac40ae39d9f4ddbe4b0a2f3e0 Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Mon, 16 Dec 2019 21:34:21 -0500 Subject: [PATCH 3/9] Merge pull request #1 from mikelazar/dbus-container--to-host-doc Dbus container to host doc (cherry picked from commit fdea75d02ff3c8a93cd1baff5098f28d17148c43) --- doc/mgmt/Docker to Host communication.md | 10 +++++++--- .../docker-to-host-services-architecture.jpg | Bin 0 -> 99850 bytes 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 doc/mgmt/images/docker-to-host-services-architecture.jpg diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index 30517957819..2d8d80b1e1b 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -100,9 +100,13 @@ All deployments ## 2.2 Functional Description -This feature enables applications such as image management, ZTP, etc. to issue -requests to the host to perform actions such as image install, ZTP -enable/disable, etc. +This feature enables management applications to issue +requests to the host to perform actions such as: +* image install / upgrade +* ZTP enable/disable +* initiate reboot and warm reboot using existing scripts +* create show-tech tar file using existing show-tech script +* config save/reload using existing scripts # 3 Design ## 3.1 Overview diff --git a/doc/mgmt/images/docker-to-host-services-architecture.jpg b/doc/mgmt/images/docker-to-host-services-architecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8bd31ee4f9df3b0f2fbb1e959a676f9b79abde18 GIT binary patch literal 99850 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

^?dX0= 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

&+xb1e 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 Date: Mon, 16 Dec 2019 21:37:37 -0500 Subject: [PATCH 4/9] Merge pull request #54 from mikelazar/master HLD - D-Bus Container to Host Communications (cherry picked from commit d17d2a45ab4c30ce2c13ff7eb1a1e1b943a4f987) --- doc/mgmt/Docker to Host communication.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index 2d8d80b1e1b..42dbc2b8b0c 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -19,7 +19,9 @@ Docker to Host communication |:---:|:-----------:|:------------------:|-----------------------------------| | 0.1 | 10/28/2019 | Nirenjan Krishnan | Initial version | |:---:|:-----------:|:------------------:|-----------------------------------| -| 0.2 | 12/16/2019 | Mike Lazar | Add details about architecture | +| 0.2 | 12/08/2019 | Mike Lazar | Add details about architecture | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.3 | 12/16/2019 | Mike Lazar | Add security and logging info | # About this Manual @@ -80,7 +82,7 @@ N/A The code will extend the existing Translib modules to provide a D-Bus based query API to issue requests to the host. The host service will be a Python based -application which listens on known D-Bus endpoints. +application which listens on known D-Bus endpoints.https://en.wikipedia.org/wiki/D-Bus The individual app modules can extend the host service by providing a small Python snippet that will register against their application endpoint. From f972ba1b8798c87bcd780be5f46a984157f46475 Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Sun, 9 Feb 2020 13:30:22 -0500 Subject: [PATCH 5/9] Address security and versioning questions. Signed-off-by: Mike Lazar --- doc/mgmt/Docker to Host communication.md | 48 +++++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index 42dbc2b8b0c..b92985c7074 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -22,6 +22,10 @@ Docker to Host communication | 0.2 | 12/08/2019 | Mike Lazar | Add details about architecture | |:---:|:-----------:|:------------------:|-----------------------------------| | 0.3 | 12/16/2019 | Mike Lazar | Add security and logging info | +|:---:|:-----------:|:------------------:|-----------------------------------| +| 0.4 | 02/07/2020 | Mike Lazar | More information about security | +|:---:|:-----------:|:------------------:|-----------------------------------| + # About this Manual @@ -133,14 +137,54 @@ This ensures that only the desired containers access the D-Bus host services. D-Bus provides a reliable communication channel between client (SONiC management container) and service (native host OS) – all actions are acknowledged and can provide return values. It should be noted that acknowledgements are important for operations such as “image upgrade” or “config-save”. In addition, D-Bus methods can return values of many types – not just ACKs. For instance, they can return strings, useful to return the output of a command. ### 3.1.1 Security of D-Bus Communications -In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files. -This allows finer grain access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users. +In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files, for defining security policies. This allows finer grain access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users. This is achieved by using the "Host Service" configuration file: +/etc/dbus-1/system.d/org.sonic.hostservice.conf + +For instance, assuming that the rest-service provided by the SONiC management framework is executed as a system user ("mgmtuser"), the configuration can allow this user access to all Host Services: +


+  
+    
+    
+  
+
+Assuming that the telemetry service is executed as a "telemetry" system user, that account may only be allowed access to a restricted set of services, and denied access to all others (e.g. ztp, configuration save/restore): + +

+  
+    
+    
+    
+    
+  
+
+ +Note. Furthermore, D-Bus allows security policies to be set per Linux user group as well: +

+  
+    
+    
+  
+
+ +

+  
+    
+    
+    
+    
+  
+
+ ### 3.1.2 Command Logging It is possible to track and log the user name and the command that the user has requested. The log record is created in the system log. +### 3.1.3 Backwards Compatibility and Upgrades + +D-Bus provides a means ("introspection") for client applications to query the objects and methods that service APIs provide. This allows client applications (e.g. management and telemetry containers) and services (D-Bus host service) to be upgraded independently. The client applications will query the APIs provided by the D-Bus Host Service, and adapt to the available functionality of the Host Service. + ## 3.2 DB Changes ### 3.2.1 CONFIG DB N/A From c9c5d6eb7e453cb0bbad83fb5a89e9d32e2d439f Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Thu, 5 Mar 2020 10:25:13 -0500 Subject: [PATCH 6/9] Update Docker to Host communication.md Add extra D-Bus security info --- doc/mgmt/Docker to Host communication.md | 53 +++++++++--------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index b92985c7074..f301841b220 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -2,7 +2,7 @@ Docker to Host communication # High Level Design Document -#### Rev 0.1 +#### Rev 0.5 # Table of Contents * [List of Tables](#list-of-tables) @@ -25,6 +25,9 @@ Docker to Host communication |:---:|:-----------:|:------------------:|-----------------------------------| | 0.4 | 02/07/2020 | Mike Lazar | More information about security | |:---:|:-----------:|:------------------:|-----------------------------------| +| 0.5 | 03/05/2020 | Mike Lazar | More D-Bus security info, | +| | | | and fixed formatting | +|:---:|:-----------:|:------------------:|-----------------------------------| @@ -117,13 +120,10 @@ requests to the host to perform actions such as: # 3 Design ## 3.1 Overview -The feature extends the SONiC management framework to add a D-Bus service on the -host. This service will register against a known endpoint, and will service -requests to the endpoint. Application modules will add snippets to the host -service, which will automatically register their endpoints, and the app module -in the container can use the APIs provided in Translib to send the request to -the host, and either wait for the response (if the request was synchronous), or -receive a channel and wait for the request to return the response on the +The feature extends the SONiC management framework to add a D-Bus service on the host. This service will register against a known endpoint, and will service requests to the endpoint. Application modules will add "applets" to the host +service, which will automatically register their endpoints (D-Bus objects and methods). + +The client application module in a container (e.g. management or telemetry) can use the APIs provided in Translib to send the request to the host - essentially, make a (remote) D-Bus method call, and either wait for the response (if the request was synchronous), or receive a channel and wait for the request to return the response on the channel (asynchronous request). The architecture of a D-Bus host service in a SONiC environment is illustrated in the diagram below: @@ -140,40 +140,27 @@ D-Bus provides a reliable communication channel between client (SONiC management In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files, for defining security policies. This allows finer grain access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users. This is achieved by using the "Host Service" configuration file: /etc/dbus-1/system.d/org.sonic.hostservice.conf -For instance, assuming that the rest-service provided by the SONiC management framework is executed as a system user ("mgmtuser"), the configuration can allow this user access to all Host Services: -

-  
-    
-    
-  
-
-Assuming that the telemetry service is executed as a "telemetry" system user, that account may only be allowed access to a restricted set of services, and denied access to all others (e.g. ztp, configuration save/restore): +D-Bus allows security policies to be set per Linux user group or Linux user. The D-Bus framework is able to determine the user name and group of the client applications, and automatically enforces the access rules specified in the security policies. -

-  
-    
-    
-    
-    
-  
-
+For instance, assuming that the REST service provided by the SONiC management framework is executed as a system user ("mgmt") in its own group ("mgmt"), the configuration can allow this system user access to all Host Services - all objects and methods under "org.SONiC.HostService": -Note. Furthermore, D-Bus allows security policies to be set per Linux user group as well: -

-  
-    
-    
+```
+  
+    
+    
   
-
+``` + +Assuming that the telemetry service is executed as a "telemetry" system user (group "telemetry"), that account may only be allowed access to a restricted set of services ("showtech"), and denied access to all others (e.g. ztp, configuration save/restore): -

-  
+```
+  
     
     
     
     
   
-
+``` ### 3.1.2 Command Logging From 3afa3e16998d50502eca7121145b99d579297fd2 Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Fri, 17 Apr 2020 11:02:58 -0400 Subject: [PATCH 7/9] Addressed review comments Provided usage recommendations, clarified logs and security approach. --- doc/mgmt/Docker to Host communication.md | 60 ++++++++++++++++-------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index f301841b220..e62703687a4 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -1,8 +1,8 @@ # Feature Name -Docker to Host communication +Docker to Host Communications # High Level Design Document -#### Rev 0.5 +#### Rev 0.6 # Table of Contents * [List of Tables](#list-of-tables) @@ -28,6 +28,9 @@ Docker to Host communication | 0.5 | 03/05/2020 | Mike Lazar | More D-Bus security info, | | | | | and fixed formatting | |:---:|:-----------:|:------------------:|-----------------------------------| +| 0.6 | 04/15/2020 | Mike Lazar | Addressed questions about | +| | | | logging and usage recommendations | +|:---:|:-----------:|:------------------:|-----------------------------------| @@ -40,6 +43,7 @@ This document describes the high level design of Docker to Host communication. This describes the infrastructure provided by the feature, and example usage, however, it does not describe the individual host-specific features. + # Definition/Abbreviation ### Table 1: Abbreviations @@ -49,20 +53,18 @@ however, it does not describe the individual host-specific features. # 1 Feature Overview -The management framework runs within a Docker container, and performs actions -translating the user CLIs or REST requests to actions. Most of these actions -perform some operation on the Redis database, but some of them require -operations to be done on the host, i.e., outside the container. This document -describes the host server, and translib API that are used to communicate between -the Docker container and the host. +This document describes a means (framework) for an application executed inside a container to securely request the execution of an operation ("action") by the host OS. The components of such framework are: +* the host services component (executed on the host OS), +* the translib API component (executed insisde a container) +This framework is intended to be used by the SONiC management and telemetry containers, but can be extended for other application containers as well. ## 1.1 Requirements ### 1.1.1 Functional Requirements -* The SONiC Management Framework and Telemetry containers must be able to issue - requests to the host, and return the responses from the host. +* The SONiC Management Framework and Telemetry (application) containers must be able to issue + requests to the host, and obtain responses to those requests from the host. * The individual applications that need access to the host must be able to create a host module and easily issue requests and get responses back from the host. @@ -87,12 +89,15 @@ N/A ## 1.2 Design Overview ### 1.2.1 Basic Approach -The code will extend the existing Translib modules to provide a D-Bus based -query API to issue requests to the host. The host service will be a Python based -application which listens on known D-Bus endpoints.https://en.wikipedia.org/wiki/D-Bus +The new code for the client application TransLib API is added to the existing Translib modules to provide a D-Bus based +API to issue requests/queries from a container based application to the host OS. + +The host service (executed as a daemon on the host OS) is a Python based +application that listens on service-specific D-Bus endpoints.https://en.wikipedia.org/wiki/D-Bus -The individual app modules can extend the host service by providing a small -Python snippet that will register against their application endpoint. +The individual app modules extend the host service by providing a Python snippet (a "servlet") that registers against a D-Bus endpoint. New servlets can be defined and added as needed. + +The application client inside containers executes DBus methods (effectively remote procedure calls), using the DBus end-points provided by the servlets on the host OS. ### 1.2.2 Container @@ -110,17 +115,19 @@ All deployments ## 2.2 Functional Description This feature enables management applications to issue -requests to the host to perform actions such as: +requests to the host to perform "actions". For instance : * image install / upgrade -* ZTP enable/disable * initiate reboot and warm reboot using existing scripts * create show-tech tar file using existing show-tech script * config save/reload using existing scripts +In contrast to typical DB operations - CRUD (create, read, update, delete), an "action" is an operation that does not directly modify a DB record, but triggers a host OS system request instead (such as SW image install/update). +It is recommended that the "Host services" only be defined for this type of applications. + # 3 Design ## 3.1 Overview -The feature extends the SONiC management framework to add a D-Bus service on the host. This service will register against a known endpoint, and will service requests to the endpoint. Application modules will add "applets" to the host +The feature extends the SONiC management framework to add a D-Bus service on the host. This service will register against a known endpoint, and will service requests to the endpoint. Application modules will add "servlets" to the host service, which will automatically register their endpoints (D-Bus objects and methods). The client application module in a container (e.g. management or telemetry) can use the APIs provided in Translib to send the request to the host - essentially, make a (remote) D-Bus method call, and either wait for the response (if the request was synchronous), or receive a channel and wait for the request to return the response on the @@ -137,7 +144,7 @@ This ensures that only the desired containers access the D-Bus host services. D-Bus provides a reliable communication channel between client (SONiC management container) and service (native host OS) – all actions are acknowledged and can provide return values. It should be noted that acknowledgements are important for operations such as “image upgrade” or “config-save”. In addition, D-Bus methods can return values of many types – not just ACKs. For instance, they can return strings, useful to return the output of a command. ### 3.1.1 Security of D-Bus Communications -In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files, for defining security policies. This allows finer grain access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users. This is achieved by using the "Host Service" configuration file: +In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files, for defining security policies. This allows finer granularity access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users or groups. This is achieved by using the "Host Service" configuration file: /etc/dbus-1/system.d/org.sonic.hostservice.conf D-Bus allows security policies to be set per Linux user group or Linux user. The D-Bus framework is able to determine the user name and group of the client applications, and automatically enforces the access rules specified in the security policies. @@ -166,6 +173,21 @@ Assuming that the telemetry service is executed as a "telemetry" system user (gr ### 3.1.2 Command Logging It is possible to track and log the user name and the command that the user has requested. +This can be achieved by calling the function: dbus_bus_get_unix_user(), which returns the user id of the client application. + +Note 1. Proper command auditing (all commands) for RBAC users (SONiC Management Users) is executed by the SONiC management Framework. + +Note 2. In fact, the group and user account of DBus commands executed by a DBus service is generally implicit, based on the access policy rules, for instance: +``` + + + + +``` + +The host services framework will implement a generic logging framework, which automatically log all commands (DBus methods) +invoked by client applications - e.g. or telemetry or management. The same approach applies to any other client application (not just management and framework), that may use the Host Services framework. + The log record is created in the system log. ### 3.1.3 Backwards Compatibility and Upgrades From 249a9b7f4549b4261ac24867d666486af53bd858 Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Thu, 23 Apr 2020 11:51:30 -0400 Subject: [PATCH 8/9] Update Docker to Host communication.md --- doc/mgmt/Docker to Host communication.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index e62703687a4..a191ccec1ea 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -2,7 +2,7 @@ Docker to Host Communications # High Level Design Document -#### Rev 0.6 +#### Rev 0.7 # Table of Contents * [List of Tables](#list-of-tables) @@ -31,6 +31,9 @@ Docker to Host Communications | 0.6 | 04/15/2020 | Mike Lazar | Addressed questions about | | | | | logging and usage recommendations | |:---:|:-----------:|:------------------:|-----------------------------------| +| 0.7 | 04/23/2020 | Mike Lazar | Added authentication failure | +| | | | log information | +|:---:|:-----------:|:------------------:|-----------------------------------| @@ -145,7 +148,9 @@ D-Bus provides a reliable communication channel between client (SONiC management ### 3.1.1 Security of D-Bus Communications In addition to standard Linux security mechanisms for file/Unix socket access rights (read/write), D-Bus provides a separate security layer, using the D-Bus service configuration files, for defining security policies. This allows finer granularity access control to D-Bus objects and methods - D-Bus can restrict access only to certain Linux users or groups. This is achieved by using the "Host Service" configuration file: +``` /etc/dbus-1/system.d/org.sonic.hostservice.conf +``` D-Bus allows security policies to be set per Linux user group or Linux user. The D-Bus framework is able to determine the user name and group of the client applications, and automatically enforces the access rules specified in the security policies. @@ -185,11 +190,26 @@ Note 2. In fact, the group and user account of DBus commands executed by a DBus ``` -The host services framework will implement a generic logging framework, which automatically log all commands (DBus methods) +The host services framework will implement a generic logging framework, which automatically logs all commands (DBus methods) invoked by client applications - e.g. or telemetry or management. The same approach applies to any other client application (not just management and framework), that may use the Host Services framework. The log record is created in the system log. +### 3.1.2.1 Logging D-Bus Authentication Failures + +D-Bus is setup by default to log all authentication failures (security policy violations). SONiC directs authentication failures to /var/log/auth.log + +For instance, if an unauthorized user tries to execute the 'reboot' method, the following log record is generated in /var/log/auth.log: +``` +Apr 23 15:25:53.381264 sonic NOTICE dbus[387]: [system] Rejected send message, 1 matched rules; type="method_call", sender=":1.9" (uid=1000 pid=7663 comm="dbus-send --session --dest=org.SONiC.HostService -") interface="org.SONiC.HostService" member="reboot" error name="(unset)" requested_reply="0" destination="org.SONiC.HostService" (uid=0 pid=402 comm="/usr/bin/python3 -u /usr/lib/sonic_host_service/so") +``` + +Note. The client application receives an error return code: +``` +Error org.freedesktop.DBus.Error.AccessDenied +``` + + ### 3.1.3 Backwards Compatibility and Upgrades D-Bus provides a means ("introspection") for client applications to query the objects and methods that service APIs provide. This allows client applications (e.g. management and telemetry containers) and services (D-Bus host service) to be upgraded independently. The client applications will query the APIs provided by the D-Bus Host Service, and adapt to the available functionality of the Host Service. From 69bb868dec98fc05b8b046f0925ca2e89604c49a Mon Sep 17 00:00:00 2001 From: Mike Lazar Date: Wed, 27 May 2020 18:00:34 -0400 Subject: [PATCH 9/9] Update Docker to Host communication.md --- doc/mgmt/Docker to Host communication.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/mgmt/Docker to Host communication.md b/doc/mgmt/Docker to Host communication.md index a191ccec1ea..9b790584012 100644 --- a/doc/mgmt/Docker to Host communication.md +++ b/doc/mgmt/Docker to Host communication.md @@ -174,6 +174,7 @@ Assuming that the telemetry service is executed as a "telemetry" system user (gr ``` +Note. The security of the D-Bus communications is completely independent of the security (authorization and authentication) that client applications may implement separately, e.g. Role Base Access Control in the case of the SONiC Management Framework. ### 3.1.2 Command Logging