Place a script in /etc/NetworkManager/dispatcher.d/

I have an “app” where all I really want is to place a Bash script in /etc/NetworkManager/dispatcher.d/ on a traditional Ubuntu Desktop (not Ubuntu Core).

I have read through the docs and most of the post in this forum but can’t figure it out. Currently, I have "classic"ly confined snap. I tried using the dump plugin, then organize so that I can move the file into the right directory. I learned that this does indeed move the file like I want, but only when the Snap is being built by snapcraft.

What I’m looking for is for this Bash script to be packaged with the Snap file, and on install, moved/copied into the dispatcher directory. Unless someone has a better idea completely. I do see that there are a few interfaces regarding networking but I see two issues with that:

  1. I’m not sure which interface I would need, there’s several
  2. They seem to really apply in an Ubuntu Core scenario where NetworkManager itself is a snap. Perhaps I’m wrong.

Thoughts?

As you’re have a classic snap you don’t really need any interface as your snap runs entirely unconfined. If your snap is only meant to be used on classic distributions and not Ubuntu Core you can easily add a configure script to your snap which is running on installation and snap refresh. Inside the configure hook you can check if the file, you want to install, exists already in /etc/NetworkManager/dispatcher.d/ and if not, copy it in place. There is no way to copy files in place via snapcraft.yaml as it can only add things inside the snap but not on the outside. That would contradict the snap concept.

An example configure hook would like this:

#!/bin/bash
if [ ! -e  /etc/NetworkManager/dispatcher.d/my-script.sh ] ; then
  cp $SNAP/my-script.sh  /etc/NetworkManager/dispatcher.d/my-script.sh
fi

Just place this script as a file snap/hooks/configure inside the directory you have your snapcraft.yaml and build your snap. To verify the configure script was correctly copied into the snap you can find it in $SNAP/meta/hooks/configure

A few more details about hooks can be found here.

1 Like

i wonder if there is any reason to deny writing to /etc/NetworkManager when using the network-manager interface though … (i would have expected that you could use that interface if not in classic mode but looking at the code that dir is not in the allowed list)

We could allow that in the interface just for classic. On core systems this is a bit more complex.

1 Like

yeah, indeed i mainly meant for classic, i simply would expect to be able to manager NM when using the interface.

Perhaps… the network-manager interface is currently more bout using the NM dbus api and less about managing its configuration. If this is a common use case, then we could explore it, certainly. On core, the network-manager snap would likely need to setup either a writable content interface or we allow writes to network-manager’s SNAP_DATA directory for similar functionality.

For clarity, note that you are not allowed to specify interfaces when using classic confinement (on classic distro).

Thank you for that. I now get the script placed exactly where I want on install.

One issue now. The linked doc (and the wiki linked from there) appears to show only one hook so far, configure. The states on which configure would be ran doesn’t list uninstall/remove nor do I see a hook for this scenario. How would I go about removing the script I placed in /etc/NetworkManager/dispatcher.d/ when the user uninstalls the snap?

When I first went through the interfaces list, network-setup-control caught my attention as the one I might be able to use for dispatcher scripts. Seems like allowing write-access to /etc/NetworkManager/dispatcher.d/ (as well as /etc/network/if-up.d/, etc would be great.

Makes sense. If my note above about network-setup-control was done, then I figure I wouldn’t need classic confinement anymore.

Actually, that is an excellent point. We could if OnClassic allow writes to /etc/NetworkManager/dispatcher.d/ just like for netplan/ifupdown. I’ll take a todo for that and update this topic when there is a PR.

Note that I’m fine if someone else wants to do this bitesize PR. :slight_smile:

I’ll take a stab at it as long as I can find the code. :slight_smile: Sounds simple though.

You’ll want to add a new networkSetupControlConnectedPlugAppArmorClassic variable, then add the rule I mentioned, then conditionally append it if release.OnClassic. Please add a test case in network_setup_control_test.go that the rule is added when on classic and not added when not. Thanks!

So I haven’t made the PR for the above post yet but

I still have this issue to figure out. I need a way to remove the script put in place by the configure hook when the user uninstalls (sudo snap remove) my snap. This piece of code tells me that there isn’t any uninstall/remove hook at this point in time.

Right now, uninstall instructions to users would have to be:

sudo snap remove SNAP-NAME
sudo rm /etc/NetworkManager/dispatcher.d/SCRIPT-NAME

which is not ideal.

@jdstrand I finally opened a PR but not sure the best way to add a test for this: https://github.com/snapcore/snapd/pull/3346