Skip to content

Commit

Permalink
Handle downloading malware-detection rules from stage environment (#3452
Browse files Browse the repository at this point in the history
)

Signed-off-by: Mark Huth <[email protected]>
(cherry picked from commit 5dd1c2e)
  • Loading branch information
mhuth authored and bfahr committed Jun 29, 2022
1 parent 59ef88f commit 80e5510
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 26 deletions.
5 changes: 5 additions & 0 deletions insights/client/apps/malware_detection/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,11 @@ def _get_rules(self):
if '/redhat_access/' in self.insights_config.base_url:
# Satellite URLs have '/redhat_access/' in the base_url config option
self.rules_location = self.insights_config.base_url + '/malware-detection/v1/' + signatures_file
elif '.stage.redhat.com' in self.insights_config.base_url:
# For downloading rules in the stage environment, use the URL of base_url (after finding it)
base_url = urlparse(self.insights_config.base_url)
self.rules_location = base_url.netloc or base_url.scheme or base_url.path.split('/')[0] or 'cert.console.stage.redhat.com'
self.rules_location += '/api/malware-detection/v1/' + signatures_file

# Make sure the rules_location starts with https://
if not re.match('^https?://', self.rules_location):
Expand Down
91 changes: 65 additions & 26 deletions insights/tests/client/apps/test_malware_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,31 +325,59 @@ def test_download_rules_basic_auth(self, log_mock, yara, conf, cmd, session, pro
@patch("insights.client.apps.malware_detection.call", return_value='4.2.1') # mock call to 'yara --version'
def test_download_rules_versioned_files(self, version_mock, exists_mock, conf, cmd, session, proxies, get, findmnt, remove):
# Test downloading different signatures files depending on the yara version found on the system
expected_rules_url = "https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar"
mdc = MalwareDetectionClient(InsightsConfig())
assert mdc.yara_version == '4.2.1'
assert mdc.rules_location == "https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=4.2.1"
get.assert_called_with("https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=4.2.1",
log_response_text=False)
assert mdc.rules_location == expected_rules_url + "?yara_version=4.2.1"
get.assert_called_with(expected_rules_url + "?yara_version=4.2.1", log_response_text=False)

version_mock.return_value = '4.1.0'
mdc = MalwareDetectionClient(InsightsConfig())
assert mdc.rules_location == "https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=4.1.0"
get.assert_called_with("https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=4.1.0",
log_response_text=False)
assert mdc.rules_location == expected_rules_url + "?yara_version=4.1.0"
get.assert_called_with(expected_rules_url + "?yara_version=4.1.0", log_response_text=False)

version_mock.return_value = '10.100'
mdc = MalwareDetectionClient(InsightsConfig())
assert mdc.rules_location == "https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=10.100"
get.assert_called_with("https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=10.100",
log_response_text=False)
assert mdc.rules_location == expected_rules_url + "?yara_version=10.100"
get.assert_called_with(expected_rules_url + "?yara_version=10.100", log_response_text=False)

# Bypass the _find_yara method so self.yara_version isn't set
with patch(FIND_YARA_TARGET, return_value=YARA):
mdc = MalwareDetectionClient(InsightsConfig())
assert not hasattr(mdc, 'yara_version')
assert mdc.rules_location == "https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar"
get.assert_called_with("https://cert.console.redhat.com/api/malware-detection/v1/signatures.yar",
log_response_text=False)
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)

@patch.dict(os.environ, {'TEST_SCAN': 'false'})
@patch("os.path.exists", return_value=True) # mock call to os.path.exists in _find_yara
@patch("insights.client.apps.malware_detection.call", return_value='4.2.0') # mock call to 'yara --version'
def test_download_rules_from_stage(self, version_mock, exists_mock, conf, cmd, session, proxies, get, findmnt, remove):
# Test downloading signatures files from the stage environment

base_url = "cert.console.stage.redhat.com:443/r/insights"
expected_rules_url = "https://cert.console.stage.redhat.com/api/malware-detection/v1/signatures.yar?yara_version=4.2.0"
mdc = MalwareDetectionClient(InsightsConfig(base_url=base_url))
assert mdc.yara_version == '4.2.0'
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)

for base_url in ('cert.console.stage.redhat.com/r/insights', 'cert.console.stage.redhat.com'):
mdc = MalwareDetectionClient(InsightsConfig(base_url=base_url))
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)

base_url = "https://cert.console.stage.redhat.com:443/r/insights"
expected_rules_url = "https://cert.console.stage.redhat.com:443/api/malware-detection/v1/signatures.yar?yara_version=4.2.0"
mdc = MalwareDetectionClient(InsightsConfig(base_url=base_url))
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)

