3166-T3-R1-e2e-mauromalara.html

Report generated on 29-Aug-2022 at 10:09:07 by pytest-html v3.1.1

Environment

Packages {"pluggy": "0.13.1", "py": "1.10.0", "pytest": "6.2.2"}
Platform Linux-5.15.0-46-generic-x86_64-with-glibc2.35
Plugins {"html": "3.1.1", "metadata": "2.0.1", "testinfra": "5.0.0"}
Python 3.8.10

Summary

4 tests ran in 718.48 seconds.

0 passed, 0 skipped, 4 failed, 0 errors, 0 expected failures, 0 unexpected passes

Results

Result Test Duration Links
Failed tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py::test_docker_monitoring[docker_pull] 331.36
configure_environment = None
metadata = {'description': 'Test if an alert is generated when using the `pull` command.', 'extra': {'data.docker.Action': 'pull'...ra_vars': {'command': 'docker pull nginx', 'event_description': "Run 'docker pull nginx'"}, 'name': 'docker_pull', ...}
get_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105', generate_events = None, clean_alerts_index = None

@pytest.mark.parametrize('metadata', configuration_metadata, ids=cases_ids)
@pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_docker_monitoring(configure_environment, metadata, get_dashboard_credentials, get_manager_ip, generate_events,
clean_alerts_index):
'''
description: Check that an alert is generated for Docker events.

test_phases:
- Set a custom Wazuh configuration.
- Pull a Docker image, start the container, run a Docker command or delete the container.
- Check in the alerts.json log that the expected alert has been triggered and get its timestamp.
- Check that the obtained alert from alerts.json has been indexed.

wazuh_min_version: 4.4.0

tier: 0

parameters:
- configurate_environment:
type: fixture
brief: Set the wazuh configuration according to the configuration playbook.
- metadata:
type: dict
brief: Wazuh configuration metadata.
- get_dashboard_credentials:
type: fixture
brief: Get the wazuh dashboard credentials.
- generate_events:
type: fixture
brief: Generate events that will trigger the alert according to the generate_events playbook.
- clean_alerts_index:
type: fixture
brief: Delete obtained alerts.json and alerts index.

assertions:
- Verify that the alert has been triggered.
- Verify that the same alert has been indexed.

input_description:
- The `configuration.yaml` file provides the module configuration for this test.
- The `generate_events.yaml`file provides the function configuration for this test.
'''
rule_description = metadata['rule.description']
rule_id = metadata['rule.id']
rule_level = metadata['rule.level']
docker_action = metadata['extra']['data.docker.Action']
timestamp_regex = r'\d+-\d+-\d+T\d+:\d+:\d+\.\d+[\+|-]\d+'

expected_alert_json = fr".+timestamp\":\"({timestamp_regex})\",.+level.+{rule_level}.+description.+" \
fr"{rule_description}.+id.+{rule_id}.+Action.+{docker_action}.+"

expected_indexed_alert = fr".+Action.+{docker_action}.+level.+{rule_level}.+description.+{rule_description}.+" \
fr"id.+{rule_id}.+timestamp\": \"({timestamp_regex})\".+"

# Check that alert has been raised and save timestamp
raised_alert = evm.check_event(callback=expected_alert_json, file_to_monitor=alerts_json,
timeout=fw.T_5, error_message='The alert has not occurred').result()
raised_alert_timestamp = raised_alert.group(1)

query = e2e.make_query([
{
"term": {
"rule.id": f"{rule_id}"
}
},
{
"term": {
"rule.description": f"{rule_description}"
}
},
{
"term": {
"data.docker.Action": f"{docker_action}"
}
},
{
"term": {
"timestamp": f"{raised_alert_timestamp}"
}
}
])

# Check if the alert has been indexed and get its data
> response = e2e.get_alert_indexer_api(query=query, credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py:147:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/wazuh_testing/tools/utils.py:48: in to_retry
return func(*args, **kwargs) # final attempt
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

query = {'query': {'bool': {'must': [{'term': {'rule.id': '87932'}}, {'term': {'rule.description': 'Docker: Image or repositor...'}}, {'term': {'timestamp': '2022-08-29T13:00:15.423+0000'}}]}}, 'size': 1, 'sort': [{'timestamp': {'order': 'desc'}}]}
credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

@retry(Exception, attempts=3, delay=5)
def get_alert_indexer_api(query, credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Get an alert from the wazuh-indexer API

Make a request to the wazuh-indexer API to get the last indexed alert that matches the values passed in
must_match.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Index in which to search for the alert.
query (dict): Query to send to the API.
credentials(dict): wazuh-indexer credentials.

Returns:
`obj`(map): Search results
"""
url = f"https://{ip_address}:9200/{index}/_search?"

response = requests.get(url=url, params={'pretty': 'true'}, json=query, verify=False,
auth=requests.auth.HTTPBasicAuth(credentials['user'], credentials['password']))

if '"hits" : [ ]' in response.text:
raise Exception('Alert not indexed')
elif response.status_code != HTTPStatus.OK:
> raise Exception(f"The request wasn't successful.\nActual response: {response.text}")
E Exception: The request wasn't successful.
E Actual response: Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:34: Exceptionget_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105'

@pytest.fixture(scope='function')
def clean_alerts_index(get_dashboard_credentials, get_manager_ip):
"""Remove the temporary file that contains the alerts and delete indices using the API.

Args:
credentials (dict): wazuh-indexer credentials.
"""
yield
remove_file(alerts_json)
> e2e.delete_index_api(credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/conftest.py:156:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

def delete_index_api(credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Delete indices from wazuh-indexer using its API.

Make a request to the wazuh-indexer API to delete indices that match a given name.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Name of the index to be deleted.
credentials(dict): wazuh-indexer credentials.

Returns:
obj(class): `Response <Response>` object
obj(class): `NoneType` object
"""
url = f"https://{ip_address}:9200/"
authorization = requests.auth.HTTPBasicAuth(credentials['user'], credentials['password'])

response = requests.delete(url=url+index, params={'pretty': 'true'}, verify=False, auth=authorization)

if response.status_code != HTTPStatus.OK:
> raise Exception(f"The index(es) have not been deleted successfully. Actual response {response.text}")
E Exception: The index(es) have not been deleted successfully. Actual response Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:59: Exception
-----------------------------Captured stdout setup------------------------------
PLAY [localhost] *************************************************************** TASK [Gathering Facts] ********************************************************* ok: [localhost] TASK [Generate a general validation playbook] ********************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 PLAY [General validation phase] ************************************************ TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [host_checker : Set flag and informative variable] ************************ ok: [centos-manager] TASK [host_checker : Check default Python version (Linux)] ********************* skipping: [centos-manager] TASK [host_checker : Get Python version (Windows)] ***************************** skipping: [centos-manager] TASK [host_checker : Check default Python version (Windows)] ******************* skipping: [centos-manager] TASK [host_checker : Check OS (Linux)] ***************************************** skipping: [centos-manager] TASK [host_checker : Check OS (Windows)] *************************************** skipping: [centos-manager] TASK [Get Wazuh installation] ************************************************** TASK [service_controller : Get installation type] ****************************** changed: [centos-manager] TASK [host_checker : Populate services facts] ********************************** ok: [centos-manager] TASK [host_checker : Check the status of Wazuh components (Manager)] *********** skipping: [centos-manager] => (item=wazuh-manager.service) skipping: [centos-manager] => (item=wazuh-indexer.service) skipping: [centos-manager] => (item=filebeat.service) TASK [host_checker : set_fact] ************************************************* skipping: [centos-manager] TASK [host_checker : Check the status of Wazuh Agent] ************************** skipping: [centos-manager] TASK [Get Wazuh installation] ************************************************** TASK [service_controller : Get installation type] ****************************** changed: [centos-manager] TASK [host_checker : Run filebeat test] **************************************** changed: [centos-manager] TASK [host_checker : Check the connection between Filebeat and Wazuh Indexer] *** skipping: [centos-manager] TASK [Get Wazuh installation] ************************************************** TASK [service_controller : Get installation type] ****************************** changed: [centos-manager] TASK [host_checker : Test connection with Wazuh Indexer] *********************** fatal: [centos-manager -> localhost]: FAILED! => {"changed": false, "msg": "The shell action failed to execute in the expected time frame (3) and was terminated"} ...ignoring TASK [host_checker : Check the connection between Controller node and Wazuh Indexer] *** skipping: [centos-manager] TASK [host_checker : set_fact] ************************************************* ok: [centos-manager] TASK [host_checker : Verify if any check have failed] ************************** skipping: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=9 changed=4 unreachable=0 failed=0 skipped=11 rescued=0 ignored=1 PLAY [Configure manager environment] ******************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Configure the docker-listener module] ************************************ TASK [manage_wazuh_configurations : Configure ossec.conf linux] **************** changed: [centos-manager] TASK [manage_wazuh_configurations : Configure ossec.conf windows] ************** skipping: [centos-manager] TASK [Restart wazuh-manager] *************************************************** TASK [manage_wazuh : Get installation type] ************************************ changed: [centos-manager] TASK [manage_wazuh : Restart manager service on linux] ************************* changed: [centos-manager] TASK [manage_wazuh : Restart agent service on linux] *************************** skipping: [centos-manager] TASK [manage_wazuh : Restart wazuh on Windows] ********************************* skipping: [centos-manager] TASK [Force systemd to reread configs] ***************************************** ok: [centos-manager] TASK [Check if Docker is installed or not on CentOS] *************************** fatal: [centos-manager]: FAILED! => {"changed": true, "cmd": ["systemctl", "status", "docker", "--no-pager"], "delta": "0:00:00.007973", "end": "2022-08-29 12:57:49.217799", "msg": "non-zero return code", "rc": 4, "start": "2022-08-29 12:57:49.209826", "stderr": "Unit docker.service could not be found.", "stderr_lines": ["Unit docker.service could not be found."], "stdout": "", "stdout_lines": []} ...ignoring TASK [Install Docker using the convenience script] ***************************** changed: [centos-manager] TASK [Stop Docker to avoid errors and start it] ******************************** changed: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=8 changed=6 unreachable=0 failed=0 skipped=3 rescued=0 ignored=1 { "ansible_connection": "ssh", "ansible_host": "172.31.6.105", "ansible_ssh_common_args": "-o StrictHostKeyChecking=no -i /home/mauro/ephemeral.pem", "ansible_user": "qa", "ansible_winrm_server_cert_validation": "ignore", "aws_access_key_id": "AKIA6B6B4XJHMKALDJGT", "aws_region": "us-east-1", "aws_secret_access_key": "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", "bucket_name": "aws-cloudtrail-logs-966237403726-09245154", "dashboard_password": "bad_pass", "dashboard_user": "admin", "s3_url": "https://s3.amazonaws.com/ci.wazuh.com/qa/testing_files/end_to_end", "slack_channel": "C03EZKLR682", "slack_token": "xoxb-746532534132-3509688290194-ITgoGLhy542RzfE7p2FxVHVN", "virustotal_key": "3e4db70c621cd9dd9e3400254297eea03215987facca9931a42dcb86ffb8aa78", "web_hook_url": "https://hooks.slack.com/services/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" } { "ansible_connection": "ssh", "ansible_host": "172.31.6.105", "ansible_ssh_common_args": "-o StrictHostKeyChecking=no -i /home/mauro/ephemeral.pem", "ansible_user": "qa", "ansible_winrm_server_cert_validation": "ignore", "aws_access_key_id": "AKIA6B6B4XJHMKALDJGT", "aws_region": "us-east-1", "aws_secret_access_key": "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", "bucket_name": "aws-cloudtrail-logs-966237403726-09245154", "dashboard_password": "bad_pass", "dashboard_user": "admin", "s3_url": "https://s3.amazonaws.com/ci.wazuh.com/qa/testing_files/end_to_end", "slack_channel": "C03EZKLR682", "slack_token": "xoxb-746532534132-3509688290194-ITgoGLhy542RzfE7p2FxVHVN", "virustotal_key": "3e4db70c621cd9dd9e3400254297eea03215987facca9931a42dcb86ffb8aa78", "web_hook_url": "https://hooks.slack.com/services/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" } PLAY [Generate events] ********************************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Truncate alert.json] ***************************************************** TASK [manage_alerts : Truncate file] ******************************************* changed: [centos-manager] TASK [Run 'docker pull nginx'] ************************************************* changed: [centos-manager] TASK [Wait for alerts to be generated] ***************************************** ok: [centos-manager] TASK [Get alert json] ********************************************************** TASK [manage_alerts : Get alerts.json] ***************************************** changed: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
-------------------------------Captured log call--------------------------------
WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 2/3 remaining attempts. Waiting 10 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 1/3 remaining attempts. Waiting 20 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 0/3 remaining attempts. Waiting 40 seconds.
Failed tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py::test_docker_monitoring[docker_run] 118.07
configure_environment = None
metadata = {'description': 'Test if an alert is generated when using the `run` command.', 'extra': {'data.docker.Action': 'start'...ntainer nginx', 'event_description': "Run 'docker run -d -P --name nginx_container nginx'"}, 'name': 'docker_run', ...}
get_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105', generate_events = None, clean_alerts_index = None

@pytest.mark.parametrize('metadata', configuration_metadata, ids=cases_ids)
@pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_docker_monitoring(configure_environment, metadata, get_dashboard_credentials, get_manager_ip, generate_events,
clean_alerts_index):
'''
description: Check that an alert is generated for Docker events.

test_phases:
- Set a custom Wazuh configuration.
- Pull a Docker image, start the container, run a Docker command or delete the container.
- Check in the alerts.json log that the expected alert has been triggered and get its timestamp.
- Check that the obtained alert from alerts.json has been indexed.

wazuh_min_version: 4.4.0

tier: 0

parameters:
- configurate_environment:
type: fixture
brief: Set the wazuh configuration according to the configuration playbook.
- metadata:
type: dict
brief: Wazuh configuration metadata.
- get_dashboard_credentials:
type: fixture
brief: Get the wazuh dashboard credentials.
- generate_events:
type: fixture
brief: Generate events that will trigger the alert according to the generate_events playbook.
- clean_alerts_index:
type: fixture
brief: Delete obtained alerts.json and alerts index.

assertions:
- Verify that the alert has been triggered.
- Verify that the same alert has been indexed.

input_description:
- The `configuration.yaml` file provides the module configuration for this test.
- The `generate_events.yaml`file provides the function configuration for this test.
'''
rule_description = metadata['rule.description']
rule_id = metadata['rule.id']
rule_level = metadata['rule.level']
docker_action = metadata['extra']['data.docker.Action']
timestamp_regex = r'\d+-\d+-\d+T\d+:\d+:\d+\.\d+[\+|-]\d+'

expected_alert_json = fr".+timestamp\":\"({timestamp_regex})\",.+level.+{rule_level}.+description.+" \
fr"{rule_description}.+id.+{rule_id}.+Action.+{docker_action}.+"

expected_indexed_alert = fr".+Action.+{docker_action}.+level.+{rule_level}.+description.+{rule_description}.+" \
fr"id.+{rule_id}.+timestamp\": \"({timestamp_regex})\".+"

# Check that alert has been raised and save timestamp
raised_alert = evm.check_event(callback=expected_alert_json, file_to_monitor=alerts_json,
timeout=fw.T_5, error_message='The alert has not occurred').result()
raised_alert_timestamp = raised_alert.group(1)

query = e2e.make_query([
{
"term": {
"rule.id": f"{rule_id}"
}
},
{
"term": {
"rule.description": f"{rule_description}"
}
},
{
"term": {
"data.docker.Action": f"{docker_action}"
}
},
{
"term": {
"timestamp": f"{raised_alert_timestamp}"
}
}
])

# Check if the alert has been indexed and get its data
> response = e2e.get_alert_indexer_api(query=query, credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py:147:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/wazuh_testing/tools/utils.py:48: in to_retry
return func(*args, **kwargs) # final attempt
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

query = {'query': {'bool': {'must': [{'term': {'rule.id': '87903'}}, {'term': {'rule.description': 'Docker: Container nginx_co...'}}, {'term': {'timestamp': '2022-08-29T13:02:14.101+0000'}}]}}, 'size': 1, 'sort': [{'timestamp': {'order': 'desc'}}]}
credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

@retry(Exception, attempts=3, delay=5)
def get_alert_indexer_api(query, credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Get an alert from the wazuh-indexer API

Make a request to the wazuh-indexer API to get the last indexed alert that matches the values passed in
must_match.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Index in which to search for the alert.
query (dict): Query to send to the API.
credentials(dict): wazuh-indexer credentials.

Returns:
`obj`(map): Search results
"""
url = f"https://{ip_address}:9200/{index}/_search?"

response = requests.get(url=url, params={'pretty': 'true'}, json=query, verify=False,
auth=requests.auth.HTTPBasicAuth(credentials['user'], credentials['password']))

if '"hits" : [ ]' in response.text:
raise Exception('Alert not indexed')
elif response.status_code != HTTPStatus.OK:
> raise Exception(f"The request wasn't successful.\nActual response: {response.text}")
E Exception: The request wasn't successful.
E Actual response: Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:34: Exceptionget_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105'

@pytest.fixture(scope='function')
def clean_alerts_index(get_dashboard_credentials, get_manager_ip):
"""Remove the temporary file that contains the alerts and delete indices using the API.

Args:
credentials (dict): wazuh-indexer credentials.
"""
yield
remove_file(alerts_json)
> e2e.delete_index_api(credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/conftest.py:156:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

def delete_index_api(credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Delete indices from wazuh-indexer using its API.

Make a request to the wazuh-indexer API to delete indices that match a given name.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Name of the index to be deleted.
credentials(dict): wazuh-indexer credentials.

Returns:
obj(class): `Response <Response>` object
obj(class): `NoneType` object
"""
url = f"https://{ip_address}:9200/"
authorization = requests.auth.HTTPBasicAuth(credentials['user'], credentials['password'])

response = requests.delete(url=url+index, params={'pretty': 'true'}, verify=False, auth=authorization)

if response.status_code != HTTPStatus.OK:
> raise Exception(f"The index(es) have not been deleted successfully. Actual response {response.text}")
E Exception: The index(es) have not been deleted successfully. Actual response Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:59: Exception
-----------------------------Captured stdout setup------------------------------
PLAY [Generate events] ********************************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Truncate alert.json] ***************************************************** TASK [manage_alerts : Truncate file] ******************************************* changed: [centos-manager] TASK [Run 'docker run -d -P --name nginx_container nginx'] ********************* changed: [centos-manager] TASK [Wait for alerts to be generated] ***************************************** ok: [centos-manager] TASK [Get alert json] ********************************************************** TASK [manage_alerts : Get alerts.json] ***************************************** changed: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
-------------------------------Captured log call--------------------------------
WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 2/3 remaining attempts. Waiting 10 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 1/3 remaining attempts. Waiting 20 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 0/3 remaining attempts. Waiting 40 seconds.
Failed tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py::test_docker_monitoring[docker_exec] 118.79
configure_environment = None
metadata = {'description': 'Test if an alert is generated when using the `exec` command.', 'extra': {'data.docker.Action': 'exec_...ntainer /bin/bash', 'event_description': "Run 'docker exec -d nginx_container /bin/bash'"}, 'name': 'docker_exec', ...}
get_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105', generate_events = None, clean_alerts_index = None

@pytest.mark.parametrize('metadata', configuration_metadata, ids=cases_ids)
@pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_docker_monitoring(configure_environment, metadata, get_dashboard_credentials, get_manager_ip, generate_events,
clean_alerts_index):
'''
description: Check that an alert is generated for Docker events.

test_phases:
- Set a custom Wazuh configuration.
- Pull a Docker image, start the container, run a Docker command or delete the container.
- Check in the alerts.json log that the expected alert has been triggered and get its timestamp.
- Check that the obtained alert from alerts.json has been indexed.

wazuh_min_version: 4.4.0

tier: 0

parameters:
- configurate_environment:
type: fixture
brief: Set the wazuh configuration according to the configuration playbook.
- metadata:
type: dict
brief: Wazuh configuration metadata.
- get_dashboard_credentials:
type: fixture
brief: Get the wazuh dashboard credentials.
- generate_events:
type: fixture
brief: Generate events that will trigger the alert according to the generate_events playbook.
- clean_alerts_index:
type: fixture
brief: Delete obtained alerts.json and alerts index.

assertions:
- Verify that the alert has been triggered.
- Verify that the same alert has been indexed.

input_description:
- The `configuration.yaml` file provides the module configuration for this test.
- The `generate_events.yaml`file provides the function configuration for this test.
'''
rule_description = metadata['rule.description']
rule_id = metadata['rule.id']
rule_level = metadata['rule.level']
docker_action = metadata['extra']['data.docker.Action']
timestamp_regex = r'\d+-\d+-\d+T\d+:\d+:\d+\.\d+[\+|-]\d+'

expected_alert_json = fr".+timestamp\":\"({timestamp_regex})\",.+level.+{rule_level}.+description.+" \
fr"{rule_description}.+id.+{rule_id}.+Action.+{docker_action}.+"

expected_indexed_alert = fr".+Action.+{docker_action}.+level.+{rule_level}.+description.+{rule_description}.+" \
fr"id.+{rule_id}.+timestamp\": \"({timestamp_regex})\".+"

# Check that alert has been raised and save timestamp
raised_alert = evm.check_event(callback=expected_alert_json, file_to_monitor=alerts_json,
timeout=fw.T_5, error_message='The alert has not occurred').result()
raised_alert_timestamp = raised_alert.group(1)

query = e2e.make_query([
{
"term": {
"rule.id": f"{rule_id}"
}
},
{
"term": {
"rule.description": f"{rule_description}"
}
},
{
"term": {
"data.docker.Action": f"{docker_action}"
}
},
{
"term": {
"timestamp": f"{raised_alert_timestamp}"
}
}
])

# Check if the alert has been indexed and get its data
> response = e2e.get_alert_indexer_api(query=query, credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py:147:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/wazuh_testing/tools/utils.py:48: in to_retry
return func(*args, **kwargs) # final attempt
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

query = {'query': {'bool': {'must': [{'term': {'rule.id': '87908'}}, {'term': {'rule.description': 'Docker: Started shell sess...'}}, {'term': {'timestamp': '2022-08-29T13:04:11.747+0000'}}]}}, 'size': 1, 'sort': [{'timestamp': {'order': 'desc'}}]}
credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

@retry(Exception, attempts=3, delay=5)
def get_alert_indexer_api(query, credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Get an alert from the wazuh-indexer API

Make a request to the wazuh-indexer API to get the last indexed alert that matches the values passed in
must_match.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Index in which to search for the alert.
query (dict): Query to send to the API.
credentials(dict): wazuh-indexer credentials.

Returns:
`obj`(map): Search results
"""
url = f"https://{ip_address}:9200/{index}/_search?"

response = requests.get(url=url, params={'pretty': 'true'}, json=query, verify=False,
auth=requests.auth.HTTPBasicAuth(credentials['user'], credentials['password']))

if '"hits" : [ ]' in response.text:
raise Exception('Alert not indexed')
elif response.status_code != HTTPStatus.OK:
> raise Exception(f"The request wasn't successful.\nActual response: {response.text}")
E Exception: The request wasn't successful.
E Actual response: Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:34: Exceptionget_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105'

@pytest.fixture(scope='function')
def clean_alerts_index(get_dashboard_credentials, get_manager_ip):
"""Remove the temporary file that contains the alerts and delete indices using the API.

Args:
credentials (dict): wazuh-indexer credentials.
"""
yield
remove_file(alerts_json)
> e2e.delete_index_api(credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/conftest.py:156:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

def delete_index_api(credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Delete indices from wazuh-indexer using its API.

Make a request to the wazuh-indexer API to delete indices that match a given name.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Name of the index to be deleted.
credentials(dict): wazuh-indexer credentials.

Returns:
obj(class): `Response <Response>` object
obj(class): `NoneType` object
"""
url = f"https://{ip_address}:9200/"
authorization = requests.auth.HTTPBasicAuth(credentials['user'], credentials['password'])

response = requests.delete(url=url+index, params={'pretty': 'true'}, verify=False, auth=authorization)

if response.status_code != HTTPStatus.OK:
> raise Exception(f"The index(es) have not been deleted successfully. Actual response {response.text}")
E Exception: The index(es) have not been deleted successfully. Actual response Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:59: Exception
-----------------------------Captured stdout setup------------------------------
PLAY [Generate events] ********************************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Truncate alert.json] ***************************************************** TASK [manage_alerts : Truncate file] ******************************************* changed: [centos-manager] TASK [Run 'docker exec -d nginx_container /bin/bash'] ************************** changed: [centos-manager] TASK [Wait for alerts to be generated] ***************************************** ok: [centos-manager] TASK [Get alert json] ********************************************************** TASK [manage_alerts : Get alerts.json] ***************************************** changed: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
-------------------------------Captured log call--------------------------------
WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 2/3 remaining attempts. Waiting 10 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 1/3 remaining attempts. Waiting 20 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 0/3 remaining attempts. Waiting 40 seconds.
Failed tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py::test_docker_monitoring[docker_rm] 149.92
configure_environment = None
metadata = {'description': 'Test if an alert is generated when using the `rm` command.', 'extra': {'data.docker.Action': 'destroy..., 'event_description': "Run 'docker stop `docker ps -a -q` && docker rm `docker ps -a -q`'"}, 'name': 'docker_rm', ...}
get_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105', generate_events = None, clean_alerts_index = None

@pytest.mark.parametrize('metadata', configuration_metadata, ids=cases_ids)
@pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_docker_monitoring(configure_environment, metadata, get_dashboard_credentials, get_manager_ip, generate_events,
clean_alerts_index):
'''
description: Check that an alert is generated for Docker events.

test_phases:
- Set a custom Wazuh configuration.
- Pull a Docker image, start the container, run a Docker command or delete the container.
- Check in the alerts.json log that the expected alert has been triggered and get its timestamp.
- Check that the obtained alert from alerts.json has been indexed.

wazuh_min_version: 4.4.0

tier: 0

parameters:
- configurate_environment:
type: fixture
brief: Set the wazuh configuration according to the configuration playbook.
- metadata:
type: dict
brief: Wazuh configuration metadata.
- get_dashboard_credentials:
type: fixture
brief: Get the wazuh dashboard credentials.
- generate_events:
type: fixture
brief: Generate events that will trigger the alert according to the generate_events playbook.
- clean_alerts_index:
type: fixture
brief: Delete obtained alerts.json and alerts index.

assertions:
- Verify that the alert has been triggered.
- Verify that the same alert has been indexed.

input_description:
- The `configuration.yaml` file provides the module configuration for this test.
- The `generate_events.yaml`file provides the function configuration for this test.
'''
rule_description = metadata['rule.description']
rule_id = metadata['rule.id']
rule_level = metadata['rule.level']
docker_action = metadata['extra']['data.docker.Action']
timestamp_regex = r'\d+-\d+-\d+T\d+:\d+:\d+\.\d+[\+|-]\d+'

expected_alert_json = fr".+timestamp\":\"({timestamp_regex})\",.+level.+{rule_level}.+description.+" \
fr"{rule_description}.+id.+{rule_id}.+Action.+{docker_action}.+"

expected_indexed_alert = fr".+Action.+{docker_action}.+level.+{rule_level}.+description.+{rule_description}.+" \
fr"id.+{rule_id}.+timestamp\": \"({timestamp_regex})\".+"

# Check that alert has been raised and save timestamp
raised_alert = evm.check_event(callback=expected_alert_json, file_to_monitor=alerts_json,
timeout=fw.T_5, error_message='The alert has not occurred').result()
raised_alert_timestamp = raised_alert.group(1)

query = e2e.make_query([
{
"term": {
"rule.id": f"{rule_id}"
}
},
{
"term": {
"rule.description": f"{rule_description}"
}
},
{
"term": {
"data.docker.Action": f"{docker_action}"
}
},
{
"term": {
"timestamp": f"{raised_alert_timestamp}"
}
}
])

# Check if the alert has been indexed and get its data
> response = e2e.get_alert_indexer_api(query=query, credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/test_basic_cases/test_docker_monitoring/test_docker_monitoring.py:147:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/wazuh_testing/tools/utils.py:48: in to_retry
return func(*args, **kwargs) # final attempt
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

query = {'query': {'bool': {'must': [{'term': {'rule.id': '87902'}}, {'term': {'rule.description': 'Docker: Container nginx_co...'}}, {'term': {'timestamp': '2022-08-29T13:06:10.956+0000'}}]}}, 'size': 1, 'sort': [{'timestamp': {'order': 'desc'}}]}
credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

@retry(Exception, attempts=3, delay=5)
def get_alert_indexer_api(query, credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Get an alert from the wazuh-indexer API

Make a request to the wazuh-indexer API to get the last indexed alert that matches the values passed in
must_match.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Index in which to search for the alert.
query (dict): Query to send to the API.
credentials(dict): wazuh-indexer credentials.

Returns:
`obj`(map): Search results
"""
url = f"https://{ip_address}:9200/{index}/_search?"

response = requests.get(url=url, params={'pretty': 'true'}, json=query, verify=False,
auth=requests.auth.HTTPBasicAuth(credentials['user'], credentials['password']))

if '"hits" : [ ]' in response.text:
raise Exception('Alert not indexed')
elif response.status_code != HTTPStatus.OK:
> raise Exception(f"The request wasn't successful.\nActual response: {response.text}")
E Exception: The request wasn't successful.
E Actual response: Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:34: Exceptionget_dashboard_credentials = {'password': 'bad_pass', 'user': 'admin'}, get_manager_ip = '172.31.6.105'

@pytest.fixture(scope='function')
def clean_alerts_index(get_dashboard_credentials, get_manager_ip):
"""Remove the temporary file that contains the alerts and delete indices using the API.

Args:
credentials (dict): wazuh-indexer credentials.
"""
yield
remove_file(alerts_json)
> e2e.delete_index_api(credentials=get_dashboard_credentials, ip_address=get_manager_ip)

tests/end_to_end/conftest.py:156:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

credentials = {'password': 'bad_pass', 'user': 'admin'}, ip_address = '172.31.6.105', index = 'wazuh-alerts-4.x-*'

def delete_index_api(credentials, ip_address, index='wazuh-alerts-4.x-*'):
"""Delete indices from wazuh-indexer using its API.

Make a request to the wazuh-indexer API to delete indices that match a given name.

Args:
ip_address (str): wazuh-indexer IP address.
index (str): Name of the index to be deleted.
credentials(dict): wazuh-indexer credentials.

Returns:
obj(class): `Response <Response>` object
obj(class): `NoneType` object
"""
url = f"https://{ip_address}:9200/"
authorization = requests.auth.HTTPBasicAuth(credentials['user'], credentials['password'])

response = requests.delete(url=url+index, params={'pretty': 'true'}, verify=False, auth=authorization)

if response.status_code != HTTPStatus.OK:
> raise Exception(f"The index(es) have not been deleted successfully. Actual response {response.text}")
E Exception: The index(es) have not been deleted successfully. Actual response Unauthorized

/usr/local/lib/python3.8/site-packages/wazuh_testing/end_to_end/__init__.py:59: Exception
-----------------------------Captured stdout setup------------------------------
PLAY [Generate events] ********************************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Truncate alert.json] ***************************************************** TASK [manage_alerts : Truncate file] ******************************************* changed: [centos-manager] TASK [Run 'docker stop `docker ps -a -q` && docker rm `docker ps -a -q`'] ****** changed: [centos-manager] TASK [Wait for alerts to be generated] ***************************************** ok: [centos-manager] TASK [Get alert json] ********************************************************** TASK [manage_alerts : Get alerts.json] ***************************************** changed: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
-------------------------------Captured log call--------------------------------
WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 2/3 remaining attempts. Waiting 10 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 1/3 remaining attempts. Waiting 20 seconds. WARNING root:utils.py:46 Exception: "The request wasn't successful. Actual response: Unauthorized". 0/3 remaining attempts. Waiting 40 seconds.
----------------------------Captured stdout teardown----------------------------
PLAY [Cleanup manager environment] ********************************************* TASK [Gathering Facts] ********************************************************* ok: [centos-manager] TASK [Delete the docker-listener module configuration] ************************* changed: [centos-manager] TASK [Restart wazuh-manager] *************************************************** TASK [manage_wazuh : Get installation type] ************************************ changed: [centos-manager] TASK [manage_wazuh : Restart manager service on linux] ************************* changed: [centos-manager] TASK [manage_wazuh : Restart agent service on linux] *************************** skipping: [centos-manager] TASK [manage_wazuh : Restart wazuh on Windows] ********************************* skipping: [centos-manager] PLAY RECAP ********************************************************************* centos-manager : ok=4 changed=3 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0