ros2 / design

Design documentation for ROS 2.0 effort
http://design.ros2.org/
Apache License 2.0
222 stars 194 forks source link

Security | Access Control Policy Format #140

Open ruffsl opened 7 years ago

ruffsl commented 7 years ago

This issue serves to track ideas for specifying the policy format to be used for access control in SROS2. Ideally this specification should be extensible enough to convey all necessary permissions or access rights, say in a traditional access control matrix where the rows are subjects/users (i.e., nodes), the columns are objects/resources (i.e., topics, services, parameters). Additionally, it would be advantageous if the format translated easily to metafiles used by other secure middleware transports (i.e., DDS Secure's builtin plugins), but is not necessarily too confirmative to inhibit being a common format among transports vinders.

Some ideal qualities for such a format may also include:

Additional, there are some aspects of the standard we may wish to decide on as well:

ruffsl commented 7 years ago

To kick start off on my own questions, I'd like to bring up some previous ideas from SROS1.

During the initial development of SROS1, I started creating an Apparmor Profile Library for ROS, as well a few base examples in it use for adding Mandatory Access Control to ROS's process runtime:

Example Apparmor Policy Profile for ROS

#include <tunables/global>
#include <tunables/ros>

/opt/ros/kinetic/bin/rosmaster {
  #include <ros/base>
  #include <ros/node>
  #include <ros/python>

  @{ROS_INSTALL_BIN}/rosmaster rix,
}

/opt/ros/kinetic/share/rospy_tutorials/001_talker_listener/listener.py {
  #include <ros/base>
  #include <ros/node>
  #include <ros/python>

  @{ROS_INSTALL_SHARE}/rospy_tutorials/001_talker_listener/listener.py r,
}

/opt/ros/kinetic/share/rospy_tutorials/001_talker_listener/talker.py {
  #include <ros/base>
  #include <ros/node>
  #include <ros/python>

  @{ROS_INSTALL_SHARE}/rospy_tutorials/001_talker_listener/talker.py r,
}

Some aspects about the Apparmor syntax I like are:

The file format for Apparmor Policy Profiles has its own style, and so it's own custom parser, but I think translates fairly well:

Example SROS policy syntax

#include global_rule
/namespace
{
  #include local_role
  resource /scope masks
}

Such a syntax incorporates few nice properties:

So for ROS1 or ROS2, the number of applicable masks could include:

Resource Mask Permission
Parameters r Read
Parameters w Write
Topics s Subscribe
Topics p Publish
Services c Call
Services x Execute

Given these, an SROS policy profile for a node named:

permits read access to the parameter:

permits publishing to topics like:

permits executing the services:

but denies everything else,
explicitly including the publishing of topics:

Example SROS policy profile

#include <ros/system>
/wheatley{,/apple}
{
  #include <ros/node>
  param /use_sim_time r,
  topic /chatter{,/**} p,
  deny topic /chatter/foo p,
  deny topic /**/e-stop p,
  service /wheatley/get_loggers x,
  service /wheatley/set_logger_level x,
}

In the above example we can see:

Some related issues I see with this includes:

ruffsl commented 7 years ago

After having a chat with @ZJohnny offline, I think we've come up with a few more refined ideas about some related issues I mentioned in my previous post.

For imports, apparmor merely adds to the subset of rules applied within the scope. I think this is quite intuitive and I see no immediate issue maintaining this behavior in SROS as well.

For inheriting context, this may be specifically useful in the case where a user would like to succinctly describe a permission in relation to the namespace of the affected node. For the SROS policy syntax, the plan so far is to bind subjects/nodes to policies that restrict access to objects/resources. This is done by globbing the node namespace to define the scope of the policy. This policy profile is eventually fully expanded before embedding it into the various metafiles used by the specific vendor or transport. So during this expansion process, we resolve the relative paths.

Example <ros/node> policy import

# Include basic node abstractions and resources needed for ros nodes

param /use_sim_time r,
service ~/get_loggers x,
service ~/set_logger_level x,
topic ~/rosout p,

Example SROS policy profile

/talker
{
  #include <ros/node>
  topic /chatter p,
}

Another interesting feature this brings up is the use of Tunables, a mechanism for tuning your configuration without having to adjust your profiles. They might also be useful, but we can hold on this and the host of other apparmor related features until we are more confident that apparmor mandatory access control syntax is what we'd like to go for.

ruffsl commented 7 years ago

For the translation of policies into metafiles, I'm still not sure how we should convey governance related attributes, such that may be used on the QOS related governance files for Secure DDS, i.e whether a topic should be encrypted or signed, etc. Another question is if they should be supported at all, or if this would be outside the scope of the generic policy syntax we sich to define in SROS.

My feeling is that this some of these plugin related features could be considered core attributes you'd want to be able to describe, such a sign or encrypt. However I'm not sure of a good boundary to determine whether an attribute is too transport specific, e.g. tags or partitions. But if the description of the security attributes is data centric, and fits well with ROS2's main target protocol, DDS, I don't think it would be to bad to enable optional rule modifiers to enable this, e.g:

/talker
{
  #include <ros/node>
  encrypt topic /foo p,
  sign topic /bar p,
}

Although, this could complicate the translation process, necessitating more contextual passing and expansion into the metafiles. For example, if a topic namespace is cited twice in two different rules, but with different modifiers, then the translation of the topic's definition into the Secure DDS governances file may be ill-defined given the contradictory occurrences. Or this could result in contradictory governance files given different node namespaces, which could be non obvious to debug.

One last idea I have is if such specific features or modifiers could be captured by a separate file, so a degree of separation between transport security and access control policy could be clearly defined, but yet enable a translation plugin that would consume both file types jointly to produce the desired custom metafiles. This somewhat already resembles the behavior of the separate governance and permission file structure in Secure DDS.