Skip to content

Commit

Permalink
Merge pull request #214 from armosec/slack-sys-test
Browse files Browse the repository at this point in the history
add slack system test
  • Loading branch information
refaelm92 authored Dec 19, 2023
2 parents 277174e + 1cfae43 commit 4a63d75
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 24 deletions.
44 changes: 44 additions & 0 deletions configurations/notifications/slack-alert-channel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"channel": {
"name": "My Slack Channel",
"provider": "slack",
"context": {
"channel": {
"id": "abcd1234"
}
}
},
"notifications": [
{
"notificationType": "push:newClusterAdmin",
"disabled": false
},
{
"notificationType": "containerScanPush:newVulnerability",
"disabled": false,
"parameters": {
"minSeverity": 500
}
},
{
"notificationType": "containerScanPush:vulnerabilityNewFix",
"disabled": false,
"parameters": {
"minSeverity": 500
}
},
{
"notificationType": "push:complianceDrift",
"disabled": false,
"parameters": {
"driftPercentage": 15
}
}
],
"scope": [
{
"cluster": "cluster",
"namespaces": []
}
]
}
16 changes: 16 additions & 0 deletions configurations/system/tests_cases/notifications_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from os.path import join

from systest_utils.statics import DEFAULT_NOTIFICATIONS_PATHS, DEFAULT_NOTIFICATIONS_DEPLOYMENT_PATH
from tests_scripts.users_notifications.alert_notifications import get_messages_from_teams_channel, \
enrich_teams_alert_channel, get_messages_from_slack_channel, enrich_slack_alert_channel
from .structures import TestConfiguration


Expand Down Expand Up @@ -32,5 +34,19 @@ def teams_alerts():
name=inspect.currentframe().f_code.co_name,
test_obj=AlertNotifications,
deployments=join(DEFAULT_NOTIFICATIONS_DEPLOYMENT_PATH, "http"),
getMessagesFunc=get_messages_from_teams_channel,
enrichAlertChannelFunc=enrich_teams_alert_channel,
alert_channel_file=join(DEFAULT_NOTIFICATIONS_PATHS, "teams-alert-channel.json")
)

@staticmethod
def slack_alerts():
from tests_scripts.users_notifications.alert_notifications import AlertNotifications
return TestConfiguration(
name=inspect.currentframe().f_code.co_name,
test_obj=AlertNotifications,
deployments=join(DEFAULT_NOTIFICATIONS_DEPLOYMENT_PATH, "http"),
getMessagesFunc=get_messages_from_slack_channel,
enrichAlertChannelFunc=enrich_slack_alert_channel,
alert_channel_file=join(DEFAULT_NOTIFICATIONS_PATHS, "slack-alert-channel.json")
)
65 changes: 41 additions & 24 deletions tests_scripts/users_notifications/alert_notifications.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import json
import os
import time
from datetime import datetime

import requests
from slack_sdk import WebClient

from infrastructure import KubectlWrapper
from systest_utils import Logger, statics, TestUtil
Expand All @@ -13,6 +15,14 @@
TEST_NAMESPACE = "alerts"


def enrich_teams_alert_channel(data):
data["channel"]["context"]["webhook"]["id"] = os.getenv("CHANNEL_WEBHOOK")


def enrich_slack_alert_channel(data):
data["channel"]["context"]["channel"]["id"] = os.getenv("SLACK_CHANNEL_ID")


