From cf208858c92b28d93e7a888b51b42ad250ddd31d Mon Sep 17 00:00:00 2001 From: F3licity Date: Thu, 10 Oct 2024 13:13:22 +0200 Subject: [PATCH 01/25] update readme (#3648) --- README.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index b2e72696f9a..071500f3eac 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ What is OpenKAT? ================ -OpenKAT aims to monitor, record and analyze the status of information systems. The basic premise is that many of the major security incidents are caused by small errors and known vulnerabilities, and that if you can find them in time your systems and infrastructure become a lot more secure. +OpenKAT aims to monitor, record and analyze the status of information systems. The basic premise is that many of the major security incidents are caused by small errors and known vulnerabilities, and if you find them and resolve them in time your systems and infrastructure become a lot more secure. OpenKAT scans, collects, analyzes and reports in an ongoing process: @@ -11,7 +11,7 @@ OpenKAT scans, collects, analyzes and reports in an ongoing process: OpenKAT scans networks, finds vulnerabilities and creates accessible reports. It integrates the most widely used network tools and scanning software into a modular framework, accesses external databases such as shodan, and combines the information from all these sources into clear reports. It also includes lots of cat hair. -OpenKAT is useful if you want to monitor a complex system and want to know whether it contains known vulnerabilities or configuration errors. Due to its modular structure and extensibility, OpenKAT can be applied in a multitude of situations. You can customize it and put it to your own use. +OpenKAT is useful if you want to monitor a complex system and know whether it contains known vulnerabilities or configuration errors. Due to its modular structure and extensibility, OpenKAT can be applied in different situations. You can customize it and put it to your own use. Documentation ============= @@ -62,7 +62,7 @@ The tools addressed by OpenKAT may have their own license, from the OS/S domain Contact ======= -There several options to contact the OpenKAT team: +There are several options to contact the OpenKAT team: - Direct contact: meedoen@openkat.nl - `Github Discussions `_ @@ -73,10 +73,10 @@ There several options to contact the OpenKAT team: Privacy ======= -OpenKAT is not designed to collect private information and it does not act on any private information that its finds. Some information considered to be personally identifying information might be collected through one or more of OpenKAT's plugins and subsequently stored, but only if that information was accessible to OpenKAT. E.g. a phone number or email address listed on a website might end up being collected as part of OpenKAT normal data collection. This data might then be stored for a long time because OpenKAT stores 'proofs' of its actions. No email or phone number models are present and as such they won't be processed into objects by OpenKAT. -An OpenKAT installation requires user accounts for users to be able to login. These accounts (and all data OpenKAT works with) are stored only on the OpenKAT installation itself and are not shared with other parties or outside of your OpenKAT install. +OpenKAT is not designed to collect private information and it does not act on any private information that it finds. Some information considered to be personally identifiable information, may be collected through one or more of OpenKAT's plugins and subsequently stored, but only if that information has been accessible to OpenKAT. For example, a phone number or email address listed on a website might end up being collected as part of OpenKAT normal data collection. These data might then be stored for a long period of time, because OpenKAT stores evidence of its actions. No email or phone number models are present and as such they won't be processed into objects by OpenKAT. +An OpenKAT installation requires user accounts for users to be able to log in. These accounts (and all data OpenKAT works with) are stored only on the OpenKAT installation itself, and are not shared with any other parties or outside of your OpenKAT install. Security ======== -OpenKAT is designed to be secure by default in its production setup. In the development setup some debugging flags are enabled by default and it will not include TLS out of the box. To setup a secure production OpenKAT install, please follow the `Production setup guidelines `_ and `Hardening guidelines `_. +OpenKAT is designed to be secure by default in its production setup. In the development setup some debugging flags are enabled by default and it will not include TLS out of the box. To set up a secure production OpenKAT install, please follow the `Production setup guidelines `_ and `Hardening guidelines `_. From 137e931f07479a681d45b5cfaf9ffe07f7ae9513 Mon Sep 17 00:00:00 2001 From: Rieven Date: Thu, 10 Oct 2024 13:41:17 +0200 Subject: [PATCH 02/25] Fix sorting plugins list (#3659) Co-authored-by: Jan Klopper Co-authored-by: ammar92 --- rocky/reports/views/base.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rocky/reports/views/base.py b/rocky/reports/views/base.py index c0a6925a0d2..49507b6b1b2 100644 --- a/rocky/reports/views/base.py +++ b/rocky/reports/views/base.py @@ -650,9 +650,14 @@ def get_plugins(self, plugins_dict: dict[str, list[str]]) -> list[dict[str, list katalogus_plugins = get_katalogus(self.organization.code).get_plugins( ids=plugin_ids_required + plugin_ids_optional ) - - plugins["required"] = [plugin for plugin in katalogus_plugins if plugin.id in plugin_ids_required] - plugins["optional"] = [plugin for plugin in katalogus_plugins if plugin.id in plugin_ids_optional] + for plugin in katalogus_plugins: + if plugin.id in plugin_ids_required: + plugins["required"].append(plugin) + if plugin.id in plugin_ids_optional: + plugins["optional"].append(plugin) + + plugins["required"] = sorted(plugins["required"], key=attrgetter("enabled")) + plugins["optional"] = sorted(plugins["optional"], key=attrgetter("enabled"), reverse=True) return format_plugin_data(plugins) From e8c4604308de2a02fc2f845271f3eb6388c696aa Mon Sep 17 00:00:00 2001 From: Jan Klopper Date: Thu, 10 Oct 2024 21:22:31 +0200 Subject: [PATCH 03/25] fix the boefje id check for uuid's. A cleaner match regex would problably be better. (#3665) Co-authored-by: Jeroen Dekkers --- rocky/katalogus/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocky/katalogus/client.py b/rocky/katalogus/client.py index 52a209b6fac..02c4999409b 100644 --- a/rocky/katalogus/client.py +++ b/rocky/katalogus/client.py @@ -24,8 +24,8 @@ def valid_plugin_id(plugin_id: str) -> str: - # plugin IDs should be valid Python identifiers but may contain dots and dashes - if not plugin_id.replace("-", "").replace(".", "").isidentifier(): + # plugin IDs should alphanumeric, including dashes, underscores and dots. + if not plugin_id.replace("-", "").replace("_", "").replace(".", "").isalnum(): raise ValueError("Plugin ID is not valid") return plugin_id From 41494e5486ad0b83e3238611755d0ea5795e3c6e Mon Sep 17 00:00:00 2001 From: Madelon Dohmen <99282220+madelondohmen@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:38:52 +0200 Subject: [PATCH 04/25] Fix table in DNS Report (#3650) Co-authored-by: Jan Klopper --- rocky/reports/report_types/dns_report/report.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rocky/reports/report_types/dns_report/report.html b/rocky/reports/report_types/dns_report/report.html index 3b71879e732..9ec2fd92ab3 100644 --- a/rocky/reports/report_types/dns_report/report.html +++ b/rocky/reports/report_types/dns_report/report.html @@ -141,7 +141,7 @@

{% translate "Other findings found" %}

{{ info.finding_type.risk_severity|capfirst }} - {{ info.finding_type }} + {{ info.finding_type.id }} + + + + + + + + + + + + + + + + +
{% translate "Plugin extra info" %}
{% translate "Plugin type" %}{% translate "Plugin description" %}
+ {{ plugin.type|title }} + {{ plugin.description }}
+ + + {% endfor %} + + + {% else %}

{% translate "Plugins" %}

{% translate "There are no required or optional plugins needed for the selected report types." %} diff --git a/rocky/rocky/locale/django.pot b/rocky/rocky/locale/django.pot index 15532d43c59..0aa3be3149d 100644 --- a/rocky/rocky/locale/django.pot +++ b/rocky/rocky/locale/django.pot @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-10 09:50+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1228,6 +1228,7 @@ msgstr "" #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html #: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -1242,6 +1243,7 @@ msgstr "" #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html #: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -3024,6 +3026,7 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -4244,6 +4247,10 @@ msgstr "" msgid "optional" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " From 825a173df32e5c0ebf8ff6ec08113f3c2cbddfd9 Mon Sep 17 00:00:00 2001 From: Donny Peeters <46660228+Donnype@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:32:54 +0200 Subject: [PATCH 07/25] Fix/yielded objects (#3669) Co-authored-by: Jan Klopper Co-authored-by: Jeroen Dekkers --- rocky/rocky/views/task_detail.py | 1 + 1 file changed, 1 insertion(+) diff --git a/rocky/rocky/views/task_detail.py b/rocky/rocky/views/task_detail.py index da6744bf460..3fba9eb1a05 100644 --- a/rocky/rocky/views/task_detail.py +++ b/rocky/rocky/views/task_detail.py @@ -55,6 +55,7 @@ def get_context_data(self, **kwargs): class NormalizerTaskJSONView(TaskDetailView): + task_type = "normalizer" plugin_type = "normalizer" def get(self, request, *args, **kwargs) -> JsonResponse | HttpResponse: From 9068e7b10934dd9dde53a6d8019a33c5bda04d25 Mon Sep 17 00:00:00 2001 From: Donny Peeters <46660228+Donnype@users.noreply.github.com> Date: Fri, 11 Oct 2024 14:55:02 +0200 Subject: [PATCH 08/25] Add rocky worker service to debian packages (#3619) Co-authored-by: Jan Klopper Co-authored-by: Jeroen Dekkers Co-authored-by: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> --- .../test_debian_packages_on_ubuntu.yml | 2 +- boefjes/boefjes/app.py | 2 +- docker-compose.release-example.yml | 18 +++++++++++++ docker-compose.yml | 2 +- .../installation_and_deployment/containers.md | 4 ++- .../debianinstall.rst | 6 ++--- .../debuggingtroubleshooting.rst | 1 + docs/source/release_notes/1.18.rst | 26 +++++++++++++++++++ rocky/debian/kat-rocky-worker.service | 18 +++++++++++++ rocky/debian/kat-rocky.service | 1 + rocky/debian/rules | 4 +++ rocky/entrypoint.sh | 6 +++++ rocky/reports/runner/worker.py | 2 +- .../installation/openkat-empty-job-queue.sh | 4 +-- scripts/installation/openkat-install.sh | 4 +-- scripts/installation/openkat-reset.sh | 4 +-- scripts/installation/openkat-restart.sh | 2 +- scripts/installation/openkat-start.sh | 2 +- scripts/installation/openkat-stop.sh | 2 +- scripts/installation/openkat-update.sh | 2 +- 20 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 docs/source/release_notes/1.18.rst create mode 100644 rocky/debian/kat-rocky-worker.service diff --git a/.github/workflows/test_debian_packages_on_ubuntu.yml b/.github/workflows/test_debian_packages_on_ubuntu.yml index 3151160ab7e..0c5bafc4d8d 100644 --- a/.github/workflows/test_debian_packages_on_ubuntu.yml +++ b/.github/workflows/test_debian_packages_on_ubuntu.yml @@ -213,7 +213,7 @@ jobs: sudo sed -i "s/BYTES_PASSWORD=\$/BYTES_PASSWORD=$(sudo grep BYTES_PASSWORD /etc/kat/bytes.conf | awk -F'=' '{ print $2 }')/" /etc/kat/mula.conf - name: Restart KAT - run: sudo systemctl restart kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker + run: sudo systemctl restart kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker - name: Setup accounts in Rocky run: | diff --git a/boefjes/boefjes/app.py b/boefjes/boefjes/app.py index 7e801f895d5..4c636de9211 100644 --- a/boefjes/boefjes/app.py +++ b/boefjes/boefjes/app.py @@ -90,7 +90,7 @@ def _fill_queue(self, task_queue: Queue, queue_type: WorkerManager.Queue): except HTTPError: # Scheduler is having issues, so make note of it and try again logger.exception("Getting the queues from the scheduler failed") - time.sleep(10 * self.settings.poll_interval) # But not immediately + time.sleep(self.settings.poll_interval) # But not immediately return # We do not target a specific queue since we start one runtime for all organisations diff --git a/docker-compose.release-example.yml b/docker-compose.release-example.yml index c90b1bf7bdb..679bdccb599 100644 --- a/docker-compose.release-example.yml +++ b/docker-compose.release-example.yml @@ -98,6 +98,7 @@ services: rocky: restart: on-failure depends_on: + - rocky_worker - octopoes_api_worker - octopoes_api - postgres @@ -108,12 +109,29 @@ services: ports: - "127.0.0.1:8000:8000" image: "ghcr.io/minvws/nl-kat-rocky:${KAT_VERSION}" + command: web env_file: - .env-prod - .env environment: - DATABASE_MIGRATION=true + rocky_worker: + restart: on-failure + depends_on: + - octopoes_api_worker + - octopoes_api + - postgres + - boefje + - normalizer + - katalogus + - scheduler + image: "ghcr.io/minvws/nl-kat-rocky:${KAT_VERSION}" + command: worker + env_file: + - .env-prod + - .env + bytes: restart: on-failure depends_on: diff --git a/docker-compose.yml b/docker-compose.yml index 5b13236e92c..7ad1333c859 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -164,7 +164,7 @@ services: target: dev args: ENVIRONMENT: dev - command: python3 manage.py worker + command: worker volumes: - ./rocky:/app/rocky - ./octopoes/octopoes:/app/rocky/octopoes diff --git a/docs/source/installation_and_deployment/containers.md b/docs/source/installation_and_deployment/containers.md index 31691a99d7c..4378c2b5641 100644 --- a/docs/source/installation_and_deployment/containers.md +++ b/docs/source/installation_and_deployment/containers.md @@ -100,10 +100,12 @@ By default OpenKAT has an IPv6 subnet configured. This configuration (step 4 and ## Container commands -We have two container images that are used to run multiple containers. What the container runs is be specified by overriding the CMD of the container. +We have three container images that are used to run multiple containers. What the container runs is be specified by overriding the CMD of the container. | Container image | CMD | Description | | --------------- | ----------- | --------------------------------------------------------------------------------- | +| rocky | web | Django web application | +| rocky | worker | Rocky reports runner | | boefjes | boefje | Boefjes runtime | | boefjes | normalizer | Normalizers runtime | | boefjes | katalogus | Katalogus API | diff --git a/docs/source/installation_and_deployment/debianinstall.rst b/docs/source/installation_and_deployment/debianinstall.rst index df31a329d99..d8ffec4774b 100644 --- a/docs/source/installation_and_deployment/debianinstall.rst +++ b/docs/source/installation_and_deployment/debianinstall.rst @@ -292,7 +292,7 @@ After finishing these steps, you should restart KAT to load the new configuratio .. code-block:: sh - sudo systemctl restart kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker + sudo systemctl restart kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker Start KAT on system boot ======================== @@ -301,7 +301,7 @@ To start KAT when the system boots, enable all KAT services: .. code-block:: sh - sudo systemctl enable kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker + sudo systemctl enable kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker Configure reverse proxy @@ -423,4 +423,4 @@ Restart all processes: .. code-block:: sh - sudo systemctl restart kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker + sudo systemctl restart kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker diff --git a/docs/source/installation_and_deployment/debuggingtroubleshooting.rst b/docs/source/installation_and_deployment/debuggingtroubleshooting.rst index 3b7d8189b65..4672ef4b032 100644 --- a/docs/source/installation_and_deployment/debuggingtroubleshooting.rst +++ b/docs/source/installation_and_deployment/debuggingtroubleshooting.rst @@ -45,6 +45,7 @@ The relevant services for OpenKAT: * kat-octopoes.service * kat-keiko.service * kat-rocky.service +* kat-rocky-worker.service * kat-boefjes.service * kat-katalogus.service * kat-octopoes-worker.service diff --git a/docs/source/release_notes/1.18.rst b/docs/source/release_notes/1.18.rst new file mode 100644 index 00000000000..77f344c1be2 --- /dev/null +++ b/docs/source/release_notes/1.18.rst @@ -0,0 +1,26 @@ +============================================ +OpenKAT 1.18 +============================================ + +New Features +============ + + +Bug fixes +========= + + +Upgrading +========= + +Debian packages +--------------- + +If you are using the :ref:`Scripts` we provide to install/upgrade OpenKAT you +need to get the latest version that includes the kat-rocky-worker service. + +Full Changelog +============== + +The full changelog can be found on `Github +`_. diff --git a/rocky/debian/kat-rocky-worker.service b/rocky/debian/kat-rocky-worker.service new file mode 100644 index 00000000000..3696c5e8824 --- /dev/null +++ b/rocky/debian/kat-rocky-worker.service @@ -0,0 +1,18 @@ +[Unit] +Description=kat-rocky worker +After=network.target + +[Service] +User=kat +Group=kat +SyslogIdentifier=kat-rocky-worker +WorkingDirectory=/opt/venvs/kat-rocky/ +EnvironmentFile=/usr/lib/kat/rocky.defaults +EnvironmentFile=/etc/kat/rocky.conf +ExecStart=/usr/bin/rocky-cli worker +Restart=on-failure +RestartSec=3s +KillMode=mixed + +[Install] +WantedBy=multi-user.target diff --git a/rocky/debian/kat-rocky.service b/rocky/debian/kat-rocky.service index 6bebab0c8ba..1f9f2871ea4 100644 --- a/rocky/debian/kat-rocky.service +++ b/rocky/debian/kat-rocky.service @@ -1,5 +1,6 @@ [Unit] Description=kat-rocky daemon +Requires=kat-rocky-worker.service After=network.target [Service] diff --git a/rocky/debian/rules b/rocky/debian/rules index ffe2524f93b..7cf60d790a4 100755 --- a/rocky/debian/rules +++ b/rocky/debian/rules @@ -50,5 +50,9 @@ override_dh_virtualenv: override_dh_gencontrol: dh_gencontrol -- -Vpython=`py3versions -d` +override_dh_installsystemd: + dh_installsystemd --name=kat-rocky + dh_installsystemd --name=kat-rocky-worker + execute_after_dh_install: dh_installsysusers diff --git a/rocky/entrypoint.sh b/rocky/entrypoint.sh index 54687790413..946332c62c6 100755 --- a/rocky/entrypoint.sh +++ b/rocky/entrypoint.sh @@ -8,4 +8,10 @@ if [ "$DATABASE_MIGRATION" = "1" ] || [[ $DATABASE_MIGRATION == "true" ]]; then python manage.py migrate --noinput fi +if [ "$1" = "web" ]; then + exec granian --interface wsgi rocky.wsgi:application --host 0.0.0.0 +elif [ "$1" = "worker" ]; then + exec python3 manage.py worker +fi + exec "$@" diff --git a/rocky/reports/runner/worker.py b/rocky/reports/runner/worker.py index 6046db33c57..34397c20120 100644 --- a/rocky/reports/runner/worker.py +++ b/rocky/reports/runner/worker.py @@ -79,7 +79,7 @@ def _fill_queue(self, task_queue: Queue): except HTTPError: # Scheduler is having issues, so make note of it and try again logger.exception("Getting the queues from the scheduler failed") - time.sleep(10 * self.poll_interval) # But not immediately + time.sleep(self.poll_interval) # But not immediately return # We do not target a specific queue since we start one runtime for all organisations diff --git a/scripts/installation/openkat-empty-job-queue.sh b/scripts/installation/openkat-empty-job-queue.sh index 312897eb4c0..7d85f5014f2 100644 --- a/scripts/installation/openkat-empty-job-queue.sh +++ b/scripts/installation/openkat-empty-job-queue.sh @@ -2,7 +2,7 @@ # Stop openKAT echo "Stopping openKAT processes" -sudo systemctl stop xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl stop xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker # Start postgres, switch to the mula_db and empty the job queue echo "Emptying job queue" @@ -13,6 +13,6 @@ EOF # Start openKAT echo "Starting openKAT processes" -sudo systemctl start xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl start xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker echo "End of script. It might take a few more seconds for OpenKAT to be fully started and available." diff --git a/scripts/installation/openkat-install.sh b/scripts/installation/openkat-install.sh index c8ad8efca41..b19f7b8d8ae 100644 --- a/scripts/installation/openkat-install.sh +++ b/scripts/installation/openkat-install.sh @@ -285,9 +285,9 @@ echo "Step 6.11 - Set kat permissions in rabbitmq" sudo rabbitmqctl set_permissions -p "kat" "kat" ".*" ".*" ".*" echo "Step 7 - Configure start at system boot" -sudo systemctl enable kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl enable kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker echo "Step 8 - Restart OpenKAT" -sudo systemctl restart kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl restart kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker echo "Step 9 - End of OpenKAT install script" diff --git a/scripts/installation/openkat-reset.sh b/scripts/installation/openkat-reset.sh index 06ebe0c5b87..df71266d6a4 100644 --- a/scripts/installation/openkat-reset.sh +++ b/scripts/installation/openkat-reset.sh @@ -29,7 +29,7 @@ fi pushd / echo "Stop OpenKAT" -sudo systemctl stop xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl stop xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker echo "Delete XTDB databases" sudo rm -rf /var/lib/xtdb/* @@ -89,6 +89,6 @@ if [[ ${1} != "no_super_user" ]]; then fi echo "Start OpenKAT" -sudo systemctl start xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl start xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker popd diff --git a/scripts/installation/openkat-restart.sh b/scripts/installation/openkat-restart.sh index a5800b1b4b1..5cecf4547d3 100644 --- a/scripts/installation/openkat-restart.sh +++ b/scripts/installation/openkat-restart.sh @@ -1,4 +1,4 @@ #!/bin/bash echo "Restarting openKAT..." -sudo systemctl restart xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl restart xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker diff --git a/scripts/installation/openkat-start.sh b/scripts/installation/openkat-start.sh index d97af35ce91..96df24dcc6a 100644 --- a/scripts/installation/openkat-start.sh +++ b/scripts/installation/openkat-start.sh @@ -1,4 +1,4 @@ #!/bin/bash echo "Starting openKAT..." -sudo systemctl start xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl start xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker diff --git a/scripts/installation/openkat-stop.sh b/scripts/installation/openkat-stop.sh index 8fa3aea7d61..f20d71cdfcb 100644 --- a/scripts/installation/openkat-stop.sh +++ b/scripts/installation/openkat-stop.sh @@ -1,4 +1,4 @@ #!/bin/bash echo "Stopping openKAT..." -sudo systemctl stop xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl stop xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker diff --git a/scripts/installation/openkat-update.sh b/scripts/installation/openkat-update.sh index 7a5be6b4b32..b8ef24b80aa 100644 --- a/scripts/installation/openkat-update.sh +++ b/scripts/installation/openkat-update.sh @@ -82,6 +82,6 @@ sudo -u kat update-katalogus-db sudo -u kat update-mula-db echo "Step 7 - Restart OpenKAT" -sudo systemctl restart xtdb-http-multinode kat-rocky kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker +sudo systemctl restart xtdb-http-multinode kat-rocky kat-rocky-worker kat-mula kat-bytes kat-boefjes kat-normalizers kat-katalogus kat-keiko kat-octopoes kat-octopoes-worker echo "End of OpenKAT update script" From 08aa9e0ecb07b2fad9157b0e7dfc7c1e61b2bf72 Mon Sep 17 00:00:00 2001 From: Jan Klopper Date: Fri, 11 Oct 2024 20:06:07 +0200 Subject: [PATCH 09/25] Update upload_raw.py (#3645) Co-authored-by: Ammar --- rocky/rocky/views/upload_raw.py | 4 +++- rocky/tools/forms/upload_raw.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/rocky/rocky/views/upload_raw.py b/rocky/rocky/views/upload_raw.py index c6586ad692c..24f7dd5de99 100644 --- a/rocky/rocky/views/upload_raw.py +++ b/rocky/rocky/views/upload_raw.py @@ -62,7 +62,9 @@ def process_raw(self, form): raw_file = form.cleaned_data["raw_file"] mime_types = form.cleaned_data["mime_types"] input_ooi = form.cleaned_data["ooi"] - valid_time = form.cleaned_data["date"].replace(tzinfo=timezone.utc) + valid_time = None + if "date" in form.cleaned_data: + valid_time = form.cleaned_data["date"].replace(tzinfo=timezone.utc) try: get_bytes_client(self.organization.code).upload_raw( diff --git a/rocky/tools/forms/upload_raw.py b/rocky/tools/forms/upload_raw.py index 79ddf35a97a..151b114941c 100644 --- a/rocky/tools/forms/upload_raw.py +++ b/rocky/tools/forms/upload_raw.py @@ -25,10 +25,11 @@ class UploadRawForm(BaseRockyForm): required=True, widget=forms.TextInput(attrs={"placeholder": "text/html, image/jpeg, ..."}), ) - raw_file = forms.FileField(label=_("Upload raw file"), allow_empty_file=False) + raw_file = forms.FileField(label=_("Upload raw file"), allow_empty_file=False, required=True) ooi_id = forms.CharField( label="Input or Scan OOI", + required=True, widget=DataListInput( attrs={"placeholder": _("Click to select one of the available options, or type one yourself")} ), @@ -64,7 +65,7 @@ def clean(self): cleaned_data = super().clean() date = self.cleaned_data["date"] - ooi_id = self.cleaned_data["ooi_id"] + ooi_id = self.data["ooi_id"] # date should not be in the future if date > datetime.now(tz=timezone.utc): From c2a79d31c08d56f278ac5deaee5ac3eef7e355de Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Mon, 14 Oct 2024 10:44:23 +0200 Subject: [PATCH 10/25] Translations update from Hosted Weblate (#3673) Co-authored-by: Jan Klopper --- rocky/rocky/locale/de/LC_MESSAGES/django.po | 148 +++++++++++--- .../locale/en@pirate/LC_MESSAGES/django.po | 148 +++++++++++--- rocky/rocky/locale/fr/LC_MESSAGES/django.po | 148 +++++++++++--- rocky/rocky/locale/fy/LC_MESSAGES/django.po | 148 +++++++++++--- rocky/rocky/locale/it/LC_MESSAGES/django.po | 148 +++++++++++--- rocky/rocky/locale/nl/LC_MESSAGES/django.po | 182 ++++++++++++++---- rocky/rocky/locale/pap/LC_MESSAGES/django.po | 148 +++++++++++--- 7 files changed, 867 insertions(+), 203 deletions(-) diff --git a/rocky/rocky/locale/de/LC_MESSAGES/django.po b/rocky/rocky/locale/de/LC_MESSAGES/django.po index 631023f8bd4..b0ed93db5aa 100644 --- a/rocky/rocky/locale/de/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: 2024-07-17 09:09+0000\n" "Last-Translator: LibreTranslate \n" "Language-Team: German Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -3988,6 +4025,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -4029,6 +4067,7 @@ msgstr "" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -4102,13 +4141,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4217,6 +4254,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4254,10 +4292,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4271,23 +4305,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4312,12 +4378,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4332,6 +4392,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4354,6 +4418,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4480,7 +4560,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -5840,6 +5920,14 @@ msgid "" "object for additional information." msgstr "" +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "" @@ -7084,6 +7172,10 @@ msgstr "" msgid "Clearance type: " msgstr "" +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "" diff --git a/rocky/rocky/locale/en@pirate/LC_MESSAGES/django.po b/rocky/rocky/locale/en@pirate/LC_MESSAGES/django.po index 0e748242577..c62f4434533 100644 --- a/rocky/rocky/locale/en@pirate/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/en@pirate/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: 2023-11-18 13:03+0000\n" "Last-Translator: jan klopper \n" "Language-Team: English (Pirate) Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -3806,6 +3843,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -3847,6 +3885,7 @@ msgstr "" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -3920,13 +3959,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4035,6 +4072,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4072,10 +4110,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4089,23 +4123,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4130,12 +4196,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4150,6 +4210,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4172,6 +4236,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4298,7 +4378,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -5658,6 +5738,14 @@ msgid "" "object for additional information." msgstr "" +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "" @@ -6902,6 +6990,10 @@ msgstr "" msgid "Clearance type: " msgstr "" +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "" diff --git a/rocky/rocky/locale/fr/LC_MESSAGES/django.po b/rocky/rocky/locale/fr/LC_MESSAGES/django.po index 91a83efb671..ab49928d4bb 100644 --- a/rocky/rocky/locale/fr/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -31,6 +31,7 @@ msgstr "" #: reports/report_types/tls_report/report.html #: reports/templates/partials/report_names_form.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html #: tools/forms/boefje.py rocky/templates/organizations/organization_list.html #: rocky/templates/organizations/organization_settings.html @@ -628,6 +629,7 @@ msgstr "" #: katalogus/forms/katalogus_filter.py #: katalogus/templates/partials/plugin_tile_modal.html #: katalogus/templates/plugin_container_image.html +#: reports/templates/summary/selected_plugins.html msgid "Disabled" msgstr "" @@ -815,13 +817,15 @@ msgstr "" #: reports/templates/partials/report_ooi_list.html #: reports/templates/report_overview/report_history_table.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Object" msgstr "" #: katalogus/templates/change_clearance_level.html onboarding/forms.py #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html tools/forms/boefje.py -#: tools/forms/ooi.py rocky/templates/oois/ooi_page_tabs.html +#: tools/forms/ooi.py rocky/templates/oois/ooi_list.html +#: rocky/templates/oois/ooi_page_tabs.html #: rocky/templates/partials/explanations.html msgid "Clearance level" msgstr "" @@ -1084,6 +1088,7 @@ msgstr "" #: katalogus/templates/partials/plugin_tile_modal.html reports/forms.py #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html msgid "Report types" msgstr "" @@ -1220,6 +1225,8 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -1233,6 +1240,8 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -1248,6 +1257,7 @@ msgstr "" #: katalogus/templates/plugin_container_image.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Creation date" msgstr "" @@ -2012,6 +2022,7 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html tools/forms/ooi.py +#: rocky/templates/oois/ooi_list.html #: rocky/templates/partials/elements/ooi_tree_condensed_table.html #: rocky/templates/partials/explanations.html #: rocky/templates/partials/ooi_detail_related_object.html @@ -2470,6 +2481,7 @@ msgstr "" #: reports/report_types/aggregate_organisation_report/appendix.html #: reports/templates/partials/plugin_overview_table.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html #: reports/templates/summary/report_asset_overview.html msgid "Report type" @@ -3012,6 +3024,7 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -3660,6 +3673,7 @@ msgid "" msgstr "" #: reports/templates/partials/export_report_settings.html +#: reports/templates/report_overview/scheduled_reports_table.html msgid "Recurrence" msgstr "" @@ -3764,15 +3778,38 @@ msgid "Year" msgstr "" #: reports/templates/partials/report_names_header.html +#: reports/templates/report_overview/report_history_table.html msgid "Report name" msgstr "" #: reports/templates/partials/report_names_header.html msgid "" -"Give your report a custom name and optionally add the reports' reference " +"Define a custom name format for your report(s). This format will be applied " +"to all generated (sub)reports." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"To make the report names more descriptive, you can include placeholders for " +"the object name, the report type and/or the reference date. Use the " +"placeholder \"{ooi}\" for the object name, \"{report type}\" for the report " +"type and use a Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -3803,6 +3840,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -3844,6 +3882,7 @@ msgstr "" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -3917,13 +3956,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4032,6 +4069,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4069,10 +4107,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4086,23 +4120,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4127,12 +4193,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4147,6 +4207,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4169,6 +4233,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4295,7 +4375,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -5655,6 +5735,14 @@ msgid "" "object for additional information." msgstr "" +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "" @@ -6899,6 +6987,10 @@ msgstr "" msgid "Clearance type: " msgstr "" +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "" diff --git a/rocky/rocky/locale/fy/LC_MESSAGES/django.po b/rocky/rocky/locale/fy/LC_MESSAGES/django.po index 627835ae75a..c64c26eb181 100644 --- a/rocky/rocky/locale/fy/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/fy/LC_MESSAGES/django.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: 2024-10-02 14:16+0000\n" "Last-Translator: Wim Benes \n" "Language-Team: Frisian Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -4057,6 +4094,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -4098,6 +4136,7 @@ msgstr "Objekten" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -4171,13 +4210,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4286,6 +4323,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4323,10 +4361,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4340,23 +4374,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4381,12 +4447,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4401,6 +4461,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4423,6 +4487,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4549,7 +4629,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -5909,6 +5989,14 @@ msgid "" "object for additional information." msgstr "" +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "" @@ -7161,6 +7249,10 @@ msgstr "Frijwarringsnivo: " msgid "Clearance type: " msgstr "" +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "" diff --git a/rocky/rocky/locale/it/LC_MESSAGES/django.po b/rocky/rocky/locale/it/LC_MESSAGES/django.po index db148544695..719403970d8 100644 --- a/rocky/rocky/locale/it/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/it/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: 2023-11-16 20:05+0000\n" "Last-Translator: Luca Racchetti \n" "Language-Team: Italian Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -4140,6 +4177,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -4181,6 +4219,7 @@ msgstr "Oggetti" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -4254,13 +4293,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4369,6 +4406,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4406,10 +4444,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4423,23 +4457,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "Oggetto di Input" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4464,12 +4530,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "Oggetto di Input" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4484,6 +4544,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4506,6 +4570,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4632,7 +4712,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -6064,6 +6144,14 @@ msgstr "" "manualmente o tramite l'esecuzione di Boefjes. Clicca su un oggetto per " "ulteriori informazioni." +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "Elimina oggetto(i)" @@ -7437,6 +7525,10 @@ msgstr "Livello di autorizzazione: " msgid "Clearance type: " msgstr "Tipo di liquidazione: " +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "Imposta" diff --git a/rocky/rocky/locale/nl/LC_MESSAGES/django.po b/rocky/rocky/locale/nl/LC_MESSAGES/django.po index 81d3a94ad53..b3914befc31 100644 --- a/rocky/rocky/locale/nl/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/nl/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: 2024-08-01 11:09+0000\n" "Last-Translator: Wim Benes \n" "Language-Team: Dutch Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -4315,6 +4352,7 @@ msgid "Select which objects you want to include in your report." msgstr "Selecteer de objecten die u op wilt nemen in het rapport." #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "Geen objecten gevonden." @@ -4356,6 +4394,7 @@ msgstr "Objecten" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "Vrijwaringstype" @@ -4445,16 +4484,12 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" -msgstr "Goed gedaan! Alle voorgestelde plug-ins zijn ingeschakeld" +msgid "Good job! All suggested plugins are enabled." +msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" -"Dit rapport vereist dat tenminste één van de volgende plug-ins is " -"geactiveerd om het rapport te genereren:" #: reports/templates/partials/report_setup_scan.html msgid "Hide suggested plugins" @@ -4568,6 +4603,7 @@ msgid "Input Objects" msgstr "Input objecten" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "Referentiedatum" @@ -4613,10 +4649,6 @@ msgstr[1] "" msgid "Subreports" msgstr "Subrapporten" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "Rapport-id" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "Subrapportdetails tonen" @@ -4629,26 +4661,58 @@ msgstr "Alle subrapporten bekijken" msgid "Overview of reports" msgstr "Overzicht van rapporten" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" -msgstr "Recent" - -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" -msgstr "Voorinstellingen" - #: reports/templates/report_overview/report_overview_navigation.html msgid "Scheduled" msgstr "Gepland" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" -msgstr "Mappen" - #: reports/templates/report_overview/report_overview_navigation.html msgid "History" msgstr "Geschiedenis" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." +msgstr "" + +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "Inputobject" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" +msgstr "" + #: reports/templates/report_overview/subreports.html #, python-format msgid "Showing %(length)s of %(total)s subreports" @@ -4671,12 +4735,6 @@ msgstr "Rapportdetails tonen" msgid "Subreports:" msgstr "Subrapporten:" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "Inputobject" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4697,6 +4755,10 @@ msgstr "" "De tabel hieronder toont aan welke rapporten zijn gekozen om dit rapport te " "genereren, inclusief een rapportomschrijving." +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4721,6 +4783,22 @@ msgstr "Plug-in-opties" msgid "Plugin scan level" msgstr "Plug-in-scanniveau" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4851,7 +4929,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -6294,6 +6372,14 @@ msgstr "" "toegevoegd of door het uitvoeren van Boefjes. Klik op een object voor meer " "informatie." +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "Object(en) verwijderen" @@ -7651,6 +7737,10 @@ msgstr "Vrijwaringsniveau: " msgid "Clearance type: " msgstr "Vrijwaringstype: " +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "Instellingen" @@ -7859,6 +7949,28 @@ msgstr "Raw-bestand kan niet naar Bytes worden geüpload: %s" msgid "Raw file successfully added." msgstr "Raw-bestand met succes toegevoegd." +#~ msgid "Good job! All suggested plugins are enabled" +#~ msgstr "Goed gedaan! Alle voorgestelde plug-ins zijn ingeschakeld" + +#~ msgid "" +#~ "This report requires at least one of the following plugins to be enabled " +#~ "to generate the report:" +#~ msgstr "" +#~ "Dit rapport vereist dat tenminste één van de volgende plug-ins is " +#~ "geactiveerd om het rapport te genereren:" + +#~ msgid "Report ID" +#~ msgstr "Rapport-id" + +#~ msgid "Recent" +#~ msgstr "Recent" + +#~ msgid "Presets" +#~ msgstr "Voorinstellingen" + +#~ msgid "Folders" +#~ msgstr "Mappen" + #~ msgid "A HTTP error occurred. Check logs for more info." #~ msgstr "" #~ "Er is een HTTP-fout opgetreden. Controleer de logboeken voor meer " diff --git a/rocky/rocky/locale/pap/LC_MESSAGES/django.po b/rocky/rocky/locale/pap/LC_MESSAGES/django.po index dbfb9fc5e5c..8edd030b342 100644 --- a/rocky/rocky/locale/pap/LC_MESSAGES/django.po +++ b/rocky/rocky/locale/pap/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-01 14:17+0000\n" +"POT-Creation-Date: 2024-10-09 14:20+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,6 +27,7 @@ msgstr "Fechanan importante" #: reports/report_types/tls_report/report.html #: reports/templates/partials/report_names_form.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html #: tools/forms/boefje.py rocky/templates/organizations/organization_list.html #: rocky/templates/organizations/organization_settings.html @@ -662,6 +663,7 @@ msgstr "Aktivá" #: katalogus/forms/katalogus_filter.py #: katalogus/templates/partials/plugin_tile_modal.html #: katalogus/templates/plugin_container_image.html +#: reports/templates/summary/selected_plugins.html msgid "Disabled" msgstr "Desaktivá" @@ -861,13 +863,15 @@ msgstr "" #: reports/templates/partials/report_ooi_list.html #: reports/templates/report_overview/report_history_table.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Object" msgstr "Opheto" #: katalogus/templates/change_clearance_level.html onboarding/forms.py #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html tools/forms/boefje.py -#: tools/forms/ooi.py rocky/templates/oois/ooi_page_tabs.html +#: tools/forms/ooi.py rocky/templates/oois/ooi_list.html +#: rocky/templates/oois/ooi_page_tabs.html #: rocky/templates/partials/explanations.html msgid "Clearance level" msgstr "Nivél di autorisashon" @@ -1160,6 +1164,7 @@ msgstr "" #: katalogus/templates/partials/plugin_tile_modal.html reports/forms.py #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html msgid "Report types" msgstr "" @@ -1296,6 +1301,8 @@ msgstr "" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -1309,6 +1316,8 @@ msgstr "Sera detayes" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -1324,6 +1333,7 @@ msgstr "" #: katalogus/templates/plugin_container_image.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Creation date" msgstr "" @@ -2204,6 +2214,7 @@ msgstr "URL" #: reports/report_types/dns_report/report.html #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html tools/forms/ooi.py +#: rocky/templates/oois/ooi_list.html #: rocky/templates/partials/elements/ooi_tree_condensed_table.html #: rocky/templates/partials/explanations.html #: rocky/templates/partials/ooi_detail_related_object.html @@ -2749,6 +2760,7 @@ msgstr "" #: reports/report_types/aggregate_organisation_report/appendix.html #: reports/templates/partials/plugin_overview_table.html #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html #: reports/templates/summary/report_asset_overview.html msgid "Report type" @@ -3291,6 +3303,7 @@ msgstr "Diskubrimentu" #: reports/report_types/dns_report/report.html #: reports/report_types/findings_report/report.html #: reports/report_types/vulnerability_report/report.html +#: reports/templates/summary/selected_plugins.html #: rocky/templates/crisis_room/crisis_room_findings_block.html #: rocky/templates/findings/finding_list.html #: rocky/templates/organizations/organization_crisis_room.html @@ -3939,6 +3952,7 @@ msgid "" msgstr "" #: reports/templates/partials/export_report_settings.html +#: reports/templates/report_overview/scheduled_reports_table.html msgid "Recurrence" msgstr "" @@ -4043,15 +4057,38 @@ msgid "Year" msgstr "" #: reports/templates/partials/report_names_header.html +#: reports/templates/report_overview/report_history_table.html msgid "Report name" msgstr "" #: reports/templates/partials/report_names_header.html msgid "" -"Give your report a custom name and optionally add the reports' reference " +"Define a custom name format for your report(s). This format will be applied " +"to all generated (sub)reports." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"To make the report names more descriptive, you can include placeholders for " +"the object name, the report type and/or the reference date. Use the " +"placeholder \"{ooi}\" for the object name, \"{report type}\" for the report " +"type and use a Python strftime code for the reference date." +msgstr "" + +#: reports/templates/partials/report_names_header.html +#, python-format +msgid "" +"For example, the format \"{report type} for {ooi} at %%x\" could generate: " +"\"DNS Report for example.com at 01/01/25\"." +msgstr "" + +#: reports/templates/partials/report_names_header.html +msgid "" +"Give your report(s) a custom name and optionally add the reports' reference " "date to the name. To do so you can select a standard option or use a Python strftime code in " -"the report name." +"href=\"https://strftime.org/\" target=\"_blank\" rel=\"noopener\">Python " +"strftime code in the report name." msgstr "" #: reports/templates/partials/report_navigation.html @@ -4082,6 +4119,7 @@ msgid "Select which objects you want to include in your report." msgstr "" #: reports/templates/partials/report_ooi_list.html +#: reports/templates/summary/report_asset_overview.html msgid "No objects found." msgstr "" @@ -4123,6 +4161,7 @@ msgstr "Ophetonan" #: reports/templates/partials/report_ooi_list.html #: reports/templates/summary/ooi_selection.html +#: rocky/templates/oois/ooi_list.html msgid "Clearance type" msgstr "" @@ -4196,13 +4235,11 @@ msgid "There are no required plugins." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "Good job! All suggested plugins are enabled" +msgid "Good job! All suggested plugins are enabled." msgstr "" #: reports/templates/partials/report_setup_scan.html -msgid "" -"This report requires at least one of the following plugins to be enabled to " -"generate the report:" +msgid "The following plugins are optional to generate the report:" msgstr "" #: reports/templates/partials/report_setup_scan.html @@ -4311,6 +4348,7 @@ msgid "Input Objects" msgstr "" #: reports/templates/report_overview/report_history_table.html +#: reports/templates/report_overview/scheduled_reports_table.html #: reports/templates/report_overview/subreports_table.html msgid "Reference date" msgstr "" @@ -4348,10 +4386,6 @@ msgstr[1] "" msgid "Subreports" msgstr "" -#: reports/templates/report_overview/report_history_table.html -msgid "Report ID" -msgstr "" - #: reports/templates/report_overview/report_history_table.html msgid "Shows subreport details" msgstr "" @@ -4365,23 +4399,55 @@ msgid "Overview of reports" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Recent" +msgid "Scheduled" msgstr "" #: reports/templates/report_overview/report_overview_navigation.html -msgid "Presets" +msgid "History" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Scheduled" +#: reports/templates/report_overview/scheduled_reports.html +msgid "Scheduled reports" msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "Folders" +#: reports/templates/report_overview/scheduled_reports.html +msgid "View your scheduled reports." msgstr "" -#: reports/templates/report_overview/report_overview_navigation.html -msgid "History" +#: reports/templates/report_overview/scheduled_reports.html +#, python-format +msgid "Showing %(length)s scheduled reports" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Report Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Subreport Name" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled for" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Scheduled Reports:" +msgstr "" + +#: reports/templates/report_overview/scheduled_reports_table.html +#: reports/templates/report_overview/subreports_table.html +#: rocky/templates/tasks/boefjes.html +#: rocky/templates/tasks/plugin_detail_task_list.html +msgid "Input Object" +msgstr "Opheto di entrada" + +#: reports/templates/report_overview/scheduled_reports_table.html +msgid "Show report details" msgstr "" #: reports/templates/report_overview/subreports.html @@ -4406,12 +4472,6 @@ msgstr "" msgid "Subreports:" msgstr "" -#: reports/templates/report_overview/subreports_table.html -#: rocky/templates/tasks/boefjes.html -#: rocky/templates/tasks/plugin_detail_task_list.html -msgid "Input Object" -msgstr "Opheto di entrada" - #: reports/templates/summary/report_asset_overview.html msgid "" "The objects listed in the table below were used to generate this report. For " @@ -4426,6 +4486,10 @@ msgid "" "including a report description." msgstr "" +#: reports/templates/summary/report_asset_overview.html +msgid "No report types found." +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "The table below shows all required or optional plugins for the selected " @@ -4448,6 +4512,22 @@ msgstr "" msgid "Plugin scan level" msgstr "" +#: reports/templates/summary/selected_plugins.html +msgid "Enabled." +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "required" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "optional" +msgstr "" + +#: reports/templates/summary/selected_plugins.html +msgid "Plugin extra info" +msgstr "" + #: reports/templates/summary/selected_plugins.html msgid "" "There are no required or optional plugins needed for the selected report " @@ -4574,7 +4654,7 @@ msgstr "" #: tools/forms/boefje.py msgid "" "Specify the scanning frequency for this Boefje in minutes. The default is 24 " -"hours.For example: 5 minutes will let the boefje scan every 5 minutes." +"hours. For example: 5 minutes will let the boefje scan every 5 minutes." msgstr "" #: tools/forms/finding_type.py @@ -5994,6 +6074,14 @@ msgstr "" "manualmente òf dor di ehekutá boefjes.
Klik riba un opheto pa mas " "informashon." +#: rocky/templates/oois/ooi_list.html +msgid "Objects " +msgstr "" + +#: rocky/templates/oois/ooi_list.html +msgid "column headers with buttons are sortable" +msgstr "" + #: rocky/templates/oois/ooi_list.html msgid "Delete object(s)" msgstr "Kita opheto(nan)" @@ -7346,6 +7434,10 @@ msgstr "Nivél di autorisashon: " msgid "Clearance type: " msgstr "Tipo di autorisashon: " +#: rocky/views/ooi_view.py +msgid "Searching for: " +msgstr "" + #: rocky/views/organization_add.py msgid "Setup" msgstr "Setup" From a581d78dede777315c489e38ccce816548075d6a Mon Sep 17 00:00:00 2001 From: Rieven Date: Mon, 14 Oct 2024 13:58:03 +0200 Subject: [PATCH 11/25] Add plugins to findings report (#3657) Co-authored-by: Jan Klopper --- .../reports/report_types/findings_report/report.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rocky/reports/report_types/findings_report/report.py b/rocky/reports/report_types/findings_report/report.py index 91fb63e2533..481e95785a3 100644 --- a/rocky/reports/report_types/findings_report/report.py +++ b/rocky/reports/report_types/findings_report/report.py @@ -23,7 +23,18 @@ class FindingsReport(Report): id = "findings-report" name = _("Findings Report") description = _("Shows all the finding types and their occurrences.") - plugins: ReportPlugins = {"required": set(), "optional": set()} + plugins: ReportPlugins = { + "required": { + "dns-records", + "nmap", + "nmap-udp", + "webpage-analysis", + "ssl-version", + "ssl-certificates", + "testssl-sh-ciphers", + }, + "optional": {"snyk", "service_banner", "shodan", "leakix"}, + } input_ooi_types = ALL_TYPES template_path = "findings_report/report.html" label_style = "3-light" From 40c7bbe6fbf18866e42eb1bdd897133778243177 Mon Sep 17 00:00:00 2001 From: JP Bruins Slot Date: Mon, 14 Oct 2024 15:25:25 +0200 Subject: [PATCH 12/25] Fix jsonb 'contained by' query (#3643) Co-authored-by: Jan Klopper --- mula/scheduler/storage/filters/casting.py | 6 ++-- mula/tests/integration/test_api.py | 28 +++++++++++++++++ mula/tests/unit/test_filter.py | 38 +++++++++++++++++++---- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/mula/scheduler/storage/filters/casting.py b/mula/scheduler/storage/filters/casting.py index e3eb2c85b18..cf3b1a98a54 100644 --- a/mula/scheduler/storage/filters/casting.py +++ b/mula/scheduler/storage/filters/casting.py @@ -43,9 +43,9 @@ def cast_expression(expression: BinaryExpression, filter_: Filter) -> BinaryExpr # if the value can be decoded. try: decoded_value = json.loads(filter_.value) - if isinstance(decoded_value, dict): - # If it's a JSON object, return the expression as is. We don't - # need to cast it. + # If the string is a JSON object, return the expression as is. + # We don't need to cast it. + if isinstance(decoded_value, dict | list): return expression expression = expression.astext except json.JSONDecodeError: diff --git a/mula/tests/integration/test_api.py b/mula/tests/integration/test_api.py index 85e14b5ec37..e1adde1f496 100644 --- a/mula/tests/integration/test_api.py +++ b/mula/tests/integration/test_api.py @@ -481,6 +481,34 @@ def test_pop_queue_filters_nested(self): self.assertEqual(second_item_id, response.json().get("id")) self.assertEqual(0, self.scheduler.queue.qsize()) + def test_pop_queue_filters_nested_contained_by(self): + # Add one task to the queue + first_item = create_task_in(1, data=functions.TestModel(id="123", name="test", categories=["foo", "bar"])) + response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/push", data=first_item) + self.assertEqual(response.status_code, 201) + self.assertEqual(1, self.scheduler.queue.qsize()) + + # Add second item to the queue + second_item = create_task_in(2, data=functions.TestModel(id="456", name="test", categories=["baz", "bat"])) + response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/push", data=second_item) + second_item_id = response.json().get("id") + self.assertEqual(response.status_code, 201) + self.assertEqual(2, self.scheduler.queue.qsize()) + + # Test contained by + response = self.client.post( + f"/queues/{self.scheduler.scheduler_id}/pop", + json={ + "filters": [ + {"column": "data", "operator": "<@", "field": "categories", "value": json.dumps(["baz", "bat"])} + ] + }, + ) + + self.assertEqual(200, response.status_code) + self.assertEqual(second_item_id, response.json().get("id")) + self.assertEqual(1, self.scheduler.queue.qsize()) + def test_pop_empty(self): """When queue is empty it should return an empty response""" response = self.client.post(f"/queues/{self.scheduler.scheduler_id}/pop") diff --git a/mula/tests/unit/test_filter.py b/mula/tests/unit/test_filter.py index 5e1882f94bc..4b804511bb0 100644 --- a/mula/tests/unit/test_filter.py +++ b/mula/tests/unit/test_filter.py @@ -38,21 +38,31 @@ def setUp(self): age=25, height=1.8, is_active=True, - data={"foo": "bar", "score": 15, "nested": {"bar": "baz"}, "list": ["foo", "bar"]}, + data={"foo": "bar", "score": 15, "nested": {"bar": "baz"}, "list": ["ipv4", "network/local"]}, ), TestModel( name="Bob", age=30, height=1.7, is_active=False, - data={"foo": "baz", "score": 25, "nested": {"bar": "baz"}, "list": ["bar", "baz"]}, + data={ + "foo": "baz", + "score": 25, + "nested": {"bar": "baz"}, + "list": ["ipv4", "ipv6", "network/local"], + }, ), TestModel( name="Charlie", age=28, height=1.6, is_active=True, - data={"foo": "bar", "score": 35, "nested": {"bar": "baz"}, "list": ["foo", "bar"]}, + data={ + "foo": "bar", + "score": 35, + "nested": {"bar": "baz"}, + "list": ["ipv4", "ipv6", "network/internet"], + }, ), ] ) @@ -705,9 +715,25 @@ def test_apply_filter_jsonb_contains(self): self.assertEqual(results[0].name, "Alice") self.assertEqual(results[1].name, "Charlie") - def test_apply_filter_jsonb_in_list(self): + def test_apply_filter_jsonb_contains_list(self): filter_request = FilterRequest( - filters=[Filter(column="data", operator="@>", value=json.dumps({"list": ["foo"]}))] + filters=[Filter(column="data", field="list", operator="@>", value=json.dumps(["ipv4"]))] + ) + + query = session.query(TestModel) + filtered_query = apply_filter(TestModel, query, filter_request) + + results = filtered_query.order_by(TestModel.name).all() + self.assertEqual(len(results), 3) + self.assertEqual(results[0].name, "Alice") + self.assertEqual(results[1].name, "Bob") + self.assertEqual(results[2].name, "Charlie") + + def test_apply_filter_jsonb_contained_by_list(self): + filter_request = FilterRequest( + filters=[ + Filter(column="data", field="list", operator="<@", value=json.dumps(["ipv4", "ipv6", "network/local"])) + ] ) query = session.query(TestModel) @@ -716,4 +742,4 @@ def test_apply_filter_jsonb_in_list(self): results = filtered_query.order_by(TestModel.name).all() self.assertEqual(len(results), 2) self.assertEqual(results[0].name, "Alice") - self.assertEqual(results[1].name, "Charlie") + self.assertEqual(results[1].name, "Bob") From c53f98df510204b8256d4a8d798670606846ed8e Mon Sep 17 00:00:00 2001 From: Madelon Dohmen <99282220+madelondohmen@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:31:22 +0200 Subject: [PATCH 13/25] Fix empty vulnerability reports (#3662) Co-authored-by: Rieven Co-authored-by: Jan Klopper --- .../report_types/vulnerability_report/report.html | 9 ++++----- rocky/reports/templatetags/report_extra.py | 7 +++++++ rocky/rocky/locale/django.pot | 8 ++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/rocky/reports/report_types/vulnerability_report/report.html b/rocky/reports/report_types/vulnerability_report/report.html index 7f52510b3ec..09eed1c928e 100644 --- a/rocky/reports/report_types/vulnerability_report/report.html +++ b/rocky/reports/report_types/vulnerability_report/report.html @@ -1,6 +1,9 @@ {% load i18n %} +{% load report_extra %} -{% if data %} +{% if data|sum_findings == 0 %} +

