howler-api 2.10.0.dev167__tar.gz → 2.10.0.dev176__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 (196) hide show
  1. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/PKG-INFO +1 -1
  2. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/action.py +4 -49
  3. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/tool.py +5 -6
  4. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/audit.py +7 -7
  5. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/action_service.py +49 -2
  6. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/hit_service.py +2 -2
  7. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/pyproject.toml +1 -1
  8. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/README.md +0 -0
  9. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/__init__.py +0 -0
  10. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/__init__.py +0 -0
  11. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/add_label.py +0 -0
  12. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/add_to_bundle.py +0 -0
  13. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/change_field.py +0 -0
  14. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/demote.py +0 -0
  15. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/example_plugin.py +0 -0
  16. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/prioritization.py +0 -0
  17. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/promote.py +0 -0
  18. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/remove_from_bundle.py +0 -0
  19. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/remove_label.py +0 -0
  20. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/transition.py +0 -0
  21. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/__init__.py +0 -0
  22. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/base.py +0 -0
  23. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/socket.py +0 -0
  24. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/__init__.py +0 -0
  25. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/analytic.py +0 -0
  26. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/auth.py +0 -0
  27. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/borealis.py +0 -0
  28. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/configs.py +0 -0
  29. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/dossier.py +0 -0
  30. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/help.py +0 -0
  31. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/hit.py +0 -0
  32. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/notebook.py +0 -0
  33. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/overview.py +0 -0
  34. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/search.py +0 -0
  35. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/template.py +0 -0
  36. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/user.py +0 -0
  37. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/utils/__init__.py +0 -0
  38. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/utils/etag.py +0 -0
  39. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/view.py +0 -0
  40. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/app.py +0 -0
  41. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/README.md +0 -0
  42. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/__init__.py +0 -0
  43. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/classification.py +0 -0
  44. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/classification.yml +0 -0
  45. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/exceptions.py +0 -0
  46. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/hexdump.py +0 -0
  47. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/iprange.py +0 -0
  48. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/loader.py +0 -0
  49. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/__init__.py +0 -0
  50. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/format.py +0 -0
  51. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/net.py +0 -0
  52. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/net_static.py +0 -0
  53. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/random_user.py +0 -0
  54. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/swagger.py +0 -0
  55. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/config.py +0 -0
  56. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/__init__.py +0 -0
  57. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/retention.py +0 -0
  58. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/rules.py +0 -0
  59. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/README.md +0 -0
  60. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/__init__.py +0 -0
  61. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/bulk.py +0 -0
  62. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/collection.py +0 -0
  63. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/constants.py +0 -0
  64. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/exceptions.py +0 -0
  65. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/howler_store.py +0 -0
  66. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/migrations/fix_process.py +0 -0
  67. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/operations.py +0 -0
  68. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/schemas.py +0 -0
  69. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/store.py +0 -0
  70. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/__init__.py +0 -0
  71. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/build.py +0 -0
  72. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/schemas.py +0 -0
  73. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/types.py +0 -0
  74. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/error.py +0 -0
  75. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/__init__.py +0 -0
  76. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_mitre.py +0 -0
  77. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_sigma_rules.py +0 -0
  78. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_tlds.py +0 -0
  79. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/reindex_data.py +0 -0
  80. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/wipe_databases.py +0 -0
  81. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/gunicorn_config.py +0 -0
  82. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/healthz.py +0 -0
  83. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/__init__.py +0 -0
  84. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/azure.py +0 -0
  85. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/discover.py +0 -0
  86. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/hit.py +0 -0
  87. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/oauth.py +0 -0
  88. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/search.py +0 -0
  89. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/workflow.py +0 -0
  90. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/ws.py +0 -0
  91. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/README.md +0 -0
  92. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/__init__.py +0 -0
  93. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/base.py +0 -0
  94. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/charter.txt +0 -0
  95. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/helper.py +0 -0
  96. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/howler_enum.py +0 -0
  97. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/__init__.py +0 -0
  98. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/action.py +0 -0
  99. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/analytic.py +0 -0
  100. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/assemblyline.py +0 -0
  101. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/aws.py +0 -0
  102. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/azure.py +0 -0
  103. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/cbs.py +0 -0
  104. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/config.py +0 -0
  105. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/dossier.py +0 -0
  106. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/__init__.py +0 -0
  107. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/agent.py +0 -0
  108. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/autonomous_system.py +0 -0
  109. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/client.py +0 -0
  110. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/cloud.py +0 -0
  111. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/code_signature.py +0 -0
  112. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/container.py +0 -0
  113. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/dns.py +0 -0
  114. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/egress.py +0 -0
  115. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/elf.py +0 -0
  116. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/email.py +0 -0
  117. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/error.py +0 -0
  118. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/event.py +0 -0
  119. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/faas.py +0 -0
  120. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/file.py +0 -0
  121. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/geo.py +0 -0
  122. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/group.py +0 -0
  123. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/hash.py +0 -0
  124. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/host.py +0 -0
  125. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/http.py +0 -0
  126. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/ingress.py +0 -0
  127. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/interface.py +0 -0
  128. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/network.py +0 -0
  129. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/observer.py +0 -0
  130. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/organization.py +0 -0
  131. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/os.py +0 -0
  132. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/pe.py +0 -0
  133. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/process.py +0 -0
  134. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/registry.py +0 -0
  135. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/related.py +0 -0
  136. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/rule.py +0 -0
  137. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/server.py +0 -0
  138. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/threat.py +0 -0
  139. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/tls.py +0 -0
  140. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/url.py +0 -0
  141. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/user.py +0 -0
  142. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/user_agent.py +0 -0
  143. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/vulnerability.py +0 -0
  144. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/gcp.py +0 -0
  145. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/hit.py +0 -0
  146. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/howler_data.py +0 -0
  147. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/lead.py +0 -0
  148. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/localized_label.py +0 -0
  149. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/overview.py +0 -0
  150. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/pivot.py +0 -0
  151. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/template.py +0 -0
  152. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/user.py +0 -0
  153. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/view.py +0 -0
  154. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/random_data.py +0 -0
  155. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/randomizer.py +0 -0
  156. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/patched.py +0 -0
  157. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/plugins/__init__.py +0 -0
  158. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/plugins/config.py +0 -0
  159. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/__init__.py +0 -0
  160. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/README.md +0 -0
  161. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/__init__.py +0 -0
  162. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/counters.py +0 -0
  163. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/events.py +0 -0
  164. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/hash.py +0 -0
  165. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/lock.py +0 -0
  166. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/__init__.py +0 -0
  167. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/comms.py +0 -0
  168. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/multi.py +0 -0
  169. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/named.py +0 -0
  170. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/priority.py +0 -0
  171. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/set.py +0 -0
  172. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  173. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/__init__.py +0 -0
  174. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/socket.py +0 -0
  175. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/utils.py +0 -0
  176. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/__init__.py +0 -0
  177. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/analytic_service.py +0 -0
  178. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/auth_service.py +0 -0
  179. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/config_service.py +0 -0
  180. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/dossier_service.py +0 -0
  181. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/event_service.py +0 -0
  182. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/jwt_service.py +0 -0
  183. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/lucene_service.py +0 -0
  184. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/notebook_service.py +0 -0
  185. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/user_service.py +0 -0
  186. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/__init__.py +0 -0
  187. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/annotations.py +0 -0
  188. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/chunk.py +0 -0
  189. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/dict_utils.py +0 -0
  190. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/isotime.py +0 -0
  191. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/list_utils.py +0 -0
  192. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/lucene.py +0 -0
  193. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/path.py +0 -0
  194. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/socket_utils.py +0 -0
  195. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/str_utils.py +0 -0
  196. {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: howler-api
3
- Version: 2.10.0.dev167
3
+ Version: 2.10.0.dev176
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -1,19 +1,9 @@
1
1
  import json
2
- from typing import Any, Optional
3
2
 
4
3
  from flask import Response, request
5
4
 
6
5
  import howler.actions as actions
7
- from howler.api import (
8
- bad_request,
9
- created,
10
- forbidden,
11
- internal_error,
12
- make_subapi_blueprint,
13
- no_content,
14
- not_found,
15
- ok,
16
- )
6
+ from howler.api import bad_request, created, forbidden, internal_error, make_subapi_blueprint, no_content, not_found, ok
17
7
  from howler.common.exceptions import HowlerException
18
8
  from howler.common.loader import datastore
19
9
  from howler.common.logging.audit import audit
@@ -22,7 +12,7 @@ from howler.config import CLASSIFICATION
22
12
  from howler.odm.models.action import Action
23
13
  from howler.odm.models.user import User
24
14
  from howler.security import api_login
25
- from howler.services.action_service import VALID_TRIGGERS
15
+ from howler.services import action_service
26
16
 
27
17
  SUB_API = "action"
28
18
  classification_definition = CLASSIFICATION.get_parsed_classification_definition()
@@ -51,41 +41,6 @@ def get_actions(**_) -> Response:
51
41
  return ok(datastore().action.search("*:*", as_obj=False)["items"])
52
42
 
53
43
 
54
- def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
55
- """Validate a new action"""
56
- if not isinstance(new_action, dict):
57
- return bad_request(err="Incorrect data structure!")
58
-
59
- if "name" not in new_action:
60
- return bad_request(err="You must specify a name.")
61
- elif not new_action["name"]:
62
- return bad_request(err="Name cannot be empty.")
63
-
64
- if "query" not in new_action:
65
- return bad_request(err="You must specify a query.")
66
- elif not new_action["query"]:
67
- return bad_request(err="Query cannot be empty.")
68
-
69
- operations = new_action.get("operations", None)
70
- if operations is None:
71
- return bad_request(err="You must specify a list of operations.")
72
-
73
- if not isinstance(operations, list):
74
- return bad_request(err="'operations' must be a list of operations.")
75
-
76
- if len(operations) < 1:
77
- return bad_request(err="You must specify at least one operation.")
78
-
79
- operation_ids = [o["operation_id"] for o in operations]
80
- if len(operation_ids) != len(set(operation_ids)):
81
- return bad_request(err="You must have a maximum of one operation of each type in the action.")
82
-
83
- if set(new_action.get("triggers", [])) - set(VALID_TRIGGERS):
84
- return bad_request(err="Invalid trigger provided.")
85
-
86
- return None
87
-
88
-
89
44
  @generate_swagger_docs()
90
45
  @action_api.route("/", methods=["POST"])
91
46
  @api_login(audit=False, check_xsrf_token=False, required_type=["automation_basic"])
@@ -120,7 +75,7 @@ def add_action(user: User, **_) -> Response:
120
75
  if new_action is None:
121
76
  return bad_request(err="You must specify an action")
122
77
 
123
- if error := validate_action(new_action):
78
+ if error := action_service.validate_action(new_action):
124
79
  return error
125
80
 
126
81
  try:
@@ -192,7 +147,7 @@ def update_action(id: str, user: User, **_) -> Response:
192
147
  "action_id": existing_action["action_id"],
193
148
  }
