Skip to content

Commit 2a4709d

Browse files
committed
Fix tests coverage
- Add tool to find missing files in coverage report. - Add packages to coverage source config, to fix the issues with the namespace packages. - Add missing __init__.py files for the inventory, okta and wsone management commands packages to facilitate the coverage discovery. - Add missing store test cases - Add all missing actions to tests base.json
1 parent a560e89 commit 2a4709d

File tree

15 files changed

+422
-10
lines changed

15 files changed

+422
-10
lines changed

ee/zentral/contrib/wsone/management/__init__.py

Whitespace-only changes.

ee/zentral/contrib/wsone/management/commands/__init__.py

Whitespace-only changes.

tests/conf/base.json

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
"metrics_bearer_token": "CHANGE ME!!!"
99
},
1010
"extra_links": [
11-
{"anchor_text": "Prometheus",
12-
"url": "https://zentral/prometheus/"}
11+
{
12+
"anchor_text": "Prometheus",
13+
"url": "https://zentral/prometheus/"
14+
}
1315
],
1416
"django": {
1517
"SECRET_KEY": "DJANGO SECRET !!! CHANGE THIS !!! DO NOT USE IN PRODUCTION !!!",
@@ -46,6 +48,70 @@
4648
"debug": {
4749
"backend": "zentral.core.actions.backends.json_file",
4850
"local_dir": "/tmp/zentral_notifications/"
51+
},
52+
"test_email": {
53+
"backend": "zentral.core.actions.backends.email",
54+
"smtp_host": "127.0.0.1",
55+
"smtp_port": 25,
56+
"recipients": [
57+
"hi@example.com"
58+
]
59+
},
60+
"test_freshdesk": {
61+
"backend": "zentral.core.actions.backends.freshdesk",
62+
"api_key": "123",
63+
"password": "456",
64+
"subdomain": "test",
65+
"default_ticket_email": "hi@example.com",
66+
"extra_attributes": {
67+
"un": "deux"
68+
}
69+
},
70+
"test_google_chat": {
71+
"backend": "zentral.core.actions.backends.google_chat",
72+
"webhook": "https://example.com"
73+
},
74+
"test_http_post": {
75+
"backend": "zentral.core.actions.backends.http_post",
76+
"url": "https://example.com",
77+
"basic_auth": {
78+
"login": "user",
79+
"password": "123"
80+
},
81+
"headers": {
82+
"X-Custom-Header": "value"
83+
}
84+
},
85+
"test_slack": {
86+
"backend": "zentral.core.actions.backends.slack",
87+
"webhook": "https://example.com"
88+
},
89+
"test_github": {
90+
"backend": "zentral.core.actions.backends.github",
91+
"repository": "example",
92+
"user": "user",
93+
"access_token": "123",
94+
"assignees": [
95+
"person1",
96+
"person2"
97+
]
98+
},
99+
"test_trello": {
100+
"backend": "zentral.core.actions.backends.trello",
101+
"application_key": "123",
102+
"token": "456",
103+
"default_board": "default_board",
104+
"default_list": "default_list"
105+
},
106+
"test_twilio": {
107+
"backend": "zentral.core.actions.backends.twilio",
108+
"account_sid": "123",
109+
"auth_token": "456",
110+
"from_number": "0123456789",
111+
"to_numbers": [
112+
"1234567890",
113+
"2345678901"
114+
]
49115
}
50116
},
51117
"apps": {
@@ -93,19 +159,29 @@
93159
"zentral.contrib.munki": {
94160
"metrics": true,
95161
"principal_user_detection": {
96-
"sources": ["company_portal", "google_chrome", "logged_in_user"],
97-
"domains": ["zentral.pro"]
162+
"sources": [
163+
"company_portal",
164+
"google_chrome",
165+
"logged_in_user"
166+
],
167+
"domains": [
168+
"zentral.pro"
169+
]
98170
}
99171
},
100172
"zentral.contrib.monolith": {
101173
"metrics": true,
102174
"enrollment_package_builders": {
103175
"zentral.contrib.munki.osx_package.builder.MunkiZentralEnrollPkgBuilder": {
104-
"requires": ["munkitools_core"],
176+
"requires": [
177+
"munkitools_core"
178+
],
105179
"optional": false
106180
},
107181
"zentral.contrib.osquery.osx_package.builder.OsqueryZentralEnrollPkgBuilder": {
108-
"requires": ["osquery"],
182+
"requires": [
183+
"osquery"
184+
],
109185
"optional": true
110186
}
111187
},

tests/stores/test_datadog.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from unittest.mock import Mock
2+
from django.test import SimpleTestCase
3+
from django.utils.crypto import get_random_string
4+
from accounts.events import EventMetadata, LoginEvent
5+
from zentral.core.stores.backends.datadog import EventStore
6+
7+
8+
class DatadogStoreTestCase(SimpleTestCase):
9+
def get_store(self, **kwargs):
10+
for arg, default in (("store_name", get_random_string(12)),
11+
("site", "datadoghq.com"),
12+
("service", None),
13+
("source", None),
14+
("api_key", "123"),
15+
("application_key", "456")):
16+
val = kwargs.get(arg)
17+
if val is None and default is not None:
18+
kwargs[arg] = default
19+
return EventStore(kwargs)
20+
21+
def build_login_event(self, username=None):
22+
if username is None:
23+
username = get_random_string(12)
24+
return LoginEvent(EventMetadata(), {"user": {"username": username}})
25+
26+
def test_event_serialization(self):
27+
username = get_random_string(12)
28+
event = self.build_login_event(username)
29+
self.assertEqual(
30+
self.get_store()._serialize_event(event),
31+
{'@timestamp': event.metadata.created_at.isoformat(),
32+
'ddsource': 'zentral',
33+
'ddtags': 'ztl-tag:zentral',
34+
'host': 'Zentral',
35+
'id': str(event.metadata.uuid),
36+
'index': 0,
37+
'logger': {'name': 'zentral_login'},
38+
'namespace': 'zentral',
39+
'service': 'Zentral',
40+
'zentral': {'user': {'username': username}}}
41+
)
42+
43+
def test_dict_event_serialization(self):
44+
username = get_random_string(12)
45+
event = self.build_login_event(username)
46+
self.assertEqual(
47+
self.get_store()._serialize_event(event.serialize()),
48+
{'@timestamp': event.metadata.created_at.isoformat(),
49+
'ddsource': 'zentral',
50+
'ddtags': 'ztl-tag:zentral',
51+
'host': 'Zentral',
52+
'id': str(event.metadata.uuid),
53+
'index': 0,
54+
'logger': {'name': 'zentral_login'},
55+
'namespace': 'zentral',
56+
'service': 'Zentral',
57+
'zentral': {'user': {'username': username}}}
58+
)
59+
60+
def test_store(self):
61+
mock_response = Mock()
62+
mock_response.raise_for_status.return_value = None
63+
mock_post = Mock(return_value=mock_response)
64+
store = self.get_store()
65+
store._session.post = mock_post
66+
event = self.build_login_event()
67+
store.store(event)
68+
mock_post.assert_called_once()
69+
mock_response.raise_for_status.assert_called_once()

tests/stores/test_http.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from unittest.mock import Mock
2+
from django.test import SimpleTestCase
3+
from django.utils.crypto import get_random_string
4+
from accounts.events import EventMetadata, LoginEvent
5+
from zentral.core.stores.backends.http import EventStore
6+
7+
8+
class HttpStoreTestCase(SimpleTestCase):
9+
def get_store(self, **kwargs):
10+
for arg, default in (("store_name", get_random_string(12)),
11+
("endpoint_url", "https://example.com"),
12+
("verify_tls", None),
13+
("headers", None),
14+
("username", None),
15+
("password", None)):
16+
val = kwargs.get(arg)
17+
if val is None and default is not None:
18+
kwargs[arg] = default
19+
return EventStore(kwargs)
20+
21+
def build_login_event(self, username=None):
22+
if username is None:
23+
username = get_random_string(12)
24+
return LoginEvent(EventMetadata(), {"user": {"username": username}})
25+
26+
def test_event_serialization(self):
27+
username = get_random_string(12)
28+
event = self.build_login_event(username)
29+
self.assertEqual(
30+
self.get_store().client._serialize_event(event),
31+
{'created_at': event.metadata.created_at.isoformat(),
32+
'id': str(event.metadata.uuid),
33+
'index': 0,
34+
'namespace': 'zentral',
35+
'tags': ['zentral'],
36+
'type': 'zentral_login',
37+
'zentral': {'user': {'username': username}}}
38+
)
39+
40+
def test_dict_event_serialization(self):
41+
username = get_random_string(12)
42+
event = self.build_login_event(username)
43+
self.assertEqual(
44+
self.get_store().client._serialize_event(event.serialize()),
45+
{'created_at': event.metadata.created_at.isoformat(),
46+
'id': str(event.metadata.uuid),
47+
'index': 0,
48+
'namespace': 'zentral',
49+
'tags': ['zentral'],
50+
'type': 'zentral_login',
51+
'zentral': {'user': {'username': username}}}
52+
)
53+
54+
def test_store(self):
55+
mock_response = Mock()
56+
mock_response.ok = True
57+
mock_post = Mock(return_value=mock_response)
58+
store = self.get_store()
59+
store.client.session.post = mock_post
60+
event = self.build_login_event()
61+
store.store(event)
62+
mock_post.assert_called_once()

tests/stores/test_humio.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from unittest.mock import Mock
2+
from django.test import SimpleTestCase
3+
from django.utils.crypto import get_random_string
4+
from accounts.events import EventMetadata, LoginEvent
5+
from zentral.core.stores.backends.humio import EventStore
6+
7+
8+
class HumioStoreTestCase(SimpleTestCase):
9+
def get_store(self, **kwargs):
10+
for arg, default in (("store_name", get_random_string(12)),
11+
("base_url", "https://example.com"),
12+
("ingest_token", "123")):
13+
val = kwargs.get(arg)
14+
if val is None and default is not None:
15+
kwargs[arg] = default
16+
return EventStore(kwargs)
17+
18+
def build_login_event(self, username=None):
19+
if username is None:
20+
username = get_random_string(12)
21+
return LoginEvent(EventMetadata(), {"user": {"username": username}})
22+
23+
def test_event_serialization(self):
24+
username = get_random_string(12)
25+
event = self.build_login_event(username)
26+
self.assertEqual(
27+
self.get_store()._serialize_event(event),
28+
[{'events': [{'attributes': {'id': str(event.metadata.uuid),
29+
'index': 0,
30+
'namespace': 'zentral',
31+
'tags': ['zentral'],
32+
'zentral': {'user': {'username': username}}},
33+
'timestamp': event.metadata.created_at.isoformat()[:-3] + "Z"}],
34+
'tags': {'event_type': 'zentral_login'}}]
35+
)
36+
37+
def test_dict_event_serialization(self):
38+
username = get_random_string(12)
39+
event = self.build_login_event(username)
40+
self.assertEqual(
41+
self.get_store()._serialize_event(event.serialize()),
42+
[{'events': [{'attributes': {'id': str(event.metadata.uuid),
43+
'index': 0,
44+
'namespace': 'zentral',
45+
'tags': ['zentral'],
46+
'zentral': {'user': {'username': username}}},
47+
'timestamp': event.metadata.created_at.isoformat()[:-3] + "Z"}],
48+
'tags': {'event_type': 'zentral_login'}}]
49+
)
50+
51+
def test_store(self):
52+
mock_response = Mock()
53+
mock_response.raise_for_status.return_value = None
54+
mock_post = Mock(return_value=mock_response)
55+
store = self.get_store()
56+
store._session.post = mock_post
57+
event = self.build_login_event()
58+
store.store(event)
59+
mock_post.assert_called_once()
60+
mock_response.raise_for_status.assert_called_once()

tests/stores/test_kinesis.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from unittest.mock import Mock
2+
from django.test import SimpleTestCase
3+
from django.utils.crypto import get_random_string
4+
from accounts.events import EventMetadata, LoginEvent
5+
from zentral.core.stores.backends.kinesis import EventStore
6+
7+
8+
class KinesisStoreTestCase(SimpleTestCase):
9+
def get_store(self, **kwargs):
10+
for arg, default in (("store_name", get_random_string(12)),
11+
("stream", "123"),
12+
("region_name", "us-east1"),
13+
("aws_access_key_id", "123"),
14+
("aws_secret_access_key", "456")):
15+
val = kwargs.get(arg)
16+
if val is None and default is not None:
17+
kwargs[arg] = default
18+
return EventStore(kwargs)
19+
20+
def build_login_event(self, username=None):
21+
if username is None:
22+
username = get_random_string(12)
23+
return LoginEvent(EventMetadata(), {"user": {"username": username}})
24+
25+
def test_store(self):
26+
store = self.get_store()
27+
store.wait_and_configure_if_necessary()
28+
mock_client = Mock()
29+
mock_client.put_record.return_value = None
30+
store.client = mock_client
31+
event = self.build_login_event()
32+
store.store(event)
33+
mock_client.put_record.assert_called_once()

tests/stores/test_syslog.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from unittest.mock import Mock, patch
2+
from django.test import SimpleTestCase
3+
from django.utils.crypto import get_random_string
4+
from accounts.events import EventMetadata, LoginEvent
5+
from zentral.core.stores.backends.syslog import EventStore
6+
7+
8+
class SyslogStoreTestCase(SimpleTestCase):
9+
def get_store(self, **kwargs):
10+
for arg, default in (("store_name", get_random_string(12)),
11+
("priority", None),
12+
("facility", None),
13+
("prepend_ecc", None),
14+
("protocol", None),
15+
("host", None),
16+
("port", None)):
17+
val = kwargs.get(arg)
18+
if val is None and default is not None:
19+
kwargs[arg] = default
20+
return EventStore(kwargs)
21+
22+
def build_login_event(self, username=None):
23+
if username is None:
24+
username = get_random_string(12)
25+
return LoginEvent(EventMetadata(), {"user": {"username": username}})
26+
27+
@patch("zentral.core.stores.backends.syslog.socket")
28+
def test_store(self, syslog_socket):
29+
mock_socket = Mock()
30+
mock_socket.connect.return_value = None
31+
mock_socket.send.return_value = None
32+
syslog_socket.socket.return_value = mock_socket
33+
store = self.get_store()
34+
store.wait_and_configure_if_necessary()
35+
event = self.build_login_event()
36+
store.store(event)
37+
mock_socket.connect.assert_called_once()
38+
mock_socket.send.assert_called_once()

0 commit comments

Comments
 (0)