{% translate "No vulnerabilities have been found on this system." %}

+{% else %} {% for ip, vulnerability_data in data.items %} {% if vulnerability_data.summary.total_findings > 0 %} {% if show_heading %} @@ -91,10 +94,6 @@

{% translate "Host:" %} {{ ip|human_readable }} {{ vulnerability_data.hostna - {% else %} - {% if data|length == 1 %} -

{% translate "No vulnerabilities have been found on this system." %}

- {% endif %} {% endif %} {% endfor %} {% endif %} diff --git a/rocky/reports/templatetags/report_extra.py b/rocky/reports/templatetags/report_extra.py index c0c4076b618..a417120407c 100644 --- a/rocky/reports/templatetags/report_extra.py +++ b/rocky/reports/templatetags/report_extra.py @@ -1,3 +1,5 @@ +from typing import Any + from django import template from reports.report_types.helpers import get_report_by_id @@ -10,6 +12,11 @@ def sum_attribute(checks, attribute): return sum(int(check[attribute]) for check in checks) +@register.filter +def sum_findings(data: dict[str, Any]) -> int: + return sum(int(ip["summary"]["total_findings"]) for ip in data.values()) + + @register.filter def get_report_type_name(report_type_id: str): return get_report_by_id(report_type_id).name diff --git a/rocky/rocky/locale/django.pot b/rocky/rocky/locale/django.pot index 0aa3be3149d..4af966792b8 100644 --- a/rocky/rocky/locale/django.pot +++ b/rocky/rocky/locale/django.pot @@ -3568,6 +3568,10 @@ msgid "" "protocols." msgstr "" +#: reports/report_types/vulnerability_report/report.html +msgid "No vulnerabilities have been found on this system." +msgstr "" + #: reports/report_types/vulnerability_report/report.html msgid "" "The Vulnerability Report provides an overview of all identified CVE " @@ -3580,10 +3584,6 @@ msgstr "" msgid "Advice" msgstr "" -#: reports/report_types/vulnerability_report/report.html -msgid "No vulnerabilities have been found on this system." -msgstr "" - #: reports/report_types/vulnerability_report/report.py msgid "Vulnerability Report" msgstr "" From 3ab9a41177c4ab5bee3514ea9ef28a6d94fea57b Mon Sep 17 00:00:00 2001 From: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:06:23 +0200 Subject: [PATCH 14/25] Add docs for xtdb analyze bits. (#3688) --- .../developer_documentation/octopoes.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/source/developer_documentation/octopoes.md b/docs/source/developer_documentation/octopoes.md index 59e87f8e038..d2400d51992 100644 --- a/docs/source/developer_documentation/octopoes.md +++ b/docs/source/developer_documentation/octopoes.md @@ -381,6 +381,38 @@ $ ./xtdb-cli.py -n MyOrganisationName attribute-stats |jq .  } ``` +### XTDB analyze bits tool + +This guide assumes the following: + +- A virtual environment for the octopoes folder is created and the development requirements are installed. + +This tooling can be used when you are developing bits (business rules). It outputs the transaction times in the database, the source and bit information, including parameters and how long the running time was. + +Enable the `GATHER_BIT_METRICS` setting in the following file. The flag is at the bottom of the file. Change `GATHER_BIT_METRICS=False` to `GATHER_BIT_METRICS=True`. + +``` +octopoes/octopoes/config/settings.py +``` + +Run a `make reset` in your KAT instance to enable the setting: + +``` +make reset +``` + +Create some data by adding a hostname, enable some boefjes, etc. This will allow the bit metrics to be gathered. You can query the bit metrics using the following commands. The `node` is the name of your organisation. In this example the organisation name is 'aa'. + +``` +python3 octopoes/tools/analyze-bit-metric.py --node "aa" raw |jq +``` + +``` +python3 octopoes/tools/xtdb-cli.py -n "aa" history --with-docs "BIT_METRIC" |jq +``` + +If you want to query the XTDB database directly, you can use the XTDB-tool. This is explained on the following page: https://docs.openkat.nl/developer_documentation/octopoes.html#xtdb-cli-tool. + ## OOI OOI objects are instances of relatively simple classes, which inherit from `OOI`. From 9ad3461b897fd5beab384df37d1acf40252fbd25 Mon Sep 17 00:00:00 2001 From: originalsouth Date: Wed, 16 Oct 2024 12:09:55 +0200 Subject: [PATCH 15/25] Silence KATFindingType not found error in JobHandler (#3686) Co-authored-by: ammar92 --- boefjes/boefjes/job_handler.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/boefjes/boefjes/job_handler.py b/boefjes/boefjes/job_handler.py index a9f8f68a68a..cc2893983ee 100644 --- a/boefjes/boefjes/job_handler.py +++ b/boefjes/boefjes/job_handler.py @@ -103,8 +103,14 @@ def handle(self, boefje_meta: BoefjeMeta) -> None: ooi = get_octopoes_api_connector(boefje_meta.organization).get( reference, valid_time=datetime.now(timezone.utc) ) - except ObjectNotFoundException as e: - raise ObjectNotFoundException(f"Object {reference} not found in Octopoes") from e + except ObjectNotFoundException: + logger.info( + "Can't run boefje because OOI does not exist anymore", + boefje_id=boefje_meta.boefje.id, + ooi=reference, + task_id=boefje_meta.id, + ) + return boefje_meta.arguments["input"] = ooi.serialize() From 08519a5ab1f9b4e1c24033f6f4afcb7ac472420e Mon Sep 17 00:00:00 2001 From: ammar92 Date: Wed, 16 Oct 2024 12:52:23 +0200 Subject: [PATCH 16/25] Updated packages (#3694) Co-authored-by: Jan Klopper --- boefjes/poetry.lock | 146 +++++++++++++++---------------- boefjes/pyproject.toml | 28 +++--- boefjes/requirements-dev.txt | 90 ++++++++++---------- boefjes/requirements.txt | 90 ++++++++++---------- bytes/poetry.lock | 146 +++++++++++++++---------------- bytes/pyproject.toml | 28 +++--- bytes/requirements-dev.txt | 90 ++++++++++---------- bytes/requirements.txt | 90 ++++++++++---------- keiko/poetry.lock | 114 ++++++++++++------------- keiko/pyproject.toml | 22 ++--- keiko/requirements-dev.txt | 72 ++++++++-------- keiko/requirements.txt | 72 ++++++++-------- mula/poetry.lock | 146 +++++++++++++++---------------- mula/pyproject.toml | 28 +++--- mula/requirements-dev.txt | 90 ++++++++++---------- mula/requirements.txt | 90 ++++++++++---------- octopoes/poetry.lock | 146 +++++++++++++++---------------- octopoes/pyproject.toml | 28 +++--- octopoes/requirements-dev.txt | 90 ++++++++++---------- octopoes/requirements.txt | 90 ++++++++++---------- rocky/poetry.lock | 156 +++++++++++++++++----------------- rocky/pyproject.toml | 30 +++---- rocky/requirements-dev.txt | 90 ++++++++++---------- rocky/requirements.txt | 90 ++++++++++---------- 24 files changed, 1031 insertions(+), 1031 deletions(-) diff --git a/boefjes/poetry.lock b/boefjes/poetry.lock index 842f0c60d25..7d666cc60d8 100644 --- a/boefjes/poetry.lock +++ b/boefjes/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -800,23 +800,23 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi-slim" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.111.1-py3-none-any.whl", hash = "sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb"}, - {file = "fastapi_slim-0.111.1.tar.gz", hash = "sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d"}, + {file = "fastapi_slim-0.115.2-py3-none-any.whl", hash = "sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d"}, + {file = "fastapi_slim-0.115.2.tar.gz", hash = "sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "filelock" @@ -1835,42 +1835,42 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -1878,19 +1878,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -1900,111 +1900,111 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Database API instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_dbapi-0.47b0-py3-none-any.whl", hash = "sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f"}, - {file = "opentelemetry_instrumentation_dbapi-0.47b0.tar.gz", hash = "sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry psycopg2 instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.47b0-py3-none-any.whl", hash = "sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73"}, - {file = "opentelemetry_instrumentation_psycopg2-0.47b0.tar.gz", hash = "sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-dbapi = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-dbapi = "0.48b0" [package.extras] instruments = ["psycopg2 (>=2.7.3.1)"] [[package]] name = "opentelemetry-instrumentation-requests" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry requests instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_requests-0.47b0-py3-none-any.whl", hash = "sha256:77fdd13f64fef2cb44665fe6975eadb993d78f96612e55a502e79b34ef7fee47"}, - {file = "opentelemetry_instrumentation_requests-0.47b0.tar.gz", hash = "sha256:f85ed52cbca21bff226e0e7f1888e5b9bc386657ecf4b0440f328e5b3aba8436"}, + {file = "opentelemetry_instrumentation_requests-0.48b0-py3-none-any.whl", hash = "sha256:d4f01852121d0bd4c22f14f429654a735611d4f7bf3cf93f244bdf1489b2233d"}, + {file = "opentelemetry_instrumentation_requests-0.48b0.tar.gz", hash = "sha256:67ab9bd877a0352ee0db4616c8b4ae59736ddd700c598ed907482d44f4c9a2b3"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["requests (>=2.0,<3.0)"] [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -2012,44 +2012,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -3003,13 +3003,13 @@ sqlcipher = ["sqlcipher3_binary"] [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -3357,4 +3357,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "cbfb370acbb705616e1504ac1c4028f1a4610501b15fdb68821608ea7267bae3" +content-hash = "1e6504539dc2b8b20e1a4c6b6661893e9dd409b18db71972fd9b34845f690a41" diff --git a/boefjes/pyproject.toml b/boefjes/pyproject.toml index 4ce5b5047d0..6d2f895fb8d 100644 --- a/boefjes/pyproject.toml +++ b/boefjes/pyproject.toml @@ -18,12 +18,12 @@ pynacl = "^1.5.0" sqlalchemy = "^1.4.48" python-dateutil = "^2.8.2" pydantic-settings = "^2.2.1" -opentelemetry-sdk = "^1.26.0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-fastapi = "^0.47b0" -opentelemetry-instrumentation-psycopg2 = "^0.47b0" -opentelemetry-instrumentation-requests = "^0.47b0" -opentelemetry-instrumentation = "^0.47b0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-fastapi = "^0.48b0" +opentelemetry-instrumentation-psycopg2 = "^0.48b0" +opentelemetry-instrumentation-requests = "^0.48b0" +opentelemetry-instrumentation = "^0.48b0" # required by kat_snyk, kat_crt_sh, kat_crt_sh boefjes requests = "^2.32.1" # required by kat_binaryedge boefje @@ -63,14 +63,14 @@ defusedxml = "^0.7.1" # required by kat_webpage_analysis/check_images normalizer pillow = "^10.3.0" httpx = "^0.27.0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-instrumentation-dbapi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" -fastapi-slim = "^0.111.0" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-instrumentation-dbapi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" +fastapi-slim = "^0.115.2" structlog = "^24.2.0" # required by kat_maxmind_geoip maxminddb = "^2.6.2" diff --git a/boefjes/requirements-dev.txt b/boefjes/requirements-dev.txt index 9b978ac02ef..91ccd9f557f 100644 --- a/boefjes/requirements-dev.txt +++ b/boefjes/requirements-dev.txt @@ -425,9 +425,9 @@ docker==7.1.0 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d filelock==3.15.4 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb \ --hash=sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7 @@ -1117,45 +1117,45 @@ multidict==6.1.0 ; python_version >= "3.10" and python_version < "4.0" \ netaddr==0.9.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:5148b1055679d2a1ec070c521b7db82137887fabd6d7e37f5199b44f775c3bb1 \ --hash=sha256:7b46fa9b1a2d71fd5de9e4a3784ef339700a53a08c8040f08baf5f1194da0128 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation-requests==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:77fdd13f64fef2cb44665fe6975eadb993d78f96612e55a502e79b34ef7fee47 \ - --hash=sha256:f85ed52cbca21bff226e0e7f1888e5b9bc386657ecf4b0440f328e5b3aba8436 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation-requests==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:67ab9bd877a0352ee0db4616c8b4ae59736ddd700c598ed907482d44f4c9a2b3 \ + --hash=sha256:d4f01852121d0bd4c22f14f429654a735611d4f7bf3cf93f244bdf1489b2233d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==24.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 @@ -1612,9 +1612,9 @@ sqlalchemy==1.4.53 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:eaaeedbceb4dfd688fff2faf25a9a87a391f548811494f7bff7fa701b639abc3 \ --hash=sha256:edf094a20a386ff2ec73de65ef18014b250259cb860edc61741e240ca22d6981 \ --hash=sha256:fb8e15dfa47f5de11ab073e12aadd6b502cfb7ac4bafd18bd18cfd1c7d13dbbc -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/boefjes/requirements.txt b/boefjes/requirements.txt index ed15784a992..e73bfcba5af 100644 --- a/boefjes/requirements.txt +++ b/boefjes/requirements.txt @@ -352,9 +352,9 @@ docker==7.1.0 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d filelock==3.15.4 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb \ --hash=sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7 @@ -1041,45 +1041,45 @@ multidict==6.1.0 ; python_version >= "3.10" and python_version < "4.0" \ netaddr==0.9.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:5148b1055679d2a1ec070c521b7db82137887fabd6d7e37f5199b44f775c3bb1 \ --hash=sha256:7b46fa9b1a2d71fd5de9e4a3784ef339700a53a08c8040f08baf5f1194da0128 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation-requests==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:77fdd13f64fef2cb44665fe6975eadb993d78f96612e55a502e79b34ef7fee47 \ - --hash=sha256:f85ed52cbca21bff226e0e7f1888e5b9bc386657ecf4b0440f328e5b3aba8436 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation-requests==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:67ab9bd877a0352ee0db4616c8b4ae59736ddd700c598ed907482d44f4c9a2b3 \ + --hash=sha256:d4f01852121d0bd4c22f14f429654a735611d4f7bf3cf93f244bdf1489b2233d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==24.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 @@ -1521,9 +1521,9 @@ sqlalchemy==1.4.53 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:eaaeedbceb4dfd688fff2faf25a9a87a391f548811494f7bff7fa701b639abc3 \ --hash=sha256:edf094a20a386ff2ec73de65ef18014b250259cb860edc61741e240ca22d6981 \ --hash=sha256:fb8e15dfa47f5de11ab073e12aadd6b502cfb7ac4bafd18bd18cfd1c7d13dbbc -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/bytes/poetry.lock b/bytes/poetry.lock index 19cda2de38d..eda968f53f5 100644 --- a/bytes/poetry.lock +++ b/bytes/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "alembic" @@ -541,23 +541,23 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi-slim" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.111.1-py3-none-any.whl", hash = "sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb"}, - {file = "fastapi_slim-0.111.1.tar.gz", hash = "sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d"}, + {file = "fastapi_slim-0.115.2-py3-none-any.whl", hash = "sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d"}, + {file = "fastapi_slim-0.115.2.tar.gz", hash = "sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "googleapis-common-protos" @@ -931,42 +931,42 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -974,19 +974,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -996,111 +996,111 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Database API instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_dbapi-0.47b0-py3-none-any.whl", hash = "sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f"}, - {file = "opentelemetry_instrumentation_dbapi-0.47b0.tar.gz", hash = "sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-instrumentation-httpx" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry HTTPX Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_httpx-0.47b0-py3-none-any.whl", hash = "sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a"}, - {file = "opentelemetry_instrumentation_httpx-0.47b0.tar.gz", hash = "sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0-py3-none-any.whl", hash = "sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0.tar.gz", hash = "sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["httpx (>=0.18.0)"] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry psycopg2 instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.47b0-py3-none-any.whl", hash = "sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73"}, - {file = "opentelemetry_instrumentation_psycopg2-0.47b0.tar.gz", hash = "sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-dbapi = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-dbapi = "0.48b0" [package.extras] instruments = ["psycopg2 (>=2.7.3.1)"] [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -1108,44 +1108,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -1766,13 +1766,13 @@ sqlcipher = ["sqlcipher3_binary"] [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -1957,4 +1957,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "b85f797781d07e41879bb0d4e5f1927cdc318229e1c0e0f68da3163cd0f3ad2d" +content-hash = "07868c4304404d1fde3b4736f009b110627b089403c3b2273584e88193e241aa" diff --git a/bytes/pyproject.toml b/bytes/pyproject.toml index 9bbb81f2cf4..bf69d831c08 100644 --- a/bytes/pyproject.toml +++ b/bytes/pyproject.toml @@ -20,24 +20,24 @@ sqlalchemy = "^1.4.48" uvicorn = "^0.29.0" # OpenTelemetry -opentelemetry-sdk = "^1.26.0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-fastapi = "^0.47b0" -opentelemetry-instrumentation-psycopg2 = "^0.47b0" -opentelemetry-instrumentation-httpx = "^0.47b0" -opentelemetry-instrumentation = "^0.47b0" -opentelemetry-instrumentation-dbapi = "^0.47b0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-fastapi = "^0.48b0" +opentelemetry-instrumentation-psycopg2 = "^0.48b0" +opentelemetry-instrumentation-httpx = "^0.48b0" +opentelemetry-instrumentation = "^0.48b0" +opentelemetry-instrumentation-dbapi = "^0.48b0" pydantic-settings = "^2.2.1" python-multipart = "^0.0.9" httpx = "^0.27.0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" pyjwt = "^2.8.0" -fastapi-slim = "^0.111.0" +fastapi-slim = "^0.115.2" structlog = "^24.2.0" cryptography = "^43.0.1" boto3 = "^1.35.15" diff --git a/bytes/requirements-dev.txt b/bytes/requirements-dev.txt index 473609c5f83..080e03d15b4 100644 --- a/bytes/requirements-dev.txt +++ b/bytes/requirements-dev.txt @@ -322,9 +322,9 @@ deprecated==1.2.14 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.65.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63 \ --hash=sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0 @@ -543,45 +543,45 @@ markupsafe==2.1.5 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \ --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \ --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==24.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 @@ -823,9 +823,9 @@ sqlalchemy==1.4.54 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:f941aaf15f47f316123e1933f9ea91a6efda73a161a6ab6046d1cde37be62c88 \ --hash=sha256:fb59a11689ff3c58e7652260127f9e34f7f45478a2f3ef831ab6db7bcd72108f \ --hash=sha256:fc9ffd9a38e21fad3e8c5a88926d57f94a32546e937e0be46142b2702003eba7 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/bytes/requirements.txt b/bytes/requirements.txt index ef22e9d4cd6..76d584a0faa 100644 --- a/bytes/requirements.txt +++ b/bytes/requirements.txt @@ -249,9 +249,9 @@ deprecated==1.2.14 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.65.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63 \ --hash=sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0 @@ -467,45 +467,45 @@ markupsafe==2.1.5 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \ --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \ --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb passlib[bcrypt]==1.7.4 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1 \ --hash=sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04 @@ -732,9 +732,9 @@ sqlalchemy==1.4.54 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:f941aaf15f47f316123e1933f9ea91a6efda73a161a6ab6046d1cde37be62c88 \ --hash=sha256:fb59a11689ff3c58e7652260127f9e34f7f45478a2f3ef831ab6db7bcd72108f \ --hash=sha256:fc9ffd9a38e21fad3e8c5a88926d57f94a32546e937e0be46142b2702003eba7 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/keiko/poetry.lock b/keiko/poetry.lock index 739c91176d3..68bf25d1269 100644 --- a/keiko/poetry.lock +++ b/keiko/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "annotated-types" @@ -218,23 +218,23 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi-slim" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.111.1-py3-none-any.whl", hash = "sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb"}, - {file = "fastapi_slim-0.111.1.tar.gz", hash = "sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d"}, + {file = "fastapi_slim-0.115.2-py3-none-any.whl", hash = "sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d"}, + {file = "fastapi_slim-0.115.2.tar.gz", hash = "sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "googleapis-common-protos" @@ -532,42 +532,42 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -575,19 +575,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -597,55 +597,55 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -653,44 +653,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -1130,13 +1130,13 @@ files = [ [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -1315,4 +1315,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "7338400214b2a3115ffcedd084b7c3c1fc5468720e4f130ffd52efa23d6128c5" +content-hash = "e38a50f11805984c153302cb55e87703492d5c4b624744076dc07b731df07211" diff --git a/keiko/pyproject.toml b/keiko/pyproject.toml index 0fc91c44dec..fca2afed6b9 100644 --- a/keiko/pyproject.toml +++ b/keiko/pyproject.toml @@ -11,18 +11,18 @@ click = "^8.1.3" pydantic = "^2.6.0" Jinja2 = "^3.1.3" uvicorn = "^0.29.0" -opentelemetry-sdk = "^1.26.0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-fastapi = "^0.47b0" -opentelemetry-instrumentation = "^0.47b0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-fastapi = "^0.48b0" +opentelemetry-instrumentation = "^0.48b0" pydantic-settings = "^2.0.3" -fastapi-slim = "^0.111.0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" +fastapi-slim = "^0.115.2" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" [tool.poetry.group.dev.dependencies] pytest = "^8.0.0" diff --git a/keiko/requirements-dev.txt b/keiko/requirements-dev.txt index c5d00b26c98..4e5115e51fe 100644 --- a/keiko/requirements-dev.txt +++ b/keiko/requirements-dev.txt @@ -113,9 +113,9 @@ deprecated==1.2.14 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.0 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \ --hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68 -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.62.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:4750113612205514f9f6aa4cb00d523a94f3e8c06c5ad2fee466387dc4875f07 \ --hash=sha256:83f0ece9f94e5672cced82f592d2a5edf527a96ed1794f0bab36d5735c996277 @@ -254,36 +254,36 @@ markupsafe==2.1.5 ; python_version >= "3.10" and python_version < "4.0" \ mdurl==0.1.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==23.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 @@ -443,9 +443,9 @@ setuptools==71.0.3 ; python_version >= "3.10" and python_version < "4.0" \ sniffio==1.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 tomli==2.0.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f diff --git a/keiko/requirements.txt b/keiko/requirements.txt index 3640a1b39f9..5d751727e8b 100644 --- a/keiko/requirements.txt +++ b/keiko/requirements.txt @@ -19,9 +19,9 @@ deprecated==1.2.14 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.0 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \ --hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68 -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.62.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:4750113612205514f9f6aa4cb00d523a94f3e8c06c5ad2fee466387dc4875f07 \ --hash=sha256:83f0ece9f94e5672cced82f592d2a5edf527a96ed1794f0bab36d5735c996277 @@ -145,36 +145,36 @@ markupsafe==2.1.5 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \ --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \ --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb protobuf==4.25.3 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4 \ --hash=sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 \ @@ -292,9 +292,9 @@ setuptools==71.0.3 ; python_version >= "3.10" and python_version < "4.0" \ sniffio==1.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 diff --git a/mula/poetry.lock b/mula/poetry.lock index e75ea82fd4c..a240970e41f 100644 --- a/mula/poetry.lock +++ b/mula/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "alembic" @@ -283,23 +283,23 @@ python-dateutil = ">=2.4" [[package]] name = "fastapi-slim" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.111.1-py3-none-any.whl", hash = "sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb"}, - {file = "fastapi_slim-0.111.1.tar.gz", hash = "sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d"}, + {file = "fastapi_slim-0.115.2-py3-none-any.whl", hash = "sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d"}, + {file = "fastapi_slim-0.115.2.tar.gz", hash = "sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "googleapis-common-protos" @@ -727,42 +727,42 @@ test = ["mypy (>=1.0)", "pytest (>=7.0.0)"] [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -770,19 +770,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -792,111 +792,111 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Database API instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_dbapi-0.47b0-py3-none-any.whl", hash = "sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f"}, - {file = "opentelemetry_instrumentation_dbapi-0.47b0.tar.gz", hash = "sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-instrumentation-httpx" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry HTTPX Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_httpx-0.47b0-py3-none-any.whl", hash = "sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a"}, - {file = "opentelemetry_instrumentation_httpx-0.47b0.tar.gz", hash = "sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0-py3-none-any.whl", hash = "sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0.tar.gz", hash = "sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["httpx (>=0.18.0)"] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry psycopg2 instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.47b0-py3-none-any.whl", hash = "sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73"}, - {file = "opentelemetry_instrumentation_psycopg2-0.47b0.tar.gz", hash = "sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-dbapi = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-dbapi = "0.48b0" [package.extras] instruments = ["psycopg2 (>=2.7.3.1)"] [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -904,44 +904,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -1433,13 +1433,13 @@ sqlcipher = ["sqlcipher3_binary"] [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -1607,4 +1607,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "04369c4a49bc4040c2a09e2e0fc4e1fad8dc7e1f1c8cf6268895647e3f242550" +content-hash = "d97c193b02f8ad371dc014165a74b2c4110d6fa58fe23befc137aff01fdd4fc9" diff --git a/mula/pyproject.toml b/mula/pyproject.toml index 0f63c0ecbaf..a0f37771c69 100644 --- a/mula/pyproject.toml +++ b/mula/pyproject.toml @@ -23,20 +23,20 @@ uvicorn = "^0.29.0" httpx = "^0.27.0" # OpenTelemetry -opentelemetry-sdk = "^1.26.0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-fastapi = "^0.47b0" -opentelemetry-instrumentation-psycopg2 = "^0.47b0" -opentelemetry-instrumentation = "^0.47b0" -opentelemetry-instrumentation-httpx = "^0.47b0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-instrumentation-dbapi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" -fastapi-slim = "^0.111.0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-fastapi = "^0.48b0" +opentelemetry-instrumentation-psycopg2 = "^0.48b0" +opentelemetry-instrumentation = "^0.48b0" +opentelemetry-instrumentation-httpx = "^0.48b0" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-instrumentation-dbapi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" +fastapi-slim = "^0.115.2" [tool.poetry.group.dev.dependencies] factory_boy = "^3.2.1" diff --git a/mula/requirements-dev.txt b/mula/requirements-dev.txt index 19acac25555..f9691878d78 100644 --- a/mula/requirements-dev.txt +++ b/mula/requirements-dev.txt @@ -110,9 +110,9 @@ factory-boy==3.3.0 ; python_version >= "3.10" and python_version < "4.0" \ faker==26.2.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:7b123090774deff5f2cd3eb92a84dcbbf1e163f30a6d07321b7852c11bfe6a75 \ --hash=sha256:81768de19012147521140f0d8bf5353e501ac42c1065d25e0cac455d3615c0a7 -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.63.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945 \ --hash=sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87 @@ -385,45 +385,45 @@ mmh3==4.1.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124 \ --hash=sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970 \ --hash=sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==24.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 @@ -651,9 +651,9 @@ sqlalchemy==2.0.32 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:c41a2b9ca80ee555decc605bd3c4520cc6fef9abde8fd66b1cf65126a6922d65 \ --hash=sha256:c750987fc876813f27b60d619b987b057eb4896b81117f73bb8d9918c14f1cad \ --hash=sha256:e567a8793a692451f706b363ccf3c45e056b67d90ead58c3bc9471af5d212202 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==23.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:24b42b914ac6bc4a4e6f716e82ac70d7fb1e8c3b1035a765591953bfc37101a5 \ --hash=sha256:d6922a88ceabef5b13b9eda9c4043624924f60edbb00397f4d193bd754cde60a diff --git a/mula/requirements.txt b/mula/requirements.txt index d78029486ae..d32de48bd33 100644 --- a/mula/requirements.txt +++ b/mula/requirements.txt @@ -31,9 +31,9 @@ deprecated==1.2.14 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d googleapis-common-protos==1.63.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945 \ --hash=sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87 @@ -303,45 +303,45 @@ mmh3==4.1.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124 \ --hash=sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970 \ --hash=sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb pika==1.3.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:0779a7c1fafd805672796085560d290213a465e4f6f76a6fb19e378d8041a14f \ --hash=sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f @@ -540,9 +540,9 @@ sqlalchemy==2.0.32 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:c41a2b9ca80ee555decc605bd3c4520cc6fef9abde8fd66b1cf65126a6922d65 \ --hash=sha256:c750987fc876813f27b60d619b987b057eb4896b81117f73bb8d9918c14f1cad \ --hash=sha256:e567a8793a692451f706b363ccf3c45e056b67d90ead58c3bc9471af5d212202 -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==23.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:24b42b914ac6bc4a4e6f716e82ac70d7fb1e8c3b1035a765591953bfc37101a5 \ --hash=sha256:d6922a88ceabef5b13b9eda9c4043624924f60edbb00397f4d193bd754cde60a diff --git a/octopoes/poetry.lock b/octopoes/poetry.lock index 1e90e2a09e6..cfc938a7596 100644 --- a/octopoes/poetry.lock +++ b/octopoes/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "amqp" @@ -475,23 +475,23 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi-slim" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_slim-0.111.1-py3-none-any.whl", hash = "sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb"}, - {file = "fastapi_slim-0.111.1.tar.gz", hash = "sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d"}, + {file = "fastapi_slim-0.115.2-py3-none-any.whl", hash = "sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d"}, + {file = "fastapi_slim-0.115.2.tar.gz", hash = "sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email_validator (>=2.0.0)", "fastapi-cli (>=0.0.2)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "filelock" @@ -857,42 +857,42 @@ files = [ [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -900,19 +900,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -922,111 +922,111 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Database API instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_dbapi-0.47b0-py3-none-any.whl", hash = "sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f"}, - {file = "opentelemetry_instrumentation_dbapi-0.47b0.tar.gz", hash = "sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-instrumentation-httpx" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry HTTPX Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_httpx-0.47b0-py3-none-any.whl", hash = "sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a"}, - {file = "opentelemetry_instrumentation_httpx-0.47b0.tar.gz", hash = "sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0-py3-none-any.whl", hash = "sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0.tar.gz", hash = "sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["httpx (>=0.18.0)"] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry psycopg2 instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.47b0-py3-none-any.whl", hash = "sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73"}, - {file = "opentelemetry_instrumentation_psycopg2-0.47b0.tar.gz", hash = "sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-dbapi = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-dbapi = "0.48b0" [package.extras] instruments = ["psycopg2 (>=2.7.3.1)"] [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -1034,44 +1034,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -1829,13 +1829,13 @@ sqlcipher = ["sqlcipher3-binary"] [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -2120,4 +2120,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "b0e8830f05dab4fe189273276c62f1a8a2b49536f9e9b0c023417d0b2e6d0219" +content-hash = "92bc9750e398c155ac4e39064fd4c675bbce210e1985b8ad35a6015a7c702128" diff --git a/octopoes/pyproject.toml b/octopoes/pyproject.toml index b25829d0b41..ecb9297ed1e 100644 --- a/octopoes/pyproject.toml +++ b/octopoes/pyproject.toml @@ -21,27 +21,27 @@ celery = "^5.2.7" pyparsing = "^3.0.9" packaging = "^23.0" tldextract = "^3.4.0" -opentelemetry-sdk = "^1.26.0" -opentelemetry-instrumentation = "^0.47b0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-fastapi = "^0.47b0" -opentelemetry-instrumentation-psycopg2 = "^0.47b0" -opentelemetry-instrumentation-httpx = "^0.47b0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-instrumentation = "^0.48b0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-fastapi = "^0.48b0" +opentelemetry-instrumentation-psycopg2 = "^0.48b0" +opentelemetry-instrumentation-httpx = "^0.48b0" sqlalchemy = "1.4.48" jsonschema = "^4.18.0" pydantic-settings = "^2.2.1" httpx = "^0.27.0" # required by disallowed-csp-hostnames bit link-shorteners = "^1.11.0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-instrumentation-dbapi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-instrumentation-dbapi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" -fastapi-slim = "^0.111.0" +fastapi-slim = "^0.115.2" structlog = "^24.2.0" asgiref = "^3.8.1" diff --git a/octopoes/requirements-dev.txt b/octopoes/requirements-dev.txt index b9f40f68f42..acedabe47b9 100644 --- a/octopoes/requirements-dev.txt +++ b/octopoes/requirements-dev.txt @@ -193,9 +193,9 @@ dnspython==2.6.1 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.1 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad \ --hash=sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16 -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d filelock==3.14.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f \ --hash=sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a @@ -343,45 +343,45 @@ kombu==5.3.7 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9 link-shorteners==1.11.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:57cf820ca3edc823ac19c2bbef02c1ba94f0abbebe43536f66676047f2cdd711 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==23.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 @@ -750,9 +750,9 @@ sqlalchemy==1.4.48 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:fb0808ad34167f394fea21bd4587fc62f3bd81bba232a1e7fbdfa17e6cfa7cd7 \ --hash=sha256:fbde5642104ac6e95f96e8ad6d18d9382aa20672008cf26068fe36f3004491df \ --hash=sha256:fe1dd2562313dd9fe1778ed56739ad5d9aae10f9f43d9f4cf81d65b0c85168bb -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/octopoes/requirements.txt b/octopoes/requirements.txt index 4238ee2c50f..7cbd10306fc 100644 --- a/octopoes/requirements.txt +++ b/octopoes/requirements.txt @@ -137,9 +137,9 @@ dnspython==2.6.1 ; python_version >= "3.10" and python_version < "4.0" \ exceptiongroup==1.2.1 ; python_version >= "3.10" and python_version < "3.11" \ --hash=sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad \ --hash=sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16 -fastapi-slim==0.111.1 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:ac29948dcbf84cc78d68ed2c4df4e695ac265cf53c339e5794008476e9befbbb \ - --hash=sha256:f799a60658f56c49fe3842eb534730fabe1168731c0b407b98a042c8d57be39d +fastapi-slim==0.115.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:7dd65a58e9b2a1558ebd479d35e621417d4572188d902a3e5564739914ddc81d \ + --hash=sha256:83a1ce1e385029cad305b49dcc03622d2be6a905b2ab65d2e7096285605cca8d filelock==3.14.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f \ --hash=sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a @@ -278,45 +278,45 @@ kombu==5.3.7 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9 link-shorteners==1.11.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:57cf820ca3edc823ac19c2bbef02c1ba94f0abbebe43536f66676047f2cdd711 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb packaging==23.2 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 @@ -653,9 +653,9 @@ sqlalchemy==1.4.48 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:fb0808ad34167f394fea21bd4587fc62f3bd81bba232a1e7fbdfa17e6cfa7cd7 \ --hash=sha256:fbde5642104ac6e95f96e8ad6d18d9382aa20672008cf26068fe36f3004491df \ --hash=sha256:fe1dd2562313dd9fe1778ed56739ad5d9aae10f9f43d9f4cf81d65b0c85168bb -starlette==0.37.2 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \ - --hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823 +starlette==0.40.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35 \ + --hash=sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4 structlog==24.4.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610 \ --hash=sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4 diff --git a/rocky/poetry.lock b/rocky/poetry.lock index b366f004844..693aeb29907 100644 --- a/rocky/poetry.lock +++ b/rocky/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "annotated-types" @@ -1540,42 +1540,42 @@ django = ">=1.11.0" [[package]] name = "opentelemetry-api" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"}, - {file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"}, + {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, + {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.0.0" +importlib-metadata = ">=6.0,<=8.4.0" [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Protobuf encoding" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0-py3-none-any.whl", hash = "sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.26.0.tar.gz", hash = "sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, ] [package.dependencies] -opentelemetry-proto = "1.26.0" +opentelemetry-proto = "1.27.0" [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Collector Protobuf over gRPC Exporter" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0-py3-none-any.whl", hash = "sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.26.0.tar.gz", hash = "sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, ] [package.dependencies] @@ -1583,19 +1583,19 @@ deprecated = ">=1.2.6" googleapis-common-protos = ">=1.52,<2.0" grpcio = ">=1.0.0,<2.0.0" opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.26.0" -opentelemetry-proto = "1.26.0" -opentelemetry-sdk = ">=1.26.0,<1.27.0" +opentelemetry-exporter-otlp-proto-common = "1.27.0" +opentelemetry-proto = "1.27.0" +opentelemetry-sdk = ">=1.27.0,<1.28.0" [[package]] name = "opentelemetry-instrumentation" -version = "0.47b0" +version = "0.48b0" description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation-0.47b0-py3-none-any.whl", hash = "sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5"}, - {file = "opentelemetry_instrumentation-0.47b0.tar.gz", hash = "sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f"}, + {file = "opentelemetry_instrumentation-0.48b0-py3-none-any.whl", hash = "sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44"}, + {file = "opentelemetry_instrumentation-0.48b0.tar.gz", hash = "sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35"}, ] [package.dependencies] @@ -1605,150 +1605,150 @@ wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-asgi" -version = "0.47b0" +version = "0.48b0" description = "ASGI instrumentation for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_asgi-0.47b0-py3-none-any.whl", hash = "sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade"}, - {file = "opentelemetry_instrumentation_asgi-0.47b0.tar.gz", hash = "sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0-py3-none-any.whl", hash = "sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d"}, + {file = "opentelemetry_instrumentation_asgi-0.48b0.tar.gz", hash = "sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785"}, ] [package.dependencies] asgiref = ">=3.0,<4.0" opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["asgiref (>=3.0,<4.0)"] [[package]] name = "opentelemetry-instrumentation-dbapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Database API instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_dbapi-0.47b0-py3-none-any.whl", hash = "sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f"}, - {file = "opentelemetry_instrumentation_dbapi-0.47b0.tar.gz", hash = "sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0-py3-none-any.whl", hash = "sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb"}, + {file = "opentelemetry_instrumentation_dbapi-0.48b0.tar.gz", hash = "sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" wrapt = ">=1.0.0,<2.0.0" [[package]] name = "opentelemetry-instrumentation-django" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Instrumentation for Django" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_django-0.47b0-py3-none-any.whl", hash = "sha256:85d5d5dd4047945917b823879933a28efddcf06d5f7fabef5ac806226602b18d"}, - {file = "opentelemetry_instrumentation_django-0.47b0.tar.gz", hash = "sha256:f23c97ffa9b9b0d06a76e4a5296f189cc6e02f66c29a0ca30a97b0ea121a30b9"}, + {file = "opentelemetry_instrumentation_django-0.48b0-py3-none-any.whl", hash = "sha256:e6742744ee1cfbfee8a6b57182a2071475531b79863411e1eb5f0d5b5322b7b4"}, + {file = "opentelemetry_instrumentation_django-0.48b0.tar.gz", hash = "sha256:d31fca8bdf5a75e004a459f2eb3fcba707fbb0a39fc3d3c520c38265775cb9df"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-wsgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-wsgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -asgi = ["opentelemetry-instrumentation-asgi (==0.47b0)"] +asgi = ["opentelemetry-instrumentation-asgi (==0.48b0)"] instruments = ["django (>=1.10)"] [[package]] name = "opentelemetry-instrumentation-fastapi" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry FastAPI Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_fastapi-0.47b0-py3-none-any.whl", hash = "sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21"}, - {file = "opentelemetry_instrumentation_fastapi-0.47b0.tar.gz", hash = "sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0-py3-none-any.whl", hash = "sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2"}, + {file = "opentelemetry_instrumentation_fastapi-0.48b0.tar.gz", hash = "sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-asgi = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-asgi = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] -instruments = ["fastapi (>=0.58,<1.0)", "fastapi-slim (>=0.111.0,<0.112.0)"] +instruments = ["fastapi (>=0.58,<1.0)"] [[package]] name = "opentelemetry-instrumentation-httpx" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry HTTPX Instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_httpx-0.47b0-py3-none-any.whl", hash = "sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a"}, - {file = "opentelemetry_instrumentation_httpx-0.47b0.tar.gz", hash = "sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0-py3-none-any.whl", hash = "sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5"}, + {file = "opentelemetry_instrumentation_httpx-0.48b0.tar.gz", hash = "sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [package.extras] instruments = ["httpx (>=0.18.0)"] [[package]] name = "opentelemetry-instrumentation-psycopg2" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry psycopg2 instrumentation" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_psycopg2-0.47b0-py3-none-any.whl", hash = "sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73"}, - {file = "opentelemetry_instrumentation_psycopg2-0.47b0.tar.gz", hash = "sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0-py3-none-any.whl", hash = "sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4"}, + {file = "opentelemetry_instrumentation_psycopg2-0.48b0.tar.gz", hash = "sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-instrumentation-dbapi = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-instrumentation-dbapi = "0.48b0" [package.extras] instruments = ["psycopg2 (>=2.7.3.1)"] [[package]] name = "opentelemetry-instrumentation-wsgi" -version = "0.47b0" +version = "0.48b0" description = "WSGI Middleware for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_instrumentation_wsgi-0.47b0-py3-none-any.whl", hash = "sha256:9a1a78aa2f5682fe1073c4cc77f24ef4f083b18b66bbb674a995b0b77eef1815"}, - {file = "opentelemetry_instrumentation_wsgi-0.47b0.tar.gz", hash = "sha256:4903c3d686d53ca7ab6545bb4cc42c3de8af5b2f370996e84db2cfec688860af"}, + {file = "opentelemetry_instrumentation_wsgi-0.48b0-py3-none-any.whl", hash = "sha256:c6051124d741972090fe94b2fa302555e1e2a22e9cdda32dd39ed49a5b34e0c6"}, + {file = "opentelemetry_instrumentation_wsgi-0.48b0.tar.gz", hash = "sha256:1a1e752367b0df4397e0b835839225ef5c2c3c053743a261551af13434fc4d51"}, ] [package.dependencies] opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.47b0" -opentelemetry-semantic-conventions = "0.47b0" -opentelemetry-util-http = "0.47b0" +opentelemetry-instrumentation = "0.48b0" +opentelemetry-semantic-conventions = "0.48b0" +opentelemetry-util-http = "0.48b0" [[package]] name = "opentelemetry-proto" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python Proto" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_proto-1.26.0-py3-none-any.whl", hash = "sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725"}, - {file = "opentelemetry_proto-1.26.0.tar.gz", hash = "sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e"}, + {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, + {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, ] [package.dependencies] @@ -1756,44 +1756,44 @@ protobuf = ">=3.19,<5.0" [[package]] name = "opentelemetry-sdk" -version = "1.26.0" +version = "1.27.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"}, - {file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"}, + {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, + {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, ] [package.dependencies] -opentelemetry-api = "1.26.0" -opentelemetry-semantic-conventions = "0.47b0" +opentelemetry-api = "1.27.0" +opentelemetry-semantic-conventions = "0.48b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.47b0" +version = "0.48b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"}, - {file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"}, + {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, + {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, ] [package.dependencies] deprecated = ">=1.2.6" -opentelemetry-api = "1.26.0" +opentelemetry-api = "1.27.0" [[package]] name = "opentelemetry-util-http" -version = "0.47b0" +version = "0.48b0" description = "Web util for OpenTelemetry" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_util_http-0.47b0-py3-none-any.whl", hash = "sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19"}, - {file = "opentelemetry_util_http-0.47b0.tar.gz", hash = "sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32"}, + {file = "opentelemetry_util_http-0.48b0-py3-none-any.whl", hash = "sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb"}, + {file = "opentelemetry_util_http-0.48b0.tar.gz", hash = "sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c"}, ] [[package]] @@ -3452,4 +3452,4 @@ test = ["pytest"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "3eac7130e42b969703acc8afe46e1e0dfe9e9861b3ecf1bedc080dca42629860" +content-hash = "75d2a4a68b5c545a524ad38f9348fc384ddeb38a34197027d1942ba67e8c8840" diff --git a/rocky/pyproject.toml b/rocky/pyproject.toml index bed8c85a5a5..14a30a4b254 100644 --- a/rocky/pyproject.toml +++ b/rocky/pyproject.toml @@ -27,29 +27,29 @@ strenum = "^0.4.15" django-rest-knox = { git = "https://github.com/jazzband/django-rest-knox", rev = "dd7b062147bc4b9718e22d5acd6cf1301a1036b9" } # OpenTelemetry -opentelemetry-sdk = "^1.26.0" -opentelemetry-exporter-otlp-proto-grpc = "^1.26.0" -opentelemetry-instrumentation-django = "^0.47b0" -opentelemetry-instrumentation-psycopg2 = "^0.47b0" +opentelemetry-sdk = "^1.27.0" +opentelemetry-exporter-otlp-proto-grpc = "^1.27.0" +opentelemetry-instrumentation-django = "^0.48b0" +opentelemetry-instrumentation-psycopg2 = "^0.48b0" whitenoise = { extras = ["brotli"], version = "^6.5.0" } -opentelemetry-instrumentation = "^0.47b0" -opentelemetry-instrumentation-fastapi = "^0.47b0" +opentelemetry-instrumentation = "^0.48b0" +opentelemetry-instrumentation-fastapi = "^0.48b0" granian = "^1.3.2" django-components = "^0.88" # These used in octopoes parts that are used by rocky pyparsing = "^3.1.1" pydantic-settings = "^2.0.3" -opentelemetry-instrumentation-httpx = "^0.47b0" +opentelemetry-instrumentation-httpx = "^0.48b0" httpx = "^0.27.0" -opentelemetry-api = "^1.26.0" -opentelemetry-exporter-otlp-proto-common = "^1.26.0" -opentelemetry-instrumentation-asgi = "^0.47b0" -opentelemetry-instrumentation-dbapi = "^0.47b0" -opentelemetry-instrumentation-wsgi = "^0.47b0" -opentelemetry-proto = "^1.26.0" -opentelemetry-semantic-conventions = "^0.47b0" -opentelemetry-util-http = "^0.47b0" +opentelemetry-api = "^1.27.0" +opentelemetry-exporter-otlp-proto-common = "^1.27.0" +opentelemetry-instrumentation-asgi = "^0.48b0" +opentelemetry-instrumentation-dbapi = "^0.48b0" +opentelemetry-instrumentation-wsgi = "^0.48b0" +opentelemetry-proto = "^1.27.0" +opentelemetry-semantic-conventions = "^0.48b0" +opentelemetry-util-http = "^0.48b0" structlog = "^24.2.0" django-structlog = "^8.1.0" diff --git a/rocky/requirements-dev.txt b/rocky/requirements-dev.txt index 19e1319b237..034f4de51e1 100644 --- a/rocky/requirements-dev.txt +++ b/rocky/requirements-dev.txt @@ -663,51 +663,51 @@ mdurl==0.1.2 ; python_version >= "3.10" and python_version < "4.0" \ model-mommy==2.0.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:3d332afce941c57f1990f45b083ba13252ba74fcd1ae43fd047e5af7a70fb312 \ --hash=sha256:40d6e740aad7509e696a324b94cf2b0a104da93c3d4a7924cea1be3d0eb95b4f -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-django==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:85d5d5dd4047945917b823879933a28efddcf06d5f7fabef5ac806226602b18d \ - --hash=sha256:f23c97ffa9b9b0d06a76e4a5296f189cc6e02f66c29a0ca30a97b0ea121a30b9 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation-wsgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4903c3d686d53ca7ab6545bb4cc42c3de8af5b2f370996e84db2cfec688860af \ - --hash=sha256:9a1a78aa2f5682fe1073c4cc77f24ef4f083b18b66bbb674a995b0b77eef1815 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-django==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d31fca8bdf5a75e004a459f2eb3fcba707fbb0a39fc3d3c520c38265775cb9df \ + --hash=sha256:e6742744ee1cfbfee8a6b57182a2071475531b79863411e1eb5f0d5b5322b7b4 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation-wsgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a1e752367b0df4397e0b835839225ef5c2c3c053743a261551af13434fc4d51 \ + --hash=sha256:c6051124d741972090fe94b2fa302555e1e2a22e9cdda32dd39ed49a5b34e0c6 +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb overrides==7.7.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ --hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49 diff --git a/rocky/requirements.txt b/rocky/requirements.txt index 8c5719d2f2d..3e401c09846 100644 --- a/rocky/requirements.txt +++ b/rocky/requirements.txt @@ -420,51 +420,51 @@ jsonschema-specifications==2023.12.1 ; python_version >= "3.10" and python_versi jsonschema==4.21.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f \ --hash=sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5 -opentelemetry-api==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ - --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 -opentelemetry-exporter-otlp-proto-common==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ - --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 -opentelemetry-exporter-otlp-proto-grpc==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ - --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 -opentelemetry-instrumentation-asgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:b798dc4957b3edc9dfecb47a4c05809036a4b762234c5071212fda39ead80ade \ - --hash=sha256:e78b7822c1bca0511e5e9610ec484b8994a81670375e570c76f06f69af7c506a -opentelemetry-instrumentation-dbapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a160029dfffdb9716ce3908f140afe7c91a4704fbe42fc623341fc5645440f \ - --hash=sha256:31fe72b7f45467592880ded77bb19aa4c04d126228684de9f0b46318325b9d50 -opentelemetry-instrumentation-django==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:85d5d5dd4047945917b823879933a28efddcf06d5f7fabef5ac806226602b18d \ - --hash=sha256:f23c97ffa9b9b0d06a76e4a5296f189cc6e02f66c29a0ca30a97b0ea121a30b9 -opentelemetry-instrumentation-fastapi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:0c7c10b5d971e99a420678ffd16c5b1ea4f0db3b31b62faf305fbb03b4ebee36 \ - --hash=sha256:5ac28dd401160b02e4f544a85a9e4f61a8cbe5b077ea0379d411615376a2bd21 -opentelemetry-instrumentation-httpx==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:24a2db480919b326e50c6a5ad01bb53b717fbd4116bb4d736d104608bf34a25a \ - --hash=sha256:4a4f7ff4726445e81aaedc025ee0f9ac66c2e9074987879082edea882c4aa22d -opentelemetry-instrumentation-psycopg2==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:35085c295d1ef9b299ba7fb0ed19e6ff31c2be010b3e7371df196c17a43885f8 \ - --hash=sha256:838fd49caf1b4fef0b5e436970e34eb1a9f79f76439ecf6383169053d0c72a73 -opentelemetry-instrumentation-wsgi==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4903c3d686d53ca7ab6545bb4cc42c3de8af5b2f370996e84db2cfec688860af \ - --hash=sha256:9a1a78aa2f5682fe1073c4cc77f24ef4f083b18b66bbb674a995b0b77eef1815 -opentelemetry-instrumentation==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ - --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f -opentelemetry-proto==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ - --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e -opentelemetry-sdk==1.26.0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ - --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 -opentelemetry-semantic-conventions==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ - --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e -opentelemetry-util-http==0.47b0 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ - --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 +opentelemetry-api==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7 \ + --hash=sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342 +opentelemetry-exporter-otlp-proto-common==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8 \ + --hash=sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a +opentelemetry-exporter-otlp-proto-grpc==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e \ + --hash=sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f +opentelemetry-instrumentation-asgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:04c32174b23c7fa72ddfe192dad874954968a6a924608079af9952964ecdf785 \ + --hash=sha256:ddb1b5fc800ae66e85a4e2eca4d9ecd66367a8c7b556169d9e7b57e10676e44d +opentelemetry-instrumentation-dbapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:0d11a73ecbf55b11e8fbc93e9e97366958b98ccb4b691c776b32e4b20b3ce8bb \ + --hash=sha256:89821288199f4f5225e74543bf14addf9b1824b8b5f1e83ad0d9dafa844f33b0 +opentelemetry-instrumentation-django==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d31fca8bdf5a75e004a459f2eb3fcba707fbb0a39fc3d3c520c38265775cb9df \ + --hash=sha256:e6742744ee1cfbfee8a6b57182a2071475531b79863411e1eb5f0d5b5322b7b4 +opentelemetry-instrumentation-fastapi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:21a72563ea412c0b535815aeed75fc580240f1f02ebc72381cfab672648637a2 \ + --hash=sha256:afeb820a59e139d3e5d96619600f11ce0187658b8ae9e3480857dd790bc024f2 +opentelemetry-instrumentation-httpx==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5 \ + --hash=sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a +opentelemetry-instrumentation-psycopg2==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:6a935f33b3d8908bee29b6b178bf84e56d93902c31282714113ffec922056aa4 \ + --hash=sha256:f86c8d15deefe80475d9778ddc425e1ae56b325ecb32653e2ad0f78abef1717d +opentelemetry-instrumentation-wsgi==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:1a1e752367b0df4397e0b835839225ef5c2c3c053743a261551af13434fc4d51 \ + --hash=sha256:c6051124d741972090fe94b2fa302555e1e2a22e9cdda32dd39ed49a5b34e0c6 +opentelemetry-instrumentation==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:94929685d906380743a71c3970f76b5f07476eea1834abd5dd9d17abfe23cc35 \ + --hash=sha256:a69750dc4ba6a5c3eb67986a337185a25b739966d80479befe37b546fc870b44 +opentelemetry-proto==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ + --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace +opentelemetry-sdk==1.27.0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d \ + --hash=sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f +opentelemetry-semantic-conventions==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a \ + --hash=sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f +opentelemetry-util-http==0.48b0 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:60312015153580cc20f322e5cdc3d3ecad80a71743235bdb77716e742814623c \ + --hash=sha256:76f598af93aab50328d2a69c786beaedc8b6a7770f7a818cc307eb353debfffb phonenumbers==8.13.42 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:18acc22ee03116d27b26e990f53806a1770a3e05f05e1620bc09ad187f889456 \ --hash=sha256:7137904f2db3b991701e853174ce8e1cb8f540b8bfdf27617540de04c0b7bed5 From 718d097b466304190681d1ab02f23972ece146a6 Mon Sep 17 00:00:00 2001 From: Jeroen Dekkers Date: Wed, 16 Oct 2024 13:13:10 +0200 Subject: [PATCH 17/25] Github action should trigger if workflow definition changes (#3680) Co-authored-by: Jan Klopper --- .github/workflows/boefjes_tests.yml | 2 ++ .github/workflows/build_docs_on_pr.yml | 1 + .github/workflows/bytes_tests.yml | 2 ++ .github/workflows/check_poetry_dependencies.yml | 2 ++ .github/workflows/keiko_itest.yml | 2 ++ .github/workflows/keiko_tex_linters.yml | 2 ++ .github/workflows/mula_tests.yml | 2 ++ .github/workflows/octopoes_rtest.yml | 2 ++ .github/workflows/octopoes_tests.yml | 2 ++ .github/workflows/rocky_tests.yml | 2 ++ 10 files changed, 19 insertions(+) diff --git a/.github/workflows/boefjes_tests.yml b/.github/workflows/boefjes_tests.yml index ec54de75776..a4c8437fc10 100644 --- a/.github/workflows/boefjes_tests.yml +++ b/.github/workflows/boefjes_tests.yml @@ -10,10 +10,12 @@ on: paths: - boefjes/** - octopoes/** + - .github/workflows/boefjes_test.yml pull_request: paths: - boefjes/** - octopoes/** + - .github/workflows/boefjes_test.yml jobs: Tests: diff --git a/.github/workflows/build_docs_on_pr.yml b/.github/workflows/build_docs_on_pr.yml index 917af6ce497..51bfa56094b 100644 --- a/.github/workflows/build_docs_on_pr.yml +++ b/.github/workflows/build_docs_on_pr.yml @@ -5,6 +5,7 @@ on: paths: - "docs/**" - "requirements.txt" + - ".github/workflows/build_docs_on_pr.yml" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/.github/workflows/bytes_tests.yml b/.github/workflows/bytes_tests.yml index 7c6660c9c46..04dd2354881 100644 --- a/.github/workflows/bytes_tests.yml +++ b/.github/workflows/bytes_tests.yml @@ -9,9 +9,11 @@ on: - "*" paths: - bytes/** + - .github/workflows/bytes_test.yml pull_request: paths: - bytes/** + - .github/workflows/bytes_test.yml jobs: test: diff --git a/.github/workflows/check_poetry_dependencies.yml b/.github/workflows/check_poetry_dependencies.yml index 7273790f122..501490f33d6 100644 --- a/.github/workflows/check_poetry_dependencies.yml +++ b/.github/workflows/check_poetry_dependencies.yml @@ -12,12 +12,14 @@ on: - "**/requirements-dev.txt" - "**/pyproject.toml" - "**/poetry.lock" + - ".github/workflows/check_poetry_dependencies.yml" pull_request: paths: - "**/requirements.txt" - "**/requirements-dev.txt" - "**/pyproject.toml" - "**/poetry.lock" + - ".github/workflows/check_poetry_dependencies.yml" jobs: poetry-dependencies: diff --git a/.github/workflows/keiko_itest.yml b/.github/workflows/keiko_itest.yml index aaed0e8e87f..acd59d4fcdb 100644 --- a/.github/workflows/keiko_itest.yml +++ b/.github/workflows/keiko_itest.yml @@ -9,9 +9,11 @@ on: - "*" paths: - keiko/** + - .github/workflows/keiko_itest.yml pull_request: paths: - keiko/** + - .github/workflows/keiko_itest.yml jobs: itest: diff --git a/.github/workflows/keiko_tex_linters.yml b/.github/workflows/keiko_tex_linters.yml index 55b183f38a4..e46c3631606 100644 --- a/.github/workflows/keiko_tex_linters.yml +++ b/.github/workflows/keiko_tex_linters.yml @@ -9,9 +9,11 @@ on: - "*" paths: - keiko/** + - .github/workflows/keiko_tex_linters.yml pull_request: paths: - keiko/** + - .github/workflows/keiko_tex_linters.yml jobs: check-latex: diff --git a/.github/workflows/mula_tests.yml b/.github/workflows/mula_tests.yml index cf9e9163088..737d936691a 100644 --- a/.github/workflows/mula_tests.yml +++ b/.github/workflows/mula_tests.yml @@ -9,9 +9,11 @@ on: - "*" paths: - mula/** + - .github/workflows/mula_test.yml pull_request: paths: - mula/** + - .github/workflows/mula_test.yml jobs: test: diff --git a/.github/workflows/octopoes_rtest.yml b/.github/workflows/octopoes_rtest.yml index e3dbb27a423..adb3bc07b8a 100644 --- a/.github/workflows/octopoes_rtest.yml +++ b/.github/workflows/octopoes_rtest.yml @@ -9,9 +9,11 @@ on: - "*" paths: - octopoes/** + - .github/workflows/octopoes_rtest.yml pull_request: paths: - octopoes/** + - .github/workflows/octopoes_rtest.yml jobs: rtest: diff --git a/.github/workflows/octopoes_tests.yml b/.github/workflows/octopoes_tests.yml index 6ee6e006fe1..a9481783532 100644 --- a/.github/workflows/octopoes_tests.yml +++ b/.github/workflows/octopoes_tests.yml @@ -9,9 +9,11 @@ on: - "*" paths: - octopoes/** + - .github/workflows/octopoes_test.yml pull_request: paths: - octopoes/** + - .github/workflows/octopoes_test.yml jobs: test: diff --git a/.github/workflows/rocky_tests.yml b/.github/workflows/rocky_tests.yml index cf037dd1901..ea18290f26e 100644 --- a/.github/workflows/rocky_tests.yml +++ b/.github/workflows/rocky_tests.yml @@ -10,10 +10,12 @@ on: paths: - octopoes/** - rocky/** + - .github/workflows/rocky_test.yml pull_request: paths: - octopoes/** - rocky/** + - .github/workflows/rocky_test.yml jobs: test: From 6e40e5251b62ea4e9b3c0ed95fbfd6c9a0a94d5d Mon Sep 17 00:00:00 2001 From: Jeroen Dekkers Date: Wed, 16 Oct 2024 13:35:10 +0200 Subject: [PATCH 18/25] Do not run dh_strip_nondeterminism in Debian packaging (#3674) Co-authored-by: Jan Klopper Co-authored-by: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> --- boefjes/debian/rules | 3 +++ bytes/debian/rules | 3 +++ keiko/debian/rules | 3 +++ mula/debian/rules | 3 +++ octopoes/debian/rules | 3 +++ rocky/debian/rules | 3 +++ 6 files changed, 18 insertions(+) diff --git a/boefjes/debian/rules b/boefjes/debian/rules index ce5a950e9cf..0d93df07cf9 100755 --- a/boefjes/debian/rules +++ b/boefjes/debian/rules @@ -45,3 +45,6 @@ override_dh_installsystemd: dh_installsystemd --name=kat-normalizers dh_installsystemd --name=kat-katalogus sed -i s/python3.9/`py3versions -d`/ debian/kat-boefjes/lib/systemd/system/*.service + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: diff --git a/bytes/debian/rules b/bytes/debian/rules index d55f2f80840..cabf6486e05 100755 --- a/bytes/debian/rules +++ b/bytes/debian/rules @@ -34,3 +34,6 @@ override_dh_gencontrol: execute_after_dh_install: dh_installsysusers + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: diff --git a/keiko/debian/rules b/keiko/debian/rules index 629869b5d55..46448935c55 100755 --- a/keiko/debian/rules +++ b/keiko/debian/rules @@ -32,3 +32,6 @@ override_dh_gencontrol: execute_after_dh_install: dh_installsysusers + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: diff --git a/mula/debian/rules b/mula/debian/rules index f7fb3cf76fe..46f62bb67d2 100755 --- a/mula/debian/rules +++ b/mula/debian/rules @@ -32,3 +32,6 @@ override_dh_gencontrol: execute_after_dh_install: dh_installsysusers + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: diff --git a/octopoes/debian/rules b/octopoes/debian/rules index f0aea9338e2..7b7ca6edb84 100755 --- a/octopoes/debian/rules +++ b/octopoes/debian/rules @@ -34,3 +34,6 @@ override_dh_installsystemd: execute_after_dh_install: dh_installsysusers + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: diff --git a/rocky/debian/rules b/rocky/debian/rules index 7cf60d790a4..8ef40792426 100755 --- a/rocky/debian/rules +++ b/rocky/debian/rules @@ -56,3 +56,6 @@ override_dh_installsystemd: execute_after_dh_install: dh_installsysusers + +# Disables dh_strip_nondeterminism because it very slow and not useful for us +override_dh_strip_nondeterminism: From 0f31898e0062fa3f4a1f52108628d22d3852737b Mon Sep 17 00:00:00 2001 From: originalsouth Date: Wed, 16 Oct 2024 14:16:31 +0200 Subject: [PATCH 19/25] Fix first order dangling affirmation delete (#3682) Co-authored-by: ammar92 Co-authored-by: Jan Klopper --- octopoes/octopoes/core/service.py | 13 ++++ .../repositories/origin_repository.py | 9 ++- .../tests/integration/test_ooi_deletion.py | 73 +++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/octopoes/octopoes/core/service.py b/octopoes/octopoes/core/service.py index 8b94efa01a9..9fcea0750fc 100644 --- a/octopoes/octopoes/core/service.py +++ b/octopoes/octopoes/core/service.py @@ -178,6 +178,19 @@ def save_origin( logger.debug("Affirmation source %s already deleted", origin.source) return + if origin.origin_type == OriginType.AFFIRMATION and not any( + other_origin + for other_origin in self.origin_repository.list_origins( + origin_type={OriginType.DECLARATION, OriginType.OBSERVATION, OriginType.INFERENCE}, + valid_time=valid_time, + result=origin.source, + ) + if not (other_origin.origin_type == OriginType.INFERENCE and [other_origin.source] == other_origin.result) + ): + logger.debug("Affirmation source %s seems dangling, deleting", origin.source) + self.ooi_repository.delete(origin.source, valid_time) + return + for ooi in oois: self.ooi_repository.save(ooi, valid_time=valid_time, end_valid_time=end_valid_time) self.origin_repository.save(origin, valid_time=valid_time) diff --git a/octopoes/octopoes/repositories/origin_repository.py b/octopoes/octopoes/repositories/origin_repository.py index 5c15f69cd0c..fa7c102b6f7 100644 --- a/octopoes/octopoes/repositories/origin_repository.py +++ b/octopoes/octopoes/repositories/origin_repository.py @@ -37,7 +37,7 @@ def list_origins( source: Reference | None = None, result: Reference | None = None, method: str | list[str] | None = None, - origin_type: OriginType | None = None, + origin_type: OriginType | list[OriginType] | set[OriginType] | None = None, ) -> list[Origin]: raise NotImplementedError @@ -77,7 +77,7 @@ def list_origins( source: Reference | None = None, result: Reference | None = None, method: str | list[str] | None = None, - origin_type: OriginType | None = None, + origin_type: OriginType | list[OriginType] | set[OriginType] | None = None, ) -> list[Origin]: where_parameters: dict[str, str | list[str]] = {"type": Origin.__name__} @@ -94,7 +94,10 @@ def list_origins( where_parameters["method"] = method if origin_type: - where_parameters["origin_type"] = origin_type.value + if isinstance(origin_type, OriginType): + where_parameters["origin_type"] = origin_type.value + elif isinstance(origin_type, list | set) and all(isinstance(otype, OriginType) for otype in origin_type): + where_parameters["origin_type"] = [otype.value for otype in origin_type] query = generate_pull_query(FieldSet.ALL_FIELDS, where_parameters, offset=offset, limit=limit) diff --git a/octopoes/tests/integration/test_ooi_deletion.py b/octopoes/tests/integration/test_ooi_deletion.py index 3bdfef317b6..1a3da5d68c8 100644 --- a/octopoes/tests/integration/test_ooi_deletion.py +++ b/octopoes/tests/integration/test_ooi_deletion.py @@ -15,6 +15,7 @@ from octopoes.models.ooi.dns.records import NXDOMAIN, DNSARecord from octopoes.models.ooi.dns.zone import Hostname from octopoes.models.ooi.findings import Finding, KATFindingType +from octopoes.models.ooi.monitoring import Application from octopoes.models.ooi.network import IPAddressV4, Network from octopoes.models.ooi.software import Software, SoftwareInstance from octopoes.models.origin import Origin, OriginType @@ -511,3 +512,75 @@ def test_delecration_ooi_delete(octopoes_api_connector: OctopoesAPIConnector, va octopoes_api_connector.delete(network.reference, valid_time) time.sleep(1) assert octopoes_api_connector.list_objects({Hostname}, valid_time).count == 1 + + +def test_dangling_affirmation_delete(xtdb_octopoes_service: OctopoesService, event_manager: Mock, valid_time: datetime): + app = Application(name="Acme") + + xtdb_octopoes_service.ooi_repository.save(app, valid_time) + time.sleep(1) + + declaration = Origin( + origin_type=OriginType.DECLARATION, + method="", + source=app.reference, + result=[app.reference], + task_id=uuid.uuid4(), + ) + + xtdb_octopoes_service.save_origin(declaration, [app], valid_time) + time.sleep(1) + event_manager.complete_process_events(xtdb_octopoes_service) + time.sleep(1) + + assert xtdb_octopoes_service.list_ooi({Application}, valid_time).count == 1 + assert ( + len( + xtdb_octopoes_service.origin_repository.list_origins( + origin_type=OriginType.DECLARATION, valid_time=valid_time + ) + ) + == 1 + ) + + xtdb_octopoes_service.origin_repository.delete(declaration, valid_time) + time.sleep(1) + event_manager.complete_process_events(xtdb_octopoes_service) + time.sleep(1) + + assert xtdb_octopoes_service.list_ooi({Application}, valid_time).count == 0 + assert ( + len( + xtdb_octopoes_service.origin_repository.list_origins( + origin_type=OriginType.DECLARATION, valid_time=valid_time + ) + ) + == 0 + ) + + xtdb_octopoes_service.ooi_repository.save(app, valid_time) + xtdb_octopoes_service.commit() + time.sleep(1) + + affirmation = Origin( + origin_type=OriginType.AFFIRMATION, + method="", + source=app.reference, + result=[app.reference], + task_id=uuid.uuid4(), + ) + + xtdb_octopoes_service.save_origin(affirmation, [app], valid_time) + time.sleep(1) + event_manager.complete_process_events(xtdb_octopoes_service) + time.sleep(1) + + assert xtdb_octopoes_service.list_ooi({Application}, valid_time).count == 0 + assert ( + len( + xtdb_octopoes_service.origin_repository.list_origins( + origin_type=OriginType.AFFIRMATION, valid_time=valid_time + ) + ) + == 0 + ) From 495522bfe9a87a7e19bcaabae69bb0f7addf6de4 Mon Sep 17 00:00:00 2001 From: Jeroen Dekkers Date: Wed, 16 Oct 2024 15:25:29 +0200 Subject: [PATCH 20/25] Fix javascript and component template in prod environments (#3672) Co-authored-by: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> Co-authored-by: Jan Klopper --- rocky/components/__init__.py | 0 rocky/debian/rules | 3 ++- rocky/katalogus/templates/partials/plugin_tile.html | 4 +--- .../reports/templates/partials/export_report_settings.html | 6 ++---- rocky/rocky/settings.py | 2 +- 5 files changed, 6 insertions(+), 9 deletions(-) create mode 100644 rocky/components/__init__.py diff --git a/rocky/components/__init__.py b/rocky/components/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/rocky/debian/rules b/rocky/debian/rules index 8ef40792426..f44974a1fb6 100755 --- a/rocky/debian/rules +++ b/rocky/debian/rules @@ -38,7 +38,8 @@ override_dh_virtualenv: && $(DH_VENV_DIR)/bin/python manage.py collectstatic --noinput --clear \ && $(DH_VENV_DIR)/bin/python manage.py compress \ && $(DH_VENV_DIR)/bin/python manage.py compilemessages - find static -type f -exec install -D "{}" "$(DESTDIR)/usr/share/kat-rocky/{}" \; + find static -type f -exec install -m 644 -D "{}" "$(DESTDIR)/usr/share/kat-rocky/{}" \; + find components -type f -name *.html -exec install -m 644 -D "{}" "$(DH_VENV_DIR)/lib/`py3versions -d`/site-packages/{}" \; # remove pip to prevent mutation of venv diff --git a/rocky/katalogus/templates/partials/plugin_tile.html b/rocky/katalogus/templates/partials/plugin_tile.html index 5110f091bbf..cd97085ffc1 100644 --- a/rocky/katalogus/templates/partials/plugin_tile.html +++ b/rocky/katalogus/templates/partials/plugin_tile.html @@ -64,7 +64,5 @@ {% endif %} {% block html_at_end_body %} - {% compress js %} - - {% endcompress %} + {% endblock html_at_end_body %} diff --git a/rocky/reports/templates/partials/export_report_settings.html b/rocky/reports/templates/partials/export_report_settings.html index 880e24a7770..e012a3dc819 100644 --- a/rocky/reports/templates/partials/export_report_settings.html +++ b/rocky/reports/templates/partials/export_report_settings.html @@ -61,8 +61,6 @@

{% translate "Recurrence" %}

{% block html_at_end_body %} - {% compress js %} - - - {% endcompress %} + + {% endblock html_at_end_body %} diff --git a/rocky/rocky/settings.py b/rocky/rocky/settings.py index 8fd42af857d..d7d7f5a8841 100644 --- a/rocky/rocky/settings.py +++ b/rocky/rocky/settings.py @@ -334,7 +334,7 @@ def immutable_file_test(path, url): WHITENOISE_IMMUTABLE_FILE_TEST = immutable_file_test -WHITENOISE_KEEP_ONLY_HASHED_FILES = True +WHITENOISE_KEEP_ONLY_HASHED_FILES = False LOGIN_URL = "login" LOGIN_REDIRECT_URL = "crisis_room" From 5dd7d69c25d992180cf7914b9f60f994fa91e183 Mon Sep 17 00:00:00 2001 From: JP Bruins Slot Date: Thu, 17 Oct 2024 11:12:17 +0200 Subject: [PATCH 21/25] Add delete schedule functionality for schedules in the scheduler (#3678) Co-authored-by: ammar92 Co-authored-by: Jan Klopper --- mula/scheduler/server/handlers/schedules.py | 25 +++++++++++++++++++++ mula/tests/integration/test_api.py | 16 +++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mula/scheduler/server/handlers/schedules.py b/mula/scheduler/server/handlers/schedules.py index 28c7a2e20d6..391ea2e21a0 100644 --- a/mula/scheduler/server/handlers/schedules.py +++ b/mula/scheduler/server/handlers/schedules.py @@ -57,6 +57,14 @@ def __init__( description="Update a schedule", ) + self.api.add_api_route( + path="/schedules/{schedule_id}", + endpoint=self.delete, + methods=["DELETE"], + status_code=204, + description="Delete a schedule", + ) + def list( self, request: fastapi.Request, @@ -246,3 +254,20 @@ def patch(self, schedule_id: uuid.UUID, schedule: serializers.SchedulePatch) -> ) from exc return updated_schedule + + def delete(self, schedule_id: uuid.UUID) -> None: + try: + self.ctx.datastores.schedule_store.delete_schedule(schedule_id) + except storage.errors.StorageError as exc: + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"error occurred while accessing the database [exception: {exc}]", + ) from exc + except Exception as exc: + self.logger.exception(exc) + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"failed to delete schedule [exception: {exc}]", + ) from exc + + return None diff --git a/mula/tests/integration/test_api.py b/mula/tests/integration/test_api.py index e1adde1f496..e48dd544362 100644 --- a/mula/tests/integration/test_api.py +++ b/mula/tests/integration/test_api.py @@ -935,21 +935,29 @@ def test_post_schedule_hash_already_exists(self): self.assertIn("schedule with the same hash already exists", response.json().get("detail")) def test_get_schedule(self): - response = self.client.get(f"/schedules/{str(self.first_schedule.id)}") + response = self.client.get(f"/schedules/{self.first_schedule.id}") self.assertEqual(200, response.status_code) self.assertEqual(str(self.first_schedule.id), response.json().get("id")) def test_patch_schedule(self): - response = self.client.patch(f"/schedules/{str(self.first_schedule.id)}", json={"enabled": False}) + response = self.client.patch(f"/schedules/{self.first_schedule.id}", json={"enabled": False}) self.assertEqual(200, response.status_code) self.assertEqual(False, response.json().get("enabled")) def test_patch_schedule_validate_schedule(self): - response = self.client.patch(f"/schedules/{str(self.first_schedule.id)}", json={"schedule": "*/5 * * * *"}) + response = self.client.patch(f"/schedules/{self.first_schedule.id}", json={"schedule": "*/5 * * * *"}) self.assertEqual(200, response.status_code) self.assertEqual("*/5 * * * *", response.json().get("schedule")) def test_patch_schedule_validate_malformed_schedule(self): - response = self.client.patch(f"/schedules/{str(self.first_schedule.id)}", json={"schedule": "malformed"}) + response = self.client.patch(f"/schedules/{self.first_schedule.id}", json={"schedule": "malformed"}) self.assertEqual(400, response.status_code) self.assertIn("validation error", response.json().get("detail")) + + def test_delete_schedule(self): + response = self.client.delete(f"/schedules/{self.first_schedule.id}") + self.assertEqual(204, response.status_code) + + # Schedule should be deleted + response = self.client.get(f"/schedules/{self.first_schedule.id}") + self.assertEqual(404, response.status_code) From 7bc231b0068c1da87aa4617b96bc875155237ce3 Mon Sep 17 00:00:00 2001 From: Donny Peeters <46660228+Donnype@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:57:15 +0200 Subject: [PATCH 22/25] Fix/report naming (#3666) Co-authored-by: Rieven Co-authored-by: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> --- octopoes/octopoes/connector/octopoes.py | 2 +- rocky/.ci/.env.test | 2 - rocky/Makefile | 1 + rocky/katalogus/client.py | 2 +- rocky/onboarding/views.py | 13 ++- rocky/reports/forms.py | 2 +- rocky/reports/runner/local.py | 45 -------- rocky/reports/runner/models.py | 2 +- rocky/reports/runner/report_runner.py | 63 +++++++++++ rocky/reports/runner/worker.py | 11 +- .../partials/report_names_header.html | 7 +- rocky/reports/views/base.py | 16 +-- rocky/reports/views/mixins.py | 62 ++++++----- rocky/rocky/bytes_client.py | 2 +- rocky/rocky/locale/django.pot | 12 ++- rocky/rocky/views/mixins.py | 11 +- rocky/tests/integration/conftest.py | 38 +++++-- rocky/tests/integration/test_report_runner.py | 101 ++++++++++++++++++ 18 files changed, 272 insertions(+), 120 deletions(-) delete mode 100644 rocky/reports/runner/local.py create mode 100644 rocky/reports/runner/report_runner.py create mode 100644 rocky/tests/integration/test_report_runner.py diff --git a/octopoes/octopoes/connector/octopoes.py b/octopoes/octopoes/connector/octopoes.py index 7bd8c261949..c8f6ba76061 100644 --- a/octopoes/octopoes/connector/octopoes.py +++ b/octopoes/octopoes/connector/octopoes.py @@ -279,7 +279,7 @@ def list_findings( def list_reports( self, valid_time: datetime, offset: int = DEFAULT_OFFSET, limit: int = DEFAULT_LIMIT - ) -> Paginated[Report]: + ) -> Paginated[tuple[Report, list[Report | None]]]: params: dict[str, str | int | list[str]] = {"valid_time": str(valid_time), "offset": offset, "limit": limit} res = self.session.get(f"/{self.client}/reports", params=params) diff --git a/rocky/.ci/.env.test b/rocky/.ci/.env.test index a834fb38ef8..c7e4af41224 100644 --- a/rocky/.ci/.env.test +++ b/rocky/.ci/.env.test @@ -16,8 +16,6 @@ ROCKY_DB_HOST=ci_rocky-db ROCKY_DB_PORT=5432 ROCKY_DB_DSN=postgres://${ROCKY_DB_USER}:${ROCKY_DB_PASSWORD}@${ROCKY_DB_HOST}:${ROCKY_DB_PORT}/${ROCKY_DB} -LOG_LEVEL=debug - KEIKO_API=http://placeholder:8005 KATALOGUS_API=http://katalogus_mock:8000 OCTOPOES_API=http://ci_octopoes:80 diff --git a/rocky/Makefile b/rocky/Makefile index 615e9719125..bce14cf9615 100644 --- a/rocky/Makefile +++ b/rocky/Makefile @@ -35,6 +35,7 @@ test: python3 manage.py test testclean: + docker compose -f .ci/docker-compose.yml kill docker compose -f .ci/docker-compose.yml down --remove-orphans docker compose -f .ci/docker-compose.yml build diff --git a/rocky/katalogus/client.py b/rocky/katalogus/client.py index 02c4999409b..9edc2cd81b0 100644 --- a/rocky/katalogus/client.py +++ b/rocky/katalogus/client.py @@ -129,7 +129,7 @@ def __init__(self, error: httpx.HTTPStatusError): class KATalogusClientV1: - def __init__(self, base_uri: str, organization: str): + def __init__(self, base_uri: str, organization: str | None): self.session = httpx.Client(base_url=base_uri) self.organization = valid_organization_code(organization) if organization else organization self.organization_uri = f"/v1/organisations/{organization}" diff --git a/rocky/onboarding/views.py b/rocky/onboarding/views.py index b935915a0f5..37826f74514 100644 --- a/rocky/onboarding/views.py +++ b/rocky/onboarding/views.py @@ -358,11 +358,14 @@ def post(self, request, *args, **kwargs): report_ooi = self.save_report([("Onboarding Report", "Onboarding Report")]) - return redirect( - reverse("view_report", kwargs={"organization_code": self.organization.code}) - + "?" - + urlencode({"report_id": report_ooi.reference}) - ) + if report_ooi: + return redirect( + reverse("view_report", kwargs={"organization_code": self.organization.code}) + + "?" + + urlencode({"report_id": report_ooi.reference}) + ) + + return self.get(request, *args, **kwargs) def set_member_onboarded(self): member = OrganizationMember.objects.get(user=self.request.user, organization=self.organization) diff --git a/rocky/reports/forms.py b/rocky/reports/forms.py index 73765b0f38c..9388d4fe4f4 100644 --- a/rocky/reports/forms.py +++ b/rocky/reports/forms.py @@ -106,7 +106,7 @@ class CustomReportScheduleForm(BaseRockyForm): class ParentReportNameForm(BaseRockyForm): parent_report_name = forms.CharField( - label=_("Report name format"), required=False, initial="{report type} for {ooi}" + label=_("Report name format"), required=False, initial="{report type} for {oois_count} objects" ) diff --git a/rocky/reports/runner/local.py b/rocky/reports/runner/local.py deleted file mode 100644 index d95cf15bff8..00000000000 --- a/rocky/reports/runner/local.py +++ /dev/null @@ -1,45 +0,0 @@ -from datetime import datetime, timezone - -from django.conf import settings -from katalogus.client import KATalogusError, get_katalogus -from tools.models import Organization - -from octopoes.connector.octopoes import OctopoesAPIConnector -from octopoes.models import Reference -from octopoes.models.ooi.reports import ReportRecipe -from reports.report_types.helpers import get_report_by_id -from reports.runner.models import JobRuntimeError, ReportJobRunner -from reports.views.base import format_plugin_data, hydrate_plugins -from reports.views.mixins import collect_reports, save_report_data -from rocky.bytes_client import get_bytes_client -from rocky.scheduler import ReportTask - - -class LocalReportJobRunner(ReportJobRunner): - def run(self, report_task: ReportTask) -> None: - now = datetime.now(timezone.utc) - connector = OctopoesAPIConnector(settings.OCTOPOES_API, report_task.organisation_id) - recipe: ReportRecipe = connector.get( - Reference.from_str(f"ReportRecipe|{report_task.report_recipe_id}"), datetime.now(timezone.utc) - ) - parsed_report_types = [get_report_by_id(report_type_id) for report_type_id in recipe.report_types] - - error_reports, report_data = collect_reports( - now, connector, list(recipe.input_recipe["input_oois"]), parsed_report_types - ) - - try: - report_type_plugins = hydrate_plugins(parsed_report_types, get_katalogus(report_task.organisation_id)) - plugins = format_plugin_data(report_type_plugins) - except KATalogusError as e: - raise JobRuntimeError("Failed to hydrate plugins from KATalogus") from e - - save_report_data( - get_bytes_client(report_task.organisation_id), - now, - connector, - Organization.objects.get(code=report_task.organisation_id), - plugins, - report_data, - [(recipe.report_name_format, recipe.report_name_format)], - ) diff --git a/rocky/reports/runner/models.py b/rocky/reports/runner/models.py index 6ea2409cbd3..6551b3db619 100644 --- a/rocky/reports/runner/models.py +++ b/rocky/reports/runner/models.py @@ -1,7 +1,7 @@ from octopoes.models.ooi.reports import ReportRecipe -class ReportJobRunner: +class ReportRunner: def run(self, recipe: ReportRecipe) -> None: raise NotImplementedError() diff --git a/rocky/reports/runner/report_runner.py b/rocky/reports/runner/report_runner.py new file mode 100644 index 00000000000..f8a742e500e --- /dev/null +++ b/rocky/reports/runner/report_runner.py @@ -0,0 +1,63 @@ +from datetime import datetime, timezone + +from django.conf import settings +from tools.models import Organization + +from octopoes.connector.octopoes import OctopoesAPIConnector +from octopoes.models import Reference +from reports.report_types.definitions import report_plugins_union +from reports.report_types.helpers import get_report_by_id +from reports.runner.models import ReportRunner +from reports.views.mixins import collect_reports, save_report_data +from rocky.bytes_client import BytesClient +from rocky.scheduler import ReportTask + + +class LocalReportRunner(ReportRunner): + def __init__(self, bytes_client: BytesClient, valid_time: datetime | None = None): + self.bytes_client = bytes_client + self.valid_time = valid_time + + def run(self, report_task: ReportTask) -> None: + valid_time = self.valid_time or datetime.now(timezone.utc) + + connector = OctopoesAPIConnector(settings.OCTOPOES_API, report_task.organisation_id) + recipe = connector.get(Reference.from_str(f"ReportRecipe|{report_task.report_recipe_id}"), valid_time) + report_types = [get_report_by_id(report_type_id) for report_type_id in recipe.report_types] + + error_reports, report_data = collect_reports( + valid_time, connector, recipe.input_recipe["input_oois"], report_types + ) + + self.bytes_client.organization = report_task.organisation_id + report_names = [] + oois_count = 0 + + for report_type_id, data in report_data.items(): + oois_count += len(data) + report_type = get_report_by_id(report_type_id) + + for ooi in data: + report_name = recipe.subreport_name_format.replace("{ooi}", ooi).replace( + "{report type}", str(report_type.name) + ) + report_names.append((report_name, report_name)) + + save_report_data( + self.bytes_client, + valid_time, + connector, + Organization.objects.get(code=report_task.organisation_id), + { + "input_data": { + "input_oois": recipe.input_recipe["input_oois"], + "report_types": recipe.report_types, + "plugins": report_plugins_union(report_types), + } + }, + report_data, + report_names, + recipe.report_name_format.replace("{oois_count}", str(oois_count)), + ) + + self.bytes_client.organization = None diff --git a/rocky/reports/runner/worker.py b/rocky/reports/runner/worker.py index 34397c20120..350bdd8ed80 100644 --- a/rocky/reports/runner/worker.py +++ b/rocky/reports/runner/worker.py @@ -10,8 +10,9 @@ from httpx import HTTPError from pydantic import ValidationError -from reports.runner.local import LocalReportJobRunner -from reports.runner.models import ReportJobRunner, WorkerManager +from reports.runner.models import ReportRunner, WorkerManager +from reports.runner.report_runner import LocalReportRunner +from rocky.bytes_client import get_bytes_client from rocky.scheduler import SchedulerClient, Task, TaskStatus, scheduler_client logger = structlog.get_logger(__name__) @@ -20,7 +21,7 @@ class SchedulerWorkerManager(WorkerManager): def __init__( self, - runner: ReportJobRunner, + runner: ReportRunner, scheduler: SchedulerClient, pool_size: int, poll_interval: int, @@ -221,7 +222,7 @@ def _format_exit_code(exitcode: int | None) -> str: def _start_working( - task_queue: mp.Queue, runner: ReportJobRunner, scheduler: SchedulerClient, handling_tasks: dict[int, str] + task_queue: mp.Queue, runner: ReportRunner, scheduler: SchedulerClient, handling_tasks: dict[int, str] ): logger.info("Started listening for tasks from worker[pid=%s]", os.getpid()) @@ -251,7 +252,7 @@ def _start_working( def get_runtime_manager() -> WorkerManager: return SchedulerWorkerManager( - LocalReportJobRunner(), + LocalReportRunner(get_bytes_client("")), # These are set dynamically. Needs a refactor. scheduler_client(None), settings.POOL_SIZE, settings.POLL_INTERVAL, diff --git a/rocky/reports/templates/partials/report_names_header.html b/rocky/reports/templates/partials/report_names_header.html index b2b0a28854c..6e3a11906fd 100644 --- a/rocky/reports/templates/partials/report_names_header.html +++ b/rocky/reports/templates/partials/report_names_header.html @@ -12,9 +12,10 @@

{% translate "Report name" %}

{% blocktranslate trimmed %} To make the report names more descriptive, you can include placeholders for the - object name, the report type and/or the reference date. Use the placeholder "{ooi}" for the - object name, "{report type}" for the report type and use a Python - strftime code for the reference date. + object name, the report type and/or the reference date. For subreports and reports over a single object, + use the placeholder "{ooi}" for the object name, "{report type}" for the report type and use a + Python strftime code for the reference + date. For reports over multiple objects, use "{oois_count}" for the number of objects in the report. {% endblocktranslate %}

diff --git a/rocky/reports/views/base.py b/rocky/reports/views/base.py index 49507b6b1b2..f03947015a9 100644 --- a/rocky/reports/views/base.py +++ b/rocky/reports/views/base.py @@ -120,13 +120,9 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: return redirect(reverse("report_history", kwargs=self.get_kwargs())) -def get_plugin_ids(report_types: list[type[BaseReport]]): - return report_plugins_union(report_types) - - def hydrate_plugins(report_types: list[type["BaseReport"]], katalogus: KATalogusClientV1) -> dict[str, list[Plugin]]: plugins: dict[str, list[Plugin]] = {"required": [], "optional": []} - merged_plugins = get_plugin_ids(report_types) + merged_plugins = report_plugins_union(report_types) required_plugins_ids = list(merged_plugins["required"]) optional_plugins_ids = list(merged_plugins["optional"]) @@ -255,14 +251,6 @@ def get_available_report_types(self) -> tuple[list[dict[str, str]] | dict[str, l report_types = self.get_report_types_for_generate_report() return report_types, len(report_types) - def get_plugin_data_for_saving(self) -> list[dict]: - try: - report_type_plugins = hydrate_plugins(self.get_report_types(), get_katalogus(self.organization.code)) - except KATalogusError as error: - return messages.error(self.request, error.message) - - return format_plugin_data(report_type_plugins) - def get_observed_at(self): return self.observed_at if self.observed_at < datetime.now(timezone.utc) else datetime.now(timezone.utc) @@ -296,7 +284,7 @@ def get_input_data(self) -> dict[str, Any]: "input_data": { "input_oois": self.get_ooi_pks(), "report_types": self.get_report_type_ids(), - "plugins": get_plugin_ids(self.get_report_types()), + "plugins": report_plugins_union(self.get_report_types()), } } diff --git a/rocky/reports/views/mixins.py b/rocky/reports/views/mixins.py index 62e1ecc5fa4..14ac15cbccd 100644 --- a/rocky/reports/views/mixins.py +++ b/rocky/reports/views/mixins.py @@ -14,7 +14,6 @@ from reports.report_types.concatenated_report.report import ConcatenatedReport from reports.report_types.helpers import REPORTS, get_report_by_id from reports.views.base import BaseReportView, ReportDataDict -from rocky.bytes_client import BytesClient def collect_reports(observed_at: datetime, octopoes_connector: OctopoesAPIConnector, ooi_pks: list[str], report_types): @@ -55,24 +54,28 @@ def collect_reports(observed_at: datetime, octopoes_connector: OctopoesAPIConnec return error_reports, report_data -def save_report_raw(bytes_client: BytesClient, data: dict) -> str: - report_data_raw_id = bytes_client.upload_raw( - raw=ReportDataDict(data).model_dump_json().encode(), manual_mime_types={"openkat/report"} - ) - - return report_data_raw_id - - def save_report_data( - bytes_client, observed_at, octopoes_api_connector, organization, input_data, report_data, report_names -): + bytes_client, + observed_at, + octopoes_api_connector, + organization, + input_data: dict, + report_data, + report_names, + parent_report_name, +) -> Report | None: + if len(report_data) == 0: + return None + now = datetime.now(timezone.utc) # if it's not a single report, we need a parent if len(report_data) > 1 or len(list(report_data.values())[0]) > 1: - raw_id = save_report_raw(bytes_client, data=input_data) - name = now.strftime(report_names[0][1]) + raw_id = bytes_client.upload_raw( + raw=ReportDataDict(input_data).model_dump_json().encode(), manual_mime_types={"openkat/report"} + ) + name = now.strftime(parent_report_name.replace("{report type}", str(ConcatenatedReport.name))) if not name or name.isspace(): name = ConcatenatedReport.name @@ -121,11 +124,13 @@ def save_report_data( ] child_input_data = { - "input_data": {"input_oois": [ooi], "report_types": [report_type_id], "plugins": child_plugins} + "input_data": {"input_oois": [ooi], "report_types": [report_type_id], "plugins": [child_plugins]} } - raw_id = save_report_raw(bytes_client, data={"report_data": data["data"]} | child_input_data) - + raw_id = bytes_client.upload_raw( + raw=ReportDataDict({"report_data": data["data"]} | child_input_data).model_dump_json().encode(), + manual_mime_types={"openkat/report"}, + ) name = now.strftime(name_to_save) if not name or name.isspace(): name = ConcatenatedReport.name @@ -153,10 +158,12 @@ def save_report_data( report_type_id = next(iter(report_data)) ooi = next(iter(report_data[report_type_id])) data = report_data[report_type_id][ooi] - - raw_id = save_report_raw(bytes_client, data={"report_data": data["data"]} | input_data) + raw_id = bytes_client.upload_raw( + raw=ReportDataDict({"report_data": data["data"]} | input_data).model_dump_json().encode(), + manual_mime_types={"openkat/report"}, + ) report_type = get_report_by_id(report_type_id) - name = now.strftime(report_names[0][1]) + name = now.strftime(parent_report_name.replace("{report type}", str(report_type.name))) if not name or name.isspace(): name = ConcatenatedReport.name @@ -182,7 +189,7 @@ def save_report_data( class SaveGenerateReportMixin(BaseReportView): - def save_report(self, report_names: list) -> Report: + def save_report(self, report_names: list) -> Report | None: error_reports, report_data = collect_reports( self.observed_at, self.octopoes_api_connector, @@ -198,6 +205,7 @@ def save_report(self, report_names: list) -> Report: self.get_input_data(), report_data, report_names, + report_names[0][0], ) # If OOI could not be found or the date is incorrect, it will be shown to the user as a message error @@ -239,10 +247,11 @@ def save_report(self, report_names: list) -> Report: now = datetime.utcnow() bytes_client = self.bytes_client - # Save report data into bytes - - report_data_raw_id = save_report_raw(bytes_client, data=post_processed_data | self.get_input_data()) - + # Create the report + report_data_raw_id = bytes_client.upload_raw( + raw=ReportDataDict(post_processed_data | self.get_input_data()).model_dump_json().encode(), + manual_mime_types={"openkat/report"}, + ) report_type = type(aggregate_report) name = now.strftime(report_names[0][1]) if not name or name.isspace(): @@ -268,6 +277,9 @@ def save_report(self, report_names: list) -> Report: # Save the child reports to bytes for ooi, types in report_data.items(): for report_type, data in types.items(): - save_report_raw(bytes_client, data=data | self.get_input_data()) + bytes_client.upload_raw( + raw=ReportDataDict(data | self.get_input_data()).model_dump_json().encode(), + manual_mime_types={"openkat/report"}, + ) return report_ooi diff --git a/rocky/rocky/bytes_client.py b/rocky/rocky/bytes_client.py index f874daab3c5..791ee8b5a5d 100644 --- a/rocky/rocky/bytes_client.py +++ b/rocky/rocky/bytes_client.py @@ -16,7 +16,7 @@ class BytesClient: - def __init__(self, base_url: str, username: str, password: str, organization: str): + def __init__(self, base_url: str, username: str, password: str, organization: str | None): self.credentials = {"username": username, "password": password} self.session = httpx.Client(base_url=base_url) self.organization = organization diff --git a/rocky/rocky/locale/django.pot b/rocky/rocky/locale/django.pot index 4af966792b8..9dc9f1faa12 100644 --- a/rocky/rocky/locale/django.pot +++ b/rocky/rocky/locale/django.pot @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-09 14:20+0000\n" +"POT-Creation-Date: 2024-10-16 14:17+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3793,10 +3793,12 @@ msgstr "" #: reports/templates/partials/report_names_header.html msgid "" "To make the report names more descriptive, you can include placeholders for " -"the object name, the report type and/or the reference date. Use the " -"placeholder \"{ooi}\" for the object name, \"{report type}\" for the report " -"type and use a Python strftime code for the reference date." +"the object name, the report type and/or the reference date. For subreports " +"and reports over a single object, use the placeholder \"{ooi}\" for the " +"object name, \"{report type}\" for the report type and use a Python " +"strftime code for the reference date. For reports over multiple objects, " +"use \"{oois_count}\" for the number of objects in the report." msgstr "" #: reports/templates/partials/report_names_header.html diff --git a/rocky/rocky/views/mixins.py b/rocky/rocky/views/mixins.py index f8f1be7bd2f..fda5d4eb250 100644 --- a/rocky/rocky/views/mixins.py +++ b/rocky/rocky/views/mixins.py @@ -391,26 +391,27 @@ def get_subreports(self, report_id: str) -> list[tuple[str, Report]]: return subreports - def hydrate_report_list(self, reports: list[Report]) -> list[HydratedReport]: + def hydrate_report_list(self, reports: list[tuple[Report, list[Report | None]]]) -> list[HydratedReport]: hydrated_reports: list[HydratedReport] = [] for report in reports: hydrated_report: HydratedReport = HydratedReport() parent_report, children_reports = report + filtered_children_reports = list(filter(None, children_reports)) - hydrated_report.total_children_reports = len(children_reports) + hydrated_report.total_children_reports = len(filtered_children_reports) if len(parent_report.input_oois) > 0: hydrated_report.total_objects = len(parent_report.input_oois) else: - hydrated_report.total_objects = len(self.get_children_input_oois(children_reports)) + hydrated_report.total_objects = len(self.get_children_input_oois(filtered_children_reports)) - hydrated_report.report_type_summary = self.report_type_summary(children_reports) + hydrated_report.report_type_summary = self.report_type_summary(filtered_children_reports) if not parent_report.has_parent: hydrated_children_reports: list[Report] = [] - for child_report in children_reports: + for child_report in filtered_children_reports: if str(child_report.parent_report) == str(parent_report): hydrated_children_reports.append(child_report) if len(hydrated_children_reports) >= 5: # We want to show only 5 children reports diff --git a/rocky/tests/integration/conftest.py b/rocky/tests/integration/conftest.py index fb80952ba6e..63ed1abd011 100644 --- a/rocky/tests/integration/conftest.py +++ b/rocky/tests/integration/conftest.py @@ -4,6 +4,8 @@ import pytest from django.conf import settings +from reports.runner.report_runner import LocalReportRunner +from tools.models import Organization from octopoes.api.models import Declaration, Observation from octopoes.connector.octopoes import OctopoesAPIConnector @@ -15,6 +17,7 @@ from octopoes.models.ooi.service import IPService, Service from octopoes.models.ooi.software import Software, SoftwareInstance from octopoes.models.ooi.web import URL, HostnameHTTPURL, HTTPHeader, HTTPResource, SecurityTXT, Website +from rocky.health import ServiceHealth @pytest.fixture @@ -23,10 +26,30 @@ def valid_time(): @pytest.fixture -def octopoes_api_connector(request) -> OctopoesAPIConnector: +def katalogus_mock(mocker): + katalogus = mocker.patch("katalogus.client.KATalogusClientV1") + katalogus().health.return_value = ServiceHealth(service="katalogus", healthy=True) + + return katalogus + + +@pytest.fixture +def integration_organization(katalogus_mock, request) -> Organization: test_node = f"test-{request.node.originalname}" - connector = OctopoesAPIConnector(settings.OCTOPOES_API, test_node) + return Organization.objects.create(name="Test", code=test_node) + + +@pytest.fixture +def integration_organization_2(request) -> Organization: + test_node = f"test-{request.node.originalname}-2" + + return Organization.objects.create(name="Test 2", code=test_node) + + +@pytest.fixture +def octopoes_api_connector(integration_organization) -> OctopoesAPIConnector: + connector = OctopoesAPIConnector(settings.OCTOPOES_API, integration_organization.code) connector.create_node() yield connector @@ -34,16 +57,19 @@ def octopoes_api_connector(request) -> OctopoesAPIConnector: @pytest.fixture -def octopoes_api_connector_2(request) -> OctopoesAPIConnector: - test_node = f"test-{request.node.originalname}-2" - - connector = OctopoesAPIConnector(settings.OCTOPOES_API, test_node) +def octopoes_api_connector_2(integration_organization_2) -> OctopoesAPIConnector: + connector = OctopoesAPIConnector(settings.OCTOPOES_API, integration_organization_2.code) connector.create_node() yield connector connector.delete_node() +@pytest.fixture +def report_runner(valid_time, mocker) -> LocalReportRunner: + return LocalReportRunner(mocker.MagicMock(), valid_time) + + def seed_system( octopoes_api_connector: OctopoesAPIConnector, valid_time: datetime, diff --git a/rocky/tests/integration/test_report_runner.py b/rocky/tests/integration/test_report_runner.py new file mode 100644 index 00000000000..75f60a3a7b7 --- /dev/null +++ b/rocky/tests/integration/test_report_runner.py @@ -0,0 +1,101 @@ +import json + +from reports.runner.report_runner import LocalReportRunner + +from octopoes.api.models import Declaration +from octopoes.connector.octopoes import OctopoesAPIConnector +from octopoes.models.ooi.reports import ReportRecipe +from rocky.health import ServiceHealth +from rocky.scheduler import ReportTask +from tests.integration.conftest import seed_system + + +def test_run_report_task(octopoes_api_connector: OctopoesAPIConnector, report_runner: LocalReportRunner, valid_time): + oois = seed_system(octopoes_api_connector, valid_time) + report_runner.bytes_client.health.return_value = ServiceHealth(service="bytes", healthy=True) + report_runner.bytes_client.upload_raw.return_value = "abcdabcd-f8ab-4bdf-9b1b-58cd98ef6342" + + recipe = ReportRecipe( + recipe_id="abc4e52b-812c-4cc2-8196-35fb8efc63ca", + report_name_format="Concatenated report for {oois_count} objects", + subreport_name_format="{report type} for {ooi} in %Y", + input_recipe={"input_oois": [oois["hostnames"][0].reference, oois["hostnames"][1].reference]}, + report_types=["dns-report"], + cron_expression="* * * * *", + ) + octopoes_api_connector.save_declaration(Declaration(ooi=recipe, valid_time=valid_time)) + + task = ReportTask(organisation_id=octopoes_api_connector.client, report_recipe_id=str(recipe.recipe_id)) + report_runner.run(task) + + assert len(report_runner.bytes_client.upload_raw.mock_calls) == 3 + + assert report_runner.bytes_client.upload_raw.mock_calls[0].kwargs["manual_mime_types"] == {"openkat/report"} + assert report_runner.bytes_client.upload_raw.mock_calls[1].kwargs["manual_mime_types"] == {"openkat/report"} + assert report_runner.bytes_client.upload_raw.mock_calls[2].kwargs["manual_mime_types"] == {"openkat/report"} + + data = json.loads(report_runner.bytes_client.upload_raw.mock_calls[0].kwargs["raw"]) + data["input_data"]["plugins"]["required"] = set(data["input_data"]["plugins"]["required"]) # ordering issues + assert data == { + "input_data": { + "input_oois": ["Hostname|test|example.com", "Hostname|test|a.example.com"], + "report_types": ["dns-report"], + "plugins": {"required": {"dns-sec", "dns-records"}, "optional": ["dns-zone"]}, + } + } + + # The order of the OOIs being processed is not guaranteed, so this is a simple workaround + both_calls = [ + { + "report_data": { + "input_ooi": "Hostname|test|example.com", + "records": [], + "security": {"spf": True, "dkim": True, "dmarc": True, "dnssec": True, "caa": True}, + "finding_types": [], + }, + "input_data": { + "input_oois": ["Hostname|test|example.com"], + "report_types": ["dns-report"], + "plugins": [{"required": {"dns-sec", "dns-records"}, "optional": ["dns-zone"]}], + }, + }, + { + "report_data": { + "input_ooi": "Hostname|test|a.example.com", + "records": [], + "security": {"spf": True, "dkim": True, "dmarc": True, "dnssec": True, "caa": True}, + "finding_types": [], + }, + "input_data": { + "input_oois": ["Hostname|test|a.example.com"], + "report_types": ["dns-report"], + "plugins": [{"required": {"dns-sec", "dns-records"}, "optional": ["dns-zone"]}], + }, + }, + ] + + data_1 = json.loads(report_runner.bytes_client.upload_raw.mock_calls[1].kwargs["raw"]) + data_1["input_data"]["plugins"][0]["required"] = set( + data_1["input_data"]["plugins"][0]["required"] + ) # ordering issues + data_2 = json.loads(report_runner.bytes_client.upload_raw.mock_calls[2].kwargs["raw"]) + data_2["input_data"]["plugins"][0]["required"] = set( + data_2["input_data"]["plugins"][0]["required"] + ) # ordering issues + + assert data_1 in both_calls + assert data_2 in both_calls + + reports = octopoes_api_connector.list_reports(valid_time) + assert reports.count == 1 + report, subreports = reports.items[0] + assert len(subreports) == 2 + + assert report.name == "Concatenated report for 2 objects" + assert "DNS Report for Hostname|test|a.example.com in 2024" in {x.name for x in subreports} + + # FIXME: the naming logic in reports/views/mixins.py 107-112 is not right. We expect to find example.com in this + # set, but instead only find a.example.com because when ooi_name is 'example.com', the check: + # `ooi_name in default_name` also passes for 'DNS Report for Hostname|test|a.example.com in %Y'. + # We shouldn't have to guess the match in the report_names argument. The name should be overridden on an object + # in the report_data list probably. Note that sometimes this does work when the OOIs are ordered differently. From 2137b58b346d57848cd6b4089becb8cd8e507282 Mon Sep 17 00:00:00 2001 From: JP Bruins Slot Date: Wed, 23 Oct 2024 10:50:13 +0200 Subject: [PATCH 23/25] Add search endpoint for schedules for scheduler (#3695) Co-authored-by: ammar92 Co-authored-by: Jan Klopper --- mula/scheduler/server/handlers/schedules.py | 49 ++++++++++++++++++--- mula/tests/integration/test_api.py | 34 +++++++++++--- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/mula/scheduler/server/handlers/schedules.py b/mula/scheduler/server/handlers/schedules.py index 391ea2e21a0..b7605f9975f 100644 --- a/mula/scheduler/server/handlers/schedules.py +++ b/mula/scheduler/server/handlers/schedules.py @@ -5,7 +5,7 @@ import fastapi import pydantic import structlog -from fastapi import status +from fastapi import Body, status from scheduler import context, models, schedulers, storage from scheduler.server import serializers, utils @@ -65,6 +65,15 @@ def __init__( description="Delete a schedule", ) + self.api.add_api_route( + path="/schedules/search", + endpoint=self.search, + methods=["POST"], + response_model=utils.PaginatedResponse, + status_code=200, + description="Search schedules", + ) + def list( self, request: fastapi.Request, @@ -255,6 +264,39 @@ def patch(self, schedule_id: uuid.UUID, schedule: serializers.SchedulePatch) -> return updated_schedule + def search( + self, + request: fastapi.Request, + offset: int = 0, + limit: int = 10, + filters: storage.filters.FilterRequest | None = Body(...), + ) -> utils.PaginatedResponse: + if filters is None: + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_400_BAD_REQUEST, detail="missing search filters" + ) + + try: + results, count = self.ctx.datastores.schedule_store.get_schedules( + offset=offset, limit=limit, filters=filters + ) + except storage.filters.errors.FilterError as exc: + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_400_BAD_REQUEST, detail=f"invalid filter(s) [exception: {exc}]" + ) from exc + except storage.errors.StorageError as exc: + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"error occurred while accessing the database [exception: {exc}]", + ) from exc + except Exception as exc: + self.logger.exception(exc) + raise fastapi.HTTPException( + status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, detail="failed to search schedules" + ) from exc + + return utils.paginate(request, results, count, offset, limit) + def delete(self, schedule_id: uuid.UUID) -> None: try: self.ctx.datastores.schedule_store.delete_schedule(schedule_id) @@ -266,8 +308,5 @@ def delete(self, schedule_id: uuid.UUID) -> None: except Exception as exc: self.logger.exception(exc) raise fastapi.HTTPException( - status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"failed to delete schedule [exception: {exc}]", + status_code=fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR, detail="failed to search schedules" ) from exc - - return None diff --git a/mula/tests/integration/test_api.py b/mula/tests/integration/test_api.py index e48dd544362..16d028b3536 100644 --- a/mula/tests/integration/test_api.py +++ b/mula/tests/integration/test_api.py @@ -729,22 +729,22 @@ class APIScheduleEndpointTestCase(APITemplateTestCase): def setUp(self): super().setUp() - first_item = functions.create_item(self.scheduler.scheduler_id, 1) + self.first_item = functions.create_item(self.scheduler.scheduler_id, 1) self.first_schedule = self.mock_ctx.datastores.schedule_store.create_schedule( models.Schedule( scheduler_id=self.scheduler.scheduler_id, - hash=first_item.hash, - data=first_item.data, + hash=self.first_item.hash, + data=self.first_item.data, deadline_at=datetime.now(timezone.utc) + timedelta(days=1), ) ) - second_item = functions.create_item(self.scheduler.scheduler_id, 1) + self.second_item = functions.create_item(self.scheduler.scheduler_id, 1) self.second_schedule = self.mock_ctx.datastores.schedule_store.create_schedule( models.Schedule( scheduler_id=self.scheduler.scheduler_id, - hash=second_item.hash, - data=second_item.data, + hash=self.second_item.hash, + data=self.second_item.data, deadline_at=datetime.now(timezone.utc) + timedelta(days=2), ) ) @@ -954,6 +954,28 @@ def test_patch_schedule_validate_malformed_schedule(self): self.assertEqual(400, response.status_code) self.assertIn("validation error", response.json().get("detail")) + def test_search_schedule(self): + response = self.client.post( + "/schedules/search", + json={ + "filters": [ + {"column": "data", "field": "name", "operator": "eq", "value": self.first_item.data.get("name")} + ] + }, + ) + self.assertEqual(200, response.status_code) + self.assertEqual(1, response.json()["count"]) + self.assertEqual(1, len(response.json()["results"])) + + def test_search_schedule_with_pagination(self): + response = self.client.post( + "/schedules/search?limit=1", + json={"filters": [{"column": "scheduler_id", "operator": "eq", "value": self.scheduler.scheduler_id}]}, + ) + self.assertEqual(200, response.status_code) + self.assertEqual(2, response.json()["count"]) + self.assertEqual(1, len(response.json()["results"])) + def test_delete_schedule(self): response = self.client.delete(f"/schedules/{self.first_schedule.id}") self.assertEqual(204, response.status_code) From 870b4febb67b6fc926d34c5bb1d5f4240c45e144 Mon Sep 17 00:00:00 2001 From: zcrt <115991818+zcrt@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:10:14 +0200 Subject: [PATCH 24/25] feat: :sparkles: add Shodan InternetDB boefje (#2615) Co-authored-by: Jan Klopper Co-authored-by: originalsouth Co-authored-by: Ammar --- boefjes/boefjes/plugins/helpers.py | 9 +++ .../kat_binaryedge/http_web/normalize.py | 10 ++-- .../service_identification/normalize.py | 5 +- .../kat_binaryedge/services/normalize.py | 17 +----- .../plugins/kat_shodan_internetdb/__init__.py | 0 .../plugins/kat_shodan_internetdb/boefje.json | 10 ++++ .../plugins/kat_shodan_internetdb/cover.jpg | Bin 0 -> 280035 bytes .../kat_shodan_internetdb/description.md | 30 ++++++++++ .../plugins/kat_shodan_internetdb/main.py | 18 ++++++ .../kat_shodan_internetdb/normalize.py | 54 ++++++++++++++++++ .../kat_shodan_internetdb/normalizer.json | 16 ++++++ boefjes/tests/integration/test_api.py | 8 +-- 12 files changed, 152 insertions(+), 25 deletions(-) create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/__init__.py create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/boefje.json create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/cover.jpg create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/description.md create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/main.py create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/normalize.py create mode 100644 boefjes/boefjes/plugins/kat_shodan_internetdb/normalizer.json diff --git a/boefjes/boefjes/plugins/helpers.py b/boefjes/boefjes/plugins/helpers.py index 5bcf2bb19ba..d897a182546 100644 --- a/boefjes/boefjes/plugins/helpers.py +++ b/boefjes/boefjes/plugins/helpers.py @@ -66,3 +66,12 @@ def get_file_from_container(container: docker.models.containers.Container, path: return None return extracted_file.read() + + +def cpe_to_name_version(cpe: str) -> tuple[str | None, str | None]: + """Fetch the software name and version from a CPE string.""" + cpe_split = cpe.split(":") + cpe_split_len = len(cpe_split) + name = None if cpe_split_len < 4 else cpe_split[3] + version = None if cpe_split_len < 5 else cpe_split[4] + return name, version diff --git a/boefjes/boefjes/plugins/kat_binaryedge/http_web/normalize.py b/boefjes/boefjes/plugins/kat_binaryedge/http_web/normalize.py index 4e9181fbf8a..73019c5076b 100644 --- a/boefjes/boefjes/plugins/kat_binaryedge/http_web/normalize.py +++ b/boefjes/boefjes/plugins/kat_binaryedge/http_web/normalize.py @@ -3,7 +3,7 @@ from collections.abc import Iterable from boefjes.job_models import NormalizerOutput -from boefjes.plugins.kat_binaryedge.services.normalize import get_name_from_cpe +from boefjes.plugins.helpers import cpe_to_name_version from octopoes.models import Reference from octopoes.models.ooi.network import IPAddressV4, IPAddressV6, IPPort, Network, PortState, Protocol from octopoes.models.ooi.software import Software, SoftwareInstance @@ -50,7 +50,8 @@ def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: for app in response.get("apps", {}): if "cpe" in app: - software_ooi = Software(name=get_name_from_cpe(app["cpe"]), cpe=app["cpe"]) + name, version = cpe_to_name_version(cpe=app["cpe"]) + software_ooi = Software(name=name, version=version, cpe=app["cpe"]) yield software_ooi yield SoftwareInstance(ooi=ip_port_ooi.reference, software=software_ooi.reference) else: @@ -74,9 +75,8 @@ def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: for potential_software in data: # Check all values for 'cpe' if isinstance(potential_software, dict) and "cpe" in potential_software: - software_ooi = Software( - name=get_name_from_cpe(potential_software["cpe"]), cpe=potential_software["cpe"] - ) + name, version = cpe_to_name_version(cpe=potential_software["cpe"]) + software_ooi = Software(name=name, version=version, cpe=potential_software["cpe"]) yield software_ooi yield SoftwareInstance(ooi=ip_port_ooi.reference, software=software_ooi.reference) diff --git a/boefjes/boefjes/plugins/kat_binaryedge/service_identification/normalize.py b/boefjes/boefjes/plugins/kat_binaryedge/service_identification/normalize.py index 08edfaed22d..3dc5b4a8f81 100644 --- a/boefjes/boefjes/plugins/kat_binaryedge/service_identification/normalize.py +++ b/boefjes/boefjes/plugins/kat_binaryedge/service_identification/normalize.py @@ -3,7 +3,7 @@ from collections.abc import Iterable from boefjes.job_models import NormalizerOutput -from boefjes.plugins.kat_binaryedge.services.normalize import get_name_from_cpe +from boefjes.plugins.helpers import cpe_to_name_version from octopoes.models import Reference from octopoes.models.ooi.findings import Finding, KATFindingType from octopoes.models.ooi.network import IPAddressV4, IPAddressV6, IPPort, Network, PortState, Protocol @@ -51,7 +51,8 @@ def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: if "cpe" in service: for cpe in service["cpe"]: - software_ooi = Software(name=get_name_from_cpe(cpe), cpe=cpe) + name, version = cpe_to_name_version(cpe=cpe) + software_ooi = Software(name=name, version=version, cpe=cpe) yield software_ooi software_instance_ooi = SoftwareInstance( ooi=ip_service_ooi.reference, software=software_ooi.reference diff --git a/boefjes/boefjes/plugins/kat_binaryedge/services/normalize.py b/boefjes/boefjes/plugins/kat_binaryedge/services/normalize.py index b4570abe843..e9d20039a49 100644 --- a/boefjes/boefjes/plugins/kat_binaryedge/services/normalize.py +++ b/boefjes/boefjes/plugins/kat_binaryedge/services/normalize.py @@ -3,24 +3,12 @@ from collections.abc import Iterable from boefjes.job_models import NormalizerOutput +from boefjes.plugins.helpers import cpe_to_name_version from octopoes.models import Reference from octopoes.models.ooi.network import IPAddressV4, IPAddressV6, IPPort, Network, PortState, Protocol from octopoes.models.ooi.software import Software, SoftwareInstance -def get_name_from_cpe(cpe: str) -> str: - split = [] - if cpe[0:5] == "cpe:/": - split = cpe[5:].split(":") - elif cpe[0:8] == "cpe:2.3:": - split = cpe[8:].split(":") - - if len(split) > 3: - return split[2] - else: - return cpe - - def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: results = json.loads(raw) pk_ooi = Reference.from_str(input_ooi["primary_key"]) @@ -73,7 +61,8 @@ def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: yield software_ooi yield SoftwareInstance(ooi=ip_port_ooi.reference, software=software_ooi.reference) for cpe in scan.get("result", {}).get("data", {}).get("cpe", []): - software_ooi = Software(name=get_name_from_cpe(cpe), cpe=cpe) + name, version = cpe_to_name_version(cpe=cpe) + software_ooi = Software(name=name, version=version, cpe=cpe) yield software_ooi yield SoftwareInstance(ooi=ip_port_ooi.reference, software=software_ooi.reference) diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/__init__.py b/boefjes/boefjes/plugins/kat_shodan_internetdb/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/boefje.json b/boefjes/boefjes/plugins/kat_shodan_internetdb/boefje.json new file mode 100644 index 00000000000..a1e96ef51df --- /dev/null +++ b/boefjes/boefjes/plugins/kat_shodan_internetdb/boefje.json @@ -0,0 +1,10 @@ +{ + "id": "shodan_internetdb", + "name": "'Shodan InternetDB", + "description": "Use Shodan InternetDB to find open ports with vulnerabilities that are found on an IP.", + "consumes": [ + "IPAddressV4", + "IPAddressV6" + ], + "scan_level": 1 +} diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/cover.jpg b/boefjes/boefjes/plugins/kat_shodan_internetdb/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6d9a833a9e5c05a9d893292f2551d20efe9e0bd GIT binary patch literal 280035 zcmb5VcT`hN^e7rYP*9qHO7Ar)(gkVK3B4rLfK(|G5CRBNq)3xq1?hwu5~M>w5JgH5 zA#~|TF$6)RNKx<|zTdm+-hb{}>kZ^&a%RpxduI0RHhce@`L_&WfN1Gzfyl@}ATr<& z^zR$ljIO%6y|Jm0mae|$|1=DMfO6>`2;_x8`kHF1@mN|}^ITs3pC>Nb9Gv`oF24US z1%Uf|>H<0lG=As*(&zu{Hnp>hpA*nw7x)PH0xt)UWd`cZkN>AGa#45upSt2jJrL=G z1o{|X)P2oO)q%P*P#1apf7BiSkGhkO??wMappT;06aR~MU6c!quel(gX2ACq;KKp( z1DS%fL24J{2Yv&^yA%Yve+U9mr2g-Fj=3OE>q`*m*6jbjCr}Im(MN+oEhGQ?-v6Ex z9|vED|G-@WuH>$+AkbbV2t;cI0x^w(Kr}Z0wE>s^3vN6>69<5oH}Llu^aSJr;sNP` z5FjVeU7#ijx(AW~$^M%Ise>rUFUrN00w|ZLE?tx>R8*8y)K_R|sIO2{(_Ev!MstQAJvWq7vE?og0WVlLw6}bEVv;2DxV!T2rc|Za46PWKy6c>c}zX}!kCCbYniYsK)K(iwQhz!7+it_U1D_6*`P>|D8 z0L>sKs_U1T`S>N(SftcV9mxdD9DF0wuQ1+_e&|%nE2!ZYRo3v~ri6@nM&rjZlW#(r z&S@p%tGlD^RF|&+tx}92a&iEN zOO%)XS1)pk>zBxw_$VbAnfcYISa_vOZ%8~ex$LO!;42_~GxFao=o$q8laYcEqyjn# z(k&O?MvbcCf5G9;?ZD{bORjrUu6tviB4k#b&AFY;Z}7wGpeK-4B&sI05c{r}w*3s6 zgNE%i20mnR^}Z9FFj+JW(f(@o)_B3n+S`;!#*%yH|LTuB_>UXK&EHcnm@$=UwKOU; z6O>dTH{OKyN!@)VS71N8IzhXAc6i3jlwlK^_uV1 z&S$Mfum15AdCRJ6>TaHO)(nzDW8{_0arnzTiT|NsZRVRZIZA%LU|n3erg>ww&J9#Y zKH$+n-M)zJA`GpyxxVpS$8sm7Pud9-CPBw$h5M)*B+~r%|A7(}ymJ%qZjQ}{iNKVs z)YRON)j>qQ3GX-UflY=;iCvB-ZA9>4v90vgP-&AE_xA?AjUV2xp`PixJb{KLyj^%- z6{UU0I-Sgf8SPfpnuhyeF3GnZY?v{@eH|JAHlq6RSj5q7`k_xrDp+4vUfbO`4I?LOw0jv+gRZ^E%&S}_UO@A%u)*K(f zx9TKH&cieDbOcw;!RPL-Zo@z1BnYlSjwqZv#D7$J79-We|DBrHd8ABwwfjRq3br{d zH4($|vAztVW3VFm%j7|EG_Ov7dMCFfiCDd!*^!d+55!BAHYbR`G#35dx;OpXiQ5+s z9f=Z?E4YnNsa0=q?dPv`&orTRFL9njcUO7-#w?rd8#Y(--{*F#c|2v&G68|6hxc{$ z(~l0x093bj2%D2`iVe~yYcZLwHry%nICvv-uWf;Mwo=ysXR1~Tn*$d|R0?Aog|RJP z%hxS@UlfmvY)K}!+O!VZNFIyOut^4Qy6bFt<$V(F(Tt4p7Y@>?WL1Kq#X2%AMR{vd zAI&Y&<-1t;HsIq2A1<|MuN_WJw6^7iqMw0pPg7s>4X$=K+$$iR)Av{r*0}ZsIj+!- z<;`VG+tgy;H5h5(6pcmP2DfT4r!{~5v(1$?Ct8g~c}pAeX>kp^VKl?g{<6O;cLqMB z({8#O?zE6nmXG|A-waWz<_ zM~~Rbr68Sm@8XU!u^;|vs`t|yaZ0@)>TP*;-D;DMZ98E!Ut%TX#qMOWD)IPoHB>Og z+A^gfn^yJ%RVamrHT2vEjC>m^yOP?=g=yckbw_q|bFZ-*(xD?eN482;N|WEwY$+#n zp8teA8OT`-bnmHw89^D(m?R#s`Q-DRey3FbqIr_Ghoupb$yGA9Rpjzkw^5FHou3(W z+$|XfeLr7V1G7Oo9SAN29Y`-Gr@YoM!nfV*L^&T4@IKahBta?5*vnrJS!RfX|Ilc|G)w%=kES@PO3RAk5Ap{e?#59Yg zSy^_s;It}C$ERR5vy*by@}lk$uYXawYK>2G<;2q9(VgBx;-j&qp1>p-Ug!Aw?4~{~ zo5S8+Y@y?-7{DD7X1=b=aF?v3o5l^-*FXYVTBRg)d>Dzf_5GrM5v2XrjZ-nm`gIvgDdLWyvk=@xrdF* zlN;R@;M?*rGdg8?e{$2Vg0l}nN$84Y6Xu`D)6_jsFI<1Diu(tOB<`D}p`rm4U5%jn zq1-{1`O2&P+Ifkhyz~%5&n(IOyIXDDv#^7eK=n1a_ArlEJEh(rsk*z&b?0_w(@L|; zGMo#+XM<2p5-1lGD~}hU6huz>mgATIGQVAsaRt7DfamxNp*azP$e=YSMww`%SX@R@E>T!&Pw>N+Z-|X-Oc4%E_w-t_vbXRpG*IK9BgB9 zF8YP~3bY;(b*X3Smdnp5FMvG7<*Vc_39W}|q&JF+z2~|ti=h0=yh?nKJj@-Lvu_#R z5N4>>+R(NAthlB&rFiEbsKcULwJ?}Q**oPVHX{}D1e=CV#~2kO&S--UXqU>$L%z`u z+@v#otD~dvdr)N+mWK@95;wC8B?~(H(!QVX{kbS36U{tqaW`Dhb8-;&&4(K6W6@1G zJ);GGpIQ1UE+}g1;rS1g#Nwc+x_51`y>Q`HxHjU!t2*_vai&^Yvm*32qw-sM4)~X? z5y-fkWCkC3oY87>%$L6E)|R#>71C#W9)=v~UVozBU*KFvIjI1XwHKIZdkaCn*oaj9 zH6F8{*gti*%J_?;ZKn{XI7esrvwV*--0<@M|j8jPcz8lrHy)j^rOJ3}``%gc0Ryh_m+zWa0)25`5PlD{(<;&6QdURQzG?^Jc_gcjVB zmUdHH3umwslVwmR9MA6*7fYWRrKuyVjcV_)(JebUC zjB=K|Y}PQV>c}wPnSh>M&M^pX9?yDoL?@Z_Ve6x7f0VM}X88?{nykyeey8Otd|t>q z#aBA>uc7iqKYl)Bm$khg=C9 zsd^AREoXKt8csM4rF9F##KjJAe1E#qXhZURwEH!FW?Ca$8#AC>(LxVu=5~Ud*+uO2 z%Mj~>T@foRuVweZ{WABnl$ z9d{dvL2+2hX`QpHUT0sK>q@r!2ldWexo^wY-&dSg$a{Jq(EGyz&V2waddgCyX?4VC z?ENYt*y;=Q`<*+7;POiHw&4jZPKr1aO8b})(7liWIdkF}$RS21RTYhd*ey|tbsfKN$YAds&)V}8yI>k(c-giRrzcS>e4*MNE%;!sNkp2s z*2`^*J33XAD@Ok;nM*7%2pZj1qUA;lvhN+^d4iQJp87WhKM=C3sN;(DBz9(EW4TMJ z&e5-x?OCQn>zw4C@JA%N%9}pNoL)IWhFN7Gi0#D9<;5( zX~=rwOUi^i@7k(Z3h|5+e?+|Xjz(-^VsN2$QhBFr|3~WH(<~34Tm6GJ%2Ba@T9?u4 zW|-j0h0>HF=h%!y%y^`lGGr$I2IC$yzIw`|DA4v~M~`ujkoA3Z>TJlrNd03@)GqWz zh4YRn^XKeik!kc={gOBX<$)sq8m3#*=164ob_h!WSJ!&rMlNqN1O0)yQZFo&#gpi^ zS~fjj=g$`?8Wt$9?L?jt6LJL=%5u3(ll>t0Pu6#hjCQkeejznwMzSJp0Ezu#n?R9I zCPF)~u4KRYy%3f=^QpVh^u!wr_%9Jx{;=I628Pb6mCOfo_n3{@ju3w)@}#K6c37WY zlXePsJW#E0(4qK6+lJ)Gxh&S|1=H6r%5d2jz3 zk2@)(N8H;rSLXS!f+&9ijaytHFG;&vbz60KA2aiz!?{jVI@rtN{YXNXiy6Uz|5cDk zvI<=zo7vlhc@A*_xtlUB1g86eQ>G8VwTb#cf%0xvdFGeaimejGgdo`OxhOfY_18(M zjT4gwiR`&G=4yPHEsDj7`;Gj}efN0!Un9B7&3Eql*D4wl!`|Hx>zd|QcHM9hYG|ls zkQy>98}F*nseU%`lL?aXwtakTEF*2Dwvu+d(YK-M8CN_1DJKL&K4&yprNZo{pQKiL zO{A{aqvzM!+Fxe+#J9I}Cf;1Z^v6c*P2^!i)>7ZEdAP{&flYl7`%$|V8cx@^viEG7 z`~tzO%Z#aVS5kWHTmy2nUDQW4A@F4X(_0A(2g2_Ya6+Mfo7sdUE zQp|S=$iJ@qeYq~|Wo$c4%_^lGG7-C66|$oWQ1i%W@sSFpydgDh7tP!B&jJ>d&#TMM zWw;CRT!#0k?+Ym5dzVu;meE(d#=Rr6Wu2lVB6)n)Pp7`g*wA=FV)#v{* zdlE?8g3k#XJJ(D0ucdyCqcLQn#n0yRajml=^^(_vUuOi0D*N5u=~WH(dF{Jv+Lh3{ zV^XB`I@HorL1Zx|MLyfll}DXe<=MLedxw|Ockjq*EY;W8HQ8v0H|2Ri912?p6Ngle z39)K#+AUxE1+z>9HtGiRq!32OQ_8%mT1ys!*$#YMh53jrHkV7O>1ku-D7{W)m)bQq zBLJmg`W?C5HrM2u*OWa_iLA9RK~T?N>+f?c#-Q5df#zCY9I@qW?*y56p6x^&Rc) zXH=>M3FkCL`2BFuzU8_*!C{9l`&Ru1S~XZHbw_*|Gf0?=_zlMXEs}XxsW@SuW|1r- zAlUH$w|JkBi~$kXKAy4V3u`0drzriG(l$8u>sfrQegKBeQCa^o+Cf3ifAXt+kKTFW z8kG_HZe}Q_k{RfWwquAWjK!MnzK2dD)AFX87&{Mu zKp4h4t8|$E18J`%oYZPkWsB|HZ8Q~r>OV>`x-}FIgFiWsfiv2};09rI1GK?7j-zU( zHk@H8;^#6p!SJPRFx%W2b^G~uvojXnkvAn@D3So<;;7U%5L|9nBIQc*BoOrh(X4;Q zF4CP}GF-s?ee|5h+F=1ueObmfM{^|)!Ijjbxp#fcESB5VH%>VQM?dYLED!e!JblRqXd=Y`J07xL;(x@WZklv+3nl`Te3(dA(vd zVCHp~A^yC=V$P#KC~KHS5Dl=1io9;h%U{BYYjtIHfZiCE)Uk6H_f>%fAe_Jh$&o(| zV)muR_FwYXj7sZNI;KKzK0TYoohh(-`&DDQN9VYA1}ei6)wt!HlF#Gb9mo`Ea0RnW zJEf@q@I4eM57&6Q_>x8DSd!0P&M)aaw*3HH9?B3zw1B6b(f1uO+Ax*gUs8vkaWXFD z;-A*|Jg-xSoL)Z~opue^_|?78P5Jl$%1(4&D*MK`uWKlEO7{~G#C2g21Ho)RMu-h^ zqp)7$yOa`5C1s|5;eGw6#Ecit?`WSGrZ~sXU^^rfB$5t9FhzvSz!FWlgBA(yTxSmZ zGmgRVK=|`Bwn3%?nQ6ChtzTt7O!Ur^9Ybl2fIjpOvQUh3(NCL%kl2#i^HC780L=#nU7{)~ zqJ8d!+u7deyYJ59ovCN0UCyo~op0MHzwAp%?7A{d;Gje}Qv9mz~AY4iUnifk;-4P-Psu~Rwl3r&8+6{GDJ z*&?jYe;~Vs!f{spVKyD7>&Ij0p(N`+7zjE4wR0h>3TU-Zg)iKH5DTTXtNq&OqfGNmr)5=`Tyzmi;j3OWUV5W@0qux1W&A1Q z@y`6y>l3iao7P*v*>?qujg+-;{ZP$?g z$twD@8?8L2dDCaCiQ#2X{Ed>9f`o^8(eBHd;`kCz+gSOn>yPd=dtiqB!m^6hCIo~G zu^rl64E!|cq^9+I*(>+@a9fTgmkPcpd>YhQ&q5Si{GQ0>3&QA%6pAI)Jn;~Il&5(o z+{=Ars~8cpRw*+=MiC%^I@ga$ecBa`{I60d+CR)T0B zC=XW)kVtofrIX*(B$$r`SrzxrsC1Qr@ zfXPx$l*v#AFXG)aRcJD~#9S+BjQiL#c@F~A+i;|AV%A-`XxjU9u^)+^?82o%t&KOA zhifcubJ1_m^u5I#eK+T{UupwFOT09cg*bWGkUJe#c z8J?I9*VpjdFnqe_qxW;i^H}tQ4@U&kMBOsBhwc?%>jYGi5uV%cOsb5h7Mx^Oatf1m zwH~_sWof=or7ky_vuoijtR?aLG|#7it)AP->`dxP2;M9yqwIv7i8OR9ibnZU!WPyfW+o-QwUV~)NX#0^VZ3j3nZHuqm)$07s+R~QsHkI` z4Y?hajR0?*ta9wGS=hr@XN>!jVcMdxYCF_3Q$0j;U=ugr`*nu5*KFMhU$s4v75`=w zX8(Cz0}vYAW`^S>Qo(E_jlSlg9=!>xQ-z#C2^GfY>F3(F!_|ZUmRCKR*KjC;Ez<)u zqENQ!cKC^`+yOh#E_qo^K-iLPwt%YUJ2|*Q=H97-wN-4p=?P5kAYklVTbBMI>DFnc z*;}G?*h>~d@as@E@I-7-&wm~K`s{yvk05G<_L@Z#^#e{bEgo8NKV{i5f=aEw4kvK4 zs_;b_MytQ6)_lShZGFlNJKirI4C z0zatboxij?BD2XTdHpMSA+L2Wc8JrKNoDU~tS7}RG@5AK&G>F=3@d47n{y#@@CD5M%*s!aiSGEW%ZS}up z#51O?GNz5^_|5q<$ooeDh415^W}W{5@>lwSNvwMRDchIWlmqF1p#MNbWj$=wtUq8W zxY0jqmj9pYif+Q2P>0N&rSAV9u5c6-x^-9lfE4&TMygX#SR&Q zMJNohTROaY{Lj*? zXZ+ub?>@uQXgU^L?$$9YPAPoR>9_^9*OB8^^4#S4{i^t7D&X(d86;JZG7-wi5Px(9 z|8rtRYy!QfXqqs;@8M*%Wu$ayvsQ_-0C1dRZe1^c@XSfGW=SXul@zJ6qJBA5TUZk- zbT^6nNdltQh20OUiTfErJ9$O)YDu}18{zi=MyNlnE0_5h=Ylad9ZN$8OD*&BAHZmg z3AhbT^QDlpSKTrd5wwOR%`TbwyFW~}uO%$|`BOwbow^)20^MvXVBbXRN>{Tfe`OI% z)w->%&Sj@?IrCkR4BeIN(-$ZtC7M%AZTyL}okXoOX z>x_Ae!(ME<#|1Zfi~T;TROj_Mv&q5PQY~~6D}ENx;p3r5t~3h491HkRratMZfVZC# zuld`bc07jZ<#(c^M;5URgQ}-P(9C47a0`mx+nPVe(Y?+t*?|q)!h20kJuC;C`yqnwd!s|~hrFC! zmrNV!o8V8nl+VcC|HeOP>MU$B73Y6vnIYVjK=GmzILyoRuUURRxxR8lFsZVlo#;gI zd0OjpojniYB&AwWmJ77o_y%uwy;VLHbw_gRCy)<#l>?_fNsp9sS@PZk1ay^WBSUwJ za!E4?EBmuF@5aMEBeu9B(Q3$^n{D@%`(}07@yFZA(8zP-lGc+?yiDB$=zcf{;N{Rk`Dpr|7M? z<4uoV0{@wS3MY#^xx>*)FJH`!K_s^O1P#WmL-L!|1=mpvU!z0$=+Ve9+8m0q?!k;MRXRb_O9Y$Si=6P z=|`u9t(DTsKqugsX-h;T&+;Qb^j(Pbg7u>hWfs$OCZ-RFmed9SkF*dQmu2BTb7mXE z$UB()15G_FE$MpsI&-Y123GjC>K|x}XWS*E^zCb)CbY!KLVIwBWO1CO`)2)4RR8HS z_jYA-OO5cu)G!4Ab360S^P2CgA?SN?gJ&oSD zRYy_j6F((LG*9t>rd#)6#viEW+rNN_Gh3zZ}K8(Kyj<+^Wy6ov5NXu7HojlWJ zs+Zv+>kI`?vu%5){TkEdnGbDHRyawl%R%nZTxyb2*)-RD}xk{}}^+ zc@40il;kc;@On>tbz@z2-|e#Z*_(%Em8Dumb+N0cGyd4~WA5ZGL)?jnQ}S?la_&FS zuiTWlf;qe*MQ949rZ;uryICEZwgpoStq$x}a=oJV)tJg3ag9$n(^DGvmPgPhj{Q>dy-k zj(5DXsFZnjkTvHrX8s}NP0>cDtG{YqEIIuMZYqe;J`EOam#%)PWmFf_b)S8m1$Dc7 z&a>juiJH@D__S-W+{~Zb7;%TR^TOG@HwKpG;gvC6vh0R4$MOF_yJ^F2=Wir>RJK~B zIXh#&^0{}=q#W!{Wx3DMB&p0ktV<$|Qz;1l12x@s$2B!4QvU<3ayG=RV(8i*J9QZVaisH*-OCj^0^9>_b51giYT;+OPpS>;@Cd{s-F7I-XRu z8o_#;m^;)1gkDuaI)SQgEDXxlrH4aM-6v^XGO(A9x<)@Yj){Un^uXj>sHU7Z)5^)= z$LWE=RMlk^>7e2aRuBIovkaBFH^Ik53Q~2K1%t}p2^CJD+ZJugGkMtLUUvm2(?Ql> z|L+j?vAWe_`pUkOM*ye>S{b<^nw#Rkt2{UCbr|xujyKs(9&8oUm&cqqsa?EEQf`Qk z`yVKmuM5Gr0#;DXq)~qLW<8hA=yZ^|XL?AIyD^~9m(4t;eh zlDn);x|g;hn`$N``0L)+lc;+Jp?JRq`il|Z1`mI5gxx;y0;Y@;HX zYwSf+L78zg^_6?Y$c5w^;GJ?34S3xkPKjo7!W&OuL;y+kl40K z4Pt~$k%Bq&^@I3Cj5a^sV*QZ223O!puWzhHRS}>0AK!^b*~y~Qf0h|0i1@Ybp0%HTe@z-1G!5GB?nJI8%fBd6I5+hE~#Po0gF^3mtbvh z3+Y201zVV*U&|ZeW}gf%|Bo}ndj*ix+^urtW}L!Efj?e6sg~7HNziP-$%673?I!q- zJG2^77G2MIwz-7BB2w$()4D7Mix4N#PkEyR|sel!IF3>qtxk~wT#VWwzN%JCl- z<3h@L&1d%=m1o=T*o!(R*|fd_7^p5oflbzQRr{Xd<588$L?xNW2k~smvt7^LtlwU3 zl-x}3GR?TOCUf(_=TljXuy#rd#$znn`v`y1RhMZ_kg|DL-QHzvnQ`~WT{mHOdQ|w> z8*T$#SazBAsX@qy1)hoJnum}kAdiYAoL<^+1=IN{=ZEVvmYoSTf%OSxMpGvCQdt$X zNR67sU{|kuPOE;S0b|^TEEQEtKjSdr`dNF?@oZgP36uXo zy&5`zR1~oI9LV%~zjo6?hGC1zv7*MXUTkjx6bg~UOA3Tnmgcdq-?=Vv28bfg+TSAS z(0Y9P?)F4XSwaE*)=yZJo49@Y6<7MdJ( zBu){d>{0E>*At(Y?)>bM@m*^nd+k{8$iZ$WGSP(+f-rpR(b`$kmI5lD!$^arF zfI;{5F67bLVzp`NOn0-1Z)-}%sZJg_en9lSoCxZ&xP{;NspL1+)_rWsykc(YW!ycy zhwZ=gy~6dx)ajc)!o=LQnS`;ZdJDbUV=tP-!>D4fDJ_f#b2Ajp>eRR!QdnPZpf@l0=Al?|ga?zM<#N&C>}Fn5Pg0||&@gmkZ;6xd5X6aw zysrPy-7-J!=g!Z>_+T(rh4a#)@L%xUA`R#c?0&DtmZ0sJ@@xI@aKB%pc(@HFu#*`C zd14@-aTXfR`FKpbck5bra_n^vyKpE-pDn0|dRlz7PT^7S)=d){C|-3U5AQUfXx@+H-8sj9QL+^(3KE=}&Qd+_FiL(Vrty2aFpOyMBpOP%XwTOw>K zQ()#5*yc-d73>QRyV@!0rHZUf&`(R@P~=O6ii5;+94Ih2qn4@L+V8ZQ^$ZExHbk2y zbzmc6#`Vu}Gb}bx5!znU*i+nec)yK7W<=E?lg9$+zDe~>G?f1W zKEoW&fHYn-ZDl~=^)39vyLZbMaB|O(WVk~Y(zq3b!hb9O5FiKxli#MB#dow8VRjc0 za;Tp`&>z;c@pMZvxSAQ%g!T-wxq{BB18j_pX;t=&9-Z3H5IpGfIqq}sPr$?mLi=Ek z52pYl9H_tqWirVc1Jj%T=eMb7kP;M#Dq>=6)i|b|wHc9`Qs|tJ%a}A|d!3}8PWv2B z9y?}0Kd6!Pdgl&@^wVT6jXZ(usbsd3qe$e*ofzL%pR81;4K~u}(7jY|LH5q@A&(*o zb9~YDFR)YO&^X7HZ)HhW%CXq%*Q*k}5~<_MnOD)A%x+6Mx*tz$I%PVL-9eAN5n=_a z>;en5VZYo~YI5{4hW&kgd`2P2bvoIAK{56$vrQ(*;Oox|xma8D^S>fy`hoA_bo^z~ z`*ejL=XFd!#PV4;-Wq7K7;gK@uhps7a~OplC;wY=nQr0E{9^>9`lmRllfLv;6ti}7 zl5zh6R%W~&OgZuKu> zM@RK(v=~$4*2@;P0%|x}Us{psH)qz1lZ5p>FoUfy5iQyJu5G`mJmF^8T1%I8`)rKZ zX#+<=#o)I4%H_hUNpFRbhNPw>K@5b+J1^>{m05HC!LuQAhVGW;yV>0>skn#EMkBw? zKf8I{5nVK)U`U>IXYzbMvFT&=Ltn-K=WiWZB(jAFhr1MhU;;c3rk)~PcC-gl7<$rV z(I^BfJd7@T1ZDD0ulxs+`tkP!{MAb<1YYTvGhW>2pKW2oRBRgVhb^a9KN9WV2>zLq zX#YBOeVKUe;}5T?bvLe=FbrIO()h6A;o5`H#b8Ao!;({)ur!})D{NzN7+TgN;G{&@ zVT9MeD(4-TRA(dnnwD^^u9`aTdEoZ#$EKN>DB?z1{0t{^(zy9N?QmWW*GscE5zG!z zzoaeaD!rHu4nA-^|8R$!Q-(z)?b_IUHHVvi0JI*uBTEP?Wnpk5ZB;BdiI@u7xE+%! z$7F?)q1j$J}Z5wT`7FwR8rOmPtRIN-d8bk~}g9JNG>%Kg8+hLqpUy9R(b8 zewr>j?Huhe4G^jM$>CPs0jp_YYcFv3;9BUIv|q*WN+3T+v7O?b+;3IMAz%th zJ)6MRn&)M2w$M^1hAE9B+Zq6^DdZ|j=*Q!vTJh$uP-HY+Ua57X&OnpT1W#pKy|nne zg6vDDK6JLaL00Mgsa2A?4cvWJSPYZP!pK`GGDc~$2CdUUuZV)VOS1*!Ceuu*35p0r zIrEJXBgQhx*dXS0g|MXIX}+>m#^G$*@X|Iy#R_>sO;dA}qh(*-EMtd(UgwF1)?ACW z2&eg}{y39W%o<{TT1>LZob}RmTlvvNRwse9EmpZK!jA)QI<3ta&8JjJ$N@!Vjihgf z!JYhJX8Jl0oO~0anaY(>8~p*kOWB0^2mZDLY-ve^zq+jGM=}o`>oTKYE4oyk(ZYAU zVo!ACi2p!Xvm;~l`WpQ~TC}5OyOeWRiLx3~F zyrzKI(-%?_;0w*aRk#N55WKjaauKQALND{&`y&tuU4Dp6aAUQyfliJEsSb4k90$NZ=<${(*p&b#q&$v% z!Dv-9ZPO5pzCE{A5kWi#PlRRx92f`Ebh(=YysDC#O^aLCDoY9fJz|9Mor{+aLM*$O zu*}7eG~ElXhPekRA)j52uhvDm93TNFW)nIYht#&v#Y`j?;y{zugZ%*TYO4@t(6n$( zR+GZl%mO^#WQ4+iG?_7N$Xu|_mxnYof_m~C<+I=#%8X_HbD;uqVvMBfdGZ%e@k4ZMiYIr-zvxeR9j=!%?a% zq2~2gL$n+cw0JRnOm~D{Faa)W8`FaIyDy5PQv&;~0pvb`MgC;|hn@{u&VPhKCM7v1 z(|>2D0cSujnVgX^tyf$8=3b=OqP1F^*KcI=m>7~_K1r_@)09UScd-_={rc|kY4h|uo~=J)TTrper>{6%MG5g!cbiS8e~;bN{E}-E)o*QLm{vAatj+HoeR19scZgcC~v76RCq4fq5MtL4Bn9)wX2od@w@uc5C&Wcuv7u zk9T>i7)8gc4o_R*+9=&S&~|W?^so3UnhZgk?FQzej+p$C3J%fn4-5sQB-3hF!7mNX z;5$x*FPT395v@AKkG5YU*b?~ry`)vxit^&WCNG#3q?nAY)X;;$;G4fEDf~46IyAlT z-1gs;Qd07$-m3o4Wir@$m^FQWx+C=T@bbX#RHDh>vO9;b;K~+wKD@c!H26*9DO&2Z zs?Cdc>`9m@1rpotR28DTm-sY$PG(-vIQI;i+lsV}`EVm7yFi#*&bW_r-QuS(sz`a0 zoIOY%48(Z~6{gy=qdu$l%J$(tx~ntYCk?AzxaY1!{{xK~3Z9=PB&B~EPam9|mtUBG zc8iBK3||_3k3&x6uwtB!Hi_RW-W+-ln;bM%6dRWP1C=u^{T-OB?mhTef_=e@XgX)e zZtZYvON0!FaLxs?67ZmLD}aiw)z+4ez0d>_2vQT^(w9&HTP`jlAxO|0neDW(%$j|< z>=#PLW_BX7r??}TPq0}KB+#kWe$L8Dm0AZOXmQidroFQqaQ>T`Kgjw9?Zj055utzq zzE8CpJ0qxACOM#)0XrEiLKX@Kbh=E;x=Zutzp(OoZY(re?vqzu&IfoJj(LTI3AU#kz^Z zWEm~Ma2J<*n^{?a)|`NcyIiu=ba8RHbgjJX2MT6Pz6BPAO0$+^<`>pLT>{?|qkm1j zVpx>af}}tKGxegK21u4pgSI{jPO5F8{I`B9|L(ZKfwB7Na6Qjqfjd+tYNDg({CjWZZZr#&KC5X#ly_3r zQ+2nbcem6-P%!rf*Knw#S?d`ztG%tUZUftREy7Ds_x0}1xEZfO{kYJbK=tKti_>HtPh1@KwZi5g7`eIQk#yxcqi1jJI??bUO;h`j*#Si}Eu zxmj-o9QBlsQo;Dril+67DKE5mLFk2Pkogi=>kEzke^!r3hQw(OWn~uMoScFIbmGco z4T8FOl#h}(Yzt)?Di{Ka8OQ}eFXLVp^3J-7!Xr~b4Omh0+H+hU8Gv^dj~rr4&cB@7 z1$+kwI)n(~;k=@?kSYo<7vP-300ht{K!O>-nWHLA`E&tXSOwc&e6@UxQEwYu>=@`# z$-LOISWG!4%KD$>0>TYtZvu8v7C1=tss$ymCDKc6>qN*rh7f7lv+h^_xCfmFGZX=aYQyW@H{jVgwu4)(gC0Wd=MCm=?gp_!2ijx?+Yd?%W{C)iDb~s ze88*$%&@tlNvons9SB;q_->AlCa|J@s*(*kI&dVg<$-;VS%KmRKo3=}jkX#nUp64S zSgdr*jrH+(1D8vbz+8>t@Y5H=ss)ZZrgOa}-Wv#IcDH1xvRXkMa_LcAqQ3?g$J{R=hZ9m#Jyy*+2C6 zy({7{Ow#e?Dypaa$Pl!ZwaE4>bG2z0HuXk=j8l>d z31ILp(7V)oCt=}tAbl}qOucCY4r}fCs?U8n2CsbWuS46sl4Lix1w`k^a(+)aN&I+} zIE7jFH1)jTF_ckI7g62X;wxfm8G1uRf>lmn=ZIbL2~WbIEi<+;{jCEpi!mE7w~Nbt zJ*fbaVu`uu$s*QqXGf z6Xo6_0$#Nk3q^qF&BF;q}i|A zICC-uut!yMmo)VL@ZihSFn%tKt>;}JL?XlQX&g#tJqps=T;$(1Pev4rcB1aag(VCG zM4--CQg_UdNr&DVxkYi*i;5}oXABVZl3CMZ4qTHxbi^s3`p|9pGAKB56}L1d)*9dklU#CVCL< zo|mg$QDC=&ZmqDjvyH#sf*VJre1gB(d;T%t!;(`i7V^HBB%}ld8P=Y`TCI}Cd*Oc`NQa&rXTo_IJ(ZPHv6B(Cz zY_(_E)Sc(dAVk%*Siod^f0)TY~qrPBoJ>3?g}q^Hhrm0 zwe;n$fTWq`#cLwp%4~grzQZvG5O*F_Uc=_+z9@Z(d3FHs+xO301-!HrBTCzE^RqvW zV3Fy+|25g?Ih<}F+y{Q2?&T6gkr_OoH;g)-FXJs+0oT=7ZXUP2Ud2_8+Zd`gZbw`n zj@HNUEf~8g%No^ISkcje=yevQkf zCja3G@y_@vWji6JY_qoG&}edHF1rKO^Ko^@rb_h1M;zke51S!%r{ddt++t5R=>4Nz zntl0Zbk!i=p#I$WJUZz+IxAgzQLtg(VPnKyuTO)Q#u|a$B}3LXvC(=V)=;BV%Ri+o zYF07orZIpH)>(WFCB6-)6c-xp$X2;1Y~1=NvzP^N9u`gOa_zpsL#40%XQ|bqP;VeJ z#gu^jyvXV0|A85Vx@&*6NiSFsp@hN2w=qt9@v7|qqxu1sWC92dFpg*Wy@L1kp66$h zZFsHYwZh>7QP80v@MqKyBETzOd2qUb0GBAhd(!OY+VVgamJ0YU*p_IycDYQl8i4T` z(z3a(F7o=DMo3jsa6it&7!iw5rRK6;Shl6dkdUh4 zvoD!AWxSy$^4#}MFGmDxr)C2!9G_^~g03Ix_)I(S2P{fGjA&hNH&SH+25Ol)4^^0$ ze9F%$o2*52Lzx#n>}pA;1ya{c%Je06#RHcsyzY0npC!5js##NnobQ5;*82fny5-UC zuM=aJ9Sp?6erN`I0tPUoGa_VSY9QsY8 zhWS#}Q4^g*_tlOxOZv~(brjZ zTV55eD;shnFQO7HXQe)rq|@j=4uX|7g)x>3G+HtF3q-VxlpT0SNa89~UdyBIyYx^` zV9TQ-Y#Bl!q~CNbDIT8AYGRKhe1N012+iOp9LR#Z&${ZyxhqF%?Fp)}pw|USI#Pt{ z0w$7wh<0l%&oQHK<+qu>BnwHtrZDS-pmsZ`{JH|aOhyL=hUjvhJY^Y1KXl>q3>)6F}?F{pZA~tpB$1Q01Xy1ql zCI=cO7SE8oRJexGfW zbNwujk^7F*GQECgLUl~&9fD6ZMnpmOZv5xbPb4d*@`S7nR-Vr#YZz{=?UYFD>%Uh8 z?_qq0I|^x%dT$x*Goptve=<|Dzs=7?@t%EBbbIcxT=`?!zZ^j@5{z`MfcD<@2S@EI z`1e?jJFe~!43wse+vdr&DHcrxloS0c)x9%np={bOdD#L)jaqL>+N ztGj-zos*r&ZRwA#nr(^oJl=C+rS^tlU-#U*v-;@bWH`ZR5xe;zPTC?V-DAMYR=D7{ zFFs7K>{b}Y*l$VbpxI#9x?{XdO?7Ti{dM{!A$l_yFTynpCXiMczu%>pTg>5A~K!`YE=gW;L_qg6iC+b6mTZ%YA$VMi?O+C8ukH?2+BKu3;9 z#Q($5S%)>%zkl3El#mh-1V%Gzgw$wIn$a~z43O^8Na{o9XrxgZHaf>Zlo|~Zqd__a zNfnImZ_n@FUDwXFopYV@IiLG}zh1YDBqFO@-DYq+xjiXA&v>xt5&NOe>%EVD%`(s$ ze7B0yqYh`$UR0&0;Y>Ny7e-@Q+csR_wwHKJhNc`&2`8}kM9j*=>F%snmlPvw1e~eH zH+m~&j6DhMBCgC(hX|n0lINi_Mh@ng0)5ITpF9+xMrB1cxW$r$AkcN{2UN6j=W>n; zm+u0PBiPx=Db0bOi>TW9#c5dZ*YX;oJ08sPuAT7M%aDOrPo$XyF`JgLDRL17_?X+E zuzv~+^Y9K@3O83L`b+t00XiPm6U!b=lBbDaGr}TX55Ah#rh5>Sx-HAW#egunZS{xc-EiSwxhe1A|29tLx$oqUvGG}2L`T;=zLf8)HULrz;fAN z7XntU6iXgFQ3mI9@-?Ja%u=cnY7$OPoZ9ax2u){jj;KhbCkSM62aWmiu=(DbhoK*(!VN}?|DD#Q2yJ1a|0hMVo^2EK#cxqCqeSHET3+D$ z8JXtGKtEZ(7qh>&z6izZ+bN2I5yf*;?!4)9j=^&`zjB6C&Ko#9ZeEFK>MJE}s|Kd6 z%`b|+%T`5kUvDu>M7%B@b-PWN>wcZI^D58AuEAT@|6*RQ+_9tKxu3!7iq?;9HnXhB zg!b^`=O4=|n17d*tFWH}VNc^JN9j7iSia;>Re`yw$nSiuH1oW-5RJ9Jv+9~Xw?-PB zQVp^|I7&c{oBQ9jRwHjod*}TP&HzLgUMm@AvZn~hd0uR&Vk-061i6y02FSrHu>$T) z2^rh#lDKlrK|mDOR^Vj=;stv8sowLS4M;#BJa~WKvUak3W^dD4P4{K7DTsq`vdXTo zY00cCixrc6T5e?c=28bLcXC~e#GcWgAY)#Uo#YU?c4$}J_3NjT2*(pafCP$H++xyP zw9Y7kVKe+)RAD}<5FMNxI7|42G)ODb_Y`(f8hB7gQf=~L^Fe4@OERb3{)TC7GHw5i?2?k2hhLju~Faj|-x)Pw!VO2l40QQdTnRo8!-+ zwgu5Ij{U_QboDk2`mE;S*XS}Esx77Qx@8vDG7ixz%NRATJrSG64%05pKdfSMgJz&7 z(X2L)`oAK4xXNwpg39?GK08Qy3gX;ql^OS<|FA$Gptwcz6SRwrBt+8Zv#Z$cH3;pB zhV`&w{iOpK4X<}Mm!SDFTKfL+=%C>#u9A+2S~`u&{Uf_^i+Kp~2CIITKwr~xVb#92 zRAQQU!G<l(cHQ72N3m^MZAsmD{&^ zW-dVibg2_8CzDA!@r1xRxZ)n7W2z1;v=M0YY1{KO75(me~*~yk84fT=b4hoDRKzTc1B4$qEe9lDR&i%2aB~ zj)*%CefJ=SOFElA((=Sal}WHdbWNm@t(u71te~|p`<#z%|G4tGVkBJ5xw`lrm|6pO zqHKn{5@tEl(bBu)G4#B&;i^a5qko1Qq4&I)Nl57;b+~;<~C27x25(l!PVY$E0LBZlqz+H^rd#_TCPBt1-C^6rFkX-w@Dy6(V?~1e(!(Hq$~oCcM%>hhtRma%Puie(LFHW?7$DkneCQ20Z$+rzv!y zYVeR;A;6w?o5t)($5UP>c+I=AvNMr7ECa`Q(!XE5w!OtovDkKa?b~24?sX&pJ4zbn zW{69&Nj4q~(V8-w)7}8ZAbkQNz*H(UR!;;uX-gMNjt%8y4}JEuA16WE&~5cz&|bZ% z8&3%^r4@E%J@3lL41n98lCMtu%na};bi*Wdo2uQ!9G?^g_zTR`Vzk?dQi;&3%(or` z&f7Xl21GZSeG#@#=_*1SM-~-D85*C6%>(L`ecahXT{y}iawaK%oJ36|sCtoe89T$K zN)i{mQ~D;_r7XJbZEL6ena>~de!tp!FZ12GObas$hX@A3E|o$`X8w*@=0SI}Guwk) zEl4)XEIgk}s-5-sGB^L#`^n1-DS#_H5`544l0`|sj(@!>*Q<4S_nAc0nq61iu^w)` z%Yb`xpIGfH46ZQKBVQ{RWOQy8?fRW3xi8J6wl2Y}^?T9!we(||@qG_g*UXuoj;d;^ z`ybW=3rB((Ds=oFvb0SDBw`)nM>g$V;3V-A;hia^Qi^Fs!C54|5eZpV8{i>($lcWgzx z3UOZ=j3hNi2j26t?g=5?BHe2E=_AyacUcr$smsP7VAhcASffjQ|NS@8q$bH)VD9Xg z^E9VaM{TwRbNeIB%q%Ke$xeq*&p7iob_+~{T)QOI)OTL?b|}b^Bm^A#yXe11C&#Zf z(}sqTX2Vpa%va6pG`=76jKzMq8<6)Mqw3R-wYKMcS=za9TC(-2J>&y7&F#bvb%88e zN;;OQNB{P&&&OnkTJxorh6)KoyR8);WscnySZl`3kmIq|95?#ohuaB&7_%WLBZ_SdS_e};TYsp=CE|&ft<<=yfq2oo3#Gj*_W7{c zOBSEjQx=r{ja>q7d0X%!-_?L}`xJ_A5kb4yeKCyq*S|{E6oBnrDN&yiwY4tO<0TD74DKPcu(; z6;#_79}8>bc$(}?WJ(C`xe1J8Rv#3Au?doXi-04e%d#(z9gnYIGpx^O3e8(Qx#M~X zp+4Ryh`j{C*5tVSOb(hDu+)>P_n9IjNrcBL@Bv*wcKXjzUnp4*7v`{2vl%=8Nkgg5 zz3yg6eLpOGqgBK+z@f3%AlMt`OzXJUkeAJ|G=PqdLn}V&N7lK1mvtS6&_Xx#BanQrs zPaTY{u(rN?Q$~m=`~Rkop0WP;`J`elZsjIK@YRe@7Fu0tN+ez;UR{9iFkrJlpo5-v zOt8{w%kYQbXu{)m=dxfA)D%zlR!>BXCIdafy<)y!lZ@TPn!VaXc)n`qgv^wx%-*R3 zxg|Jb7vv{V{b!W7Ze>pkmn7F093etmJgK$?2i?xlYSIV4{0(|rsz1EhFb-1llL2P? zlSkv6Ynh0~4f6{BsfdPl;5{@uO$-Uh_CjgwOg%=^!p2q_{Z%UzE)x5JKJVZMqeA3Y zn9=^gF*CN{$Z_+ncf3E3%DC%|@D=T(6jdeG#JlUE!?3H) zmStfaZzhszrzf)|JdDr$7s=d^Y2wFSfPMNR*fClhPDB6gCWj|=xOg}kU+cZOPMkj{ zmO1%YZU%r;d}(C;Pqam+2ZLe^Vou-b{`#zkZ2q6Bs(#3)-J?_13OgflKRmn8V%Zm( zcgbDWl}QDi-o9OrQs0Sa2cjO@QMk%dd9-R!Xio1Z>r8Nqqte`+2YGM51J^wlAG9Mbr6{r1%L-7akW&Vxx1~dlo z01wggmGa6=kn~QVT~LK_-PXKV9b7HFg2==N)=60Ya7X*>d>h&fHHZ!UI4aSWpZe+O zpJRb9+;Lsp`pd5~;mk9}+H=G}M&mEMXXxJ$(VfRiCd0`awD0CZJ+^fm2mu-9aIfTr z^B}G>x+up?T(Ag>2;oh~T6sz%jjG1MlGL6TQ*V_6zYYv{t#U;aRCW&px}QF^?DDms zPNJX6DxFveP8AnfMb<6z%YaP$UN?po93uJED%S|*0IYJY-c_8(k*m7KHi!^a2PSCINDsc z*&!MGGopX4fn4Sur2DY$r0GE83VDDmS^@IlRq}`x)MiK$Rv4AA4w&eHYHn-3)8Yk3 znU#nrR!Cg>FER^j*Ul^Mu5t-_Dp7NnMOg0R&F%WJIQ!t5GHUAB2BY0Z)x8~sk`Hc+ zM$F*8V~+){x*#{8?yQ!iS;8x$=2DD$DQ5JD|IJhTki6Li zxf$|@2Won{ObawdERG$LE8kC&FCK(PA62gwudf{D{e}Q|?n|Aqln0ftT#FQm;IE?+ zzHkaoUx$2`PlH`N@Xp;NIJ%lbTW*J`-!vQq*-Gq#e|xUH84T?GXw?U3B|Hi>={ zoV~qP;LCkWT&oS@gE0qzn2ky%`)+bvb?rI_j2noT4jpA2Q;}Z%cZBN>EH0<1NX~$1 zsn#TJa7FKN1~&xe1nX)bYfP0I&~E%UHbx52Q7Dg;=#^uaWft`s?H!i7*wPwu_E#MO=_QuUVCK29@%wrAz*3427j~8 zFn(_?T$$U`^a}F@c0HBa&<^Tgq|rMjZf4M8-<^DV0IMCALHreZ#ZK9w@8;{DnENGm z^X-%qg=4PkawybzNuM~Zfx1p5WR%D;?G~M+Wrcu)P1B1lK!+|0 zxwC4{N)5GdvX&5b&1nN>6*4Ng7cpFSLuPdOSAVz2%_@L76NSz5;hP9;-UBnacjW)Z z2ZQI~v8_xZWa>$GH3CV6Yd+%CAE4ih#c0ZX^U+<0Cq;iv%+t9Bo&nNY z_24o4lWV1tCTVny?g+UF{JiMpfX@(+)hFnmbdx&WVrv%sGGWg|!cbVeG9R7suAr7K zlWtmsFADY5F0q~9I|&sWWK8!`sgK1!7iJerDgmu9h~iPbJ!IPu7RamlM*4$UwP5`l zEhc0~Cowj?q?l}khJ_<3fx_2wFFm!i0` zkK-adya3LFv07~uTu`)q#Fk|mT(%oD;LlfXtkme75B5bBroA$X%WP%NblLm%c~#+s zi@_6xUsxR6M7RZIjvE9h1PspQ${t4Oiv)U95eJJE$8Lp@$L^f+?Z!us!eHWw@6c%Gevnj9diQxXmW){-Y8 zFTI2r)ds5o=FeKCE9$6ouUZCXv1lW>tDaH?QU5 z=bYIkU{q|Fe;Jda(JfD&IWvXYmYsCI7m$@HehX(ciO9>^uX3Yby;b zNZhQ3xCXcZ>#riN&q@jOT`+rX3O*GAHlE3~u-dq1n*B)2e2gmF(ba>Ml=HFhd(G>f zuwu(l=2uiT#+I*#ARf$i$nf^7=i0Q8%t37*FyW|^w_5g2((ZN#4J;vS+ZJ0aj<)pr z<)W(_yE>+8JaA^3$i-@6-NI%RIxaYTF;nj7UDgJ5i(`7iegig_=QW9i>vyn_y|Hew zr7N9YUNkg~cipnCKX1u4sLNxIEKxXSp!QFj*lD-G(29G>Vr9Zw#4(CLnh6qOtH+p+ zp;x_0mO#iJi!CHLakaFd-#&~9nSWQ1#5Le0P(ykR7iQ3ie?@Rx%mf5S?6!s)XSEW- z0_K&76U8*+Bu>?>dYxY$?kC2Cyca>ntCD4*Q%f+cqFRc~j9x0$t70Mir6urMR0FY( z1GvTLYk1CJMKa;Ss2T;{ufCd-``^~(nsC$UEB831Q<}K8F^Qf@ zD|#n-(yqQxXQWuAk_+JklOdDsB`9J>t;wps(r(RWYuH))tNuHwG2;G>sV)raJq08+ zg}*8u52I}L@a0A%eeltzHYu&zGbs>AgOG|VSdSg2a5>jormoz2FkP|1z&isgs-aB) z-&P}`Z{m2P6s}Op*&<4E#^Yb614gME0nj(8+;jYE1y~Wdp7V{6S}~Yso@$5Hjn&$R&?o4?fX0?aOqul-F%ySPxd1CER3bAD($_X{7^dHk~g0Z*e?e2CQ( zwkygrs4x8tBjKT`H&N_lHfQ9{W|xMpr~IKR_B3GUkCYt^vX+GsFwyB=*(bh&9!wiu zMq$%*A3I9WdcwF#t~|E@cj7RnS`eOxq353Q%3~5CTnbDoD-+o4FCVQP*}g zH8zjvqxa`JLC_hM?$Js|V&pn3wtBM(Qer)p+ik6N7W{q-_Nz{C(bdU4JtF?6y7OPm zUVL}=6Gr<<>rLcqpx8X_JM(rZWdA9YrkuzisFc@6X<_*6mL8q^)JA}cH5FlenO2X| zHec|+Yg|DnB&1kc+zQF+bYmQ&7e-ke^8_>2G0JiFye$Jo5#$NR(gbleY zQ_qEdi;370Pl>d-#P%&vd&?;LZl5u~hnAcF@j;MeC3Uv_oTT#jXKcDjH={%l=Gx3$ti4=nRgJ1&55f zR!QbbiW5nA3>XKgn_h(;J18=`@AMFAyBa^Y9cZ26omq9g?r!Lx=uVS#20S^*mo75h z+oz*Ii26(x2&YHsJL02Q=m3EDJ9}dY<(UAto@1a$-T&@szv12*@FV)CmyJF^%F$AI ze;I1=^B28zV7&1Ln9(~nc}+dRjuZ~d8+cnJ=VWDFu)Q?pr~PeqO5MS0 z`2?ek-gC!2^v4%>iuQ*EpLPrt?VutV8J>;A#*IcjG{H3zqY(Kh&YNFt zweG+$`RMjv*i*#^zbiz?;c`>Ln{Q;m`lfiD%eEQY&pleX$mLb?N)YOl zz7RGz&=B_3-RiXkMZ`ag@RH4giJ1 zshdzCg^{Jc$y6xEU*v?GH~KU^kWG=L1|ggd{w#XF#bK<%{WgA|dt`m#t6--kWWGGD zZRi~XBrK_~a~qmYQ41klJi8I*|{LM`yZZ_-Mm*ECYIRyRRE z+#5M_vv2(@(i-gShT>^KPoGdk*4N~pXt(7H#QBQ;{F-3}bNf!Cb@N(2=b2*p{5BCE z%sG_}RR2{tY&@DOPo}nJL?MQWPGf5Zqq{EEpPZxS>a3#uOwxkQgUDT-Pb#!~S2Dr5 z83h1;BQ7osw2hdrS9;>-PvpCRTyAz&kr^ErfX}6nT}RB2DlUUYhs?+6l`=UtWc@vp z-q#9A?a<0$cG~K7;bVFJcBN3c@MB+XgrrD`#LQ7K@m@(womr^7&)}l?>qjz)v4Ego zpS}qq$bRT5blKAUEE-UZnHWrBzciHMis$yZScDus5{ecl?1r!v7ZPDfhL}Z5@BPxhot?n@h z;D-l3V8wuSx+q+aSk1!HRVFh&EkMUnh0Ka5ZfB{}Y>!2fI?~s4fg`-^vD9!uikMni zxx@Tsae;>=E1kYe(S&EQqi*onbG=!;rB>;O{!zXpj}Oyy%|9(gy-dNiFHb^8Ol+Rk z-Tb%$_`VDNsk%jQY7~sG^-0JIUk062Ndi*Hn8i*P`GzY}DKhTVVakW=C8#yW)rx>+ zTiIKN*L+CPZB%h9dxgfgvRP?z^@$I6y03xW^`MoR9ux??u*c1O*iVmd1;#Y0HZW_% zPp$abfN$Sjfd-8lxRt0 zUk0Kk*q^`H7G?m9bC6!o55tZZGMpi}L+wiBvXO(4hPdurP+3H|Xs=H-k*0;g`wgbL zxQ5L|&|ZJDTlkaAtnaB}FuMr4YD>LOi-xYlB%Se(yvp*#2DaRF^7$j{-j)?QG(_}A zJ92foN^@Ct>XGcY*|pp2VdKrDI>2z-9n=@d$_xE6y_*jO#ycrjkY{wcN`_g3ndv5C zjRojDna9VSq)8b#W9_06Be^~#6s0)Sv|8?7dA%JSbiTDn=S4qXKo_m!laddL9B96q z+g-GE#j!)3#U1y`p`3!}WMU?h8X`-Jh!u}WC8NAr)kR|PqRWw=uaE=8|5dB4l;lkU zxEhB5-{e?{eV?s3w_nSyoY27;jSgyiYr|N1n+!}=IN$t#*xvBx$@`c=SJx^hpCgSVjAGn7f)6bvfyY{>lw;$?iIVRY(wYkJxcMS0&->28x?B!;po zZ#!=>hl!gp6r4g}(t&e+&*{nZNH{j#I@;%>&FL(zQg;7%iLgI@xM1@LxInD7#-=@Q zsl${zB>*yJ>?Vy7hxkYax}&N8>AVU^DJ}*NMlK)`)#qrV_D3EfjL+}LFQ>bn{=01~ zb?M$VXn4%#;fgN(Y^-KDSYfH99;)3f`H+;ibUg3ZquM!fxVle6HU~cL0^E0o+mYsp z&>Au>gSsf3kbL{FU|!1&>vsGo5l>5D&NQRmY@FliO`!ik z4=*YcmU8m5HjJ&2*s4?_x!6Mw`a;*%y+I@>zos8zIS>{=;rfHQzrHl+QJ?^dc>jLF>Bft;O#u-7pz$V6^9&!-KVt!dbR>E=&8{P7+`-Un`% z`&*ySn2457VU`>AuB&4lYcVmCUm6q!^Uw@5Lmhr-?-z4-D#L^g_CHel9i0EW$6ojM zs>E*U_RfoHP-^Y@i!&47qes+mz2QT~VO!~SH$FzJRMXC5S+3d%1gIpy1Hl9T9avud zb4vL6tB1wYWtS`P0pE%R65vxJ<{H7rZYPvjgdOruItMq43)yw~Q(;fN`rhT4^{r`X z%J`qMUPiUn(Dpp`}VLAnB@exs)?2WN~4HdO*J@}{5yCUwt7;tJ;UBx0Ps=yfW z(Yqo1uYcD)CM?pEk57&j$?q%WGR$i@TOZPG<{$oC)4DB;Cf@P0*7xqIn;nRh_oN*w?A4tpYO=?^dS92(O`kta^Eh;Az@*w0&cO z)Z1zpAFnNG_f_<1Z&sA9G&+4@LWvc-KOr6CDCS?Oz?o}8w?q|^fRL8RC1MV{q3A_2 zcpQFJqN+$gr`&D!(@f0b-yG*G@)b;~supVvah-1k{2BR?4>cv!`3}dNRpGpd*~(^M z@KUQz^6E4qEq!pjGX8h}2Q0%%TP=V(ZUg>0o+<%MN}07$LqLm%z>lnY#Lt{jvb-2{ z{+|`zfj@o-VIns7+|lOmH89V`4^z?Ev)oVnI@B8nQSYny;!bF3m9alUP)o?jg)Gkm z<@;(EP<9!-uv5xfL_WRl;F0;y^$I|(!cbTAMI`gF*J`0T=aUSl#;WJMh9^dKS}(qd zSM{14rV1OI=O>5fO4kZU1mDUHWT1^!HNM)T^L`pB3(t=nTcmD~22gnfR_<(dQaW7* z2E?bR9Lf)!ov2T&Dw2wn7*Ui31#&P6JMiE2Wug_FL>H-Rt@ctJp>3x##Poy80h8R* zz2n*{*vSc@F;(V$9f!Xl4^BrUfpd^@n}bD)p1Ew8WirX;teD2JSY2Xg3VfxWMtGH+ zyBV3-%8HImK24^T7sP-qjXh4;a+(gExpWng+oqsfiwYs)B8jShkXQ!MUY;@4J9yld z!LPwUjiiGFM$^=UHTx(^?Imjl*Eedl5%;BuG|dY*(?4V5oI;9WixU6F_eVGi{$wJ( z)r2t7`~~sMFbhVTR`@o?vIh@oppzNd z(&h<}N-v0~I9$-m|17RFc2BVI8NDIrV7jnMrh?^}v;pZ6*0A&bhx`1joJ_U#oo~>q z=g`bWJ#7y_Et1&hFtM|st9h{R8O^RGjc4InMcE_(WkqAaQ#g4L6HvQSqr@+?Hxzfk z%Vm+VdDjm*wJwki@O&`@Ot<8}uS0R%bktSkIIhz#gFZaGQTSt7OCMsAxL|7Y501aT z`E;Go)S`|vq1v`G;hOR9R+d?1*VAUwC*AYH=^K4Ewc*W7%wvi6C)@~5bGfWz)K6U8 zJ7?;w_T@f(PGyewE%%9eJDj-(aWw$Y(W|GKucs8X2ekK#o#oUyo`4pV)Y2J4J_t^J zXL*+>sj>AL>M2bE|5Jga7!`X|L?Ms8`?rpqjgZbopg#z?PO-nYk>S;e)}OS!>h5_I z{6Pdx4ZBd%+lpWqvlobxXzfPmRYI5JubCMa$$T^-tgV^BpM2}B6?~nD7D!Q|LzFxA z7BwjYJ@w&)fI-#HE0$ySU5dnFG5ZHTy@cAuu}*w~dQT77`N5>_^yH=0xM@+$c1ul+ zwPxq6$%teP;;GN;b$4a0l;!iw(6pKl1NFi(S{p!uf1-V$B=1E}d;p%Ci{>0ERv`?e zHKB!j_b~pfonpsPk!}HxhmAZ(x()Qw&d*$OXZN-}NdTfbG*}vMVWYdCnI+41vryDBLexiw)gE_4ol`ztr??@;}7w=*@uJB zp6|oPw2-SZtK%yZ9&nefWG?4*R^)fa3$OPx+G6xL?5AH(PK7<(Ex!rK4}{m+9Xjo! z736c~FojR0J>p0E2H~KZRA1MddpO_X3=Z(NX%a`FVYnIwNKj5p-r+oH1_GGctik~_!7D`+!kUl?u zFj`A*jsj|}f0;Jyrc_TQoEO{C2NBqHt0%?V|B+eynL6D((`^m|?W|-JN{i;{jK85X zKNaM0t`uY=z@VCGE4ZHO%SAplq0UOM1 zYh2wPxUQU;pz1G^`HVM+ai$NEemZFu15XbMI?f*Ce*$(^nnu@OQU;oJDzb(#oD+n6 zw@1Xg_VsO0PADi*kDHihp-TPARPwtxMV76!^}{1Fh~!XTV?pWc<&xJ1TB~y8^U}r8 z0Dt~5#~j0`x1v;LrvAb@`G^kh4_3LjBA#gWq;|u(k5$Z{PVvqQs^$l^HJQBMFCv^w zGMRIQw%Q=sZa_>!!YAOB(J%0{Pp#hWFKF<~+&=PvZ&>We2%ywWVAk{OQ2MF8K9V`H zWL=BdP8Qm`hiZk;K{!ms8s8Sj6QAVG{h*m+HtcYs`hJF{aH>FtfSkcM*<)IZ#OP$y zM_LFa`Xt8MdMuVp8RKIyYEuvLQNGFUaKotmg0eBa%oD(PWFISOD|Tfn{2Ci{QAM;c zEFib$kF}gGU{-c!p(zI4@SRer+5kt)=mJbz&TwS_wQ~A(_F8bl@Etz|#Howq-3MFg z>qLQBlR-Xbxvw9ygSU5IBC`WhikV|&I!zku0g@I zTBWBh|GO8ftryJDH0Njh8cZ03U_yEKVNcvSdv&wAivZHso;JUZTO0T`Yg)g~)sj9m zFA=i5!0*V;BNUF0gWhu^FtOi_4~Yc-BVn`uxiQbv6At0eqQ=Fexj-rq<$xTkQJenO zRsvf2aTFKM7- zgEmWhbXDct>uu{woAqzA7J`>WC`u1%o5p!AgOAZ^vFU)y$H~^%4Bh5(sAvA^g5!CQ z`Usx}sTff3m9mjIR5p<{0FYLwbXM1y_gN0x@P^f2Dz7b%p;0>Gcywgw3!&i%+MA2M zpe=Ud4eel>c;JPQu@p>gLcF~%RnD=HoFkYhd5h{a#JRr}qF#beI({>$SSQTCqZU3; zCY6(l7u9-_@xcc{Jv)~ufVAuDbc6vnS{Rs+q z^(umy0N^M~PMxo3&F^?ZjOzADYVQl@Hzcm>kia^dO=e^hb7)P`51)zg z=}UC1lVjxA@(?bR^D5jS8ggO-iZUM2mcp5d7eT4>co0D8n;+6_%6>0kgF!XxAU_>J z@B4%#rPTBotj10l#U@t1NS)LX6)xczH=@xr$uoHfbm41zV{^%~i zWcm2Xbn$j0rexp=L)Fe_k$NxsaSLV(%pWLSp?VPh#%Uq#J+FQ7e+}fYCnMPJN{z!t zboSk^9;~Rac+^OzvM@>uS!%Z~N@NVR@H?toloBif%Yl?N(r``&85E9n=1eAaV8 z&LlstTawk65)c=2|rn%S1;h}tDl@D<5- z3Fu_LMc`$TrFei)8C}~3^b0#OngoEpmSbToZ2N-hWFl65%$P=+{F(;J&)1rKPWo3L z^uK#m%0Bvafj2uU;*={}_{Yhet+r3v!jf5EhE((*lA|Zv3Ql$DF3$&iF1XWzKTRGV zgKcm&HbR*n(#oER5e0RRuTEK}Q*2sGYke1SYJ6vGE8-~ue9;--b2w;biXScg!)M^2 z3GunO1EfU!TU$6J6$KS$<*{j}ME51sY^M^>gt@d$^*q@rpWP2#XdQ$kzRl7jN^&{r zy)SW2xz*4|)hIFO5Wn?F5qL_!EhmMQQq?z+ZE$QG$-ZkSR-R zfvo+>@gfiYz5^ZPLjTCyN^v*c>Pr_xN(Ubb{21e+x-4w9X|fkwM~m8Xbc{TUH<|G* z$Ed##?3D&+V7WXB=8(nqB+LWD{EU$Ck|d@b{sm45>E2UCEH*voci(4rZSKnpJYO{l zS)Oz0!TRT`Nnwq4zD0f)S~qc?D>}Fzas{e8uP~VP`he37tBh-6{6TD8Towt|9@j`m zo~Foe6Fk9V2E`Pk9-(%(yz#M5kQd|r#IQ$7~@(_n4OeXjX6oAbi0yANSA;fr6)@e zDr_Z|9LYGtedpqrBi^kmpZ9^opE)1Jt&MPsFI2J8Q%odFzQ5j1kVGS5<~`yFkqXa! zDWq>+=!oXG&#e>IR0<2b=}I@Y=kb@I(=qE6zS-s`c$9|jE*ZV`aQV8p#*|tm4ujnG z*!^^|EAQvcUUtxFR+Sj=hc14ywkPk!@Iob2lUwc2d}dwqJKYU8QBJdOiXRbZVSYFH zio9d5t8da!Wz4P7OP_ZA=0pJeeYnwO!Kbqp49h1ixqY^Uvs?j}qbwoajNAn#(Un%c z_HP0mqT<%l93vmrjR@&Zfuj41{D0HqHY}5H?4UK$1<947G8RA%w}$(VjW7m&LjH4) z@g1eJ6k?}VOn?Vnt9oIm+ZF}!d4;M=zf~0r%*$Ww*)Xi=$j`%0DAzmiBF1{Y{xN>$ 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%0A&YZ`DDyOyu;&ITbaIN$DI7C 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

b;G*p*Lx0LNFs4=|S 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 I%9tPj*-0qrc>n+a literal 0 HcmV?d00001 diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/description.md b/boefjes/boefjes/plugins/kat_shodan_internetdb/description.md new file mode 100644 index 00000000000..c2bfdb90edf --- /dev/null +++ b/boefjes/boefjes/plugins/kat_shodan_internetdb/description.md @@ -0,0 +1,30 @@ +# Shodan InternetDB + +Fast IP Lookups for Open Ports and Vulnerabilities. Only free for non-commercial use. The API gets updated once a week. + +See: https://internetdb.shodan.io/, https://internetdb.shodan.io/docs + +## Return Schema: + +``` +{ + "cpes": [ + "string" + ], + "hostnames": [ + "string" + ], + "ip": "string", + "ports": [ + 0 + ], + "tags": [ + "string" + ], + "vulns": [ + "string" + ] +} +``` + +Tags are discarded in the normalizer. diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/main.py b/boefjes/boefjes/plugins/kat_shodan_internetdb/main.py new file mode 100644 index 00000000000..5c39e821581 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_shodan_internetdb/main.py @@ -0,0 +1,18 @@ +from ipaddress import ip_address + +import requests + +from boefjes.job_models import BoefjeMeta + +REQUEST_TIMEOUT = 60 + + +def run(boefje_meta: BoefjeMeta) -> list[tuple[set, bytes | str]]: + """Make request to InternetDB.""" + ip = boefje_meta.arguments["input"]["address"] + if ip_address(ip).is_private: + return [({"info/boefje"}, "Skipping private IP address")] + response = requests.get(f"https://internetdb.shodan.io/{ip}", timeout=REQUEST_TIMEOUT) + response.raise_for_status() + + return [(set(), response.content)] diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/normalize.py b/boefjes/boefjes/plugins/kat_shodan_internetdb/normalize.py new file mode 100644 index 00000000000..9a548515b46 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_shodan_internetdb/normalize.py @@ -0,0 +1,54 @@ +import json +import logging +from collections.abc import Iterable + +from boefjes.plugins.helpers import cpe_to_name_version +from octopoes.models import OOI, Reference +from octopoes.models.ooi.dns.records import DNSPTRRecord +from octopoes.models.ooi.dns.zone import Hostname +from octopoes.models.ooi.findings import CVEFindingType, Finding +from octopoes.models.ooi.network import Network +from octopoes.models.ooi.software import Software, SoftwareInstance + +DNS_PTR_STR = ".in-addr.arpa" + + +def run(input_ooi: dict, raw: bytes) -> Iterable[OOI]: + """Normalize InternetDB output.""" + result = json.loads(raw) + input_ooi_reference = Reference.from_str(input_ooi["primary_key"]) + input_ooi_str = input_ooi["address"] + + if not result: + logging.info("No InternetDB results available for normalization.") + elif "detail" in result: + if result["detail"] == "No information available": + logging.info("No information available for IP.") + else: + logging.warning("Unexpected detail: %s", result["detail"]) + else: + for hostname in result["hostnames"]: + hostname_ooi = Hostname(name=hostname, network=Network(name=input_ooi["network"]["name"]).reference) + yield hostname_ooi + if hostname.endswith(DNS_PTR_STR): + yield DNSPTRRecord(hostname=hostname_ooi.reference, value=hostname, address=input_ooi_reference) + + # ruff: noqa: ERA001 + # for port in result["ports"]: + # yield IPPort(address=input_ooi_reference, port=int(port), state=PortState("open")) + + for cve in result["vulns"]: + finding_type = CVEFindingType(id=cve) + finding = Finding( + finding_type=finding_type.reference, + ooi=input_ooi_reference, + proof=f"https://internetdb.shodan.io/{input_ooi_str}", + ) + yield finding_type + yield finding + + for cpe in result["cpes"]: + name, version = cpe_to_name_version(cpe=cpe) + software = Software(name=name, version=version, cpe=cpe) + yield software + yield SoftwareInstance(software=software.reference, ooi=input_ooi_reference) diff --git a/boefjes/boefjes/plugins/kat_shodan_internetdb/normalizer.json b/boefjes/boefjes/plugins/kat_shodan_internetdb/normalizer.json new file mode 100644 index 00000000000..ec875265cce --- /dev/null +++ b/boefjes/boefjes/plugins/kat_shodan_internetdb/normalizer.json @@ -0,0 +1,16 @@ +{ + "id": "kat_shodan_internetdb_normalize", + "name": "Shodan InternetDB normalizer", + "consumes": [ + "boefje/shodan_internetdb" + ], + "produces": [ + "Finding", + "IPPort", + "Hostname", + "CVEFindingType", + "DNSPTRRecord", + "Software", + "SoftwareInstance" + ] +} diff --git a/boefjes/tests/integration/test_api.py b/boefjes/tests/integration/test_api.py index 71bd08a316f..9596578a5ee 100644 --- a/boefjes/tests/integration/test_api.py +++ b/boefjes/tests/integration/test_api.py @@ -17,9 +17,9 @@ def test_get_local_plugin(test_client, organisation): def test_filter_plugins(test_client, organisation): response = test_client.get(f"/v1/organisations/{organisation.id}/plugins/") - assert len(response.json()) == 99 + assert len(response.json()) == 101 response = test_client.get(f"/v1/organisations/{organisation.id}/plugins?plugin_type=boefje") - assert len(response.json()) == 44 + assert len(response.json()) == 45 response = test_client.get(f"/v1/organisations/{organisation.id}/plugins?limit=10") assert len(response.json()) == 10 @@ -62,7 +62,7 @@ def test_add_boefje(test_client, organisation): assert response.status_code == 422 response = test_client.get(f"/v1/organisations/{organisation.id}/plugins/?plugin_type=boefje") - assert len(response.json()) == 45 + assert len(response.json()) == 46 boefje_dict = boefje.model_dump() boefje_dict["consumes"] = list(boefje_dict["consumes"]) @@ -119,7 +119,7 @@ def test_add_normalizer(test_client, organisation): assert response.status_code == 201 response = test_client.get(f"/v1/organisations/{organisation.id}/plugins/?plugin_type=normalizer") - assert len(response.json()) == 56 + assert len(response.json()) == 57 response = test_client.get(f"/v1/organisations/{organisation.id}/plugins/test_normalizer") assert response.json() == normalizer.model_dump() From 64461ad933d32601577191a9b7c4956667780925 Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:01:44 +0200 Subject: [PATCH 25/25] Add sterr to output list (#3649) Co-authored-by: Jan Klopper --- boefjes/boefjes/plugins/kat_dnssec/main.py | 6 +++++- boefjes/boefjes/plugins/kat_nmap_tcp/main.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_dnssec/main.py b/boefjes/boefjes/plugins/kat_dnssec/main.py index 950225b1829..9fc385134f2 100644 --- a/boefjes/boefjes/plugins/kat_dnssec/main.py +++ b/boefjes/boefjes/plugins/kat_dnssec/main.py @@ -17,4 +17,8 @@ def run(boefje_meta: dict): cmd = ["/usr/bin/drill", "-DT", domain] output = subprocess.run(cmd, capture_output=True) - return [({"openkat/dnssec-output"}, output.stdout)] + output.check_returncode() + + results = [({"openkat/dnssec-output"}, output.stdout)] + + return results diff --git a/boefjes/boefjes/plugins/kat_nmap_tcp/main.py b/boefjes/boefjes/plugins/kat_nmap_tcp/main.py index 41fdaa5cd97..3b14b10292c 100644 --- a/boefjes/boefjes/plugins/kat_nmap_tcp/main.py +++ b/boefjes/boefjes/plugins/kat_nmap_tcp/main.py @@ -18,4 +18,10 @@ def run(boefje_meta: dict): cmd.append("-6") cmd.extend(["-oX", "-", str(ip)]) - return [({"openkat/nmap-output"}, subprocess.run(cmd, capture_output=True).stdout.decode())] + output = subprocess.run(cmd, capture_output=True) + + output.check_returncode() + + results = [({"openkat/nmap-output"}, output.stdout.decode())] + + return results