194
149
 
195
- if error := validate_action(updated_action):
150
+ if error := action_service.validate_action(updated_action):
196
151
  return error
197
152
 
198
153
  try:
@@ -22,8 +22,6 @@ SUB_API = "tools"
22
22
  tool_api = make_subapi_blueprint(SUB_API, api_version=1)
23
23
  tool_api._doc = "Manage the tools"
24
24
 
25
- FIELDS = Hit.flat_fields()
26
-
27
25
  logger = get_logger(__file__)
28
26
 
29
27
  hit_helper = OdmHelper(Hit)
@@ -78,6 +76,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
78
76
  return bad_request(err="Invalid: 'hits' field is missing or invalid.")
79
77
  warnings = []
80
78
  # Validate field_map targets
79
+ hit_fields = Hit.flat_fields()
81
80
  for targets in field_map.values():
82
81
  for target in targets:
83
82
  # This is checking to see if the target matches one of two cases:
@@ -85,7 +84,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
85
84
  # Compound fields - hit.obj of type dict (should also match)
86
85
  # This allows significantly easier creation of hits, since you don't need to deconstruct every dict into
87
86
  # individual fields
88
- if target not in FIELDS and not any(f for f in FIELDS.keys() if get_parent_key(f) == target):
87
+ if target not in hit_fields and not any(f for f in hit_fields.keys() if get_parent_key(f) == target):
89
88
  warning = f"Invalid target field in the map: {target}"
