From da6941e2a80697e31c0f62c0f62c52f570ebb7e9 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 5 Oct 2026 22:41:37 +0200 Subject: op-mode: T861: add "show secure-boot detail" command "show secure-boot" only reported whether Secure Boot is enabled, not who signed the running Linux Kernel. An image signed by the VyOS CA could not be told apart from one signed with a custom Machine Owner Key. "show secure-boot detail" now lists issuer and subject of the Kernel image signature certificates. The same information is added to the raw "show version" data as "secure_boot_detail", issuer and subject delimited by ",". The key is only present when Secure Boot is enabled and a signature could be read. --- src/op_mode/secure_boot.py | 21 +++++++++++++++++++++ src/op_mode/version.py | 11 +++++++++++ 2 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/op_mode/secure_boot.py b/src/op_mode/secure_boot.py index a2d4c9e72..70c4371e6 100755 --- a/src/op_mode/secure_boot.py +++ b/src/op_mode/secure_boot.py @@ -18,6 +18,7 @@ import sys import vyos.opmode from vyos.utils.boot import is_uefi_system +from vyos.utils.system import get_secure_boot_certificates from vyos.utils.system import get_secure_boot_state def _get_raw_data(name=None): @@ -40,6 +41,26 @@ def show(raw: bool): else: return _get_formatted_output(sb_data) +def _get_formatted_detail(certificates): + out = [] + for certificate in certificates: + out.append(f'Issuer: {certificate["issuer"]}') + out.append(f'Subject: {certificate["subject"]}') + return '\n'.join(out) + +def show_detail(raw: bool): + if not get_secure_boot_state(): + raise vyos.opmode.UnsupportedOperation('SecureBoot disabled') + + certificates = get_secure_boot_certificates() + if not certificates: + raise vyos.opmode.DataUnavailable('No Linux Kernel signature certificate found') + + if raw: + return certificates + else: + return _get_formatted_detail(certificates) + if __name__ == "__main__": try: res = vyos.opmode.run(sys.modules[__name__]) diff --git a/src/op_mode/version.py b/src/op_mode/version.py index bc74f83fc..09ca62984 100755 --- a/src/op_mode/version.py +++ b/src/op_mode/version.py @@ -27,6 +27,7 @@ import vyos.limericks from vyos.utils.boot import is_uefi_system from vyos.system.image import is_running_as_container +from vyos.utils.system import get_secure_boot_certificates from vyos.utils.system import get_secure_boot_state from jinja2 import Template @@ -62,6 +63,13 @@ Copyright: VyOS maintainers and contributors {% endif -%} """ +def _get_secure_boot_detail(): + """ Return issuer and subject of the running Kernel image signature + certificates as "issuer, subject" - multiple signatures are delimited by + "; ". Returns None if no signature could be read. """ + certificates = get_secure_boot_certificates() + return '; '.join(f'{c["issuer"]}, {c["subject"]}' for c in certificates) or None + def _get_raw_data(funny=False): version_data = vyos.version.get_full_version_data() # A container has no firmware of its own - it is not booted at all, thus @@ -74,6 +82,9 @@ def _get_raw_data(funny=False): version_data["secure_boot"] = "disabled" if get_secure_boot_state(): version_data["secure_boot"] = "enabled" + detail = _get_secure_boot_detail() + if detail: + version_data["secure_boot_detail"] = detail if funny: version_data["limerick"] = vyos.limericks.get_random() -- cgit v1.2.3