Snappy capability types and attributes

Zygmunt Krynicki zygmunt.krynicki at
Tue Nov 17 13:55:41 UTC 2015


More and more bits are landing so I've started exploring a simple
scenario. An application that need to access a device that is normally
1) not known at compile time 2) not accessible to confined snaps.

For the purpose of this idea, we'll try to write a simple program that
opens a serial ports and keeps saying "yes". The program has one piece
of configuration, the path of the serial port to open. For now I'll
silently ignore this. I have a very neat idea on how to address this
but let's take one step at a time.

The application ships without any custom security policy. Nothing
fancy is needed. For now the fact that this application can consume a
capability will not be modeled on the application developer side.
Again, baby steps.

The user installs the application and tries to run it. For now it will
just say that it is not configured since it does not know which serial
port to open. Now the magic starts to happen.

Let's use some hypothetical command line extension to snappy to create
and assign a capability

$ snappy create-cap serial-debug "Debug serial port" serial-port path=/dev/ttyS0

Here the create-capability is the new command. "serial-debug" is the
*name*, "Debug serial port" is the *label* and "serial-port" is the
type. What follows after is a set of key=value pairs that define
attributes. Here we just say that the "path" attribute should have the
value "/dev/ttyS0".

Let's take a small detour now. The idea of types is to combine the
concepts across developers , system builders and end-users. A system
builder will do the hard work to ensure that the "Debug serial port"
capability is pre-created on a system they build. A developer will do
the hard work to ensure that they can correctly use any capability of
type "serial-port". A user will do the easy task of giving the "Debug
serial port" capability to the snap they've just installed.

Attributes allow capabilities to convey information across the three
users. The developer will know how to access the serial port at
runtime. The system builder needs to put correct information there.
The user, in this example, won't have to care about this. There are
interesting ideas that I have on how the users _can_ benefit from
attributes but for now, let's not go there.

So now we have our shiny new capability. Let's assign it to our
"say-yes-over-serial-port" snap.

$ snappy assign-cap serial-debug say-yes-over-serial-port

What happens here is partially obvious, partially open to discussion.
At a fundamental level, snappy needs to remember this fact, adjust the
security system and notify the application *somehow*. The way this can
happen is open to discussion. Right now I'd like to try the most
basic, easy-to-use method that can be safely extended over time. I'd
like to add a new hook, "assign" (and unassign later, for parity).

This hook would be written by the application developer (something I
expect snapcraft parts and language specific libraries to simplify to
the point of being a one-liner) and would be in charge of remembering
the fact in a way that is meaningful to the application. Here we could
simply write a configuration file, use snappy config itself to set a
configuration item or do something else appropriate (talk to a
service, etc).

The hook would be called with extra environment variables that carry
data about the capability being assigned (or unassigned). In no
particular order, I'd like to propose

$SNAPPY_CAP_SLOT_NAME (I'll explain this later, for now you can think
of a place where the capability is being assigned within the snap)

The last of those would be defined for each of the attributes, which
are defined by types. Types would be documented (perhaps on the
developer portal) so that all the people involved would understand
what to expect out of each attribute. Types would also be versioned
but I'd like not to discuss this yet.

Back to our simple application. The "assign" hook could be written in
shell and simply do something like this:

        echo "$SNAPPY_CAP_ATTR_path" > "$SNAP_APP_DATA_PATH/file-to-open"
        exit 1

The application (or a wrapper) would read the config file mentioned
above to know which serial port to open. The unassign hook could
simply remove the file based on the same information.

I'm open to feedback to this idea and without any information to the
contrary, I will be slowly going towards that direction.

Best regards

More information about the snappy-devel mailing list