@@ -296,6 +296,13 @@ class AzureImageStandard(TestSuite):
296296 # 1.1
297297 _openssl_version_pattern = re .compile (r"(?:Python\s*)?(\d+\.\d+(?:\.\d+)?)" )
298298
299+ # OMI-1.9.1-0 - Wed Aug 28 23:16:27 PDT 2024
300+ # ii omi 1.9.1.0 amd64 Open Management Infrastructure
301+ # omi-1.9.1-0.x86_64
302+ _omi_version_pattern = re .compile (
303+ r"(?:OMI-|omi\s+|omi-)(\d+\.\d+\.\d+(?:\.\d+|-\d+)?)"
304+ )
305+
299306 @TestCaseMetadata (
300307 description = """
301308 This test will verify that `Defaults targetpw` is not enabled in the
@@ -1330,7 +1337,7 @@ def verify_waagent_version(self, node: Node) -> None:
13301337 def verify_python_version (self , node : Node ) -> None :
13311338 minimum_version = Version ("3.8.0" )
13321339 python_command = ["python3 --version" , "python --version" ]
1333- self ._check_version_by_pattern_value (
1340+ self ._verify_version_by_pattern_value (
13341341 node = node ,
13351342 commands = python_command ,
13361343 version_pattern = self ._python_version_pattern ,
@@ -1357,7 +1364,7 @@ def verify_openssl_version(self, node: Node) -> None:
13571364 minimum_version = Version ("3.0.0" )
13581365 openssl_command = ["openssl version" ]
13591366 extended_support_versions = [Version ("1.1.1" ), Version ("1.0.2" )]
1360- self ._check_version_by_pattern_value (
1367+ self ._verify_version_by_pattern_value (
13611368 node = node ,
13621369 commands = openssl_command ,
13631370 version_pattern = self ._openssl_version_pattern ,
@@ -1388,7 +1395,72 @@ def verify_azure_64bit_os(self, node: Node) -> None:
13881395 f"64-bit architectures: { ', ' .join (str (a .value ) for a in arch_64bit )} ."
13891396 )
13901397
1391- def _check_version_by_pattern_value (
1398+ @TestCaseMetadata (
1399+ description = """
1400+ This test verifies the version of the Open Management Infrastructure (OMI)
1401+ version installed on the system is not vulnerable to the "OMIGOD"
1402+ vulnerabilities.
1403+
1404+ The "OMIGOD" vulnerabilities (CVE-2021-38647, CVE-2021-38648,
1405+ CVE-2021-38645, CVE-2021-38649) were fixed in OMI version 1.6.8.1.
1406+
1407+ OMI github: https://github.com/microsoft/omi
1408+
1409+ Steps:
1410+ 1. Check if OMI is installed on the system.
1411+ a. If OMI is installed, the version can be got by using
1412+ ""/opt/omi/bin/omiserver --version"" command.
1413+ b. If omiserver command fails, use ""dpkg -l omi | grep omi"" and
1414+ ""rpm -q omi"" to double-check whether the OMI package is installed.
1415+ c. If all the commands fail, it means OMI is not installed.
1416+ 2. Verify that the version is 1.6.8.1 or later.
1417+ 3. Pass if OMI is not installed or the version is secure.
1418+ """ ,
1419+ priority = 1 ,
1420+ requirement = simple_requirement (supported_platform_type = [AZURE ]),
1421+ )
1422+ def verify_omi_version (self , node : Node ) -> None :
1423+ minimum_secure_version = Version ("1.6.8.1" )
1424+ # LISA has node.os.package_exists to check if a package is installed. However,
1425+ # since this test case is for Azure image certification, we prefer to use
1426+ # simpler and more generic commands to support a wider range of distributions.
1427+ # OMI supports most modern Linux platforms, including Ubuntu, Debian, CentOS,
1428+ # Oracle, Red Hat, SUSE, Rocky, and Alma. All of these distributions include
1429+ # either the dpkg command (for Debian-based systems like Ubuntu and Debian)
1430+ # or the rpm command (for RPM-based systems like CentOS and SUSE).
1431+ commands = [
1432+ "/opt/omi/bin/omiserver --version" ,
1433+ "dpkg -l omi | grep omi" ,
1434+ "rpm -q omi" ,
1435+ ]
1436+
1437+ try :
1438+ self ._verify_version_by_pattern_value (
1439+ node = node ,
1440+ commands = commands ,
1441+ version_pattern = self ._omi_version_pattern ,
1442+ minimum_version = minimum_secure_version ,
1443+ library_name = "OMI" ,
1444+ )
1445+ except LisaException as e :
1446+ if "lower than the required version" in str (e ):
1447+ raise LisaException (
1448+ f"Vulnerable OMI version detected. You have an OMI framework "
1449+ f"version less than { minimum_secure_version } . "
1450+ f"Please update OMI to the version { minimum_secure_version } or "
1451+ "later. For more information, please see the OMI update guidance at"
1452+ " https://aka.ms/omi-updation."
1453+ ) from e
1454+ elif "Failed to retrieve" in str (e ):
1455+ node .log .info ("OMI is not installed on the system. Pass the case." )
1456+ elif "Failed to parse" in str (e ):
1457+ raise LisaException (
1458+ "OMI is installed but could not determine version. Please verify "
1459+ "manually that the OMI version is at least "
1460+ f"{ minimum_secure_version } to prevent OMIGOD vulnerabilities."
1461+ ) from e
1462+
1463+ def _verify_version_by_pattern_value (
13921464 self ,
13931465 node : Node ,
13941466 commands : List [str ],
@@ -1398,6 +1470,21 @@ def _check_version_by_pattern_value(
13981470 library_name : str = "library" ,
13991471 group_index : int = 1 ,
14001472 ) -> None :
1473+ """
1474+ Verifies the version of a library or tool against a minimum required version.
1475+ Args:
1476+ node: The node to execute commands on
1477+ commands: List of commands to try to get version information
1478+ version_pattern: Regex pattern to extract version string from command
1479+ output
1480+ minimum_version: Minimum required version. Please use dots (.) to separate
1481+ version numbers for proper version comparison, e.g. "1.2.3" or
1482+ "1.2.3.4"
1483+ extended_support_versions: Optional list of versions that are still
1484+ supported despite being lower than minimum_version
1485+ library_name: Name of the library/tool being checked (for messages)
1486+ group_index: Index of the regex group that contains the version string
1487+ """
14011488 version_output = None
14021489
14031490 for command in commands :
@@ -1417,7 +1504,17 @@ def _check_version_by_pattern_value(
14171504 f"Failed to parse { library_name } version from output: { version_output } "
14181505 )
14191506
1420- current_version = Version (match .group (group_index ))
1507+ # The reason we don't use 'parse_version' and 'LisaVersionInfo' here is because
1508+ # they don't support the four-part version like "1.2.3.4". Some versions of
1509+ # waagent have this format. So we use 'Version' class from 'packaging'.
1510+ #
1511+ # Version class supports multiple formats but is unable comparing versions with
1512+ # hyphens like "1.2.3-4" and "1.2.3-5". So we replace "-" with "." for proper
1513+ # version comparison.
1514+ #
1515+ # e.g. the version of OMI has the format of "1.9.0-1". Changing it to "1.9.0.1"
1516+ # allows proper comparison with the minimum version.
1517+ current_version = Version (match .group (group_index ).replace ("-" , "." ))
14211518 if current_version < minimum_version :
14221519 message = (
14231520 f"The { library_name } version { current_version } is lower than the "
0 commit comments