howler-api 2.13.0.dev329__py3-none-any.whl

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 (200) hide show
  1. howler/__init__.py +0 -0
  2. howler/actions/__init__.py +167 -0
  3. howler/actions/add_label.py +111 -0
  4. howler/actions/add_to_bundle.py +159 -0
  5. howler/actions/change_field.py +76 -0
  6. howler/actions/demote.py +160 -0
  7. howler/actions/example_plugin.py +104 -0
  8. howler/actions/prioritization.py +93 -0
  9. howler/actions/promote.py +147 -0
  10. howler/actions/remove_from_bundle.py +133 -0
  11. howler/actions/remove_label.py +111 -0
  12. howler/actions/transition.py +200 -0
  13. howler/api/__init__.py +249 -0
  14. howler/api/base.py +88 -0
  15. howler/api/socket.py +114 -0
  16. howler/api/v1/__init__.py +97 -0
  17. howler/api/v1/action.py +372 -0
  18. howler/api/v1/analytic.py +748 -0
  19. howler/api/v1/auth.py +382 -0
  20. howler/api/v1/borealis.py +101 -0
  21. howler/api/v1/configs.py +55 -0
  22. howler/api/v1/dossier.py +222 -0
  23. howler/api/v1/help.py +28 -0
  24. howler/api/v1/hit.py +1181 -0
  25. howler/api/v1/notebook.py +82 -0
  26. howler/api/v1/overview.py +191 -0
  27. howler/api/v1/search.py +715 -0
  28. howler/api/v1/template.py +206 -0
  29. howler/api/v1/tool.py +183 -0
  30. howler/api/v1/user.py +414 -0
  31. howler/api/v1/utils/__init__.py +0 -0
  32. howler/api/v1/utils/etag.py +84 -0
  33. howler/api/v1/view.py +288 -0
  34. howler/app.py +235 -0
  35. howler/common/README.md +144 -0
  36. howler/common/__init__.py +0 -0
  37. howler/common/classification.py +979 -0
  38. howler/common/classification.yml +107 -0
  39. howler/common/exceptions.py +167 -0
  40. howler/common/hexdump.py +48 -0
  41. howler/common/iprange.py +171 -0
  42. howler/common/loader.py +154 -0
  43. howler/common/logging/__init__.py +241 -0
  44. howler/common/logging/audit.py +138 -0
  45. howler/common/logging/format.py +38 -0
  46. howler/common/net.py +79 -0
  47. howler/common/net_static.py +1494 -0
  48. howler/common/random_user.py +316 -0
  49. howler/common/swagger.py +117 -0
  50. howler/config.py +64 -0
  51. howler/cronjobs/__init__.py +29 -0
  52. howler/cronjobs/retention.py +61 -0
  53. howler/cronjobs/rules.py +274 -0
  54. howler/cronjobs/view_cleanup.py +88 -0
  55. howler/datastore/README.md +112 -0
  56. howler/datastore/__init__.py +0 -0
  57. howler/datastore/bulk.py +72 -0
  58. howler/datastore/collection.py +2327 -0
  59. howler/datastore/constants.py +117 -0
  60. howler/datastore/exceptions.py +41 -0
  61. howler/datastore/howler_store.py +105 -0
  62. howler/datastore/migrations/fix_process.py +41 -0
  63. howler/datastore/operations.py +130 -0
  64. howler/datastore/schemas.py +90 -0
  65. howler/datastore/store.py +231 -0
  66. howler/datastore/support/__init__.py +0 -0
  67. howler/datastore/support/build.py +214 -0
  68. howler/datastore/support/schemas.py +90 -0
  69. howler/datastore/types.py +22 -0
  70. howler/error.py +91 -0
  71. howler/external/__init__.py +0 -0
  72. howler/external/generate_mitre.py +96 -0
  73. howler/external/generate_sigma_rules.py +31 -0
  74. howler/external/generate_tlds.py +47 -0
  75. howler/external/reindex_data.py +46 -0
  76. howler/external/wipe_databases.py +58 -0
  77. howler/gunicorn_config.py +25 -0
  78. howler/healthz.py +47 -0
  79. howler/helper/__init__.py +0 -0
  80. howler/helper/azure.py +50 -0
  81. howler/helper/discover.py +59 -0
  82. howler/helper/hit.py +236 -0
  83. howler/helper/oauth.py +247 -0
  84. howler/helper/search.py +92 -0
  85. howler/helper/workflow.py +110 -0
  86. howler/helper/ws.py +378 -0
  87. howler/odm/README.md +102 -0
  88. howler/odm/__init__.py +1 -0
  89. howler/odm/base.py +1504 -0
  90. howler/odm/charter.txt +146 -0
  91. howler/odm/helper.py +416 -0
  92. howler/odm/howler_enum.py +25 -0
  93. howler/odm/models/__init__.py +0 -0
  94. howler/odm/models/action.py +33 -0
  95. howler/odm/models/analytic.py +90 -0
  96. howler/odm/models/assemblyline.py +48 -0
  97. howler/odm/models/aws.py +23 -0
  98. howler/odm/models/azure.py +16 -0
  99. howler/odm/models/cbs.py +44 -0
  100. howler/odm/models/config.py +558 -0
  101. howler/odm/models/dossier.py +33 -0
  102. howler/odm/models/ecs/__init__.py +0 -0
  103. howler/odm/models/ecs/agent.py +17 -0
  104. howler/odm/models/ecs/autonomous_system.py +16 -0
  105. howler/odm/models/ecs/client.py +149 -0
  106. howler/odm/models/ecs/cloud.py +141 -0
  107. howler/odm/models/ecs/code_signature.py +27 -0
  108. howler/odm/models/ecs/container.py +32 -0
  109. howler/odm/models/ecs/dns.py +62 -0
  110. howler/odm/models/ecs/egress.py +10 -0
  111. howler/odm/models/ecs/elf.py +74 -0
  112. howler/odm/models/ecs/email.py +122 -0
  113. howler/odm/models/ecs/error.py +14 -0
  114. howler/odm/models/ecs/event.py +140 -0
  115. howler/odm/models/ecs/faas.py +24 -0
  116. howler/odm/models/ecs/file.py +84 -0
  117. howler/odm/models/ecs/geo.py +30 -0
  118. howler/odm/models/ecs/group.py +18 -0
  119. howler/odm/models/ecs/hash.py +16 -0
  120. howler/odm/models/ecs/host.py +17 -0
  121. howler/odm/models/ecs/http.py +37 -0
  122. howler/odm/models/ecs/ingress.py +12 -0
  123. howler/odm/models/ecs/interface.py +21 -0
  124. howler/odm/models/ecs/network.py +30 -0
  125. howler/odm/models/ecs/observer.py +45 -0
  126. howler/odm/models/ecs/organization.py +12 -0
  127. howler/odm/models/ecs/os.py +21 -0
  128. howler/odm/models/ecs/pe.py +17 -0
  129. howler/odm/models/ecs/process.py +216 -0
  130. howler/odm/models/ecs/registry.py +26 -0
  131. howler/odm/models/ecs/related.py +45 -0
  132. howler/odm/models/ecs/rule.py +51 -0
  133. howler/odm/models/ecs/server.py +24 -0
  134. howler/odm/models/ecs/threat.py +247 -0
  135. howler/odm/models/ecs/tls.py +58 -0
  136. howler/odm/models/ecs/url.py +51 -0
  137. howler/odm/models/ecs/user.py +57 -0
  138. howler/odm/models/ecs/user_agent.py +20 -0
  139. howler/odm/models/ecs/vulnerability.py +41 -0
  140. howler/odm/models/gcp.py +16 -0
  141. howler/odm/models/hit.py +356 -0
  142. howler/odm/models/howler_data.py +328 -0
  143. howler/odm/models/lead.py +33 -0
  144. howler/odm/models/localized_label.py +13 -0
  145. howler/odm/models/overview.py +16 -0
  146. howler/odm/models/pivot.py +40 -0
  147. howler/odm/models/template.py +24 -0
  148. howler/odm/models/user.py +83 -0
  149. howler/odm/models/view.py +34 -0
  150. howler/odm/random_data.py +888 -0
  151. howler/odm/randomizer.py +606 -0
  152. howler/patched.py +5 -0
  153. howler/plugins/__init__.py +25 -0
  154. howler/plugins/config.py +123 -0
  155. howler/remote/__init__.py +0 -0
  156. howler/remote/datatypes/README.md +355 -0
  157. howler/remote/datatypes/__init__.py +98 -0
  158. howler/remote/datatypes/counters.py +63 -0
  159. howler/remote/datatypes/events.py +66 -0
  160. howler/remote/datatypes/hash.py +206 -0
  161. howler/remote/datatypes/lock.py +42 -0
  162. howler/remote/datatypes/queues/__init__.py +0 -0
  163. howler/remote/datatypes/queues/comms.py +59 -0
  164. howler/remote/datatypes/queues/multi.py +32 -0
  165. howler/remote/datatypes/queues/named.py +93 -0
  166. howler/remote/datatypes/queues/priority.py +215 -0
  167. howler/remote/datatypes/set.py +118 -0
  168. howler/remote/datatypes/user_quota_tracker.py +54 -0
  169. howler/security/__init__.py +253 -0
  170. howler/security/socket.py +108 -0
  171. howler/security/utils.py +185 -0
  172. howler/services/__init__.py +0 -0
  173. howler/services/action_service.py +111 -0
  174. howler/services/analytic_service.py +128 -0
  175. howler/services/auth_service.py +323 -0
  176. howler/services/config_service.py +128 -0
  177. howler/services/dossier_service.py +252 -0
  178. howler/services/event_service.py +93 -0
  179. howler/services/hit_service.py +893 -0
  180. howler/services/jwt_service.py +158 -0
  181. howler/services/lucene_service.py +286 -0
  182. howler/services/notebook_service.py +119 -0
  183. howler/services/overview_service.py +44 -0
  184. howler/services/template_service.py +45 -0
  185. howler/services/user_service.py +330 -0
  186. howler/utils/__init__.py +0 -0
  187. howler/utils/annotations.py +28 -0
  188. howler/utils/chunk.py +38 -0
  189. howler/utils/dict_utils.py +200 -0
  190. howler/utils/isotime.py +17 -0
  191. howler/utils/list_utils.py +11 -0
  192. howler/utils/lucene.py +77 -0
  193. howler/utils/path.py +27 -0
  194. howler/utils/socket_utils.py +61 -0
  195. howler/utils/str_utils.py +256 -0
  196. howler/utils/uid.py +47 -0
  197. howler_api-2.13.0.dev329.dist-info/METADATA +71 -0
  198. howler_api-2.13.0.dev329.dist-info/RECORD +200 -0
  199. howler_api-2.13.0.dev329.dist-info/WHEEL +4 -0
  200. howler_api-2.13.0.dev329.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,82 @@
