From d2a7023e5245e359ea3c57ef130c89071385c1e3 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sun, 30 Jun 2019 19:45:01 +0200 Subject: [PATCH] treewide: rework GPG signing Specify the GPG signing key directly in config.ini and pass it via environment variable to signall.sh. Signed-off-by: Jo-Philipp Wich --- phase1/config.ini.example | 11 +++++--- phase1/master.cfg | 31 +++++++++++----------- phase2/config.ini.example | 11 +++++--- phase2/master.cfg | 43 +++++++++++++++--------------- scripts/signall.sh | 56 +++++++++++++++++++++++++-------------- 5 files changed, 90 insertions(+), 62 deletions(-) diff --git a/phase1/config.ini.example b/phase1/config.ini.example index 2eeb537..c06edbd 100644 --- a/phase1/config.ini.example +++ b/phase1/config.ini.example @@ -38,9 +38,14 @@ source_url = user@example.org::upload-sources source_password = example2 [gpg] -home = ~/.gnupg -keyid = 626471F1 -passfile = ./gpg-passphrase.txt +key = -----BEGIN PGP PRIVATE KEY BLOCK----- + Version: GnuPG v2 + + mQGNBFX4kxkBDACcTUVUl6zbn4r9tDap0/aCpcK9MO+HPatS7p2aBGY51kh78Ixr + ... + HwHLaFTMvYFY7WJDwA== + -----END PGP PRIVATE KEY BLOCK----- +passphrase = secret password comment = Unattended build signature [usign] diff --git a/phase1/master.cfg b/phase1/master.cfg index dcba17e..a99d945 100644 --- a/phase1/master.cfg +++ b/phase1/master.cfg @@ -143,23 +143,19 @@ if ini.has_option("rsync", "source_url"): rsync_defopts = ["-4", "-v", "--timeout=120", "--contimeout=20"] -gpg_home = "~/.gnupg" -gpg_keyid = None -gpg_comment = "Unattended build signature" -gpg_passfile = "/dev/null" +gpg_key = None +gpg_passphrase = None +gpg_comment = repo_branch.replace("-", " ").title() + " key" -if ini.has_option("gpg", "home"): - gpg_home = ini.get("gpg", "home") +if ini.has_option("gpg", "key"): + gpg_key = ini.get("gpg", "key") -if ini.has_option("gpg", "keyid"): - gpg_keyid = ini.get("gpg", "keyid") +if ini.has_option("gpg", "passphrase"): + gpg_passphrase = ini.get("gpg", "passphrase") if ini.has_option("gpg", "comment"): gpg_comment = ini.get("gpg", "comment") -if ini.has_option("gpg", "passfile"): - gpg_passfile = ini.get("gpg", "passfile") - usign_key = None usign_comment = "untrusted comment: " + repo_branch.replace("-", " ").title() + " key" @@ -945,7 +941,7 @@ for target in targets: )) # sign - if gpg_keyid is not None: + if gpg_key is not None or usign_key is not None: factory.addStep(MasterShellCommand( name = "signprepare", description = "Preparing temporary signing directory", @@ -969,9 +965,14 @@ for target in targets: factory.addStep(MasterShellCommand( name = "signfiles", description = "Signing files", - command = ["%s/signall.sh" %(scripts_dir), "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1]), gpg_keyid, gpg_comment], - env = {'GNUPGHOME': gpg_home, 'PASSFILE': gpg_passfile, 'USIGNKEY': usign_key, 'USIGNCOMMENT': usign_comment}, - logEnviron = False, + command = ["%s/signall.sh" %(scripts_dir), "%s/signing/%s.%s.tar.gz" %(home_dir, ts[0], ts[1])], + env = { + 'GPGKEY': gpg_key, + 'GPGPASS': gpg_passphrase, + 'GPGCOMMENT': gpg_comment, + 'USIGNKEY': usign_key, + 'USIGNCOMMENT': usign_comment + }, haltOnFailure = True )) diff --git a/phase2/config.ini.example b/phase2/config.ini.example index 25f4213..c6192f4 100644 --- a/phase2/config.ini.example +++ b/phase2/config.ini.example @@ -32,9 +32,14 @@ sdk_password = example3 sdk_pattern = openwrt-sdk-*.tar.xz [gpg] -home = ~/.gnupg -keyid = 626471F1 -passfile = ./gpg-passphrase.txt +key = -----BEGIN PGP PRIVATE KEY BLOCK----- + Version: GnuPG v2 + + mQGNBFX4kxkBDACcTUVUl6zbn4r9tDap0/aCpcK9MO+HPatS7p2aBGY51kh78Ixr + ... + HwHLaFTMvYFY7WJDwA== + -----END PGP PRIVATE KEY BLOCK----- +passphrase = secret password comment = Unattended build signature [usign] diff --git a/phase2/master.cfg b/phase2/master.cfg index 11e3f0f..bed036a 100644 --- a/phase2/master.cfg +++ b/phase2/master.cfg @@ -108,23 +108,25 @@ if ini.has_option("rsync", "sdk_password"): if ini.has_option("rsync", "sdk_pattern"): rsync_sdk_pat = ini.get("rsync", "sdk_pattern") -gpg_home = "~/.gnupg" -gpg_keyid = None -gpg_comment = "Unattended build signature" -gpg_passfile = "/dev/null" +repo_url = ini.get("repo", "url") +repo_branch = "master" -if ini.has_option("gpg", "home"): - gpg_home = ini.get("gpg", "home") +if ini.has_option("repo", "branch"): + repo_branch = ini.get("repo", "branch") -if ini.has_option("gpg", "keyid"): - gpg_keyid = ini.get("gpg", "keyid") +gpg_key = None +gpg_passphrase = None +gpg_comment = repo_branch.replace("-", " ").title() + " key" + +if ini.has_option("gpg", "key"): + gpg_key = ini.get("gpg", "key") + +if ini.has_option("gpg", "passphrase"): + gpg_passphrase = ini.get("gpg", "passphrase") if ini.has_option("gpg", "comment"): gpg_comment = ini.get("gpg", "comment") -if ini.has_option("gpg", "passfile"): - gpg_passfile = ini.get("gpg", "passfile") - usign_key = None usign_comment = "untrusted comment: " + repo_branch.replace("-", " ").title() + " key" @@ -134,12 +136,6 @@ if ini.has_option("usign", "key"): if ini.has_option("usign", "comment"): usign_comment = ini.get("usign", "comment") -repo_url = ini.get("repo", "url") -repo_branch = "master" - -if ini.has_option("repo", "branch"): - repo_branch = ini.get("repo", "branch") - # find arches arches = [ ] @@ -458,7 +454,7 @@ for arch in arches: workdir = "build/sdk", command = "./scripts/feeds list -s -f > bin/packages/%s/feeds.conf" %(arch[0]))) - if gpg_keyid is not None: + if gpg_key is not None or usign_key is not None: factory.addStep(MasterShellCommand( name = "signprepare", description = "Preparing temporary signing directory", @@ -483,9 +479,14 @@ for arch in arches: factory.addStep(MasterShellCommand( name = "signfiles", description = "Signing files", - command = ["%s/signall.sh" %(scripts_dir), "%s/signing/%s.tar.gz" %(home_dir, arch[0]), gpg_keyid, gpg_comment], - env = {'GNUPGHOME': gpg_home, 'PASSFILE': gpg_passfile, 'USIGNKEY': usign_key, 'USIGNCOMMENT': usign_comment}, - logEnviron = False, + command = ["%s/signall.sh" %(scripts_dir), "%s/signing/%s.tar.gz" %(home_dir, arch[0])], + env = { + 'GPGKEY': gpg_key, + 'GPGPASS': gpg_passphrase, + 'GPGCOMMENT': gpg_comment, + 'USIGNKEY': usign_key, + 'USIGNCOMMENT': usign_comment + }, haltOnFailure = True )) diff --git a/scripts/signall.sh b/scripts/signall.sh index 1e40ead..1c36074 100755 --- a/scripts/signall.sh +++ b/scripts/signall.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash tarball="$1" -keyid="$2" -comment="$3" tmpdir="signall.$$" tarball="$(readlink -f "$tarball")" @@ -12,15 +10,21 @@ finish() { rm -rf "$tmpdir"; exit $1; } trap "finish 255" HUP INT TERM if [ ! -f "$tarball" ]; then - echo "Usage: [GNUPGHOME=... [PASSFILE=...]] [USIGNKEY=... [USIGNCOMMENT=...]] \\" - echo " $0 [ []]" + echo "Usage: [GPGKEY=... [GPGCOMMENT=... [GPGPASS=...]]] [USIGNKEY=... [USIGNCOMMENT=...]] $0 " >&2 finish 1 fi -umask 022 +[ ! -e "$tmpdir" ] || { + echo "Temporary directory $tmpdir already exists!" >&2 + finish 2 +} + +umask 077 +mkdir "$tmpdir" "$tmpdir/tar" "$tmpdir/gpg" "$tmpdir/gpg/private-keys-v1.d" || finish 2 -mkdir "$tmpdir" || finish 2 -tar -C "$tmpdir/" -xzf "$tarball" || finish 3 +umask 022 +chmod 0755 "$tmpdir/tar" +tar -C "$tmpdir/tar/" -xzf "$tarball" || finish 3 loopback="" @@ -28,23 +32,35 @@ case "$(gpg --version | head -n1)" in *\ 2.*) loopback=1 ;; esac -find "$tmpdir/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec gpg \ - --no-version --batch --yes -a -b \ - ${loopback:+--pinentry-mode loopback --no-tty --passphrase-fd 0} \ - ${keyid:+-u "$keyid"} \ - ${comment:+--comment="$comment"} \ - ${GNUPGHOME:+--homedir "$GNUPGHOME"} \ - ${PASSFILE:+--passphrase-file "$PASSFILE"} \ - -o "{}.asc" "{}" \; || finish 4 +if echo "$GPGKEY" | grep -q "BEGIN PGP PRIVATE KEY BLOCK"; then + umask 077 + echo "$GPGPASS" > "$tmpdir/gpg.pass" + echo "$GPGKEY" | gpg --batch --homedir "$tmpdir/gpg" \ + ${loopback:+--pinentry-mode loopback --no-tty --passphrase-fd 0} \ + ${GPGPASS:+--passphrase-file "$tmpdir/gpg.pass"} \ + --import - || finish 4 -export USIGNID="$(echo "$USIGNKEY" | base64 -d -i | dd bs=1 skip=32 count=8 2>/dev/null | od -v -t x1 | sed -rne 's/^0+ //p' | tr -d ' ')" + umask 022 + find "$tmpdir/tar/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec \ + gpg --no-version --batch --yes -a -b \ + --homedir "$tmpdir/gpg" \ + ${loopback:+--pinentry-mode loopback --no-tty --passphrase-fd 0} \ + ${GPGPASS:+--passphrase-file "$tmpdir/gpg.pass"} \ + ${GPGCOMMENT:+--comment="$GPGCOMMENT"} \ + -o "{}.asc" "{}" \; || finish 4 +fi + +USIGNID="$(echo "$USIGNKEY" | base64 -d -i | dd bs=1 skip=32 count=8 2>/dev/null | od -v -t x1 | sed -rne 's/^0+ //p' | tr -d ' ')" if echo "$USIGNID" | grep -qxE "[0-9a-f]{16}"; then - find "$tmpdir/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec sh -c \ - 'printf "untrusted comment: %s\n%s\n" "${USIGNCOMMENT:-key ID $USIGNID}" "$USIGNKEY" | \ - signify-openbsd -S -s - -m "{}"' \; || finish 5 + umask 077 + printf "untrusted comment: %s\n%s\n" "${USIGNCOMMENT:-key ID $USIGNID}" "$USIGNKEY" > "$tmpdir/usign.key" + + umask 022 + find "$tmpdir/tar/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec \ + signify-openbsd -S -s "$(readlink -f "$tmpdir/usign.key")" -m "{}" \; || finish 5 fi -tar -C "$tmpdir/" -czf "$tarball" . || finish 6 +tar -C "$tmpdir/tar/" -czf "$tarball" . || finish 6 finish 0 -- 2.30.2