ff3dbe1ea9
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=131
195 lines
8.7 KiB
Diff
195 lines
8.7 KiB
Diff
From 3bad9e211c2e76ddac48f7c8ff1632e32e0a256e Mon Sep 17 00:00:00 2001
|
|
From: Bo Maryniuk <bo@suse.de>
|
|
Date: Tue, 9 Oct 2018 14:08:50 +0200
|
|
Subject: [PATCH] Add CPE_NAME for osversion* grain parsing (U#49946)
|
|
|
|
Remove unnecessary linebreak
|
|
|
|
Override VERSION_ID from os-release, if CPE_NAME is given
|
|
|
|
Add unit test for WFN format of CPE_NAME
|
|
|
|
Add unit test for v2.3 of CPE format
|
|
|
|
Add unit test for broken CPE_NAME
|
|
|
|
Prevent possible crash if CPE_NAME is wrongly written in the distro
|
|
|
|
Add part parsing
|
|
|
|
Keep CPE_NAME only for opensuse series
|
|
|
|
Remove linebreak
|
|
|
|
Expand unit test to verify part name
|
|
|
|
Fix proper part name in the string-bound CPE
|
|
---
|
|
salt/grains/core.py | 43 +++++++++++++++++++++---
|
|
tests/unit/grains/test_core.py | 60 +++++++++++++++++++++++++++++-----
|
|
2 files changed, 90 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
|
index 80eebd1c05..e41ab4e0ae 100644
|
|
--- a/salt/grains/core.py
|
|
+++ b/salt/grains/core.py
|
|
@@ -1355,6 +1355,34 @@ def _parse_os_release(os_release_files):
|
|
return data
|
|
|
|
|
|
+def _parse_cpe_name(cpe):
|
|
+ '''
|
|
+ Parse CPE_NAME data from the os-release
|
|
+
|
|
+ Info: https://csrc.nist.gov/projects/security-content-automation-protocol/scap-specifications/cpe
|
|
+
|
|
+ :param cpe:
|
|
+ :return:
|
|
+ '''
|
|
+ part = {
|
|
+ 'o': 'operating system',
|
|
+ 'h': 'hardware',
|
|
+ 'a': 'application',
|
|
+ }
|
|
+ ret = {}
|
|
+ cpe = (cpe or '').split(':')
|
|
+ if len(cpe) > 4 and cpe[0] == 'cpe':
|
|
+ if cpe[1].startswith('/'): # WFN to URI
|
|
+ ret['vendor'], ret['product'], ret['version'] = cpe[2:5]
|
|
+ ret['phase'] = cpe[5] if len(cpe) > 5 else None
|
|
+ ret['part'] = part.get(cpe[1][1:])
|
|
+ elif len(cpe) == 13 and cpe[1] == '2.3': # WFN to a string
|
|
+ ret['vendor'], ret['product'], ret['version'], ret['phase'] = [x if x != '*' else None for x in cpe[3:7]]
|
|
+ ret['part'] = part.get(cpe[2])
|
|
+
|
|
+ return ret
|
|
+
|
|
+
|
|
def os_data():
|
|
'''
|
|
Return grains pertaining to the operating system
|
|
@@ -1554,13 +1582,20 @@ def os_data():
|
|
codename = codename_match.group(1)
|
|
grains['lsb_distrib_codename'] = codename
|
|
if 'CPE_NAME' in os_release:
|
|
- if ":suse:" in os_release['CPE_NAME'] or ":opensuse:" in os_release['CPE_NAME']:
|
|
+ cpe = _parse_cpe_name(os_release['CPE_NAME'])
|
|
+ if not cpe:
|
|
+ log.error('Broken CPE_NAME format in /etc/os-release!')
|
|
+ elif cpe.get('vendor', '').lower() in ['suse', 'opensuse']:
|
|
grains['os'] = "SUSE"
|
|
# openSUSE `osfullname` grain normalization
|
|
if os_release.get("NAME") == "openSUSE Leap":
|
|
grains['osfullname'] = "Leap"
|
|
elif os_release.get("VERSION") == "Tumbleweed":
|
|
grains['osfullname'] = os_release["VERSION"]
|
|
+ # Override VERSION_ID, if CPE_NAME around
|
|
+ if cpe.get('version') and cpe.get('vendor') == 'opensuse': # Keep VERSION_ID for SLES
|
|
+ grains['lsb_distrib_release'] = cpe['version']
|
|
+
|
|
elif os.path.isfile('/etc/SuSE-release'):
|
|
grains['lsb_distrib_id'] = 'SUSE'
|
|
version = ''
|
|
@@ -1666,8 +1701,7 @@ def os_data():
|
|
# Commit introducing this comment should be reverted after the upstream bug is released.
|
|
if 'CentOS Linux 7' in grains.get('lsb_distrib_codename', ''):
|
|
grains.pop('lsb_distrib_release', None)
|
|
- grains['osrelease'] = \
|
|
- grains.get('lsb_distrib_release', osrelease).strip()
|
|
+ grains['osrelease'] = grains.get('lsb_distrib_release', osrelease).strip()
|
|
grains['oscodename'] = grains.get('lsb_distrib_codename', '').strip() or oscodename
|
|
if 'Red Hat' in grains['oscodename']:
|
|
grains['oscodename'] = oscodename
|
|
@@ -1702,8 +1736,7 @@ def os_data():
|
|
r'((?:Open|Oracle )?Solaris|OpenIndiana|OmniOS) (Development)?'
|
|
r'\s*(\d+\.?\d*|v\d+)\s?[A-Z]*\s?(r\d+|\d+\/\d+|oi_\S+|snv_\S+)?'
|
|
)
|
|
- osname, development, osmajorrelease, osminorrelease = \
|
|
- release_re.search(rel_data).groups()
|
|
+ osname, development, osmajorrelease, osminorrelease = release_re.search(rel_data).groups()
|
|
except AttributeError:
|
|
# Set a blank osrelease grain and fallback to 'Solaris'
|
|
# as the 'os' grain.
|
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
|
index e973428add..2ab32ef41b 100644
|
|
--- a/tests/unit/grains/test_core.py
|
|
+++ b/tests/unit/grains/test_core.py
|
|
@@ -62,10 +62,11 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
|
def test_parse_etc_os_release(self, path_isfile_mock):
|
|
path_isfile_mock.side_effect = lambda x: x == "/usr/lib/os-release"
|
|
with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")) as os_release_file:
|
|
- os_release_content = os_release_file.readlines()
|
|
- with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
|
|
- os_release_file.return_value.__iter__.return_value = os_release_content
|
|
- os_release = core._parse_os_release(["/etc/os-release", "/usr/lib/os-release"])
|
|
+ os_release_content = os_release_file.read()
|
|
+ with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
|
|
+ os_release = core._parse_os_release(
|
|
+ '/etc/os-release',
|
|
+ '/usr/lib/os-release')
|
|
self.assertEqual(os_release, {
|
|
"NAME": "Ubuntu",
|
|
"VERSION": "17.10 (Artful Aardvark)",
|
|
@@ -81,10 +82,53 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
|
"UBUNTU_CODENAME": "artful",
|
|
})
|
|
|
|
- @patch("os.path.isfile")
|
|
- def test_missing_os_release(self, path_isfile_mock):
|
|
- path_isfile_mock.return_value = False
|
|
- os_release = core._parse_os_release(["/etc/os-release", "/usr/lib/os-release"])
|
|
+ def test_parse_cpe_name_wfn(self):
|
|
+ '''
|
|
+ Parse correct CPE_NAME data WFN formatted
|
|
+ :return:
|
|
+ '''
|
|
+ for cpe, cpe_ret in [('cpe:/o:opensuse:leap:15.0',
|
|
+ {'phase': None, 'version': '15.0', 'product': 'leap',
|
|
+ 'vendor': 'opensuse', 'part': 'operating system'}),
|
|
+ ('cpe:/o:vendor:product:42:beta',
|
|
+ {'phase': 'beta', 'version': '42', 'product': 'product',
|
|
+ 'vendor': 'vendor', 'part': 'operating system'})]:
|
|
+ ret = core._parse_cpe_name(cpe)
|
|
+ for key in cpe_ret:
|
|
+ assert key in ret
|
|
+ assert cpe_ret[key] == ret[key]
|
|
+
|
|
+ def test_parse_cpe_name_v23(self):
|
|
+ '''
|
|
+ Parse correct CPE_NAME data v2.3 formatted
|
|
+ :return:
|
|
+ '''
|
|
+ for cpe, cpe_ret in [('cpe:2.3:o:microsoft:windows_xp:5.1.601:beta:*:*:*:*:*:*',
|
|
+ {'phase': 'beta', 'version': '5.1.601', 'product': 'windows_xp',
|
|
+ 'vendor': 'microsoft', 'part': 'operating system'}),
|
|
+ ('cpe:2.3:h:corellian:millenium_falcon:1.0:*:*:*:*:*:*:*',
|
|
+ {'phase': None, 'version': '1.0', 'product': 'millenium_falcon',
|
|
+ 'vendor': 'corellian', 'part': 'hardware'}),
|
|
+ ('cpe:2.3:*:dark_empire:light_saber:3.0:beta:*:*:*:*:*:*',
|
|
+ {'phase': 'beta', 'version': '3.0', 'product': 'light_saber',
|
|
+ 'vendor': 'dark_empire', 'part': None})]:
|
|
+ ret = core._parse_cpe_name(cpe)
|
|
+ for key in cpe_ret:
|
|
+ assert key in ret
|
|
+ assert cpe_ret[key] == ret[key]
|
|
+
|
|
+ def test_parse_cpe_name_broken(self):
|
|
+ '''
|
|
+ Parse broken CPE_NAME data
|
|
+ :return:
|
|
+ '''
|
|
+ for cpe in ['cpe:broken', 'cpe:broken:in:all:ways:*:*:*:*',
|
|
+ 'cpe:x:still:broken:123', 'who:/knows:what:is:here']:
|
|
+ assert core._parse_cpe_name(cpe) == {}
|
|
+
|
|
+ def test_missing_os_release(self):
|
|
+ with patch('salt.utils.files.fopen', mock_open(read_data={})):
|
|
+ os_release = core._parse_os_release('/etc/os-release', '/usr/lib/os-release')
|
|
self.assertEqual(os_release, {})
|
|
|
|
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
|
--
|
|
2.19.0
|
|
|
|
|