def get_access_token():
url = "https://login.microsoftonline.com/50a70646-52e3-4e46-911e-6ca1b46afba3/oauth2/v2.0/token"
headers = {
Expand All @@ -29,8 +39,9 @@ def get_access_token():


def get_messages_from_teams_channel(before_test):
before_test_utc = datetime.utcfromtimestamp(before_test).isoformat() + "Z"
endpoint = f'https://graph.microsoft.com/v1.0/teams/{os.getenv("TEAMS_ID")}/channels/{os.getenv("CHANNEL_ID")}' \
f'/messages/delta?$filter=lastModifiedDateTime gt {before_test}'
f'/messages/delta?$filter=lastModifiedDateTime gt {before_test_utc}'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Accept': 'application/json',
Expand All @@ -40,10 +51,10 @@ def get_messages_from_teams_channel(before_test):
return response.json().get('value', [])


def assert_test_message_sent(before_test):
messages = get_messages_from_teams_channel(before_test)
assert len(messages) == 1, "expected to be only one message"
assert "Test Alert" in str(messages[0]), "expected message to be a Test Alert"
def get_messages_from_slack_channel(before_test):
client = WebClient(token=os.getenv("SLACK_TOKEN"))
result = client.conversations_history(channel=f'{os.getenv("SLACK_CHANNEL_ID")}', oldest=before_test)
return result['messages']


def assert_vulnerability_message_sent(messages, cluster):
Expand Down Expand Up @@ -73,21 +84,6 @@ def assert_misconfiguration_message_sent(messages, cluster):
assert found == 1, "expected to have exactly one new misconfiguration message"


def assert_all_messages_sent(begin_time, cluster):
TestUtil.sleep(NOTIFICATIONS_SVC_DELAY, "waiting for notifications")
for i in range(5):
try:
messages = get_messages_from_teams_channel(begin_time)
assert str(messages).count(cluster) > 2, "expected to have at least 3 messages"
assert_vulnerability_message_sent(messages, cluster)
assert_new_admin_message_sent(messages, cluster)
assert_misconfiguration_message_sent(messages, cluster)
except AssertionError:
if i == 4:
raise
TestUtil.sleep(30, "waiting additional 30 seconds for messages to arrive")


class AlertNotifications(BaseHelm):

def __init__(self, test_obj=None, backend=None, kubernetes_obj=None, test_driver=None):
Expand Down Expand Up @@ -120,11 +116,12 @@ def start(self):
channel_guid = self.create_alert_channel(self.cluster)

Logger.logger.info("Stage 3: Send Test Alert message")
before_test_message_ts = time.time()
before_test_message = datetime.utcnow().isoformat() + "Z"
self.backend.send_test_message(channel_guid)

Logger.logger.info("Stage 4: Read Test Alert message")
assert_test_message_sent(before_test_message)
self.assert_test_message_sent(before_test_message_ts)

Logger.logger.info('Stage 5: Apply deployment')
workload_objs: list = self.apply_directory(path=self.test_obj["deployments"], namespace=TEST_NAMESPACE)
Expand All @@ -142,13 +139,14 @@ def start(self):
framework_guid=fw['guid'], cluster_name=self.cluster)

Logger.logger.info('Stage 9: Add SA to cluster-admin')
KubectlWrapper.add_new_service_account_to_cluster_admin(service_account="service-account", namespace=TEST_NAMESPACE)
KubectlWrapper.add_new_service_account_to_cluster_admin(service_account="service-account",
namespace=TEST_NAMESPACE)

Logger.logger.info('Stage 10: Trigger second scan')
self.backend.create_kubescape_job_request(cluster_name=self.cluster, framework_list=[self.fw_name])

Logger.logger.info('Stage 11: Assert all messages sent')
assert_all_messages_sent(before_test_message, self.cluster)
self.assert_all_messages_sent(before_test_message, self.cluster)
return self.cleanup()

def cleanup(self, **kwargs):
Expand Down Expand Up @@ -186,6 +184,25 @@ def get_alert_channel_payload(self, cluster_name: str):
with open(self.test_obj["alert_channel_file"], 'r') as file:
data = json.load(file)
data["channel"]["name"] = cluster_name + "_cluster"
data["channel"]["context"]["webhook"]["id"] = os.getenv("CHANNEL_WEBHOOK")
data["scope"][0]["cluster"] = cluster_name
self.test_obj["enrichAlertChannelFunc"](data)
return data

def assert_all_messages_sent(self, begin_time, cluster):
TestUtil.sleep(NOTIFICATIONS_SVC_DELAY, "waiting for notifications")
for i in range(5):
try:
messages = self.test_obj["getMessagesFunc"](begin_time)
assert str(messages).count(cluster) > 2, "expected to have at least 3 messages"
assert_vulnerability_message_sent(messages, cluster)
assert_new_admin_message_sent(messages, cluster)
assert_misconfiguration_message_sent(messages, cluster)
except AssertionError:
if i == 4:
raise
TestUtil.sleep(30, "waiting additional 30 seconds for messages to arrive")

def assert_test_message_sent(self, before_test):
messages = self.test_obj["getMessagesFunc"](before_test)
assert len(messages) == 1, "expected to be only one message"
assert "Test Alert" in str(messages[0]), "expected message to be a Test Alert"

0 comments on commit 4a63d75

Please sign in to comment.