1
+ from flask import request
2
+
3
+ from howler.api import bad_request, internal_error, make_subapi_blueprint, ok
4
+ from howler.common.swagger import generate_swagger_docs
5
+ from howler.security import api_login
6
+ from howler.services import notebook_service
7
+
8
+ SUB_API = "notebook"
9
+ notebook_api = make_subapi_blueprint(SUB_API, api_version=1)
10
+ notebook_api._doc = "Get notebook information"
11
+
12
+
13
+ @generate_swagger_docs()
14
+ @notebook_api.route("/environments", methods=["GET"])
15
+ @api_login(required_priv=["R"], required_method=["oauth"])
16
+ def get_user_environments(**kwargs):
17
+ """Get user's jupyter hub environments
18
+
19
+ Variables:
20
+ None
21
+
22
+ Arguments:
23
+
24
+ Result Example:
25
+ {
26
+ [
27
+ Env1,
28
+ Env2
29
+ ]
30
+ }
31
+ """
32
+ try:
33
+ env = notebook_service.get_user_envs()
34
+
35
+ return ok({"envs": env})
36
+ except Exception as error:
37
+ return internal_error(err=f"Failed to retrieve user's environments from nbgallery. {error}")
38
+
39
+
40
+ @generate_swagger_docs()
41
+ @notebook_api.route("/notebook", methods=["POST"])
42
+ @api_login(required_priv=["R"], required_method=["oauth"])
43
+ def get_notebook(**kwargs):
44
+ """Return patched notebook
45
+
46
+ Variables:
47
+ None
48
+
49
+ Arguments:
50
+
51
+
52
+ Data Block:
53
+ {
54
+ link: "https://nbgallery...",
55
+ analytic: Analytic object,
56
+ hit: Hit object
57
+ }
58
+
59
+ Result Example:
60
+ {
61
+ [
62
+ Env1,
63
+ Env2
64
+ ]
65
+ }
66
+ """
67
+ data = request.json
68
+ if not isinstance(data, dict):
69
+ return bad_request(err="Invalid data format")
70
+
71
+ if "link" not in data:
72
+ return bad_request(err="You must provide a link")
73
+
74
+ if "analytic" not in data:
75
+ return bad_request(err="You must provide an analytic")
76
+
77
+ try:
78
+ json_content, name = notebook_service.get_nb_information(data["link"], data["analytic"], data.get("hit", {}))
79
+ except Exception as error:
80
+ return internal_error(err=f"Failed to retrieve notebook from nbgallery. {error}")
81
+
82
+ return ok({"nb_content": json_content, "name": name})
@@ -0,0 +1,191 @@
1
+ from flask import request
2
+
3
+ from howler.api import (
4
+ bad_request,
5
+ conflict,
6
+ created,
7
+ forbidden,
8
+ make_subapi_blueprint,
9
+ no_content,
10
+ not_found,
11
+ ok,
12
+ )
13
+ from howler.common.exceptions import HowlerException
14
+ from howler.common.loader import datastore
15
+ from howler.common.logging import get_logger
16
+ from howler.common.swagger import generate_swagger_docs
17
+ from howler.odm.models.overview import Overview
18
+ from howler.odm.models.user import User
19
+ from howler.security import api_login
20
+ from howler.utils.str_utils import sanitize_lucene_query
21
+
22
+ SUB_API = "overview"
23
+ overview_api = make_subapi_blueprint(SUB_API, api_version=1)
24
+ overview_api._doc = "Manage the different overviews created for viewing hits"
25
+
26
+ logger = get_logger(__file__)
27
+
28
+
29
+ @generate_swagger_docs()
30
+ @overview_api.route("/", methods=["GET"])
31
+ @api_login(required_priv=["R"])
32
+ def get_overviews(**kwargs):
33
+ """Get a list of overviews the user can use to render hits
34
+
35
+ Variables:
36
+ None
37
+
38
+ Optional Arguments:
39
+ None
40
+
41
+ Result Example:
42
+ [
43
+ ...overviews # A list of overviews the user can use
44
+ ]
45
+ """
46
+ try:
47
+ return ok(
48
+ datastore().overview.search(
49
+ "overview_id:*",
50
+ as_obj=False,
51
+ rows=10000,
52
+ )["items"]
53
+ )
54
+ except ValueError as e:
55
+ return bad_request(err=str(e))
56
+
57
+
58
+ @generate_swagger_docs()
59
+ @overview_api.route("/", methods=["POST"])
60
+ @api_login(required_priv=["R", "W"])
61
+ def create_overview(**kwargs):
62
+ """Create a new overview
63
+
64
+ Variables:
65
+ None
66
+
67
+ Optional Arguments:
68
+ None
69
+
70
+ Data Block:
71
+ {
72
+ "analytic": "analytic name" # The analytic this overview applies to
73
+ "detection": "detection name" # The detection this overview applies to
74
+ "content": "# Hello, World!\n\nExample Text" # The content to show when this overview matches a hit
75
+ }
76
+
77
+ Result Example:
78
+ {
79
+ ...overview # The new overview data
80
+ }
81
+ """
82
+ overview_data = request.json
83
+ if not isinstance(overview_data, dict):
84
+ return bad_request(err="Invalid data format")
85
+
86
+ if "content" not in overview_data:
87
+ return bad_request(err="You must specify content when creating an overview!")
88
+
89
+ storage = datastore()
90
+
91
+ try:
92
+ overview = Overview(overview_data)
93
+
94
+ overview.owner = kwargs["user"]["uname"]
95
+
96
+ query_str = f"analytic:{sanitize_lucene_query(overview.analytic)}"
97
+
98
+ if overview.detection:
99
+ query_str += f" AND detection:{overview.detection}"
100
+ else:
101
+ query_str += " AND -_exists_:detection"
102
+
103
+ if storage.overview.search(query_str)["total"] > 0:
104
+ return conflict(err="An overview covering this case already exists.")
105
+
106
+ storage.overview.save(overview.overview_id, overview)
107
+ return created(overview)
108
+ except HowlerException as e:
109
+ return bad_request(err=str(e))
110
+
111
+
112
+ @generate_swagger_docs()
113
+ @overview_api.route("/<id>", methods=["DELETE"])
114
+ @api_login(required_priv=["W"])
115
+ def delete_overview(id: str, user: User, **kwargs):
116
+ """Delete an overview
117
+
118
+ Variables:
119
+ id => The id of the overview to delete
120
+
121
+ Optional Arguments:
122
+ None
123
+
124
+ Data Block:
125
+ None
126
+
127
+ Result Example:
128
+ {
129
+ "success": true # Did the deletion succeed?
130
+ }
131
+ """
132
+ storage = datastore()
133
+
134
+ if not storage.overview.exists(id):
135
+ return not_found(err="This overview does not exist")
136
+
137
+ existing_overview: Overview = storage.overview.get_if_exists(id)
138
+
139
+ if existing_overview.owner != user.uname and "admin" not in user.type:
140
+ return forbidden(err="You cannot delete an overview that is not owned by you.")
141
+
142
+ result = storage.overview.delete(id)
143
+ if result:
144
+ return no_content()
145
+ else:
146
+ return not_found()
147
+
148
+
149
+ @generate_swagger_docs()
150
+ @overview_api.route("/<id>", methods=["PUT"])
151
+ @api_login(required_priv=["R", "W"])
152
+ def update_overview_content(id: str, user: User, **kwargs):
153
+ """Update an overview's content
154
+
155
+ Variables:
156
+ id => The id of the overview to modify
157
+
158
+ Optional Arguments:
159
+ None
160
+
161
+ Data Block:
162
+ {
163
+ "content: "# New Markdown\n\nExample
164
+ }
165
+
166
+ Result Example:
167
+ {
168
+ ...overview # The updated overview data
169
+ }
170
+ """
171
+ storage = datastore()
172
+
173
+ if not storage.overview.exists(id):
174
+ return not_found(err="This overview does not exist")
175
+
176
+ data = request.json
177
+ if not data or not isinstance(data.get("content", None), str):
178
+ return bad_request(err="New overview content must be a string.")
179
+
180
+ content = data["content"]
181
+
182
+ existing_overview: Overview = storage.overview.get_if_exists(id)
183
+
184
+ existing_overview.content = content
185
+
186
+ storage.overview.save(existing_overview.overview_id, existing_overview)
187
+
188
+ try:
189
+ return ok(storage.overview.get_if_exists(existing_overview.overview_id, as_obj=False))
190
+ except HowlerException as e:
191
+ return bad_request(err=str(e))