By default, the snap daemon (snapd) has plugin signing verification enabled. To disable it or turn it to warning, the flag --plugin-trust, -t
can be set to 0 or 2 respectively.
##How it works
Private/public keys and keyrings are generated by GPG. The plugin is signed with the private key and the public key needs to be added to the user's keyring. The signing is an armored detached signature in the form of a .asc
file.
The snap daemon uses the Golang OpenPGP library's CheckArmoredDetachedSignature
function to validate the signature using the keyring, plugin, and signature file before loading the plugin. It checks the issuer key ID, hash, and signature type.
openpgp.CheckArmoredDetachedSignature(keyring, signed, signature)
##Usage
snapd
--plugin-trust, -t '1' 0-2 (Disabled, Enabled, Warning) [$SNAP_TRUST_LEVEL]
--keyring-paths, -k Keyring files for signing verification separated by colons [$SNAP_KEYRING_FILES]
One keyring (-t flag is not needed for signing enabled)
$ $SNAP_PATH/bin/snapd -k <keyringFileOrDirectory>
$ $SNAP_PATH/bin/snapd -t <trustLevel> -k <keyringFileOrDirectory>
$ $SNAP_PATH/bin/snapd -t <trustLevel> -k someDirectory/someFile.gpg
$ $SNAP_PATH/bin/snapd -t <trustLevel> -k someDirectory/
Multiple keyrings (may need full path, not ~)
$ $SNAP_PATH/bin/snapd -t <trustLevel> -k <keyringFile1>:<keyringFile2>
By default, plugin-trust is 1 (enabled), so the flag is only needed for 0 (disabled) and 2 (warning)
You can make an export to avoid needing the -k
flag:
$ export SNAP_KEYRING_FILE=<keyringFile>
$ $SNAP_PATH/bin/snapd -t <trustLevel>
Loading a single plugin using $SNAP_PATH/bin/snapctl
$ $SNAP_PATH/bin/snapctl plugin load <pluginFile> -a <pluginFile>.asc
####Examples #####No keyring, trust enabled/warning
$ $SNAP_PATH/bin/snapd -l 1
INFO[0000] setting plugin trust level to: enabled
FATA[0000] need keyring file when trust is on (--keyring-file or -k) _module=snapd block=main
#####Invalid Keyring Keyring doesn't exist
$ $SNAP_PATH/bin/snapd -l 1 -k /Users/tiffany/.gnupg/pubring.gpg:/Users/tiffany/.gnupg/stuff.gpg
INFO[0000] adding keyring file /Users/tiffany/.gnupg/pubring.gpg
FATA[0000] bad keyring file _module=snapd block=main error=stat /Users/tiffany/.gnupg/stuff.gpg: no such file or directory keyringPath=/Users/tiffany/.gnupg/stuff.gpg
#####Correct Keyring, trust enabled Valid signature
$ $SNAP_PATH/bin/snapd -l 1 -k /Users/tiffany/.gnupg/
INFO[0000] setting plugin trust level to: enabled
INFO[0000] Adding keyrings from: /Users/tiffany/.gnupg
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/pubkeys.gpg
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/pubkeys2.gpg
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/pubring.gpg
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/snap.pubring
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/secring.gpg
INFO[0000] adding keyring file: /Users/tiffany/.gnupg/trustdb.gpg
$ $SNAP plugin load build/plugin/snap-collector-mock1 -a build/plugin/snap-collector-mock1.asc
Plugin loaded
Name: mock
Version: 1
Type: collector
Signed: true
Loaded Time: Thu, 12 Nov 2015 13:53:58 PST
INFO[0036] API request _module=_mgmt-rest index=3 method=POST url=/v1/plugins
DEBU[0037] wrote 7332032 to /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/485061199/snap-collector-mock1
DEBU[0037] wrote 473 to /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/784063842/snap-collector-mock1.asc
INFO[0037] Loading plugin: /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/485061199/snap-collector-mock1 _module=_mgmt-rest
Signature made Thu, 12 Nov 2015 13:53:58 PST using RSA key ID 43F744A0
Good signature from Tiffany Jernigan (Main signing key) <my.email@intel.com>
No signature
$ $SNAP_PATH/bin/snapctl plugin load build/plugin/snap-collector-mock2
Error loading plugin:
Signature file (.asc) not found:
open : no such file or directory
DEBU[0033] wrote 7327840 to /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/180549107/snap-collector-mock2
INFO[0033] Loading plugin: /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/180549107/snap-collector-mock2 _module=_mgmt-rest
ERRO[0033] Signature file (.asc) not found:
open : no such file or directory _module=_mgmt-rest
DEBU[0033] Removing file (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/180549107/snap-collector-mock2) after failure to load plugin (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/180549107/snap-collector-mock2) _module=_mgmt-rest
Invalid signature
$SNAP_PATH/bin/snapctl plugin load build/plugin/snap-collector-mock2 -a build/plugin/snap-collector-mock1.asc
Error loading plugin:
Error checking signature
openpgp: invalid signature: hash tag doesn't match
DEBU[0003] wrote 7327840 to /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/719702627/snap-collector-mock2
DEBU[0003] wrote 473 to /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/700509798/snap-collector-mock1.asc
INFO[0003] Loading plugin: /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/719702627/snap-collector-mock2 _module=_mgmt-rest
ERRO[0003] Error checking signature
openpgp: invalid signature: hash tag doesn't match _module=_mgmt-rest
DEBU[0003] Removing file (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/719702627/snap-collector-mock2) after failure to load plugin (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/719702627/snap-collector-mock2) _module=_mgmt-rest
DEBU[0003] Removing file (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/700509798/snap-collector-mock1.asc) after failure to load plugin (/var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/719702627/snap-collector-mock2) _module=_mgmt-rest
Wrong keyring
$ $SNAP_PATH/bin/snapctl plugin load build/plugin/snap-collector-mock1 -a build/plugin/snap-collector-mock1.asc
Error loading plugin:
Error checking signature
openpgp: signature made by unknown entity
INFO[0002] Loading plugin: /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/057449871/snap-collector-mock1 _module=_mgmt-rest
ERRO[0002] Error checking signature
openpgp: signature made by unknown entity _module=_mgmt-rest
#####Correct keyring, trust warning
$ $SNAP_PATH/bin/snapd -l 1 -k ~/.gnupg/pubring.gpg -t 2
INFO[0000] setting plugin trust level to: warning
INFO[0000] adding keyring file /Users/tiffany/.gnupg/pubring.gpg
$ $SNAP_PATH/bin/snapctl plugin load build/plugin/snap-collector-mock1 -a build/plugin/snap-collector-mock1.asc
Plugin loaded
Name: mock
Version: 1
Type: collector
Signed: true
Loaded Time: Thu, 12 Nov 2015 14:08:32 PST
$ $SNAP_PATH/bin/snapctl plugin load build/plugin/snap-collector-mock2
Plugin loaded
Name: mock
Version: 2
Type: collector
Signed: false
Loaded Time: Thu, 12 Nov 2015 14:08:49 PST
INFO[0338] Loading plugin: /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/276797457/snap-collector-mock1 _module=_mgmt-rest
Signature made Thu, 12 Nov 2015 14:08:32 PST using RSA key ID 43F744A0
Good signature from Tiffany Jernigan (ACI signing key) <my.email@intel.com>
WARN[0355] Loading unsigned plugin /var/folders/kh/v2qy5_zx3zlgbc0gll7fzjnm0000gp/T/205904491/snap-collector-mock2 _block=load _module=control
##Creating Signing Files and Validating Signature ###Creating a key for plugin signing The following is leveraged from the CoreOS RKT Signing and Verification Guide
Create a file named gpg-batch
with the following
%echo Generating a default key
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: Tiffany Jernigan
Name-Comment: Plugin signing key
Name-Email: my.email@intel.com
Expire-Date: 0
Passphrase: snap
%pubring snap.pubring
%secring snap.secring
%commit
%echo done
#####Generate the key using batch mode
$ gpg --batch --gen-key gpg-batch
#####List the keys
$ gpg --no-default-keyring --secret-keyring ./snap.secring --keyring ./snap.pubring \
--list-keys
./snap.pubring
-----------
pub 2048R/FE9B5E28 2015-11-04
uid Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
sub 2048R/0BC6D4D7 2015-11-04
Since we know exactly where this key came from let's trust it:
$ gpg --no-default-keyring --secret-keyring ./snap.secring --keyring ./snap.pubring \
--edit-key FE9B5E28 trust
gpg (GnuPG) 1.4.19; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/FE9B5E28 created: 2015-11-04 expires: never usage: SCEA
trust: unknown validity: unknown
sub 2048R/0BC6D4D7 created: 2015-11-04 expires: never usage: SEA
[ unknown] (1). Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
pub 2048R/FE9B5E28 created: 2015-11-04 expires: never usage: SCEA
trust: unknown validity: unknown
sub 2048R/0BC6D4D7 created: 2015-11-04 expires: never usage: SEA
[ unknown] (1). Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
pub 2048R/FE9B5E28 created: 2015-11-04 expires: never usage: SCEA
trust: ultimate validity: unknown
sub 2048R/0BC6D4D7 created: 2015-11-04 expires: never usage: SEA
[ unknown] (1). Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
Please note that the shown key validity is not necessarily correct
unless you restart the program.
gpg> quit
#####Export the public key
$ gpg --no-default-keyring --armor \
--secret-keyring ./snap.secring --keyring ./snap.pubring \
--export my.email@intel.com > pubkeys.gpg
###Signing the plugin/plugin package using generated keyrings #####Sign file
$ gpg --no-default-keyring --armor \
--secret-keyring ./snap.secring --keyring ./snap.pubring \
--output <pluginFile>.asc \
--detach-sig <pluginFile>
#####Verify the image using gpg
$ gpg --no-default-keyring \
--secret-keyring ./snap.secring --keyring ./snap.pubring \
--verify <pluginFile>.asc <pluginFile>
gpg: Signature made Wed Nov 4 14:24:18 2015 PST using RSA key ID 0BC6D4D7
gpg: Good signature from "Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
###Signing file using key in your default keyring
If you already have a key, you can use that. Otherwise you can create a key and directly add to your keyring
Create a file named gpg-batch
with the following
%echo Generating a default key
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: Tiffany Jernigan
Name-Comment: Main signing key
Name-Email: my.email@intel.com
Expire-Date: 0
Passphrase: snap
%commit
%echo done
#####Generate the key using batch mode
$ gpg --batch --gen-key gpg-batch
$ gpg --list-keys
/Users/tiffany/.gnupg/pubring.gpg
----------------------------------
pub 2048R/43F744A0 2015-08-22
uid Tiffany Jernigan (Main signing key) <my.email@intel.com>
sub 2048R/2ED40FB2 2015-08-22
#####Sign file
$ gpg --armor --output <pluginFile>.asc --detach-sig <pluginFile>
#####Verify the image using gpg
$ gpg --verify <pluginFile>.asc <pluginFile>
###Keyring
####Adding to your keyring
If you only have one key, you can use the snap.pubring
you just made as your <keyringFile>
. For multiple you can just separate them by a colon (e.g. : ) . If you want to add future pubkeys.gpg files to an existing keyring you can do:
$ gpg --no-default-keyring --keyring <keyringFile> --import pubkeys.gpg
If you just want to add to your gnupg default keyring (e.g. ~/.gnupg/pubring.gpg
) you can just do
$ gpg --import pubkeys.gpg
####Validating a public key from someone else
From the GPG Handbook:
Once a key is imported it should be validated. GnuPG uses a powerful and flexible trust model that does not require you to personally validate each key you import. Some keys may need to be personally validated, however. A key is validated by verifying the key's fingerprint and then signing the key to certify it as a valid key. A key's fingerprint can be quickly viewed with the --fingerprint command-line option, but in order to certify the key you must edit it.
Add --no-default-keyring --keyring to all commands below if you are editing a specific keyring that isn't your gnupg default one.
$ gpg --list-keys
/Users/tiffany/.gnupg/pubring.gpg
----------------------------------
pub 2048R/43F744A0 2015-08-22
uid Tiffany Jernigan (Main signing key) <my.email@intel.com>
sub 2048R/2ED40FB2 2015-08-22
pub 2048R/FE9B5E28 2015-11-04
uid Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
sub 2048R/0BC6D4D7 2015-11-04
$ gpg --edit-key FE9B5E28
gpg (GnuPG) 1.4.19; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
pub 2048R/FE9B5E28 created: 2015-11-04 expires: never usage: SCEA
trust: unknown validity: ultimate
sub 2048R/0BC6D4D7 created: 2015-11-04 expires: never usage: SEA
[ultimate] (1). Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
gpg> sign
pub 2048R/FE9B5E28 created: 2015-11-04 expires: never usage: SCEA
trust: unknown validity: ultimate
Primary key fingerprint: 60BF B0AD 3CDB 5188 CE27 EBD5 F7D3 7AF8 FE9B 5E28
Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
Are you sure that you want to sign this key with your
key "Tiffany Jernigan (Main signing key) <my.email@intel.com>" (43F744A0)
Really sign? (y/N) y
You need a passphrase to unlock the secret key for
user: "Tiffany Jernigan (Main signing key) <my.email@intel.com>"
2048-bit RSA key, ID 43F744A0, created 2015-08-22
gpg> check
uid Tiffany Jernigan (Plugin signing key) <my.email@intel.com>
sig!3 FE9B5E28 2015-11-04 [self-signature]
sig! 43F744A0 2015-11-05 Tiffany Jernigan (Main signing key) <my.email@intel.com>
gpg> quit
Save changes? (y/N) y