IPK signing for the gpg_sign module
v5 cover IPK signing for the gpg_sign module
This patch series extends the gpg_sign module to support ipk signing.
v5 is a rebase on top of Markus' refactoring of the gpg_sign module. Most notably signature types have been reworked to function parameters with default values in accordance with the refactoring.
Ioan-Adrian Ratiu (3):
gpg_sign: add local ipk package signing functionality
gpg_sign: detached_sign: add signature type support
package_manager: sign IPK package feeds
meta/classes/package_ipk.bbclass | 6 ++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++ meta/classes/sign_package_feed.bbclass | 10 ++++++- meta/lib/oe/gpg_sign.py | 45 ++++++++++++++++++++++++++-- meta/lib/oe/package_manager.py | 17 +++++++++-- 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 meta/classes/sign_ipk.bbclass
Signature · 1 line
2.7.1
PATCH v5 1/3 gpg_sign: add local ipk package signing functionality
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.
--- meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6 -0
@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)
meta/classes/sign_ipk.bbclass new file +55 -0
55 lines not on this page · raw message
meta/lib/oe/gpg_sign.py +39 -0
@@ -1,5 +1,6 @@ """Helper module for GPG signing""" import os +import sys import bb import oe.utils
@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e: + bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0])) + raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocess
Signature · 1 line
2.7.1
Re: [PATCH v5 1/3] gpg_sign: add local ipk package signing functionality
Hi,
Quoted 87 lines · Ioan-Adrian Ratiu
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6
-0@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)meta/classes/sign_ipk.bbclass new file +45
-0@@ -0,0 +1,55 @@ +# Class for generating signed IPK packages. +# +# Configuration variables used by this class: +# IPK_GPG_PASSPHRASE_FILE +# Path to a file containing the passphrase of the signing key. +# IPK_GPG_NAME +# Name of the key to sign with. +# IPK_GPG_BACKEND +# Optional variable for specifying the backend to use for signing. +# Currently the only available option is 'local', i.e. local signing +# on the build host. +# IPK_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signatures, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) +# GPG_BIN +# Optional variable for specifying the gpg binary/wrapper to use for +# signing. +# GPG_PATH +# Optional variable for specifying the gnupg "home" directory: +# + +inherit sanity + +IPK_SIGN_PACKAGES = '1' +IPK_GPG_BACKEND ?= 'local' +IPK_GPG_SIGNATURE_TYPE ?= 'ASC' + +python () { + # Check configuration + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'): + if not d.getVar(var, True): + raise_sanity_error("You need to define %s in the config" % var, d) + + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) +} + +python sign_ipk () { + from oe.gpg_sign import get_signer + + ipk_file = d.getVar('IPK_TO_SIGN') + bb.debug(1, 'Signing ipk: %s' % ipk_file) +
meta/classes/sign_ipk.bbclass line 55
Quoted 10 lines
meta/classes/sign_ipk.bbclass new file +10
-0+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True)) + + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (sig_type.upper() != "BIN") + + signer.sign_ipk(ipk_file, + d.getVar('IPK_GPG_NAME', True), + d.getVar('IPK_GPG_PASSPHRASE_FILE', True), + is_ascii_sig) +}
To me, it would be seem more straightforward to not circulate ipk_to_sign through 'd'. Just define a regular python function like def sign_ipk(d, ipk_to_sign):
...
And then in package_ipk.bbclass just do "sign_ipk(d, ipk_to_sign)" instead of bb.build.exec_func("sign_ipk", d)"
Quoted 46 lines
meta/lib/oe/gpg_sign.py +0
-0@@ -1,5 +1,6 @@"""Helper module for GPG signing"""
import os
+import sysimport bb
import oe.utilsmeta/lib/oe/gpg_sign.py +31
-0@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e:
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 94
Quoted 10 lines
meta/lib/oe/gpg_sign.py +7
-0+ bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0])) + raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocess
Couldn't you just use detach_sign() instead of introducing sign_ipk(). To me the functionality seems identical.
Thanks,
Markus
Re: [PATCH v5 1/3] gpg_sign: add local ipk package signing functionality
Hello
Quoted 163 lines · On Thu, 18 Feb 2016 11:04:22 +0200 Markus Lehtonen…
Hi,
Quoted 87 lines · Ioan-Adrian Ratiu
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6
-0@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)meta/classes/sign_ipk.bbclass new file +45
-0@@ -0,0 +1,55 @@ +# Class for generating signed IPK packages. +# +# Configuration variables used by this class: +# IPK_GPG_PASSPHRASE_FILE +# Path to a file containing the passphrase of the signing key. +# IPK_GPG_NAME +# Name of the key to sign with. +# IPK_GPG_BACKEND +# Optional variable for specifying the backend to use for signing. +# Currently the only available option is 'local', i.e. local signing +# on the build host. +# IPK_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signatures, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) +# GPG_BIN +# Optional variable for specifying the gpg binary/wrapper to use for +# signing. +# GPG_PATH +# Optional variable for specifying the gnupg "home" directory: +# + +inherit sanity + +IPK_SIGN_PACKAGES = '1' +IPK_GPG_BACKEND ?= 'local' +IPK_GPG_SIGNATURE_TYPE ?= 'ASC' + +python () { + # Check configuration + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'): + if not d.getVar(var, True): + raise_sanity_error("You need to define %s in the config" % var, d) + + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) +} + +python sign_ipk () { + from oe.gpg_sign import get_signer + + ipk_file = d.getVar('IPK_TO_SIGN') + bb.debug(1, 'Signing ipk: %s' % ipk_file) +meta/classes/sign_ipk.bbclass line 55
Quoted 10 lines
meta/classes/sign_ipk.bbclass new file +10
-0+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True)) + + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (sig_type.upper() != "BIN") + + signer.sign_ipk(ipk_file, + d.getVar('IPK_GPG_NAME', True), + d.getVar('IPK_GPG_PASSPHRASE_FILE', True), + is_ascii_sig) +}To me, it would be seem more straightforward to not circulate
ipk_to_signthrough 'd'. Just define a regular python function like defsign_ipk(d, ipk_to_sign):...And then in package_ipk.bbclass just do "
sign_ipk(d, ipk_to_sign)" instead ofbb.build.exec_func("sign_ipk", d)"Quoted 50 lines
meta/lib/oe/gpg_sign.py +0
-0@@ -1,5 +1,6 @@"""Helper module for GPG signing"""
import os
+import sysimport bb
import oe.utilsmeta/lib/oe/gpg_sign.py +35
-0@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e: + bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0]))
Quoted 8 lines
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 94
Quoted 6 lines
meta/lib/oe/gpg_sign.py +3
-0+ raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocessCouldn't you just use
detach_sign()instead of introducingsign_ipk(). To me the functionality seems identical.
The functionality is almost identical, yes, and consolidating it into one function is a very good idea. I'll do it but I have one question.
The only diference between them is the usage in detach-sign of gpg's "--with-passphrase" arg, and that arg seems to cause some errors on my system:
"gpg: signing failed: Inappropriate ioctl for device"
I have not managed to reliably reproduce and find the cause of this issue. However, if we always open the file in python and read directly in a pipe which we always pass to gpg using "--passphrase-fd", the error goes away.
Is using something like the following in detach_sign() ok with you?
with open(passphrase_file) as fobj:
os.write(keypipe[1], fobj.readline() + '\n')
cmd += ["--passphrase-fd", str(keypipe[0])]
Quoted 6 lines
Thanks,
Markus
Re: [PATCH v5 1/3] gpg_sign: add local ipk package signing functionality
Quoted 177 lines · Ioan-Adrian Ratiu
Hello
Quoted 163 lines · On Thu, 18 Feb 2016 11:04:22 +0200 Markus Lehtonen…
Hi,
Quoted 87 lines · Ioan-Adrian Ratiu
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6
-0@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)meta/classes/sign_ipk.bbclass new file +45
-0@@ -0,0 +1,55 @@ +# Class for generating signed IPK packages. +# +# Configuration variables used by this class: +# IPK_GPG_PASSPHRASE_FILE +# Path to a file containing the passphrase of the signing key. +# IPK_GPG_NAME +# Name of the key to sign with. +# IPK_GPG_BACKEND +# Optional variable for specifying the backend to use for signing. +# Currently the only available option is 'local', i.e. local signing +# on the build host. +# IPK_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signatures, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) +# GPG_BIN +# Optional variable for specifying the gpg binary/wrapper to use for +# signing. +# GPG_PATH +# Optional variable for specifying the gnupg "home" directory: +# + +inherit sanity + +IPK_SIGN_PACKAGES = '1' +IPK_GPG_BACKEND ?= 'local' +IPK_GPG_SIGNATURE_TYPE ?= 'ASC' + +python () { + # Check configuration + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'): + if not d.getVar(var, True): + raise_sanity_error("You need to define %s in the config" % var, d) + + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) +} + +python sign_ipk () { + from oe.gpg_sign import get_signer + + ipk_file = d.getVar('IPK_TO_SIGN') + bb.debug(1, 'Signing ipk: %s' % ipk_file) +meta/classes/sign_ipk.bbclass line 55
Quoted 10 lines
meta/classes/sign_ipk.bbclass new file +10
-0+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True)) + + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (sig_type.upper() != "BIN") + + signer.sign_ipk(ipk_file, + d.getVar('IPK_GPG_NAME', True), + d.getVar('IPK_GPG_PASSPHRASE_FILE', True), + is_ascii_sig) +}To me, it would be seem more straightforward to not circulate
ipk_to_signthrough 'd'. Just define a regular python function like defsign_ipk(d, ipk_to_sign):...And then in package_ipk.bbclass just do "
sign_ipk(d, ipk_to_sign)" instead ofbb.build.exec_func("sign_ipk", d)"Quoted 50 lines
meta/lib/oe/gpg_sign.py +0
-0@@ -1,5 +1,6 @@"""Helper module for GPG signing"""
import os
+import sysimport bb
import oe.utilsmeta/lib/oe/gpg_sign.py +35
-0@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e: + bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0]))Quoted 8 lines
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 94
Quoted 6 lines
meta/lib/oe/gpg_sign.py +3
-0+ raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocessCouldn't you just use
detach_sign()instead of introducingsign_ipk(). To me the functionality seems identical.
Quoted 4 lines
The functionality is almost identical, yes, and consolidating it into one function is a very good idea. I'll do it but I have one question.
The only diference between them is the usage in detach-sign of gpg's "--with-passphrase" arg, and that arg seems to cause some errors on my system:
"gpg: signing failed: Inappropriate ioctl for device"
You mean the "--passphrase-file" option? I don't see any "--with-passphrase" option anywhere.
The problem sounds really strange. What host OS and gpg version do you have? I'd like to understand what is happening there.
Quoted 9 lines
I have not managed to reliably reproduce and find the cause of this issue. However, if we always open the file in python and read directly in a pipe which we always pass to gpg using "--passphrase-fd", the error goes away.
Is using something like the following in
detach_sign()ok with you?with
open(passphrase_file)as fobj:os.write(keypipe[1], fobj.readline() + '\n')cmd += ["--passphrase-fd",
str(keypipe[0])]
If we need to do this, why do you want to use pipes? Why not just something like with open(passphrase_file) as fobj:
job.communicate(fobj.readline() + '\n')
Thanks,
Markus
Re: [PATCH v5 1/3] gpg_sign: add local ipk package signing functionality
In reply to Ioan-Adrian RatiuQuoted 185 lines · On Thu, 18 Feb 2016 11:28:58 +0200 Ioan-Adrian Ratiu <[email protected]>…
Hello
Quoted 163 lines · On Thu, 18 Feb 2016 11:04:22 +0200 Markus Lehtonen…
Hi,
Quoted 87 lines · Ioan-Adrian Ratiu
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6
-0@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)meta/classes/sign_ipk.bbclass new file +45
-0@@ -0,0 +1,55 @@ +# Class for generating signed IPK packages. +# +# Configuration variables used by this class: +# IPK_GPG_PASSPHRASE_FILE +# Path to a file containing the passphrase of the signing key. +# IPK_GPG_NAME +# Name of the key to sign with. +# IPK_GPG_BACKEND +# Optional variable for specifying the backend to use for signing. +# Currently the only available option is 'local', i.e. local signing +# on the build host. +# IPK_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signatures, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) +# GPG_BIN +# Optional variable for specifying the gpg binary/wrapper to use for +# signing. +# GPG_PATH +# Optional variable for specifying the gnupg "home" directory: +# + +inherit sanity + +IPK_SIGN_PACKAGES = '1' +IPK_GPG_BACKEND ?= 'local' +IPK_GPG_SIGNATURE_TYPE ?= 'ASC' + +python () { + # Check configuration + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'): + if not d.getVar(var, True): + raise_sanity_error("You need to define %s in the config" % var, d) + + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) +} + +python sign_ipk () { + from oe.gpg_sign import get_signer + + ipk_file = d.getVar('IPK_TO_SIGN') + bb.debug(1, 'Signing ipk: %s' % ipk_file) +meta/classes/sign_ipk.bbclass line 55
Quoted 10 lines
meta/classes/sign_ipk.bbclass new file +10
-0+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True)) + + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (sig_type.upper() != "BIN") + + signer.sign_ipk(ipk_file, + d.getVar('IPK_GPG_NAME', True), + d.getVar('IPK_GPG_PASSPHRASE_FILE', True), + is_ascii_sig) +}To me, it would be seem more straightforward to not circulate
ipk_to_signthrough 'd'. Just define a regular python function like defsign_ipk(d, ipk_to_sign):...And then in package_ipk.bbclass just do "
sign_ipk(d, ipk_to_sign)" instead ofbb.build.exec_func("sign_ipk", d)"Quoted 50 lines
meta/lib/oe/gpg_sign.py +0
-0@@ -1,5 +1,6 @@"""Helper module for GPG signing"""
import os
+import sysimport bb
import oe.utilsmeta/lib/oe/gpg_sign.py +35
-0@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e: + bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0]))Quoted 8 lines
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 94
Quoted 6 lines
meta/lib/oe/gpg_sign.py +3
-0+ raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocessCouldn't you just use
detach_sign()instead of introducingsign_ipk(). To me the functionality seems identical.The functionality is almost identical, yes, and consolidating it into one function is a very good idea. I'll do it but I have one question.
The only diference between them is the usage in detach-sign of gpg's "--with-passphrase" arg, and that arg seems to cause some errors on my system:
"gpg: signing failed: Inappropriate ioctl for device"I have not managed to reliably reproduce and find the cause of this issue. However, if we always open the file in python and read directly in a pipe which we always pass to gpg using "--passphrase-fd", the error goes away.
Quoted 6 lines
Is using something like the following in
detach_sign()ok with you?with
open(passphrase_file)as fobj:os.write(keypipe[1], fobj.readline() + '\n')cmd += ["--passphrase-fd",
str(keypipe[0])]
Good news: I managed to reproduce and find the cause of the problem: pinentry mode. Gpg has a parameter "--pinentry-mode" which by default is set to ask, but when doing batch singing and sending the passphrases through pipes it needs to be set to cancel.
So now both methods work! :) I'll go with your method of using --passphrase-file and --passphrase-fd 0 because it is more clearer.
Quoted 8 lines
Quoted 7 lines
Thanks,
Markus
Re: [PATCH v5 1/3] gpg_sign: add local ipk package signing functionality
Quoted 193 lines · On Fri, 19 Feb 2016 13:18:12 +0200 Ioan-Adrian Ratiu <[email protected]>…
Quoted 190 lines · On Thu, 18 Feb 2016 11:28:58 +0200 Ioan-Adrian Ratiu <[email protected]>…
Hello
Quoted 163 lines · On Thu, 18 Feb 2016 11:04:22 +0200 Markus Lehtonen…
Hi,
Quoted 87 lines · Ioan-Adrian Ratiu
Implement local ipk signing logic inside the gpg backend and add a new bbclass which configures signing similar to how rpm does it.
The ipk signing process is a bit different from rpm:
- Signatures are stored outside ipk files; opkg connects to a feed
server and downloads them to verify a package.
- Signatures are of two types (both supported by opkg): binary or
ascii armoured. By default we sign using ascii armoured.
- Public keys are stored on targets to verify ipks using the
opkg-keyrings recipe.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/package_ipk.bbclass | 6 +++++ meta/classes/sign_ipk.bbclass | 55 ++++++++++++++++++++++++++++++++++++++++ meta/lib/oe/gpg_sign.py | 39 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)create mode 100644 meta/classes/sign_ipk.bbclass
meta/classes/package_ipk.bbclass +6
-0@@ -246,6 +246,12 @@ python do_package_ipk () { bb.utils.unlockfile(lf) raise bb.build.FuncFailed("opkg-build execution failed") + if d.getVar('IPK_SIGN_PACKAGES', True) == '1': + ipkver = "%s-%s" % (d.getVar('PKGV'), d.getVar('PKGR')) + ipk_to_sign = "%s/%s_%s_%s.ipk" % (pkgoutdir, pkgname, ipkver, d.getVar('PACKAGE_ARCH', True)) + d.setVar('IPK_TO_SIGN', ipk_to_sign) + bb.build.exec_func("sign_ipk", d) + cleanupcontrol(root) bb.utils.unlockfile(lf)meta/classes/sign_ipk.bbclass new file +45
-0@@ -0,0 +1,55 @@ +# Class for generating signed IPK packages. +# +# Configuration variables used by this class: +# IPK_GPG_PASSPHRASE_FILE +# Path to a file containing the passphrase of the signing key. +# IPK_GPG_NAME +# Name of the key to sign with. +# IPK_GPG_BACKEND +# Optional variable for specifying the backend to use for signing. +# Currently the only available option is 'local', i.e. local signing +# on the build host. +# IPK_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signatures, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) +# GPG_BIN +# Optional variable for specifying the gpg binary/wrapper to use for +# signing. +# GPG_PATH +# Optional variable for specifying the gnupg "home" directory: +# + +inherit sanity + +IPK_SIGN_PACKAGES = '1' +IPK_GPG_BACKEND ?= 'local' +IPK_GPG_SIGNATURE_TYPE ?= 'ASC' + +python () { + # Check configuration + for var in ('IPK_GPG_NAME', 'IPK_GPG_PASSPHRASE_FILE'): + if not d.getVar(var, True): + raise_sanity_error("You need to define %s in the config" % var, d) + + sigtype = d.getVar("IPK_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for IPK_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) +} + +python sign_ipk () { + from oe.gpg_sign import get_signer + + ipk_file = d.getVar('IPK_TO_SIGN') + bb.debug(1, 'Signing ipk: %s' % ipk_file) +meta/classes/sign_ipk.bbclass line 55
Quoted 10 lines
meta/classes/sign_ipk.bbclass new file +10
-0+ signer = get_signer(d, d.getVar('IPK_GPG_BACKEND', True)) + + sig_type = d.getVar('IPK_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (sig_type.upper() != "BIN") + + signer.sign_ipk(ipk_file, + d.getVar('IPK_GPG_NAME', True), + d.getVar('IPK_GPG_PASSPHRASE_FILE', True), + is_ascii_sig) +}To me, it would be seem more straightforward to not circulate
ipk_to_signthrough 'd'. Just define a regular python function like defsign_ipk(d, ipk_to_sign):...And then in package_ipk.bbclass just do "
sign_ipk(d, ipk_to_sign)" instead ofbb.build.exec_func("sign_ipk", d)"Quoted 50 lines
meta/lib/oe/gpg_sign.py +0
-0@@ -1,5 +1,6 @@"""Helper module for GPG signing"""
import os
+import sysimport bb
import oe.utilsmeta/lib/oe/gpg_sign.py +35
-0@@ -50,6 +51,44 @@ class LocalSigner(object): bb.error('rpmsign failed: %s' % proc.before.strip()) raise bb.build.FuncFailed("Failed to sign RPM packages") + def sign_ipk(self, ipkfile, keyid, passphrase_file, armor=True): + """Sign IPK files""" + import subprocess + from subprocess import Popen + + cmd = [self.gpg_bin, "-q", "--batch", "--yes", "-b", "-u", keyid] + if self.gpg_path: + cmd += ["--homedir", self.gpg_path] + if armor: + cmd += ["--armor"] + + try: + keypipe = os.pipe() + + # Need to add '\n' in case the passfile does not have it + with open(passphrase_file) as fobj: + os.write(keypipe[1], fobj.readline() + '\n') + + cmd += ["--passphrase-fd", str(keypipe[0])] + cmd += [ipkfile] + + gpg_proc = Popen(cmd, stdin=subprocess.PIPE) + gpg_proc.wait() + + os.close(keypipe[1]); + os.close(keypipe[0]); + + except IOError as e: + bb.error("IO error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except OSError as e: + bb.error("OS error ({0}): {1}".format(e.errno, e.strerror)) + raise bb.build.FuncFailed("Failed to sign IPK packages") + except: + bb.error("Unexpected error: {1}".format(sys.exc_info()[0]))Quoted 8 lines
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 94
Quoted 6 lines
meta/lib/oe/gpg_sign.py +3
-0+ raise bb.build.FuncFailed("Failed to sign IPK packages") + + def detach_sign(self, input_file, keyid, passphrase_file, passphrase=None, armor=True): """Create a detached signature of a file""" import subprocessCouldn't you just use
detach_sign()instead of introducingsign_ipk(). To me the functionality seems identical.The functionality is almost identical, yes, and consolidating it into one function is a very good idea. I'll do it but I have one question.
The only diference between them is the usage in detach-sign of gpg's "--with-passphrase" arg, and that arg seems to cause some errors on my system:
"gpg: signing failed: Inappropriate ioctl for device"I have not managed to reliably reproduce and find the cause of this issue. However, if we always open the file in python and read directly in a pipe which we always pass to gpg using "--passphrase-fd", the error goes away.
Is using something like the following in
detach_sign()ok with you?with
open(passphrase_file)as fobj:os.write(keypipe[1], fobj.readline() + '\n')
Quoted 8 lines
Quoted 1 line
cmd += ["--passphrase-fd",
str(keypipe[0])]Good news: I managed to reproduce and find the cause of the problem: pinentry mode. Gpg has a parameter "--pinentry-mode" which by default is set to ask, but when doing batch singing and sending the passphrases through pipes it needs to be set to cancel.
So now both methods work! :) I'll go with your method of using --passphrase-file and --passphrase-fd 0 because it is more clearer.
*facepalm*
I mistyped the value of the pinentry-mode parameter it's loopback not cancel.
More info at https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase
Quoted 10 lines
Quoted 9 lines
Quoted 8 lines
Thanks,
Markus
PATCH v5 2/3 gpg_sign: detached_sign: add signature type support
In reply to Ioan-Adrian RatiuAdd support for multiple types of signatures (binary or ascii) in export_pubkey(). There is no change in behaviour for the function, the previous implicit default is the new parameter "armor" default.
--- meta/lib/oe/gpg_sign.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
meta/lib/oe/gpg_sign.py +4 -2
@@ -13,12 +13,14 @@ class LocalSigner(object): self.gpg_path = d.getVar('GPG_PATH', True) self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpm") - def export_pubkey(self, output_file, keyid): + def export_pubkey(self, output_file, keyid, armor=True): """Export GPG public key to a file""" - cmd = '%s --batch --yes --export --armor -o %s ' % \ + cmd = '%s --batch --yes --export -o %s ' % \ (self.gpg_bin, output_file) if self.gpg_path: cmd += "--homedir %s " % self.gpg_path + if armor: + cmd += "--armor " cmd += keyid status, output = oe.utils.getstatusoutput(cmd) if status:
Signature · 1 line
2.7.1
Re: [PATCH v5 2/3] gpg_sign: detached_sign: add signature type support
Quoted 20 lines · Ioan-Adrian Ratiu
Add support for multiple types of signatures (binary or ascii) in
export_pubkey(). There is no change in behaviour for the function, the previous implicit default is the new parameter "armor" default.Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/lib/oe/gpg_sign.py| 6 ++++--1 file changed, 4 insertions(+), 2 deletions(-)meta/lib/oe/gpg_sign.py +1
-1@@ -13,12 +13,14 @@ class LocalSigner(object): self.gpg_path = d.getVar('GPG_PATH', True) self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpm") - def export_pubkey(self, output_file, keyid): + def export_pubkey(self, output_file, keyid, armor=True): """Export GPG public key to a file"""
meta/lib/oe/gpg_sign.py class LocalSigner(object): · line 26
Quoted 10 lines
meta/lib/oe/gpg_sign.py +3
-1- cmd = '%s --batch --yes --export --armor -o %s ' % \ + cmd = '%s --batch --yes --export -o %s ' % \ (self.gpg_bin, output_file) if self.gpg_path: cmd += "--homedir %s " % self.gpg_path + if armor: + cmd += "--armor " cmd += keyid status, output = oe.utils.getstatusoutput(cmd) if status:
Just change "detached_sign" in the commit subject to "export_pubkey"
Thanks,
Markus
PATCH v5 3/3 package_manager: sign IPK package feeds
In reply to Ioan-Adrian RatiuCreate gpg signed ipk package feeds using the gpg backend if configured.
--- meta/classes/sign_package_feed.bbclass | 10 +++++++++- meta/lib/oe/package_manager.py | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-)
meta/classes/sign_package_feed.bbclass +9 -1
@@ -10,6 +10,10 @@ # Optional variable for specifying the backend to use for signing. # Currently the only available option is 'local', i.e. local signing # on the build host. +# PACKAGE_FEED_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signature, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN) # GPG_BIN # Optional variable for specifying the gpg binary/wrapper to use for # signing.
@@ -20,7 +24,7 @@ inherit sanity PACKAGE_FEED_SIGN = '1' PACKAGE_FEED_GPG_BACKEND ?= 'local' - +PACKAGE_FEED_GPG_SIGNATURE_TYPE ?= 'ASC' python () { # Check sanity of configuration
@@ -28,6 +32,10 @@ python () { if not d.getVar(var, True): raise_sanity_error("You need to define %s in the config" % var, d) + sigtype = d.getVar("PACKAGE_FEED_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for PACKAGE_FEED_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) + # Set expected location of the public key d.setVar('PACKAGE_FEED_GPG_PUBKEY', os.path.join(d.getVar('STAGING_ETCDIR_NATIVE', False),
meta/lib/oe/package_manager.py +15 -2
@@ -163,11 +163,16 @@ class OpkgIndexer(Indexer): "MULTILIB_ARCHS"] opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index") + if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1': + signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND', True)) + else: + signer = None if not os.path.exists(os.path.join(self.deploy_dir, "Packages")): open(os.path.join(self.deploy_dir, "Packages"), "w").close() index_cmds = [] + index_sign_files = [] for arch_var in arch_vars: archs = self.d.getVar(arch_var, True) if archs is None:
@@ -186,6 +191,8 @@ class OpkgIndexer(Indexer): index_cmds.append('%s -r %s -p %s -m %s' % (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir)) + index_sign_files.append(pkgs_file) + if len(index_cmds) == 0: bb.note("There are no packages in %s!" % self.deploy_dir) return
@@ -193,9 +200,15 @@ class OpkgIndexer(Indexer): result = oe.utils.multiprocess_exec(index_cmds, create_index) if result: bb.fatal('%s' % ('\n'.join(result))) - if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1': - raise NotImplementedError('Package feed signing not implementd for ipk') + if signer: + feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (feed_sig_type.upper() != "BIN") + for f in index_sign_files: + signer.detach_sign(f, + self.d.getVar('PACKAGE_FEED_GPG_NAME', True), + self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE', True), + armor=is_ascii_sig) class DpkgIndexer(Indexer):
Signature · 1 line
2.7.1
Re: [PATCH v5 3/3] package_manager: sign IPK package feeds
Quoted 13 lines · Ioan-Adrian Ratiu
Create gpg signed ipk package feeds using the gpg backend if configured.
Signed-off-by Ioan-Adrian Ratiu <[email protected]>---
meta/classes/sign_package_feed.bbclass | 10 +++++++++-meta/lib/oe/package_manager.py| 17 +++++++++++++++--2 files changed, 24 insertions(+), 3 deletions(-)meta/classes/sign_package_feed.bbclass +0
-0
meta/classes/sign_package_feed.bbclass line 16
Quoted 7 lines
meta/classes/sign_package_feed.bbclass +4
-0@@ -10,6 +10,10 @@ # Optional variable for specifying the backend to use for signing. # Currently the only available option is 'local', i.e. local signing # on the build host. +# PACKAGE_FEED_GPG_SIGNATURE_TYPE +# Optional variable for specifying the type of gpg signature, can be: +# 1. Ascii armored (ASC), default if not set +# 2. Binary (BIN)
I'd add a note that PACKAGE_FEED_GPG_SIGNATURE_TYPE is only supported for ipk feeds. This setting is ignored for RPM feeds and afaiu only .asc signatures are supported in rpm-md repositories.
Thanks,
Markus
Quoted 71 lines
meta/classes/sign_package_feed.bbclass +0
-0# GPG_BIN # Optional variable for specifying the gpg binary/wrapper to use for # signing.@@ -20,7 +24,7 @@ inherit sanity
PACKAGE_FEED_SIGN= '1'PACKAGE_FEED_GPG_BACKEND?= 'local'meta/classes/sign_package_feed.bbclass +1
-1- +PACKAGE_FEED_GPG_SIGNATURE_TYPE ?= 'ASC'python () {
# Check sanity of configurationmeta/classes/sign_package_feed.bbclass +4
-0@@ -28,6 +32,10 @@ python () { if not d.getVar(var, True): raise_sanity_error("You need to define %s in the config" % var, d) + sigtype = d.getVar("PACKAGE_FEED_GPG_SIGNATURE_TYPE", True) + if sigtype.upper() != "ASC" and sigtype.upper() != "BIN": + raise_sanity_error("Bad value for PACKAGE_FEED_GPG_SIGNATURE_TYPE (%s), use either ASC or BIN" % sigtype) + # Set expected location of the public key d.setVar('PACKAGE_FEED_GPG_PUBKEY', os.path.join(d.getVar('STAGING_ETCDIR_NATIVE', False),meta/lib/oe/package_manager.py +15
-2@@ -163,11 +163,16 @@ class OpkgIndexer(Indexer): "MULTILIB_ARCHS"] opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index") + if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1': + signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND', True)) + else: + signer = None if not os.path.exists(os.path.join(self.deploy_dir, "Packages")): open(os.path.join(self.deploy_dir, "Packages"), "w").close() index_cmds = [] + index_sign_files = [] for arch_var in arch_vars: archs = self.d.getVar(arch_var, True) if archs is None:@@ -186,6 +191,8 @@ class OpkgIndexer(Indexer): index_cmds.append('%s -r %s -p %s -m %s' % (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir)) + index_sign_files.append(pkgs_file) + if len(index_cmds) == 0: bb.note("There are no packages in %s!" % self.deploy_dir) return@@ -193,9 +200,15 @@ class OpkgIndexer(Indexer): result = oe.utils.multiprocess_exec(index_cmds, create_index) if result: bb.fatal('%s' % ('\n'.join(result))) - if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1': - raise NotImplementedError('Package feed signing not implementd for ipk') + if signer: + feed_sig_type = self.d.getVar('PACKAGE_FEED_GPG_SIGNATURE_TYPE', True) + is_ascii_sig = (feed_sig_type.upper() != "BIN") + for f in index_sign_files: + signer.detach_sign(f, + self.d.getVar('PACKAGE_FEED_GPG_NAME', True), + self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE', True), + armor=is_ascii_sig)class DpkgIndexer(Indexer):