90
89
  if ignore_extra_values:
91
90
  warnings.append(warning)
@@ -114,11 +113,11 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
114
113
  for target in targets:
115
114
  _val = val
116
115
  try:
117
- field_data: Optional[_Field] = FIELDS[target]
116
+ field_data: Optional[_Field] = hit_fields[target]
118
117
  except KeyError:
119
- logger.debug(f"`{target}` not in FIELDS")
118
+ logger.debug(f"`{target}` not in hit fields")
120
119
  field_data = next(
121
- (v for k, v in FIELDS.items() if get_parent_key(k) == target),
120
+ (v for k, v in hit_fields.items() if get_parent_key(k) == target),
122
121
  None,
123
122
  )
124
123
 
@@ -4,12 +4,7 @@ import sys
4
4
 
5
5
  from flask import request
6
6
 
7
- from howler.common.logging.format import (
8
- HWL_AUDIT_FORMAT,
9
- HWL_DATE_FORMAT,
10
- HWL_ISO_DATE_FORMAT,
11
- HWL_LOG_FORMAT,
12
- )
7
+ from howler.common.logging.format import HWL_AUDIT_FORMAT, HWL_DATE_FORMAT, HWL_ISO_DATE_FORMAT, HWL_LOG_FORMAT
13
8
  from howler.config import DEBUG, config
14
9
 
15
10
  AUDIT = config.ui.audit
@@ -94,10 +89,15 @@ def audit(args, kwargs, logged_in_uname, user, func, impersonator=None):
94
89
  except Exception:
95
90
  json_blob = {}
96
91
 
