poky/meta/lib/oeqa/selftest/cases/signing.py
Richard Purdie c7592b0147 oeqa: Drop OETestID
These IDs refer to testopia which we're no longer using. We would now use the test
names to definitively reference tests and the IDs can be dropped, along with their
supporting code.

(From OE-Core rev: 8e2d0575e4e7036b5f60e632f377a8ab2b96ead8)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2019-05-09 16:31:55 +01:00

212 lines
8.5 KiB
Python

from oeqa.selftest.case import OESelftestTestCase
from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
import os
import oe
import glob
import re
import shutil
import tempfile
from contextlib import contextmanager
from oeqa.utils.ftools import write_file
class Signing(OESelftestTestCase):
gpg_dir = ""
pub_key_path = ""
secret_key_path = ""
def setup_gpg(self):
bitbake('gnupg-native -c addto_recipe_sysroot')
self.gpg_dir = tempfile.mkdtemp(prefix="oeqa-signing-")
self.track_for_cleanup(self.gpg_dir)
self.pub_key_path = os.path.join(self.testlayer_path, 'files', 'signing', "key.pub")
self.secret_key_path = os.path.join(self.testlayer_path, 'files', 'signing', "key.secret")
nsysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "gnupg-native")
runCmd('gpg --batch --homedir %s --import %s %s' % (self.gpg_dir, self.pub_key_path, self.secret_key_path), native_sysroot=nsysroot)
return nsysroot + get_bb_var("bindir_native")
@contextmanager
def create_new_builddir(self, builddir, newbuilddir):
bb.utils.mkdirhier(newbuilddir)
oe.path.copytree(builddir + "/conf", newbuilddir + "/conf")
oe.path.copytree(builddir + "/cache", newbuilddir + "/cache")
origenv = os.environ.copy()
for e in os.environ:
if builddir in os.environ[e]:
os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
os.chdir(newbuilddir)
try:
yield
finally:
for e in origenv:
os.environ[e] = origenv[e]
os.chdir(builddir)
def test_signing_packages(self):
"""
Summary: Test that packages can be signed in the package feed
Expected: Package should be signed with the correct key
Expected: Images can be created from signed packages
Product: oe-core
Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
Author: Alexander Kanavin <alex.kanavin@gmail.com>
AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
"""
import oe.packagedata
self.setup_gpg()
package_classes = get_bb_var('PACKAGE_CLASSES')
if 'package_rpm' not in package_classes:
self.skipTest('This test requires RPM Packaging.')
test_recipe = 'ed'
feature = 'INHERIT += "sign_rpm"\n'
feature += 'RPM_GPG_PASSPHRASE = "test123"\n'
feature += 'RPM_GPG_NAME = "testuser"\n'
feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
self.write_config(feature)
bitbake('-c clean %s' % test_recipe)
bitbake('-f -c package_write_rpm %s' % test_recipe)
self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
needed_vars = ['PKGDATA_DIR', 'DEPLOY_DIR_RPM', 'PACKAGE_ARCH', 'STAGING_BINDIR_NATIVE']
bb_vars = get_bb_vars(needed_vars, test_recipe)
pkgdatadir = bb_vars['PKGDATA_DIR']
pkgdata = oe.packagedata.read_pkgdatafile(pkgdatadir + "/runtime/ed")
if 'PKGE' in pkgdata:
pf = pkgdata['PN'] + "-" + pkgdata['PKGE'] + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
else:
pf = pkgdata['PN'] + "-" + pkgdata['PKGV'] + '-' + pkgdata['PKGR']
deploy_dir_rpm = bb_vars['DEPLOY_DIR_RPM']
package_arch = bb_vars['PACKAGE_ARCH'].replace('-', '_')
staging_bindir_native = bb_vars['STAGING_BINDIR_NATIVE']
pkg_deploy = os.path.join(deploy_dir_rpm, package_arch, '.'.join((pf, package_arch, 'rpm')))
# Use a temporary rpmdb
rpmdb = tempfile.mkdtemp(prefix='oeqa-rpmdb')
runCmd('%s/rpmkeys --define "_dbpath %s" --import %s' %
(staging_bindir_native, rpmdb, self.pub_key_path))
ret = runCmd('%s/rpmkeys --define "_dbpath %s" --checksig %s' %
(staging_bindir_native, rpmdb, pkg_deploy))
# tmp/deploy/rpm/i586/ed-1.9-r0.i586.rpm: rsa sha1 md5 OK
self.assertIn('digests signatures OK', ret.output, 'Package signed incorrectly.')
shutil.rmtree(rpmdb)
#Check that an image can be built from signed packages
self.add_command_to_tearDown('bitbake -c clean core-image-minimal')
bitbake('-c clean core-image-minimal')
bitbake('core-image-minimal')
def test_signing_sstate_archive(self):
"""
Summary: Test that sstate archives can be signed
Expected: Package should be signed with the correct key
Product: oe-core
Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
"""
test_recipe = 'ed'
# Since we need gpg but we can't use gpg-native for sstate signatures, we
# build gpg-native in our original builddir then run the tests in a second one.
builddir = os.environ.get('BUILDDIR') + "-testsign"
sstatedir = os.path.join(builddir, 'test-sstate')
nsysroot = self.setup_gpg()
feature = 'SSTATE_SIG_KEY ?= "testuser"\n'
feature += 'SSTATE_SIG_PASSPHRASE ?= "test123"\n'
feature += 'SSTATE_VERIFY_SIG ?= "1"\n'
feature += 'GPG_PATH = "%s"\n' % self.gpg_dir
feature += 'SSTATE_DIR = "%s"\n' % sstatedir
# Any mirror might have partial sstate without .sig files, triggering failures
feature += 'SSTATE_MIRRORS_forcevariable = ""\n'
self.write_config(feature)
with self.create_new_builddir(os.environ['BUILDDIR'], builddir):
os.environ["PATH"] = nsysroot + ":" + os.environ["PATH"]
self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
self.add_command_to_tearDown('rm -rf %s' % sstatedir)
self.add_command_to_tearDown('rm -rf %s' % builddir)
bitbake('-c clean %s' % test_recipe)
bitbake('-c populate_lic %s' % test_recipe)
recipe_sig = glob.glob(sstatedir + '/*/*:ed:*_populate_lic.tgz.sig')
recipe_tgz = glob.glob(sstatedir + '/*/*:ed:*_populate_lic.tgz')
self.assertEqual(len(recipe_sig), 1, 'Failed to find .sig file.')
self.assertEqual(len(recipe_tgz), 1, 'Failed to find .tgz file.')
ret = runCmd('gpg --homedir %s --verify %s %s' % (self.gpg_dir, recipe_sig[0], recipe_tgz[0]))
# gpg: Signature made Thu 22 Oct 2015 01:45:09 PM EEST using RSA key ID 61EEFB30
# gpg: Good signature from "testuser (nocomment) <testuser@email.com>"
self.assertIn('gpg: Good signature from', ret.output, 'Package signed incorrectly.')
class LockedSignatures(OESelftestTestCase):
def test_locked_signatures(self):
"""
Summary: Test locked signature mechanism
Expected: Locked signatures will prevent task to run
Product: oe-core
Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
"""
test_recipe = 'ed'
locked_sigs_file = 'locked-sigs.inc'
self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file))
bitbake(test_recipe)
# Generate locked sigs include file
bitbake('-S none %s' % test_recipe)
feature = 'require %s\n' % locked_sigs_file
feature += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "warn"\n'
self.write_config(feature)
# Build a locked recipe
bitbake(test_recipe)
# Make a change that should cause the locked task signature to change
recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend'
recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', test_recipe, recipe_append_file)
feature = 'SUMMARY += "test locked signature"\n'
os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', test_recipe))
write_file(recipe_append_path, feature)
self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe))
# Build the recipe again
ret = bitbake(test_recipe)
# Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked)
patt = r'WARNING: The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe
found_warn = re.search(patt, ret.output)
self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)