os.environ['TEST_SCAN'] = 'true'
base_url = "cloud.stage.redhat.com"
expected_rules_url = "https://cloud.stage.redhat.com/api/malware-detection/v1/test-rule.yar"
mdc = MalwareDetectionClient(InsightsConfig(base_url=base_url))
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=True)

@patch.dict(os.environ, {'TEST_SCAN': 'true', 'RULES_LOCATION': 'console.redhat.com/rules.yar'})
@patch(FIND_YARA_TARGET, return_value=YARA)
Expand Down Expand Up @@ -417,38 +445,49 @@ def test_get_rules_location_as_file(self, isfile, yara, conf, cmd, session, prox

@patch.dict(os.environ, {'TEST_SCAN': 'true'})
@patch(LOGGER_TARGET)
def test_via_satellite_proxy(self, log_mock, conf, cmd, session, proxies, get, findmnt, remove):
def test_download_rules_via_satellite(self, log_mock, conf, cmd, session, proxies, get, findmnt, remove):
# Test recognizing and handling of Satellite URLs.
# Satellite URLs have '/redhat_access/' in their path (which is how the Satellite knows to redirect the
# query to C.R.C).
# For malware-detection requests through a Satellite we append the malware-detection path and add https://
satellite_url = 'satellite.example.com:443/redhat_access/r/insights/platform'
replaced_url_prefix = "https://satellite.example.com:443/redhat_access/r/insights/platform/malware-detection/v1/"
expected_rules_url_prefix = "https://satellite.example.com:443/redhat_access/r/insights/platform/malware-detection/v1/"

# Firstly try with test-rule
replaced_url = replaced_url_prefix + "test-rule.yar"
expected_rules_url = expected_rules_url_prefix + "test-rule.yar"
with patch(FIND_YARA_TARGET, return_value=YARA):
mdc = MalwareDetectionClient(InsightsConfig(base_url=satellite_url, verbose=True))
assert mdc.rules_location == replaced_url
get.assert_called_with(replaced_url, log_response_text=True)
log_mock.debug.assert_called_with("Downloading rules from: %s", replaced_url)
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=True)
log_mock.debug.assert_called_with("Downloading rules from: %s", expected_rules_url)

# Then with the actual rules file
os.environ['TEST_SCAN'] = 'false'
replaced_url = replaced_url_prefix + "signatures.yar"
expected_rules_url = expected_rules_url_prefix + "signatures.yar"
with patch(FIND_YARA_TARGET, return_value=YARA):
mdc = MalwareDetectionClient(InsightsConfig(base_url=satellite_url, verbose=True))
assert mdc.rules_location == replaced_url
get.assert_called_with(replaced_url, log_response_text=False)
log_mock.debug.assert_called_with("Downloading rules from: %s", replaced_url)
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)
log_mock.debug.assert_called_with("Downloading rules from: %s", expected_rules_url)

replaced_url += '?yara_version=4.1'
expected_rules_url += '?yara_version=4.1'
with patch('os.path.exists', return_value=True):
with patch("insights.client.apps.malware_detection.call", return_value='4.1'):
mdc = MalwareDetectionClient(InsightsConfig(base_url=satellite_url, verbose=True))
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)
log_mock.debug.assert_called_with("Downloading rules from: %s", expected_rules_url)

# Test a Satellite URL with 'stage.redhat.com' in its name - expect to still download from Satellite
satellite_url = 'satellite.stage.redhat.com:443/redhat_access/r/insights/platform'
expected_rules_url = "https://satellite.stage.redhat.com:443/redhat_access/r/insights/platform/malware-detection/v1/"
expected_rules_url += 'signatures.yar?yara_version=4.1'
with patch('os.path.exists', return_value=True):
with patch("insights.client.apps.malware_detection.call", return_value='4.1'):
mdc = MalwareDetectionClient(InsightsConfig(base_url=satellite_url, verbose=True))
assert mdc.rules_location == replaced_url
get.assert_called_with(replaced_url, log_response_text=False)
log_mock.debug.assert_called_with("Downloading rules from: %s", replaced_url)
assert mdc.rules_location == expected_rules_url
get.assert_called_with(expected_rules_url, log_response_text=False)
log_mock.debug.assert_called_with("Downloading rules from: %s", expected_rules_url)


@pytest.mark.skipif(IS_RHEL6, reason=SKIP_IF_RHEL6_REASON)
Expand Down

0 comments on commit 80e5510

Please sign in to comment.