howler-api 4.0.0.dev1266__tar.gz → 4.0.0.dev1281__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 (224) hide show
  1. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/PKG-INFO +1 -1
  2. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/demote.py +2 -2
  3. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/promote.py +2 -6
  4. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/howler_store.py +9 -1
  5. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/hit.py +10 -9
  6. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/workflow.py +7 -1
  7. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/helper.py +1 -1
  8. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/config.py +3 -2
  9. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/related.py +27 -1
  10. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/howler_data.py +2 -6
  11. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/random_data.py +0 -1
  12. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/hit_service.py +1 -1
  13. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/pyproject.toml +1 -1
  14. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/README.md +0 -0
  15. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/__init__.py +0 -0
  16. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/__init__.py +0 -0
  17. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/add_label.py +0 -0
  18. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/add_to_bundle.py +0 -0
  19. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/add_to_case.py +0 -0
  20. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/change_field.py +0 -0
  21. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/example_plugin.py +0 -0
  22. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/prioritization.py +0 -0
  23. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/remove_from_bundle.py +0 -0
  24. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/remove_label.py +0 -0
  25. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/actions/transition.py +0 -0
  26. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/__init__.py +0 -0
  27. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/base.py +0 -0
  28. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/socket.py +0 -0
  29. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/__init__.py +0 -0
  30. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/action.py +0 -0
  31. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/analytic.py +0 -0
  32. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/auth.py +0 -0
  33. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/clue.py +0 -0
  34. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/configs.py +0 -0
  35. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/dossier.py +0 -0
  36. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/help.py +0 -0
  37. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/hit.py +0 -0
  38. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/notebook.py +0 -0
  39. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/overview.py +0 -0
  40. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/search.py +0 -0
  41. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/template.py +0 -0
  42. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/tool.py +0 -0
  43. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/user.py +0 -0
  44. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/utils/__init__.py +0 -0
  45. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/utils/etag.py +0 -0
  46. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/utils/params.py +0 -0
  47. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v1/view.py +0 -0
  48. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v2/__init__.py +0 -0
  49. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v2/case.py +0 -0
  50. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v2/fuzzy.py +0 -0
  51. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v2/ingest.py +0 -0
  52. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/api/v2/search.py +0 -0
  53. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/app.py +0 -0
  54. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/README.md +0 -0
  55. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/__init__.py +0 -0
  56. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/classification.py +0 -0
  57. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/classification.yml +0 -0
  58. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/exceptions.py +0 -0
  59. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/loader.py +0 -0
  60. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/logging/__init__.py +0 -0
  61. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/logging/audit.py +0 -0
  62. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/logging/format.py +0 -0
  63. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/net.py +0 -0
  64. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/net_static.py +0 -0
  65. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/random_user.py +0 -0
  66. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/common/swagger.py +0 -0
  67. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/config.py +0 -0
  68. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/cronjobs/__init__.py +0 -0
  69. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/cronjobs/action_queue_worker.py +0 -0
  70. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/cronjobs/correlation.py +0 -0
  71. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/cronjobs/retention.py +0 -0
  72. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/cronjobs/view_cleanup.py +0 -0
  73. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/README.md +0 -0
  74. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/__init__.py +0 -0
  75. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/bulk.py +0 -0
  76. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/collection.py +0 -0
  77. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/constants.py +0 -0
  78. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/exceptions.py +0 -0
  79. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/migrations/fix_process.py +0 -0
  80. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/operations.py +0 -0
  81. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/schemas.py +0 -0
  82. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/store.py +0 -0
  83. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/support/__init__.py +0 -0
  84. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/support/build.py +0 -0
  85. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/support/schemas.py +0 -0
  86. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/datastore/types.py +0 -0
  87. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/error.py +0 -0
  88. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/README.md +0 -0
  89. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/__init__.py +0 -0
  90. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/generate_mitre.py +0 -0
  91. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/generate_sigma_rules.py +0 -0
  92. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/generate_tlds.py +0 -0
  93. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/reindex_data.py +0 -0
  94. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/external/wipe_databases.py +0 -0
  95. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/gunicorn_config.py +0 -0
  96. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/healthz.py +0 -0
  97. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/__init__.py +0 -0
  98. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/azure.py +0 -0
  99. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/discover.py +0 -0
  100. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/oauth.py +0 -0
  101. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/search.py +0 -0
  102. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/helper/ws.py +0 -0
  103. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/README.md +0 -0
  104. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/__init__.py +0 -0
  105. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/base.py +0 -0
  106. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/charter.txt +0 -0
  107. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/constants.py +0 -0
  108. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/howler_enum.py +0 -0
  109. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/mixins.py +0 -0
  110. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/__init__.py +0 -0
  111. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/action.py +0 -0
  112. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/analytic.py +0 -0
  113. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/assemblyline.py +0 -0
  114. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/aws.py +0 -0
  115. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/azure.py +0 -0
  116. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/case.py +0 -0
  117. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/cbs.py +0 -0
  118. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/clue.py +0 -0
  119. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/dossier.py +0 -0
  120. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/__init__.py +0 -0
  121. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/agent.py +0 -0
  122. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/autonomous_system.py +0 -0
  123. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/client.py +0 -0
  124. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/cloud.py +0 -0
  125. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/code_signature.py +0 -0
  126. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/container.py +0 -0
  127. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/dns.py +0 -0
  128. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/egress.py +0 -0
  129. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/elf.py +0 -0
  130. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/email.py +0 -0
  131. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/error.py +0 -0
  132. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/event.py +0 -0
  133. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/faas.py +0 -0
  134. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/file.py +0 -0
  135. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/geo.py +0 -0
  136. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/group.py +0 -0
  137. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/hash.py +0 -0
  138. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/host.py +0 -0
  139. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/http.py +0 -0
  140. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/ingress.py +0 -0
  141. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/interface.py +0 -0
  142. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/network.py +0 -0
  143. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/observer.py +0 -0
  144. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/organization.py +0 -0
  145. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/os.py +0 -0
  146. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/pe.py +0 -0
  147. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/process.py +0 -0
  148. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/registry.py +0 -0
  149. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/rule.py +0 -0
  150. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/server.py +0 -0
  151. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/threat.py +0 -0
  152. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/tls.py +0 -0
  153. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/url.py +0 -0
  154. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/user.py +0 -0
  155. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/user_agent.py +0 -0
  156. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/ecs/vulnerability.py +0 -0
  157. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/event.py +0 -0
  158. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/gcp.py +0 -0
  159. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/hit.py +0 -0
  160. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/lead.py +0 -0
  161. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/localized_label.py +0 -0
  162. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/overview.py +0 -0
  163. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/pivot.py +0 -0
  164. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/record.py +0 -0
  165. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/template.py +0 -0
  166. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/user.py +0 -0
  167. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/models/view.py +0 -0
  168. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/odm/randomizer.py +0 -0
  169. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/patched.py +0 -0
  170. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/plugins/__init__.py +0 -0
  171. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/plugins/config.py +0 -0
  172. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/__init__.py +0 -0
  173. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/README.md +0 -0
  174. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/__init__.py +0 -0
  175. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/counters.py +0 -0
  176. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/events.py +0 -0
  177. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/hash.py +0 -0
  178. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/lock.py +0 -0
  179. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/queues/__init__.py +0 -0
  180. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/queues/comms.py +0 -0
  181. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/queues/multi.py +0 -0
  182. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/queues/named.py +0 -0
  183. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/queues/priority.py +0 -0
  184. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/set.py +0 -0
  185. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  186. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/security/__init__.py +0 -0
  187. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/security/socket.py +0 -0
  188. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/security/utils.py +0 -0
  189. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/__init__.py +0 -0
  190. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/action_service.py +0 -0
  191. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/analytic_service.py +0 -0
  192. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/auth_service.py +0 -0
  193. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/bundle_compat_service.py +0 -0
  194. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/case_service.py +0 -0
  195. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/comms_service.py +0 -0
  196. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/config_service.py +0 -0
  197. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/correlation_service.py +0 -0
  198. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/docs_service.py +0 -0
  199. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/dossier_service.py +0 -0
  200. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/event_service.py +0 -0
  201. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/fuzzy_service.py +0 -0
  202. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/jwt_service.py +0 -0
  203. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/lucene_service.py +0 -0
  204. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/notebook_service.py +0 -0
  205. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/overview_service.py +0 -0
  206. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/search_service.py +0 -0
  207. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/template_service.py +0 -0
  208. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/user_service.py +0 -0
  209. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/services/viewer_service.py +0 -0
  210. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/telemetry.py +0 -0
  211. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/__init__.py +0 -0
  212. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/annotations.py +0 -0
  213. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/chunk.py +0 -0
  214. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/compat.py +0 -0
  215. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/constants.py +0 -0
  216. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/dict_utils.py +0 -0
  217. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/isotime.py +0 -0
  218. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/list_utils.py +0 -0
  219. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/lucene.py +0 -0
  220. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/net_utils.py +0 -0
  221. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/path.py +0 -0
  222. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/socket_utils.py +0 -0
  223. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/str_utils.py +0 -0
  224. {howler_api-4.0.0.dev1266 → howler_api-4.0.0.dev1281}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 4.0.0.dev1266
