From 58aa8824f3d611473b9e4e4b732e2d6b826c98ba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 20 Feb 2026 01:56:52 +0900 Subject: [PATCH] test_ukify: apply "ruff format" Also drops unnecessary noqa attribute for importing pefile. --- src/ukify/test/test_ukify.py | 545 ++++++++++++++++++++--------------- 1 file changed, 319 insertions(+), 226 deletions(-) diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py index 224a38569f..0fe27601f1 100755 --- a/src/ukify/test/test_ukify.py +++ b/src/ukify/test/test_ukify.py @@ -33,8 +33,7 @@ except ImportError as e: sys.exit(77) try: - # pyflakes: noqa - import pefile # noqa + import pefile except ImportError as e: print(str(e), file=sys.stderr) sys.exit(77) @@ -59,42 +58,51 @@ except ValueError: slow_tests = True arg_tools = ['--tools', build_root] if build_root else [] -if build_root and ( - p := pathlib.Path(f"{build_root}/linux{ukify.guess_efi_arch()}.efi.stub") -).exists(): +if ( + build_root + and (p := pathlib.Path(f'{build_root}/linux{ukify.guess_efi_arch()}.efi.stub')).exists() +): # fmt: skip arg_tools += ['--stub', p] + def systemd_measure(): opts = ukify.create_parser().parse_args(arg_tools) return ukify.find_tool('systemd-measure', opts=opts) + def test_guess_efi_arch(): arch = ukify.guess_efi_arch() assert arch in ukify.EFI_ARCHES + def test_shell_join(): assert ukify.shell_join(['a', 'b', ' ']) == "a b ' '" + def test_round_up(): assert ukify.round_up(0) == 0 assert ukify.round_up(4095) == 4096 assert ukify.round_up(4096) == 4096 assert ukify.round_up(4097) == 8192 + def test_namespace_creation(): ns = ukify.create_parser().parse_args(()) assert ns.linux is None assert ns.initrd is None + def test_config_example(): ex = ukify.config_example() assert '[UKI]' in ex assert 'Splash = BMP' in ex + def test_apply_config(tmp_path): config = tmp_path / 'config1.conf' - config.write_text(textwrap.dedent( - f''' + config.write_text( + textwrap.dedent( + f''' [UKI] Linux = LINUX Initrd = initrd1 initrd2 @@ -117,7 +125,9 @@ def test_apply_config(tmp_path): PCRPrivateKey = some/path7 PCRPublicKey = some/path8 Phases = {':'.join(ukify.KNOWN_PHASES)} - ''')) + ''' + ) + ) ns = ukify.create_parser().parse_args(['build']) ns.linux = None @@ -125,9 +135,11 @@ def test_apply_config(tmp_path): ukify.apply_config(ns, config) assert ns.linux == pathlib.Path('LINUX') - assert ns.initrd == [pathlib.Path('initrd1'), - pathlib.Path('initrd2'), - pathlib.Path('initrd3')] + assert ns.initrd == [ + pathlib.Path('initrd1'), + pathlib.Path('initrd2'), + pathlib.Path('initrd3'), + ] assert ns.cmdline == '1 2 3 4 5\n6 7 8' assert ns.os_release == '@some/path1' assert ns.devicetree == pathlib.Path('some/path2') @@ -148,9 +160,11 @@ def test_apply_config(tmp_path): ukify.finalize_options(ns) assert ns.linux == pathlib.Path('LINUX') - assert ns.initrd == [pathlib.Path('initrd1'), - pathlib.Path('initrd2'), - pathlib.Path('initrd3')] + assert ns.initrd == [ + pathlib.Path('initrd1'), + pathlib.Path('initrd2'), + pathlib.Path('initrd3'), + ] assert ns.cmdline == '1 2 3 4 5 6 7 8' assert ns.os_release == pathlib.Path('some/path1') assert ns.devicetree == pathlib.Path('some/path2') @@ -168,6 +182,7 @@ def test_apply_config(tmp_path): assert ns.pcr_public_keys == ['some/path8'] assert ns.phase_path_groups == [['enter-initrd:leave-initrd:sysinit:ready:shutdown:final']] + def test_parse_args_minimal(): with pytest.raises(ValueError): ukify.parse_args([]) @@ -175,32 +190,39 @@ def test_parse_args_minimal(): opts = ukify.parse_args('arg1 arg2'.split()) assert opts.linux == pathlib.Path('arg1') assert opts.initrd == [pathlib.Path('arg2')] - assert opts.os_release in (pathlib.Path('/etc/os-release'), - pathlib.Path('/usr/lib/os-release')) + assert opts.os_release in ( + pathlib.Path('/etc/os-release'), + pathlib.Path('/usr/lib/os-release'), + ) + def test_parse_args_many_deprecated(): opts = ukify.parse_args( - ['/ARG1', '///ARG2', '/ARG3 WITH SPACE', - '--cmdline=a b c', - '--os-release=K1=V1\nK2=V2', - '--devicetree=DDDDTTTT', - '--splash=splash', - '--pcrpkey=PATH', - '--uname=1.2.3', - '--stub=STUBPATH', - '--pcr-private-key=PKEY1', - '--pcr-public-key=PKEY2', - '--pcr-banks=SHA1,SHA256', - '--signing-engine=ENGINE', - '--secureboot-private-key=SBKEY', - '--secureboot-certificate=SBCERT', - '--sign-kernel', - '--no-sign-kernel', - '--tools=TOOLZ///', - '--output=OUTPUT', - '--measure', - '--no-measure', - ]) + [ + '/ARG1', + '///ARG2', + '/ARG3 WITH SPACE', + '--cmdline=a b c', + '--os-release=K1=V1\nK2=V2', + '--devicetree=DDDDTTTT', + '--splash=splash', + '--pcrpkey=PATH', + '--uname=1.2.3', + '--stub=STUBPATH', + '--pcr-private-key=PKEY1', + '--pcr-public-key=PKEY2', + '--pcr-banks=SHA1,SHA256', + '--signing-engine=ENGINE', + '--secureboot-private-key=SBKEY', + '--secureboot-certificate=SBCERT', + '--sign-kernel', + '--no-sign-kernel', + '--tools=TOOLZ///', + '--output=OUTPUT', + '--measure', + '--no-measure', + ] + ) assert opts.linux == pathlib.Path('/ARG1') assert opts.initrd == [pathlib.Path('/ARG2'), pathlib.Path('/ARG3 WITH SPACE')] assert opts.cmdline == 'a b c' @@ -221,34 +243,37 @@ def test_parse_args_many_deprecated(): assert opts.output == pathlib.Path('OUTPUT') assert opts.measure is False + def test_parse_args_many(): opts = ukify.parse_args( - ['build', - '--linux=/ARG1', - '--initrd=///ARG2', - '--initrd=/ARG3 WITH SPACE', - '--cmdline=a b c', - '--os-release=K1=V1\nK2=V2', - '--devicetree=DDDDTTTT', - '--splash=splash', - '--pcrpkey=PATH', - '--uname=1.2.3', - '--stub=STUBPATH', - '--pcr-private-key=PKEY1', - '--pcr-public-key=PKEY2', - '--pcr-banks=SHA1,SHA256', - '--signing-engine=ENGINE', - '--secureboot-private-key=SBKEY', - '--secureboot-certificate=SBCERT', - '--sign-kernel', - '--no-sign-kernel', - '--tools=TOOLZ///', - '--output=OUTPUT', - '--measure', - '--no-measure', - '--policy-digest', - '--no-policy-digest', - ]) + [ + 'build', + '--linux=/ARG1', + '--initrd=///ARG2', + '--initrd=/ARG3 WITH SPACE', + '--cmdline=a b c', + '--os-release=K1=V1\nK2=V2', + '--devicetree=DDDDTTTT', + '--splash=splash', + '--pcrpkey=PATH', + '--uname=1.2.3', + '--stub=STUBPATH', + '--pcr-private-key=PKEY1', + '--pcr-public-key=PKEY2', + '--pcr-banks=SHA1,SHA256', + '--signing-engine=ENGINE', + '--secureboot-private-key=SBKEY', + '--secureboot-certificate=SBCERT', + '--sign-kernel', + '--no-sign-kernel', + '--tools=TOOLZ///', + '--output=OUTPUT', + '--measure', + '--no-measure', + '--policy-digest', + '--no-policy-digest', + ] + ) assert opts.linux == pathlib.Path('/ARG1') assert opts.initrd == [pathlib.Path('/ARG2'), pathlib.Path('/ARG3 WITH SPACE')] assert opts.cmdline == 'a b c' @@ -270,14 +295,17 @@ def test_parse_args_many(): assert opts.measure is False assert opts.policy_digest is False + def test_parse_sections(): opts = ukify.parse_args( - ['build', - '--linux=/ARG1', - '--initrd=/ARG2', - '--section=test:TESTTESTTEST', - '--section=test2:@FILE', - ]) + [ + 'build', + '--linux=/ARG1', + '--initrd=/ARG2', + '--section=test:TESTTESTTEST', + '--section=test2:@FILE', + ] + ) assert opts.linux == pathlib.Path('/ARG1') assert opts.initrd == [pathlib.Path('/ARG2')] @@ -293,11 +321,13 @@ def test_parse_sections(): assert opts.sections[1].tmpfile is None assert opts.sections[1].measure is False + def test_config_priority(tmp_path): config = tmp_path / 'config1.conf' # config: use pesign and give certdir + certname - config.write_text(textwrap.dedent( - f''' + config.write_text( + textwrap.dedent( + f''' [UKI] Linux = LINUX Initrd = initrd1 initrd2 @@ -321,44 +351,50 @@ def test_config_priority(tmp_path): PCRPrivateKey = some/path7 PCRPublicKey = some/path8 Phases = {':'.join(ukify.KNOWN_PHASES)} - ''')) + ''' + ) + ) # args: use sbsign and give key + cert, should override pesign opts = ukify.parse_args( - ['build', - '--linux=/ARG1', - '--initrd=///ARG2', - '--initrd=/ARG3 WITH SPACE', - '--cmdline= a b c ', - '--os-release=K1=V1\nK2=V2', - '--devicetree=DDDDTTTT', - '--splash=splash', - '--pcrpkey=PATH', - '--uname=1.2.3', - '--stub=STUBPATH', - '--pcr-private-key=PKEY1', - '--pcr-public-key=PKEY2', - '--pcr-banks=SHA1,SHA256', - '--signing-engine=ENGINE', - '--signtool=sbsign', - '--secureboot-private-key=SBKEY', - '--secureboot-certificate=SBCERT', - '--sign-kernel', - '--no-sign-kernel', - '--tools=TOOLZ///', - '--output=OUTPUT', - '--measure', - ]) + [ + 'build', + '--linux=/ARG1', + '--initrd=///ARG2', + '--initrd=/ARG3 WITH SPACE', + '--cmdline= a b c ', + '--os-release=K1=V1\nK2=V2', + '--devicetree=DDDDTTTT', + '--splash=splash', + '--pcrpkey=PATH', + '--uname=1.2.3', + '--stub=STUBPATH', + '--pcr-private-key=PKEY1', + '--pcr-public-key=PKEY2', + '--pcr-banks=SHA1,SHA256', + '--signing-engine=ENGINE', + '--signtool=sbsign', + '--secureboot-private-key=SBKEY', + '--secureboot-certificate=SBCERT', + '--sign-kernel', + '--no-sign-kernel', + '--tools=TOOLZ///', + '--output=OUTPUT', + '--measure', + ] + ) ukify.apply_config(opts, config) ukify.finalize_options(opts) assert opts.linux == pathlib.Path('/ARG1') - assert opts.initrd == [pathlib.Path('initrd1'), - pathlib.Path('initrd2'), - pathlib.Path('initrd3'), - pathlib.Path('/ARG2'), - pathlib.Path('/ARG3 WITH SPACE')] + assert opts.initrd == [ + pathlib.Path('initrd1'), + pathlib.Path('initrd2'), + pathlib.Path('initrd3'), + pathlib.Path('/ARG2'), + pathlib.Path('/ARG3 WITH SPACE'), + ] assert opts.cmdline == 'a b c' assert opts.os_release == 'K1=V1\nK2=V2' assert opts.devicetree == pathlib.Path('DDDDTTTT') @@ -370,16 +406,17 @@ def test_config_priority(tmp_path): assert opts.pcr_public_keys == ['PKEY2', 'some/path8'] assert opts.pcr_banks == ['SHA1', 'SHA256'] assert opts.signing_engine == 'ENGINE' - assert opts.signtool == 'sbsign' # from args - assert opts.sb_key == 'SBKEY' # from args - assert opts.sb_cert == pathlib.Path('SBCERT') # from args - assert opts.sb_certdir == 'some/path5' # from config - assert opts.sb_cert_name == 'some/name1' # from config + assert opts.signtool == 'sbsign' # from args + assert opts.sb_key == 'SBKEY' # from args + assert opts.sb_cert == pathlib.Path('SBCERT') # from args + assert opts.sb_certdir == 'some/path5' # from config + assert opts.sb_cert_name == 'some/name1' # from config assert opts.sign_kernel is False assert opts.tools == [pathlib.Path('TOOLZ/')] assert opts.output == pathlib.Path('OUTPUT') assert opts.measure is True + def test_help(capsys): with pytest.raises(SystemExit): ukify.parse_args(['--help']) @@ -387,6 +424,7 @@ def test_help(capsys): assert '--section' in out.out assert not out.err + def test_help_display(capsys): with pytest.raises(SystemExit): ukify.parse_args(['inspect', '--help']) @@ -394,6 +432,7 @@ def test_help_display(capsys): assert '--section' in out.out assert not out.err + def test_help_error_deprecated(capsys): with pytest.raises(SystemExit): ukify.parse_args(['a', 'b', '--no-such-option']) @@ -402,6 +441,7 @@ def test_help_error_deprecated(capsys): assert '--no-such-option' in out.err assert len(out.err.splitlines()) == 1 + def test_help_error(capsys): with pytest.raises(SystemExit): ukify.parse_args(['build', '--no-such-option']) @@ -410,6 +450,7 @@ def test_help_error(capsys): assert '--no-such-option' in out.err assert len(out.err.splitlines()) == 1 + @pytest.fixture(scope='session') def kernel_initrd(): items = sorted(glob.glob('/lib/modules/*/vmlinuz')) @@ -426,6 +467,7 @@ def kernel_initrd(): # We don't look _into_ the initrd. Any file is OK. return ['--linux', linux, '--initrd', ukify.__file__] + def test_check_splash(): try: # pyflakes: noqa @@ -436,16 +478,19 @@ def test_check_splash(): with pytest.raises(OSError): ukify.check_splash(os.devnull) + def test_basic_operation(kernel_initrd, tmp_path): if kernel_initrd is None: pytest.skip('linux+initrd not found') output = f'{tmp_path}/basic.efi' - opts = ukify.parse_args([ - 'build', - *kernel_initrd, - f'--output={output}', - ]) + opts = ukify.parse_args( + [ + 'build', + *kernel_initrd, + f'--output={output}', + ] + ) try: ukify.check_inputs(opts) except OSError as e: @@ -458,20 +503,23 @@ def test_basic_operation(kernel_initrd, tmp_path): shutil.rmtree(tmp_path) + def test_sections(kernel_initrd, tmp_path): if kernel_initrd is None: pytest.skip('linux+initrd not found') output = f'{tmp_path}/basic.efi' - opts = ukify.parse_args([ - 'build', - *kernel_initrd, - f'--output={output}', - '--uname=1.2.3', - '--cmdline=ARG1 ARG2 ARG3', - '--os-release=K1=V1\nK2=V2\n', - '--section=.test:CONTENTZ', - ]) + opts = ukify.parse_args( + [ + 'build', + *kernel_initrd, + f'--output={output}', + '--uname=1.2.3', + '--cmdline=ARG1 ARG2 ARG3', + '--os-release=K1=V1\nK2=V2\n', + '--section=.test:CONTENTZ', + ] + ) try: ukify.check_inputs(opts) @@ -484,24 +532,25 @@ def test_sections(kernel_initrd, tmp_path): dump = subprocess.check_output(['objdump', '-h', output], text=True) for sect in 'text osrel cmdline linux initrd uname test'.split(): - assert re.search(fr'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) + assert re.search(rf'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) shutil.rmtree(tmp_path) + def test_addon(tmp_path): output = f'{tmp_path}/addon.efi' args = [ 'build', f'--output={output}', '--cmdline=ARG1 ARG2 ARG3', - """--sbat=sbat,1,foo + '''--sbat=sbat,1,foo foo,1 bar,2 -""", +''', '--section=.test:CONTENTZ', - """--sbat=sbat,1,foo + '''--sbat=sbat,1,foo baz,3 -""" +''', ] if stub := os.getenv('EFI_ADDON'): args += [f'--stub={stub}'] @@ -521,26 +570,33 @@ baz,3 dump = subprocess.check_output(['objdump', '-h', output], text=True) for sect in 'text cmdline test sbat'.split(): - assert re.search(fr'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) + assert re.search(rf'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) pe = pefile.PE(output, fast_load=True) found = False for section in pe.sections: - if section.Name.rstrip(b"\x00").decode() == ".sbat": + if section.Name.rstrip(b'\x00').decode() == '.sbat': assert found is False - split = section.get_data().rstrip(b"\x00").decode().splitlines() - assert split == ["sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md", "foo,1", "bar,2", "baz,3"] + split = section.get_data().rstrip(b'\x00').decode().splitlines() + assert split == [ + 'sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md', + 'foo,1', + 'bar,2', + 'baz,3', + ] found = True assert found is True + def unbase64(filename): tmp = tempfile.NamedTemporaryFile() base64.decode(filename.open('rb'), tmp) tmp.flush() return tmp + def test_uname_scraping(kernel_initrd): if kernel_initrd is None: pytest.skip('linux+initrd not found') @@ -549,8 +605,9 @@ def test_uname_scraping(kernel_initrd): uname = ukify.Uname.scrape(kernel_initrd[1]) assert re.match(r'\d+\.\d+\.\d+', uname) + @pytest.mark.skipif(not slow_tests, reason='slow') -@pytest.mark.parametrize("days", [365*10, None]) +@pytest.mark.parametrize('days', [365 * 10, None]) def test_efi_signing_sbsign(days, kernel_initrd, tmp_path): if kernel_initrd is None: pytest.skip('linux+initrd not found') @@ -585,16 +642,20 @@ def test_efi_signing_sbsign(days, kernel_initrd, tmp_path): if shutil.which('sbverify'): # let's check that sbverify likes the resulting file - dump = subprocess.check_output([ - 'sbverify', - '--cert', cert.name, - output, - ], text=True) + dump = subprocess.check_output( + [ + 'sbverify', + '--cert', cert.name, + output, + ], + text=True, + ) # fmt: skip assert 'Signature verification OK' in dump shutil.rmtree(tmp_path) + @pytest.mark.skipif(not slow_tests, reason='slow') def test_efi_signing_pesign(kernel_initrd, tmp_path): if kernel_initrd is None: @@ -613,16 +674,18 @@ def test_efi_signing_pesign(kernel_initrd, tmp_path): subprocess.check_call(cmd) output = f'{tmp_path}/signed.efi' - opts = ukify.parse_args([ - 'build', - *kernel_initrd, - f'--output={output}', - '--uname=1.2.3', - '--signtool=pesign', - '--cmdline=ARG1 ARG2 ARG3', - f'--secureboot-certificate-name={name}', - f'--secureboot-certificate-dir={nss_db}', - ]) + opts = ukify.parse_args( + [ + 'build', + *kernel_initrd, + f'--output={output}', + '--uname=1.2.3', + '--signtool=pesign', + '--cmdline=ARG1 ARG2 ARG3', + f'--secureboot-certificate-name={name}', + f'--secureboot-certificate-dir={nss_db}', + ] + ) try: ukify.check_inputs(opts) @@ -632,15 +695,20 @@ def test_efi_signing_pesign(kernel_initrd, tmp_path): ukify.make_uki(opts) # let's check that pesign likes the resulting file - dump = subprocess.check_output([ - 'pesign', '-S', - '-i', output, - ], text=True) + dump = subprocess.check_output( + [ + 'pesign', + '-S', + '-i', output, + ], + text=True, + ) # fmt: skip assert f"The signer's common name is {author}" in dump shutil.rmtree(tmp_path) + def test_inspect(kernel_initrd, tmp_path, capsys, osrel=True): if kernel_initrd is None: pytest.skip('linux+initrd not found') @@ -652,9 +720,9 @@ def test_inspect(kernel_initrd, tmp_path, capsys, osrel=True): key = unbase64(ourdir / 'example.signing.key.base64') output = f'{tmp_path}/signed2.efi' - uname_arg='1.2.3' - osrel_arg='Linux' if osrel else '' - cmdline_arg='ARG1 ARG2 ARG3' + uname_arg = '1.2.3' + osrel_arg = 'Linux' if osrel else '' + cmdline_arg = 'ARG1 ARG2 ARG3' args = [ 'build', @@ -698,9 +766,11 @@ def test_inspect(kernel_initrd, tmp_path, capsys, osrel=True): shutil.rmtree(tmp_path) + def test_inspect_no_osrel(kernel_initrd, tmp_path, capsys): test_inspect(kernel_initrd, tmp_path, capsys, osrel=False) + @pytest.mark.skipif(not slow_tests, reason='slow') def test_pcr_signing(kernel_initrd, tmp_path): if kernel_initrd is None: @@ -722,7 +792,7 @@ def test_pcr_signing(kernel_initrd, tmp_path): '--uname=1.2.3', '--cmdline=ARG1 ARG2 ARG3', '--os-release=ID=foobar\n', - '--pcr-banks=sha384', # sha1 might not be allowed, use something else + '--pcr-banks=sha384', # sha1 might not be allowed, use something else f'--pcr-private-key={priv.name}', ] + arg_tools @@ -743,21 +813,25 @@ def test_pcr_signing(kernel_initrd, tmp_path): dump = subprocess.check_output(['objdump', '-h', output], text=True) for sect in 'text osrel cmdline linux initrd uname pcrsig'.split(): - assert re.search(fr'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) + assert re.search(rf'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) # objcopy fails when called without an output argument (EPERM). # It also fails when called with /dev/null (file truncated). # It also fails when called with /dev/zero (because it reads the # output file, infinitely in this case.) # So let's just call it with a dummy output argument. - subprocess.check_call([ - 'objcopy', - *(f'--dump-section=.{n}={tmp_path}/out.{n}' for n in ( - 'pcrpkey', 'pcrsig', 'osrel', 'uname', 'cmdline')), - output, - tmp_path / 'dummy', - ], - text=True) + subprocess.check_call( + [ + 'objcopy', + *( + f'--dump-section=.{n}={tmp_path}/out.{n}' + for n in ('pcrpkey', 'pcrsig', 'osrel', 'uname', 'cmdline') + ), + output, + tmp_path / 'dummy', + ], + text=True, + ) assert open(tmp_path / 'out.pcrpkey').read() == open(pub.name).read() assert open(tmp_path / 'out.osrel').read() == 'ID=foobar\n' @@ -766,10 +840,11 @@ def test_pcr_signing(kernel_initrd, tmp_path): sig = open(tmp_path / 'out.pcrsig').read() sig = json.loads(sig) assert list(sig.keys()) == ['sha384'] - assert len(sig['sha384']) == 4 # four items for four phases + assert len(sig['sha384']) == 4 # four items for four phases shutil.rmtree(tmp_path) + @pytest.mark.skipif(not slow_tests, reason='slow') def test_pcr_signing2(kernel_initrd, tmp_path): if kernel_initrd is None: @@ -791,24 +866,27 @@ def test_pcr_signing2(kernel_initrd, tmp_path): output = f'{tmp_path}/signed.efi' assert kernel_initrd[0] == '--linux' - opts = ukify.parse_args([ - 'build', - *kernel_initrd[:2], - f'--initrd={microcode.name}', - *kernel_initrd[2:], - f'--output={output}', - '--uname=1.2.3', - '--cmdline=ARG1 ARG2 ARG3', - '--os-release=ID=foobar\n', - '--pcr-banks=sha384', - f'--pcrpkey={pub2.name}', - f'--pcr-public-key={pub.name}', - f'--pcr-private-key={priv.name}', - '--phases=enter-initrd enter-initrd:leave-initrd', - f'--pcr-public-key={pub2.name}', - f'--pcr-private-key={priv2.name}', - '--phases=sysinit ready shutdown final', # yes, those phase paths are not reachable - ] + arg_tools) + opts = ukify.parse_args( + [ + 'build', + *kernel_initrd[:2], + f'--initrd={microcode.name}', + *kernel_initrd[2:], + f'--output={output}', + '--uname=1.2.3', + '--cmdline=ARG1 ARG2 ARG3', + '--os-release=ID=foobar\n', + '--pcr-banks=sha384', + f'--pcrpkey={pub2.name}', + f'--pcr-public-key={pub.name}', + f'--pcr-private-key={priv.name}', + '--phases=enter-initrd enter-initrd:leave-initrd', + f'--pcr-public-key={pub2.name}', + f'--pcr-private-key={priv2.name}', + '--phases=sysinit ready shutdown final', # yes, those phase paths are not reachable + ] + + arg_tools + ) try: ukify.check_inputs(opts) @@ -821,16 +899,20 @@ def test_pcr_signing2(kernel_initrd, tmp_path): dump = subprocess.check_output(['objdump', '-h', output], text=True) for sect in 'text osrel cmdline linux initrd uname pcrsig'.split(): - assert re.search(fr'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) + assert re.search(rf'^\s*\d+\s+\.{sect}\s+[0-9a-f]+', dump, re.MULTILINE) - subprocess.check_call([ - 'objcopy', - *(f'--dump-section=.{n}={tmp_path}/out.{n}' for n in ( - 'pcrpkey', 'pcrsig', 'osrel', 'uname', 'cmdline', 'initrd')), - output, - tmp_path / 'dummy', - ], - text=True) + subprocess.check_call( + [ + 'objcopy', + *( + f'--dump-section=.{n}={tmp_path}/out.{n}' + for n in ('pcrpkey', 'pcrsig', 'osrel', 'uname', 'cmdline', 'initrd') + ), + output, + tmp_path / 'dummy', + ], + text=True, + ) assert open(tmp_path / 'out.pcrpkey').read() == open(pub2.name).read() assert open(tmp_path / 'out.osrel').read() == 'ID=foobar\n' @@ -841,22 +923,25 @@ def test_pcr_signing2(kernel_initrd, tmp_path): sig = open(tmp_path / 'out.pcrsig').read() sig = json.loads(sig) assert list(sig.keys()) == ['sha384'] - assert len(sig['sha384']) == 6 # six items for six phases paths + assert len(sig['sha384']) == 6 # six items for six phases paths shutil.rmtree(tmp_path) + def test_key_cert_generation(tmp_path): - opts = ukify.parse_args([ - 'genkey', - f"--pcr-public-key={tmp_path / 'pcr1.pub.pem'}", - f"--pcr-private-key={tmp_path / 'pcr1.priv.pem'}", - '--phases=enter-initrd enter-initrd:leave-initrd', - f"--pcr-public-key={tmp_path / 'pcr2.pub.pem'}", - f"--pcr-private-key={tmp_path / 'pcr2.priv.pem'}", - '--phases=sysinit ready', - f"--secureboot-private-key={tmp_path / 'sb.priv.pem'}", - f"--secureboot-certificate={tmp_path / 'sb.cert.pem'}", - ]) + opts = ukify.parse_args( + [ + 'genkey', + f'--pcr-public-key={tmp_path / "pcr1.pub.pem"}', + f'--pcr-private-key={tmp_path / "pcr1.priv.pem"}', + '--phases=enter-initrd enter-initrd:leave-initrd', + f'--pcr-public-key={tmp_path / "pcr2.pub.pem"}', + f'--pcr-private-key={tmp_path / "pcr2.priv.pem"}', + '--phases=sysinit ready', + f'--secureboot-private-key={tmp_path / "sb.priv.pem"}', + f'--secureboot-certificate={tmp_path / "sb.cert.pem"}', + ] + ) assert opts.verb == 'genkey' ukify.check_cert_and_keys_nonexistent(opts) @@ -867,39 +952,46 @@ def test_key_cert_generation(tmp_path): if not shutil.which('openssl'): return - for key in (tmp_path / 'pcr1.priv.pem', - tmp_path / 'pcr2.priv.pem', - tmp_path / 'sb.priv.pem'): - out = subprocess.check_output([ - 'openssl', 'rsa', - '-in', key, - '-text', - '-noout', - ], text = True) + for key in (tmp_path / 'pcr1.priv.pem', tmp_path / 'pcr2.priv.pem', tmp_path / 'sb.priv.pem'): + out = subprocess.check_output( + [ + 'openssl', 'rsa', + '-in', key, + '-text', + '-noout', + ], + text=True, + ) # fmt: skip assert 'Private-Key' in out assert '2048 bit' in out - for pub in (tmp_path / 'pcr1.pub.pem', - tmp_path / 'pcr2.pub.pem'): - out = subprocess.check_output([ - 'openssl', 'rsa', - '-pubin', - '-in', pub, - '-text', - '-noout', - ], text = True) + for pub in (tmp_path / 'pcr1.pub.pem', tmp_path / 'pcr2.pub.pem'): + out = subprocess.check_output( + [ + 'openssl', 'rsa', + '-pubin', + '-in', pub, + '-text', + '-noout', + ], + text=True, + ) # fmt: skip assert 'Public-Key' in out assert '2048 bit' in out - out = subprocess.check_output([ - 'openssl', 'x509', - '-in', tmp_path / 'sb.cert.pem', - '-text', - '-noout', - ], text = True) + out = subprocess.check_output( + [ + 'openssl', 'x509', + '-in', tmp_path / 'sb.cert.pem', + '-text', + '-noout', + ], + text=True, + ) # fmt: skip assert 'Certificate' in out assert re.search(r'Issuer: CN\s?=\s?SecureBoot signing key on host', out) + @pytest.mark.skipif(not slow_tests, reason='slow') def test_join_pcrsig(capsys, kernel_initrd, tmp_path): if kernel_initrd is None: @@ -965,5 +1057,6 @@ def test_join_pcrsig(capsys, kernel_initrd, tmp_path): shutil.rmtree(tmp_path) + if __name__ == '__main__': sys.exit(pytest.main(sys.argv))