howler-api 2.10.0.dev168__tar.gz → 2.10.0.dev178__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.dev168 → howler_api-2.10.0.dev178}/PKG-INFO +1 -1
  2. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/action.py +4 -49
  3. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/user.py +1 -1
  4. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/logging/audit.py +7 -7
  5. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/action_service.py +49 -2
  6. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/hit_service.py +2 -2
  7. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/pyproject.toml +1 -1
  8. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/README.md +0 -0
  9. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/__init__.py +0 -0
  10. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/__init__.py +0 -0
  11. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/add_label.py +0 -0
  12. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/add_to_bundle.py +0 -0
  13. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/change_field.py +0 -0
  14. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/demote.py +0 -0
  15. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/example_plugin.py +0 -0
  16. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/prioritization.py +0 -0
  17. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/promote.py +0 -0
  18. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/remove_from_bundle.py +0 -0
  19. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/remove_label.py +0 -0
  20. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/actions/transition.py +0 -0
  21. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/__init__.py +0 -0
  22. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/base.py +0 -0
  23. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/socket.py +0 -0
  24. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/__init__.py +0 -0
  25. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/analytic.py +0 -0
  26. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/auth.py +0 -0
  27. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/borealis.py +0 -0
  28. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/configs.py +0 -0
  29. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/dossier.py +0 -0
  30. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/help.py +0 -0
  31. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/hit.py +0 -0
  32. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/notebook.py +0 -0
  33. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/overview.py +0 -0
  34. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/search.py +0 -0
  35. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/template.py +0 -0
  36. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/tool.py +0 -0
  37. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/utils/__init__.py +0 -0
  38. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/utils/etag.py +0 -0
  39. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/api/v1/view.py +0 -0
  40. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/app.py +0 -0
  41. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/README.md +0 -0
  42. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/__init__.py +0 -0
  43. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/classification.py +0 -0
  44. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/classification.yml +0 -0
  45. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/exceptions.py +0 -0
  46. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/hexdump.py +0 -0
  47. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/iprange.py +0 -0
  48. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/loader.py +0 -0
  49. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/logging/__init__.py +0 -0
  50. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/logging/format.py +0 -0
  51. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/net.py +0 -0
  52. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/net_static.py +0 -0
  53. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/random_user.py +0 -0
  54. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/common/swagger.py +0 -0
  55. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/config.py +0 -0
  56. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/cronjobs/__init__.py +0 -0
  57. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/cronjobs/retention.py +0 -0
  58. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/cronjobs/rules.py +0 -0
  59. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/README.md +0 -0
  60. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/__init__.py +0 -0
  61. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/bulk.py +0 -0
  62. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/collection.py +0 -0
  63. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/constants.py +0 -0
  64. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/exceptions.py +0 -0
  65. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/howler_store.py +0 -0
  66. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/migrations/fix_process.py +0 -0
  67. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/operations.py +0 -0
  68. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/schemas.py +0 -0
  69. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/store.py +0 -0
  70. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/support/__init__.py +0 -0
  71. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/support/build.py +0 -0
  72. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/support/schemas.py +0 -0
  73. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/datastore/types.py +0 -0
  74. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/error.py +0 -0
  75. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/__init__.py +0 -0
  76. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/generate_mitre.py +0 -0
  77. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/generate_sigma_rules.py +0 -0
  78. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/generate_tlds.py +0 -0
  79. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/reindex_data.py +0 -0
  80. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/external/wipe_databases.py +0 -0
  81. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/gunicorn_config.py +0 -0
  82. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/healthz.py +0 -0
  83. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/__init__.py +0 -0
  84. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/azure.py +0 -0
  85. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/discover.py +0 -0
  86. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/hit.py +0 -0
  87. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/oauth.py +0 -0
  88. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/search.py +0 -0
  89. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/workflow.py +0 -0
  90. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/helper/ws.py +0 -0
  91. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/README.md +0 -0
  92. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/__init__.py +0 -0
  93. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/base.py +0 -0
  94. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/charter.txt +0 -0
  95. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/helper.py +0 -0
  96. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/howler_enum.py +0 -0
  97. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/__init__.py +0 -0
  98. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/action.py +0 -0
  99. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/analytic.py +0 -0
  100. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/assemblyline.py +0 -0
  101. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/aws.py +0 -0
  102. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/azure.py +0 -0
  103. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/cbs.py +0 -0
  104. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/config.py +0 -0
  105. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/dossier.py +0 -0
  106. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/__init__.py +0 -0
  107. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/agent.py +0 -0
  108. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/autonomous_system.py +0 -0
  109. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/client.py +0 -0
  110. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/cloud.py +0 -0
  111. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/code_signature.py +0 -0
  112. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/container.py +0 -0
  113. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/dns.py +0 -0
  114. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/egress.py +0 -0
  115. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/elf.py +0 -0
  116. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/email.py +0 -0
  117. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/error.py +0 -0
  118. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/event.py +0 -0
  119. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/faas.py +0 -0
  120. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/file.py +0 -0
  121. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/geo.py +0 -0
  122. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/group.py +0 -0
  123. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/hash.py +0 -0
  124. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/host.py +0 -0
  125. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/http.py +0 -0
  126. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/ingress.py +0 -0
  127. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/interface.py +0 -0
  128. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/network.py +0 -0
  129. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/observer.py +0 -0
  130. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/organization.py +0 -0
  131. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/os.py +0 -0
  132. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/pe.py +0 -0
  133. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/process.py +0 -0
  134. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/registry.py +0 -0
  135. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/related.py +0 -0
  136. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/rule.py +0 -0
  137. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/server.py +0 -0
  138. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/threat.py +0 -0
  139. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/tls.py +0 -0
  140. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/url.py +0 -0
  141. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/user.py +0 -0
  142. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/user_agent.py +0 -0
  143. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/ecs/vulnerability.py +0 -0
  144. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/gcp.py +0 -0
  145. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/hit.py +0 -0
  146. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/howler_data.py +0 -0
  147. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/lead.py +0 -0
  148. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/localized_label.py +0 -0
  149. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/overview.py +0 -0
  150. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/pivot.py +0 -0
  151. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/template.py +0 -0
  152. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/user.py +0 -0
  153. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/models/view.py +0 -0
  154. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/random_data.py +0 -0
  155. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/odm/randomizer.py +0 -0
  156. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/patched.py +0 -0
  157. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/plugins/__init__.py +0 -0
  158. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/plugins/config.py +0 -0
  159. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/__init__.py +0 -0
  160. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/README.md +0 -0
  161. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/__init__.py +0 -0
  162. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/counters.py +0 -0
  163. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/events.py +0 -0
  164. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/hash.py +0 -0
  165. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/lock.py +0 -0
  166. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/queues/__init__.py +0 -0
  167. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/queues/comms.py +0 -0
  168. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/queues/multi.py +0 -0
  169. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/queues/named.py +0 -0
  170. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/queues/priority.py +0 -0
  171. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/set.py +0 -0
  172. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  173. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/security/__init__.py +0 -0
  174. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/security/socket.py +0 -0
  175. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/security/utils.py +0 -0
  176. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/__init__.py +0 -0
  177. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/analytic_service.py +0 -0
  178. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/auth_service.py +0 -0
  179. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/config_service.py +0 -0
  180. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/dossier_service.py +0 -0
  181. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/event_service.py +0 -0
  182. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/jwt_service.py +0 -0
  183. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/lucene_service.py +0 -0
  184. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/notebook_service.py +0 -0
  185. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/services/user_service.py +0 -0
  186. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/__init__.py +0 -0
  187. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/annotations.py +0 -0
  188. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/chunk.py +0 -0
  189. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/dict_utils.py +0 -0
  190. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/isotime.py +0 -0
  191. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/list_utils.py +0 -0
  192. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/lucene.py +0 -0
  193. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/path.py +0 -0
  194. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/socket_utils.py +0 -0
  195. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/howler/utils/str_utils.py +0 -0
  196. {howler_api-2.10.0.dev168 → howler_api-2.10.0.dev178}/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.dev168
3
+ Version: 2.10.0.dev178
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:
@@ -327,7 +327,7 @@ def get_user_avatar(username, **_):
327
327
  resp.headers["ETag"] = sha256(avatar.encode("utf-8")).hexdigest()
328
328
  return resp
329
329
  else:
330
- return not_found(err="No avatar for specified user")
330
+ return no_content()
331
331
 
332
332
 
333
333
  @generate_swagger_docs()
@@ -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.dev168"
151
+ version = "2.10.0.dev178"
152
152
  description = "Howler - API server"
153
153
  authors = [
154
154
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",