howler-api 4.1.0.dev1436__tar.gz → 4.1.0.dev1460__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.
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/PKG-INFO +1 -1
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/search.py +8 -2
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/action_queue_worker.py +3 -3
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/action_service.py +22 -16
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/search_service.py +20 -2
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/pyproject.toml +1 -1
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_label.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_to_bundle.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/add_to_case.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/change_field.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/demote.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/example_plugin.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/prioritization.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/promote.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/remove_from_bundle.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/remove_label.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/actions/transition.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/base.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/socket.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/action.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/analytic.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/auth.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/clue.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/configs.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/dossier.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/help.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/hit.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/notebook.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/overview.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/search.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/template.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/tool.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/user.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/etag.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/utils/params.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v1/view.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/case.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/fuzzy.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/api/v2/ingest.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/app.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/classification.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/classification.yml +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/exceptions.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/loader.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/audit.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/logging/format.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/net.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/net_static.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/random_user.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/common/swagger.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/config.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/correlation.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/retention.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/view_cleanup.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/bulk.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/collection.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/constants.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/exceptions.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/howler_store.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/migrations/fix_process.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/operations.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/schemas.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/store.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/build.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/support/schemas.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/types.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/error.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/check_duplicates.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_mitre.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_sigma_rules.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_tlds.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/reindex_data.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/wipe_databases.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/gunicorn_config.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/healthz.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/azure.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/discover.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/hit.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/oauth.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/search.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/workflow.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/helper/ws.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/base.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/charter.txt +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/constants.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/helper.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/howler_enum.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/mixins.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/action.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/analytic.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/assemblyline.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/aws.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/azure.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/case.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/cbs.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/clue.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/config.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/dossier.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/agent.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/autonomous_system.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/client.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/cloud.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/code_signature.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/container.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/dns.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/egress.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/elf.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/email.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/error.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/event.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/faas.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/file.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/geo.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/group.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/hash.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/host.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/http.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/ingress.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/interface.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/network.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/observer.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/organization.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/os.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/pe.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/process.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/registry.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/related.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/rule.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/server.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/threat.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/tls.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/url.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/user.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/user_agent.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/vulnerability.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/event.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/gcp.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/hit.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/howler_data.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/lead.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/localized_label.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/overview.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/pivot.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/record.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/template.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/user.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/view.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/random_data.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/randomizer.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/patched.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/plugins/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/plugins/config.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/README.md +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/counters.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/events.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/hash.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/lock.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/comms.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/multi.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/named.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/priority.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/set.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/user_quota_tracker.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/socket.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/security/utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/analytic_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/auth_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/bundle_compat_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/case_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/comms_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/config_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/correlation_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/docs_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/dossier_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/event_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/fuzzy_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/hit_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/jwt_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/lucene_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/notebook_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/overview_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/template_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/user_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/viewer_service.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/telemetry.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/__init__.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/annotations.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/chunk.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/compat.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/constants.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/dict_utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/indexes.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/isotime.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/list_utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/lucene.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/net_utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/path.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/socket_utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/str_utils.py +0 -0
- {howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/utils/uid.py +0 -0
|
@@ -7,7 +7,7 @@ from elasticsearch import BadRequestError
|
|
|
7
7
|
from elasticsearch._sync.client.indices import IndicesClient
|
|
8
8
|
from flask import request
|
|
9
9
|
|
|
10
|
-
from howler.api import bad_request, internal_error, make_subapi_blueprint, ok
|
|
10
|
+
from howler.api import bad_request, forbidden, internal_error, make_subapi_blueprint, ok
|
|
11
11
|
from howler.common.loader import datastore
|
|
12
12
|
from howler.common.logging import get_logger
|
|
13
13
|
from howler.common.logging.audit import audit
|
|
@@ -17,6 +17,7 @@ from howler.helper.search import get_collection, has_access_control
|
|
|
17
17
|
from howler.odm.models.user import User
|
|
18
18
|
from howler.security import api_login
|
|
19
19
|
from howler.services import hit_service, lucene_service, search_service
|
|
20
|
+
from howler.services.search_service import SensitiveUserFieldsException
|
|
20
21
|
from howler.utils.net_utils import generate_params
|
|
21
22
|
|
|
22
23
|
SUB_API = "search"
|
|
@@ -98,7 +99,10 @@ def search(indexes: str, user: User, **kwargs):
|
|
|
98
99
|
}
|
|
99
100
|
)
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
if params.get("sort"):
|
|
103
|
+
params["sort"] = [entry for entry in params["sort"].split(",") if entry]
|
|
104
|
+
else:
|
|
105
|
+
params.pop("sort", None)
|
|
102
106
|
|
|
103
107
|
query = req_data.get("query", None)
|
|
104
108
|
if not query:
|
|
@@ -110,6 +114,8 @@ def search(indexes: str, user: User, **kwargs):
|
|
|
110
114
|
|
|
111
115
|
try:
|
|
112
116
|
result = search_service.search(indexes, query, user=user, **params)
|
|
117
|
+
except SensitiveUserFieldsException as e:
|
|
118
|
+
return forbidden(err=e.message)
|
|
113
119
|
except (SearchException, BadRequestError) as e:
|
|
114
120
|
logger.exception(f"SearchException on query {query}")
|
|
115
121
|
return bad_request(err=f"SearchException on query {query}: {str(e)}")
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/cronjobs/action_queue_worker.py
RENAMED
|
@@ -13,7 +13,7 @@ from apscheduler.schedulers.base import BaseScheduler
|
|
|
13
13
|
from howler.common.logging import get_logger
|
|
14
14
|
from howler.config import config
|
|
15
15
|
from howler.odm.models.action import VALID_TRIGGERS
|
|
16
|
-
from howler.services.action_service import
|
|
16
|
+
from howler.services.action_service import TriggeredAction, get_action_queue, process_action_batch
|
|
17
17
|
|
|
18
18
|
logger = get_logger(__file__)
|
|
19
19
|
|
|
@@ -33,7 +33,7 @@ def run_worker(trigger: str) -> None: # pragma: no cover – long-running loop,
|
|
|
33
33
|
logger.info("Action queue worker disabled by configuration, not starting for trigger=%s", trigger)
|
|
34
34
|
return
|
|
35
35
|
|
|
36
|
-
queue =
|
|
36
|
+
queue = get_action_queue(trigger)
|
|
37
37
|
logger.info(
|
|
38
38
|
"Action queue worker started for trigger=%s (batch_size=%d, timeout=%ds)",
|
|
39
39
|
trigger,
|
|
@@ -41,7 +41,7 @@ def run_worker(trigger: str) -> None: # pragma: no cover – long-running loop,
|
|
|
41
41
|
BATCH_TIMEOUT,
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
batch: list[
|
|
44
|
+
batch: list[TriggeredAction] = []
|
|
45
45
|
|
|
46
46
|
while True:
|
|
47
47
|
try:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from typing import Any, Optional, TypedDict
|
|
3
4
|
|
|
4
5
|
from flask import Response
|
|
5
6
|
|
|
@@ -18,11 +19,19 @@ from howler.utils.str_utils import sanitize_lucene_query
|
|
|
18
19
|
|
|
19
20
|
logger = get_logger(__file__)
|
|
20
21
|
|
|
22
|
+
|
|
23
|
+
class TriggeredAction(TypedDict):
|
|
24
|
+
"""Type for triggered actions"""
|
|
25
|
+
|
|
26
|
+
hit_ids: list[str]
|
|
27
|
+
uname: str | None
|
|
28
|
+
|
|
29
|
+
|
|
21
30
|
# Per-trigger persistent queues for buffering action execution requests.
|
|
22
|
-
_action_queues: dict[str, NamedQueue[
|
|
31
|
+
_action_queues: dict[str, NamedQueue[TriggeredAction]] = {}
|
|
23
32
|
|
|
24
33
|
|
|
25
|
-
def
|
|
34
|
+
def get_action_queue(trigger: str) -> NamedQueue[TriggeredAction]:
|
|
26
35
|
"""Return the action queue for *trigger*, creating it on first use.
|
|
27
36
|
|
|
28
37
|
Raises:
|
|
@@ -65,10 +74,10 @@ def enqueue_action_execution(hit_ids: list[str], trigger: str = "create", user:
|
|
|
65
74
|
return
|
|
66
75
|
|
|
67
76
|
try:
|
|
68
|
-
|
|
77
|
+
get_action_queue(trigger).push(
|
|
69
78
|
{
|
|
70
79
|
"hit_ids": hit_ids,
|
|
71
|
-
"
|
|
80
|
+
"uname": user.uname if user else None,
|
|
72
81
|
}
|
|
73
82
|
)
|
|
74
83
|
except Exception:
|
|
@@ -77,7 +86,7 @@ def enqueue_action_execution(hit_ids: list[str], trigger: str = "create", user:
|
|
|
77
86
|
bulk_execute_on_query(query, trigger=trigger, user=user)
|
|
78
87
|
|
|
79
88
|
|
|
80
|
-
def process_action_batch(trigger: str, items: list[
|
|
89
|
+
def process_action_batch(trigger: str, items: list[TriggeredAction]) -> None:
|
|
81
90
|
"""Process a batch of queued action execution requests for a single trigger.
|
|
82
91
|
|
|
83
92
|
Groups items by user and issues a single coalesced
|
|
@@ -90,26 +99,23 @@ def process_action_batch(trigger: str, items: list[dict]) -> None:
|
|
|
90
99
|
if not items:
|
|
91
100
|
return
|
|
92
101
|
|
|
93
|
-
groups: dict[str | None,
|
|
102
|
+
groups: dict[str | None, list[str]] = defaultdict(list)
|
|
94
103
|
|
|
95
104
|
for item in items:
|
|
96
|
-
|
|
97
|
-
user_key = user_data["uname"] if isinstance(user_data, dict) and "uname" in user_data else None
|
|
98
|
-
|
|
99
|
-
if user_key not in groups:
|
|
100
|
-
groups[user_key] = ([], user_data)
|
|
105
|
+
uname = item.get("uname")
|
|
101
106
|
|
|
102
|
-
groups[
|
|
107
|
+
groups[uname].extend(item["hit_ids"])
|
|
103
108
|
|
|
104
|
-
for
|
|
109
|
+
for uname, hit_ids in groups.items():
|
|
105
110
|
# Deduplicate IDs within a batch group
|
|
106
111
|
unique_ids = list(dict.fromkeys(hit_ids))
|
|
107
112
|
query = f"howler.id:({' OR '.join(sanitize_lucene_query(h) for h in unique_ids)})"
|
|
108
113
|
|
|
109
114
|
try:
|
|
110
|
-
|
|
115
|
+
user = datastore().user.get(uname)
|
|
116
|
+
bulk_execute_on_query(query, trigger=trigger, user=user)
|
|
111
117
|
except Exception:
|
|
112
|
-
logger.exception("Error processing action batch for trigger=%s user=%s", trigger,
|
|
118
|
+
logger.exception("Error processing action batch for trigger=%s user=%s", trigger, uname)
|
|
113
119
|
|
|
114
120
|
|
|
115
121
|
def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
|
|
@@ -10,7 +10,7 @@ from howler.common.logging import get_logger
|
|
|
10
10
|
from howler.datastore.collection import parse_sort
|
|
11
11
|
from howler.datastore.exceptions import SearchException, SearchRetryException
|
|
12
12
|
from howler.datastore.types import SearchResult
|
|
13
|
-
from howler.helper.search import get_collection, has_access_control
|
|
13
|
+
from howler.helper.search import get_collection, get_default_sort, has_access_control
|
|
14
14
|
from howler.odm.models.user import User
|
|
15
15
|
from howler.services import case_service
|
|
16
16
|
from howler.utils.indexes import get_logical_index_name, normalize_indexes
|
|
@@ -20,10 +20,15 @@ DEFAULT_ROW_SIZE = 25
|
|
|
20
20
|
DEFAULT_SORT: list[dict[str, str]] = [{"_id": "asc"}]
|
|
21
21
|
DEFAULT_SEARCH_FIELD = "__text__"
|
|
22
22
|
SCROLL_TIMEOUT = "5m"
|
|
23
|
+
SENSITIVE_USER_FIELDS = ["password", "apikeys", "*"]
|
|
23
24
|
|
|
24
25
|
logger = get_logger(__file__)
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
class SensitiveUserFieldsException(SearchException):
|
|
29
|
+
"""Raised when a user search requests protected source fields."""
|
|
30
|
+
|
|
31
|
+
|
|
27
32
|
def _format_items(hits: list[dict[str, Any]], user_classification: str | None) -> list[dict[str, Any]]:
|
|
28
33
|
"""Formats Elasticsearch search hits into a standardized item format.
|
|
29
34
|
|
|
@@ -93,6 +98,14 @@ def search( # noqa: C901
|
|
|
93
98
|
"""
|
|
94
99
|
del metadata
|
|
95
100
|
|
|
101
|
+
index_list = _parse_index_list(indexes)
|
|
102
|
+
if (
|
|
103
|
+
fl is not None
|
|
104
|
+
and "user" in index_list
|
|
105
|
+
and any(sensitive_field in fl for sensitive_field in SENSITIVE_USER_FIELDS)
|
|
106
|
+
):
|
|
107
|
+
raise SensitiveUserFieldsException("Invalid fields to retrieve.")
|
|
108
|
+
|
|
96
109
|
client: Elasticsearch = datastore().ds.client
|
|
97
110
|
parsed_indexes = normalize_indexes(indexes)
|
|
98
111
|
|
|
@@ -113,7 +126,12 @@ def search( # noqa: C901
|
|
|
113
126
|
query = "id:*"
|
|
114
127
|
|
|
115
128
|
if sort is None:
|
|
116
|
-
|
|
129
|
+
default_sorts = [get_default_sort(index, user) for index in _parse_index_list(indexes)] if user else []
|
|
130
|
+
default_sort = default_sorts[0] if default_sorts else None
|
|
131
|
+
if default_sort is not None and all(index_sort == default_sort for index_sort in default_sorts):
|
|
132
|
+
sort = default_sort
|
|
133
|
+
else:
|
|
134
|
+
sort = DEFAULT_SORT
|
|
117
135
|
|
|
118
136
|
if rows is None:
|
|
119
137
|
rows = DEFAULT_ROW_SIZE
|
|
@@ -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.1.0.
|
|
155
|
+
version = "4.1.0.dev1460"
|
|
156
156
|
description = "Howler - API server"
|
|
157
157
|
authors = [
|
|
158
158
|
"Canadian Centre for Cyber Security <howler@cyber.gc.ca>",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/datastore/migrations/fix_process.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/external/generate_sigma_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/autonomous_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/code_signature.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/odm/models/ecs/vulnerability.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/__init__.py
RENAMED
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/comms.py
RENAMED
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/multi.py
RENAMED
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/named.py
RENAMED
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/queues/priority.py
RENAMED
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/remote/datatypes/user_quota_tracker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/bundle_compat_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.1.0.dev1436 → howler_api-4.1.0.dev1460}/howler/services/correlation_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|