Oh, snap - why is not yq working as it should?
Introduction
While I was adding some test automation I encountered a strange problem.
For some strange reason the command yq would just not work as it usually does.
It just printed out it’s usage information.
All kinds of debugging ensued (file access rights etc.) and all was good.
The file was definitely there, but why cannot yq do what it should?
Eventually I ran which yq:
$ which yq
/snap/bin/yq
Then it dawned. Oh snap.
Snapcraft snaps
Snaps - the packaging format by snapcraft.io (part of Canonical) is a sand-boxed packing format for distributing Linux applications. It aims for high security and minimal installation hassle, as each snap brings in all the dependencies the application has. Which in theory sounds very nice, but in practice can be a bit cumbersome.
Snaps are a divisive topic and ItsFOSS actually published an article about Canonical discontinuing snaps, which got people genuinely upset as it turned out to be April’s fool joke.
By default the snaps do not have any access to any local files. Applications can by default have permissions to the files under $HOME-folder and/or removable media. But nothing else.
When I originally installed yq I tried to install it as per usual - sudo apt-get install yq. However, this failed - Canonical
does not provide that application anymore via an apt service for Ubuntu 22.04 - only as a snap. Which means running sudo snap install yq.
Which then also means that yq cannot access files in other than $HOME-folder and removable media folder. My files were not there.
Shell redirections to the rescue
Typical use cases for yq include changing some value in a YAML-configuration file to some specific
value. You usually do something along these lines then:
yq eval '.["yaml-section"]["yaml-field"] = "your_value"' configfile.yaml -i
Only in this case with snap based yq, the configfile.yaml cannot be read by the yq application.
However, you can feed the files in via and out via shell redirections.
yq eval '.["yaml-section"]["yaml-field"] = "your_value"' <configfile.yaml >tempfile.yaml
mv tempfile.yaml configfile.yaml
This effectively allows you to work around the file access containment/access, as from snap point of view it is just reading the stdin (and your shell feeds the configfile.yaml to stdin).
Output is similary just written to stdout from the snap’s point of view and your shell writes it to the actual tempfile.yaml. In-place editing is not possible with this approach.
This is however the easiest way to work around the issues requiring no sudo rights.
What if I do want to give snap the access rights?
You can of course do that as well - however, only if the snap application has the required capabilites - the snap package developer must have added
the plugs to the snapcraft.yaml file. Example from yq’s snapcraft.yaml.
plugs: [home, removable-media]
If that is the case access is granted by issuing a sudo snap command.
You can view current access rights using:
$ snap connections yq
Interface Plug Slot Notes
home yq:home :home -
removable-media yq:removable-media - -
If the application does not have these rights, you can grant them.
sudo snap connect your-snap:home
sudo snap connect your-snap:removable-media
However, if you have for example /work or /data partition where your files are located - snaps cannot access those.
You must mount those partitions to be folders either:
- in your
$HOMEdirectory or - removable media directories (
/media/$USER)
Snaps cannot access files in any other locations. Please note that symbolic links will not work.
This can be done either temporarily using the mount command or permanently by modifying the /etc/fstab.
Temporary addition via mount
The temporary addition can be done using mount command. You cannot however mount it by the name, you need
to mount it using the block device name. This can be found out with lsblk command.
First create the folder (this needs to be done only once) under your $HOME-folder.
mkdir $HOME/data
Next we need to figure out the block device name:
$ lsblk |grep data
lsblk |grep data
└─sdb1 8:17 0 238.5G 0 part /data
So, we know the block device name is /dev/sdb1. Next we need to mount it.
sudo mount /dev/sdb1 $HOME/data
For example would mount the /data partition to be visible as data-folder under your $HOME-directory.
Permanent change via fstab
To do the same permanently we must modify /etc/fstab -file.
Again we must first create that folder and figure out the block device name.
$ mkdir $HOME/data
$ lsblk |grep data
lsblk |grep data
└─sdb1 8:17 0 238.5G 0 part /data
Then take a a backup copy of /etc/fstab with:
sudo cp /etc/fstab /etc/fstab.backup
with a sudo capable editor (for example sudo nano /etc/fstab) modify the line to mount the drive under your home folder.
/dev/sdb1 /home/your_username/data auto defaults 0 0
Reboot your machine now you will have a folder $HOME/ssd. This solution is however not that feasible for larger machines shared by multiple users.
Any mistake with /etc/fstab typically yields a non-booting device. If that happens, get the device into emergency mode and make the backup fstab the real one.
cp /etc/fstab.backup /etc/fstab
Install the snap without confinement
You can also install the snap application in developer mode. This also allows it to break the confinement.
sudo snap install <appname> --devmode
Allows the snap application to access files in other folders, too.
Or just install the binary
The other alternative is of course to either build the component from source and use that,
or see if the tool in question does do releases directly as .deb or .rpm packages.
Quite a few do, for example yq’s binary releases are available directly at: https://github.com/mikefarah/yq/releases
Future updates however are then in one’s own hands, as your package managers update scope will not cover it.
Conclusion
What is the right solution for you? Depends on your needs and how tight you want to be with security.
If you do not want to modify anything in the system - the shell redirections are the safest and quickest way. This will however only work with applications, that understand stdin (typically all Linux command line tools do).
Canonical provides also the popular image processing package gimp as a snap as well and with that you cannot use stdin.
All other options require already sudo permissions and expose more of your system/files to the application.