Two weeks ago, my colleague Alan wrote an article on how one goes about packaging an application as a snap. The focus of that piece was a handful of tips and tricks that should make the transition from raw code to a working snap easier and more fun.
Today, I’ll give you a slightly different spin to this story, with a Golang application example, highlighting some of the ins and out of snap development. Hopefully, it will make your own efforts smoother and snappier.
We got ourselves a volunteer!
To demonstrate, I chose a rather interesting application – bettercap. This program is designed to be the Swiss Army knife for network reconnaissance and MITM attacks, working with 802.11, BLE and Ethernet protocols. It is used by security experts and system administrators to probe, audit and harden their networks. Bettercap is a good example, as it requires additional libraries to build and stage, and it needs access to a large number of different interfaces. Let’s dig into the YAML, shall we:
summary: 802.11, BLE and Ethernet networks reconnaissance and MITM attacks tool.
The Swiss Army knife for 802.11, BLE and Ethernet networks reconnaissance and MITM attacks.
Words are very…necessary
Golang is one of the many languages supported in snapcraft. Developers have a readily available plugin that lets them build snaps with ease. In the example above, we used several Go-specific keywords, including:
- Source – The root of the project containing the Go code.
- Go-importpath – When using local sources, snapcraft needs to construct a suitable GOPATH. For this it uses go-importpath to know where the sources should live within GOPATH/src.
However, if you require a different version of Go, you can use additional keywords available in the plugin to override the defaults. Specifically, you can do this with the go-channel keyword (e.g. “1.8/stable”).
We built this city with … snaps
The bettercap documentation explicitly mentions the packages required to build the application, so adding them to the snapcraft.yaml file is trivial. If you don’t have a list of required dependencies, you can build the snap, and when you hit an error, add the missing package(s) to YAML, and then iterate on the build.
Similarly, bettercap needs several runtime libraries to work. Alan showed a very neat trick on how to derive the required libraries and add them to the YAML. Ideally, the project documentation will list the dependencies – as bettercap does.
So many interfaces
Strictly-confined snaps can have fine-tuned control of system resources through interfaces. Developers specify what their applications are capable of accessing once installed by creating a list of plugs in the snapcraft.yaml file. Each plug specifies a connection request to a system resource, like audio, network, webcam, home directory, etc.
The bettercap plug section contains a fairly long list of interfaces. As a network inspection and control tool, bettercap requires the ability to access sockets, ports and control interfaces, and to that end, this part of the snapcraft.yaml file looks fairly long. This is rather typical with security software.
plugs: - home - network - network-bind - network-control - network-observe - netlink-connector - netlink-audit - bluetooth-control - firewall-control - x11
When the snap is installed, some of these interfaces will be auto-connected, while others, for security reasons, will not. You will need elevated permissions to connect these interfaces – as well connect to privileged network ports.
As a developer, you also have the ability to tweak the list of interfaces. Your application may need similar capabilities to bettercap. For instance, you can choose to release a specific edition of your tool that only has access to Bluetooth interfaces. You also give your users the control they need to connect/disconnect interfaces, so they can test different scenarios, or use the software in the manner that is most suitable to their needs.
For an installed snap, you can check the list of available interfaces on the command line:
snap interfaces bettercap
Auto-connected interfaces show with both the slot and the plug. Interfaces that are not connected have an empty slot, denoted by the dash character. Bettercap will not be able to work correctly without the ability to control interfaces. When you run, you will see the following error:
snap run bettercap
bettercap v2.11 (type 'help' for a list of commands)
enp0s3: You don't have permission to capture on that device (socket: Permission denied
You can then manually connect (or disconnect) interfaces. For example:
snap connect bettercap:firewall-control
For a more streamlined experience, developers can apply for a store assertion via the snapcraft forum. Once the assertion is approved, the interfaces will be automatically connected, so users do not need to take any manual steps.
Still not sure what to do?
Having read this article, it is quite possible that you are still a bit confused what to do next. Worry not. You will also find language guides on snapcraft.io – semi-interactive step-by-step tutorials to get you started with snaps. Each guide tailors a different programming language, so whether you like Python, Java, Rust, Go, or something else, you have a good starting point.
We hope you enjoyed this. We’re looking forward to sharing additional stories and pointers with you in future articles. Meanwhile, if you have any questions or comments, you may want to start a discussion on the forum.
P.S. No Wham!, Depeche Mode or Starship songs were harmed in the production of this article.