92
+ try:
93
+ req_args = ["%s='%s'" % (k, v) for k, v in request.args.items() if k in AUDIT_KW_TARGET]
94
+ except RuntimeError:
95
+ req_args = []
96
+
97
97
  params_list = (
98
98
  list(args)
99
99
  + ["%s='%s'" % (k, v) for k, v in kwargs.items() if k in AUDIT_KW_TARGET]
100
- + ["%s='%s'" % (k, v) for k, v in request.args.items() if k in AUDIT_KW_TARGET]
100
+ + req_args
101
101
  + ["%s='%s'" % (k, v) for k, v in json_blob.items() if k in AUDIT_KW_TARGET]
102
102
  )
103
103
 
@@ -1,7 +1,11 @@
1
1
  import json
2
- from typing import Optional
2
+ import sys
3
+ from typing import Any, Optional
4
+
5
+ from flask import Response
3
6
 
4
7
  from howler import actions
8
+ from howler.api import bad_request
5
9
  from howler.common.exceptions import HowlerValueError
6
10
  from howler.common.loader import datastore
7
11
  from howler.common.logging import get_logger
@@ -13,6 +17,41 @@ from howler.utils.str_utils import sanitize_lucene_query
13
17
  logger = get_logger(__file__)
14
18
 
15
19
 
20
+ def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
21
+ """Validate a new action"""
22
+ if not isinstance(new_action, dict):
23
+ return bad_request(err="Incorrect data structure!")
24
+
25
+ if "name" not in new_action:
26
+ return bad_request(err="You must specify a name.")
27
+ elif not new_action["name"]:
28
+ return bad_request(err="Name cannot be empty.")
29
+
30
+ if "query" not in new_action:
31
+ return bad_request(err="You must specify a query.")
32
+ elif not new_action["query"]:
33
+ return bad_request(err="Query cannot be empty.")
34
+
35
+ operations = new_action.get("operations", None)
36
+ if operations is None:
37
+ return bad_request(err="You must specify a list of operations.")
38
+
39
+ if not isinstance(operations, list):
40
+ return bad_request(err="'operations' must be a list of operations.")
41
+
42
+ if len(operations) < 1:
43
+ return bad_request(err="You must specify at least one operation.")
44
+
45
+ operation_ids = [o["operation_id"] for o in operations]
46
+ if len(operation_ids) != len(set(operation_ids)):
47
+ return bad_request(err="You must have a maximum of one operation of each type in the action.")
48
+
49
+ if set(new_action.get("triggers", [])) - set(VALID_TRIGGERS):
50
+ return bad_request(err="Invalid trigger provided.")
51
+
52
+ return None
53
+
54
+
16
55
  def bulk_execute_on_query(query: str, trigger: str = "create", user: Optional[User] = None):
17
56
  """Execute the operations specified in registered actions on the given query"""
18
57
  storage = datastore()
@@ -20,11 +59,19 @@ def bulk_execute_on_query(query: str, trigger: str = "create", user: Optional[Us
20
59
  if trigger not in VALID_TRIGGERS:
21
60
  raise HowlerValueError(f"{trigger} is not a valid trigger. It must be one of {','.join(VALID_TRIGGERS)}")
22
61
 
23
- on_trigger_actions: list[Action] = storage.action.search(f"triggers:{sanitize_lucene_query(trigger)}")["items"]
62
+ on_trigger_actions: list[Action] = storage.action.search(f"triggers:{sanitize_lucene_query(trigger)}", rows=10000)[
63
+ "items"
64
+ ]
24
65
 
25
66
  for action in on_trigger_actions:
26
67
  intersected_query = f"({query}) AND ({action.query})"
27
68
 
69
+ if datastore().hit.search(intersected_query, rows=0)["total"] < 1:
70
+ if "pytest" in sys.modules:
71
+ logger.debug("Action %s does not apply to query %s", action.action_id, query)
72
+
73
+ continue
74
+
28
75
  logger.info("Running action %s on bulk query %s", action.action_id, query)
29
76
  for operation in action.operations:
30
77
  if operation.operation_id == "example_plugin":
@@ -555,9 +555,9 @@ def transition_hit(
555
555
  trigger: Union[Literal["promote"], Literal["demote"]]
556
556
 
557
557
  if transition == HitStatusTransition.ASSESS:
558
- new_assessment = AssessmentEscalationMap[kwargs["assessment"]]
558
+ new_escalation = AssessmentEscalationMap[kwargs["assessment"]]
559
559
 
560
- if new_assessment == Escalation.EVIDENCE:
560
+ if new_escalation == Escalation.EVIDENCE:
561
561
  trigger = "promote"
562
562
  else:
563
563
  trigger = "demote"
@@ -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.10.0.dev167"
151
+ version = "2.10.0.dev176"
152
152
  description = "Howler - API server"
153
153
  authors = [
154
154
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",