3
+ Version: 4.0.0.dev1281
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -76,7 +76,7 @@ def execute(
76
76
  *hit_helper.demote_hit(escalation=escalation),
77
77
  odm_helper.update("howler.assessment", None),
78
78
  odm_helper.update("howler.rationale", None),
79
- odm_helper.update("howler.assignment", None),
79
+ odm_helper.update("howler.triaged", None),
80
80
  ],
81
81
  )
82
82
  else:
@@ -94,7 +94,7 @@ def execute(
94
94
  ds.hit.update_by_query(
95
95
  query,
96
96
  [
97
- *hit_helper.assess_hit(assessment, rationale, user=(user if user else "automation")),
97
+ *hit_helper.assess_hit(assessment, rationale),
98
98
  odm_helper.update(
99
99
  "howler.assignment",
100
100
  user.get("uname", "automation") if user else "automation",
@@ -10,7 +10,6 @@ from howler.odm.models.howler_data import (
10
10
  AssessmentEscalationMap,
11
11
  Escalation,
12
12
  )
13
- from howler.odm.models.user import User
14
13
  from howler.utils.str_utils import sanitize_lucene_query
15
14
 
16
15
  OPERATION_ID = "promote"
@@ -27,7 +26,6 @@ def execute(
27
26
  escalation: Escalation = Escalation.ALERT,
28
27
  assessment: Optional[str] = None,
29
28
  rationale: Optional[str] = None,
30
- user: Optional[User] = None,
31
29
  **kwargs,
32
30
  ):
33
31
  """Promote a hit.
@@ -75,7 +73,7 @@ def execute(
75
73
  *hit_helper.promote_hit(escalation=escalation),
76
74
  odm_helper.update("howler.assessment", None),
77
75
  odm_helper.update("howler.rationale", None),
78
- odm_helper.update("howler.assignment", None),
76
+ odm_helper.update("howler.triaged", None),
79
77
  ],
80
78
  )
81
79
  else:
@@ -90,9 +88,7 @@ def execute(
90
88
  )
91
89
  return report
92
90
 
93
- ds.hit.update_by_query(
94
- query, hit_helper.assess_hit(assessment, rationale, user=(user if user else "automation"))
95
- )
91
+ ds.hit.update_by_query(query, hit_helper.assess_hit(assessment, rationale))
96
92
 
97
93
  report.append(
98
94
  {
@@ -8,6 +8,7 @@ from howler.odm.models.action import Action
8
8
  from howler.odm.models.analytic import Analytic
9
9
  from howler.odm.models.case import Case
10
10
  from howler.odm.models.clue import Clue
11
+ from howler.odm.models.config import ILMIndexConfig
11
12
  from howler.odm.models.dossier import Dossier
12
13
  from howler.odm.models.event import Event
13
14
  from howler.odm.models.hit import Hit
@@ -34,6 +35,8 @@ INDEXES = {
34
35
  "user_avatar": None,
35
36
  }
36
37
 
38
+ ILM_ENABLED_INDEXES = {"hit", "event", "case"}
39
+
37
40
 
38
41
  class HowlerDatastore(object):
39
42
  def __init__(self, datastore_object: "ESStore"):
@@ -55,7 +58,12 @@ class HowlerDatastore(object):
55
58
  )
56
59
 
57
60
  for _index, _odm in INDEXES.items():
58
- ilm_index_config = config.datastore.ilm.indices.get(_index) if config.datastore.ilm.enabled else None
61
+ ilm_index_config = config.datastore.ilm.indices.get(_index)
62
+ if ilm_index_config is None:
63
+ ilm_index_config = ILMIndexConfig(enabled=_index in ILM_ENABLED_INDEXES)
64
+ if not (config.datastore.ilm.enabled and ilm_index_config.enabled):
65
+ ilm_index_config = None
66
+
59
67
  self.ds.register(_index, _odm, ilm_config=ilm_index_config)
60
68
 
61
69
  def __enter__(self):
@@ -24,14 +24,11 @@ def assess_hit(
24
24
  assessment: Optional[str] = None,
25
25
  rationale: Optional[str] = None,
26
26
  hit: Optional[Union[dict[str, Any], Hit]] = None,
27
- *,
28
- user: User | str,
29
27
  **kwargs,
30
28
  ) -> list[OdmUpdateOperation]:
31
29
  """Update the assessment and esclation of a hit
32
30
 
33
31
  Args:
34
- user (User | str): The user making the assessment
35
32
  assessment (Optional[str], optional): The assessment to set the hit to. Defaults to None.
36
33
  hit (Optional[Union[dict[str, Any], Hit]], optional): The hit to update. Defaults to None.
37
34
 
@@ -55,6 +52,14 @@ def assess_hit(
55
52
  if assessment is None and rationale:
56
53
  rationale = None
57
54
 
55
+ if assessment is None:
56
+ # reset the timestamp and set state to in progress if removing assessment (re-assessing)
57
+ triaged_timestamp = None
58
+ status = Status.IN_PROGRESS
59
+ else:
60
+ triaged_timestamp = "NOW"
61
+ status = Status.RESOLVED
62
+
58
63
  logger.debug(
59
64
  "Updating assessment of %s to %s",
60
65
  hit["howler"]["id"] if hit else "unknown",
@@ -66,16 +71,12 @@ def assess_hit(
66
71
  escalation,
67
72
  )
68
73
 
69
- if assessment is None:
70
- assessor_id = None
71
- else:
72
- assessor_id = user.get("uname", user.get("username", None)) if isinstance(user, User) else user
73
-
74
74
  return [
75
75
  odm_helper.update("howler.assessment", assessment),
76
76
  odm_helper.update("howler.escalation", escalation),
77
77
  odm_helper.update("howler.rationale", rationale, silent=True),
78
- odm_helper.update("howler.assessor", assessor_id, silent=True),
78
+ odm_helper.update("howler.triaged", triaged_timestamp),
79
+ odm_helper.update("howler.status", status),
79
80
  ]
80
81
 
81
82
 
@@ -86,7 +86,13 @@ class Workflow:
86
86
 
87
87
  updates_dict[update.key] = update
88
88
 
89
- if self.status_prop not in updates_dict and _transition.get("dest", False):
89
+ if _transition.get("dest", False):
90
+ if self.status_prop in updates_dict and updates_dict[self.status_prop].value != _transition["dest"]:
91
+ raise WorkflowException(
92
+ f"Transition {transition} attempted to update the status {self.status_prop} with \
93
+ a different value than the transition destination."
94
+ )
95
+
90
96
  updates_dict[self.status_prop] = OdmUpdateOperation(
91
97
  ESCollection.UPDATE_SET,
92
98
  self.status_prop,
@@ -178,10 +178,10 @@ def generate_useful_hit( # noqa: C901
178
178
 
179
179
  hit.howler.assessment = None
180
180
  hit.howler.rationale = None
181
+ hit.howler.triaged = None
181
182
  hit.howler.status = "open"
182
183
  hit.howler.assignment = "unassigned"
183
184
  hit.howler.escalation = choice([Escalation.HIT, Escalation.ALERT])
184
- hit.howler.assessor = None
185
185
 
186
186
  if randint(1, 10) > 9:
187
187
  hit.howler.expiry = datetime.now() + timedelta(days=randint(1, 60))
@@ -97,10 +97,11 @@ class Host(BaseModel):
97
97
  class ILMIndexConfig(BaseModel):
98
98
  """Per-index ILM phase configuration.
99
99
 
100
- Controls when an index transitions to warm and cold phases.
100
+ Controls whether an index uses ILM and when it transitions to warm and cold phases.
101
101
  Values are Elasticsearch age strings (e.g. "30d", "90d").
102
102
  """
103
103
 
104
+ enabled: bool = Field(default=True, description="Enable ILM for this index")
104
105
  warm: Optional[str] = Field(
105
106
  default=None,
106
107
  description="Min age before the index enters the warm phase (e.g. '30d'). None to skip.",
@@ -135,7 +136,7 @@ class ILMConfig(BaseModel):
135
136
  description="Maximum primary shard size before rollover (e.g. '50gb')",
136
137
  )
137
138
  indices: dict[str, ILMIndexConfig] = Field(
138
- default={},
139
+ default_factory=dict,
139
140
  description="Per-index ILM configuration, keyed by collection name (e.g. 'hit')",
140
141
  )
141
142
 
@@ -33,7 +33,13 @@ class Related(odm.Model):
33
33
  )
34
34
 
35
35
  # Extra fields not defined in ECS but added for outline purposes
36
- id = odm.Optional(odm.Keyword(description="The id related to the event."))
36
+ id = odm.Optional(
37
+ odm.Keyword(
38
+ description="The id related to the event.",
39
+ deprecated=True,
40
+ deprecated_description="related.ids should be used instead of related.id.",
41
+ )
42
+ )
37
43
 
38
44
  uri = odm.Optional(odm.List(odm.URI(), description="All of the URIs related to the event."))
39
45
 
@@ -43,3 +49,23 @@ class Related(odm.Model):
43
49
  description="All the signatures/rules that were triggered by the event.",
44
50
  )
45
51
  )
52
+
53
+ def __init__(self, data: dict = None, *args, **kwargs):
54
+ if data is not None and data.get("id") is not None:
55
+ # Avoid mutating the caller-provided dict
56
+ data = dict(data)
57
+
58
+ existing_ids = data.get("ids")
59
+ if isinstance(existing_ids, (list, tuple)):
60
+ merged_ids = list(existing_ids)
61
+ elif existing_ids is None:
62
+ merged_ids = []
63
+ else:
64
+ merged_ids = [existing_ids]
65
+
66
+ if data["id"] not in merged_ids:
67
+ merged_ids.append(data["id"])
68
+
69
+ data["ids"] = merged_ids
70
+
71
+ super().__init__(data, *args, **kwargs)
@@ -1,4 +1,5 @@
1
1
  # mypy: ignore-errors
2
+ from datetime import datetime
2
3
  from typing import Optional
3
4
 
4
5
  from howler import odm
@@ -180,12 +181,6 @@ class HowlerData(odm.Model):
180
181
  description="Unique identifier of the assigned user.",
181
182
  default=DEFAULT_ASSIGNMENT,
182
183
  )
183
- assessor: Optional[str] = odm.Optional(
184
- odm.Keyword(
185
- description="The most recent person to assess a hit",
186
- default=None,
187
- )
188
- )
189
184
  data: list[str] = odm.List(
190
185
  odm.Keyword(description="Raw telemetry records associated with this hit."),
191
186
  default=[],
@@ -248,6 +243,7 @@ class HowlerData(odm.Model):
248
243
  )
249
244
  )
250
245
  )
246
+ triaged: Optional[datetime] = odm.Optional(odm.Date(description="Timestamp at which the hit was triaged."))
251
247
  comment: list[Comment] = odm.List(
252
248
  odm.Compound(Comment),
253
249
  default=[],
@@ -595,7 +595,6 @@ def create_hits(ds: HowlerDatastore, hit_count: int = 200):
595
595
  hit.howler.id,
596
596
  [
597
597
  *assess_hit(
598
- user=user,
599
598
  assessment=choice(Assessment.list()),
600
599
  rationale=get_random_string(),
601
600
  hit=hit,
@@ -111,7 +111,7 @@ def get_hit_workflow() -> Workflow:
111
111
  "source": [Status.OPEN, Status.IN_PROGRESS],
112
112
  "transition": HitStatusTransition.ASSESS,
113
113
  "dest": Status.RESOLVED,
114
- "actions": [assess_hit],
114
+ "actions": [assess_hit, assign_hit],
115
115
  }
116
116
  ),
117
117
  Transition(
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "4.0.0.dev1266"
155
+ version = "4.0.0.dev1281"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",