clue-api 1.3.0.dev20__tar.gz → 1.3.0.dev28__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 (91) hide show
  1. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/PKG-INFO +1 -1
  2. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/lookup.py +4 -1
  3. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/constants/supported_types.py +1 -1
  4. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/selector.py +4 -4
  5. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/pyproject.toml +1 -1
  6. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/LICENSE +0 -0
  7. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/README.md +0 -0
  8. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/.gitignore +0 -0
  9. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/__init__.py +0 -0
  10. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/__init__.py +0 -0
  11. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/base.py +0 -0
  12. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/__init__.py +0 -0
  13. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/actions.py +0 -0
  14. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/auth.py +0 -0
  15. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/configs.py +0 -0
  16. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/fetchers.py +0 -0
  17. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/registration.py +0 -0
  18. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/api/v1/static.py +0 -0
  19. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/app.py +0 -0
  20. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/cache/__init__.py +0 -0
  21. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/__init__.py +0 -0
  22. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/classification.py +0 -0
  23. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/classification.yml +0 -0
  24. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/dict_utils.py +0 -0
  25. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/exceptions.py +0 -0
  26. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/forge.py +0 -0
  27. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/json_utils.py +0 -0
  28. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/list_utils.py +0 -0
  29. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/logging/__init__.py +0 -0
  30. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/logging/audit.py +0 -0
  31. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/logging/format.py +0 -0
  32. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/regex.py +0 -0
  33. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/str_utils.py +0 -0
  34. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/swagger.py +0 -0
  35. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/common/uid.py +0 -0
  36. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/config.py +0 -0
  37. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/constants/__init__.py +0 -0
  38. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/cronjobs/__init__.py +0 -0
  39. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/cronjobs/plugins.py +0 -0
  40. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/error.py +0 -0
  41. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/extensions/__init__.py +0 -0
  42. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/extensions/config.py +0 -0
  43. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/gunicorn_config.py +0 -0
  44. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/healthz.py +0 -0
  45. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/helper/discover.py +0 -0
  46. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/helper/headers.py +0 -0
  47. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/helper/oauth.py +0 -0
  48. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/__init__.py +0 -0
  49. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/actions.py +0 -0
  50. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/config.py +0 -0
  51. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/fetchers.py +0 -0
  52. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/graph.py +0 -0
  53. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/model_list.py +0 -0
  54. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/network.py +0 -0
  55. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/__init__.py +0 -0
  56. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/base.py +0 -0
  57. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/graph.py +0 -0
  58. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/image.py +0 -0
  59. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/status.py +0 -0
  60. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/results/validation.py +0 -0
  61. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/models/validators.py +0 -0
  62. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/patched.py +0 -0
  63. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/__init__.py +0 -0
  64. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/helpers/__init__.py +0 -0
  65. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/helpers/central_server.py +0 -0
  66. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/helpers/email_render.py +0 -0
  67. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/helpers/token.py +0 -0
  68. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/helpers/trino.py +0 -0
  69. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/models.py +0 -0
  70. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/plugin/utils.py +0 -0
  71. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/py.typed +0 -0
  72. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/__init__.py +0 -0
  73. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/__init__.py +0 -0
  74. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/cache.py +0 -0
  75. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/events.py +0 -0
  76. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/hash.py +0 -0
  77. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/queues/__init__.py +0 -0
  78. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/queues/comms.py +0 -0
  79. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/set.py +0 -0
  80. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/remote/datatypes/user_quota_tracker.py +0 -0
  81. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/security/__init__.py +0 -0
  82. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/security/obo.py +0 -0
  83. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/security/utils.py +0 -0
  84. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/action_service.py +0 -0
  85. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/auth_service.py +0 -0
  86. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/config_service.py +0 -0
  87. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/fetcher_service.py +0 -0
  88. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/jwt_service.py +0 -0
  89. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/lookup_service.py +0 -0
  90. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/clue/services/type_service.py +0 -0
  91. {clue_api-1.3.0.dev20 → clue_api-1.3.0.dev28}/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.dev20
3
+ Version: 1.3.0.dev28
4
4
  Summary: Clue distributed enrichment service
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -205,13 +205,16 @@ def enrich(type_name: str, value: str, **kwargs) -> dict[str, QueryResult]:
205
205
  user = kwargs["user"]
206
206
 
207
207
  # For backwards compatability, if eml is used it is replaced with email
208
- type_name = type_name.replace("eml", "email")
208
+ type_name = type_name.lower().replace("eml", "email")
209
209
 
210
210
  if type_name == "telemetry":
211
211
  try:
212
212
  json.loads(urllib.parse.unquote(value))
213
213
  except json.JSONDecodeError:
214
214
  return bad_request(err="If type is telemetry, value must be a valid JSON object.")
215
+ else:
216
+ # Normalize to lowercase all non-telemetry inputs
217
+ value = value.lower()
215
218
 
216
219
  # re-encode the type after being decoded going through flask/wsgi route
217
220
  value = urllib.parse.quote(value, safe="")
@@ -37,4 +37,4 @@ SUPPORTED_TYPES = {
37
37
  "tenant-id": UUID4_REGEX,
38
38
  }
39
39
 
40
- CASE_INSENSITIVE_TYPES = ["ip", "domain", "port", "tenant-id"]
40
+ CASE_INSENSITIVE_TYPES = ["ip", "domain", "port", "tenant-id", "hbs_oid", "hbs_agent_id"]
@@ -1,9 +1,10 @@
1
1
  # ruff: noqa: D101
2
2
  import ipaddress
3
3
  import json
4
+ from typing import Annotated
4
5
 
5
6
  from flask import request
6
- from pydantic import BaseModel, Field, model_validator
7
+ from pydantic import BaseModel, Field, StringConstraints, model_validator
7
8
  from typing_extensions import Self
8
9
 
9
10
  from clue.common.logging import get_logger
@@ -14,7 +15,7 @@ logger = get_logger(__file__)
14
15
 
15
16
 
16
17
  class Selector(BaseModel):
17
- type: str
18
+ type: Annotated[str, StringConstraints(to_lower=True, strip_whitespace=True)]
18
19
  value: str
19
20
  classification: str | None = Field(default=None)
20
21
  sources: list[str] | None = Field(default=None)
@@ -41,8 +42,7 @@ class Selector(BaseModel):
41
42
  json.loads(self.value)
42
43
  except json.JSONDecodeError as e:
43
44
  raise AssertionError("If type is telemetry, value must be a valid JSON object.") from e
44
-
45
- if self.type in CASE_INSENSITIVE_TYPES:
45
+ elif self.type in CASE_INSENSITIVE_TYPES:
46
46
  self.value = self.value.lower()
47
47
 
48
48
  if not self.classification:
@@ -146,7 +146,7 @@ log_cli_level = "WARN"
146
146
  [tool.poetry]
147
147
  package-mode = true
148
148
  name = "clue-api"
149
- version = "1.3.0.dev20"
149
+ version = "1.3.0.dev28"
150
150
  description = "Clue distributed enrichment service"
151
151
  authors = ["Canadian Centre for Cyber Security <contact@cyber.gc.ca>"]
152
152
  license = "MIT"
File without changes
File without changes