GPG in a confined environemt

Hi,
My snap package wants to encrypt some data during «a hook» plug/slot connection. I know that «within snapcraft.yaml» you have to stage your hooks to get an environment, and it works perfectly with e.g uuid etc. But…

To be simple;
I want to

  1. generate a key
  2. sign a file, and
  3. share a key,
  4. share a file

upon connection. It’s not important who,when, why, but a valid signature is is crucial to ensure that the connecting app doesn’t change.

However, I’ve tried to stage my «prepare» hook w/stage packages (gpg, gpg-client), but I’m still getting «/usr/bin/gpg-agent» = “Not found”.

If I log in to the running daemon (snap run --shell), I can see that which gpg and gpg-agent shows $SNAP/usr/bin/gpg and $SNAP/usr/bin/gpg-agent. If I execute $SNAP/usr/bin/gpg-agent- I’ll get gpg-agent[3326939]: gpg-agent running and available

Will I have to change to OpenSSL for this matter or can I use GPG?

You can try to use the Layouts snap feature to map certain paths to the location the program is expected to be in.

I don’t think that will help, as the location exist.

Running the following in the hook (preprare-slot-<name>)

which gpg-agent
gpg-agent
$SNAP/usr/bin/gpg-agent

returns

/snap/<name>/x1/usr/bin/gpg-agent
gpg-agent[3771720]: no gpg-agent running in this session
gpg-agent[3771721]: no gpg-agent running in this session

So the it seems to exist, but it doesn’t run. (Note that it is running if I snap run --shell).

I managed to solve this by creating a script that checks if the plug is set when the daemon starts, and then generate a GPG-key, which is OK as the plug requires a restart of the daemon anyway.

But I don’t understand what is missing (e.g en env.var) for it to run under a prepare-hook.

Do you need additional interfaces for the hook when it creates the key? What interfaces does your daemon use when it runs? Also note that hooks always run as root, not sure if that is relevant for your use case as well or not

Do you need additional interfaces for the hook when it creates the key?

Not that I’m aware of.

What interfaces does your daemon use when it runs?

  • bluez
  • network
  • network-bind
  • raw-usb
  • physical-memory-control

Also note that hooks always run as root, not sure if that is relevant for your use case as well or not

I know, but that’s fine as the daemon also runs as root. :slight_smile:

Just out of curiosity; Tried setting the same plugs for the hook - without success.

So I’ve done some further investigations. It turns out that gpg-agent needs network + network-bind plugs.

I moved the code to an post-refresh hook, as it’s easier to debug. It hangs on

Run post-refresh hook of "test-snap" snap if present

While it’s hanging on that hook, I’m able to shell into the daemon.

sudo snap run --shell test-snap.daemon

now issuing the command gpg --list-keys outputs the newly generated key.

However the only way to end the «refresh» routine is to terminate the process (CTRL+C ) and the snap will roll back to the previous version.

This is the whole script

#!/usr/bin/env -S bash -ex

UUID_FILE="${SNAP_DATA}/.install-id"

if ! [[ -f "${UUID_FILE}" ]]; then
    echo "Generate UUID"
    uuid > "${UUID_FILE}"
    echo "UUID `cat ${UUID_FILE}`"
fi

UUID=`cat "${UUID_FILE}"`
echo "UUID: ${UUID}"
KEY=`gpg --armor --export "${UUID}"`
echo "KEY: $KEY"

if [ -z "${KEY}" ]; then
    gpg-agent --daemon &
    gpg --batch --gen-key <<< "%no-protection
    Key-Type: DSA
    Key-Length: 2048
    Name-Real: ${UUID}
    Expire-Date: 0"
fi

KEY=`gpg --armor --export "${UUID}"`
echo "KEY: $KEY"
exit 0

I think the issue you are seeing with hanging is that you have a gpg-agent --daemon & which forks, and snapd when running the hook will block waiting for that process to exit, so if you save the pid that is created when you start the agent in daemon mode, and kill it after the script is done, it should exit automatically.

Hi,

Maybe. But it hangs even if I exit 1(with set -e). It seems like nothing is executed after the gpg-agent --daemon command.

However, I just found out that the following worked:

gpg-agent --server
gpg-agent --daemon

Why - I don’t understand.