howler-api 4.1.0.dev1433__tar.gz → 4.1.0.dev1436__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.dev1433 → howler_api-4.1.0.dev1436}/PKG-INFO +1 -1
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/utils/params.py +13 -8
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/base.py +92 -20
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/case.py +10 -2
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/howler_data.py +8 -1
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/record.py +11 -3
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/pyproject.toml +1 -1
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/add_label.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/add_to_bundle.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/add_to_case.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/change_field.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/demote.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/example_plugin.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/prioritization.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/promote.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/remove_from_bundle.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/remove_label.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/actions/transition.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/base.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/socket.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/action.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/analytic.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/auth.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/clue.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/configs.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/dossier.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/help.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/hit.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/notebook.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/overview.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/search.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/template.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/tool.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/user.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/utils/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/utils/etag.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v1/view.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v2/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v2/case.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v2/fuzzy.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v2/ingest.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/api/v2/search.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/app.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/classification.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/classification.yml +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/exceptions.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/loader.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/logging/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/logging/audit.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/logging/format.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/net.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/net_static.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/random_user.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/common/swagger.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/config.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/cronjobs/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/cronjobs/action_queue_worker.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/cronjobs/correlation.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/cronjobs/retention.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/cronjobs/view_cleanup.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/bulk.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/collection.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/constants.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/exceptions.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/howler_store.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/migrations/fix_process.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/operations.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/schemas.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/store.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/support/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/support/build.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/support/schemas.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/types.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/datastore/utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/error.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/check_duplicates.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/generate_mitre.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/generate_sigma_rules.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/generate_tlds.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/reindex_data.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/external/wipe_databases.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/gunicorn_config.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/healthz.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/azure.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/discover.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/hit.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/oauth.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/search.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/workflow.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/helper/ws.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/charter.txt +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/constants.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/helper.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/howler_enum.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/mixins.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/action.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/analytic.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/assemblyline.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/aws.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/azure.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/cbs.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/clue.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/config.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/dossier.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/agent.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/autonomous_system.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/client.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/cloud.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/code_signature.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/container.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/dns.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/egress.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/elf.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/email.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/error.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/event.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/faas.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/file.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/geo.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/group.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/hash.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/host.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/http.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/ingress.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/interface.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/network.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/observer.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/organization.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/os.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/pe.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/process.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/registry.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/related.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/rule.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/server.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/threat.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/tls.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/url.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/user.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/user_agent.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/vulnerability.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/event.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/gcp.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/hit.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/lead.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/localized_label.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/overview.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/pivot.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/template.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/user.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/view.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/random_data.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/randomizer.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/patched.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/plugins/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/plugins/config.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/README.md +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/counters.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/events.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/hash.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/lock.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/queues/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/queues/comms.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/queues/multi.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/queues/named.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/queues/priority.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/set.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/remote/datatypes/user_quota_tracker.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/security/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/security/socket.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/security/utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/action_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/analytic_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/auth_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/bundle_compat_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/case_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/comms_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/config_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/correlation_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/docs_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/dossier_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/event_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/fuzzy_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/hit_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/jwt_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/lucene_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/notebook_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/overview_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/search_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/template_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/user_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/services/viewer_service.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/telemetry.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/__init__.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/annotations.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/chunk.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/compat.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/constants.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/dict_utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/indexes.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/isotime.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/list_utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/lucene.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/net_utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/path.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/socket_utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/str_utils.py +0 -0
- {howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/utils/uid.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Parameter parsing and error handling reused across multiple endpoints."""
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
|
-
from typing import Callable, Literal
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
5
|
|
|
6
6
|
from flask import request
|
|
7
7
|
|
|
@@ -10,8 +10,10 @@ from howler.common.exceptions import HowlerInvalidParameterException
|
|
|
10
10
|
|
|
11
11
|
REFRESH_ARG_OPTIONS = ["true", "false", "wait_for"]
|
|
12
12
|
|
|
13
|
+
parser_t = Callable[[str | None], Any]
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
def parse_parameters(**requested_params: parser_t | Literal["required"] | tuple[parser_t, Literal["required"]] | None):
|
|
15
17
|
"""A decorator to parse required parameters from the request args.
|
|
16
18
|
|
|
17
19
|
Usage:
|
|
@@ -32,6 +34,9 @@ def parse_parameters(**requested_params: Callable[[str | None], str | None] | Li
|
|
|
32
34
|
and the raw string value from the request args will be passed to the endpoint function.
|
|
33
35
|
Alternatively, if the parameter is required but does not need parsing,
|
|
34
36
|
pass "required" as the value for the parameter.
|
|
37
|
+
|
|
38
|
+
Parser functions which normally accept None can also be marked as required
|
|
39
|
+
by passing a tuple of (parser_func, "required") as the value for the parameter.
|
|
35
40
|
"""
|
|
36
41
|
|
|
37
42
|
def decorator(func):
|
|
@@ -40,17 +45,17 @@ def parse_parameters(**requested_params: Callable[[str | None], str | None] | Li
|
|
|
40
45
|
def wrapper(*args, **kwargs):
|
|
41
46
|
try:
|
|
42
47
|
for param_name, parser in requested_params.items():
|
|
48
|
+
required_flag = None
|
|
49
|
+
if isinstance(parser, tuple):
|
|
50
|
+
parser, required_flag = parser
|
|
51
|
+
|
|
43
52
|
raw_value = request.args.get(param_name, None)
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
if parser == "required":
|
|
54
|
+
if parser == "required" or required_flag == "required":
|
|
47
55
|
if raw_value is None:
|
|
48
56
|
return bad_request(err=f"Missing required parameter: [{param_name}]")
|
|
49
|
-
parsed_value = raw_value
|
|
50
|
-
else:
|
|
51
|
-
parsed_value = parser(raw_value) if parser else raw_value
|
|
52
57
|
|
|
53
|
-
kwargs[param_name] =
|
|
58
|
+
kwargs[param_name] = parser(raw_value) if callable(parser) else raw_value
|
|
54
59
|
|
|
55
60
|
except HowlerInvalidParameterException as e:
|
|
56
61
|
return bad_request(err=e.message)
|
|
@@ -11,14 +11,16 @@ independent data models in python. This gives us:
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
import base64
|
|
14
15
|
import copy
|
|
15
16
|
import json
|
|
16
17
|
import re
|
|
17
18
|
import typing
|
|
18
|
-
from datetime import datetime
|
|
19
|
+
from datetime import datetime, timezone
|
|
19
20
|
from enum import Enum as PyEnum
|
|
20
21
|
from enum import EnumMeta
|
|
21
|
-
from
|
|
22
|
+
from ipaddress import ip_address
|
|
23
|
+
from typing import TYPE_CHECKING, Callable, Literal
|
|
22
24
|
from typing import Any as _Any
|
|
23
25
|
from venv import logger
|
|
24
26
|
|
|
@@ -125,6 +127,7 @@ class _Field:
|
|
|
125
127
|
reference=None,
|
|
126
128
|
optional=False,
|
|
127
129
|
deprecated=False,
|
|
130
|
+
sync=True,
|
|
128
131
|
):
|
|
129
132
|
self.index = index
|
|
130
133
|
self.store = store
|
|
@@ -134,6 +137,7 @@ class _Field:
|
|
|
134
137
|
self.copyto.append(copyto)
|
|
135
138
|
elif copyto:
|
|
136
139
|
self.copyto.extend(copyto)
|
|
140
|
+
self.sync = sync
|
|
137
141
|
|
|
138
142
|
self.name = name
|
|
139
143
|
self.parent_name = None
|
|
@@ -1427,34 +1431,36 @@ class Model:
|
|
|
1427
1431
|
# attribute assignment
|
|
1428
1432
|
self.__frozen = True
|
|
1429
1433
|
|
|
1430
|
-
def as_primitives(
|
|
1434
|
+
def as_primitives(
|
|
1435
|
+
self,
|
|
1436
|
+
hidden_fields=False,
|
|
1437
|
+
strip_null=True,
|
|
1438
|
+
ip_format: Literal["str", "int", "encoded_bytes"] | None = None,
|
|
1439
|
+
timestamp_format: Literal["iso", "posix"] | None = None,
|
|
1440
|
+
) -> dict[str, typing.Any]:
|
|
1431
1441
|
"""Convert the object back into primitives that can be json serialized."""
|
|
1432
1442
|
out = {}
|
|
1433
1443
|
|
|
1434
1444
|
fields = self.fields()
|
|
1435
1445
|
for key, value in self._odm_py_obj.items():
|
|
1436
1446
|
field_type = fields.get(key, Any)
|
|
1447
|
+
if isinstance(field_type, Optional):
|
|
1448
|
+
field_type = field_type.child_type
|
|
1449
|
+
|
|
1437
1450
|
if value is not None or (value is None and field_type.default_set):
|
|
1438
1451
|
if strip_null and value is None:
|
|
1439
1452
|
continue
|
|
1440
1453
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
out[key] = [(v.as_primitives(strip_null=strip_null) if isinstance(v, Model) else v) for v in value]
|
|
1452
|
-
elif isinstance(value, ClassificationObject):
|
|
1453
|
-
out[key] = str(value)
|
|
1454
|
-
if hidden_fields:
|
|
1455
|
-
out.update(value.get_access_control_parts())
|
|
1456
|
-
else:
|
|
1457
|
-
out[key] = value
|
|
1454
|
+
out[key] = self._as_primitive(
|
|
1455
|
+
value,
|
|
1456
|
+
field_type,
|
|
1457
|
+
strip_null=strip_null,
|
|
1458
|
+
ip_format=ip_format,
|
|
1459
|
+
timestamp_format=timestamp_format,
|
|
1460
|
+
)
|
|
1461
|
+
|
|
1462
|
+
if hidden_fields and isinstance(value, ClassificationObject):
|
|
1463
|
+
out.update(value.get_access_control_parts())
|
|
1458
1464
|
return out
|
|
1459
1465
|
|
|
1460
1466
|
def json(self):
|
|
@@ -1520,6 +1526,72 @@ class Model:
|
|
|
1520
1526
|
def __contains__(self, name):
|
|
1521
1527
|
return name.rstrip("_") in self.fields()
|
|
1522
1528
|
|
|
1529
|
+
@staticmethod
|
|
1530
|
+
def _as_primitive(value, field_type, strip_null=True, ip_format=None, timestamp_format=None):
|
|
1531
|
+
if isinstance(value, Model):
|
|
1532
|
+
return value.as_primitives(strip_null=strip_null, ip_format=ip_format, timestamp_format=timestamp_format)
|
|
1533
|
+
|
|
1534
|
+
if isinstance(value, datetime):
|
|
1535
|
+
if timestamp_format == "iso":
|
|
1536
|
+
return value.isoformat()
|
|
1537
|
+
|
|
1538
|
+
if timestamp_format == "posix":
|
|
1539
|
+
return int(value.timestamp())
|
|
1540
|
+
|
|
1541
|
+
if value.tzinfo is not None:
|
|
1542
|
+
value = value.astimezone(timezone.utc)
|
|
1543
|
+
return value.strftime(DATEFORMAT)
|
|
1544
|
+
|
|
1545
|
+
if value is not None and isinstance(field_type, IP):
|
|
1546
|
+
if ip_format == "encoded_bytes":
|
|
1547
|
+
ip_bytes = ip_address(value).packed
|
|
1548
|
+
return base64.b64encode(ip_bytes).decode("utf-8")
|
|
1549
|
+
|
|
1550
|
+
if ip_format == "int":
|
|
1551
|
+
return int(ip_address(value))
|
|
1552
|
+
|
|
1553
|
+
if ip_format == "str":
|
|
1554
|
+
return str(ip_address(value))
|
|
1555
|
+
|
|
1556
|
+
return value
|
|
1557
|
+
|
|
1558
|
+
if isinstance(value, TypedMapping):
|
|
1559
|
+
return {
|
|
1560
|
+
k: (
|
|
1561
|
+
v.as_primitives(strip_null=strip_null, ip_format=ip_format, timestamp_format=timestamp_format)
|
|
1562
|
+
if isinstance(v, Model)
|
|
1563
|
+
else Model._as_primitive(
|
|
1564
|
+
v,
|
|
1565
|
+
value.type,
|
|
1566
|
+
strip_null=strip_null,
|
|
1567
|
+
ip_format=ip_format,
|
|
1568
|
+
timestamp_format=timestamp_format,
|
|
1569
|
+
)
|
|
1570
|
+
)
|
|
1571
|
+
for k, v in value.items()
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
if isinstance(value, TypedList):
|
|
1575
|
+
return [
|
|
1576
|
+
(
|
|
1577
|
+
v.as_primitives(strip_null=strip_null, ip_format=ip_format, timestamp_format=timestamp_format)
|
|
1578
|
+
if isinstance(v, Model)
|
|
1579
|
+
else Model._as_primitive(
|
|
1580
|
+
v,
|
|
1581
|
+
value.type,
|
|
1582
|
+
strip_null=strip_null,
|
|
1583
|
+
ip_format=ip_format,
|
|
1584
|
+
timestamp_format=timestamp_format,
|
|
1585
|
+
)
|
|
1586
|
+
)
|
|
1587
|
+
for v in value
|
|
1588
|
+
]
|
|
1589
|
+
|
|
1590
|
+
if isinstance(value, ClassificationObject):
|
|
1591
|
+
return str(value)
|
|
1592
|
+
|
|
1593
|
+
return value
|
|
1594
|
+
|
|
1523
1595
|
|
|
1524
1596
|
def recursive_set_name(field, name, to_parent=False):
|
|
1525
1597
|
if not to_parent:
|
|
@@ -257,8 +257,16 @@ class Case(DatastoreMixin["Case"], odm.Model):
|
|
|
257
257
|
)
|
|
258
258
|
)
|
|
259
259
|
|
|
260
|
-
def as_primitives(
|
|
261
|
-
|
|
260
|
+
def as_primitives(
|
|
261
|
+
self,
|
|
262
|
+
hidden_fields=False,
|
|
263
|
+
strip_null=True,
|
|
264
|
+
ip_format: Literal["int", "str", "encoded_bytes"] | None = None,
|
|
265
|
+
timestamp_format: Literal["iso", "posix"] | None = None,
|
|
266
|
+
) -> dict[str, Any]:
|
|
267
|
+
result = super().as_primitives(
|
|
268
|
+
hidden_fields, strip_null, ip_format=ip_format, timestamp_format=timestamp_format
|
|
269
|
+
)
|
|
262
270
|
|
|
263
271
|
result["__index"] = self.__class__.__name__.lower()
|
|
264
272
|
|
|
@@ -185,11 +185,13 @@ class HowlerData(odm.Model):
|
|
|
185
185
|
odm.Keyword(description="Raw telemetry records associated with this hit."),
|
|
186
186
|
default=[],
|
|
187
187
|
store=False,
|
|
188
|
+
sync=False,
|
|
188
189
|
)
|
|
189
190
|
links: list[Link] = odm.List(
|
|
190
191
|
odm.Compound(Link),
|
|
191
192
|
default=[],
|
|
192
193
|
description="A list of links associated with this hit.",
|
|
194
|
+
sync=False,
|
|
193
195
|
)
|
|
194
196
|
detection: str | None = odm.Optional(
|
|
195
197
|
odm.CaseInsensitiveKeyword(description="The detection that produced this hit.")
|
|
@@ -248,11 +250,13 @@ class HowlerData(odm.Model):
|
|
|
248
250
|
odm.Compound(Comment),
|
|
249
251
|
default=[],
|
|
250
252
|
description="A list of comments with timestamps and attribution.",
|
|
253
|
+
sync=False,
|
|
251
254
|
)
|
|
252
255
|
log: list[Log] = odm.List(
|
|
253
256
|
odm.Compound(Log),
|
|
254
257
|
default=[],
|
|
255
258
|
description="A list of changes to the hit with timestamps and attribution.",
|
|
259
|
+
sync=False,
|
|
256
260
|
)
|
|
257
261
|
monitored: str | None = odm.Optional(odm.Keyword(description="Link to the incident monitoring dashboard."))
|
|
258
262
|
reported: str | None = odm.Optional(odm.Keyword(description="Link to the incident report."))
|
|
@@ -272,5 +276,8 @@ class HowlerData(odm.Model):
|
|
|
272
276
|
description="Votes relating to the hit",
|
|
273
277
|
)
|
|
274
278
|
dossier: list[Lead] = odm.List(
|
|
275
|
-
odm.Compound(Lead),
|
|
279
|
+
odm.Compound(Lead),
|
|
280
|
+
default=[],
|
|
281
|
+
description="A list of leads forming the dossier associated with this hit",
|
|
282
|
+
sync=False,
|
|
276
283
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# mypy: ignore-errors
|
|
2
|
-
from typing import Any, Optional
|
|
2
|
+
from typing import Any, Literal, Optional
|
|
3
3
|
|
|
4
4
|
from howler import odm
|
|
5
5
|
from howler.common.logging import get_logger
|
|
@@ -342,8 +342,16 @@ class Record(odm.Model):
|
|
|
342
342
|
)
|
|
343
343
|
)
|
|
344
344
|
|
|
345
|
-
def as_primitives(
|
|
346
|
-
|
|
345
|
+
def as_primitives(
|
|
346
|
+
self,
|
|
347
|
+
hidden_fields=False,
|
|
348
|
+
strip_null=True,
|
|
349
|
+
ip_format: Literal["int", "str", "encoded_bytes"] | None = None,
|
|
350
|
+
timestamp_format: Literal["iso", "posix"] | None = None,
|
|
351
|
+
) -> dict[str, Any]:
|
|
352
|
+
result = super().as_primitives(
|
|
353
|
+
hidden_fields, strip_null, ip_format=ip_format, timestamp_format=timestamp_format
|
|
354
|
+
)
|
|
347
355
|
|
|
348
356
|
result["__index"] = self.__class__.__name__.lower()
|
|
349
357
|
|
|
@@ -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.dev1436"
|
|
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
|
{howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/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.1.0.dev1433 → howler_api-4.1.0.dev1436}/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.dev1433 → howler_api-4.1.0.dev1436}/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
|
{howler_api-4.1.0.dev1433 → howler_api-4.1.0.dev1436}/howler/odm/models/ecs/autonomous_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|