clue-api 1.3.0.dev87__tar.gz → 1.3.0.dev92__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/PKG-INFO +1 -1
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/app.py +24 -10
- clue_api-1.3.0.dev92/clue/constants/supported_types.py +71 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/extensions/config.py +1 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/pyproject.toml +1 -1
- clue_api-1.3.0.dev87/clue/constants/supported_types.py +0 -40
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/LICENSE +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/README.md +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/.gitignore +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/base.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/actions.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/auth.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/configs.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/fetchers.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/lookup.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/registration.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/static.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cache/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/classification.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/classification.yml +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/dict_utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/exceptions.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/forge.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/json_utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/list_utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/audit.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/format.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/regex.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/str_utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/swagger.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/uid.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/config.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/constants/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/constants/env.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cronjobs/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cronjobs/plugins.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/error.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/extensions/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/gunicorn_config.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/healthz.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/discover.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/headers.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/oauth.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/actions.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/config.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/fetchers.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/graph.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/model_list.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/network.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/base.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/graph.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/image.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/status.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/validation.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/selector.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/validators.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/patched.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/central_server.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/email_render.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/token.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/trino.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/models.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/py.typed +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/cache.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/events.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/hash.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/queues/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/queues/comms.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/set.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/user_quota_tracker.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/__init__.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/obo.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/utils.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/action_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/auth_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/config_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/fetcher_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/jwt_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/lookup_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/type_service.py +0 -0
- {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/user_service.py +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
1
3
|
from gevent import monkey
|
|
2
4
|
|
|
3
5
|
monkey.patch_all()
|
|
@@ -10,16 +12,25 @@ from dotenv import load_dotenv
|
|
|
10
12
|
|
|
11
13
|
load_dotenv()
|
|
12
14
|
|
|
13
|
-
# We append the
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
# We append the extension directory for howler to the python part
|
|
16
|
+
EXTENSION_PATH = Path(
|
|
17
|
+
os.environ.get("CLUE_EXTENSION_PATH", os.environ.get("CLUE_PLUGIN_DIRECTORY", "/etc/clue/extensions"))
|
|
18
|
+
)
|
|
19
|
+
if not EXTENSION_PATH.exists():
|
|
20
|
+
if "CLUE_EXTENSION_PATH" not in os.environ and "CLUE_PLUGIN_DIRECTORY" not in os.environ:
|
|
21
|
+
warnings.warn(
|
|
22
|
+
f"{EXTENSION_PATH} doesn't exist, using legacy extension path /etc/clue/plugins", DeprecationWarning
|
|
23
|
+
)
|
|
24
|
+
EXTENSION_PATH = Path("/etc/clue/plugins")
|
|
25
|
+
|
|
26
|
+
sys.path.insert(0, str(EXTENSION_PATH))
|
|
16
27
|
|
|
17
28
|
from clue.config import DEBUG, SECRET_KEY, cache, config
|
|
18
29
|
|
|
19
|
-
if config.api.debug and
|
|
20
|
-
for
|
|
30
|
+
if config.api.debug and EXTENSION_PATH.exists():
|
|
31
|
+
for _extension in EXTENSION_PATH.iterdir():
|
|
21
32
|
sys.path.append(
|
|
22
|
-
str(Path(os.path.realpath(
|
|
33
|
+
str(Path(os.path.realpath(_extension)) / f"../.venv/lib/python3.{sys.version_info.minor}/site-packages")
|
|
23
34
|
)
|
|
24
35
|
|
|
25
36
|
import logging
|
|
@@ -121,12 +132,15 @@ app.register_blueprint(registration_api)
|
|
|
121
132
|
app.register_blueprint(static_api)
|
|
122
133
|
|
|
123
134
|
|
|
124
|
-
logger.info("Checking
|
|
125
|
-
for
|
|
126
|
-
if
|
|
135
|
+
logger.info("Checking extensions for additional routes")
|
|
136
|
+
for extension in get_extensions():
|
|
137
|
+
if extension.modules.init:
|
|
138
|
+
extension.modules.init(flask_app=app)
|
|
139
|
+
|
|
140
|
+
if not extension.modules.routes:
|
|
127
141
|
continue
|
|
128
142
|
|
|
129
|
-
for route in cast(list[Blueprint],
|
|
143
|
+
for route in cast(list[Blueprint], extension.modules.routes):
|
|
130
144
|
logger.info("Enabling additional endpoint: %s", route.url_prefix)
|
|
131
145
|
app.register_blueprint(route)
|
|
132
146
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from clue.common.logging import get_logger
|
|
2
|
+
from clue.common.regex import (
|
|
3
|
+
DOMAIN_ONLY_REGEX,
|
|
4
|
+
EMAIL_PATH_REGEX,
|
|
5
|
+
EMAIL_REGEX,
|
|
6
|
+
HBS_AGENT_ID_REGEX,
|
|
7
|
+
IPV4_ONLY_REGEX,
|
|
8
|
+
IPV6_ONLY_REGEX,
|
|
9
|
+
MD5_REGEX,
|
|
10
|
+
PORT_REGEX,
|
|
11
|
+
SHA1_REGEX,
|
|
12
|
+
SHA256_REGEX,
|
|
13
|
+
URI_ONLY,
|
|
14
|
+
UUID4_REGEX,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__file__)
|
|
18
|
+
|
|
19
|
+
SUPPORTED_TYPES = {
|
|
20
|
+
"ipv4": IPV4_ONLY_REGEX,
|
|
21
|
+
"ipv6": IPV6_ONLY_REGEX,
|
|
22
|
+
# We don't auto-detect ip types, as it's redundant with ipv4/v6. This is just a convenience/backwards compat thing
|
|
23
|
+
"ip": None,
|
|
24
|
+
"domain": DOMAIN_ONLY_REGEX,
|
|
25
|
+
"port": PORT_REGEX,
|
|
26
|
+
"url": URI_ONLY,
|
|
27
|
+
"userid": None,
|
|
28
|
+
"user_agent": None,
|
|
29
|
+
"email_address": EMAIL_REGEX,
|
|
30
|
+
"email_id": None,
|
|
31
|
+
"email_path": EMAIL_PATH_REGEX,
|
|
32
|
+
"md5": MD5_REGEX,
|
|
33
|
+
"sha1": SHA1_REGEX,
|
|
34
|
+
"sha256": SHA256_REGEX,
|
|
35
|
+
"hbs_oid": None,
|
|
36
|
+
"hbs_agent_id": HBS_AGENT_ID_REGEX,
|
|
37
|
+
"telemetry": None,
|
|
38
|
+
"howler_id": None,
|
|
39
|
+
"hostname": None,
|
|
40
|
+
"tenant-id": UUID4_REGEX,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def add_supported_type(type: str, regex: str | None = None, namespace: str | None = None):
|
|
45
|
+
r"""Add a supported type to the SUPPORTED_TYPES registry.
|
|
46
|
+
|
|
47
|
+
This function registers a new type with an optional regex pattern for validation.
|
|
48
|
+
The type can be added to either the default namespace or a custom namespace.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
type (str): The name of the type to be added.
|
|
52
|
+
regex (str | None, optional): A regex pattern for validating the type. Defaults to None.
|
|
53
|
+
namespace (str | None, optional): The namespace for the type. If None, adds to default namespace.
|
|
54
|
+
Defaults to None.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
None
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
>>> add_supported_type("email", r"^[\w\.-]+@[\w\.-]+\.\w+$")
|
|
61
|
+
>>> add_supported_type("custom_id", r"^\d{5}$", namespace="myapp")
|
|
62
|
+
"""
|
|
63
|
+
if not namespace:
|
|
64
|
+
logger.info("Adding new type %s to the default namespace with regex %s", type, regex)
|
|
65
|
+
SUPPORTED_TYPES[type] = regex
|
|
66
|
+
else:
|
|
67
|
+
logger.info("Adding type %s to namespace %s with regex %s", type, namespace, regex)
|
|
68
|
+
SUPPORTED_TYPES[f"{namespace}/{type}"] = regex
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
CASE_INSENSITIVE_TYPES = ["ip", "domain", "port", "tenant-id", "hbs_oid", "hbs_agent_id"]
|
|
@@ -142,7 +142,7 @@ log_cli_level = "WARN"
|
|
|
142
142
|
[tool.poetry]
|
|
143
143
|
package-mode = true
|
|
144
144
|
name = "clue-api"
|
|
145
|
-
version = "1.3.0.
|
|
145
|
+
version = "1.3.0.dev92"
|
|
146
146
|
description = "Clue distributed enrichment service"
|
|
147
147
|
authors = ["Canadian Centre for Cyber Security <contact@cyber.gc.ca>"]
|
|
148
148
|
license = "MIT"
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
from clue.common.regex import (
|
|
2
|
-
DOMAIN_ONLY_REGEX,
|
|
3
|
-
EMAIL_PATH_REGEX,
|
|
4
|
-
EMAIL_REGEX,
|
|
5
|
-
HBS_AGENT_ID_REGEX,
|
|
6
|
-
IPV4_ONLY_REGEX,
|
|
7
|
-
IPV6_ONLY_REGEX,
|
|
8
|
-
MD5_REGEX,
|
|
9
|
-
PORT_REGEX,
|
|
10
|
-
SHA1_REGEX,
|
|
11
|
-
SHA256_REGEX,
|
|
12
|
-
URI_ONLY,
|
|
13
|
-
UUID4_REGEX,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
SUPPORTED_TYPES = {
|
|
17
|
-
"ipv4": IPV4_ONLY_REGEX,
|
|
18
|
-
"ipv6": IPV6_ONLY_REGEX,
|
|
19
|
-
# We don't auto-detect ip types, as it's redundant with ipv4/v6. This is just a convenience/backwards compat thing
|
|
20
|
-
"ip": None,
|
|
21
|
-
"domain": DOMAIN_ONLY_REGEX,
|
|
22
|
-
"port": PORT_REGEX,
|
|
23
|
-
"url": URI_ONLY,
|
|
24
|
-
"userid": None,
|
|
25
|
-
"user_agent": None,
|
|
26
|
-
"email_address": EMAIL_REGEX,
|
|
27
|
-
"email_id": None,
|
|
28
|
-
"email_path": EMAIL_PATH_REGEX,
|
|
29
|
-
"md5": MD5_REGEX,
|
|
30
|
-
"sha1": SHA1_REGEX,
|
|
31
|
-
"sha256": SHA256_REGEX,
|
|
32
|
-
"hbs_oid": None,
|
|
33
|
-
"hbs_agent_id": HBS_AGENT_ID_REGEX,
|
|
34
|
-
"telemetry": None,
|
|
35
|
-
"howler_id": None,
|
|
36
|
-
"hostname": None,
|
|
37
|
-
"tenant-id": UUID4_REGEX,
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
CASE_INSENSITIVE_TYPES = ["ip", "domain", "port", "tenant-id", "hbs_oid", "hbs_agent_id"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|