org.osbuild.grub2.iso.legacy: Add support for optional fips menu
On RHEL 9.7+ and on RHEL 10.1+ we need to be able to include a menu that boots the installer environment with fips=1 on the cmdline. This adds an optional menu entry controlled by the "fips" boolean. This also includes a test for the new behavior. Related: RHEL-104075
This commit is contained in:
parent
9a563f8306
commit
d085681911
3 changed files with 60 additions and 8 deletions
|
|
@ -34,6 +34,7 @@ menuentry 'Test this media & install ${product} ${version}' --class fedora --cla
|
||||||
linux ${kernelpath} ${root} rd.live.check quiet
|
linux ${kernelpath} ${root} rd.live.check quiet
|
||||||
initrd ${initrdpath}
|
initrd ${initrdpath}
|
||||||
}
|
}
|
||||||
|
$fipsentry
|
||||||
submenu 'Troubleshooting -->' {
|
submenu 'Troubleshooting -->' {
|
||||||
menuentry 'Install ${product} ${version} in basic graphics mode' --class fedora --class gnu-linux --class gnu --class os {
|
menuentry 'Install ${product} ${version} in basic graphics mode' --class fedora --class gnu-linux --class gnu --class os {
|
||||||
linux ${kernelpath} ${root} nomodeset quiet
|
linux ${kernelpath} ${root} nomodeset quiet
|
||||||
|
|
@ -49,6 +50,14 @@ submenu 'Troubleshooting -->' {
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Optional FIPS menu entry
|
||||||
|
FIPS_ENTRY_TEMPLATE = """
|
||||||
|
menuentry 'Install ${product} ${version} in FIPS mode' --class fedora --class gnu-linux --class gnu --class os {
|
||||||
|
linux ${kernelpath} ${root} quiet fips=1
|
||||||
|
initrd ${initrdpath}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def main(root, options):
|
def main(root, options):
|
||||||
name = options["product"]["name"]
|
name = options["product"]["name"]
|
||||||
|
|
@ -58,6 +67,7 @@ def main(root, options):
|
||||||
kopts = options["kernel"].get("opts")
|
kopts = options["kernel"].get("opts")
|
||||||
cfg = options.get("config", {})
|
cfg = options.get("config", {})
|
||||||
timeout = cfg.get("timeout", 60)
|
timeout = cfg.get("timeout", 60)
|
||||||
|
fips = options.get("fips", False)
|
||||||
|
|
||||||
grub2dir = os.path.join(root, "boot", "grub2")
|
grub2dir = os.path.join(root, "boot", "grub2")
|
||||||
os.makedirs(grub2dir, exist_ok=True)
|
os.makedirs(grub2dir, exist_ok=True)
|
||||||
|
|
@ -67,17 +77,25 @@ def main(root, options):
|
||||||
shutil.copytree("/usr/lib/grub/i386-pc", moduledir, dirs_exist_ok=True)
|
shutil.copytree("/usr/lib/grub/i386-pc", moduledir, dirs_exist_ok=True)
|
||||||
|
|
||||||
print(f"kernel dir at {kdir}")
|
print(f"kernel dir at {kdir}")
|
||||||
|
tplt_variables = {
|
||||||
tplt = string.Template(GRUB2_CFG_TEMPLATE)
|
|
||||||
data = tplt.safe_substitute({
|
|
||||||
"version": version,
|
"version": version,
|
||||||
"product": name,
|
"product": name,
|
||||||
"kernelpath": os.path.join(kdir, "vmlinuz"),
|
"kernelpath": os.path.join(kdir, "vmlinuz"),
|
||||||
"initrdpath": os.path.join(kdir, "initrd.img"),
|
"initrdpath": os.path.join(kdir, "initrd.img"),
|
||||||
"isolabel": isolabel,
|
"isolabel": isolabel,
|
||||||
"root": " ".join(kopts),
|
"root": " ".join(kopts),
|
||||||
"timeout": timeout
|
"timeout": timeout,
|
||||||
})
|
"fipsentry": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Insert optional fips menu entry
|
||||||
|
if fips:
|
||||||
|
fips_tmpl = string.Template(FIPS_ENTRY_TEMPLATE)
|
||||||
|
fipsentry = fips_tmpl.safe_substitute(tplt_variables)
|
||||||
|
tplt_variables["fipsentry"] = fipsentry
|
||||||
|
|
||||||
|
tplt = string.Template(GRUB2_CFG_TEMPLATE)
|
||||||
|
data = tplt.safe_substitute(tplt_variables)
|
||||||
|
|
||||||
config = os.path.join(grub2dir, "grub.cfg")
|
config = os.path.join(grub2dir, "grub.cfg")
|
||||||
with open(config, "w", encoding="utf8") as cfg:
|
with open(config, "w", encoding="utf8") as cfg:
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@
|
||||||
"isolabel": {
|
"isolabel": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"fips": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"description": "Configuration options for grub itself",
|
"description": "Configuration options for grub itself",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import pytest
|
||||||
|
|
||||||
STAGE_NAME = "org.osbuild.grub2.iso.legacy"
|
STAGE_NAME = "org.osbuild.grub2.iso.legacy"
|
||||||
|
|
||||||
expected_grub_cfg = """
|
CONFIG_PART_1 = """
|
||||||
function load_video {
|
function load_video {
|
||||||
insmod all_video
|
insmod all_video
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +33,9 @@ menuentry 'Test this media & install Fedora-IoT 41' --class fedora --class gnu-l
|
||||||
linux /images/pxeboot/vmlinuz inst.ks=hd:LABEL=Fedora-41-X86_64:/install.ks rd.live.check quiet
|
linux /images/pxeboot/vmlinuz inst.ks=hd:LABEL=Fedora-41-X86_64:/install.ks rd.live.check quiet
|
||||||
initrd /images/pxeboot/initrd.img
|
initrd /images/pxeboot/initrd.img
|
||||||
}
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
CONFIG_PART_2 = """
|
||||||
submenu 'Troubleshooting -->' {
|
submenu 'Troubleshooting -->' {
|
||||||
menuentry 'Install Fedora-IoT 41 in basic graphics mode' --class fedora --class gnu-linux --class gnu --class os {
|
menuentry 'Install Fedora-IoT 41 in basic graphics mode' --class fedora --class gnu-linux --class gnu --class os {
|
||||||
linux /images/pxeboot/vmlinuz inst.ks=hd:LABEL=Fedora-41-X86_64:/install.ks nomodeset quiet
|
linux /images/pxeboot/vmlinuz inst.ks=hd:LABEL=Fedora-41-X86_64:/install.ks nomodeset quiet
|
||||||
|
|
@ -48,9 +51,22 @@ submenu 'Troubleshooting -->' {
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
CONFIG_FIPS = """
|
||||||
|
menuentry 'Install Fedora-IoT 41 in FIPS mode' --class fedora --class gnu-linux --class gnu --class os {
|
||||||
|
linux /images/pxeboot/vmlinuz inst.ks=hd:LABEL=Fedora-41-X86_64:/install.ks quiet fips=1
|
||||||
|
initrd /images/pxeboot/initrd.img
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@patch("shutil.copytree")
|
@patch("shutil.copytree")
|
||||||
def test_grub2_iso_legacy_smoke(mocked_copytree, tmp_path, stage_module):
|
@pytest.mark.parametrize("test_data,expected_conf", [
|
||||||
|
# default
|
||||||
|
({}, CONFIG_PART_1 + CONFIG_PART_2),
|
||||||
|
# fips menu enable
|
||||||
|
({"fips": True}, CONFIG_PART_1 + CONFIG_FIPS + CONFIG_PART_2)
|
||||||
|
])
|
||||||
|
def test_grub2_iso_legacy_smoke(mocked_copytree, tmp_path, stage_module, test_data, expected_conf):
|
||||||
treedir = tmp_path / "tree"
|
treedir = tmp_path / "tree"
|
||||||
confpath = treedir / "boot/grub2/grub.cfg"
|
confpath = treedir / "boot/grub2/grub.cfg"
|
||||||
confpath.parent.mkdir(parents=True, exist_ok=True)
|
confpath.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
@ -72,11 +88,12 @@ def test_grub2_iso_legacy_smoke(mocked_copytree, tmp_path, stage_module):
|
||||||
"timeout": 10,
|
"timeout": 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
options.update(test_data)
|
||||||
|
|
||||||
stage_module.main(treedir, options)
|
stage_module.main(treedir, options)
|
||||||
|
|
||||||
assert os.path.exists(confpath)
|
assert os.path.exists(confpath)
|
||||||
assert confpath.read_text() == expected_grub_cfg
|
assert confpath.read_text() == expected_conf
|
||||||
assert mocked_copytree.call_args_list == [
|
assert mocked_copytree.call_args_list == [
|
||||||
call("/usr/lib/grub/i386-pc", os.fspath(treedir / "boot/grub2/i386-pc"),
|
call("/usr/lib/grub/i386-pc", os.fspath(treedir / "boot/grub2/i386-pc"),
|
||||||
dirs_exist_ok=True),
|
dirs_exist_ok=True),
|
||||||
|
|
@ -120,6 +137,20 @@ def test_grub2_iso_legacy_smoke(mocked_copytree, tmp_path, stage_module):
|
||||||
},
|
},
|
||||||
}, "",
|
}, "",
|
||||||
),
|
),
|
||||||
|
# good + fips
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"isolabel": "an-isolabel",
|
||||||
|
"product": {
|
||||||
|
"name": "a-name",
|
||||||
|
"version": "a-version",
|
||||||
|
},
|
||||||
|
"kernel": {
|
||||||
|
"dir": "/path/to",
|
||||||
|
},
|
||||||
|
"fips": True,
|
||||||
|
}, "",
|
||||||
|
),
|
||||||
])
|
])
|
||||||
def test_schema_validation(stage_schema, test_data, expected_err):
|
def test_schema_validation(stage_schema, test_data, expected_err):
|
||||||
test_input = {
|
test_input = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue