howler-api 2.13.0.dev341__tar.gz → 2.13.0.dev343__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.

Potentially problematic release.


This version of howler-api might be problematic. Click here for more details.

Files changed (199) hide show
  1. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/PKG-INFO +1 -1
  2. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/__init__.py +1 -1
  3. howler_api-2.13.0.dev341/howler/api/v1/borealis.py → howler_api-2.13.0.dev343/howler/api/v1/clue.py +24 -26
  4. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/search.py +74 -1
  5. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/app.py +4 -4
  6. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/helper.py +5 -5
  7. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/config.py +10 -10
  8. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/pivot.py +1 -1
  9. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/security/__init__.py +2 -2
  10. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/config_service.py +2 -2
  11. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/pyproject.toml +1 -1
  12. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/README.md +0 -0
  13. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/__init__.py +0 -0
  14. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/__init__.py +0 -0
  15. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/add_label.py +0 -0
  16. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/add_to_bundle.py +0 -0
  17. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/change_field.py +0 -0
  18. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/demote.py +0 -0
  19. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/example_plugin.py +0 -0
  20. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/prioritization.py +0 -0
  21. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/promote.py +0 -0
  22. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/remove_from_bundle.py +0 -0
  23. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/remove_label.py +0 -0
  24. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/actions/transition.py +0 -0
  25. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/base.py +0 -0
  26. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/socket.py +0 -0
  27. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/__init__.py +0 -0
  28. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/action.py +0 -0
  29. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/analytic.py +0 -0
  30. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/auth.py +0 -0
  31. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/configs.py +0 -0
  32. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/dossier.py +0 -0
  33. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/help.py +0 -0
  34. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/hit.py +0 -0
  35. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/notebook.py +0 -0
  36. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/overview.py +0 -0
  37. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/template.py +0 -0
  38. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/tool.py +0 -0
  39. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/user.py +0 -0
  40. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/utils/__init__.py +0 -0
  41. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/utils/etag.py +0 -0
  42. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/api/v1/view.py +0 -0
  43. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/README.md +0 -0
  44. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/__init__.py +0 -0
  45. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/classification.py +0 -0
  46. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/classification.yml +0 -0
  47. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/exceptions.py +0 -0
  48. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/hexdump.py +0 -0
  49. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/iprange.py +0 -0
  50. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/loader.py +0 -0
  51. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/logging/__init__.py +0 -0
  52. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/logging/audit.py +0 -0
  53. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/logging/format.py +0 -0
  54. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/net.py +0 -0
  55. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/net_static.py +0 -0
  56. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/random_user.py +0 -0
  57. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/common/swagger.py +0 -0
  58. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/config.py +0 -0
  59. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/cronjobs/__init__.py +0 -0
  60. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/cronjobs/retention.py +0 -0
  61. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/cronjobs/rules.py +0 -0
  62. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/cronjobs/view_cleanup.py +0 -0
  63. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/README.md +0 -0
  64. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/__init__.py +0 -0
  65. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/bulk.py +0 -0
  66. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/collection.py +0 -0
  67. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/constants.py +0 -0
  68. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/exceptions.py +0 -0
  69. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/howler_store.py +0 -0
  70. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/migrations/fix_process.py +0 -0
  71. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/operations.py +0 -0
  72. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/schemas.py +0 -0
  73. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/store.py +0 -0
  74. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/support/__init__.py +0 -0
  75. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/support/build.py +0 -0
  76. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/support/schemas.py +0 -0
  77. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/datastore/types.py +0 -0
  78. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/error.py +0 -0
  79. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/__init__.py +0 -0
  80. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/generate_mitre.py +0 -0
  81. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/generate_sigma_rules.py +0 -0
  82. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/generate_tlds.py +0 -0
  83. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/reindex_data.py +0 -0
  84. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/external/wipe_databases.py +0 -0
  85. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/gunicorn_config.py +0 -0
  86. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/healthz.py +0 -0
  87. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/__init__.py +0 -0
  88. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/azure.py +0 -0
  89. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/discover.py +0 -0
  90. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/hit.py +0 -0
  91. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/oauth.py +0 -0
  92. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/search.py +0 -0
  93. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/workflow.py +0 -0
  94. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/helper/ws.py +0 -0
  95. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/README.md +0 -0
  96. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/__init__.py +0 -0
  97. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/base.py +0 -0
  98. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/charter.txt +0 -0
  99. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/howler_enum.py +0 -0
  100. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/__init__.py +0 -0
  101. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/action.py +0 -0
  102. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/analytic.py +0 -0
  103. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/assemblyline.py +0 -0
  104. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/aws.py +0 -0
  105. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/azure.py +0 -0
  106. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/cbs.py +0 -0
  107. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/dossier.py +0 -0
  108. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/__init__.py +0 -0
  109. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/agent.py +0 -0
  110. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/autonomous_system.py +0 -0
  111. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/client.py +0 -0
  112. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/cloud.py +0 -0
  113. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/code_signature.py +0 -0
  114. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/container.py +0 -0
  115. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/dns.py +0 -0
  116. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/egress.py +0 -0
  117. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/elf.py +0 -0
  118. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/email.py +0 -0
  119. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/error.py +0 -0
  120. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/event.py +0 -0
  121. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/faas.py +0 -0
  122. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/file.py +0 -0
  123. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/geo.py +0 -0
  124. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/group.py +0 -0
  125. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/hash.py +0 -0
  126. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/host.py +0 -0
  127. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/http.py +0 -0
  128. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/ingress.py +0 -0
  129. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/interface.py +0 -0
  130. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/network.py +0 -0
  131. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/observer.py +0 -0
  132. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/organization.py +0 -0
  133. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/os.py +0 -0
  134. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/pe.py +0 -0
  135. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/process.py +0 -0
  136. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/registry.py +0 -0
  137. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/related.py +0 -0
  138. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/rule.py +0 -0
  139. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/server.py +0 -0
  140. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/threat.py +0 -0
  141. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/tls.py +0 -0
  142. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/url.py +0 -0
  143. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/user.py +0 -0
  144. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/user_agent.py +0 -0
  145. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/ecs/vulnerability.py +0 -0
  146. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/gcp.py +0 -0
  147. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/hit.py +0 -0
  148. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/howler_data.py +0 -0
  149. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/lead.py +0 -0
  150. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/localized_label.py +0 -0
  151. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/overview.py +0 -0
  152. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/template.py +0 -0
  153. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/user.py +0 -0
  154. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/models/view.py +0 -0
  155. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/random_data.py +0 -0
  156. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/odm/randomizer.py +0 -0
  157. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/patched.py +0 -0
  158. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/plugins/__init__.py +0 -0
  159. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/plugins/config.py +0 -0
  160. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/__init__.py +0 -0
  161. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/README.md +0 -0
  162. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/__init__.py +0 -0
  163. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/counters.py +0 -0
  164. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/events.py +0 -0
  165. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/hash.py +0 -0
  166. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/lock.py +0 -0
  167. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/queues/__init__.py +0 -0
  168. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/queues/comms.py +0 -0
  169. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/queues/multi.py +0 -0
  170. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/queues/named.py +0 -0
  171. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/queues/priority.py +0 -0
  172. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/set.py +0 -0
  173. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  174. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/security/socket.py +0 -0
  175. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/security/utils.py +0 -0
  176. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/__init__.py +0 -0
  177. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/action_service.py +0 -0
  178. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/analytic_service.py +0 -0
  179. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/auth_service.py +0 -0
  180. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/dossier_service.py +0 -0
  181. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/event_service.py +0 -0
  182. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/hit_service.py +0 -0
  183. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/jwt_service.py +0 -0
  184. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/lucene_service.py +0 -0
  185. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/notebook_service.py +0 -0
  186. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/overview_service.py +0 -0
  187. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/template_service.py +0 -0
  188. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/services/user_service.py +0 -0
  189. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/__init__.py +0 -0
  190. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/annotations.py +0 -0
  191. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/chunk.py +0 -0
  192. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/dict_utils.py +0 -0
  193. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/isotime.py +0 -0
  194. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/list_utils.py +0 -0
  195. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/lucene.py +0 -0
  196. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/path.py +0 -0
  197. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/socket_utils.py +0 -0
  198. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/str_utils.py +0 -0
  199. {howler_api-2.13.0.dev341 → howler_api-2.13.0.dev343}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 2.13.0.dev341
3
+ Version: 2.13.0.dev343
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -32,7 +32,7 @@ def _make_api_response(
32
32
  ) -> Response:
33
33
  quota_user = flsk_session.pop("quota_user", None)
34
34
  quota_set = flsk_session.pop("quota_set", False)
35
- if quota_user and quota_set and not request.path.startswith("/api/v1/borealis"):
35
+ if quota_user and quota_set and not request.path.startswith("/api/v1/clue"):
36
36
  QUOTA_TRACKER.end(quota_user)
37
37
 
38
38
  if type(err) is Exception: # pragma: no cover
@@ -14,9 +14,9 @@ from howler.config import cache, config
14
14
  from howler.plugins import get_plugins
15
15
  from howler.security import api_login
16
16
 
17
- SUB_API = "borealis"
18
- borealis_api = make_subapi_blueprint(SUB_API, api_version=1)
19
- borealis_api._doc = "Proxy enrichment requests to borealis"
17
+ SUB_API = "clue"
18
+ clue_api = make_subapi_blueprint(SUB_API, api_version=1)
19
+ clue_api._doc = "Proxy enrichment requests to clue"
20
20
 
21
21
  logger = get_logger(__file__)
22
22
 
@@ -28,27 +28,27 @@ def skip_cache(*args):
28
28
 
29
29
  @cache.memoize(15 * 60, unless=skip_cache)
30
30
  def get_token(access_token: str) -> str:
31
- """Get a borealis token based on the current howler token"""
32
- get_borealis_token: Optional[Callable[[str], str]] = None
31
+ """Get a clue token based on the current howler token"""
32
+ get_clue_token: Optional[Callable[[str], str]] = None
33
33
 
34
34
  for plugin in get_plugins():
35
- if get_borealis_token := plugin.modules.token_functions.get("borealis", None):
35
+ if get_clue_token := plugin.modules.token_functions.get("clue", None):
36
36
  break
37
37
 
38
- if get_borealis_token:
39
- borealis_access_token = get_borealis_token(access_token)
38
+ if get_clue_token:
39
+ clue_access_token = get_clue_token(access_token)
40
40
  else:
41
- logger.info("No custom borealis token logic provided, continuing with howler credentials")
42
- borealis_access_token = access_token
41
+ logger.info("No custom clue token logic provided, continuing with howler credentials")
42
+ clue_access_token = access_token
43
43
 
44
- return borealis_access_token
44
+ return clue_access_token
45
45
 
46
46
 
47
47
  @generate_swagger_docs()
48
- @borealis_api.route("/<path:path>", methods=["GET", "POST"])
48
+ @clue_api.route("/<path:path>", methods=["GET", "POST"])
49
49
  @api_login(required_priv=["R"], required_method=["oauth"])
50
- def proxy_to_borealis(path, **kwargs):
51
- """Proxy enrichment requests to Borealis
50
+ def proxy_to_clue(path, **kwargs):
51
+ """Proxy enrichment requests to Clue
52
52
 
53
53
  Variables:
54
54
  None
@@ -60,11 +60,9 @@ def proxy_to_borealis(path, **kwargs):
60
60
  Any
61
61
 
62
62
  Result Example:
63
- Borealis Responses
63
+ Clue Responses
64
64
  """
65
- logger.info(
66
- "Proxying borealis request to path %s/%s?%s", config.core.borealis.url, path, request.query_string.decode()
67
- )
65
+ logger.info("Proxying clue request to path %s/%s?%s", config.core.clue.url, path, request.query_string.decode())
68
66
 
69
67
  auth_data: Optional[str] = request.headers.get("Authorization", None, type=str)
70
68
 
@@ -73,29 +71,29 @@ def proxy_to_borealis(path, **kwargs):
73
71
 
74
72
  auth_token = auth_data.split(" ")[1]
75
73
 
76
- borealis_token = get_token(auth_token)
74
+ clue_token = get_token(auth_token)
77
75
 
78
76
  start = time.perf_counter()
79
- with elasticapm.capture_span("borealis", span_type="http"):
77
+ with elasticapm.capture_span("clue", span_type="http"):
80
78
  if request.method.lower() == "get":
81
79
  response = requests.get(
82
- f"{config.core.borealis.url}/{path}",
83
- headers={"Authorization": f"Bearer {borealis_token}", "Accept": "application/json"},
80
+ f"{config.core.clue.url}/{path}",
81
+ headers={"Authorization": f"Bearer {clue_token}", "Accept": "application/json"},
84
82
  params=request.args.to_dict(),
85
83
  timeout=5 * 60,
86
84
  )
87
85
  else:
88
86
  response = requests.post(
89
- f"{config.core.borealis.url}/{path}",
87
+ f"{config.core.clue.url}/{path}",
90
88
  json=request.json,
91
- headers={"Authorization": f"Bearer {borealis_token}", "Accept": "application/json"},
89
+ headers={"Authorization": f"Bearer {clue_token}", "Accept": "application/json"},
92
90
  params=request.args.to_dict(),
93
91
  timeout=5 * 60,
94
92
  )
95
93
 
96
- logger.debug(f"Request to borealis completed in {round(time.perf_counter() - start)}ms")
94
+ logger.debug(f"Request to clue completed in {round(time.perf_counter() - start)}ms")
97
95
 
98
96
  if not response.ok:
99
- return bad_gateway(response.json(), err="Something went wrong when connecting to borealis")
97
+ return bad_gateway(response.json(), err="Something went wrong when connecting to clue")
100
98
 
101
99
  return ok(response.json()["api_response"])
@@ -1,6 +1,9 @@
1
+ import re
2
+ from copy import deepcopy
1
3
  from typing import Any, Union
2
4
 
3
5
  from elasticsearch import BadRequestError
6
+ from elasticsearch._sync.client.indices import IndicesClient
4
7
  from flask import request
5
8
  from sigma.backends.elasticsearch import LuceneBackend
6
9
  from sigma.rule import SigmaRule
@@ -14,7 +17,7 @@ from howler.common.swagger import generate_swagger_docs
14
17
  from howler.datastore.exceptions import SearchException
15
18
  from howler.helper.search import get_collection, get_default_sort, has_access_control, list_all_fields
16
19
  from howler.security import api_login
17
- from howler.services import hit_service
20
+ from howler.services import hit_service, lucene_service
18
21
 
19
22
  SUB_API = "search"
20
23
  search_api = make_subapi_blueprint(SUB_API, api_version=1)
@@ -146,6 +149,76 @@ def search(index, **kwargs):
146
149
  return bad_request(err=f"SearchException: {e}")
147
150
 
148
151
 
152
+ @generate_swagger_docs()
153
+ @search_api.route("/<index>/explain", methods=["GET", "POST"])
154
+ @api_login(required_priv=["R"])
155
+ def explain_query(index, **kwargs):
156
+ """Search through specified index for a given Lucene query. Uses Lucene search syntax for query.
157
+
158
+ Variables:
159
+ index => Index to explain against (hit, user,...)
160
+
161
+ Arguments:
162
+ query => Lucene Query to explain
163
+
164
+ Data Block:
165
+ # Note that the data block is for POST requests only!
166
+ {
167
+ "query": "id:*", # Lucene Query to explain
168
+ }
169
+
170
+
171
+ Result Example:
172
+ {
173
+ 'valid': True,
174
+ 'explanations': [
175
+ {
176
+ 'valid': True,
177
+ 'explanation': 'ConstantScore(FieldExistsQuery [field=id])'
178
+ }
179
+ ]
180
+ }
181
+ """
182
+ user = kwargs["user"]
183
+ collection = get_collection(index, user)
184
+
185
+ if collection is None:
186
+ return bad_request(err=f"Not a valid index to explain: {index}")
187
+
188
+ fields = ["query"]
189
+ multi_fields: list[str] = []
190
+
191
+ params, req_data = generate_params(request, fields, multi_fields)
192
+
193
+ params["as_obj"] = False
194
+
195
+ query = req_data.get("query", None)
196
+ if not query:
197
+ return bad_request(err="There was no query.")
198
+
199
+ # This regex checks for lucene phrases (i.e. the "Example Analytic" part of howler.analytic:"Example Analytic")
200
+ # And then escapes them.
201
+ # https://regex101.com/r/8u5F6a/1
202
+ escaped_lucene = re.sub(r'((:\()?(".+?")(\)?))', lucene_service.replace_lucene_phrase, query)
203
+
204
+ try:
205
+ indices_client = IndicesClient(datastore().hit.datastore.client)
206
+
207
+ result = deepcopy(
208
+ indices_client.validate_query(q=escaped_lucene, explain=True, index=collection().index_name).body
209
+ )
210
+
211
+ del result["_shards"]
212
+
213
+ for explanation in result["explanations"]:
214
+ del explanation["index"]
215
+
216
+ return ok(result)
217
+ except Exception as e:
218
+ logger.exception("Exception on query explanation")
219
+ return bad_request(err=f"Exception: {e}")
220
+
221
+
149
222
  @generate_swagger_docs()
150
223
  @search_api.route("/<index>/eql", methods=["GET", "POST"])
151
224
  @api_login(required_priv=["R"])
@@ -138,11 +138,11 @@ if HWL_USE_REST_API or DEBUG:
138
138
  logger.debug("Enabled Notebook Integration")
139
139
  app.register_blueprint(notebook_api)
140
140
 
141
- if config.core.borealis.enabled:
142
- from howler.api.v1.borealis import borealis_api
141
+ if config.core.clue.enabled:
142
+ from howler.api.v1.clue import clue_api
143
143
 
144
- logger.debug("Enabled Borealis Integration")
145
- app.register_blueprint(borealis_api)
144
+ logger.debug("Enabled Clue Integration")
145
+ app.register_blueprint(clue_api)
146
146
 
147
147
  logger.info("Checking plugins for additional routes")
148
148
  for plugin in get_plugins():
@@ -259,13 +259,13 @@ def generate_useful_hit(lookups: dict[str, dict[str, Any]], users: list[User], p
259
259
  ),
260
260
  ]
261
261
 
262
- if config.core.borealis.enabled:
262
+ if config.core.clue.enabled:
263
263
  hit.howler.dossier.append(
264
264
  Lead(
265
265
  {
266
266
  "icon": "material-symbols:image",
267
- "label": {"en": "Borealis", "fr": "Borealis"},
268
- "format": "borealis",
267
+ "label": {"en": "Clue", "fr": "Clue"},
268
+ "format": "clue",
269
269
  "content": "test-plugin.image",
270
270
  "metadata": {"type": "ip", "value": "127.0.01", "classification": "TLP:CLEAR"},
271
271
  }
@@ -276,8 +276,8 @@ def generate_useful_hit(lookups: dict[str, dict[str, Any]], users: list[User], p
276
276
  Lead(
277
277
  {
278
278
  "icon": "material-symbols:code-rounded",
279
- "label": {"en": "Borealis", "fr": "Borealis"},
280
- "format": "borealis",
279
+ "label": {"en": "Clue", "fr": "Clue"},
280
+ "format": "clue",
281
281
  "content": "test-plugin.json",
282
282
  "metadata": {"type": "ip", "value": "127.0.01", "classification": "TLP:CLEAR"},
283
283
  }
@@ -409,24 +409,24 @@ class UI(BaseModel):
409
409
  )
410
410
 
411
411
 
412
- class Borealis(BaseModel):
413
- """Borealis enrichment service integration configuration.
412
+ class Clue(BaseModel):
413
+ """Clue enrichment service integration configuration.
414
414
 
415
- Defines settings for integrating with Borealis, an external enrichment
415
+ Defines settings for integrating with Clue, an external enrichment
416
416
  service that can provide additional context and status information for
417
417
  hits displayed in the Howler UI.
418
418
  """
419
419
 
420
- enabled: bool = Field(default=False, description="Should borealis integration be enabled?")
420
+ enabled: bool = Field(default=False, description="Should clue integration be enabled?")
421
421
 
422
422
  url: str = Field(
423
423
  default="http://enrichment-rest.enrichment.svc.cluster.local:5000",
424
- description="What url should Howler connect to to interact with Borealis?",
424
+ description="What url should Howler connect to to interact with Clue?",
425
425
  )
426
426
 
427
427
  status_checks: list[str] = Field(
428
428
  default=[],
429
- description="A list of borealis fetchers that return status results given a Howler ID to show in the UI.",
429
+ description="A list of clue fetchers that return status results given a Howler ID to show in the UI.",
430
430
  )
431
431
 
432
432
 
@@ -451,7 +451,7 @@ class Core(BaseModel):
451
451
  """Core application configuration for Howler.
452
452
 
453
453
  Aggregates all core service configurations including Redis, metrics,
454
- and external integrations like Borealis and nbgallery notebooks.
454
+ and external integrations like Clue and nbgallery notebooks.
455
455
  Also manages the loading of external plugins.
456
456
  """
457
457
 
@@ -463,8 +463,8 @@ class Core(BaseModel):
463
463
  redis: Redis = Redis()
464
464
  "Configuration for Redis instances"
465
465
 
466
- borealis: Borealis = Borealis()
467
- "Configuration for Borealis Integration"
466
+ clue: Clue = Clue()
467
+ "Configuration for Clue Integration"
468
468
 
469
469
  notebook: Notebook = Notebook()
470
470
  "Configuration for Notebook Integration"
@@ -529,7 +529,7 @@ class Config(BaseSettings):
529
529
  logging: Logging = Logging()
530
530
  system: System = System()
531
531
  ui: UI = UI()
532
- mapping: dict[str, str] = Field(description="Mapping of alert keys to borealis type", default={})
532
+ mapping: dict[str, str] = Field(description="Mapping of alert keys to clue types", default={})
533
533
 
534
534
  model_config = SettingsConfigDict(
535
535
  yaml_file=config_locations,
@@ -31,7 +31,7 @@ class Pivot(odm.Model):
31
31
  description="An optional icon to use in the tab display for this dossier.", optional=True
32
32
  )
33
33
  label: LocalizedLabel = odm.Compound(LocalizedLabel, description="Labels for the pivot in the UI.")
34
- value: str = odm.Keyword(description="The link/borealis id to pivot on.")
34
+ value: str = odm.Keyword(description="The link/plugin information to pivot on.")
35
35
  format: str = odm.Keyword(description="The format of the pivot.")
36
36
  mappings: list[Mapping] = odm.List(
37
37
  odm.Compound(Mapping),
@@ -220,8 +220,8 @@ class api_login(object): # noqa: D101, N801
220
220
  user_id=user.get("uname", None),
221
221
  )
222
222
 
223
- if request.path.startswith("/api/v1/borealis"):
224
- logger.debug("Bypassing quota limits for borealis enrichment")
223
+ if request.path.startswith("/api/v1/clue"):
224
+ logger.debug("Bypassing quota limits for clue enrichment")
225
225
  elif self.enforce_quota:
226
226
  # Check current user quota
227
227
  flsk_session["quota_user"] = user["uname"]
@@ -117,11 +117,11 @@ def get_configuration(user: User, **kwargs):
117
117
  },
118
118
  "mapping": config.mapping,
119
119
  "features": {
120
- "borealis": config.core.borealis.enabled,
120
+ "clue": config.core.clue.enabled,
121
121
  "notebook": config.core.notebook.enabled,
122
122
  **plugin_features,
123
123
  },
124
- "borealis": {"status_checks": config.core.borealis.status_checks},
124
+ "clue": {"status_checks": config.core.clue.status_checks},
125
125
  },
126
126
  "c12nDef": classification_definition,
127
127
  "indexes": list_all_fields("admin" in user["type"] if user is not None else False),
@@ -148,7 +148,7 @@ suppress-none-returning = true
148
148
  [tool.poetry]
149
149
  package-mode = true
150
150
  name = "howler-api"
151
- version = "2.13.0.dev341"
151
+ version = "2.13.0.dev343"
152
152
  description = "Howler - API server"
153
153
  authors = [
154
154
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",