diff --git a/insights/specs/datasources/httpd.py b/insights/specs/datasources/httpd.py
index 1c8adde76d..7192cad9e5 100644
--- a/insights/specs/datasources/httpd.py
+++ b/insights/specs/datasources/httpd.py
@@ -71,8 +71,14 @@ def _get_all_include_conf(root, glob_path):
_paths.add(conf)
with open(conf) as cfp:
_includes = None
+ section_number = 0
for line in cfp.readlines():
- if line.strip().startswith("Include"):
+ line = line.strip()
+ if line.startswith(""):
+ section_number = section_number - 1
+ elif line.startswith("<"):
+ section_number = section_number + 1
+ if section_number == 0 and (line.startswith("Include ") or line.startswith("IncludeOptional ")):
_includes = line.split()[-1].strip('"\'')
_paths.update(_get_all_include_conf(root, _includes))
if os.path.isdir(conf):
@@ -92,11 +98,17 @@ def get_httpd_configuration_files(httpd_root):
server_root = httpd_root
# Add it only when it exists
all_paths.add(main_httpd_conf)
+ section_number = 0
for line in cfp.readlines():
- if line.strip().startswith("ServerRoot"):
+ line = line.strip()
+ if line.startswith(""):
+ section_number = section_number - 1
+ elif line.startswith("<"):
+ section_number = section_number + 1
+ if line.startswith("ServerRoot "):
server_root = line.strip().split()[-1].strip().strip('"\'')
- elif line.strip().startswith("Include"):
- includes = line.strip().split()[-1].strip('"\'')
+ elif section_number == 0 and (line.startswith("Include ") or line.startswith("IncludeOptional ")):
+ includes = line.split()[-1].strip('"\'')
# For multiple "Include" directives, all of them will be included
all_paths.update(_get_all_include_conf(server_root, includes))
except Exception:
@@ -117,10 +129,7 @@ def httpd_configuration_files(broker):
SkipComponent: there is no httpd configuration file
"""
httpd_root = '/etc/httpd'
- all_paths = get_httpd_configuration_files(httpd_root)
- if all_paths:
- return all_paths
- raise SkipComponent
+ return get_httpd_configuration_files(httpd_root)
@datasource(HostContext)
@@ -135,10 +144,7 @@ def httpd24_scl_configuration_files(broker):
SkipComponent: there is no httpd24 slc configuration file
"""
httpd_root = '/opt/rh/httpd24/root/etc/httpd'
- all_paths = get_httpd_configuration_files(httpd_root)
- if all_paths:
- return all_paths
- raise SkipComponent
+ return get_httpd_configuration_files(httpd_root)
@datasource(HostContext)
@@ -153,7 +159,4 @@ def httpd24_scl_jbcs_configuration_files(broker):
SkipComponent: there is no httpd24 slc jbcs configuration file
"""
httpd_root = '/opt/rh/jbcs-httpd24/root/etc/httpd'
- all_paths = get_httpd_configuration_files(httpd_root)
- if all_paths:
- return all_paths
- raise SkipComponent
+ return get_httpd_configuration_files(httpd_root)
diff --git a/insights/tests/datasources/test_httpd.py b/insights/tests/datasources/test_httpd.py
index 274db2df80..60f80dfc00 100644
--- a/insights/tests/datasources/test_httpd.py
+++ b/insights/tests/datasources/test_httpd.py
@@ -22,6 +22,11 @@
/dev/mapper/httpd1 /httpd1 nfs4 rw,relatime,vers=4,barrier=1,data=ordered 0 0
/dev/mapper/httpd2 /httpd2 nfs4 rw,relatime,vers=4,barrier=1,data=ordered 0 0
""".strip()
+
+MOUNT_DATA_NO_NFS = """
+/dev/mapper/root / ext4 rw,relatime,barrier=1,data=ordered 0 0
+""".strip()
+
NFS_LSOF_666 = """
zsh 3520 httpd 3r REG 253,0 6940392 648646 /httpd1
zsh 3520 httpd 11r REG 253,0 9253600 648644 /httpd1
@@ -46,6 +51,14 @@ def shell_out(self, cmd, split=True, timeout=None, keep_rc=False, env=None, sign
raise Exception
+class FakeContext_NO_httpd(HostContext):
+ def shell_out(self, cmd, split=True, timeout=None, keep_rc=False, env=None, signum=None):
+ if 'pgrep' in cmd:
+ return ''
+
+ raise Exception
+
+
# The ``get_running_commands()`` is tested in:
# - insights/tests/datasources/test_get_running_commands.py
# Here, we do not test it
@@ -71,6 +84,20 @@ def test_httpd_on_nfs(run_cmds):
assert '"nfs_mounts": ["/httpd1", "/httpd2"]' in result.content[0]
+@patch('insights.specs.datasources.httpd.get_running_commands')
+def test_httpd_on_nfs_no_httpd(run_cmds):
+ broker = {ProcMounts: ProcMounts(context_wrap(MOUNT_DATA)), HostContext: FakeContext_NO_httpd()}
+ with pytest.raises(SkipComponent):
+ httpd_on_nfs(broker)
+
+
+@patch('insights.specs.datasources.httpd.get_running_commands')
+def test_httpd_on_nfs_no_mount(run_cmds):
+ broker = {ProcMounts: ProcMounts(context_wrap(MOUNT_DATA_NO_NFS)), HostContext: FakeContext()}
+ with pytest.raises(SkipComponent):
+ httpd_on_nfs(broker)
+
+
data_lines_httpd_conf = """
ServerRoot "/etc/httpd"
Include conf.d/*.conf
@@ -88,6 +115,24 @@ def test_httpd_on_nfs(run_cmds):
data_lines_ssl_conf = """
Listen 443 https
+IncludeOptional modsecurity.d/*.conf
+
+ # ModSecurity Core Rules Set and Local configuration
+ IncludeOptional modsecurity.d/*.conf
+
+""".strip()
+
+data_lines_httpd_conf_section_test = """
+ServerRoot "/etc/httpd"
+
+ # ModSecurity Core Rules Set and Local configuration
+ IncludeOptional modsecurity.d/*.conf
+
+""".strip()
+
+data_lines_crs_setup_conf = """
+SecAction \
+ "id:900990,\
""".strip()
@@ -103,6 +148,39 @@ def test_httpd_conf_files(m_open, m_glob, m_isdir, m_isfile):
assert result == set(['/etc/httpd/conf.d/ssl.conf', '/etc/httpd/conf/httpd.conf'])
+@patch("os.path.isfile", return_value=True)
+@patch("os.path.isdir", return_value=True)
+@patch("glob.glob", return_value=["/etc/httpd/modsecurity.d/crs-setup.conf"])
+@patch(builtin_open, new_callable=mock_open, read_data=data_lines_httpd_conf_section_test)
+def test_httpd_conf_files_section(m_open, m_glob, m_isdir, m_isfile):
+ handlers = (m_open.return_value, mock_open(read_data=data_lines_crs_setup_conf).return_value)
+ m_open.side_effect = handlers
+ broker = {HostContext: None}
+ result = httpd_configuration_files(broker)
+ assert result == set(['/etc/httpd/conf/httpd.conf'])
+
+
+@patch("os.path.isfile", return_value=False)
+@patch("os.path.isdir", return_value=False)
+@patch("glob.glob", return_value=["/etc/httpd/conf.d/ssl.conf"])
+@patch(builtin_open, new_callable=mock_open, read_data=data_lines_httpd_conf)
+def test_httpd_conf_files_ssl_miss(m_open, m_glob, m_isdir, m_isfile):
+ handlers = (m_open.return_value, mock_open(read_data=data_lines_ssl_conf).return_value)
+ m_open.side_effect = handlers
+ broker = {HostContext: None}
+ result = httpd_configuration_files(broker)
+ assert result == set(['/etc/httpd/conf/httpd.conf'])
+
+
+@patch("os.path.isfile", return_value=True)
+@patch("os.path.isdir", return_value=True)
+@patch("glob.glob", return_value=["/etc/httpd/conf.d/ssl.conf"])
+def test_httpd_conf_files_main_miss(m_glob, m_isdir, m_isfile):
+ broker = {HostContext: None}
+ with pytest.raises(SkipComponent):
+ httpd_configuration_files(broker)
+
+
@patch("os.path.isfile", return_value=True)
@patch("os.path.isdir", return_value=True)
@patch("glob.glob", return_value=["/opt/rh/httpd24/root/etc/httpd/conf.d/ssl.conf"])