howler-api 2.10.0.dev167__tar.gz → 2.10.0.dev176__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-2.10.0.dev167 → howler_api-2.10.0.dev176}/PKG-INFO +1 -1
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/action.py +4 -49
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/tool.py +5 -6
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/audit.py +7 -7
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/action_service.py +49 -2
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/hit_service.py +2 -2
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/pyproject.toml +1 -1
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/README.md +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/add_label.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/add_to_bundle.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/change_field.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/demote.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/example_plugin.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/prioritization.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/promote.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/remove_from_bundle.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/remove_label.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/actions/transition.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/base.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/socket.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/analytic.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/auth.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/borealis.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/configs.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/dossier.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/help.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/hit.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/notebook.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/overview.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/search.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/template.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/user.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/utils/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/utils/etag.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/api/v1/view.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/app.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/README.md +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/classification.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/classification.yml +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/exceptions.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/hexdump.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/iprange.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/loader.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/logging/format.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/net.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/net_static.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/random_user.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/common/swagger.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/config.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/retention.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/cronjobs/rules.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/README.md +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/bulk.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/collection.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/constants.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/exceptions.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/howler_store.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/migrations/fix_process.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/operations.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/schemas.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/store.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/build.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/support/schemas.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/datastore/types.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/error.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_mitre.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_sigma_rules.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/generate_tlds.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/reindex_data.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/external/wipe_databases.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/gunicorn_config.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/healthz.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/azure.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/discover.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/hit.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/oauth.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/search.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/workflow.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/helper/ws.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/README.md +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/base.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/charter.txt +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/helper.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/howler_enum.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/action.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/analytic.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/assemblyline.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/aws.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/azure.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/cbs.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/config.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/dossier.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/agent.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/autonomous_system.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/client.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/cloud.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/code_signature.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/container.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/dns.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/egress.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/elf.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/email.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/error.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/event.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/faas.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/file.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/geo.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/group.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/hash.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/host.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/http.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/ingress.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/interface.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/network.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/observer.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/organization.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/os.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/pe.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/process.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/registry.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/related.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/rule.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/server.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/threat.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/tls.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/url.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/user.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/user_agent.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/vulnerability.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/gcp.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/hit.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/howler_data.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/lead.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/localized_label.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/overview.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/pivot.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/template.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/user.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/view.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/random_data.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/randomizer.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/patched.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/plugins/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/plugins/config.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/README.md +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/counters.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/events.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/hash.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/lock.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/comms.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/multi.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/named.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/priority.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/set.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/user_quota_tracker.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/socket.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/security/utils.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/analytic_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/auth_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/config_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/dossier_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/event_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/jwt_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/lucene_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/notebook_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/services/user_service.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/__init__.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/annotations.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/chunk.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/dict_utils.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/isotime.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/list_utils.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/lucene.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/path.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/socket_utils.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/str_utils.py +0 -0
- {howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/utils/uid.py +0 -0
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Any, Optional
|
|
3
2
|
|
|
4
3
|
from flask import Response, request
|
|
5
4
|
|
|
6
5
|
import howler.actions as actions
|
|
7
|
-
from howler.api import
|
|
8
|
-
bad_request,
|
|
9
|
-
created,
|
|
10
|
-
forbidden,
|
|
11
|
-
internal_error,
|
|
12
|
-
make_subapi_blueprint,
|
|
13
|
-
no_content,
|
|
14
|
-
not_found,
|
|
15
|
-
ok,
|
|
16
|
-
)
|
|
6
|
+
from howler.api import bad_request, created, forbidden, internal_error, make_subapi_blueprint, no_content, not_found, ok
|
|
17
7
|
from howler.common.exceptions import HowlerException
|
|
18
8
|
from howler.common.loader import datastore
|
|
19
9
|
from howler.common.logging.audit import audit
|
|
@@ -22,7 +12,7 @@ from howler.config import CLASSIFICATION
|
|
|
22
12
|
from howler.odm.models.action import Action
|
|
23
13
|
from howler.odm.models.user import User
|
|
24
14
|
from howler.security import api_login
|
|
25
|
-
from howler.services
|
|
15
|
+
from howler.services import action_service
|
|
26
16
|
|
|
27
17
|
SUB_API = "action"
|
|
28
18
|
classification_definition = CLASSIFICATION.get_parsed_classification_definition()
|
|
@@ -51,41 +41,6 @@ def get_actions(**_) -> Response:
|
|
|
51
41
|
return ok(datastore().action.search("*:*", as_obj=False)["items"])
|
|
52
42
|
|
|
53
43
|
|
|
54
|
-
def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
|
|
55
|
-
"""Validate a new action"""
|
|
56
|
-
if not isinstance(new_action, dict):
|
|
57
|
-
return bad_request(err="Incorrect data structure!")
|
|
58
|
-
|
|
59
|
-
if "name" not in new_action:
|
|
60
|
-
return bad_request(err="You must specify a name.")
|
|
61
|
-
elif not new_action["name"]:
|
|
62
|
-
return bad_request(err="Name cannot be empty.")
|
|
63
|
-
|
|
64
|
-
if "query" not in new_action:
|
|
65
|
-
return bad_request(err="You must specify a query.")
|
|
66
|
-
elif not new_action["query"]:
|
|
67
|
-
return bad_request(err="Query cannot be empty.")
|
|
68
|
-
|
|
69
|
-
operations = new_action.get("operations", None)
|
|
70
|
-
if operations is None:
|
|
71
|
-
return bad_request(err="You must specify a list of operations.")
|
|
72
|
-
|
|
73
|
-
if not isinstance(operations, list):
|
|
74
|
-
return bad_request(err="'operations' must be a list of operations.")
|
|
75
|
-
|
|
76
|
-
if len(operations) < 1:
|
|
77
|
-
return bad_request(err="You must specify at least one operation.")
|
|
78
|
-
|
|
79
|
-
operation_ids = [o["operation_id"] for o in operations]
|
|
80
|
-
if len(operation_ids) != len(set(operation_ids)):
|
|
81
|
-
return bad_request(err="You must have a maximum of one operation of each type in the action.")
|
|
82
|
-
|
|
83
|
-
if set(new_action.get("triggers", [])) - set(VALID_TRIGGERS):
|
|
84
|
-
return bad_request(err="Invalid trigger provided.")
|
|
85
|
-
|
|
86
|
-
return None
|
|
87
|
-
|
|
88
|
-
|
|
89
44
|
@generate_swagger_docs()
|
|
90
45
|
@action_api.route("/", methods=["POST"])
|
|
91
46
|
@api_login(audit=False, check_xsrf_token=False, required_type=["automation_basic"])
|
|
@@ -120,7 +75,7 @@ def add_action(user: User, **_) -> Response:
|
|
|
120
75
|
if new_action is None:
|
|
121
76
|
return bad_request(err="You must specify an action")
|
|
122
77
|
|
|
123
|
-
if error := validate_action(new_action):
|
|
78
|
+
if error := action_service.validate_action(new_action):
|
|
124
79
|
return error
|
|
125
80
|
|
|
126
81
|
try:
|
|
@@ -192,7 +147,7 @@ def update_action(id: str, user: User, **_) -> Response:
|
|
|
192
147
|
"action_id": existing_action["action_id"],
|
|
193
148
|
}
|
|
194
149
|
|
|
195
|
-
if error := validate_action(updated_action):
|
|
150
|
+
if error := action_service.validate_action(updated_action):
|
|
196
151
|
return error
|
|
197
152
|
|
|
198
153
|
try:
|
|
@@ -22,8 +22,6 @@ SUB_API = "tools"
|
|
|
22
22
|
tool_api = make_subapi_blueprint(SUB_API, api_version=1)
|
|
23
23
|
tool_api._doc = "Manage the tools"
|
|
24
24
|
|
|
25
|
-
FIELDS = Hit.flat_fields()
|
|
26
|
-
|
|
27
25
|
logger = get_logger(__file__)
|
|
28
26
|
|
|
29
27
|
hit_helper = OdmHelper(Hit)
|
|
@@ -78,6 +76,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
|
|
|
78
76
|
return bad_request(err="Invalid: 'hits' field is missing or invalid.")
|
|
79
77
|
warnings = []
|
|
80
78
|
# Validate field_map targets
|
|
79
|
+
hit_fields = Hit.flat_fields()
|
|
81
80
|
for targets in field_map.values():
|
|
82
81
|
for target in targets:
|
|
83
82
|
# This is checking to see if the target matches one of two cases:
|
|
@@ -85,7 +84,7 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
|
|
|
85
84
|
# Compound fields - hit.obj of type dict (should also match)
|
|
86
85
|
# This allows significantly easier creation of hits, since you don't need to deconstruct every dict into
|
|
87
86
|
# individual fields
|
|
88
|
-
if target not in
|
|
87
|
+
if target not in hit_fields and not any(f for f in hit_fields.keys() if get_parent_key(f) == target):
|
|
89
88
|
warning = f"Invalid target field in the map: {target}"
|
|
90
89
|
if ignore_extra_values:
|
|
91
90
|
warnings.append(warning)
|
|
@@ -114,11 +113,11 @@ def create_one_or_many_hits(tool_name: str, user: User, **kwargs): # noqa: C901
|
|
|
114
113
|
for target in targets:
|
|
115
114
|
_val = val
|
|
116
115
|
try:
|
|
117
|
-
field_data: Optional[_Field] =
|
|
116
|
+
field_data: Optional[_Field] = hit_fields[target]
|
|
118
117
|
except KeyError:
|
|
119
|
-
logger.debug(f"`{target}` not in
|
|
118
|
+
logger.debug(f"`{target}` not in hit fields")
|
|
120
119
|
field_data = next(
|
|
121
|
-
(v for k, v in
|
|
120
|
+
(v for k, v in hit_fields.items() if get_parent_key(k) == target),
|
|
122
121
|
None,
|
|
123
122
|
)
|
|
124
123
|
|
|
@@ -4,12 +4,7 @@ import sys
|
|
|
4
4
|
|
|
5
5
|
from flask import request
|
|
6
6
|
|
|
7
|
-
from howler.common.logging.format import
|
|
8
|
-
HWL_AUDIT_FORMAT,
|
|
9
|
-
HWL_DATE_FORMAT,
|
|
10
|
-
HWL_ISO_DATE_FORMAT,
|
|
11
|
-
HWL_LOG_FORMAT,
|
|
12
|
-
)
|
|
7
|
+
from howler.common.logging.format import HWL_AUDIT_FORMAT, HWL_DATE_FORMAT, HWL_ISO_DATE_FORMAT, HWL_LOG_FORMAT
|
|
13
8
|
from howler.config import DEBUG, config
|
|
14
9
|
|
|
15
10
|
AUDIT = config.ui.audit
|
|
@@ -94,10 +89,15 @@ def audit(args, kwargs, logged_in_uname, user, func, impersonator=None):
|
|
|
94
89
|
except Exception:
|
|
95
90
|
json_blob = {}
|
|
96
91
|
|
|
92
|
+
try:
|
|
93
|
+
req_args = ["%s='%s'" % (k, v) for k, v in request.args.items() if k in AUDIT_KW_TARGET]
|
|
94
|
+
except RuntimeError:
|
|
95
|
+
req_args = []
|
|
96
|
+
|
|
97
97
|
params_list = (
|
|
98
98
|
list(args)
|
|
99
99
|
+ ["%s='%s'" % (k, v) for k, v in kwargs.items() if k in AUDIT_KW_TARGET]
|
|
100
|
-
+
|
|
100
|
+
+ req_args
|
|
101
101
|
+ ["%s='%s'" % (k, v) for k, v in json_blob.items() if k in AUDIT_KW_TARGET]
|
|
102
102
|
)
|
|
103
103
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
|
-
|
|
2
|
+
import sys
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from flask import Response
|
|
3
6
|
|
|
4
7
|
from howler import actions
|
|
8
|
+
from howler.api import bad_request
|
|
5
9
|
from howler.common.exceptions import HowlerValueError
|
|
6
10
|
from howler.common.loader import datastore
|
|
7
11
|
from howler.common.logging import get_logger
|
|
@@ -13,6 +17,41 @@ from howler.utils.str_utils import sanitize_lucene_query
|
|
|
13
17
|
logger = get_logger(__file__)
|
|
14
18
|
|
|
15
19
|
|
|
20
|
+
def validate_action(new_action: Any) -> Optional[Response]: # noqa: C901
|
|
21
|
+
"""Validate a new action"""
|
|
22
|
+
if not isinstance(new_action, dict):
|
|
23
|
+
return bad_request(err="Incorrect data structure!")
|
|
24
|
+
|
|
25
|
+
if "name" not in new_action:
|
|
26
|
+
return bad_request(err="You must specify a name.")
|
|
27
|
+
elif not new_action["name"]:
|
|
28
|
+
return bad_request(err="Name cannot be empty.")
|
|
29
|
+
|
|
30
|
+
if "query" not in new_action:
|
|
31
|
+
return bad_request(err="You must specify a query.")
|
|
32
|
+
elif not new_action["query"]:
|
|
33
|
+
return bad_request(err="Query cannot be empty.")
|
|
34
|
+
|
|
35
|
+
operations = new_action.get("operations", None)
|
|
36
|
+
if operations is None:
|
|
37
|
+
return bad_request(err="You must specify a list of operations.")
|
|
38
|
+
|
|
39
|
+
if not isinstance(operations, list):
|
|
40
|
+
return bad_request(err="'operations' must be a list of operations.")
|
|
41
|
+
|
|
42
|
+
if len(operations) < 1:
|
|
43
|
+
return bad_request(err="You must specify at least one operation.")
|
|
44
|
+
|
|
45
|
+
operation_ids = [o["operation_id"] for o in operations]
|
|
46
|
+
if len(operation_ids) != len(set(operation_ids)):
|
|
47
|
+
return bad_request(err="You must have a maximum of one operation of each type in the action.")
|
|
48
|
+
|
|
49
|
+
if set(new_action.get("triggers", [])) - set(VALID_TRIGGERS):
|
|
50
|
+
return bad_request(err="Invalid trigger provided.")
|
|
51
|
+
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
16
55
|
def bulk_execute_on_query(query: str, trigger: str = "create", user: Optional[User] = None):
|
|
17
56
|
"""Execute the operations specified in registered actions on the given query"""
|
|
18
57
|
storage = datastore()
|
|
@@ -20,11 +59,19 @@ def bulk_execute_on_query(query: str, trigger: str = "create", user: Optional[Us
|
|
|
20
59
|
if trigger not in VALID_TRIGGERS:
|
|
21
60
|
raise HowlerValueError(f"{trigger} is not a valid trigger. It must be one of {','.join(VALID_TRIGGERS)}")
|
|
22
61
|
|
|
23
|
-
on_trigger_actions: list[Action] = storage.action.search(f"triggers:{sanitize_lucene_query(trigger)}")[
|
|
62
|
+
on_trigger_actions: list[Action] = storage.action.search(f"triggers:{sanitize_lucene_query(trigger)}", rows=10000)[
|
|
63
|
+
"items"
|
|
64
|
+
]
|
|
24
65
|
|
|
25
66
|
for action in on_trigger_actions:
|
|
26
67
|
intersected_query = f"({query}) AND ({action.query})"
|
|
27
68
|
|
|
69
|
+
if datastore().hit.search(intersected_query, rows=0)["total"] < 1:
|
|
70
|
+
if "pytest" in sys.modules:
|
|
71
|
+
logger.debug("Action %s does not apply to query %s", action.action_id, query)
|
|
72
|
+
|
|
73
|
+
continue
|
|
74
|
+
|
|
28
75
|
logger.info("Running action %s on bulk query %s", action.action_id, query)
|
|
29
76
|
for operation in action.operations:
|
|
30
77
|
if operation.operation_id == "example_plugin":
|
|
@@ -555,9 +555,9 @@ def transition_hit(
|
|
|
555
555
|
trigger: Union[Literal["promote"], Literal["demote"]]
|
|
556
556
|
|
|
557
557
|
if transition == HitStatusTransition.ASSESS:
|
|
558
|
-
|
|
558
|
+
new_escalation = AssessmentEscalationMap[kwargs["assessment"]]
|
|
559
559
|
|
|
560
|
-
if
|
|
560
|
+
if new_escalation == Escalation.EVIDENCE:
|
|
561
561
|
trigger = "promote"
|
|
562
562
|
else:
|
|
563
563
|
trigger = "demote"
|
|
@@ -148,7 +148,7 @@ suppress-none-returning = true
|
|
|
148
148
|
[tool.poetry]
|
|
149
149
|
package-mode = true
|
|
150
150
|
name = "howler-api"
|
|
151
|
-
version = "2.10.0.
|
|
151
|
+
version = "2.10.0.dev176"
|
|
152
152
|
description = "Howler - API server"
|
|
153
153
|
authors = [
|
|
154
154
|
"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
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/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
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/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
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/odm/models/ecs/autonomous_system.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/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-2.10.0.dev167 → howler_api-2.10.0.dev176}/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
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/__init__.py
RENAMED
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/comms.py
RENAMED
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/multi.py
RENAMED
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/named.py
RENAMED
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/howler/remote/datatypes/queues/priority.py
RENAMED
|
File without changes
|
|
File without changes
|
{howler_api-2.10.0.dev167 → howler_api-2.10.0.dev176}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|