All snaps downloaded in the stable channel are confined. There is a mode, called “devmode” which sets the snap basically unconfined, meaning having all access to our system. Those should only be installed when you fully trust the developers, and throw away a great part of snaps security model (trustability in applications, which can’t touch or destroy parts they don’t have access to), but it can be convenient, at least for developers.
Let’s look at interfaces first, which are what confined snaps are using. We’ll then shortly explore devmode and what its implications are, before jumping to classic snaps.
Interfaces
Permissions are given through one or multiple interfaces. The snap plug corresponding to that interface will connect to the core slot which declares that same interface. For an easy analogy, thinks of a plug as an electrical plug, slot is what you put the plug into, and the interface is the voltage amount chosen (permissions here) which will be sent over through that interface. Better for both sides to match!
Listing interfaces
First, install the chuck-norris-webserver test snap:
$ snap install chuck-norris-webserver
Now list all available interfaces on our machine:
$ snap interfaces
Slot Plug
:bluetooth-control -
:browser-support -
:camera -
:cups-control -
:docker-support -
:firewall-control -
:fuse-support -
:gsettings -
:hardware-observe -
:home -
:kernel-module-control -
:libvirt -
:locale-control -
:log-observe -
:lxd-support -
:modem-manager -
:mount-observe -
:network chuck-norris-webserver
:network-bind chuck-norris-webserver
:network-control -
:network-manager -
:network-observe -
:network-setup-observe -
:opengl -
:optical-drive -
:ppp -
:process-control -
:pulseaudio -
:removable-media -
:screen-inhibit-control -
:snapd-control -
:system-observe -
:system-trace -
:timeserver-control -
:timezone-control -
:tpm -
:unity7 -
:upower-observe -
:x11 -
- chuck-norris-webserver:camera
This list of interfaces evolves over time. It also depends on your hardware capabilities (the gadget snap, to be precise), which defines which additional interfaces your device can expose, like GPIO devices, camera, I2C and such…
You have the confirmation here that chuck-norris-webserver
connects its network-bind plug to the network-bind slot from the core snap (slot, plug and interface names are abbreviated when they all match). This interface is used for the daemon to listen on a TCP port, which is kind of useful for a webserver to accept incoming requests on that port! Note that you didn’t have to do anything manually. The slot and plugs have been connected automatically.
It’s similar for the network interface which is needed by the command line tool to get access to the network.
On the contrary, the last line will show that the camera plug isn’t connected to the core camera slot. Indeed, some interfaces will auto-connect on install (the ones considered safe, like having access to the network), some won’t (like accessing the user’s camera). This default behavior is defined in snapd and the gadget snap of your device. You can refer to relevant tutorials on how to create a device and the gadget snap for overriding the default policy of your device.
Let’s check that in practice!
Default behavior
Running the command line tool after installing the snap gives us:
$ chuck-norris-webserver.cli
FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu Core 16.
CAMERA [FAIL]: Urgh, even Chuck doesn't have access to the camera
HOME ACCESS [FAIL]: What's happening? I can't even read your home directory.
NETWORK [OK]: Chuck Norris doesn't pair program.
Indeed, we got a Chuck Norris quote from the network. However, access to the camera and some files in the home directory was denied. It’s all making sense!
Giving access to the camera
Let’s connect our camera plug to the ubuntu core slot before rerunning the application:
$ snap connect chuck-norris-webserver:camera :camera
$ chuck-norris-webserver.cli
FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu Core 16.
HOME ACCESS [FAIL]: What's happening? I can't even read your home directory.
CAMERA [OK]: I can see you, you should smile more!
NETWORK [OK]: No statement can catch the ChuckNorrisException.
Of course, we still have access to the network and the file access is a failure. However, we can see now that the camera is accessible to our command line tool! Smile 
We can also check that via snap interfaces
:
$ snap interfaces
Slot Plug
:bluetooth-control -
:browser-support -
:camera chuck-norris-webserver
:cups-control -
[…]
:mount-observe -
:network chuck-norris-webserver
:network-bind chuck-norris-webserver
[…]
That matches our expectations!
the core snap can be abbreviated (also visible in the snap interfaces
command) with directly using “:<slot-name>
” instead of “core:
`”.
Remove permissions from a snap
Disconnecting the network plug for this snap will simply be done via:
$ snap disconnect chuck-norris-webserver:network
$ chuck-norris-webserver.cli
FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu Core 16.
NETWORK [FAIL]: I can't connect to chucknorris.io. Offering you a network-related joke then: Chuck Norris's OSI network model has only one layer - Physical.
HOME ACCESS [FAIL]: What's happening? I can't even read your home directory.
CAMERA [OK]: I can see you, you should smile more!
$ snap interfaces
[…]
- chuck-norris-webserver:network
We thus have access from the command line tool to the camera, but not to the network anymore (and still don’t have access to the home directory).
A note on multiple commands/services in the same snaps.
Our snap contains 2 elements: a services and a command. We just used the command here. You should know (even if you don’t plan to craft any snaps… but you should!) that a different set of interfaces can be defined for each elements.
For instance, the service and cli definition request access to different interfaces:
node-service:
command: bin/chuck-norris-app
daemon: simple
restart-condition: always
plugs: [network-bind]
cli:
command: bin/chuck-norris-cli
plugs: [network, camera]
The service needs to listen (and write) to the network. The network-bind interface is suited for this.
The command line application requests access to the network (as a reader, not a webserver listener) and to the user’s camera.
When you run snap interfaces, snap connect, snap disconnect, you only specify the snap name, meaning that it will connect/disconnect every applications from your snap which wants to use that interface.
In practice, when we did run snap connect chuck-norris-webserver:camera :camera
, we were only giving to the command line tool (and not the service!) access to the camera. The snap system is fine-grained!
Once thing is left though, the home interface wasn’t declared for this snap. We simulate here an interface that wouldn’t exist yet and a snap needing even more access, or a snap that someone is developing, before fully confining it. How to progressively get there and disable complete confinement on a snap? This is where devmode is useful.
devmode
Something to clearly understand first is that you are giving any access your user has (or root access for daemons) to any snap you are installing in devmode! You are thus warned
It’s not something to take lightly if you are not the creator of the snap and don’t know exactly what the application is doing.
The good news is that you can’t trigger devmode without knowing it!
Purpose of devmode
devmode is not for devil but developer mode! I guess that states clearly that it’s for developers and beta testers that really trusts the developers.
“devmode” lifts all restrictions and give all access to your snap: camera, files and such, as if you were running any application as your user. This isn’t that different from installing software from anywhere which isn’t trusted (ubuntu ppa, random website) and running it straight away! However, confined snaps give you confidence in the code you are running, so take advantage of it!
Channel restrictions
We did put some needed restrictions so that not all snaps are published innocently in devmode. The incentive is that devmode snaps can’t be published in stable or candidate channels. They can only be found in beta or alpha channels (as they are for developers and testers!), and thus, aren’t listed in snap find
by default.
Installing a snap in devmode
You need to explicitly declare you are installing a snap in devmode. Snaps in devmode won’t install unless the --devmode
flag is set.
For instance, face-detection-demo, in the beta channel, is a devmode snap. You can’t install it normally:
$ snap install --beta face-detection-demo
error: snap "face-detection-demo" requires devmode or confinement override
And so, installing it would require:
$ snap install --devmode --beta face-detection-demo
face-detection-demo (beta) 1.0 from 'didrocks' installed
You can check that the snap is installed in devmode:
$ snap list
Name Version Rev Developer Notes
[…]
face-detection-demo 1.0 52 didrocks devmode
However, you can install or reinstall a confined snap in devmode easily:
$ snap remove chuck-norris-webserver
chuck-norris-webserver removed
$ snap install --devmode chuck-norris-webserver
chuck-norris-webserver (stable) 1.0 from 'didrocks' installed
$ snap list
Name Version Rev Developer Notes
[…]
chuck-norris-webserver 1.0.0 10 devmode
You will notice that snap interfaces still shows the default auto-connections and permissions:
$ snap interfaces
Slot Plug
[…]
:camera -
[…]
:mount-observe -
:network chuck-norris-webserver
:network-bind chuck-norris-webserver
:network-control -
[…]
- chuck-norris-webserver:camera
However, they don’t matter anymore, as every access is now granted to the system:
$ chuck-norris-webserver.cli
FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu Core 16.
HOME ACCESS [OK]: My power enables me to see that you have .hidden in your home directory. I'm unstoppable!
CAMERA [OK]: I can see you, you should smile more!
NETWORK [OK]: When Chuck Norris break the build, you can't fix it, because there is not a single line of code left.
Even if no plug was defined to access the home directory, it will now list one of your file to prove it has access to it! Same with the non-connected camera plug, keep smiling!
This is great, but that’s not all! We need to talk about files!
File system structures
Snaps are, at the core, relocatable: meaning they embed all needed libraries and files. Both fully confined and devmode confinement modes are not seeing the exact file system. It means that the root “/” file system they are seeing isn’t the one you have on your host. This “/” and everything under it is coming from the core snap we mentioned in previous tutorials. It means that if you have for instance firefox installed on your machine, the snap application will never see the firefox binaries, icons, its libraries and such. It’s like if it was running on a small virtual machine!
You probably noticed that on both confined and devmode snaps, chuck-norris-webserver.cli
was printing “FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu Core 16.
”. This is the case even if you are running that on any laptop! Indeed, the /etc/os-release
file is the one coming from the core snap.
Let’s have a look at this file on your machine:
$ cat /etc/os-release
Name="Ubuntu"
VERSION="16.04.2 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.2 LTS"
VERSION_ID="16.04"
[…]
We are interesting in particular in the PRETTY_NAME line as this is what chuck-norris-webserver.cli
is printing. Note that it differs!
Your os-release
content will obviously differ between different distributions and version. Of course, if you are using Ubuntu Core, you may have the exact os-release file than in the snap as it’s using the core snap for populating “/”.
And here enters the classic snap!
Classic snap
What if your snap can’t live in a lying world? What if it needs system on libraries that can’t be relocated? Or also, what if the developer wanted to use a transition period to move to awesome snaps as quickly as possible?
Free the snap, Let / be / I hear! And that’s exactly why classic snaps exist! A classic snap sees the real host machine world, with its system libraries, installed (or absent) packages. There is a risk of course: as with just uncompressing an archive and running its program, some dependencies may be missing and such. Also, confinement is turned off. You can really see classic being “non relocated devmode snaps”. Classics snap can be published in the stable channel, though.
Classic snaps can only be installed on a traditional desktop system, not on a headless distribution like Ubuntu Core. Those need to state clearly that they are classic snaps, and they can’t be installed in devmode or confined. Indeed, some intricacies makes the two modes (relocatable vs non relocatable) incompatible with each others.
Let’s install and run the same snap than before, but a version declaring confinement: classic
.
$ snap install --classic chuck-norris-webserver-classic
$ chuck-norris-webserver-classic.cli
FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu 16.04.2 LTS.
HOME ACCESS [OK]: My power enables me to see that you have .hidden in your home directory. I'm unstoppable!
CAMERA [OK]: I can see you, you should smile more!
NETWORK [OK]: When Chuck Norris break the build, you can't fix it, because there is not a single line of code left.
This snap confirms that it can see the original (host) file system via FILE SYSTEM: I see from /etc/os-release that I'm running on Ubuntu 16.04.2 LTS
. Also, the snap has access to everything (network, camera, and home directory), confirming the fact that it’s an augmented devmode snap.
The developer corner
What does it mean for developers? If you want to snap a complex application and you don’t want to dive right away into making your application relocatable, you:
- can start with a classic snap, which should be easy to craft.
- then make your snap relocatable, and include all its dependencies. You can now turn on devmode! Remember, though, that you can’t publish it to the stable channel.
- finally, confine your application, turn it to strict mode and publish to the stable channel!
This gives you a nice and progressive workflow.
You can remove the 2 snaps now and reinstall one of them confined with:
$ snap remove chuck-norris-webserver-classic chuck-norris-webserver
chuck-norris-webserver-classic removed
chuck-norris-webserver removed
$ snap install chuck-norris-webserver
chuck-norris-webserver (stable) 1.0 from 'didrocks' installed
Closing up
A final note is that when you are connecting interfaces, those are only applied on command or service startup. You thus need to restart or relaunch a command to see those new capabilities apply. Launching a command or program is trivial. Restarting a service is a little bit more complex and that’s exactly what we are going to do next!