gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/README.md (about)

     1  # Interface policy
     2  
     3  ## Plug and slot rules
     4  
     5  Declarative rules are used to control what plugs or slots a snap is
     6  allowed to use, and if a snap is allowed to use a plug/slot, what other
     7  slots/plugs can connect to that plug/slot on this snap.
     8  
     9  These rules are declared as a map which has 6 possible keys:
    10  
    11  - allow-installation
    12  - deny-installation
    13  - allow-connection
    14  - deny-connection
    15  - allow-auto-connection
    16  - deny-auto-connection
    17  
    18  Each of these keys can either have a static value of true/false or can be a
    19  more complex object/list which is “evaluated” by snapd on a device to
    20  determine the actual value, be it true or false.
    21  
    22  
    23  ### Base declaration and snap declarations
    24  
    25  The rules defined in the snapd interfaces source code (via setting
    26  `commonInterface.baseDeclarationSlots/Plugs`) form the
    27  “base declaration” and can be overridden by per-snap rules in the
    28  snap store published via the per-snap `snap-declaration` assertions,
    29  which make it possible for a store to alter the policy hardcoded in
    30  snapd. For example, a store assertion is typically used to grant
    31  auto-connection to some plugs of a specific application where this is
    32  deemed reasonable or safe (such as auto-connecting the `camera`
    33  interface in a web-streaming application).
    34  
    35  ### Basic evaluation and precedence
    36  
    37  The default value of the `allow-*` keys when not otherwise specified is `true`
    38  and the default value of `deny-*` keys when not otherwise specified is `false`.
    39  Matching `deny-*` constraints override/take precedence over `allow-*`
    40  constraints specified in the same declaration. The order of evaluation of rules
    41  is the following (execution stops as soon as a matching rule is found, meaning
    42  that the topmost elements in this list have higher priority):
    43  
    44  - `deny-*` keys in plug snap-declaration rule
    45  - `allow-*` keys in plug snap-declaration rule
    46  - `deny-*` keys in slot snap-declaration rule
    47  - `allow-*` keys in slot snap-declaration rule
    48  - `deny-*` keys in plug base-declaration rule
    49  - `allow-*` keys in plug base-declaration rule
    50  - `deny-*` keys in slot base-declaration rule
    51  - `allow-*` keys in slot base-declaration rule
    52  
    53  In other words, snap-declaration (store) rules have priority over
    54  base-declaration rules; then, plug rules have priority over slot rules, and
    55  finally, deny rules have priority over allow rules.
    56  
    57  
    58  ### allow-installation
    59  
    60  The `allow-installation` key is evaluated when the snap is being installed. If
    61  this evaluates to false, the snap cannot be installed if an interface plug or
    62  slot for which `allow-installation` evaluated to `false` exists in the snap. An
    63  example would be the `snapd-control` interface, which has in the
    64  base-declaration the static `allow-installation: false` rule for plugs:
    65  
    66      snapd-control:
    67        allow-installation: false
    68        deny-auto-connection: true
    69  
    70  If a snap does not plug `snapd-control` then this rule does not apply, but if
    71  the snap does declare a `snapd-control` plug and there are no assertions in the
    72  store for this snap about allowing `snapd-control`, then snap installation will
    73  fail.
    74  
    75  Snap interfaces that have `allow-installation` set to `false` for their plugs
    76  in the base-declaration are said to be “**super-privileged**”, meaning they
    77  cannot be used at all without a snap-declaration assertion.
    78  
    79  
    80  ### allow-connection
    81  
    82  The `allow-connection` key controls whether an API/manual connection
    83  is permitted at all and usually is used to ensure that only
    84  “compatible” plugs and slots are connected to each other. A great
    85  example is the content interface, where the following (abbreviated)
    86  rule from the base-declaration is used to ensure that a candidate plug
    87  and slot content interface have matching `content` attribute values:
    88  
    89      allow-connection:
    90        plug-attributes:
    91          content: $SLOT(content)
    92  
    93  This can be read as `allow-connection` evaluating to `true` only when the plug
    94  has an attribute `content` with the same value as the attribute `content` in
    95  the slot. That is to say, these plug and slots are compatible because `content`
    96  does match for the plug and slot:
    97  
    98      # in the snap providing the content:
    99      slots:
   100        foo-content:
   101          interface: content
   102          content: specific-files
   103  
   104      # in the snap consuming the content:
   105      plugs:
   106        foo-content:
   107          interface: content
   108          content: specific-files
   109  
   110  While the following plug and slots are not compatible:
   111  
   112      slots:
   113        foo-content:
   114          interface: content
   115          content: other-files
   116  
   117      plugs:
   118        foo-content:
   119          interface: content
   120          content: specific-files
   121  
   122  
   123  ### allow-auto-connection
   124  
   125  The allow-auto-connection key is the final key considered when snapd is
   126  evaluating the automatic connection of interface plugs and slots. If this key
   127  evaluates to `true`, then this plug/slot combination is considered a valid
   128  candidate for automatic connection. In this context allow-connection is ignored.
   129  
   130  An automatic connection will happen normally only if there is one single
   131  candidate combination with a slot for a given plug.
   132  
   133  
   134  ### Supported rule constraints
   135  
   136  Each of the keys seen before (`allow/deny-installation`,
   137  `allow/deny-connection`, and `allow/deny-auto-connection`) has a set of
   138  sub-keys that can be used as rules with each constraint. The authoritative
   139  place where this information comes from is inside snapd in the `asserts`
   140  package, specifically the file `ifacedecls.go` is the main place where these
   141  are defined.
   142  
   143  In `allow-connection` or `allow-auto-connection` constraints about snap type,
   144  snap ID and publisher can only be specified for the other side snap (e.g. a
   145  slot-side `allow-connection` constraint can only specify plug-snap-type,
   146  plug-snap-id, plug-snap-publisher).
   147  
   148  For the `plug-snap-type` and `slot-snap-type` rules there are 4
   149  possible values: `core`, `gadget`, `kernel`, and `app`. The `core` snap
   150  type refers to whichever snap is providing snapd on the system and
   151  therefore the system interface slots, either the `core` snap or `snapd`
   152  snap (typically `core` snap on UC16 devices, `snapd` snap on UC18+
   153  systems, and either on classic systems depending on re-exec logic).
   154  
   155  The `on-store`, `on-brand`, and `on-model` rules are not generally hardcoded in
   156  the snapd interfaces, but are specified in store assertions; they are known as
   157  “device context constraints” and are primarily used to ensure that a given
   158  rule only applies to a device with a serial assertion (and thus model
   159  assertion) from a given brand. This is because if the assertion and snap from a
   160  brand store were copied to a non-branded device, the assertion could still be
   161  acknowledged by the device and the snap installed, but the assertion would not
   162  operate, and snap connections would not take place as they do on the branded
   163  device.
   164  
   165  The `plug-names` and `slot-names` rules are also only used in store assertions.
   166  They refer to the naming of a plug or slot when that slot is scoped globally
   167  with a name other than the generic interface name.
   168  For example this assertion:
   169  
   170      plugs:
   171        gpio:
   172          allow-auto-connection:
   173            slot-names: [ gpio1 ]
   174            plug-names: [ gpio-red-led ]
   175  
   176  only allows the plugging snap to have its plug named `gpio-red-led`
   177  auto-connected to a gpio slot named `gpio1`.
   178  
   179  
   180  ### Rule evaluation
   181  
   182  #### Greedy connection / single slot rule
   183  
   184  The first rule about whether an automatic connection happens between a plug and
   185  a slot has to do with “arity” or how many slots a given plug is being
   186  considered to connect to and vice versa. This is expressed with the
   187  `slots-per-plug` and `plugs-per-slot` rules, with the default value of
   188  `plugs-per-slot` being “`*`” meaning any number of plugs can be connected to a
   189  specific slot. The default value of `slots-per-plug` is “`1`”, however, meaning that a
   190  plug can in general without a special snap-declaration only automatically
   191  connect to one slot. All that is to say, if there are multiple candidate slots,
   192  in the default case a plug will auto-connect to neither of them and
   193  snapd will issue a warning.
   194  
   195  See also [this forum
   196  post](https://forum.snapcraft.io/t/plug-slot-declaration-rules-greedy-plugs/12438)
   197  which was written when this logic was first implemented.
   198  
   199  
   200  #### Maps and Lists
   201  
   202  The next rule about evaluating snap-declaration assertions is that maps are
   203  treated as logical ANDs where each key in the map must individually evaluate to
   204  `true` and lists are treated as logical ORs where only one of the elements of
   205  the list must evaluate to `true`. With the following example assertion,
   206  order
   207  for the `serial-port` plug in this snap to auto-connect, either the first
   208  element of the list must evaluate to `true` or the second element of the list
   209  must evaluate to `true` (or they could both theoretically evaluate to `true`,
   210  but this is impossible in practice since the slots can only come from gadgets
   211  and so to match both the system would have to have two gadget snaps installed
   212  simultaneously which is impossible).
   213  
   214      plugs:
   215        serial-port:
   216          allow-auto-connection:
   217            -
   218              on-store:
   219                - my-app-store
   220              plug-names:
   221                - serial-rf-nic
   222              slot-attributes:
   223                path: /dev/serial-port-rfnic
   224              slot-names:
   225                - serial-rf-nic
   226              slot-snap-id:
   227                - Cx4J8ADDq8xULNaAjO7mQid75ru4rObB
   228            -
   229              on-store:
   230                - my-app-store
   231              plug-names:
   232                - serial-rf-nic
   233              slot-attributes:
   234                path: /dev/serial-port-rfnic
   235              slot-names:
   236                - serial-rf-nic
   237              slot-snap-id:
   238                - WabnwLoV48BCMj8NoOetmdxFFMxDsPGb
   239  
   240  For the first element of the allow-auto-connection list to evaluate to
   241  `true`, the following things must be true:
   242  
   243  - The device must be on a brand device in `my-app-store` AND
   244  - The plug name must be `serial-rf-nic` AND
   245  - The slot name must be `serial-rf-nic` AND
   246  - The slot must declare an attribute, `path`, with the value
   247    `/dev/serial-port-rfnic` AND
   248  - The slot must come from a snap with a snap ID of
   249    `Cx4J8ADDq8xULNaAjO7mQid75ru4rObB`
   250  
   251  The above is also true for the second element of the allow-auto-connection list.
   252  
   253  An equivalent way to write an assertion that works in exactly the same way would be:
   254  
   255      plugs:
   256        serial-port:
   257          allow-auto-connection:
   258            on-store:
   259              - my-app-store
   260            plug-names:
   261              - serial-rf-nic
   262            slot-attributes:
   263              path: /dev/serial-port-rfnic
   264            slot-names:
   265              - serial-rf-nic
   266            slot-snap-id:
   267              - Cx4J8ADDq8xULNaAjO7mQid75ru4rObB
   268              - WabnwLoV48BCMj8NoOetmdxFFMxDsPGb
   269  
   270  The chief difference here is that instead of having a list of two maps, we
   271  instead have a single map, and the key which changes for the two gadgets is the
   272  `slot-snap-id` which now has two values in a list. In this case, the slot snap
   273  ID must be one of the snap IDs in the list in order for the `slot-snap-id` rule
   274  to evaluate to true. So the following things must be true:
   275  
   276  - The device must be on a brand device in `my-app-store` AND
   277  - The plug name must be `serial-rf-nic` AND
   278  - The slot-name must be `serial-rf-nic` AND
   279  - The slot must declare an attribute, `path`, with the value
   280    `/dev/serial-port-rfnic` AND
   281  - The slot must come from a snap with a snap ID of any of the following elements:
   282    - `Cx4J8ADDq8xULNaAjO7mQid75ru4rObB`, OR
   283    - `WabnwLoV48BCMj8NoOetmdxFFMxDsPGb`
   284  
   285  Lists and maps can also be used as values for attributes under
   286  plug/slot-attributes constraints. A map will match only if the attribute value
   287  contains all the entries in the constraints map with the same values (extra
   288  attribute elements are ignored).
   289  A list will match against a non-list attribute value if the value matches any
   290  of the list elements. A list will match against a list attribute value if all
   291  the elements in the attribute list value in turn match something in the list.
   292  This means, for example, a constraint list of value constraints will match a list
   293  of attribute scalars if the two groups of values match as a set (order doesn't
   294  matter).
   295  
   296  
   297  #### Attribute constraints and special matches and variables
   298  
   299  Plug/slot-attributes string value constraints are interpreted as regexps
   300  (wrapped implicitly in `^$` anchors), unless they are one of the special forms
   301  starting with `$`.
   302  
   303  The special forms starting with `$` currently consist of:
   304  
   305  - `$SLOT_PUBLISHER_ID`, `$PLUG_PUBLISHER_ID`: these can be specified in the
   306    `plug-publisher-id` and `slot-publisher-id` constraints respectively and are
   307    used from the plug side and slot side of a declaration to refer to the
   308    publisher-id of the other side of the connection.
   309  - `$PLUG()`, `$SLOT()`: similar to the above, but used in the `plug-attributes`
   310    and `slot-attributes` constraints for specifying attributes instead of
   311    publisher-ids.
   312  - `$MISSING`: used in the `plug-attributes` and `slot-attributes` constraints
   313    to match when the attribute set to `$MISSING` is not specified in the snap.
   314  
   315  For example, these features are used in the base-declaration for the `content`
   316  interface to express that a connection is only allowed when the attribute value
   317  of the verbatim “content” attribute on the slot side is the same as the plug
   318  side and that auto-connection should only take place by default when the plug
   319  publisher ID is the same as the slot publisher ID (unless this is overridden by
   320  a store assertion):
   321  
   322      content:
   323        allow-installation:
   324          slot-snap-type:
   325            - app
   326            - gadget
   327        allow-connection:
   328          plug-attributes:
   329            content: $SLOT(content)
   330        allow-auto-connection:
   331          plug-publisher-id:
   332            - $SLOT_PUBLISHER_ID
   333          plug-attributes:
   334            content: $SLOT(content)
   335