summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc_collector/schema.py57
-rw-r--r--src/soc_collector/soc_collector_cli.py8
-rw-r--r--tests/data/example_data_1.json9
-rw-r--r--tests/data/example_data_1_replace_test.json9
-rw-r--r--tests/data/example_data_3.json8
-rw-r--r--tests/data/example_data_3_replace_test.json8
6 files changed, 65 insertions, 34 deletions
diff --git a/src/soc_collector/schema.py b/src/soc_collector/schema.py
index 2c2dfb9..7688631 100644
--- a/src/soc_collector/schema.py
+++ b/src/soc_collector/schema.py
@@ -1,6 +1,10 @@
"""Our schema module"""
from typing import Any, Dict, Optional, Union
-import jsonschema
+from jsonschema.exceptions import ValidationError
+
+# docker-compose require jsonschema < 4 so use Draft7 for now
+from jsonschema.validators import Draft7Validator
+
from bson import ObjectId
from bson.errors import InvalidId
@@ -8,12 +12,19 @@ from bson.errors import InvalidId
# NOTE: Commented out properties are left intentionally, so it is easier to see
# what properties are optional.
schema = {
- "$schema": "http://json-schema.org/schema#",
+ "$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
- "document_version": {"type": "integer"},
+ "document_version": {"type": "integer", "minimum": 2},
+ "tags": {
+ "type": "array",
+ "uniqueItems": True,
+ "items": {"type": "string", "enum": ["dev", "display", "hide", "notify"]},
+ "minItems": 1,
+ "maxItems": 3 # hide is incompatible with notify and/or display
+ },
"ip": {"type": "string"},
- "port": {"type": "integer"},
+ "port": {"type": "integer", "minimum": 1, "maximum": 65535},
"whois_description": {"type": "string"},
"asn": {"type": "string"},
"asn_country_code": {"type": "string"},
@@ -50,34 +61,29 @@ schema = {
"display_name": {"type": "string"},
"vulnerable": {"type": "boolean"},
"investigation_needed": {"type": "boolean"},
- "reliability": {"type": "integer"},
+ "reliability": {"type": "integer", "minimum": 1, "maximum": 5},
+ "severity": {"type": "integer", "minimum": 1, "maximum": 5},
"description": {"type": "string"},
},
"oneOf": [
{
- "required": [
- "display_name",
- "vulnerable",
- # "reliability", # TODO: reliability is required if vulnerable = true
- # "description",
- ]
+ "properties": {"investigation_needed": {"const": True}},
+ "required": ["display_name", "investigation_needed", "description"]
},
{
- "required":
- [
- "display_name",
- "investigation_needed",
- # "reliability", # TODO: reliability is required if investigation_needed = true
- # "description",
- ]
- },
+ "properties": {"vulnerable": {"type": "boolean"}},
+ "if": {"properties": {"vulnerable": {"const": True}}},
+ "then": {"required": ["display_name", "vulnerable", "reliability", "severity", "description"]},
+ "else": {"required": ["display_name", "vulnerable"]}
+ }
]
- },
- },
- },
+ }
+ }
+ }
},
"required": [
"document_version",
+ "tags",
"ip",
"port",
"whois_description",
@@ -88,9 +94,9 @@ schema = {
"domain",
"timestamp",
"display_name",
+ "result"
# "description",
# "custom_data",
- "result",
],
}
@@ -103,8 +109,9 @@ def valid_schema(json_data: Dict[str, Any]) -> bool:
"""
try:
- jsonschema.validate(json_data, schema, format_checker=jsonschema.FormatChecker())
- except jsonschema.exceptions.ValidationError as exc:
+ # docker-compose require jsonschema < 4 so use Draft7 for now
+ Draft7Validator(schema).validate(json_data)
+ except ValidationError as exc:
print(f"Validation failed with error: {exc.message}")
return False
return True
diff --git a/src/soc_collector/soc_collector_cli.py b/src/soc_collector/soc_collector_cli.py
index 4929655..85afce1 100644
--- a/src/soc_collector/soc_collector_cli.py
+++ b/src/soc_collector/soc_collector_cli.py
@@ -8,7 +8,7 @@ from sys import exit as app_exit
import json
import requests
-from .schema import object_id_from_data
+from .schema import object_id_from_data, valid_schema
ROOT_CA_FILE = __file__.replace("soc_collector_cli.py", "data/collector_root_ca.crt")
@@ -136,6 +136,9 @@ def replace_action(data: str, api_key: str, base_url: str = "https://collector-d
print("ERROR: Valid '_id' key not in data")
app_exit(1)
+ if not valid_schema(json_data):
+ app_exit(1)
+
req = requests.put(
f"{base_url}/sc/v0", json=json_data, headers={"API-KEY": api_key}, timeout=5, verify=ROOT_CA_FILE
)
@@ -166,6 +169,9 @@ def insert_action(data: str, api_key: str, base_url: str = "https://collector-de
print("ERROR: '_id' key in data")
app_exit(1)
+ if not valid_schema(json_data):
+ app_exit(1)
+
req = requests.post(
f"{base_url}/sc/v0", json=json_data, headers={"API-KEY": api_key}, timeout=5, verify=ROOT_CA_FILE
)
diff --git a/tests/data/example_data_1.json b/tests/data/example_data_1.json
index 69f5d85..b0adb8a 100644
--- a/tests/data/example_data_1.json
+++ b/tests/data/example_data_1.json
@@ -1,5 +1,6 @@
{
- "document_version": 1,
+ "document_version": 2,
+ "tags": ["dev", "hide"],
"ip": "192.0.2.10",
"port": 443,
"whois_description": "SOMENET",
@@ -35,7 +36,9 @@
"cve_2015_0060": {
"display_name": "CVE-2015-0060",
"vulnerable": true,
- "reliability": 2
+ "reliability": 2,
+ "severity": 2,
+ "description": "Allows local users to cause a denial of service (system hang) via a crafted application, aka Windows Font Driver Denial of Service Vulnerability."
},
"cve_2015_0063": {
"display_name": "CVE-2015-0063",
@@ -45,12 +48,14 @@
"display_name": "Insecure cryptography",
"vulnerable": true,
"reliability": 5,
+ "severity": 3,
"description": "Uses RSA instead of elliptic curve."
},
"possible_webshell": {
"display_name": "Webshells (PST)",
"investigation_needed": true,
"reliability": 1,
+ "severity": 3,
"description": "A webshell of type PST was confirmed at /test/webshell.php"
}
}
diff --git a/tests/data/example_data_1_replace_test.json b/tests/data/example_data_1_replace_test.json
index f56d82c..4d07181 100644
--- a/tests/data/example_data_1_replace_test.json
+++ b/tests/data/example_data_1_replace_test.json
@@ -1,5 +1,6 @@
{
"document_version": 2,
+ "tags": ["dev", "hide"],
"ip": "192.0.2.10",
"port": 444,
"whois_description": "SOMENET",
@@ -9,7 +10,7 @@
"abuse_mail": "abuse@test.soc.sunet.se",
"domain": "sunet.se",
"timestamp": "2021-06-21T14:06:00Z",
- "display_name": "Apache 2.1.3",
+ "display_name": "Apache 2.1.4",
"description": "The Apache HTTP Server is a free and open-source cross-platform web server software, released under the terms of Apache License 2.0.",
"custom_data": {
"subject_cn": {
@@ -35,7 +36,9 @@
"cve_2015_0060": {
"display_name": "CVE-2015-0060",
"vulnerable": true,
- "reliability": 2
+ "reliability": 2,
+ "severity": 3,
+ "description": "Allows local users to cause a denial of service (system hang) via a crafted application, aka Windows Font Driver Denial of Service Vulnerability."
},
"cve_2015_0063": {
"display_name": "CVE-2015-0063",
@@ -45,12 +48,14 @@
"display_name": "Insecure cryptography",
"vulnerable": true,
"reliability": 5,
+ "severity": 2,
"description": "Uses RSA instead of elliptic curve."
},
"possible_webshell": {
"display_name": "Webshells (PST)",
"investigation_needed": true,
"reliability": 1,
+ "severity": 1,
"description": "A webshell of type PST was confirmed at /test/webshell.php"
}
}
diff --git a/tests/data/example_data_3.json b/tests/data/example_data_3.json
index 44d483b..897f9d3 100644
--- a/tests/data/example_data_3.json
+++ b/tests/data/example_data_3.json
@@ -1,5 +1,6 @@
{
- "document_version": 1,
+ "document_version": 3,
+ "tags": ["notify", "display"],
"ip": "192.0.2.28",
"port": 111,
"whois_description": "SOMENET",
@@ -36,6 +37,7 @@
"display_name": "CVE-2015-0003",
"vulnerable": true,
"reliability": 2,
+ "severity": 4,
"description": "A carefully crafted request body can cause a read to a random memory area which could cause the process to crash."
},
"cve_2015_0004": {
@@ -45,7 +47,9 @@
"cve_2015_0005": {
"display_name": "CVE-2015-0005",
"vulnerable": true,
- "reliability": 4
+ "severity": 4,
+ "reliability": 4,
+ "description": "Allows local users to cause a denial of service (system hang) via a crafted application, aka Windows Font Driver Denial of Service Vulnerability."
}
}
}
diff --git a/tests/data/example_data_3_replace_test.json b/tests/data/example_data_3_replace_test.json
index 31cc64d..5f09020 100644
--- a/tests/data/example_data_3_replace_test.json
+++ b/tests/data/example_data_3_replace_test.json
@@ -1,6 +1,7 @@
{
"_id": "6370498050845fac09e0fc01",
"document_version": 2,
+ "tags": ["dev"],
"ip": "192.0.2.28",
"port": 112,
"whois_description": "SOMENET",
@@ -10,7 +11,7 @@
"abuse_mail": "abuse@test.soc.sunet.se",
"domain": "sunet.se",
"timestamp": "2021-06-30T15:00:00Z",
- "display_name": "VMware ESXi 6.7.0 build-17700523",
+ "display_name": "VMware ESXi 6.7.1 build-17700523",
"description": "VMware ESXi is an enterprise-class, type-1 hypervisor developed by VMware for deploying and serving virtual computers. As a type-1 hypervisor, ESXi is not a software application that is installed on an operating system; instead, it includes and integrates vital OS components, such as a kernel.",
"custom_data": {
"subject_cn": {
@@ -37,6 +38,7 @@
"display_name": "CVE-2015-0003",
"vulnerable": true,
"reliability": 2,
+ "severity": 4,
"description": "A carefully crafted request body can cause a read to a random memory area which could cause the process to crash."
},
"cve_2015_0004": {
@@ -46,7 +48,9 @@
"cve_2015_0005": {
"display_name": "CVE-2015-0005",
"vulnerable": true,
- "reliability": 4
+ "severity": 5,
+ "reliability": 4,
+ "description": "Allows local users to cause a denial of service (system hang) via a crafted application, aka Windows Font Driver Denial of Service Vulnerability."
}
}
}