diff --git a/KR-12.features b/KR-12.features new file mode 100644 index 0000000000000000000000000000000000000000..33fe5ec864ceacfc070fe50785301f2c8398463c --- /dev/null +++ b/KR-12.features @@ -0,0 +1,13 @@ +Feature: PIACERE Runtime environment + +Scenario: Inspect PIACERE Security Monitoring - basic metrics +Given An initiated IaC deployment +When The user navigates to the IaC deployment record in the IDE +And The user requests see Security Monitoring Dashboard +Then The user's browser is launched with the Security Monitoring Dashboard shown (Kibana Dashboard) + +Scenario: Inspect PIACERE Security Monitoring - Self-learning +Given An initiated IaC deployment +When The user navigates to the IaC deployment record in the IDE +And The user requests see Security Monitoring Self-learning Dashboard +Then The user's browser is launched with the Security Monitoring Dashboard shown (dedicated Grafana Dashboard) \ No newline at end of file diff --git a/configuration/smc_settings.cfg b/configuration/smc_settings.cfg index 8e7aeb5f3519778e65f92aaf9ba4ee25bc4ed113..51145e5aff2945e59b9e04e33b15c33c8c470c23 100644 --- a/configuration/smc_settings.cfg +++ b/configuration/smc_settings.cfg @@ -6,16 +6,22 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False [sm] # Security Monitoring section SM_KIBANA_ENDPOINT = https://0.0.0.0:443/kibana -SM_ELASTICSEARCH_USERNAME = elasticsearch -SM_ELASTICSEARCH_PASSWORD = espassword +SM_ELASTICSEARCH_USERNAME = admin +SM_ELASTICSEARCH_PASSWORD = p14c3r3P14c3r3 SM_ELASTICSEARCH_ENDPOINT = 0.0.0.0:9200 SM_ELASTICSEARCH_SCHEMA = https SM_DEFAULT_DEPLOYMENT_NAME = PIACERE Deployment -SM_ADMIN_USERNAME = smadmin -SM_ADMIN_PASSWORD = smadminpassword +SM_ADMIN_USERNAME = admin +SM_ADMIN_PASSWORD = test + +SM_POLL_WEBHOOK_URL = https://sh.ci.piacere.digital.tecnalia.dev/api/self-healing/notify +SM_POLL_WEBHOOK_USERNAME = admin +SM_POLL_WEBHOOK_PASSWORD = password +SM_POLL_TIMEOUT = 10 +SM_POLL_THRESHOLD = 9 [smsl] # Security Monitoring Self Learning section -SMSL_ENDPOINT = -SMSL_API_ENDPOINT = -SMSL_GRAFANA_ENDPOINT = +SMSL_ENDPOINT = https://piacere-security-monitoring.xlab.si +SMSL_API_ENDPOINT = https://piacere-security-monitoring.xlab.si/api +SMSL_GRAFANA_ENDPOINT = https://piacere-security-monitoring.xlab.si/grafana diff --git a/configuration/smc_settings_production.cfg b/configuration/smc_settings_production.cfg index 6befdef85876a95335c40dab8b635c54b569277d..19bd6643ce5821b3e1ff5753bf0c38227a2723d6 100644 --- a/configuration/smc_settings_production.cfg +++ b/configuration/smc_settings_production.cfg @@ -5,17 +5,21 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False [sm] # Security Monitoring section -SM_KIBANA_ENDPOINT = -SM_ELASTICSEARCH_USERNAME = elasticsearch -SM_ELASTICSEARCH_PASSWORD = espassword -SM_ELASTICSEARCH_ENDPOINT = +SM_KIBANA_ENDPOINT = https://sm.ci.piacere.digital.tecnalia.dev/security-monitoring/kibana +SM_ELASTICSEARCH_USERNAME = admin +SM_ELASTICSEARCH_PASSWORD = admin +SM_ELASTICSEARCH_ENDPOINT = sm.ci.piacere.digital.tecnalia.dev/security-monitoring/elasticsearch:9200 SM_ELASTICSEARCH_SCHEMA = https SM_DEFAULT_DEPLOYMENT_NAME = PIACERE Deployment -SM_ADMIN_USERNAME = smadmin -SM_ADMIN_PASSWORD = smadminpassword +SM_ADMIN_USERNAME = admin +SM_ADMIN_PASSWORD = test + +SM_POLL_WEBHOOK_URL = http://0.0.0.0:9090/reports +SM_POLL_TIMEOUT = 60 +SM_POLL_THRESHOLD = 7 [smsl] # Security Monitoring Self Learning section -SMSL_ENDPOINT = -SMSL_API_ENDPOINT = -SMSL_GRAFANA_ENDPOINT = +SMSL_ENDPOINT = https://piacere-security-monitoring.xlab.si +SMSL_API_ENDPOINT = https://piacere-security-monitoring.xlab.si/api +SMSL_GRAFANA_ENDPOINT = https://piacere-security-monitoring.xlab.si/grafana diff --git a/swagger_server/controllers/monitoring_controller.py b/swagger_server/controllers/monitoring_controller.py index 32fd57adfc3fb4904ddf428f196563a0ad8fd29a..32974a4fa1d4f27c220819c6245e548d69cb2144 100644 --- a/swagger_server/controllers/monitoring_controller.py +++ b/swagger_server/controllers/monitoring_controller.py @@ -117,7 +117,7 @@ def deployments_delete(deployment_id): deployment = Deployments.query.filter(Deployments.id == deployment_id).first() if not deployment: - return "Deyploment with this ID not found", 404 + return "Deployment with this ID not found", 404 db.session.delete(deployment) db.session.commit() diff --git a/swagger_server/helpers/__init__.py b/swagger_server/helpers/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..368bb2cf2c08f78c4a5524244fe3f9697af60a64 100644 --- a/swagger_server/helpers/__init__.py +++ b/swagger_server/helpers/__init__.py @@ -0,0 +1,5 @@ +import swagger_server.helpers.event_reports_helper + +event_reports_helper.start_thread() + + diff --git a/swagger_server/helpers/event_reports_helper.py b/swagger_server/helpers/event_reports_helper.py new file mode 100644 index 0000000000000000000000000000000000000000..26c8ea1c673876c6e2fa2a219a30daea948d08ec --- /dev/null +++ b/swagger_server/helpers/event_reports_helper.py @@ -0,0 +1,83 @@ +from swagger_server.helpers import config_helper +import requests +import _thread +import json +import time + + +def threadEventReports(): + timeout = int(config_helper.sm_config.config_parser["sm"]["SM_POLL_TIMEOUT"]) + timestamp = "now-" + str(timeout) + "s" + + # Setup variables for request + url = config_helper.sm_config.config_parser["sm"]["SM_ELASTICSEARCH_SCHEMA"] + "://" + config_helper.sm_config.config_parser["sm"]["SM_ELASTICSEARCH_ENDPOINT"] + "/wazuh-alerts*/_search" + + headers = { + "Content-Type": "application/json", + } + + data = { + "query": { + "bool": { + "must": [ + { + "range": { + "rule.level": { + "gte": int(config_helper.sm_config.config_parser["sm"]["SM_POLL_THRESHOLD"]) + } + } + }, + { + "range": { + "timestamp": { + "gte": timestamp + } + } + } + ] + } + } + } + elastic_auth = (config_helper.sm_config.config_parser["sm"]["SM_ELASTICSEARCH_USERNAME"], + config_helper.sm_config.config_parser["sm"]["SM_ELASTICSEARCH_PASSWORD"]) + webhook_auth = (config_helper.sm_config.config_parser["sm"]["SM_POLL_WEBHOOK_USERNAME"], + config_helper.sm_config.config_parser["sm"]["SM_POLL_WEBHOOK_PASSWORD"]) + + time.sleep(timeout) + while True: + elapsed_time = 0 + try: + elastic_response = requests.get(url, data=json.dumps(data), headers=headers, auth=elastic_auth, verify=False) + elapsed_time = elastic_response.elapsed.total_seconds() + except Exception as get_err: + print("Error occured (GET request): ", get_err) + else: + if json.loads(elastic_response.text)["hits"]["total"]["value"] > 0: + try: + print("sending data to webhook") + webhook_response = requests.post( + config_helper.sm_config.config_parser["sm"]["SM_POLL_WEBHOOK_URL"], + auth=webhook_auth, + json=elastic_response.json(), + timeout=timeout + ) + elapsed_time = elapsed_time + webhook_response.elapsed.total_seconds() + except requests.exceptions.ReadTimeout: + elapsed_time = timeout + # pass when no response from webhook + pass + except Exception as post_err: + print("Possibly no webhook, exiting events reporter thread") + print("Error: ", post_err) + break + time.sleep(timeout - elapsed_time) + +# Start new thread +def start_thread(): + try: + _thread.start_new_thread(threadEventReports, ()) + except Exception as err: + print("Unable to start thread for reporting events") + print("Error: ", err) + + diff --git a/test-requirements.txt b/test-requirements.txt index 2640639a25a3bffe0f449788303300a364c55cb7..e43ba7cba7af84f647036ffa36a314e12d86da8c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,4 +4,4 @@ nose>=1.3.7 pluggy>=0.3.1 py>=1.4.31 randomize>=0.13 -tox==3.20.1 +tox==3.27.1 diff --git a/tox.ini b/tox.ini index a24806146efbfa1c07b848b70f670de390ae0dc4..982148864b6cd6f1304920d8ea12080e7cb8c0d8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38 +envlist = py310 [testenv] deps=-r{toxinidir}/requirements.txt