-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
buildSupport: add helpers for verifying code signatures #43233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2738727
317ece1
376eeee
403e8a1
8f961de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # This function downloads a PGP public key and verifies its fingerprint | ||
| # Because it is based on fetchurl, it will still require a sha256 | ||
| # in addition to the fingerprint | ||
|
|
||
| { lib, fetchurl, gnupg }: | ||
|
|
||
| { | ||
| fingerprint | ||
| , ... } @ args: | ||
|
|
||
| lib.overrideDerivation (fetchurl ({ | ||
|
|
||
| name = "pubkey-${fingerprint}"; | ||
|
|
||
| postFetch = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we could reduce issues when a key gets an additional signature (eg. for when fetching from sks-keyservers) by stripping it of all UIDs, signatures, etc. before the |
||
| '' | ||
| # extract fingerprint | ||
| fpr=$(cat "$downloadedFile" | gpg --homedir . --import --import-options show-only --with-colons 2>/dev/null | grep -m 1 '^fpr' | cut -d: -f 10) | ||
| # verify | ||
| if [ "$fpr" == "${fingerprint}" ]; then | ||
| echo "key fingerprint $fpr verified" | ||
| else | ||
| echo "key fingerprint mismatch: got $fpr, expected ${fingerprint}" | ||
| exit 1 | ||
| fi | ||
| ''; | ||
|
|
||
| } // removeAttrs args [ "fingerprint" ] )) | ||
| (x: {nativeBuildInputs = x.nativeBuildInputs++ [gnupg];}) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # Helper functions for verifying (detached) PGP signatures | ||
|
|
||
| # importPublicKey | ||
| # Add PGP public key contained in ${publicKey} to the keyring. | ||
| # All imported keys will be trusted by verifySig | ||
| _importPublicKey() { | ||
| if [ -z "$signaturePublicKey" ]; then | ||
| echo "error: verifySignatureHook requires signaturePublicKey" >&2 | ||
| exit 1 | ||
| fi | ||
| gpg -q --import "$signaturePublicKey" | ||
| } | ||
|
|
||
|
|
||
| # verifySignature SIGFILE DATAFILE UNCOMPRESS | ||
| # verify the signature SIGFILE for the file DATAFILE | ||
| # if DATAFILE is omitted, it is derived from SIGFILE by dropping the .asc or .sig suffix | ||
| # if UNCOMPRESS is set, uncompress DATAFILE before verification | ||
| verifySignature() { | ||
| if [ -z "$3" ]; then | ||
| gpgv --keyring pubring.kbx "$1" "$2" || exit 1 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you make gpg ignoring expire dates? Otherwise it will become a problem when somebody tries to build an old nixpkgs revision. We could print a warning if a gpg key is expired.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The warning should be good enough for the TOFU case. |
||
| else | ||
| gunzip -c "$2" | gpgv --keyring pubring.kbx "$1" - || exit 1 | ||
| fi | ||
| } | ||
|
|
||
|
|
||
| # verifySrcSignature | ||
| # verify the signature $srcSignature for source file $src | ||
| verifySrcSignature() { | ||
| _importPublicKey | ||
| [ -z "$srcSignature" ] && return | ||
| verifySignature "$srcSignature" "$src" "$signatureUncompressed" | ||
| } | ||
|
|
||
|
|
||
| # setup | ||
|
|
||
| # create temporary gpg homedir | ||
| export GNUPGHOME=$(readlink -f .gnupgtmp) | ||
| rm -rf $GNUPGHOME # make sure it's a fresh empty dir | ||
| mkdir -p -m 700 $GNUPGHOME | ||
|
|
||
| # automatically check the signature before unpack if srcSignature is set | ||
| preUnpackHooks+=(verifySrcSignature) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| { lib, stdenv, fetchurl, python, pkgconfig, perl, libxslt, docbook_xsl | ||
| , fetchpatch | ||
| , fetchpgpkey | ||
| , verifySignatureHook | ||
| , docbook_xml_dtd_42, docbook_xml_dtd_45, readline, talloc | ||
| , popt, iniparser, libbsd, libarchive, libiconv, gettext | ||
| , krb5Full, zlib, openldap, cups, pam, avahi, acl, libaio, fam, libceph, glusterfs | ||
|
|
@@ -29,6 +31,20 @@ stdenv.mkDerivation rec { | |
| sha256 = "0vkxqp3wh7bpn1fd45lznmrpn2ma1fq75yq28vi08rggr07y7v8y"; | ||
| }; | ||
|
|
||
| srcSignature = fetchurl { | ||
| url = "mirror://samba/pub/samba/stable/${name}.tar.asc"; | ||
| sha256 = "0wpcbwbs1bj1y0amhn0z29v55f2hhmzc5p8n7sbwg9kaf0hc5mz5"; | ||
| }; | ||
| signatureUncompressed = true; | ||
|
|
||
| signaturePublicKey = fetchpgpkey { | ||
| url = https://download.samba.org/pub/samba/samba-pubkey.asc; | ||
| sha256 = "1fndhq0c34va34z137gvsl9gpwjv30b06makfx8cq5vrmgiax1x1"; | ||
| fingerprint = "52FBC0B86D954B0843324CDC6F33915B6568B7EA"; | ||
| }; | ||
|
|
||
| nativeBuildInputs = [ verifySignatureHook ]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this work? We aren't downloading binaries here so I have no idea where the signature would be coming from. This should be not needed at all for source based builds.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It works by convention: The hook assumes that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And yes, it can be used for source base builds if upstream provides a signature for the source tarball. It obviously doesn't work with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok did not realize that on tarball signatures! I wonder if we could put the source-based part of the hook in fetchurl then? Just have an optional attribute that is verified for us. This would also make it possible to support multiple-src derivations.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure we can do that. I only decided against modifying fetchurl for now to avoid a rebuild-everything change. It would take several extra attributes: URL and hash of the signature file, and the public key which I would still download separately with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually it shouldn't though! fetchurl is fixed output so you can make any changes you want to it. |
||
|
|
||
| outputs = [ "out" "dev" "man" ]; | ||
|
|
||
| patches = | ||
|
|
@@ -41,6 +57,7 @@ stdenv.mkDerivation rec { | |
| }) | ||
| ]; | ||
|
|
||
|
|
||
| buildInputs = | ||
| [ python pkgconfig perl libxslt docbook_xsl docbook_xml_dtd_42 /* | ||
| docbook_xml_dtd_45 */ readline talloc popt iniparser | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if they update their key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we fetch their key from a key-server using the current keyid instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keyservers are just one of many ways of fetching OpenPGP keys, I don't think it would make sense to force downloads through them (also, we'd want to fetch using the fingerprint, not the keyid).
Having a
fetchFromSkswrapper offetchpgpkeythat fetches from the sks-keyservers network might be a meaningful addition, but I don't think it's required for the first iteration