howler-api 4.0.0.dev1121__tar.gz → 4.0.0.dev1141__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.0.0.dev1121 → howler_api-4.0.0.dev1141}/PKG-INFO +1 -1
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v2/case.py +4 -2
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v2/search.py +3 -10
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/case.py +8 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/case_service.py +27 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/search_service.py +14 -5
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/pyproject.toml +1 -1
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/add_label.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/add_to_bundle.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/add_to_case.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/change_field.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/demote.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/example_plugin.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/prioritization.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/promote.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/remove_from_bundle.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/remove_label.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/actions/transition.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/base.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/socket.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/action.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/analytic.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/auth.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/clue.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/configs.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/dossier.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/help.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/hit.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/notebook.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/overview.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/search.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/template.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/tool.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/user.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/utils/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/utils/etag.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/utils/params.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v1/view.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v2/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v2/fuzzy.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/api/v2/ingest.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/app.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/classification.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/classification.yml +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/exceptions.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/loader.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/logging/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/logging/audit.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/logging/format.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/net.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/net_static.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/random_user.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/common/swagger.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/config.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/action_queue_worker.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/correlation.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/retention.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/view_cleanup.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/bulk.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/collection.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/constants.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/exceptions.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/howler_store.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/migrations/fix_process.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/operations.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/schemas.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/store.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/support/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/support/build.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/support/schemas.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/datastore/types.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/error.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/generate_mitre.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/generate_sigma_rules.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/generate_tlds.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/reindex_data.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/external/wipe_databases.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/gunicorn_config.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/healthz.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/azure.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/discover.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/hit.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/oauth.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/search.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/workflow.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/helper/ws.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/base.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/charter.txt +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/constants.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/helper.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/howler_enum.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/mixins.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/action.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/analytic.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/assemblyline.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/aws.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/azure.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/cbs.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/clue.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/config.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/dossier.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/agent.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/autonomous_system.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/client.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/cloud.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/code_signature.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/container.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/dns.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/egress.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/elf.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/email.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/error.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/event.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/faas.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/file.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/geo.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/group.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/hash.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/host.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/http.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/ingress.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/interface.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/network.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/observer.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/organization.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/os.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/pe.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/process.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/registry.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/related.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/rule.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/server.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/threat.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/tls.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/url.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/user.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/user_agent.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/vulnerability.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/event.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/gcp.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/hit.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/howler_data.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/lead.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/localized_label.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/overview.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/pivot.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/record.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/template.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/user.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/view.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/random_data.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/randomizer.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/patched.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/plugins/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/plugins/config.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/README.md +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/counters.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/events.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/hash.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/lock.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/comms.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/multi.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/named.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/priority.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/set.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/user_quota_tracker.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/security/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/security/socket.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/security/utils.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/action_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/analytic_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/auth_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/bundle_compat_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/comms_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/config_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/correlation_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/docs_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/dossier_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/event_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/fuzzy_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/hit_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/jwt_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/lucene_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/notebook_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/overview_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/template_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/user_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/viewer_service.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/telemetry.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/__init__.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/annotations.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/chunk.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/compat.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/constants.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/dict_utils.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/isotime.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/list_utils.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/lucene.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/path.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/socket_utils.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/str_utils.py +0 -0
- {howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/utils/uid.py +0 -0
|
@@ -63,7 +63,7 @@ def create_case(user: User, **kwargs):
|
|
|
63
63
|
@generate_swagger_docs()
|
|
64
64
|
@case_api.route("/<id>", methods=["GET"])
|
|
65
65
|
@api_login(audit=True, required_priv=["R"])
|
|
66
|
-
def get_case(id: str, **kwargs):
|
|
66
|
+
def get_case(id: str, user: User, **kwargs):
|
|
67
67
|
"""Get a case.
|
|
68
68
|
|
|
69
69
|
Variables:
|
|
@@ -77,11 +77,13 @@ def get_case(id: str, **kwargs):
|
|
|
77
77
|
...case # The requested case, if it exists
|
|
78
78
|
}
|
|
79
79
|
"""
|
|
80
|
-
case = datastore().case.
|
|
80
|
+
case = datastore().case.get(id, as_obj=False)
|
|
81
81
|
|
|
82
82
|
if not case:
|
|
83
83
|
return not_found(err="Case %s does not exist" % id)
|
|
84
84
|
|
|
85
|
+
case_service.filter_case_items_by_classification(case, user.classification)
|
|
86
|
+
|
|
85
87
|
return ok(case)
|
|
86
88
|
|
|
87
89
|
|
|
@@ -12,6 +12,7 @@ from howler.common.logging import get_logger
|
|
|
12
12
|
from howler.common.swagger import generate_swagger_docs
|
|
13
13
|
from howler.datastore.exceptions import SearchException
|
|
14
14
|
from howler.helper.search import get_collection, has_access_control
|
|
15
|
+
from howler.odm.models.user import User
|
|
15
16
|
from howler.security import api_login
|
|
16
17
|
from howler.services import hit_service, lucene_service, search_service
|
|
17
18
|
|
|
@@ -51,7 +52,7 @@ def generate_params(request: Request, fields: list[str], multi_fields: list[str]
|
|
|
51
52
|
@generate_swagger_docs()
|
|
52
53
|
@search_api.route("/<indexes>", methods=["GET", "POST"])
|
|
53
54
|
@api_login(required_priv=["R"])
|
|
54
|
-
def search(indexes: str, **kwargs):
|
|
55
|
+
def search(indexes: str, user: User, **kwargs):
|
|
55
56
|
"""Search through specified index for a given query. Uses lucene search syntax for query.
|
|
56
57
|
|
|
57
58
|
Variables:
|
|
@@ -91,8 +92,6 @@ def search(indexes: str, **kwargs):
|
|
|
91
92
|
"next_deep_paging_id": "asX3f...342", # ID to pass back for the next page during deep paging
|
|
92
93
|
"items": []} # List of results
|
|
93
94
|
"""
|
|
94
|
-
user = kwargs["user"]
|
|
95
|
-
|
|
96
95
|
index_list = indexes.split(",")
|
|
97
96
|
|
|
98
97
|
fields = [
|
|
@@ -117,12 +116,6 @@ def search(indexes: str, **kwargs):
|
|
|
117
116
|
}
|
|
118
117
|
)
|
|
119
118
|
|
|
120
|
-
# NOTE: This means index searches must be either ALL access controlled or none of them havbe access control.
|
|
121
|
-
# Otherwise, the access control requirements on one index will cause the other index to return no items.
|
|
122
|
-
# This is pretty reasonable constraint, as all the relevant, searchable items support classifications.
|
|
123
|
-
if has_access_control(index_list):
|
|
124
|
-
params["access_control"] = user["access_control"]
|
|
125
|
-
|
|
126
119
|
params["sort"] = [entry for entry in params.get("sort", "").split(",") if entry] or search_service.DEFAULT_SORT
|
|
127
120
|
|
|
128
121
|
query = req_data.get("query", None)
|
|
@@ -130,7 +123,7 @@ def search(indexes: str, **kwargs):
|
|
|
130
123
|
return bad_request(err="There was no search query.")
|
|
131
124
|
|
|
132
125
|
metadata = params.pop("metadata", [])
|
|
133
|
-
result = search_service.search(indexes, query,
|
|
126
|
+
result = search_service.search(indexes, query, user=user, **params)
|
|
134
127
|
|
|
135
128
|
if metadata and any(idx in index_list for idx in ["hit"]):
|
|
136
129
|
hit_service.augment_metadata(result["items"], metadata, user)
|
|
@@ -79,6 +79,14 @@ class CaseItem(odm.Model):
|
|
|
79
79
|
type: str = odm.Enum(values=CaseItemTypes, description="Type of case item.")
|
|
80
80
|
value: str = odm.Keyword(description="String reference value for the item (ID, URL, or token).")
|
|
81
81
|
visible: bool = odm.Boolean(default=True, description="Whether the item is visible/accessible in the frontend.")
|
|
82
|
+
classification: Optional[str] = odm.Optional(
|
|
83
|
+
odm.Classification(
|
|
84
|
+
is_user_classification=False,
|
|
85
|
+
copyto="__text__",
|
|
86
|
+
default=CLASSIFICATION.UNRESTRICTED,
|
|
87
|
+
description="Classification of the related record. Automatically populated for hit and event items.",
|
|
88
|
+
)
|
|
89
|
+
)
|
|
82
90
|
|
|
83
91
|
|
|
84
92
|
@odm.model(index=True, store=True, description="Rule used to place/query data into case paths.")
|
|
@@ -12,6 +12,7 @@ from prometheus_client import Counter
|
|
|
12
12
|
from howler.common.exceptions import HowlerValueError, InvalidDataException, NotFoundException
|
|
13
13
|
from howler.common.loader import APP_NAME, datastore
|
|
14
14
|
from howler.common.logging import get_logger
|
|
15
|
+
from howler.config import CLASSIFICATION
|
|
15
16
|
from howler.datastore.exceptions import DataStoreException
|
|
16
17
|
from howler.odm.models.case import Case, CaseItem, CaseItemTypes, CaseLog, CaseRule
|
|
17
18
|
from howler.odm.models.ecs.related import Related
|
|
@@ -150,6 +151,28 @@ def delete_cases(case_ids: set[str]) -> bool:
|
|
|
150
151
|
return ds.case.delete_by_query(f"case_id:({' OR '.join(case_ids)})")
|
|
151
152
|
|
|
152
153
|
|
|
154
|
+
def filter_case_items_by_classification(_case: dict, user_classification: str):
|
|
155
|
+
"""Remove items from a case dict that exceed the user's classification.
|
|
156
|
+
|
|
157
|
+
Items without a ``classification`` value are always included. Items with a
|
|
158
|
+
classification are only included when ``CLASSIFICATION.is_accessible``
|
|
159
|
+
confirms the requesting user can see them.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
case: Raw case dict (as returned by ``as_obj=False`` datastore calls).
|
|
163
|
+
user_classification: The requesting user's maximum classification string.
|
|
164
|
+
"""
|
|
165
|
+
if "items" not in _case:
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
_case["items"] = [
|
|
169
|
+
item
|
|
170
|
+
for item in _case["items"]
|
|
171
|
+
if item.get("classification") is None
|
|
172
|
+
or CLASSIFICATION.is_accessible(user_classification, item["classification"])
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
|
|
153
176
|
def get_last_resolved_time(case: Case) -> datetime | None:
|
|
154
177
|
"""Return the timestamp of the most recent resolution of a case.
|
|
155
178
|
|
|
@@ -389,6 +412,8 @@ def append_hit(case_id: str, item: CaseItem) -> Case:
|
|
|
389
412
|
if hit is None:
|
|
390
413
|
raise NotFoundException(f"Hit {item.value} not found, cannot be added to case")
|
|
391
414
|
|
|
415
|
+
item.classification = hit.classification
|
|
416
|
+
|
|
392
417
|
_case.items.append(item)
|
|
393
418
|
|
|
394
419
|
if not ds.case.save(_case.case_id, _case):
|
|
@@ -436,6 +461,8 @@ def append_event(case_id: str, item: CaseItem) -> Case:
|
|
|
436
461
|
if event is None:
|
|
437
462
|
raise NotFoundException(f"Event {item.value} not found, cannot be added to case")
|
|
438
463
|
|
|
464
|
+
item.classification = event.classification
|
|
465
|
+
|
|
439
466
|
_case.items.append(item)
|
|
440
467
|
|
|
441
468
|
if not ds.case.save(_case.case_id, _case):
|
|
@@ -9,6 +9,9 @@ from howler.common.loader import APP_NAME, datastore
|
|
|
9
9
|
from howler.datastore.collection import parse_sort
|
|
10
10
|
from howler.datastore.exceptions import SearchException, SearchRetryException
|
|
11
11
|
from howler.datastore.types import SearchResult
|
|
12
|
+
from howler.helper.search import has_access_control
|
|
13
|
+
from howler.odm.models.user import User
|
|
14
|
+
from howler.services import case_service
|
|
12
15
|
|
|
13
16
|
DEFAULT_OFFSET = 0
|
|
14
17
|
DEFAULT_ROW_SIZE = 25
|
|
@@ -61,7 +64,7 @@ def _normalize_indexes(indexes: str | list[str]) -> str:
|
|
|
61
64
|
return ",".join(normalized_indexes)
|
|
62
65
|
|
|
63
66
|
|
|
64
|
-
def _format_items(hits: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
67
|
+
def _format_items(hits: list[dict[str, Any]], user_classification: str | None) -> list[dict[str, Any]]:
|
|
65
68
|
"""Formats Elasticsearch search hits into a standardized item format.
|
|
66
69
|
|
|
67
70
|
Extracts the _source content from each hit.
|
|
@@ -82,6 +85,9 @@ def _format_items(hits: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
|
82
85
|
if raw_index:
|
|
83
86
|
source["__index"] = raw_index.replace(f"{APP_NAME}-", "").replace("_hot", "")
|
|
84
87
|
|
|
88
|
+
if source.get("__index") == "case" and user_classification:
|
|
89
|
+
case_service.filter_case_items_by_classification(source, user_classification)
|
|
90
|
+
|
|
85
91
|
items.append(source)
|
|
86
92
|
|
|
87
93
|
return items
|
|
@@ -99,7 +105,7 @@ def search( # noqa: C901
|
|
|
99
105
|
timeout: int | None = None,
|
|
100
106
|
track_total_hits: bool = False,
|
|
101
107
|
metadata: list[str] | None = None,
|
|
102
|
-
|
|
108
|
+
user: User | None = None,
|
|
103
109
|
) -> SearchResult[dict[str, Any]]:
|
|
104
110
|
"""Search through specified index for a given query. Uses lucene search syntax for query.
|
|
105
111
|
|
|
@@ -137,8 +143,11 @@ def search( # noqa: C901
|
|
|
137
143
|
else:
|
|
138
144
|
parsed_filters = filters
|
|
139
145
|
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
# NOTE: This means index searches must be either ALL access controlled or none of them have access control.
|
|
147
|
+
# Otherwise, the access control requirements on one index will cause the other index to return no items.
|
|
148
|
+
# This is pretty reasonable constraint, as all the relevant, searchable items support classifications.
|
|
149
|
+
if user and user.access_control and has_access_control(indexes):
|
|
150
|
+
parsed_filters.append(user.access_control)
|
|
142
151
|
|
|
143
152
|
if query is None:
|
|
144
153
|
query = "id:*"
|
|
@@ -197,7 +206,7 @@ def search( # noqa: C901
|
|
|
197
206
|
"offset": int(offset),
|
|
198
207
|
"rows": len(hits),
|
|
199
208
|
"total": int(total),
|
|
200
|
-
"items": _format_items(hits),
|
|
209
|
+
"items": _format_items(hits, user.classification if user else None),
|
|
201
210
|
}
|
|
202
211
|
|
|
203
212
|
next_deep_paging_id = result.get("_scroll_id")
|
|
@@ -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.
|
|
155
|
+
version = "4.0.0.dev1141"
|
|
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
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/cronjobs/action_queue_worker.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
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/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
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/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
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/odm/models/ecs/autonomous_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/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.0.0.dev1121 → howler_api-4.0.0.dev1141}/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.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/__init__.py
RENAMED
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/comms.py
RENAMED
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/multi.py
RENAMED
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/named.py
RENAMED
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/remote/datatypes/queues/priority.py
RENAMED
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/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
|
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/howler/services/bundle_compat_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-4.0.0.dev1121 → howler_api-4.0.0.dev1141}/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
|