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.
Files changed (93) hide show
  1. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/PKG-INFO +1 -1
  2. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/app.py +24 -10
  3. clue_api-1.3.0.dev92/clue/constants/supported_types.py +71 -0
  4. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/extensions/config.py +1 -0
  5. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/pyproject.toml +1 -1
  6. clue_api-1.3.0.dev87/clue/constants/supported_types.py +0 -40
  7. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/LICENSE +0 -0
  8. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/README.md +0 -0
  9. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/.gitignore +0 -0
  10. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/__init__.py +0 -0
  11. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/__init__.py +0 -0
  12. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/base.py +0 -0
  13. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/__init__.py +0 -0
  14. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/actions.py +0 -0
  15. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/auth.py +0 -0
  16. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/configs.py +0 -0
  17. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/fetchers.py +0 -0
  18. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/lookup.py +0 -0
  19. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/registration.py +0 -0
  20. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/api/v1/static.py +0 -0
  21. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cache/__init__.py +0 -0
  22. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/__init__.py +0 -0
  23. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/classification.py +0 -0
  24. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/classification.yml +0 -0
  25. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/dict_utils.py +0 -0
  26. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/exceptions.py +0 -0
  27. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/forge.py +0 -0
  28. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/json_utils.py +0 -0
  29. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/list_utils.py +0 -0
  30. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/__init__.py +0 -0
  31. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/audit.py +0 -0
  32. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/logging/format.py +0 -0
  33. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/regex.py +0 -0
  34. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/str_utils.py +0 -0
  35. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/swagger.py +0 -0
  36. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/common/uid.py +0 -0
  37. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/config.py +0 -0
  38. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/constants/__init__.py +0 -0
  39. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/constants/env.py +0 -0
  40. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cronjobs/__init__.py +0 -0
  41. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/cronjobs/plugins.py +0 -0
  42. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/error.py +0 -0
  43. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/extensions/__init__.py +0 -0
  44. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/gunicorn_config.py +0 -0
  45. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/healthz.py +0 -0
  46. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/discover.py +0 -0
  47. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/headers.py +0 -0
  48. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/helper/oauth.py +0 -0
  49. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/__init__.py +0 -0
  50. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/actions.py +0 -0
  51. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/config.py +0 -0
  52. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/fetchers.py +0 -0
  53. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/graph.py +0 -0
  54. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/model_list.py +0 -0
  55. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/network.py +0 -0
  56. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/__init__.py +0 -0
  57. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/base.py +0 -0
  58. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/graph.py +0 -0
  59. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/image.py +0 -0
  60. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/status.py +0 -0
  61. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/results/validation.py +0 -0
  62. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/selector.py +0 -0
  63. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/models/validators.py +0 -0
  64. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/patched.py +0 -0
  65. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/__init__.py +0 -0
  66. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/__init__.py +0 -0
  67. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/central_server.py +0 -0
  68. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/email_render.py +0 -0
  69. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/token.py +0 -0
  70. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/helpers/trino.py +0 -0
  71. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/models.py +0 -0
  72. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/plugin/utils.py +0 -0
  73. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/py.typed +0 -0
  74. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/__init__.py +0 -0
  75. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/__init__.py +0 -0
  76. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/cache.py +0 -0
  77. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/events.py +0 -0
  78. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/hash.py +0 -0
  79. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/queues/__init__.py +0 -0
  80. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/queues/comms.py +0 -0
  81. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/set.py +0 -0
  82. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/remote/datatypes/user_quota_tracker.py +0 -0
  83. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/__init__.py +0 -0
  84. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/obo.py +0 -0
  85. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/security/utils.py +0 -0
  86. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/action_service.py +0 -0
  87. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/auth_service.py +0 -0
  88. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/config_service.py +0 -0
  89. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/fetcher_service.py +0 -0
  90. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/jwt_service.py +0 -0
  91. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/lookup_service.py +0 -0
  92. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/type_service.py +0 -0
  93. {clue_api-1.3.0.dev87 → clue_api-1.3.0.dev92}/clue/services/user_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clue-api
3
- Version: 1.3.0.dev87
3
+ Version: 1.3.0.dev92
4
4
  Summary: Clue distributed enrichment service
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -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 plugin directory for howler to the python part
14
- PLUGIN_PATH = Path(os.environ.get("CLUE_PLUGIN_DIRECTORY", "/etc/clue/plugins"))
15
- sys.path.insert(0, str(PLUGIN_PATH))
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 PLUGIN_PATH.exists():
20
- for _plugin in PLUGIN_PATH.iterdir():
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(_plugin)) / f"../.venv/lib/python3.{sys.version_info.minor}/site-packages")
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 plugins for additional routes")
125
- for plugin in get_extensions():
126
- if not plugin.modules.routes:
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], plugin.modules.routes):
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"]
@@ -21,6 +21,7 @@ logger.addHandler(console)
21
21
  class Modules(BaseModel):
22
22
  "A list of components exposed for use in Clue by this plugin."
23
23
 
24
+ init: ImportString | None = None
24
25
  routes: list[ImportString] = []
25
26
  obo_module: ImportString | None = None
26
27
 
@@ -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.dev87"
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